220 lines
19 KiB
Plaintext
220 lines
19 KiB
Plaintext
|
|
<div x-data="{ selectedTab: 'setting' }" class="relative flex w-full flex-col md:flex-row h-[92vh]">
|
|||
|
|
|
|||
|
|
<nav x-cloak class="fixed left-0 z-20 flex h-svh w-60 shrink-0 flex-col border-r border-slate-300 bg-slate-100 p-4 transition-transform duration-300 md:w-64 md:translate-x-0 md:relative dark:border-slate-700 dark:bg-slate-800" aria-label="sidebar navigation">
|
|||
|
|
|
|||
|
|
<!-- sidebar links -->
|
|||
|
|
<div class="flex flex-col gap-2 overflow-y-auto pb-6">
|
|||
|
|
<a href="#" @click="selectedTab = 'setting'" :class="selectedTab === 'setting' ? 'bg-blue-700/30' : ''" class="flex items-center rounded-xl gap-2 px-2 py-1.5 text-sm font-medium text-slate-700 underline-offset-2 hover:bg-blue-700/5 hover:text-black focus-visible:underline focus:outline-none dark:text-slate-300 dark:hover:bg-blue-600/5 dark:hover:text-white">
|
|||
|
|
<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>
|
|||
|
|
<span>大模型管理</span>
|
|||
|
|
</a>
|
|||
|
|
<!--
|
|||
|
|
<a href="#" @click="selectedTab = 'source'" :class="selectedTab === 'source' ? 'bg-blue-700/30' : ''" class="flex items-center rounded-xl gap-2 px-2 py-1.5 text-sm font-medium text-slate-700 underline-offset-2 hover:bg-blue-700/5 hover:text-black focus-visible:underline focus:outline-none dark:text-slate-300 dark:hover:bg-blue-600/5 dark:hover:text-white">
|
|||
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="size-5 shrink-0" aria-hidden="true">
|
|||
|
|
<path d="M15.5 2A1.5 1.5 0 0 0 14 3.5v13a1.5 1.5 0 0 0 1.5 1.5h1a1.5 1.5 0 0 0 1.5-1.5v-13A1.5 1.5 0 0 0 16.5 2h-1ZM9.5 6A1.5 1.5 0 0 0 8 7.5v9A1.5 1.5 0 0 0 9.5 18h1a1.5 1.5 0 0 0 1.5-1.5v-9A1.5 1.5 0 0 0 10.5 6h-1ZM3.5 10A1.5 1.5 0 0 0 2 11.5v5A1.5 1.5 0 0 0 3.5 18h1A1.5 1.5 0 0 0 6 16.5v-5A1.5 1.5 0 0 0 4.5 10h-1Z"/>
|
|||
|
|
</svg>
|
|||
|
|
<span>知识库管理</span>
|
|||
|
|
</a>
|
|||
|
|
-->
|
|||
|
|
<a href="#" @click="selectedTab = 'user'" :class="selectedTab === 'user' ? 'bg-blue-700/30' : ''" class="flex items-center rounded-xl gap-2 px-2 py-1.5 text-sm font-medium text-slate-700 underline-offset-2 hover:bg-blue-700/5 hover:text-black focus-visible:underline focus:outline-none dark:text-slate-300 dark:hover:bg-blue-600/5 dark:hover:text-white">
|
|||
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true" class="size-5">
|
|||
|
|
<path d="M10 9a3 3 0 1 0 0-6 3 3 0 0 0 0 6ZM6 8a2 2 0 1 1-4 0 2 2 0 0 1 4 0ZM1.49 15.326a.78.78 0 0 1-.358-.442 3 3 0 0 1 4.308-3.516 6.484 6.484 0 0 0-1.905 3.959c-.023.222-.014.442.025.654a4.97 4.97 0 0 1-2.07-.655ZM16.44 15.98a4.97 4.97 0 0 0 2.07-.654.78.78 0 0 0 .357-.442 3 3 0 0 0-4.308-3.517 6.484 6.484 0 0 1 1.907 3.96 2.32 2.32 0 0 1-.026.654ZM18 8a2 2 0 1 1-4 0 2 2 0 0 1 4 0ZM5.304 16.19a.844.844 0 0 1-.277-.71 5 5 0 0 1 9.947 0 .843.843 0 0 1-.277.71A6.975 6.975 0 0 1 10 18a6.974 6.974 0 0 1-4.696-1.81Z" />
|
|||
|
|
</svg>
|
|||
|
|
|
|||
|
|
<span>用户管理</span>
|
|||
|
|
</a>
|
|||
|
|
<a href="#" @click="selectedTab = 'login'" :class="selectedTab === 'login' ? 'bg-blue-700/30' : ''" class="flex items-center rounded-xl gap-2 px-2 py-1.5 text-sm font-medium text-slate-700 underline-offset-2 hover:bg-blue-700/5 hover:text-black focus-visible:underline focus:outline-none dark:text-slate-300 dark:hover:bg-blue-600/5 dark:hover:text-white">
|
|||
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true" class="size-5">
|
|||
|
|
<path d="m9.653 16.915-.005-.003-.019-.01a20.759 20.759 0 0 1-1.162-.682 22.045 22.045 0 0 1-2.582-1.9C4.045 12.733 2 10.352 2 7.5a4.5 4.5 0 0 1 8-2.828A4.5 4.5 0 0 1 18 7.5c0 2.852-2.044 5.233-3.885 6.82a22.049 22.049 0 0 1-3.744 2.582l-.019.01-.005.003h-.002a.739.739 0 0 1-.69.001l-.002-.001Z" />
|
|||
|
|
</svg>
|
|||
|
|
<span>日志管理</span>
|
|||
|
|
</a>
|
|||
|
|
<a href="#" @click="selectedTab = 'chat_history'" :class="selectedTab === 'chat_history' ? 'bg-blue-700/30' : ''" class="flex items-center rounded-xl gap-2 px-2 py-1.5 text-sm font-medium text-slate-700 underline-offset-2 hover:bg-blue-700/5 hover:text-black focus-visible:underline focus:outline-none dark:text-slate-300 dark:hover:bg-blue-600/5 dark:hover:text-white">
|
|||
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true" class="size-5">
|
|||
|
|
<path d="M3.505 2.365A41.369 41.369 0 0 1 9 2c1.863 0 3.697.124 5.495.365 1.247.167 2.18 1.108 2.435 2.268a4.45 4.45 0 0 0-.577-.069 43.141 43.141 0 0 0-4.706 0C9.229 4.696 7.5 6.727 7.5 8.998v2.24c0 1.413.67 2.735 1.76 3.562l-2.98 2.98A.75.75 0 0 1 5 17.25v-3.443c-.501-.048-1-.106-1.495-.172C2.033 13.438 1 12.162 1 10.72V5.28c0-1.441 1.033-2.717 2.505-2.914Z" />
|
|||
|
|
<path d="M14 6c-.762 0-1.52.02-2.271.062C10.157 6.148 9 7.472 9 8.998v2.24c0 1.519 1.147 2.839 2.71 2.935.214.013.428.024.642.034.2.009.385.09.518.224l2.35 2.35a.75.75 0 0 0 1.28-.531v-2.07c1.453-.195 2.5-1.463 2.5-2.915V8.998c0-1.526-1.157-2.85-2.729-2.936A41.645 41.645 0 0 0 14 6Z" />
|
|||
|
|
</svg>
|
|||
|
|
|
|||
|
|
<span>历史对话</span>
|
|||
|
|
</a>
|
|||
|
|
<a href="#" @click="selectedTab = 'gcfg'" :class="selectedTab === 'gcfg' ? 'bg-blue-700/30' : ''" class="flex items-center rounded-xl gap-2 px-2 py-1.5 text-sm font-medium text-slate-700 underline-offset-2 hover:bg-blue-700/5 hover:text-black focus-visible:underline focus:outline-none dark:text-slate-300 dark:hover:bg-blue-600/5 dark:hover:text-white">
|
|||
|
|
<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="M7.84 1.804A1 1 0 0 1 8.82 1h2.36a1 1 0 0 1 .98.804l.331 1.652a6.993 6.993 0 0 1 1.929 1.115l1.598-.54a1 1 0 0 1 1.186.447l1.18 2.044a1 1 0 0 1-.205 1.251l-1.267 1.113a7.047 7.047 0 0 1 0 2.228l1.267 1.113a1 1 0 0 1 .206 1.25l-1.18 2.045a1 1 0 0 1-1.187.447l-1.598-.54a6.993 6.993 0 0 1-1.929 1.115l-.33 1.652a1 1 0 0 1-.98.804H8.82a1 1 0 0 1-.98-.804l-.331-1.652a6.993 6.993 0 0 1-1.929-1.115l-1.598.54a1 1 0 0 1-1.186-.447l-1.18-2.044a1 1 0 0 1 .205-1.251l1.267-1.114a7.05 7.05 0 0 1 0-2.227L1.821 7.773a1 1 0 0 1-.206-1.25l1.18-2.045a1 1 0 0 1 1.187-.447l1.598.54A6.992 6.992 0 0 1 7.51 3.456l.33-1.652ZM10 13a3 3 0 1 0 0-6 3 3 0 0 0 0 6Z" clip-rule="evenodd"/>
|
|||
|
|
</svg>
|
|||
|
|
|
|||
|
|
<span>系统参数</span>
|
|||
|
|
</a>
|
|||
|
|
</div>
|
|||
|
|
</nav>
|
|||
|
|
|
|||
|
|
<!-- main content -->
|
|||
|
|
<div id="main-content" class="h-[92vh] w-full overflow-y-auto p-4 bg-white dark:bg-slate-900">
|
|||
|
|
<div x-show="selectedTab === 'gcfg'" class="w-full h-full">
|
|||
|
|
<div alp-unit="gcfg.html"></div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div x-show="selectedTab === 'user'" class="w-full h-full">
|
|||
|
|
<div alp-unit="user.html"></div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div x-show="selectedTab === 'login'" class="w-full h-full">
|
|||
|
|
<div alp-unit="logs.html"></div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div x-show="selectedTab === 'chat_history'" class="w-full h-full">
|
|||
|
|
<div alp-unit="chat_history.html"></div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<template x-if="selectedTab === 'setting'">
|
|||
|
|
<div class="w-full h-full">
|
|||
|
|
<!-- 大模型设置 -->
|
|||
|
|
<div
|
|||
|
|
x-data="{
|
|||
|
|
tabSelected: '',
|
|||
|
|
save_fin: false,
|
|||
|
|
llm_cfg:[],
|
|||
|
|
chat_modalIsOpen:false,
|
|||
|
|
tabButtonClicked(tab,tabButton){
|
|||
|
|
this.tabSelected = tab
|
|||
|
|
this.tabRepositionMarker(tabButton);
|
|||
|
|
},
|
|||
|
|
tabRepositionMarker(tabButton){
|
|||
|
|
|
|||
|
|
this.$refs.tabMarker.style.width=tabButton.offsetWidth + 'px';
|
|||
|
|
this.$refs.tabMarker.style.height=tabButton.offsetHeight + 'px';
|
|||
|
|
this.$refs.tabMarker.style.left=tabButton.offsetLeft + 'px';
|
|||
|
|
},
|
|||
|
|
init(){
|
|||
|
|
axios.get('/api/llm').then(response => {
|
|||
|
|
this.tabSelected = response.data.selected;
|
|||
|
|
this.llm_cfg = response.data.llm_cfg;
|
|||
|
|
$nextTick(() => {
|
|||
|
|
this.tabRepositionMarker(document.getElementById(this.tabSelected))
|
|||
|
|
})
|
|||
|
|
}).catch(error => {
|
|||
|
|
console.error('Error fetching data:', error);
|
|||
|
|
throw error; // 重新抛出错误以便调用者可以处理
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
//动态加载,AI对话框
|
|||
|
|
this.$watch('chat_modalIsOpen',value => {
|
|||
|
|
if (value){
|
|||
|
|
this.$nextTick(() => {
|
|||
|
|
var dom = document.getElementById('chat_ai_dialog')
|
|||
|
|
scan_alp_units(dom);
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
},
|
|||
|
|
save(){
|
|||
|
|
const newItem = {
|
|||
|
|
selected: this.tabSelected,
|
|||
|
|
llm_cfg: this.llm_cfg,
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 使用 axios 发送 POST 请求
|
|||
|
|
axios.post('/api/llm', newItem)
|
|||
|
|
.then(response =>{
|
|||
|
|
this.save_fin=true;
|
|||
|
|
console.info(response.data.code);
|
|||
|
|
})
|
|||
|
|
.catch(error => {
|
|||
|
|
alert(error);
|
|||
|
|
console.error('Error post data:', error);
|
|||
|
|
throw error; // 重新抛出错误以便调用者可以处理
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
}"
|
|||
|
|
|
|||
|
|
class="mx-auto relative w-full max-w-3xl">
|
|||
|
|
|
|||
|
|
<div class="relative inline-grid items-center justify-center w-full h-10 grid-cols-9 p-1 text-gray-500 bg-gray-100 rounded-lg select-none">
|
|||
|
|
<template x-for="(llm, index) in llm_cfg" :key="index">
|
|||
|
|
<button :id="llm.id" @click="tabButtonClicked(llm.id,$el)" x-text="llm.tab" type="button" class="relative z-20 inline-flex items-center justify-center w-full h-8 px-3 text-sm font-medium transition-all rounded-md cursor-pointer whitespace-nowrap">本地大模型</button>
|
|||
|
|
|
|||
|
|
</template>
|
|||
|
|
<div x-ref="tabMarker" class="absolute left-0 z-10 w-1/2 h-full duration-300 ease-out" x-cloak><div class="w-full h-full bg-white rounded-md shadow-sm"></div></div>
|
|||
|
|
</div>
|
|||
|
|
<div class="relative w-full mt-2 content">
|
|||
|
|
|
|||
|
|
<template x-for="(llm, index) in llm_cfg" :key="index">
|
|||
|
|
<div x-show="tabSelected==llm.id" class="relative">
|
|||
|
|
<!-- Tab Content 2 - Replace with your content -->
|
|||
|
|
<div class="border rounded-lg shadow-sm bg-card text-neutral-900">
|
|||
|
|
<div class="flex flex-col space-y-1.5 p-6">
|
|||
|
|
<h3 x-text="llm.title" class="text-lg font-semibold leading-none tracking-tight">阿里通义千问大模型</h3>
|
|||
|
|
<p x-text="llm.desc" class="text-sm text-neutral-500">阿里云厂家提供的大模型API,需要付费使用。支持兼容OpenAI的接口形式,可以选择qwen-max,qwen-72b等</p>
|
|||
|
|
</div>
|
|||
|
|
<div class="p-6 pt-0 space-y-2">
|
|||
|
|
<div class="space-y-1"><label class="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70" for="password">Server地址</label>
|
|||
|
|
<input type="text" x-model="llm.url" value="https://dashscope.aliyuncs.com/compatible-mode/v1" class="flex w-full h-10 px-3 py-2 text-sm bg-white border rounded-md peer border-neutral-300 ring-offset-background placeholder:text-neutral-400 focus:border-neutral-300 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-neutral-400 disabled:cursor-not-allowed disabled:opacity-50" /></div>
|
|||
|
|
<div class="space-y-1"><label class="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70" for="password">模型名称</label>
|
|||
|
|
<input type="text" x-model="llm.name" value="qwen-max" class="flex w-full h-10 px-3 py-2 text-sm bg-white border rounded-md peer border-neutral-300 ring-offset-background placeholder:text-neutral-400 focus:border-neutral-300 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-neutral-400 disabled:cursor-not-allowed disabled:opacity-50" /></div>
|
|||
|
|
|
|||
|
|
<div class="space-y-1"><label class="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70" for="password_new">Api_key</label>
|
|||
|
|
<input type="text" x-model="llm.api_key" placeholder="你的api_key" class="flex w-full h-10 px-3 py-2 text-sm bg-white border rounded-md border-neutral-300 ring-offset-background placeholder:text-neutral-400 focus:border-neutral-300 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-neutral-400 disabled:cursor-not-allowed disabled:opacity-50" /></div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
</div>
|
|||
|
|
<!-- End Tab Content 2 -->
|
|||
|
|
</div>
|
|||
|
|
</template>
|
|||
|
|
<div class="flex items-center p-6 pt-4">
|
|||
|
|
<button type="button" @click="save" class="mx-auto 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 type="button" @click="chat_modalIsOpen=true" class="mx-auto 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>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<template x-if="chat_modalIsOpen">
|
|||
|
|
<!-- 大模型对话测试窗口 -->
|
|||
|
|
<div x-transition.opacity.duration.200ms x-trap.inert.noscroll="chat_modalIsOpen" x-on:keydown.esc.window="chat_modalIsOpen = false" x-on:click.self="chat_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 = 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 id="chat_ai_dialog" alp-unit="llm_chat.aps"></div>
|
|||
|
|
|
|||
|
|
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</template>
|
|||
|
|
|
|||
|
|
<!-- 通知窗口-->
|
|||
|
|
<!-- Success Alert -->
|
|||
|
|
<div x-show="save_fin" class="fixed top-10 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">保存成功</h3>
|
|||
|
|
<p class="text-xs font-medium sm:text-sm">大模型配置完成后,需要重新启动web服务才能生效!</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>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</template>
|
|||
|
|
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
|
|||
|
|
</div>
|