1052 lines
56 KiB
HTML
1052 lines
56 KiB
HTML
<!DOCTYPE html>
|
||
<html>
|
||
<link href="wang/wangedit.css" rel="stylesheet" />
|
||
<style>
|
||
#editor—wrapper {
|
||
border: 1px solid #ccc;
|
||
z-index: 10; /* 按需定义 */
|
||
}
|
||
#toolbar-container {
|
||
border-bottom: 1px solid #ccc;
|
||
}
|
||
</style>
|
||
<style>
|
||
/* WebKit 浏览器的滚动条 */
|
||
::-webkit-scrollbar {
|
||
width: 4px; /* 滚动条宽度 */
|
||
height: 10px;
|
||
}
|
||
|
||
::-webkit-scrollbar-track {
|
||
background: #f1f1f1; /* 轨道背景色 */
|
||
}
|
||
|
||
::-webkit-scrollbar-thumb {
|
||
background: #888; /* 滚动条颜色 */
|
||
border-radius: 4px; /* 圆角 */
|
||
}
|
||
|
||
::-webkit-scrollbar-thumb:hover {
|
||
background: #555; /* 滚动条悬停时的颜色 */
|
||
}
|
||
html, body {
|
||
overflow: hidden;
|
||
}
|
||
|
||
/* 基础样式 */
|
||
h1, h2, h3, h4, h5 {
|
||
font-weight: bold;
|
||
line-height: 1.2;
|
||
margin-top: 1.5em;
|
||
margin-bottom: 0.5em;
|
||
}
|
||
|
||
|
||
</style>
|
||
<!--<script src="https://cdn.tailwindcss.com"></script>-->
|
||
<link rel="stylesheet" href="tw.k3gpt.css">
|
||
|
||
<script src="js/axios.min.js"></script>
|
||
<script src="js/marked.js"></script>
|
||
<script defer src="js/alpine.js"></script>
|
||
<script defer src="js/alp_unit.js"></script>
|
||
|
||
<body>
|
||
|
||
<!-- 编辑器的主窗口 -->
|
||
<div x-data="$store.ai_job" x-init="init2" class="overflow-hidden">
|
||
<!-- 查询器 四角弧形的矩形容器 -->
|
||
<div class="flex rounded-lg bg-white shadow-lg p-2 space-x-4 mb-4">
|
||
<!-- 横向排列的四个元素 -->
|
||
<!--<div class="flex items-center justify-center text-neutral-600 dark:text-zinc-200">标题</div>-->
|
||
<div class="relative flex w-full max-w-xs flex-col gap-1 text-neutral-600 dark:text-zinc-200">
|
||
<input x-model="title" type="text" class="w-full rounded border border-zinc-300 bg-zinc-100 py-2 pl-2 pr-2 text-sm focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-sky-700 disabled:cursor-not-allowed disabled:opacity-75 dark:border-zinc-700 dark:bg-zinc-800/50 dark:focus-visible:outline-sky-600" name="search" placeholder="输入标题" aria-label="search"/>
|
||
</div>
|
||
<!--<div class="flex items-center justify-center text-neutral-600 dark:text-zinc-200">分类</div>-->
|
||
<div class="relative flex w-full max-w-s1 flex-col gap-1 text-neutral-600 dark:text-zinc-200">
|
||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="absolute pointer-events-none right-2 top-2 h-5 w-5">
|
||
<path fill-rule="evenodd" d="M5.22 8.22a.75.75 0 0 1 1.06 0L10 11.94l3.72-3.72a.75.75 0 1 1 1.06 1.06l-4.25 4.25a.75.75 0 0 1-1.06 0L5.22 9.28a.75.75 0 0 1 0-1.06Z" clip-rule="evenodd" />
|
||
</svg>
|
||
<select id="catalog" x-model="catalog" class="w-full appearance-none rounded border border-zinc-300 bg-zinc-100 px-4 py-2 text-sm focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-sky-700 disabled:cursor-not-allowed disabled:opacity-75 dark:border-zinc-700 dark:bg-zinc-800/50 dark:focus-visible:outline-sky-600">
|
||
<template x-for="(item,index) in catalogs" :key="index">
|
||
<option x-text="item" :selected="catalog==item">词条</option>
|
||
</template>
|
||
</select>
|
||
</div>
|
||
|
||
<button id="save" @click="do_save" type="button" class="cursor-pointer whitespace-nowrap rounded bg-sky-700 px-4 py-2 text-sm font-medium tracking-wide text-white transition hover:opacity-75 text-center focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-sky-700 active:opacity-100 active:outline-offset-0 disabled:opacity-75 disabled:cursor-not-allowed dark:bg-sky-600 dark:text-white dark:focus-visible:outline-sky-600">保存</button>
|
||
<button id="save_text" @click="do_save_text" type="button" class="cursor-pointer whitespace-nowrap rounded bg-zinc-200 px-4 py-2 text-sm font-medium tracking-wide text-white transition hover:opacity-75 text-center focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-sky-700 active:opacity-100 active:outline-offset-0 disabled:opacity-75 disabled:cursor-not-allowed dark:bg-sky-600 dark:text-white dark:focus-visible:outline-sky-600">原始</button>
|
||
<button @click="window.open('view.html?id='+baike_id)" type="button" class="cursor-pointer inline-flex justify-center items-center gap-2 whitespace-nowrap rounded bg-blue-700 px-4 py-2 text-sm font-medium tracking-wide text-white transition hover:opacity-75 text-center focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-sky-700 active:opacity-100 active:outline-offset-0 disabled:opacity-75 disabled:cursor-not-allowed dark:bg-sky-600 dark:text-white dark:focus-visible:outline-sky-600">
|
||
预览
|
||
</button>
|
||
<button @click="gen_word" type="button" class="cursor-pointer inline-flex justify-center items-center gap-2 whitespace-nowrap rounded bg-sky-700 px-4 py-2 text-sm font-medium tracking-wide text-white transition hover:opacity-75 text-center focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-sky-700 active:opacity-100 active:outline-offset-0 disabled:opacity-75 disabled:cursor-not-allowed dark:bg-sky-600 dark:text-white dark:focus-visible:outline-sky-600">
|
||
DOC
|
||
</button>
|
||
<button @click="gen_pdf" type="button" class="cursor-pointer inline-flex justify-center items-center gap-2 whitespace-nowrap rounded bg-sky-700 px-4 py-2 text-sm font-medium tracking-wide text-white transition hover:opacity-75 text-center focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-sky-700 active:opacity-100 active:outline-offset-0 disabled:opacity-75 disabled:cursor-not-allowed dark:bg-sky-600 dark:text-white dark:focus-visible:outline-sky-600">
|
||
PDF
|
||
</button>
|
||
<button @click="gen_ppt" type="button" class="cursor-pointer inline-flex justify-center items-center gap-2 whitespace-nowrap rounded bg-green-700 px-4 py-2 text-sm font-medium tracking-wide text-white transition text-center focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-sky-700 active:opacity-100 active:outline-offset-0 disabled:opacity-75 disabled:cursor-not-allowed dark:bg-sky-600 dark:text-white dark:focus-visible:outline-sky-600">
|
||
PPT
|
||
<svg @click="gen_ppt2($event)" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" class="size-5 fill-white dark:fill-white hover:bg-zinc-900/10" fill="currentColor">
|
||
<path fill-rule="evenodd" d="M12 3.75a.75.75 0 01.75.75v6.75h6.75a.75.75 0 010 1.5h-6.75v6.75a.75.75 0 01-1.5 0v-6.75H4.5a.75.75 0 010-1.5h6.75V4.5a.75.75 0 01.75-.75z" clip-rule="evenodd" />
|
||
</svg>
|
||
</button>
|
||
<button @click="gen_poster" type="button" class="cursor-pointer inline-flex justify-center items-center gap-2 whitespace-nowrap rounded bg-green-700 px-4 py-2 text-sm font-medium tracking-wide text-white transition text-center focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-sky-700 active:opacity-100 active:outline-offset-0 disabled:opacity-75 disabled:cursor-not-allowed dark:bg-sky-600 dark:text-white dark:focus-visible:outline-sky-600">
|
||
海报
|
||
<svg @click="gen_poster2($event)" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" class="size-5 fill-white dark:fill-white hover:bg-zinc-900/10" fill="currentColor">
|
||
<path fill-rule="evenodd" d="M12 3.75a.75.75 0 01.75.75v6.75h6.75a.75.75 0 010 1.5h-6.75v6.75a.75.75 0 01-1.5 0v-6.75H4.5a.75.75 0 010-1.5h6.75V4.5a.75.75 0 01.75-.75z" clip-rule="evenodd" />
|
||
</svg>
|
||
</button>
|
||
<button @click="successModalIsOpen=true" class="rounded-full p-2.5 hover:text-green-700 bg-zinc-900/10 text-neutral-600 focus:outline-none focus-visible:text-neutral-600 focus-visible:zinc-300 focus-visible:outline-offset-0 focus-visible:outline-sky-700 active:bg-zinc-900/5 active:-outline-offset-2 dark:text-zinc-200/75 dark:hover:bg-zinc-50/10 dark:hover:text-zinc-200 dark:focus-visible:text-zinc-200 dark:focus-visible:outline-sky-600 dark:active:bg-zinc-50/5" title="使用技巧" aria-label="使用技巧" >
|
||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="size-5 shrink-0" aria-hidden="true">
|
||
<path fill-rule="evenodd" d="M10 2c-2.236 0-4.43.18-6.57.524C1.993 2.755 1 4.014 1 5.426v5.148c0 1.413.993 2.67 2.43 2.902 1.168.188 2.352.327 3.55.414.28.02.521.18.642.413l1.713 3.293a.75.75 0 0 0 1.33 0l1.713-3.293a.783.783 0 0 1 .642-.413 41.102 41.102 0 0 0 3.55-.414c1.437-.231 2.43-1.49 2.43-2.902V5.426c0-1.413-.993-2.67-2.43-2.902A41.289 41.289 0 0 0 10 2ZM6.75 6a.75.75 0 0 0 0 1.5h6.5a.75.75 0 0 0 0-1.5h-6.5Zm0 2.5a.75.75 0 0 0 0 1.5h3.5a.75.75 0 0 0 0-1.5h-3.5Z" clip-rule="evenodd"/>
|
||
</svg>
|
||
</button>
|
||
</div>
|
||
<!-- 进度条-->
|
||
<template x-if="progressbar">
|
||
<div class="flex h-4 w-full overflow-hidden rounded-radius bg-slate-100 dark:bg-surface-dark-alt" role="progressbar" aria-label="default progress bar" x-bind:aria-valuenow="currentVal" x-bind:aria-valuemin="minVal" x-bind:aria-valuemax="maxVal">
|
||
<div class="h-full rounded-radius bg-sky-700 dark:bg-primary-dark" x-bind:style="`width: ${calcPercentage(minVal, maxVal, currentVal)}%`"></div>
|
||
</div>
|
||
</template>
|
||
<!-- 编辑器部分 -->
|
||
<div id="editor—wrapper">
|
||
<div id="toolbar-container"><!-- 工具栏 --></div>
|
||
<div id="editor-container" class="h-[75vh]"><!-- 编辑器 --></div>
|
||
</div>
|
||
|
||
<!-- AI创作窗口 -->
|
||
<template x-if="modalIsOpen">
|
||
<div x-cloak x-transition.opacity.duration.200ms x-trap.inert.noscroll="modalIsOpen" @keydown.esc.window="modalIsOpen = false" class="fixed inset-0 z-50 flex items-end justify-center p-4 sm:items-center lg:p-4" role="dialog" aria-modal="true" aria-labelledby="defaultModalTitle">
|
||
<!-- Modal Dialog-->
|
||
<div x-show="modalIsOpen" x-transition:enter="transition ease-out duration-200 delay-100 motion-reduce:transition-opacity" x-transition:enter-start="opacity-0 scale-50" x-transition:enter-end="opacity-100 scale-100" class="flex w-3/5 max-h-[80vh] flex-col gap-4 overflow-hidden rounded-xl border border-slate-300 bg-white text-slate-700 dark:border-slate-700 dark:bg-slate-800 dark:text-slate-300">
|
||
|
||
<!-- Dialog Header -->
|
||
<div class="flex items-center justify-between border-b border-slate-300 bg-slate-100/60 px-2 dark:border-slate-700 dark:bg-slate-900/20">
|
||
<h4 id="defaultModalTitle" class="font-semibold tracking-wide text-black dark:text-white">AI创作</h4>
|
||
<!-- 搜索框-->
|
||
<div class="flex justify-center w-full max-w-md gap-2 border-zinc-300 dark:border-zinc-700" role="tablist" aria-label="tab options">
|
||
<div class="relative py-2 flex w-full max-w-md flex-col gap-1 text-neutral-600 dark:text-zinc-200">
|
||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke="currentColor" fill="none" stroke-width="2" class="absolute left-2 top-1/2 size-5 -translate-y-1/2 text-neutral-600/50 dark:text-zinc-200/50" aria-hidden="true">
|
||
<path stroke-linecap="round" stroke-linejoin="round" d="m21 21-5.197-5.197m0 0A7.5 7.5 0 1 0 5.196 5.196a7.5 7.5 0 0 0 10.607 10.607Z"/>
|
||
</svg>
|
||
<input x-model="search" x-on:input.debounce.900ms="fetchSomething()" placeholder="搜索全站文档,选定一个文档,来进行精准对话" type="search" class="w-full border border-zinc-300 rounded bg-zinc-50 px-2 py-1.5 pl-9 text-sm focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-sky-700 disabled:cursor-not-allowed disabled:opacity-75 dark:border-zinc-700 dark:bg-zinc-900/50 dark:focus-visible:outline-sky-600" name="search" aria-label="Search" placeholder="Search"/>
|
||
</div>
|
||
</div>
|
||
<button @click="modalIsOpen = false" aria-label="close modal">
|
||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" aria-hidden="true" stroke="currentColor" fill="none" stroke-width="1.4" class="w-5 h-5">
|
||
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12"/>
|
||
</svg>
|
||
</button>
|
||
</div>
|
||
<!-- 创作完成后的方式-->
|
||
<div class="flex justify-center gap-1">
|
||
|
||
<!-- 下拉框-->
|
||
<div x-data="{
|
||
options: [
|
||
{
|
||
value: 'AI续写',
|
||
label: 'AI续写',
|
||
},
|
||
{
|
||
value: 'AI摘要',
|
||
label: 'AI摘要',
|
||
},
|
||
{
|
||
value: 'AI大纲',
|
||
label: 'AI大纲',
|
||
},
|
||
{
|
||
value: 'AI丰富',
|
||
label: 'AI丰富',
|
||
},
|
||
{
|
||
value: 'AI优化',
|
||
label: 'AI优化',
|
||
},
|
||
{
|
||
value: '拼写检查',
|
||
label: '拼写检查',
|
||
},
|
||
{
|
||
value: '智能翻译',
|
||
label: '智能翻译',
|
||
},
|
||
{
|
||
value: '指令模式',
|
||
label: '指令模式',
|
||
},
|
||
],
|
||
isOpen: false,
|
||
openedWithKeyboard: false,
|
||
selectedOption: null,
|
||
setSelectedOption(option) {
|
||
this.selectedOption = option
|
||
this.isOpen = false
|
||
this.openedWithKeyboard = false
|
||
this.$refs.hiddenTextField.value = option.value
|
||
},
|
||
highlightFirstMatchingOption(pressedKey) {
|
||
const option = this.options.find((item) =>
|
||
item.label.toLowerCase().startsWith(pressedKey.toLowerCase()),
|
||
)
|
||
if (option) {
|
||
const index = this.options.indexOf(option)
|
||
const allOptions = document.querySelectorAll('.combobox-option')
|
||
if (allOptions[index]) {
|
||
allOptions[index].focus()
|
||
}
|
||
}
|
||
},
|
||
}" class="w-60 flex flex-col gap-1" x-on:keydown="highlightFirstMatchingOption($event.key)" x-on:keydown.esc.window="isOpen = false, openedWithKeyboard = false">
|
||
|
||
<div class="relative">
|
||
|
||
<!-- Trigger Button -->
|
||
<button type="button" role="combobox" class="inline-flex w-full items-center justify-between gap-2 whitespace-nowrap border-slate-300 bg-slate-100 px-4 py-2 text-sm font-medium capitalize tracking-wide text-slate-700 transition hover:opacity-75 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-700 dark:border-slate-700 dark:bg-slate-800/50 dark:text-slate-300 dark:focus-visible:outline-blue-600 rounded-xl border" aria-haspopup="listbox" aria-controls="industriesList" x-on:click="isOpen = ! isOpen" x-on:keydown.down.prevent="openedWithKeyboard = true" x-on:keydown.enter.prevent="openedWithKeyboard = true" x-on:keydown.space.prevent="openedWithKeyboard = true" x-bind:aria-label="selectedOption ? selectedOption.value : 'Please Select'" x-bind:aria-expanded="isOpen || openedWithKeyboard">
|
||
<span class="text-sm font-normal" x-text="selectedOption ? selectedOption.value : '选择创作模式'"></span>
|
||
<!-- Chevron -->
|
||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="size-5">
|
||
<path fill-rule="evenodd" d="M5.22 8.22a.75.75 0 0 1 1.06 0L10 11.94l3.72-3.72a.75.75 0 1 1 1.06 1.06l-4.25 4.25a.75.75 0 0 1-1.06 0L5.22 9.28a.75.75 0 0 1 0-1.06Z" clip-rule="evenodd"/>
|
||
</svg>
|
||
</button>
|
||
|
||
<!-- Hidden Input To Grab The Selected Value -->
|
||
<input id="ai_mode" name="ai_mode" type="text" x-ref="hiddenTextField" hidden/>
|
||
<ul x-cloak x-show="isOpen || openedWithKeyboard" id="industriesList" class="absolute z-10 left-0 top-11 flex max-h-44 w-full flex-col overflow-hidden overflow-y-auto border-slate-300 bg-slate-100 py-1.5 dark:border-slate-700 dark:bg-slate-800 rounded-xl border" role="listbox" aria-label="industries list" x-on:click.outside="isOpen = false, openedWithKeyboard = false" x-on:keydown.down.prevent="$focus.wrap().next()" x-on:keydown.up.prevent="$focus.wrap().previous()" x-transition x-trap="openedWithKeyboard">
|
||
<template x-for="(item, index) in options" x-bind:key="item.value">
|
||
<li class="combobox-option inline-flex cursor-pointer justify-between gap-6 bg-slate-100 px-4 py-2 text-sm text-slate-700 hover:bg-slate-800/5 hover:text-black focus-visible:bg-slate-800/5 focus-visible:text-black focus-visible:outline-none dark:bg-slate-800 dark:text-slate-300 dark:hover:bg-slate-100/5 dark:hover:text-white dark:focus-visible:bg-slate-100/10 dark:focus-visible:text-white" role="option" x-on:click="setSelectedOption(item)" x-on:keydown.enter="setSelectedOption(item)" x-bind:id="'option-' + index" tabindex="0" >
|
||
<!-- Label -->
|
||
<span x-bind:class="selectedOption == item ? 'font-bold' : null" x-text="item.label"></span>
|
||
<!-- Screen Reader 'Selected' Indicator -->
|
||
<span class="sr-only" x-text="selectedOption == item ? 'selected' : null"></span>
|
||
<!-- Checkmark -->
|
||
<svg x-cloak x-show="selectedOption == item" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke="currentColor" fill="none" stroke-width="2" class="size-4" aria-hidden="true">
|
||
<path stroke-linecap="round" stroke-linejoin="round" d="m4.5 12.75 6 6 9-13.5"/>
|
||
</svg>
|
||
</li>
|
||
</template>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Success Button With Icon -->
|
||
<button type="button" x-on:click="do_gen" class="cursor-pointer inline-flex justify-center items-center gap-2 whitespace-nowrap rounded-xl bg-green-600 px-4 py-2 text-xs font-medium tracking-wide text-white transition hover:opacity-75 text-center focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-green-600 active:opacity-100 active:outline-offset-0 disabled:opacity-75 disabled:cursor-not-allowed dark:bg-green-600 dark:text-white dark:focus-visible:outline-green-600">
|
||
|
||
AI生成
|
||
</button>
|
||
|
||
<!-- Primary Button With Icon -->
|
||
<button type="button" x-on:click="do_insert" class="cursor-pointer inline-flex justify-center items-center gap-2 whitespace-nowrap rounded-xl bg-blue-700 px-4 py-2 text-xs font-medium tracking-wide text-slate-100 transition hover:opacity-75 text-center focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-700 active:opacity-100 active:outline-offset-0 disabled:opacity-75 disabled:cursor-not-allowed dark:bg-blue-600 dark:text-slate-100 dark:focus-visible:outline-blue-600">
|
||
|
||
开头插入
|
||
</button>
|
||
<!-- Info Button With Icon -->
|
||
<button type="button" x-on:click="do_cur_insert" class="cursor-pointer inline-flex justify-center items-center gap-2 whitespace-nowrap rounded-xl bg-sky-600 px-4 py-2 text-xs font-medium tracking-wide text-white transition hover:opacity-75 text-center focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-sky-600 active:opacity-100 active:outline-offset-0 disabled:opacity-75 disabled:cursor-not-allowed dark:bg-sky-600 dark:text-white dark:focus-visible:outline-sky-600">
|
||
|
||
当前插入
|
||
</button>
|
||
<!-- Info Button With Icon -->
|
||
<button type="button" x-on:click="do_replace" class="cursor-pointer inline-flex justify-center items-center gap-2 whitespace-nowrap rounded-xl bg-sky-600 px-4 py-2 text-xs font-medium tracking-wide text-white transition hover:opacity-75 text-center focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-sky-600 active:opacity-100 active:outline-offset-0 disabled:opacity-75 disabled:cursor-not-allowed dark:bg-sky-600 dark:text-white dark:focus-visible:outline-sky-600">
|
||
|
||
文本替换
|
||
</button>
|
||
<button type="button" x-on:click="do_end_insert" class="cursor-pointer inline-flex justify-center items-center gap-2 whitespace-nowrap rounded-xl bg-indigo-700 px-4 py-2 text-xs font-medium tracking-wide text-slate-100 transition hover:opacity-75 text-center focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-700 active:opacity-100 active:outline-offset-0 disabled:opacity-75 disabled:cursor-not-allowed dark:bg-indigo-600 dark:text-slate-100 dark:focus-visible:outline-indigo-600">
|
||
|
||
末尾插入
|
||
</button>
|
||
|
||
</div>
|
||
<!-- Dialog Body -->
|
||
<div id="ai_creator" x-show="!search_list" class="px-4 flex-grow overflow-y-auto min-h-[40vh] min-w-[24rem] md:min-w-[32rem]" x-html="message"> </div>
|
||
|
||
<div x-show="search_list" class="flex flex-col gap-2 px-4 flex-grow overflow-y-auto min-h-[40vh] min-w-[24rem]">
|
||
<template x-for="(item,index) in aItems" key="index">
|
||
<label class="flex w-fit min-w-[14rem] cursor-pointer items-center justify-start gap-2 rounded border border-zinc-300 bg-zinc-100 px-4 py-2 font-medium text-neutral-600 has-[:disabled]:opacity-75 dark:border-zinc-700 dark:bg-zinc-800 dark:text-zinc-200">
|
||
<input type="radio" name="radioDefault" :value="index" x-model="search_checked" class="before:content[''] relative h-4 w-4 appearance-none rounded-full border border-zinc-300 bg-zinc-50 before:invisible before:absolute before:left-1/2 before:top-1/2 before:h-1.5 before:w-1.5 before:-translate-x-1/2 before:-translate-y-1/2 before:rounded-full before:bg-white checked:border-sky-700 checked:bg-sky-700 checked:before:visible focus:outline focus:outline-2 focus:outline-offset-2 focus:outline-zinc-500 checked:focus:outline-sky-700 disabled:cursor-not-allowed dark:border-zinc-700 dark:bg-zinc-900 dark:before:bg-white dark:checked:border-sky-600 dark:checked:bg-sky-600 dark:focus:outline-zinc-500 dark:checked:focus:outline-sky-600">
|
||
<span class="text-sm" x-text="item.base+':'+item.f_name">Mac</span>
|
||
</label>
|
||
</template>
|
||
</div>
|
||
|
||
<!-- Dialog Footer -->
|
||
<div class="flex flex-col-reverse justify-between gap-2 border-t border-slate-300 bg-slate-100/60 p-2 dark:border-slate-700 dark:bg-slate-900/20 sm:flex-row sm:items-center md:justify-end">
|
||
<!-- AI input-->
|
||
<div class="relative w-full">
|
||
<label for="aiPromt" for="aiPromt" class="sr-only">ai prompt</label>
|
||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" aria-hidden="true" class="absolute left-3 top-1/2 size-4 -translate-y-1/2 fill-blue-700 dark:fill-blue-600">
|
||
<path fill-rule="evenodd" d="M5 4a.75.75 0 0 1 .738.616l.252 1.388A1.25 1.25 0 0 0 6.996 7.01l1.388.252a.75.75 0 0 1 0 1.476l-1.388.252A1.25 1.25 0 0 0 5.99 9.996l-.252 1.388a.75.75 0 0 1-1.476 0L4.01 9.996A1.25 1.25 0 0 0 3.004 8.99l-1.388-.252a.75.75 0 0 1 0-1.476l1.388-.252A1.25 1.25 0 0 0 4.01 6.004l.252-1.388A.75.75 0 0 1 5 4ZM12 1a.75.75 0 0 1 .721.544l.195.682c.118.415.443.74.858.858l.682.195a.75.75 0 0 1 0 1.442l-.682.195a1.25 1.25 0 0 0-.858.858l-.195.682a.75.75 0 0 1-1.442 0l-.195-.682a1.25 1.25 0 0 0-.858-.858l-.682-.195a.75.75 0 0 1 0-1.442l.682-.195a1.25 1.25 0 0 0 .858-.858l.195-.682A.75.75 0 0 1 12 1ZM10 11a.75.75 0 0 1 .728.568.968.968 0 0 0 .704.704.75.75 0 0 1 0 1.456.968.968 0 0 0-.704.704.75.75 0 0 1-1.456 0 .968.968 0 0 0-.704-.704.75.75 0 0 1 0-1.456.968.968 0 0 0 .704-.704A.75.75 0 0 1 10 11Z" clip-rule="evenodd" />
|
||
</svg>
|
||
<input id="aiPromt" x-model="query" x-on:keydown.enter="chat_gen" type="text" class="w-full border-outline bg-slate-100 border border-slate-300 rounded-xl px-2 py-2 pl-10 pr-24 text-sm text-slate-700 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-700 disabled:cursor-not-allowed disabled:opacity-75 dark:border-slate-700 dark:bg-slate-800/50 dark:text-slate-300 dark:focus-visible:outline-blue-600" name="prompt" placeholder="Ask AI ..." />
|
||
<button type="button" x-on:click="chat_gen" class="absolute right-3 top-1/2 -translate-y-1/2 cursor-pointer bg-blue-700 rounded-xl px-2 py-1 text-xs tracking-wide text-slate-100 transition hover:opacity-75 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-700 active:opacity-100 active:outline-offset-0 dark:bg-blue-600 dark:text-slate-100 dark:focus-visible:outline-blue-600">Go</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<!-- 通知窗口-->
|
||
<!-- Success Alert -->
|
||
<template x-if="save_fin">
|
||
<div class="fixed bottom-4 left-0 right-0 z-30 mx-auto max-w-2xl w-full overflow-hidden rounded border border-green-700 bg-zinc-50 text-neutral-600 dark:bg-zinc-900 dark:text-zinc-200" role="alert">
|
||
<div class="flex w-full items-center gap-2 bg-green-700/10 p-4">
|
||
<div class="bg-green-700/15 text-green-700 rounded-full p-1" aria-hidden="true">
|
||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="size-6" aria-hidden="true">
|
||
<path fill-rule="evenodd" d="M10 18a8 8 0 1 0 0-16 8 8 0 0 0 0 16Zm3.857-9.809a.75.75 0 0 0-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 1 0-1.06 1.061l2.5 2.5a.75.75 0 0 0 1.137-.089l4-5.5Z" clip-rule="evenodd" />
|
||
</svg>
|
||
</div>
|
||
<div class="ml-2">
|
||
<h3 class="text-sm font-semibold text-green-700" x-text="doc_length">保存成功</h3>
|
||
<p class="text-xs font-medium sm:text-sm">窗口会在3秒后自动消失,你也可以手工关闭</p>
|
||
</div>
|
||
<button @click="save_fin=false" class="ml-auto" aria-label="dismiss alert">
|
||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" aria-hidden="true" stroke="currentColor" fill="none" stroke-width="2.5" class="w-4 h-4 shrink-0">
|
||
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12"/>
|
||
</svg>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<template x-if="chat_modalIsOpen">
|
||
<!-- PPT对话设置窗口 -->
|
||
<div x-transition.opacity.duration.200ms x-trap.inert.noscroll="chat_modalIsOpen" x-on:keydown.esc.window="chat_modalIsOpen = ppt_modalIsOpen = poster_modalIsOpen = false" x-on:click.self="chat_modalIsOpen = ppt_modalIsOpen = poster_modalIsOpen = false" class="fixed inset-0 z-30 flex w-full h-100vh items-start justify-end bg-black/20 backdrop-blur-md" role="dialog" aria-modal="true" aria-labelledby="defaultModalTitle">
|
||
<!-- Modal Dialog -->
|
||
<div x-show="chat_modalIsOpen" x-transition:enter="transition ease-out duration-200 delay-100 motion-reduce:transition-opacity" x-transition:enter-start="opacity-0 scale-50" x-transition:enter-end="opacity-100 scale-100" class="flex w-100 flex-col gap-4 overflow-hidden rounded border border-zinc-300 bg-zinc-50 text-neutral-600 dark:border-zinc-700 dark:bg-zinc-800 dark:text-zinc-200">
|
||
<!-- Dialog Header -->
|
||
<div class="flex items-center justify-between border-b border-zinc-300 bg-zinc-100/60 p-4 dark:border-zinc-700 dark:bg-zinc-900/20">
|
||
<h3 id="defaultModalTitle" class="font-semibold tracking-wide text-neutral-900 dark:text-zinc-50">生成助手</h3>
|
||
<button x-on:click="chat_modalIsOpen = ppt_modalIsOpen = poster_modalIsOpen = false" aria-label="close modal">
|
||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" aria-hidden="true" stroke="currentColor" fill="none" stroke-width="1.4" class="w-5 h-5">
|
||
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12"/>
|
||
</svg>
|
||
</button>
|
||
</div>
|
||
<!-- Dialog Body -->
|
||
<template x-if="ppt_modalIsOpen">
|
||
<div id="ppt_ai_dialog" alp-unit="ppt_chat.aps"></div>
|
||
</template>
|
||
<template x-if="poster_modalIsOpen">
|
||
<div id="poster_ai_dialog" alp-unit="poster_chat.aps"></div>
|
||
</template>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
|
||
<template x-if="successModalIsOpen">
|
||
<div x-cloak x-show="successModalIsOpen" x-transition.opacity.duration.200ms x-trap.inert.noscroll="successModalIsOpen" x-on:keydown.esc.window="successModalIsOpen = false" x-on:click.self="successModalIsOpen = false" class="fixed inset-0 z-30 flex items-end justify-center bg-black/20 p-4 pb-8 backdrop-blur-md sm:items-center lg:p-8" role="dialog" aria-modal="true" aria-labelledby="successModalTitle">
|
||
<!-- Modal Dialog -->
|
||
<div x-show="successModalIsOpen" x-transition:enter="transition ease-out duration-200 delay-100 motion-reduce:transition-opacity" x-transition:enter-start="opacity-0 scale-50" x-transition:enter-end="opacity-100 scale-100" class="flex max-w-lg flex-col gap-4 overflow-hidden rounded-radius border border-outline bg-surface text-on-surface dark:border-outline-dark dark:bg-surface-dark-alt dark:text-on-surface-dark">
|
||
<!-- Dialog Header -->
|
||
<div class="flex items-center justify-between border-b border-outline bg-surface-alt/60 px-4 py-2 dark:border-outline-dark dark:bg-surface-dark/20">
|
||
<div class="flex items-center justify-center rounded-full bg-success/20 text-success p-1">
|
||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="size-6" aria-hidden="true">
|
||
<path fill-rule="evenodd" d="M10 18a8 8 0 1 0 0-16 8 8 0 0 0 0 16Zm3.857-9.809a.75.75 0 0 0-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 1 0-1.06 1.061l2.5 2.5a.75.75 0 0 0 1.137-.089l4-5.5Z" clip-rule="evenodd" />
|
||
</svg>
|
||
</div>
|
||
<h3 id="successModalTitle" class="mb-2 font-semibold tracking-wide text-on-surface-strong dark:text-on-surface-dark-strong">
|
||
<span x-text="share_title"></span>
|
||
PPT和海报编辑技巧</h3>
|
||
<button x-on:click="successModalIsOpen = false" aria-label="close modal">
|
||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" aria-hidden="true" stroke="currentColor" fill="none" stroke-width="1.4" class="w-5 h-5">
|
||
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12"/>
|
||
</svg>
|
||
</button>
|
||
</div>
|
||
<!-- Dialog Body -->
|
||
<div class="px-4">
|
||
|
||
<h3 class="mb-2 font-semibold tracking-wide text-on-surface-strong">标记使用大全</h3>
|
||
<p>H1 是PPT和海报的标题(必选)</p>
|
||
<p>H3 是PPT和海报的副标题(在第一个H2之前,必选)</p>
|
||
<p>H2 是PPT单页主标题或海报的章节主标题(必选),H2在文中会有一横线作为区分</p>
|
||
<p>H3 是PPT单页副标题或海报的章节副标题(可选,可以有多个)</p>
|
||
<p>H4 是海报的摘要内容,一个海报一般只有一个(可选)</p>
|
||
<p>H5 是PPT内容或海报内容一级标题</p>
|
||
<p>li 是PPT内容或海报内容二级标题,可以是有序或无序</p>
|
||
<p>p 是PPT内容或海报内容三级标题</p>
|
||
<p>hr 横线表示海报的尾部,后续可以添加图片和h5以及p</p>
|
||
<p>图片可以添加描述,用做图片的标题显示</p>
|
||
|
||
|
||
</div>
|
||
<!-- Dialog Footer -->
|
||
<div class="flex items-center justify-center border-outline p-4 dark:border-outline-dark">
|
||
<button x-on:click="successModalIsOpen = false" type="button" class="w-full whitespace-nowrap rounded-radius border border-success bg-success px-4 py-2 text-center text-sm font-semibold tracking-wide text-on-success transition hover:opacity-75 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-success active:opacity-100 active:outline-offset-0">开始体验</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
</div>
|
||
</div>
|
||
|
||
|
||
|
||
</body>
|
||
<script src="wang/wangedit.js"></script>
|
||
<script>
|
||
const { createEditor, createToolbar,Boot } = window.wangEditor
|
||
|
||
class MyButtonMenu {
|
||
constructor() {
|
||
this.title = 'AI' // 自定义菜单标题
|
||
// this.iconSvg = '<svg>...</svg>' // 可选
|
||
this.tag = 'button'
|
||
}
|
||
|
||
getValue(editor) { // JS 语法
|
||
return ''
|
||
}
|
||
|
||
//是否需要激活
|
||
isActive(editor) { // JS 语法
|
||
return false
|
||
}
|
||
|
||
//是否禁用
|
||
isDisabled(editor) { // JS 语法
|
||
return false
|
||
}
|
||
|
||
//启用时的动作
|
||
exec(editor, value) { // JS 语法
|
||
if (this.isDisabled(editor)) return
|
||
var text = editor.getSelectionText();
|
||
Alpine.store('ai_job').open(text);
|
||
//editor.insertText(value) // value 即 this.value(editor) 的返回值
|
||
}
|
||
|
||
}
|
||
|
||
const menu1Conf = {
|
||
key: 'menu-ai', // 定义 menu key :要保证唯一、不重复(重要)
|
||
factory() {
|
||
return new MyButtonMenu() // 把 `YourMenuClass` 替换为你菜单的 class
|
||
},
|
||
}
|
||
|
||
Boot.registerMenu(menu1Conf)
|
||
|
||
const editorConfig = {
|
||
placeholder: '开始输入',
|
||
|
||
MENU_CONF: {
|
||
//上传图片
|
||
uploadImage: {
|
||
server: '/api/uploadimg',
|
||
fieldName: 'file',
|
||
base64LimitSize: 2 * 1024,// 2k以下插入 base64
|
||
// 单个文件的最大体积限制,默认为 2M
|
||
maxFileSize: 50 * 1024 * 1024, // 50M
|
||
maxNumberOfFiles: 50, //最多可上传几个文件
|
||
},
|
||
//上传视频
|
||
uploadVideo: {
|
||
server: '/api/uploadvideo',
|
||
fieldName: 'file',
|
||
maxNumberOfFiles: 50, //最多可上传几个文件
|
||
// 单个文件的最大体积限制,默认为 10M
|
||
maxFileSize: 1000 * 1024 * 1024, // 5M
|
||
|
||
}
|
||
},
|
||
onChange(editor) {
|
||
const html = editor.getHtml()
|
||
//console.log('editor content', html)
|
||
// 也可以同步到 <textarea>
|
||
},
|
||
}
|
||
|
||
|
||
|
||
const editor = createEditor({
|
||
selector: '#editor-container',
|
||
html: '',
|
||
config: editorConfig,
|
||
mode: 'default', // or 'simple'
|
||
})
|
||
|
||
const toolbarConfig = {}
|
||
|
||
toolbarConfig.insertKeys = {
|
||
index: 0, // 插入的位置,基于当前的 toolbarKeys
|
||
keys: ['menu-ai'],
|
||
}
|
||
|
||
const toolbar = createToolbar({
|
||
editor,
|
||
selector: '#toolbar-container',
|
||
config: toolbarConfig,
|
||
mode: 'default', // or 'simple'
|
||
})
|
||
|
||
console.info(editor.getConfig().hoverbarKeys);
|
||
|
||
editor.getConfig().hoverbarKeys.text.menuKeys.unshift("menu-ai");
|
||
|
||
const url = new URL(window.location.href);
|
||
var baike_id = url.searchParams.get('id');
|
||
|
||
if (baike_id!==undefined){
|
||
|
||
baike_id=parseInt(baike_id);
|
||
}
|
||
|
||
|
||
//可以再外部js调用的一种方式
|
||
//A使用Alpine.store('ai_job').open();
|
||
document.addEventListener('alpine:init', () => {
|
||
|
||
Alpine.store('ai_job', {
|
||
title:"自动标题",
|
||
catalog:"词条",
|
||
modalIsOpen: false, //AI创作的窗口
|
||
chat_modalIsOpen: false, //ppt和海报对话设置的窗口
|
||
ppt_modalIsOpen: false, //ppt对话设置的窗口
|
||
poster_modalIsOpen: false, //海报对话设置的窗口
|
||
successModalIsOpen: false, //技巧窗口
|
||
save_fin: false,
|
||
search: "",
|
||
search_list: false,
|
||
search_checked: "-1",
|
||
aItems:[],
|
||
progressbar: false, //进度条,显示
|
||
currentVal: 20 , //进度条默认值
|
||
minVal: 0 ,//进度条最新值
|
||
maxVal: 100, //进度条做大值
|
||
calcPercentage(min, max, val){return ((val-min)/(max-min))*100},
|
||
init(){
|
||
|
||
//动态加载,AI对话框
|
||
this.$watch('ppt_modalIsOpen',value => {
|
||
if (value){
|
||
this.$nextTick(() => {
|
||
var dom = document.getElementById("ppt_ai_dialog")
|
||
scan_alp_units(dom);
|
||
});
|
||
}
|
||
});
|
||
|
||
//动态加载,AI对话框
|
||
this.$watch('poster_modalIsOpen',value => {
|
||
if (value){
|
||
this.$nextTick(() => {
|
||
var dom = document.getElementById("poster_ai_dialog")
|
||
scan_alp_units(dom);
|
||
});
|
||
}
|
||
});
|
||
|
||
},//初始化函数
|
||
tips: "<span class='bg-green-600 text-white px-4 py-1 text-xs font-medium'>提示:</span>"
|
||
+" 我是人工智能助手,我可以帮你完成文档创作。请先选择创作的模式然后点击上方的"
|
||
+"<span class='bg-green-600 rounded-xl text-white px-4 py-1 text-xs font-medium opacity-50'>AI生成</span>按钮,就会自动生成内容,满意的话可以选择插入或替换文本,不满意的话可以再次点击按钮重新生成。<br><br>"
|
||
+"AI续写: 根据上文的内容自动续写后续的内容,可以不选中内容<br>"
|
||
+"AI摘要: 根据上文的内容自动编写一个摘要,可以不选中内容<br>"
|
||
+"AI大纲: 根据选中的文字一般是标题来进行思维脑图式的创作<br>"
|
||
+"AI丰富: 对选中的文字内容进行扩写,使其内容变长<br>"
|
||
+"AI优化: 对选中的文字内容进行缩写,使其更加精简<br>"
|
||
+"拼写检查: 对选中的文字的内容进行错别字等检查和修复<br>"
|
||
+"智能翻译: 中文翻译成引文或英文翻译成中文<br>"
|
||
+"<br>也可以用知识对话的方式来生成所需的内容<br>"
|
||
,
|
||
message: "",
|
||
context: "",
|
||
catalogs: "",
|
||
query: "",
|
||
doc_length:"",
|
||
x: 0,
|
||
y: 0,
|
||
dragging: false,
|
||
|
||
dragStart(e) {
|
||
this.dragging = true;
|
||
this.startX = e.clientX - this.x;
|
||
this.startY = e.clientY - this.y;
|
||
},
|
||
|
||
drag(e) {
|
||
if (!this.dragging) return;
|
||
this.x = e.clientX - this.startX;
|
||
this.y = e.clientY - this.startY;
|
||
},
|
||
open(text){
|
||
this.modalIsOpen=true;
|
||
this.context = text;
|
||
|
||
this.message = "<span class='bg-yellow-300 text-white'>"+text+"</span><br><br>"+this.tips;
|
||
const div = document.getElementById("ai_creator");
|
||
div.scrollTop = 0;
|
||
|
||
},
|
||
up_message(msg){
|
||
this.message=msg;
|
||
},
|
||
do_insert(){
|
||
editor.focus();
|
||
let html = editor.getHtml();
|
||
editor.clear();
|
||
editor.dangerouslyInsertHtml(this.pre_message())
|
||
editor.dangerouslyInsertHtml(html);
|
||
|
||
const div = document.querySelector(".w-e-scroll")
|
||
div.scrollTop = 0;
|
||
},
|
||
do_cur_insert(){
|
||
//editor.blur()
|
||
editor.focus();
|
||
// if (editor.selection){
|
||
// console.info("选中")
|
||
// editor.deselect()
|
||
// }else{
|
||
// console.info("未选")
|
||
// }
|
||
editor.dangerouslyInsertHtml(this.context+this.pre_message())
|
||
},
|
||
do_replace(){
|
||
editor.focus()
|
||
editor.deleteFragment();
|
||
editor.dangerouslyInsertHtml(this.pre_message())
|
||
},
|
||
do_end_insert(){
|
||
editor.focus();
|
||
let html = editor.getHtml();
|
||
editor.clear();
|
||
editor.dangerouslyInsertHtml(html);
|
||
editor.dangerouslyInsertHtml(this.pre_message())
|
||
const div = document.querySelector(".w-e-scroll")
|
||
div.scrollTop = div.scrollHeight;;
|
||
},
|
||
pre_message(){ //纯的message,没有思考过程
|
||
let end = this.message.lastIndexOf('padding:5px;">');
|
||
var rsp = this.message.slice(end+'padding:5px;">'.length,-6);
|
||
return rsp;
|
||
},
|
||
|
||
//初始化
|
||
init2(){
|
||
this.baike_id= baike_id;
|
||
if (baike_id !==0){
|
||
axios.get('/api/baike/'+baike_id).then(response => {
|
||
|
||
this.title= response.data.title;
|
||
this.catalog=response.data.catalog;
|
||
editor.setHtml(response.data.html);
|
||
}).catch(error => {
|
||
console.error('Error fetching data:', error);
|
||
throw error; // 重新抛出错误以便调用者可以处理
|
||
});
|
||
}
|
||
//分类
|
||
axios.get('/api/catalogs').then(response => {
|
||
//console.log('Data:', response.data);
|
||
this.catalogs = response.data.data;
|
||
}).catch(error => {
|
||
console.error('Error fetching data:', error);
|
||
throw error; // 重新抛出错误以便调用者可以处理
|
||
});
|
||
|
||
},
|
||
//保存编辑信息
|
||
do_save(){
|
||
|
||
// 数据对象,代表要发送的数据
|
||
const newItem = {
|
||
id: this.baike_id,
|
||
title: this.title,
|
||
catalog: this.catalog,
|
||
trans: false,
|
||
html: editor.getHtml()
|
||
};
|
||
|
||
// 使用 axios 发送 POST 请求
|
||
axios.post('/api/baike', newItem)
|
||
.then(response =>{
|
||
//alert(response.data.msg)
|
||
this.doc_length = `保存成功,大约${editor.getText().length}字`;
|
||
this.save_fin = true;
|
||
this.baike_id = response.data.id
|
||
setTimeout(() => {
|
||
this.save_fin = false;
|
||
}, 3000); // 3000 毫秒 = 3 秒
|
||
})
|
||
.catch(error => {
|
||
alert(error);
|
||
console.error('Error post data:', error);
|
||
throw error; // 重新抛出错误以便调用者可以处理
|
||
});
|
||
|
||
},
|
||
//保存编辑信息为text格式
|
||
do_save_text(){
|
||
// 数据对象,代表要发送的数据
|
||
const newItem = {
|
||
id: this.baike_id,
|
||
title: this.title,
|
||
catalog: this.catalog,
|
||
trans: false,
|
||
html: editor.getText()
|
||
};
|
||
|
||
// 使用 axios 发送 POST 请求
|
||
axios.post('/api/baike', newItem)
|
||
.then(response =>{
|
||
//alert(response.data.msg)
|
||
this.save_fin = true;
|
||
this.doc_length = `保存成功,大约${editor.getText().length}字`;
|
||
this.baike_id = response.data.id
|
||
setTimeout(() => {
|
||
this.save_fin = false;
|
||
}, 3000); // 3000 毫秒 = 3 秒
|
||
})
|
||
.catch(error => {
|
||
alert(error);
|
||
console.error('Error post data:', error);
|
||
throw error; // 重新抛出错误以便调用者可以处理
|
||
});
|
||
|
||
},
|
||
//生成word文档
|
||
gen_word(){
|
||
|
||
// 数据对象,代表要发送的数据
|
||
const newItem = {
|
||
id: this.baike_id,
|
||
title: this.title,
|
||
catalog: this.catalog,
|
||
html: editor.getHtml()
|
||
};
|
||
|
||
// 使用 axios 发送 POST 请求
|
||
axios.post('/api/baike_gen_word', newItem)
|
||
.then(response =>{
|
||
window.open(`/api/fsd/${response.data.filename}`);
|
||
})
|
||
.catch(error => {
|
||
alert(error.response.data.detail);
|
||
});
|
||
|
||
},
|
||
//生成pdf文档
|
||
gen_pdf(){
|
||
|
||
// 数据对象,代表要发送的数据
|
||
const newItem = {
|
||
id: this.baike_id,
|
||
title: this.title,
|
||
catalog: this.catalog,
|
||
html: editor.getHtml()
|
||
};
|
||
|
||
// 使用 axios 发送 POST 请求
|
||
axios.post('/api/baike_gen_pdf', newItem)
|
||
.then(response =>{
|
||
window.open(`/api/fsd/${response.data.filename}`);
|
||
})
|
||
.catch(error => {
|
||
alert(error.response.data.detail);
|
||
console.error('Error post data:', error);
|
||
throw error; // 重新抛出错误以便调用者可以处理
|
||
});
|
||
|
||
},
|
||
//生成PPT文档
|
||
gen_ppt(){
|
||
|
||
// 数据对象,代表要发送的数据
|
||
const newItem = {
|
||
id: this.baike_id,
|
||
title: this.title,
|
||
catalog: this.catalog,
|
||
html: editor.getHtml()
|
||
};
|
||
|
||
this.progressbar = true;
|
||
this.currentVal =10;
|
||
setInterval(() => {
|
||
this.currentVal +=10;
|
||
}, 1000); // 1秒
|
||
|
||
// 使用 axios 发送 POST 请求
|
||
axios.post('/api/baike_gen_ppt', newItem)
|
||
.then(response =>{
|
||
this.progressbar = false;
|
||
window.open(`/api/fsd/${response.data.filename}`);
|
||
})
|
||
.catch(error => {
|
||
this.progressbar = false;
|
||
alert(error.response.data.detail);
|
||
});
|
||
|
||
},
|
||
//打开ppt设置的对话框
|
||
gen_ppt2(event){
|
||
this.chat_modalIsOpen = true;
|
||
this.ppt_modalIsOpen = true;
|
||
event.stopPropagation(); // 阻止事件冒泡
|
||
return false;
|
||
},
|
||
//生成海报
|
||
gen_poster(){
|
||
|
||
|
||
// 数据对象,代表要发送的数据
|
||
const newItem = {
|
||
id: this.baike_id,
|
||
title: this.title,
|
||
catalog: this.catalog,
|
||
html: editor.getHtml()
|
||
};
|
||
|
||
this.progressbar = true;
|
||
this.currentVal =10;
|
||
setInterval(() => {
|
||
this.currentVal +=10;
|
||
}, 1000); // 1秒
|
||
|
||
// 使用 axios 发送 POST 请求
|
||
axios.post('/api/baike_gen_poster', newItem)
|
||
.then(response =>{
|
||
this.progressbar = false;
|
||
window.open(`/api/fsd/${response.data.filename}`);
|
||
})
|
||
.catch(error => {
|
||
this.progressbar = false;
|
||
|
||
alert(error.response.data.detail);
|
||
});
|
||
|
||
},
|
||
gen_poster2(event){
|
||
this.chat_modalIsOpen = true;
|
||
this.poster_modalIsOpen = true;
|
||
event.stopPropagation(); // 阻止事件冒泡
|
||
return false;
|
||
},
|
||
do_gen(){
|
||
this.message="";
|
||
this.search_list = false;
|
||
const input_ai_mode = document.getElementById("ai_mode");
|
||
if (input_ai_mode.value==""){
|
||
alert("请选择创作模式");
|
||
return;
|
||
}
|
||
if (input_ai_mode.value=="指令模式"){
|
||
alert("请在下方输入框输入指令,点击GO即可完成");
|
||
return;
|
||
}
|
||
|
||
if (input_ai_mode.value=="AI续写" && this.context==""){
|
||
this.context=editor.getText();
|
||
}
|
||
|
||
if (input_ai_mode.value=="AI摘要" && this.context==""){
|
||
this.context=editor.getText();
|
||
}
|
||
|
||
// 数据对象,代表要发送的数据
|
||
const newItem = {
|
||
question: this.context,
|
||
ai_mode: input_ai_mode.value,
|
||
};
|
||
|
||
// 使用 axios 发送 POST 请求
|
||
axios.post('/api/ai_create', newItem)
|
||
.then(response =>{
|
||
|
||
rsp = response.data;
|
||
// 创建一个EventSource实例连接到服务器发送的事件流
|
||
const eventSource = new EventSource('/api/ai_create/'+rsp.chat_id);
|
||
// 监听消息事件
|
||
eventSource.onmessage = function(event) {
|
||
// 将接收到的数据显示在网页上
|
||
const message = JSON.parse(event.data);
|
||
|
||
var gen_rsp ="";
|
||
|
||
if (message.rsp.indexOf("<think>")==0){
|
||
var end = message.rsp.indexOf("</think>");
|
||
if (end==-1){ //思考还未结束
|
||
|
||
var think_mk = marked.parse(message.rsp.slice(7));
|
||
|
||
gen_rsp = think_mk;
|
||
}else{
|
||
var think_mk = marked.parse(message.rsp.slice(7,end));
|
||
var result= marked.parse(message.rsp.slice(end+8));
|
||
var think_all=`${think_mk} <div style="color: white; background-color: rgb(29 78 216 / 0.9); border-radius: 5px; margin: 5px; padding:5px;">${result}</div>`;
|
||
gen_rsp= think_all;
|
||
}
|
||
|
||
}else{
|
||
gen_rsp =marked.parse(message.rsp);
|
||
}
|
||
|
||
Alpine.store('ai_job').up_message(gen_rsp);
|
||
const div = document.getElementById("ai_creator");
|
||
div.scrollTop = div.scrollHeight;
|
||
|
||
};
|
||
// 监听错误事件
|
||
eventSource.onerror = function(error) {
|
||
console.error("EventSource failed:", error);
|
||
eventSource.close(); // 关闭连接
|
||
};
|
||
})
|
||
.catch(error => {
|
||
console.error('Error post data:', error);
|
||
throw error; // 重新抛出错误以便调用者可以处理
|
||
});
|
||
|
||
},
|
||
chat_gen(){
|
||
this.search_list = false;
|
||
this.message="";
|
||
|
||
const input_ai_mode = document.getElementById("ai_mode");
|
||
var mode="KG"; //知识库问答
|
||
if (input_ai_mode.value=="指令模式"){
|
||
mode="FA"; //大模型回答
|
||
}
|
||
|
||
if (this.search_checked=="-1" || mode=="FA"){
|
||
|
||
// 数据对象,代表要发送的数据
|
||
const newItem = {
|
||
question: this.context+"\n"+this.query,
|
||
ai_mode: mode,
|
||
|
||
};
|
||
|
||
// 使用 axios 发送 POST 请求
|
||
axios.post('/api/chat_search', newItem)
|
||
.then(response =>{
|
||
this.query="";
|
||
rsp = response.data;
|
||
// this.Items[this.Items.length-1].chat_id=rsp.chat_id;
|
||
// this.Items[this.Items.length-1].rsp=`搜索到${rsp.count}篇文档[${rsp.meta}],正在整理中...`;
|
||
// this.Items[this.Items.length-1].rsp_show=true;
|
||
update_chat(rsp.chat_id);
|
||
|
||
})
|
||
.catch(error => {
|
||
console.error('Error post data:', error);
|
||
throw error; // 重新抛出错误以便调用者可以处理
|
||
});
|
||
}else
|
||
{ //单个文档回答
|
||
|
||
let doc_index=parseInt(this.search_checked);
|
||
let doc= this.aItems[doc_index];
|
||
//单个文档对话
|
||
// 数据对象,代表要发送的数据
|
||
const newItem = {
|
||
question: this.query,
|
||
file: doc.f_name,
|
||
base: doc.base,
|
||
path: doc.path,
|
||
};
|
||
|
||
// 使用 axios 发送 POST 请求
|
||
axios.post('/api/chat_one_doc', newItem)
|
||
.then(response =>{
|
||
this.query="";
|
||
rsp = response.data;
|
||
update_chat(rsp.chat_id);
|
||
})
|
||
.catch(error => {
|
||
console.error('Error post data:', error);
|
||
throw error; // 重新抛出错误以便调用者可以处理
|
||
});
|
||
}
|
||
|
||
},
|
||
fetchSomething() {//查询文档
|
||
this.search_list = true;
|
||
|
||
if (this.search==""){
|
||
return;
|
||
}
|
||
|
||
axios.get('/api/kg_doc?demo='+this.search).then(response => {
|
||
//console.log('Data:', response.data);
|
||
this.aItems = response.data.data;
|
||
this.search_checked = -1;
|
||
this.count=response.data.count;
|
||
}).catch(error => {
|
||
console.error('Error fetching data:', error);
|
||
throw error; // 重新抛出错误以便调用者可以处理
|
||
});
|
||
},
|
||
})
|
||
})
|
||
|
||
function update_chat(chat_id){
|
||
// 创建一个EventSource实例连接到服务器发送的事件流
|
||
const eventSource = new EventSource('/api/chat/'+chat_id);
|
||
// 监听消息事件
|
||
eventSource.onmessage = function(event) {
|
||
// 将接收到的数据显示在网页上
|
||
const message = JSON.parse(event.data);
|
||
|
||
var gen_rsp ="";
|
||
|
||
if (message.rsp.indexOf("<think>")==0){
|
||
var end = message.rsp.indexOf("</think>");
|
||
if (end==-1){ //思考还未结束
|
||
|
||
var think_mk = marked.parse(message.rsp.slice(7));
|
||
|
||
gen_rsp = think_mk;
|
||
}else{
|
||
var think_mk = marked.parse(message.rsp.slice(7,end));
|
||
var result= marked.parse(message.rsp.slice(end+8));
|
||
var think_all=`${think_mk} <div style="color: white; background-color: rgb(29 78 216 / 0.9); border-radius: 5px; margin: 5px; padding:5px;">${result}</div>`;
|
||
gen_rsp= think_all;
|
||
}
|
||
|
||
}else{
|
||
gen_rsp =marked.parse(message.rsp);
|
||
}
|
||
|
||
|
||
Alpine.store('ai_job').up_message(gen_rsp);
|
||
|
||
const div = document.getElementById("ai_creator");
|
||
div.scrollTop = div.scrollHeight;
|
||
|
||
};
|
||
// 监听错误事件
|
||
eventSource.onerror = function(error) {
|
||
console.error("EventSource failed:", error);
|
||
eventSource.close(); // 关闭连接
|
||
};
|
||
}
|
||
|
||
|
||
function auto_save(){
|
||
|
||
var catalog = document.getElementById('catalog').value;
|
||
if ( catalog.startsWith("大模型/") )
|
||
var button = document.getElementById('save_text');
|
||
else{
|
||
var button = document.getElementById('save');
|
||
}
|
||
|
||
// 触发点击事件
|
||
button.click();
|
||
}
|
||
|
||
|
||
//开启30 秒后,自动保存
|
||
let timerId = setTimeout(() => {
|
||
//定时60秒保存
|
||
setInterval(auto_save,60000);
|
||
}, 60000);
|
||
|
||
|
||
</script>
|
||
</html> |