提交 59b14e7f 编写于 作者: D DebugIsFalse

Merge branch 'main' of gitcode.com:git_bot/ai-fe

<template> <template>
<NuxtPwaManifest /> <NuxtPwaManifest/>
<NuxtLoadingIndicator /> <NuxtLoadingIndicator/>
<NuxtLayout> <NuxtLayout>
<NuxtPage /> <NuxtPage/>
</NuxtLayout> </NuxtLayout>
<UNotifications /> <UNotifications/>
<UModals /> <UModals/>
</template> </template>
<script setup> <script setup>
const { $updateUserInfo } = useUserStore() const { $updateUserInfo } = useUserStore()
......
<template> <template>
<UPopover :popper="{ strategy: 'absolute' }" :ui="{ width: 'w-[156px]' }"> <UPopover :popper="{ strategy: 'absolute' }" :ui="{ width: 'w-[156px]' }">
<template #default="{ open }"> <template #default="{ open }">
<UButton <UButton
color="gray" color="gray"
variant="ghost" variant="ghost"
square square
:class="[open && 'bg-gray-50 dark:bg-gray-800']" :class="[open && 'bg-gray-50 dark:bg-gray-800']"
icon="i-heroicons-swatch-16-solid" icon="i-heroicons-swatch-16-solid"
:ui="{ icon: { base: 'text-primary-500 dark:text-primary-400' } }" :ui="{ icon: { base: 'text-primary-500 dark:text-primary-400' } }"
aria-label="Color picker" aria-label="Color picker"
/> />
</template> </template>
<template #panel> <template #panel>
<div class="flex flex-col p-2 gap-2"> <div class="flex flex-col p-2 gap-2">
<div class="grid grid-cols-5 gap-px"> <div class="grid grid-cols-5 gap-px">
<ColorPickerPill v-for="color in primaryColors" :key="color.value" :color="color" :selected="primary" @select="primary = color" /> <ColorPickerPill v-for="color in primaryColors" :key="color.value" :color="color" :selected="primary"
</div> @select="primary = color"/>
</div>
<UDivider />
<UDivider/>
<div class="grid grid-cols-5 gap-px">
<ColorPickerPill v-for="color in grayColors" :key="color.value" :color="color" :selected="gray" @select="gray = color" /> <div class="grid grid-cols-5 gap-px">
</div> <ColorPickerPill v-for="color in grayColors" :key="color.value" :color="color" :selected="gray"
</div> @select="gray = color"/>
</template> </div>
</UPopover> </div>
</template>
</UPopover>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
......
<template> <template>
<UTooltip :text="color.value" class="capitalize" :open-delay="500"> <UTooltip :text="color.value" class="capitalize" :open-delay="500">
<UButton <UButton
color="white" color="white"
square square
:ui="{ :ui="{
color: { color: {
white: { white: {
solid: 'ring-0 bg-gray-100 dark:bg-gray-800 hover:bg-gray-100 dark:hover:bg-gray-800', solid: 'ring-0 bg-gray-100 dark:bg-gray-800 hover:bg-gray-100 dark:hover:bg-gray-800',
...@@ -11,12 +11,12 @@ ...@@ -11,12 +11,12 @@
} }
} }
}" }"
:variant="color.value === selected.value ? 'solid' : 'ghost'" :variant="color.value === selected.value ? 'solid' : 'ghost'"
@click.stop.prevent="$emit('select')" @click.stop.prevent="$emit('select')"
> >
<span class="inline-block w-3 h-3 rounded-full" :style="{ backgroundColor: color.hex }" /> <span class="inline-block w-3 h-3 rounded-full" :style="{ backgroundColor: color.hex }"/>
</UButton> </UButton>
</UTooltip> </UTooltip>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
......
<template> <template>
<div class="flex-grow overflow-hidden bg-gray-100 dark:bg-gray-900 border-r border-gray-200 dark:border-gray-800"> <div class="flex-grow overflow-hidden bg-gray-100 dark:bg-gray-900 border-r border-gray-200 dark:border-gray-800">
<div class="p-4 h-full flex flex-col"> <div class="p-4 h-full flex flex-col">
<ILogo class="mt-2" /> <ILogo class="mt-2"/>
<UButton <UButton
:ui="{ rounded: 'rounded-full' }" :ui="{ rounded: 'rounded-full' }"
class="flex w-full mt-6" class="flex w-full mt-6"
color="gray" color="gray"
leading-icon="i-heroicons-plus-20-solid" leading-icon="i-heroicons-plus-20-solid"
size="md" size="md"
@click="handleShowCreate" @click="handleShowCreate"
> >
<div class="flex flex-grow justify-between items-center"> <div class="flex flex-grow justify-between items-center">
<span>新主题</span> <span>新主题</span>
<div v-if="$device.isDesktop" class="flex items-center gap-0.5"> <div v-if="$device.isDesktop" class="flex items-center gap-0.5">
<UKbd>{{ metaSymbol }}</UKbd> <UKbd>{{ metaSymbol }}</UKbd>
<UKbd>K</UKbd> <UKbd>K</UKbd>
</div> </div>
</div> </div>
</UButton> </UButton>
<div class="flex flex-grow overflow-hidden mt-4"> <div class="flex flex-grow overflow-hidden mt-4">
<INav /> <INav/>
</div> </div>
</div> </div>
</div> </div>
<UDivider /> <UDivider/>
<div class="bg-gray-100 dark:bg-gray-900 border-r border-gray-200 dark:border-gray-800 flex flex-col items-center justify-center"> <div
<IUserInfo /> class="bg-gray-100 dark:bg-gray-900 border-r border-gray-200 dark:border-gray-800 flex flex-col items-center justify-center">
</div> <IUserInfo/>
<UModal v-model="isOpenCreate" :ui="{ width: 'w-full sm:max-w-screen-md' }"> </div>
<ICreate @search="handleCloseCreate" /> <UModal v-model="isOpenCreate" :ui="{ width: 'w-full sm:max-w-screen-md' }">
</UModal> <ICreate @search="handleCloseCreate"/>
</UModal>
</template> </template>
<script setup> <script setup>
const { metaSymbol } = useShortcuts() const { metaSymbol } = useShortcuts()
......
<template> <template>
<Transition <Transition
@enter="onEnter" @enter="onEnter"
@after-enter="onAfterEnter" @after-enter="onAfterEnter"
@before-leave="onBeforeLeave" @before-leave="onBeforeLeave"
@leave="onLeave" @leave="onLeave"
> >
<div v-show="open" class="flex transition-[height] overflow-hidden"><slot /></div> <div v-show="open" class="flex transition-[height] overflow-hidden">
</Transition> <slot/>
</div>
</Transition>
</template> </template>
<script setup> <script setup>
defineProps({ defineProps({
......
<template> <template>
<UModal :ui="{ width: 'w-96 sm:max-w-screen-md' }"> <UModal :ui="{ width: 'w-96 sm:max-w-screen-md' }">
<div class="flex p-6 gap-4"> <div class="flex p-6 gap-4">
<div class="flex"> <div class="flex">
<div class="mx-auto flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-full bg-red-100"> <div class="mx-auto flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-full bg-red-100">
<UIcon name="i-heroicons-exclamation-triangle" class="w-6 h-6 text-red-600" /> <UIcon name="i-heroicons-exclamation-triangle" class="w-6 h-6 text-red-600"/>
</div> </div>
</div> </div>
<div class="flex-grow flex flex-col"> <div class="flex-grow flex flex-col">
<div class="text-base leading-6 text-gray-900 dark:text-gray-300 truncate">{{ title }}</div> <div class="text-base leading-6 text-gray-900 dark:text-gray-300 truncate">{{ title }}</div>
<div class="mt-2 text-sm text-gray-500">{{ description }}</div> <div class="mt-2 text-sm text-gray-500">{{ description }}</div>
</div> </div>
</div> </div>
<div class="p-4 flex justify-end gap-2"> <div class="p-4 flex justify-end gap-2">
<UButton color="white" @click="handleCancel">取消</UButton> <UButton color="white" @click="handleCancel">取消</UButton>
<UButton color="red" @click="handleSuccess">确定</UButton> <UButton color="red" @click="handleSuccess">确定</UButton>
</div> </div>
</UModal> </UModal>
</template> </template>
<script setup> <script setup>
defineProps({ defineProps({
......
<template> <template>
<div class="max-w-screen-md w-full flex flex-col space-y-4 p-6"> <div class="max-w-screen-md w-full flex flex-col space-y-4 p-6">
<UCard <UCard
class="transition-[box-shadow] hover:ring-2 has-[textarea:focus]:ring-2 has-[textarea:focus]:ring-primary-500 dark:has-[textarea:focus]:ring-primary-400" class="transition-[box-shadow] hover:ring-2 has-[textarea:focus]:ring-2 has-[textarea:focus]:ring-primary-500 dark:has-[textarea:focus]:ring-primary-400"
:ui="cardUI" :ui="cardUI"
> >
<UTextarea <UTextarea
v-model="query" v-model="query"
name="createInput" name="createInput"
autoresize autoresize
placeholder="输入搜索内容..." placeholder="输入搜索内容..."
:rows="5" :rows="5"
variant="none" variant="none"
:padded="false" :padded="false"
maxlength="2000" maxlength="2000"
/> />
<div class="flex justify-between items-center"> <div class="flex justify-between items-center">
<div class="flex items-center gap-2"> <div class="flex items-center gap-2">
<UTooltip class="relative" :text="isPro ? '已开启专家搜索' : '已关闭专家搜索'" :shortcuts="[metaSymbol, 'O']"> <UTooltip class="relative" :text="isPro ? '已开启专家搜索' : '已关闭专家搜索'" :shortcuts="[metaSymbol, 'O']">
<div v-show="!isPro" class="absolute w-7 h-0.5 rotate-45 top-3.5 left-1 bg-gray-700 dark:bg-gray-200 hover:bg-gray-900 dark:hover:bg-white rounded"/> <div v-show="!isPro"
<UButton class="absolute w-7 h-0.5 rotate-45 top-3.5 left-1 bg-gray-700 dark:bg-gray-200 hover:bg-gray-900 dark:hover:bg-white rounded"/>
:ui="{ rounded: 'rounded-full' }" <UButton
:icon="isPro ? 'i-heroicons-sparkles-20-solid' : 'i-heroicons-sparkles-20-solid'" :ui="{ rounded: 'rounded-full' }"
color="gray" :icon="isPro ? 'i-heroicons-sparkles-20-solid' : 'i-heroicons-sparkles-20-solid'"
variant="ghost" color="gray"
@click="handleTogglePro" variant="ghost"
/> @click="handleTogglePro"
</UTooltip> />
<USelectMenu </UTooltip>
v-model="selectedRepo" <USelectMenu
:ui-menu="menuUI" v-model="selectedRepo"
:options="$repos" :ui-menu="menuUI"
placeholder="选择 GitHub 项目" :options="$repos"
value-attribute="label" placeholder="选择 GitHub 项目"
option-attribute="label" value-attribute="label"
> option-attribute="label"
<UTooltip v-if="!selectedRepo" :text="isPro ? '选择 GitHub 项目' : '选择 GitHub 项目(需开启专家搜索)'"> >
<UButton <UTooltip v-if="!selectedRepo" :text="isPro ? '选择 GitHub 项目' : '选择 GitHub 项目(需开启专家搜索)'">
:ui="{ rounded: 'rounded-full' }" <UButton
icon="i-simple-icons-github" :ui="{ rounded: 'rounded-full' }"
color="gray" icon="i-simple-icons-github"
variant="ghost" color="gray"
:disabled="!isPro" variant="ghost"
/> :disabled="!isPro"
</UTooltip> />
</UTooltip>
<UButton v-else color="gray" variant="ghost" :class="{ 'group': selectedRepo }"> <UButton v-else color="gray" variant="ghost" :class="{ 'group': selectedRepo }">
<UIcon name="i-simple-icons-github" /> <UIcon name="i-simple-icons-github"/>
<span>{{ selectedRepo }}</span> <span>{{ selectedRepo }}</span>
<UIcon name="i-heroicons-chevron-down-20-solid" class="text-xl flex group-hover:hidden" /> <UIcon name="i-heroicons-chevron-down-20-solid" class="text-xl flex group-hover:hidden"/>
<UButton <UButton
v-if="selectedRepo" v-if="selectedRepo"
class="hidden group-hover:flex" class="hidden group-hover:flex"
icon="i-heroicons-x-mark-20-solid" icon="i-heroicons-x-mark-20-solid"
:padded="false" :padded="false"
color="gray" color="gray"
variant="link" variant="link"
@click.stop.prevent="handleClearRepo" @click.stop.prevent="handleClearRepo"
/> />
</UButton> </UButton>
</USelectMenu> </USelectMenu>
</div> </div>
<UTooltip text="搜索" :shortcuts="[metaSymbol, '↵']"> <UTooltip text="搜索" :shortcuts="[metaSymbol, '↵']">
<UButton <UButton
:ui="{ rounded: 'rounded-full' }" :ui="{ rounded: 'rounded-full' }"
icon="i-heroicons-chevron-right-20-solid" icon="i-heroicons-chevron-right-20-solid"
:loading="loading" :loading="loading"
:disabled="query === ''" :disabled="query === ''"
size="md" size="md"
@click="handleSearch" @click="handleSearch"
/> />
</UTooltip> </UTooltip>
</div> </div>
</UCard> </UCard>
</div> </div>
</template> </template>
<script setup> <script setup>
const { $repos } = storeToRefs(useReposStore()) const { $repos } = storeToRefs(useReposStore())
......
<template> <template>
<div class="flex flex-col justify-center h-72 items-center text-gray-300" :class="{ 'h-36': size === 'xs' }"> <div class="flex flex-col justify-center h-72 items-center text-gray-300" :class="{ 'h-36': size === 'xs' }">
<UIcon name="i-heroicons-inbox" class="text-6xl" /> <UIcon name="i-heroicons-inbox" class="text-6xl"/>
<div>暂无数据</div> <div>暂无数据</div>
</div> </div>
</template> </template>
<script setup> <script setup>
defineProps({ defineProps({
......
<template> <template>
<div class="grid min-h-full place-items-center px-6 py-24 sm:py-32 lg:px-8"> <div class="grid min-h-full place-items-center px-6 py-24 sm:py-32 lg:px-8">
<div class="text-center"> <div class="text-center">
<p class="text-base font-semibold text-red-600">{{ code }}</p> <p class="text-base font-semibold text-red-600">{{ code }}</p>
<h1 class="mt-4 text-3xl font-bold tracking-tight sm:text-5xl">{{ errorTitle }}</h1> <h1 class="mt-4 text-3xl font-bold tracking-tight sm:text-5xl">{{ errorTitle }}</h1>
<p class="mt-6 text-base leading-7">{{ errorDescription }}</p> <p class="mt-6 text-base leading-7">{{ errorDescription }}</p>
<div class="mt-10 flex items-center justify-center gap-x-6"> <div class="mt-10 flex items-center justify-center gap-x-6">
<UButton to="/" size="lg">返回首页</UButton> <UButton to="/" size="lg">返回首页</UButton>
</div> </div>
</div> </div>
</div> </div>
</template> </template>
<script setup> <script setup>
const props = defineProps({ const props = defineProps({
......
<template> <template>
<div class="flex justify-center"> <div class="flex justify-center">
<NuxtLink to="/" class="font-mono text-2xl font-medium">GitBot.<span class="text-primary">AI</span></NuxtLink> <NuxtLink to="/" class="font-mono text-2xl font-medium">GitBot.<span class="text-primary">AI</span></NuxtLink>
</div> </div>
</template> </template>
\ No newline at end of file
<template> <template>
<div class="flex md:hidden flex-shrink-0"> <div class="flex md:hidden flex-shrink-0">
<UButton <UButton
class="z-20" class="z-20"
:class="{ 'fixed top-2 left-2' : fixed }" :class="{ 'fixed top-2 left-2' : fixed }"
color="white" color="white"
trailing-icon="i-heroicons-bars-3-20-solid" trailing-icon="i-heroicons-bars-3-20-solid"
@click="handleToggleAside" @click="handleToggleAside"
/> />
<USlideover <USlideover
v-model="isOpenAside" v-model="isOpenAside"
class="w-64" class="w-64"
side="left" side="left"
:overlay="false" :overlay="false"
> >
<UButton <UButton
class="absolute top-2 right-2 z-20" class="absolute top-2 right-2 z-20"
color="white" color="white"
trailing-icon="i-heroicons-x-mark-20-solid" trailing-icon="i-heroicons-x-mark-20-solid"
@click="handleToggleAside" @click="handleToggleAside"
/> />
<IAside /> <IAside/>
</USlideover> </USlideover>
</div> </div>
</template> </template>
<script setup> <script setup>
defineProps({ defineProps({
......
<template> <template>
<div class="flex flex-col w-full gap-2"> <div class="flex flex-col w-full gap-2">
<UButton <UButton
leading-icon="i-heroicons-home" leading-icon="i-heroicons-home"
color="gray" color="gray"
variant="ghost" variant="ghost"
size="md" size="md"
label="首页" label="首页"
to="/" to="/"
/> />
<UButton <UButton
leading-icon="i-heroicons-rectangle-stack" leading-icon="i-heroicons-rectangle-stack"
color="gray" color="gray"
variant="ghost" variant="ghost"
size="md" size="md"
label="主题" label="主题"
to="/library" to="/library"
/> />
<ISearchHistory @sign="$openSign" /> <ISearchHistory @sign="$openSign"/>
<ClientOnly> <ClientOnly>
<UButton <UButton
v-if="!$isSignIn" v-if="!$isSignIn"
class="flex gap-2 justify-center" class="flex gap-2 justify-center"
size="lg" size="lg"
label="登录" label="登录"
@click="$openSign" @click="$openSign"
/> />
</ClientOnly> </ClientOnly>
</div> </div>
<UModal v-model="$isOpenSign"> <UModal v-model="$isOpenSign">
<ISign @close="$closeSign" /> <ISign @close="$closeSign"/>
</UModal> </UModal>
</template> </template>
<script setup> <script setup>
const { $isSignIn, $isOpenSign } = storeToRefs(useUserStore()) const { $isSignIn, $isOpenSign } = storeToRefs(useUserStore())
......
<template> <template>
<div class="flex flex-col overflow-hidden group"> <div class="flex flex-col overflow-hidden group">
<div class="flex justify-between"> <div class="flex justify-between">
<UButton <UButton
class="flex-grow cursor-default hover:bg-transparent dark:hover:bg-transparent" class="flex-grow cursor-default hover:bg-transparent dark:hover:bg-transparent"
leading-icon="i-heroicons-queue-list" leading-icon="i-heroicons-queue-list"
color="gray" color="gray"
variant="ghost" variant="ghost"
size="md" size="md"
label="浏览记录" label="浏览记录"
/> />
<UButton <UButton
class="hidden group-hover:flex" class="hidden group-hover:flex"
label="清空" label="清空"
size="md" size="md"
variant="link" variant="link"
@click="handleClear" @click="handleClear"
/> />
</div> </div>
<ClientOnly> <ClientOnly>
<div v-auto-animate class="flex overflow-y-auto flex-col gap-1 border-l border-gray-200 dark:border-gray-800 pl-2 ml-5"> <div v-auto-animate
<template v-for="item in $searchHistory.reverse()" :key="item.c_id"> class="flex overflow-y-auto flex-col gap-1 border-l border-gray-200 dark:border-gray-800 pl-2 ml-5">
<UButton <template v-for="item in $searchHistory.reverse()" :key="item.c_id">
class="flex text-gray-400" <UButton
color="gray" class="flex text-gray-400"
variant="ghost" color="gray"
size="xs" variant="ghost"
long size="xs"
:to="`/search/${item.c_id}`" long
> :to="`/search/${item.c_id}`"
<div class="flex-grow truncate" :title="item.title">{{ item.title }}</div> >
</UButton> <div class="flex-grow truncate" :title="item.title">{{ item.title }}</div>
</template> </UButton>
</div> </template>
</ClientOnly> </div>
</div> </ClientOnly>
</div>
</template> </template>
<script setup> <script setup>
const { $searchHistory } = storeToRefs(useSearchStore()) const { $searchHistory } = storeToRefs(useSearchStore())
......
<template> <template>
<div class="flex flex-col items-start gap-4 p-4"> <div class="flex flex-col items-start gap-4 p-4">
<div class="flex w-full justify-between"> <div class="flex w-full justify-between">
<ILogo /> <ILogo/>
<UButton <UButton
color="gray" color="gray"
variant="ghost" variant="ghost"
leading-icon="i-heroicons-x-mark-20-solid" leading-icon="i-heroicons-x-mark-20-solid"
@click="handleClose" @click="handleClose"
/> />
</div> </div>
<div>登录以继续使用</div> <div>登录以继续使用</div>
<UButton <UButton
block block
color="gray" color="gray"
size="md" size="md"
@click="handleGetSignUrl('gitcode')" @click="handleGetSignUrl('gitcode')"
> >
<img src="~/assets/svg/logo-gitcode.svg" > <img src="~/assets/svg/logo-gitcode.svg">
使用 GitCode 登录 使用 GitCode 登录
</UButton> </UButton>
<UButton <UButton
block block
leading-icon="i-simple-icons-github" leading-icon="i-simple-icons-github"
label="使用 GitHub 登录" label="使用 GitHub 登录"
color="gray" color="gray"
size="md" size="md"
@click="handleGetSignUrl('github')" @click="handleGetSignUrl('github')"
/> />
<UButton <UButton
block block
leading-icon="i-simple-icons-google" leading-icon="i-simple-icons-google"
label="使用 Google 登录" label="使用 Google 登录"
color="gray" color="gray"
size="md" size="md"
disabled disabled
/> />
<!-- <UDivider label="或" />--> <!-- <UDivider label="或" />-->
<!-- <UInput--> <!-- <UInput-->
<!-- class="w-full"--> <!-- class="w-full"-->
<!-- v-model="email"--> <!-- v-model="email"-->
<!-- placeholder="输入邮箱地址..."--> <!-- placeholder="输入邮箱地址..."-->
<!-- size="md"--> <!-- size="md"-->
<!-- />--> <!-- />-->
<!-- <UButton--> <!-- <UButton-->
<!-- block--> <!-- block-->
<!-- leading-icon="i-heroicons-envelope-20-solid"--> <!-- leading-icon="i-heroicons-envelope-20-solid"-->
<!-- label="邮箱登录"--> <!-- label="邮箱登录"-->
<!-- size="md"--> <!-- size="md"-->
<!-- @click="handleSign"--> <!-- @click="handleSign"-->
<!-- />--> <!-- />-->
</div> </div>
</template> </template>
<script setup> <script setup>
const emits = defineEmits(['close', 'signIn']) const emits = defineEmits(['close', 'signIn'])
......
<template> <template>
<div class="flex flex-col w-full"> <div class="flex flex-col w-full">
<ClientOnly> <ClientOnly>
<template v-if="$isSignIn"> <template v-if="$isSignIn">
<div class="flex flex-grow justify-between items-center p-4"> <div class="flex flex-grow justify-between items-center p-4">
<UDropdown class="flex flex-grow" :items="items"> <UDropdown class="flex flex-grow" :items="items">
<UButton class="flex flex-grow" color="gray" variant="ghost"> <UButton class="flex flex-grow" color="gray" variant="ghost">
<div class="flex flex-grow items-center gap-2"> <div class="flex flex-grow items-center gap-2">
<UAvatar :src="$info.avatar_url" /> <UAvatar :src="$info.avatar_url"/>
<div>{{ $info.nickname }}</div> <div>{{ $info.nickname }}</div>
<UBadge v-if="$info.pro" size="xs" color="yellow" variant="soft" label="PRO" /> <UBadge v-if="$info.pro" size="xs" color="yellow" variant="soft" label="PRO"/>
<UBadge v-else size="xs" color="gray" variant="soft" label="FREE" /> <UBadge v-else size="xs" color="gray" variant="soft" label="FREE"/>
</div> </div>
<UIcon name="i-heroicons-chevron-down-20-solid" class="text-lg" /> <UIcon name="i-heroicons-chevron-down-20-solid" class="text-lg"/>
</UButton> </UButton>
</UDropdown> </UDropdown>
</div> </div>
<UDivider /> <UDivider/>
</template> </template>
</ClientOnly> </ClientOnly>
<div class="flex justify-between gap-2 p-4"> <div class="flex justify-between gap-2 p-4">
<UButton <UButton
color="gray" color="gray"
variant="ghost" variant="ghost"
label="问题反馈" label="问题反馈"
/> />
<ClientOnly> <ClientOnly>
<div class="flex"> <div class="flex">
<ColorPicker /> <ColorPicker/>
<USelectMenu <USelectMenu
v-model="colorMode.preference" v-model="colorMode.preference"
:ui-menu="{ width: 'w-32' }" :ui-menu="{ width: 'w-32' }"
:options="themeItems" :options="themeItems"
value-attribute="value" value-attribute="value"
> >
<UButton <UButton
color="gray" color="gray"
variant="ghost" variant="ghost"
square square
:icon="colorMode.value === 'dark' ? 'i-heroicons-moon-16-solid' : 'i-heroicons-sun-16-solid'" :icon="colorMode.value === 'dark' ? 'i-heroicons-moon-16-solid' : 'i-heroicons-sun-16-solid'"
aria-label="Theme" aria-label="Theme"
/> />
</USelectMenu> </USelectMenu>
<USelectMenu <USelectMenu
v-if="false" v-if="false"
:ui-menu="{ width: 'w-32' }" :ui-menu="{ width: 'w-32' }"
:model-value="$lang" :model-value="$lang"
:options="$langOptions" :options="$langOptions"
value-attribute="value" value-attribute="value"
> >
<UButton <UButton
icon="i-heroicons-language-16-solid" icon="i-heroicons-language-16-solid"
color="gray" color="gray"
variant="ghost" variant="ghost"
/> />
</USelectMenu> </USelectMenu>
</div> </div>
</ClientOnly> </ClientOnly>
</div> </div>
</div> </div>
</template> </template>
<script setup> <script setup>
const { $signOut } = useUserStore() const { $signOut } = useUserStore()
......
<template> <template>
<UDropdown class="flex flex-grow" :items="actionItems"> <UDropdown class="flex flex-grow" :items="actionItems">
<UButton <UButton
color="gray" color="gray"
variant="ghost" variant="ghost"
square square
icon="i-heroicons-ellipsis-horizontal" icon="i-heroicons-ellipsis-horizontal"
/> />
</UDropdown> </UDropdown>
<ILibraryEdit :id="id" ref="refEdit" /> <ILibraryEdit :id="id" ref="refEdit"/>
</template> </template>
<script setup> <script setup>
import { IConfirm } from '#components' import { IConfirm } from '#components'
......
<template> <template>
<UDropdown class="flex flex-grow" :items="actionItems"> <UDropdown class="flex flex-grow" :items="actionItems">
<UButton <UButton
color="gray" color="gray"
variant="ghost" variant="ghost"
:size="size" :size="size"
square square
icon="i-heroicons-ellipsis-horizontal" icon="i-heroicons-ellipsis-horizontal"
/> />
</UDropdown> </UDropdown>
</template> </template>
<script setup> <script setup>
import { IConfirm } from '#components' import { IConfirm } from '#components'
......
<template> <template>
<ULink :to="`/library/${item.id}`"> <ULink :to="`/library/${item.id}`">
<UCard :ui="cardUI"> <UCard :ui="cardUI">
<div class="flex flex-col gap-1"> <div class="flex flex-col gap-1">
<div>{{ item.name }}</div> <div>{{ item.name }}</div>
<div class="flex"> <div class="flex">
<div class="flex items-center text-gray-500 text-sm gap-0.5"> <div class="flex items-center text-gray-500 text-sm gap-0.5">
<UIcon name="i-heroicons-square-3-stack-3d" /> <UIcon name="i-heroicons-square-3-stack-3d"/>
<span>{{ item.record_count }}</span> <span>{{ item.record_count }}</span>
</div> </div>
</div> </div>
</div> </div>
</UCard> </UCard>
</ULink> </ULink>
</template> </template>
<script setup> <script setup>
defineProps({ defineProps({
......
<template> <template>
<UModal <UModal
:model-value="!id ? $isLibraryCreateOpen : updateVisible" :model-value="!id ? $isLibraryCreateOpen : updateVisible"
:ui="{ width: 'w-96 sm:max-w-screen-md' }" :ui="{ width: 'w-96 sm:max-w-screen-md' }"
@update:model-value="handleCloseModal" @update:model-value="handleCloseModal"
> >
<UCard :ui="{ ring: '', divide: 'divide-y divide-gray-100 dark:divide-gray-800' }"> <UCard :ui="{ ring: '', divide: 'divide-y divide-gray-100 dark:divide-gray-800' }">
<template #header> <template #header>
<div class="flex items-center justify-between"> <div class="flex items-center justify-between">
<div v-if="!id" class="text-xl">创建合集</div> <div v-if="!id" class="text-xl">创建合集</div>
<div v-else class="text-xl">更新合集</div> <div v-else class="text-xl">更新合集</div>
<UButton <UButton
leading-icon="i-heroicons-x-mark-20-solid" leading-icon="i-heroicons-x-mark-20-solid"
color="gray" color="gray"
variant="ghost" variant="ghost"
@click="handleClose" @click="handleClose"
/> />
</div> </div>
</template> </template>
<div class="flex flex-col gap-6"> <div class="flex flex-col gap-6">
<div class="flex flex-col gap-1"> <div class="flex flex-col gap-1">
<div class="flex content-center items-center justify-between text-sm"> <div class="flex content-center items-center justify-between text-sm">
<label class="block font-medium text-gray-700 dark:text-gray-200">标题</label> <label class="block font-medium text-gray-700 dark:text-gray-200">标题</label>
</div> </div>
<UInput <UInput
v-model="title" v-model="title"
placeholder="合集标题" placeholder="合集标题"
autofocus autofocus
/> />
</div> </div>
<div class="flex flex-col gap-1"> <div class="flex flex-col gap-1">
<div class="flex content-center items-center justify-between text-sm"> <div class="flex content-center items-center justify-between text-sm">
<label class="block font-medium text-gray-700 dark:text-gray-200"> <label class="block font-medium text-gray-700 dark:text-gray-200">
描述 描述
<span class="text-gray-400 dark:text-gray-100">(可选)</span> <span class="text-gray-400 dark:text-gray-100">(可选)</span>
</label> </label>
</div> </div>
<UTextarea <UTextarea
v-model="description" v-model="description"
placeholder="合集描述" placeholder="合集描述"
/> />
</div> </div>
</div> </div>
<template #footer> <template #footer>
<div class="flex justify-end"> <div class="flex justify-end">
<UButton <UButton
v-if="!id" v-if="!id"
size="md" size="md"
label="创建" label="创建"
:loading="loading" :loading="loading"
:disabled="!title" :disabled="!title"
@click="handleCreate" @click="handleCreate"
/> />
<UButton <UButton
v-else v-else
size="md" size="md"
label="更新" label="更新"
:loading="loading" :loading="loading"
:disabled="!title" :disabled="!title"
@click="handleUpdate" @click="handleUpdate"
/> />
</div> </div>
</template> </template>
</UCard> </UCard>
</UModal> </UModal>
</template> </template>
<script setup> <script setup>
const { $isLibraryCreateOpen, $collection } = storeToRefs(useLibraryStore()) const { $isLibraryCreateOpen, $collection } = storeToRefs(useLibraryStore())
......
<template> <template>
<ILibraryCreate :id="id" ref="refCreate" /> <ILibraryCreate :id="id" ref="refCreate"/>
</template> </template>
<script setup> <script setup>
defineProps({ defineProps({
......
<template> <template>
<div class="flex flex-col w-full items-center sticky top-0 bg-white dark:bg-black z-10"> <div class="flex flex-col w-full items-center sticky top-0 bg-white dark:bg-black z-10">
<div class="container max-w-screen-lg 2xl:max-w-screen-xl flex flex-col p-6"> <div class="container max-w-screen-lg 2xl:max-w-screen-xl flex flex-col p-6">
<div class="flex justify-between items-center gap-4"> <div class="flex justify-between items-center gap-4">
<div class="flex gap-4"> <div class="flex gap-4">
<IMenuSider /> <IMenuSider/>
<div v-if="!collect" class="flex flex-shrink-0 items-center text-xl gap-2"> <div v-if="!collect" class="flex flex-shrink-0 items-center text-xl gap-2">
<UIcon name="i-heroicons-rectangle-stack-20-solid" /> <UIcon name="i-heroicons-rectangle-stack-20-solid"/>
<div>主题</div> <div>主题</div>
</div> </div>
<template v-else> <template v-else>
<UButton <UButton
icon="i-heroicons-chevron-left" icon="i-heroicons-chevron-left"
color="gray" color="gray"
variant="ghost" variant="ghost"
to="/library" to="/library"
/> />
<div class="flex items-center text-xl gap-2"> <div class="flex items-center text-xl gap-2">
<UIcon name="i-heroicons-squares-2x2" /> <UIcon name="i-heroicons-squares-2x2"/>
<div>{{ collect }}</div> <div>{{ collect }}</div>
<UBadge color="gray" variant="soft" :label="count" /> <UBadge color="gray" variant="soft" :label="count"/>
</div> </div>
</template> </template>
</div> </div>
<div class="flex flex-grow justify-end items-center gap-4"> <div class="flex flex-grow justify-end items-center gap-4">
<div class="flex"> <div class="flex">
<IActionCollect v-if="collect" :id="collectId" /> <IActionCollect v-if="collect" :id="collectId"/>
</div> </div>
<div v-if="!collect" class="flex"> <div v-if="!collect" class="flex">
<UInput <UInput
v-model="searchQuery" v-model="searchQuery"
name="queryInput" name="queryInput"
:ui="{ icon: { trailing: { pointer: '' } } }" :ui="{ icon: { trailing: { pointer: '' } } }"
:loading="searchLoading" :loading="searchLoading"
icon="i-heroicons-magnifying-glass-20-solid" icon="i-heroicons-magnifying-glass-20-solid"
placeholder="搜索你的主题..." placeholder="搜索你的主题..."
size="md" size="md"
> >
<template #trailing> <template #trailing>
<UButton <UButton
v-show="searchQuery !== ''" v-show="searchQuery !== ''"
color="gray" color="gray"
variant="link" variant="link"
icon="i-heroicons-x-mark-20-solid" icon="i-heroicons-x-mark-20-solid"
:padded="false" :padded="false"
@click="handleClear" @click="handleClear"
/> />
</template> </template>
</UInput> </UInput>
</div> </div>
</div> </div>
</div> </div>
<div v-if="description" class="text-gray-500 ml-12 mt-2">{{ description }}</div> <div v-if="description" class="text-gray-500 ml-12 mt-2">{{ description }}</div>
</div> </div>
<UDivider /> <UDivider/>
<div v-if="showTabs" class="w-full p-6 block lg:hidden"> <div v-if="showTabs" class="w-full p-6 block lg:hidden">
<UTabs :model-value="tab" :items="tabs" @update:model-value="handleChangeTab" /> <UTabs :model-value="tab" :items="tabs" @update:model-value="handleChangeTab"/>
</div> </div>
</div> </div>
</template> </template>
<script setup> <script setup>
defineProps({ defineProps({
......
<template> <template>
<UModal v-model="$isLibrarySelectOpen" :ui="{ width: 'w-96 sm:max-w-screen-md' }"> <UModal v-model="$isLibrarySelectOpen" :ui="{ width: 'w-96 sm:max-w-screen-md' }">
<UCard :ui="{ ring: '', divide: 'divide-y divide-gray-100 dark:divide-gray-800' }"> <UCard :ui="{ ring: '', divide: 'divide-y divide-gray-100 dark:divide-gray-800' }">
<template #header> <template #header>
<div class="flex items-center justify-between"> <div class="flex items-center justify-between">
<div class="text-xl">选择合集</div> <div class="text-xl">选择合集</div>
<UButton <UButton
leading-icon="i-heroicons-x-mark-20-solid" leading-icon="i-heroicons-x-mark-20-solid"
color="gray" color="gray"
variant="ghost" variant="ghost"
@click="handleClose" @click="handleClose"
/> />
</div> </div>
</template> </template>
<div class="flex flex-col gap-4"> <div class="flex flex-col gap-4">
<UButton <UButton
leading-icon="i-heroicons-plus-20-solid" leading-icon="i-heroicons-plus-20-solid"
label="创建新合集" label="创建新合集"
color="gray" color="gray"
@click="handleOpenCreate" @click="handleOpenCreate"
/> />
<div class="flex flex-col gap-2"> <div class="flex flex-col gap-2">
<UButton <UButton
v-for="item in $collection" v-for="item in $collection"
:key="item.id" :key="item.id"
color="white" color="white"
size="md" size="md"
class="flex" class="flex"
@click="handleSelected(item.id)" @click="handleSelected(item.id)"
> >
<div class="flex flex-grow justify-between items-center"> <div class="flex flex-grow justify-between items-center">
<div>{{ item.name }}</div> <div>{{ item.name }}</div>
<UIcon v-if="selected.includes(item.id)" name="i-heroicons-check-circle-20-solid" class="text-primary text-lg" /> <UIcon v-if="selected.includes(item.id)" name="i-heroicons-check-circle-20-solid"
</div> class="text-primary text-lg"/>
</UButton> </div>
</div> </UButton>
</div> </div>
<template #footer> </div>
<div class="flex justify-end"> <template #footer>
<UButton <div class="flex justify-end">
size="md" <UButton
label="保存" size="md"
:loading="loading" label="保存"
@click="handleSave" :loading="loading"
/> @click="handleSave"
</div> />
</template> </div>
</UCard> </template>
</UModal> </UCard>
</UModal>
</template> </template>
<script setup> <script setup>
const { $isLibrarySelectOpen, $selectCollectionId, $selectThreadId, $collection } = storeToRefs(useLibraryStore()) const { $isLibrarySelectOpen, $selectCollectionId, $selectThreadId, $collection } = storeToRefs(useLibraryStore())
......
<template> <template>
<ULink :to="`/search/${thread.c_id}`" class="flex flex-col group"> <ULink :to="`/search/${thread.c_id}`" class="flex flex-col group">
<div class="flex items-center gap-2 transition group-hover:text-primary">{{ thread.title }}</div> <div class="flex items-center gap-2 transition group-hover:text-primary">{{ thread.title }}</div>
<div v-if="false" class="break-word text-balance line-clamp-2 font-sans text-sm" :class="textColor"> <div v-if="false" class="break-word text-balance line-clamp-2 font-sans text-sm" :class="textColor">
{{ thread.description }} {{ thread.description }}
</div> </div>
</ULink> </ULink>
<div class="flex justify-between items-center"> <div class="flex justify-between items-center">
<div class="flex gap-4"> <div class="flex gap-4">
<UTooltip class="flex items-center text-sm gap-0.5" :class="textColor" :text="thread.is_public ? '公开主题,链接可被发现' : '私密主题,仅自己可见'"> <UTooltip class="flex items-center text-sm gap-0.5" :class="textColor"
<UIcon :name="thread.is_public ? 'i-heroicons-lock-open' : 'i-heroicons-lock-closed'" /> :text="thread.is_public ? '公开主题,链接可被发现' : '私密主题,仅自己可见'">
<span>{{ thread.is_public ? '公开' : '私有' }}</span> <UIcon :name="thread.is_public ? 'i-heroicons-lock-open' : 'i-heroicons-lock-closed'"/>
</UTooltip> <span>{{ thread.is_public ? '公开' : '私有' }}</span>
<!-- <div class="flex items-center text-sm gap-0.5" :class="textColor">--> </UTooltip>
<!-- <UIcon name="i-heroicons-eye" />--> <!-- <div class="flex items-center text-sm gap-0.5" :class="textColor">-->
<!-- <span>1</span>--> <!-- <UIcon name="i-heroicons-eye" />-->
<!-- </div>--> <!-- <span>1</span>-->
<div class="flex" :class="textColor"> <!-- </div>-->
<UTooltip class="flex items-center text-sm gap-0.5"> <div class="flex" :class="textColor">
<UIcon name="i-heroicons-clock" /> <UTooltip class="flex items-center text-sm gap-0.5">
<span>{{ useTime(thread.create_time) }}</span> <UIcon name="i-heroicons-clock"/>
<template #text> <span>{{ useTime(thread.create_time) }}</span>
{{ toValue(useDateFormat(thread.create_time, 'YYYY年M月D日 HH:mm')) }} <template #text>
</template> {{ toValue(useDateFormat(thread.create_time, 'YYYY年M月D日 HH:mm')) }}
</UTooltip> </template>
</div> </UTooltip>
</div> </div>
<div class="flex gap-4"> </div>
<template v-for="collect in thread.collections" :key="collect.collection_id"> <div class="flex gap-4">
<UButton <template v-for="collect in thread.collections" :key="collect.collection_id">
:ui="{ rounded: 'rounded-full' }" <UButton
:to="`/library/${collect.collection_id}`" :ui="{ rounded: 'rounded-full' }"
color="white" :to="`/library/${collect.collection_id}`"
size="2xs" color="white"
:label="collect.collection_name" size="2xs"
/> :label="collect.collection_name"
</template> />
<UTooltip v-if="!thread.collections.length" text="添加到收藏"> </template>
<UButton <UTooltip v-if="!thread.collections.length" text="添加到收藏">
color="gray" <UButton
variant="ghost" color="gray"
size="2xs" variant="ghost"
square size="2xs"
icon="i-heroicons-plus" square
@click="handleOpenSelect" icon="i-heroicons-plus"
/> @click="handleOpenSelect"
</UTooltip> />
<IActionThread </UTooltip>
:collection_id="thread.collections.length ? thread.collections[0].collection_id : ''" <IActionThread
:c_id="item.c_id" :collection_id="thread.collections.length ? thread.collections[0].collection_id : ''"
size="2xs" :c_id="item.c_id"
@delete="handleDeletedThread" size="2xs"
/> @delete="handleDeletedThread"
</div> />
</div> </div>
<UDivider /> </div>
<UDivider/>
</template> </template>
<script setup> <script setup>
const Layout = inject('Layout') const Layout = inject('Layout')
......
<template> <template>
<div class="grid grid-cols-1"> <div class="grid grid-cols-1">
<MDC v-if="content" class="prose dark:prose-invert max-w-none" :class="'prose-' + size" :value="content" tag="article" /> <MDC v-if="content" class="prose dark:prose-invert max-w-none" :class="'prose-' + size" :value="content"
</div> tag="article"/>
</div>
</template> </template>
<script setup> <script setup>
defineProps({ defineProps({
......
<template> <template>
<div class="flex flex-col lg:flex-row gap-6 space-x-0 lg:space-x-6"> <div class="flex flex-col lg:flex-row gap-6 space-x-0 lg:space-x-6">
<div class="flex flex-grow flex-col gap-6"> <div class="flex flex-grow flex-col gap-6">
<div class="grid"> <div class="grid">
<slot name="title" /> <slot name="title"/>
</div> </div>
<slot /> <slot/>
</div> </div>
<div v-if="$slots.extra" class="flex flex-col w-full lg:w-64 flex-shrink-0 gap-6"> <div v-if="$slots.extra" class="flex flex-col w-full lg:w-64 flex-shrink-0 gap-6">
<slot name="extra" /> <slot name="extra"/>
</div> </div>
</div> </div>
</template> </template>
<script setup>
</script>
\ No newline at end of file
<template> <template>
<div class="flex w-full justify-center"> <div class="flex w-full justify-center">
<UCard <UCard
class="hover:ring-2 has-[textarea:focus]:ring-2 has-[textarea:focus]:ring-primary-500 dark:has-[textarea:focus]:ring-primary-400" class="hover:ring-2 has-[textarea:focus]:ring-2 has-[textarea:focus]:ring-primary-500 dark:has-[textarea:focus]:ring-primary-400"
:ui="cardUI" :ui="cardUI"
> >
<UTextarea <UTextarea
ref="queryInput" ref="queryInput"
v-model="continueQuestion" v-model="continueQuestion"
class="flex-grow" class="flex-grow"
name="queryInput" name="queryInput"
:rows="1" :rows="1"
:maxrows="10" :maxrows="10"
autoresize autoresize
:placeholder="placeholder" :placeholder="placeholder"
size="xl" size="xl"
:padded="false" :padded="false"
variant="none" variant="none"
maxlength="2000" maxlength="2000"
@focus="handleInputFocus" @focus="handleInputFocus"
@blur="handleInputBlur" @blur="handleInputBlur"
/> />
<div class="flex flex-shrink-0 gap-2"> <div class="flex flex-shrink-0 gap-2">
<UButton <UButton
v-if="!asking" v-if="!asking"
:ui="{ rounded: 'rounded-full' }" :ui="{ rounded: 'rounded-full' }"
:disabled="!continueQuestion" :disabled="!continueQuestion"
trailing-icon="i-heroicons-chevron-right-20-solid" trailing-icon="i-heroicons-chevron-right-20-solid"
size="xl" size="xl"
@click.stop="handleAsk" @click.stop="handleAsk"
/> />
<UTooltip v-else text="停止生成"> <UTooltip v-else text="停止生成">
<UButton <UButton
:ui="{ rounded: 'rounded-full' }" :ui="{ rounded: 'rounded-full' }"
color="red" color="red"
trailing-icon="i-heroicons-stop-20-solid" trailing-icon="i-heroicons-stop-20-solid"
size="xl" size="xl"
variant="ghost" variant="ghost"
@click.stop="handleStop" @click.stop="handleStop"
/> />
</UTooltip> </UTooltip>
</div> </div>
</UCard> </UCard>
</div> </div>
</template> </template>
<script setup> <script setup>
const { metaSymbol } = useShortcuts() const { metaSymbol } = useShortcuts()
......
<template> <template>
<ISearchProcess :collapse="collapse" :actions="actions" :status="processStatus" /> <ISearchProcess :collapse="collapse" :actions="actions" :status="processStatus"/>
<template v-if="item.source && item.source.length > 0"> <template v-if="item.source && item.source.length > 0">
<div class="text-xl flex items-center space-x-1"> <div class="text-xl flex items-center space-x-1">
<UIcon name="i-heroicons-link-20-solid" /> <UIcon name="i-heroicons-link-20-solid"/>
<span>来源</span> <span>来源</span>
</div> </div>
<div class="grid grid-cols-1 lg:grid-cols-3 gap-4"> <div class="grid grid-cols-1 lg:grid-cols-3 gap-4">
<ISearchSource :source="item.source" /> <ISearchSource :source="item.source"/>
</div> </div>
</template> </template>
<div v-if="processStatus ==='finish'" class="text-xl flex items-center space-x-1"> <div v-if="processStatus ==='finish'" class="text-xl flex items-center space-x-1">
<UIcon name="i-heroicons-chat-bubble-left-right-20-solid" /> <UIcon name="i-heroicons-chat-bubble-left-right-20-solid"/>
<span>{{ item.ansLoading ? '回答中' : '回答' }}</span> <span>{{ item.ansLoading ? '回答中' : '回答' }}</span>
</div> </div>
<IMdMdc :content="item.article" /> <IMdMdc :content="item.article"/>
<div v-if="item.showActions" class="space-x-2"> <div v-if="item.showActions" class="space-x-2">
<UButton size="xs" color="gray" leading-icon="i-heroicons-document-duplicate-20-solid" label="复制" @click="handleCopyMD" /> <UButton size="xs" color="gray" leading-icon="i-heroicons-document-duplicate-20-solid" label="复制"
<UButton size="xs" color="gray" leading-icon="i-heroicons-share-20-solid" label="分享" @click="handleShare" /> @click="handleCopyMD"/>
<UButton v-if="isLastIndex" size="xs" color="gray" leading-icon="i-heroicons-arrow-path-rounded-square-20-solid" label="重写" @click="handleReGenerate" /> <UButton size="xs" color="gray" leading-icon="i-heroicons-share-20-solid" label="分享" @click="handleShare"/>
</div> <UButton v-if="isLastIndex" size="xs" color="gray" leading-icon="i-heroicons-arrow-path-rounded-square-20-solid"
label="重写" @click="handleReGenerate"/>
</div>
</template> </template>
<script setup> <script setup>
const Search = inject('Search') const Search = inject('Search')
......
<template> <template>
<div class="flex flex-col gap-4 sticky top-16"> <div class="flex flex-col gap-4 sticky top-16">
<div class="text-xl flex items-center space-x-1"> <div class="text-xl flex items-center space-x-1">
<UIcon name="i-heroicons-square-3-stack-3d-20-solid" /> <UIcon name="i-heroicons-square-3-stack-3d-20-solid"/>
<span>补充信息</span> <span>补充信息</span>
</div> </div>
<template v-for="(item, index) in data" :key="index"> <template v-for="(item, index) in data" :key="index">
<template v-if="item.ready"> <template v-if="item.ready">
<template v-if="item.type === 'search_relate_repo'"> <template v-if="item.type === 'search_relate_repo'">
<template v-if="item.data.length"> <template v-if="item.data.length">
<template v-for="(chart, cIndex) in item.data" :key="cIndex"> <template v-for="(chart, cIndex) in item.data" :key="cIndex">
<UCard :ui="cardUI"> <UCard :ui="cardUI">
<template v-if="chart.info"> <template v-if="chart.info">
<div class="flex mb-2"> <div class="flex mb-2">
<div class="flex items-center gap-1 text-sm overflow-hidden"> <div class="flex items-center gap-1 text-sm overflow-hidden">
<UIcon class="flex-shrink-0" name="i-simple-icons-github" /> <UIcon class="flex-shrink-0" name="i-simple-icons-github"/>
<ULink class="flex-grow truncate underline" :to="chart.info.url" target="_blank" :title="chart.info.description">{{ chart.info.name }}</ULink> <ULink class="flex-grow truncate underline" :to="chart.info.url" target="_blank"
<UIcon class="flex-shrink-0" name="i-heroicons-arrow-top-right-on-square" /> :title="chart.info.description">{{ chart.info.name }}
</div> </ULink>
</div> <UIcon class="flex-shrink-0" name="i-heroicons-arrow-top-right-on-square"/>
</template> </div>
<ProseChart </div>
type="line" </template>
:labels="chart.labels" <ProseChart
:data="chart.data" type="line"
:info="chart.info" :labels="chart.labels"
simple :data="chart.data"
/> :info="chart.info"
<div class="text-xs text-center text-gray-500 dark:text-gray-400 mt-2">{{ item.title }}</div> simple
</UCard> />
</template> <div class="text-xs text-center text-gray-500 dark:text-gray-400 mt-2">{{ item.title }}</div>
</template> </UCard>
<template v-else> </template>
<UCard :ui="cardUI"> </template>
<IEmpty size="xs"/> <template v-else>
</UCard> <UCard :ui="cardUI">
</template> <IEmpty size="xs"/>
</template> </UCard>
</template> </template>
<template v-else> </template>
<UCard :ui="cardUI"> </template>
<div class="flex flex-col gap-1"> <template v-else>
<USkeleton class="h-4" /> <UCard :ui="cardUI">
<USkeleton class="h-4 w-2/3" /> <div class="flex flex-col gap-1">
<USkeleton class="h-4" /> <USkeleton class="h-4"/>
<USkeleton class="h-4 w-2/3" /> <USkeleton class="h-4 w-2/3"/>
</div> <USkeleton class="h-4"/>
</UCard> <USkeleton class="h-4 w-2/3"/>
</template> </div>
</template> </UCard>
</div> </template>
</template>
</div>
</template> </template>
<script setup> <script setup>
defineProps({ defineProps({
......
<template> <template>
<header class="sticky top-0 z-10 bg-white dark:bg-black w-full flex flex-col"> <header class="sticky top-0 z-10 bg-white dark:bg-black w-full flex flex-col">
<div class="w-full p-2 justify-between flex"> <div class="w-full p-2 justify-between flex">
<IMenuSider /> <IMenuSider/>
<div class="hidden md:flex"> <div class="hidden md:flex">
<div v-if="repo" class="flex items-center gap-2"> <div v-if="repo" class="flex items-center gap-2">
<UIcon name="i-simple-icons-github" />{{ repo }} <UIcon name="i-simple-icons-github"/>
</div> {{ repo }}
</div> </div>
<div class="flex-grow justify-center items-center space-x-2 hidden sm:flex"> </div>
<UTooltip v-if="!isEditTitle" text="点击修改标题"> <div class="flex-grow justify-center items-center space-x-2 hidden sm:flex">
<div @click="handleFocusTitle">{{ editTitle }}</div> <UTooltip v-if="!isEditTitle" text="点击修改标题">
</UTooltip> <div @click="handleFocusTitle">{{ editTitle }}</div>
<UInput </UTooltip>
v-else <UInput
ref="titleRef" v-else
autofocus ref="titleRef"
:model-value="editTitle" autofocus
@blur="handleBlurTitle" :model-value="editTitle"
/> @blur="handleBlurTitle"
</div> />
<div class="flex gap-2"> </div>
<IActionThread <div class="flex gap-2">
:collection_id="$selectCollectionId.length ? $selectCollectionId[0] : ''" <IActionThread
:c_id="state.id" :collection_id="$selectCollectionId.length ? $selectCollectionId[0] : ''"
@delete="handleDeletedThread" :c_id="state.id"
/> @delete="handleDeletedThread"
<UButton />
color="gray" <UButton
variant="ghost" color="gray"
leading-icon="i-heroicons-plus-small" variant="ghost"
:label="$selectCollectionId.length ? '已收藏' : '收藏'" leading-icon="i-heroicons-plus-small"
@click="handleOpenSelect" :label="$selectCollectionId.length ? '已收藏' : '收藏'"
/> @click="handleOpenSelect"
<UPopover v-model:open="isShareOpen"> />
<UButton <UPopover v-model:open="isShareOpen">
:leading-icon="isOpen ? 'i-heroicons-share-16-solid' : 'i-heroicons-lock-closed-16-solid'" <UButton
label="分享" :leading-icon="isOpen ? 'i-heroicons-share-16-solid' : 'i-heroicons-lock-closed-16-solid'"
@click="handleSetOpenState" label="分享"
/> @click="handleSetOpenState"
<template #panel> />
<div class="flex flex-col p-3 gap-2 min-w-72"> <template #panel>
<div>访问权限</div> <div class="flex flex-col p-3 gap-2 min-w-72">
<div class="flex flex-col border dark:border-gray-800 rounded"> <div>访问权限</div>
<div <div class="flex flex-col border dark:border-gray-800 rounded">
class="flex flex-grow justify-between m-1 p-1 cursor-pointer rounded hover:bg-gray-100 dark:hover:bg-gray-800" <div
@click="handleUpdateOpenState(false)" class="flex flex-grow justify-between m-1 p-1 cursor-pointer rounded hover:bg-gray-100 dark:hover:bg-gray-800"
> @click="handleUpdateOpenState(false)"
<div class="flex-grow flex flex-col gap-1 text-sm"> >
<div class="flex items-center gap-1" :class="{ 'text-primary-500': !isOpen }"> <div class="flex-grow flex flex-col gap-1 text-sm">
<UIcon name="i-heroicons-lock-closed-16-solid" /> <div class="flex items-center gap-1" :class="{ 'text-primary-500': !isOpen }">
<span>私密</span> <UIcon name="i-heroicons-lock-closed-16-solid"/>
</div> <span>私密</span>
<div class="text-xs text-gray-500">只有作者可以查看</div> </div>
</div> <div class="text-xs text-gray-500">只有作者可以查看</div>
<div v-if="!isOpen"> </div>
<UIcon name="i-heroicons-check-circle-20-solid" class="text-primary-500 text-xl" /> <div v-if="!isOpen">
</div> <UIcon name="i-heroicons-check-circle-20-solid" class="text-primary-500 text-xl"/>
</div> </div>
<UDivider /> </div>
<div <UDivider/>
class="flex flex-grow justify-between m-1 p-1 cursor-pointer rounded hover:bg-gray-100 dark:hover:bg-gray-800" <div
@click="handleUpdateOpenState(true)" class="flex flex-grow justify-between m-1 p-1 cursor-pointer rounded hover:bg-gray-100 dark:hover:bg-gray-800"
> @click="handleUpdateOpenState(true)"
<div class="flex-grow flex flex-col gap-1 text-sm" :class="{ 'text-primary-500': isOpen }"> >
<div class="flex items-center gap-1"> <div class="flex-grow flex flex-col gap-1 text-sm" :class="{ 'text-primary-500': isOpen }">
<UIcon name="i-heroicons-share-20-solid" /> <div class="flex items-center gap-1">
<span>可分享的</span> <UIcon name="i-heroicons-share-20-solid"/>
</div> <span>可分享的</span>
<div class="text-xs text-gray-500">任何持有链接的人都可以查看</div> </div>
</div> <div class="text-xs text-gray-500">任何持有链接的人都可以查看</div>
<div v-if="isOpen"> </div>
<UIcon name="i-heroicons-check-circle-20-solid" class="text-primary-500 text-xl" /> <div v-if="isOpen">
</div> <UIcon name="i-heroicons-check-circle-20-solid" class="text-primary-500 text-xl"/>
</div> </div>
</div> </div>
<div v-if="isOpen" class="flex gap-1 items-center text-xs text-primary-500"> </div>
<UIcon name="i-heroicons-clipboard-document-check" /> <div v-if="isOpen" class="flex gap-1 items-center text-xs text-primary-500">
<span>链接已复制</span> <UIcon name="i-heroicons-clipboard-document-check"/>
</div> <span>链接已复制</span>
</div> </div>
</template> </div>
</UPopover> </template>
</div> </UPopover>
</div> </div>
<UDivider /> </div>
</header> <UDivider/>
</header>
</template> </template>
<script setup> <script setup>
const toast = useToast() const toast = useToast()
......
<template> <template>
<UCard :ui="{ body: { padding: 'p-4 sm:p-4' } }"> <UCard :ui="{ body: { padding: 'p-4 sm:p-4' } }">
<div class="flex justify-between items-center"> <div class="flex justify-between items-center">
<div class="flex items-center gap-2 text-lg"> <div class="flex items-center gap-2 text-lg">
<UIcon name="i-heroicons-sparkles-20-solid" /> <UIcon name="i-heroicons-sparkles-20-solid"/>
搜索过程 搜索过程
</div> </div>
<UButton <UButton
size="md" size="md"
color="gray" color="gray"
variant="ghost" variant="ghost"
:icon="openCollapse ? 'i-heroicons-chevron-up-20-solid' : 'i-heroicons-chevron-down-20-solid'" :icon="openCollapse ? 'i-heroicons-chevron-up-20-solid' : 'i-heroicons-chevron-down-20-solid'"
:ui="{ rounded: 'rounded-full' }" :ui="{ rounded: 'rounded-full' }"
@click="handleToggleCollapse" @click="handleToggleCollapse"
/> />
</div> </div>
<ICollapse :open="openCollapse" class="mt-2"> <ICollapse :open="openCollapse" class="mt-2">
<div v-auto-animate class="flex flex-col gap-2 w-full text-gray-500 dark:text-gray-400"> <div v-auto-animate class="flex flex-col gap-2 w-full text-gray-500 dark:text-gray-400">
<template v-if="status !== 'finish' && !actions.length"> <template v-if="status !== 'finish' && !actions.length">
<USkeleton class="h-4" /> <USkeleton class="h-4"/>
<USkeleton class="h-4 w-2/3" /> <USkeleton class="h-4 w-2/3"/>
</template> </template>
<template v-for="(action, index) in actions" :key="action.action"> <template v-for="(action, index) in actions" :key="action.action">
<ISearchProcessAction <ISearchProcessAction
:action="action" :action="action"
:last="actions.length === index + 1" :last="actions.length === index + 1"
:status="status" :status="status"
/> />
</template> </template>
</div> </div>
</ICollapse> </ICollapse>
</UCard> </UCard>
</template> </template>
<script setup> <script setup>
const props = defineProps({ const props = defineProps({
......
<template> <template>
<div class="text-base flex items-center gap-1"> <div class="text-base flex items-center gap-1">
<UIcon :name="item.icon" /> <UIcon :name="item.icon"/>
{{ item.name }} {{ item.name }}
</div> </div>
<template v-if="['rephrase_question', 'tool_select'].includes((action.action))"> <template v-if="['rephrase_question', 'tool_select'].includes((action.action))">
<div class="pl-5"> <div class="pl-5">
<IMdMdc :content="action.output" size="sm" /> <IMdMdc :content="action.output" size="sm"/>
</div> </div>
</template> </template>
<template v-else-if="['search_file', 'search_web'].includes(action.action)"> <template v-else-if="['search_file', 'search_web'].includes(action.action)">
<div class="text-xs pl-5">找到 {{ action.output.length }} 条来源</div> <div class="text-xs pl-5">找到 {{ action.output.length }} 条来源</div>
</template> </template>
<template v-if="last && status !== 'finish'"> <template v-if="last && status !== 'finish'">
<USkeleton class="h-4" /> <USkeleton class="h-4"/>
<USkeleton class="h-4 w-2/3" /> <USkeleton class="h-4 w-2/3"/>
</template> </template>
</template> </template>
<script setup> <script setup>
const props = defineProps({ const props = defineProps({
......
<template> <template>
<div class="text-xl flex items-center space-x-1"> <div class="text-xl flex items-center space-x-1">
<UIcon name="i-heroicons-rectangle-group-20-solid" /> <UIcon name="i-heroicons-rectangle-group-20-solid"/>
<span>相关问题</span> <span>相关问题</span>
</div> </div>
<div class="flex flex-col gap-2"> <div class="flex flex-col gap-2">
<UButton <UButton
v-for="(item, index) in recommendQuestions" v-for="(item, index) in recommendQuestions"
:key="index" :key="index"
color="gray" color="gray"
...@@ -12,12 +12,12 @@ ...@@ -12,12 +12,12 @@
variant="soft" variant="soft"
@click="handleClick(item.title)" @click="handleClick(item.title)"
> >
<div class="justify-between w-full flex items-center"> <div class="justify-between w-full flex items-center">
<div class="truncate">{{ item.title }}</div> <div class="truncate">{{ item.title }}</div>
<UIcon name="i-heroicons-plus-20-solid" class="text-base" /> <UIcon name="i-heroicons-plus-20-solid" class="text-base"/>
</div> </div>
</UButton> </UButton>
</div> </div>
</template> </template>
<script setup> <script setup>
defineProps({ defineProps({
......
<template> <template>
<ULink v-for="(item, index) in limitSource" :key="index" :to="item.url" :title="item.url" target="_blank"> <ULink v-for="(item, index) in limitSource" :key="index" :to="item.url" :title="item.url" target="_blank">
<UCard :ui="cardUI"> <UCard :ui="cardUI">
<div class="flex flex-col h-full gap-1"> <div class="flex flex-col h-full gap-1">
<template v-if="getIconPath(item.url) === 'github'"> <template v-if="getIconPath(item.url) === 'github'">
<div class="items-center flex gap-1"> <div class="items-center flex gap-1">
<UIcon name="i-simple-icons-github" class="flex-shrink-0" /> <UIcon name="i-simple-icons-github" class="flex-shrink-0"/>
<div class="flex flex-grow overflow-hidden"> <div class="flex flex-grow overflow-hidden">
<div class="truncate">{{ item.title }}</div> <div class="truncate">{{ item.title }}</div>
</div> </div>
<div class="text-gray-200">{{ index + 1 }}</div> <div class="text-gray-200">{{ index + 1 }}</div>
</div> </div>
<div class="text-blue-500 line-clamp-1">{{ item.label }}</div> <div class="text-blue-500 line-clamp-1">{{ item.label }}</div>
</template> </template>
<template v-else> <template v-else>
<div class="flex gap-1 h-full"> <div class="flex gap-1 h-full">
<div class="line-clamp-2 text-sm">{{ item.title }}</div> <div class="line-clamp-2 text-sm">{{ item.title }}</div>
</div> </div>
<div class="items-center flex gap-1"> <div class="items-center flex gap-1">
<UAvatar :src="getIconPath(item.url)" size="2xs" class="flex-shrink-0" /> <UAvatar :src="getIconPath(item.url)" size="2xs" class="flex-shrink-0"/>
<div class="flex flex-grow overflow-hidden"> <div class="flex flex-grow overflow-hidden">
<div class="truncate text-xs text-gray-500">{{ getDomain(item.url) }}</div> <div class="truncate text-xs text-gray-500">{{ getDomain(item.url) }}</div>
</div> </div>
<div class="text-gray-200 text-sm">{{ index + 1 }}</div> <div class="text-gray-200 text-sm">{{ index + 1 }}</div>
</div> </div>
</template> </template>
</div> </div>
</UCard> </UCard>
</ULink> </ULink>
<UCard v-if="source.length > 6" class="cursor-pointer" :ui="cardUI" @click="handleToggleShowAll"> <UCard v-if="source.length > 6" class="cursor-pointer" :ui="cardUI" @click="handleToggleShowAll">
<div class="flex items-center justify-center h-full gap-1"> <div class="flex items-center justify-center h-full gap-1">
<UIcon v-if="!showAllSource" name="i-heroicons-chevron-down-20-solid" /> <UIcon v-if="!showAllSource" name="i-heroicons-chevron-down-20-solid"/>
<UIcon v-else name="i-heroicons-chevron-up-20-solid" /> <UIcon v-else name="i-heroicons-chevron-up-20-solid"/>
<div v-if="!showAllSource">查看全部{{ source.length }}个来源</div> <div v-if="!showAllSource">查看全部{{ source.length }}个来源</div>
<div v-else>收起</div> <div v-else>收起</div>
</div> </div>
</UCard> </UCard>
</template> </template>
<script setup> <script setup>
const props = defineProps({ const props = defineProps({
......
<template> <template>
<component :is="titleTag" :id="id" :class="{ 'text-3xl': titleTag !== 'div' }">{{ title }}</component> <component :is="titleTag" :id="id" :class="{ 'text-3xl': titleTag !== 'div' }">{{ title }}</component>
</template> </template>
<script setup> <script setup>
const props = defineProps({ const props = defineProps({
......
<template> <template>
<div class="grid grid-cols-1"> <div class="grid grid-cols-1">
<article class="prose dark:prose-invert max-w-none" v-html="mdHtml"/> <article class="prose dark:prose-invert max-w-none" v-html="mdHtml"/>
</div> </div>
</template> </template>
<script setup> <script setup>
import MarkdownIt from 'markdown-it' import MarkdownIt from 'markdown-it'
......
<template> <template>
<div class="w-full relative" style="aspect-ratio: 2/1"> <div class="w-full relative" style="aspect-ratio: 2/1">
<canvas ref="refChart" :aria-label="title"/> <canvas ref="refChart" :aria-label="title"/>
</div> </div>
</template> </template>
<script setup> <script setup>
import { Chart } from 'chart.js/auto'; import { Chart } from 'chart.js/auto';
......
<template> <template>
<UTable <UTable
:rows="data" :rows="data"
:columns="columns" :columns="columns"
:ui="config" :ui="config"
:sort-button="sortButton" :sort-button="sortButton"
> >
<template #repo_name-data="{ row }"> <template #repo_name-data="{ row }">
<ULink :to="'https://github.com/' + row.repo_name" target="_blank">{{ row.repo_name }}</ULink> <ULink :to="'https://github.com/' + row.repo_name" target="_blank">{{ row.repo_name }}</ULink>
</template> </template>
<template #repo_url-data="{ row }"> <template #repo_url-data="{ row }">
<ULink :to="row.repo_url" target="_blank">{{ row.repo_url }}</ULink> <ULink :to="row.repo_url" target="_blank">{{ row.repo_url }}</ULink>
</template> </template>
</UTable> </UTable>
</template> </template>
<script setup> <script setup>
const props = defineProps({ const props = defineProps({
......
<template> <template>
<NuxtLink <NuxtLink
:href="href" :href="href"
:target="target" :target="target"
> >
<slot /> <slot/>
</NuxtLink> </NuxtLink>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
......
<template> <template>
<UCard :ui="cardUI"> <UCard :ui="cardUI">
<pre class="flex justify-between items-center m-0 p-1 pl-4 pr-1 rounded-none dark"> <pre class="flex justify-between items-center m-0 p-1 pl-4 pr-1 rounded-none dark">
<div>{{ language }}</div> <div>{{ language }}</div>
<UButton <UButton
leading-icon="i-heroicons-document-duplicate-20-solid" leading-icon="i-heroicons-document-duplicate-20-solid"
color="gray" color="gray"
variant="link" variant="link"
@click="handleCopy" @click="handleCopy"
/> />
</pre> </pre>
<UDivider :ui="{ border: { base: 'border-gray-700' } }" /> <UDivider :ui="{ border: { base: 'border-gray-700' } }"/>
<pre :class="$props.class" class="m-0 rounded-none"><code v-html="codeBlock"/></pre> <pre :class="$props.class" class="m-0 rounded-none"><code v-html="codeBlock"/></pre>
</UCard> </UCard>
</template> </template>
<script setup> <script setup>
......
...@@ -6,8 +6,8 @@ export default withNuxt({ ...@@ -6,8 +6,8 @@ export default withNuxt({
rules: { rules: {
'semi': [0], 'semi': [0],
'vue/html-indent': ['off'],
'indent': ['error', 2], 'indent': ['error', 2],
'vue/html-indent': ['off', 2, {}],
'no-empty': ['error', { 'allowEmptyCatch': true }], 'no-empty': ['error', { 'allowEmptyCatch': true }],
'vue/no-v-html': 'off', 'vue/no-v-html': 'off',
'no-useless-escape': 'error', 'no-useless-escape': 'error',
......
<template> <template>
<div class="flex min-h-screen"> <div class="flex min-h-screen">
<div class="fixed top-0 w-64 hidden md:flex flex-col h-screen"> <div class="fixed top-0 w-64 hidden md:flex flex-col h-screen">
<IAside /> <IAside/>
</div> </div>
<div class="w-full ml-0 md:ml-64 bg-white dark:bg-black flex flex-grow"> <div class="w-full ml-0 md:ml-64 bg-white dark:bg-black flex flex-grow">
<slot /> <slot/>
</div> </div>
</div> </div>
<ILibraryCreate /> <ILibraryCreate/>
<ILibrarySelect @success="handleCollectSuccess" /> <ILibrarySelect @success="handleCollectSuccess"/>
</template> </template>
<script setup> <script setup>
const selectCollectData = ref(null) const selectCollectData = ref(null)
......
<template> <template>
<slot /> <slot/>
</template> </template>
...@@ -5012,8 +5012,6 @@ ...@@ -5012,8 +5012,6 @@
}, },
"node_modules/@parcel/watcher-wasm/node_modules/napi-wasm": { "node_modules/@parcel/watcher-wasm/node_modules/napi-wasm": {
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmmirror.com/napi-wasm/-/napi-wasm-1.1.0.tgz",
"integrity": "sha512-lHwIAJbmLSjF9VDRm9GoVOy9AGp3aIvkjv+Kvz9h16QR3uSVYH78PNQUnT2U4X53mhlnV2M7wrhibQ3GHicDmg==",
"inBundle": true, "inBundle": true,
"license": "MIT" "license": "MIT"
}, },
...@@ -24105,8 +24103,6 @@ ...@@ -24105,8 +24103,6 @@
"dependencies": { "dependencies": {
"napi-wasm": { "napi-wasm": {
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmmirror.com/napi-wasm/-/napi-wasm-1.1.0.tgz",
"integrity": "sha512-lHwIAJbmLSjF9VDRm9GoVOy9AGp3aIvkjv+Kvz9h16QR3uSVYH78PNQUnT2U4X53mhlnV2M7wrhibQ3GHicDmg==",
"bundled": true "bundled": true
} }
} }
<template> <template>
<div class="flex flex-col items-center justify-center w-full h-full"> <div class="flex flex-col items-center justify-center w-full h-full">
<ILogo /> <ILogo/>
<div class="mt-2">开源搜索,直达结果</div> <div class="mt-2">开源搜索,直达结果</div>
<ICreate ref="refCreate" /> <ICreate ref="refCreate"/>
<div class="max-w-screen-md w-full p-6 grid grid-cols-1 lg:grid-cols-2 gap-4"> <div class="max-w-screen-md w-full p-6 grid grid-cols-1 lg:grid-cols-2 gap-4">
<template v-for="(item, index) in recommendQuestions" :key="index"> <template v-for="(item, index) in recommendQuestions" :key="index">
<UButton <UButton
class="flex justify-between" class="flex justify-between"
color="gray" color="gray"
variant="soft" variant="soft"
size="md" size="md"
:trailing-icon="item.c_id ? 'i-heroicons-chevron-right-20-solid' : 'i-heroicons-plus-20-solid'" :trailing-icon="item.c_id ? 'i-heroicons-chevron-right-20-solid' : 'i-heroicons-plus-20-solid'"
:label="item.title" :label="item.title"
:to="item.c_id ? `/search/${item.c_id}` : ''" :to="item.c_id ? `/search/${item.c_id}` : ''"
@click="handleSearch(item)" @click="handleSearch(item)"
/> />
</template> </template>
</div> </div>
</div> </div>
<IMenuSider fixed /> <IMenuSider fixed/>
</template> </template>
<script setup> <script setup>
const recommendQuestions = [ const recommendQuestions = [
......
<template> <template>
<div class="w-full items-center flex flex-col"> <div class="w-full items-center flex flex-col">
<ILibraryHeader <ILibraryHeader
v-if="currentCollect" v-if="currentCollect"
:collect="currentCollect.name" :collect="currentCollect.name"
:description="currentCollect.description" :description="currentCollect.description"
:count="currentCollect.record_count" :count="currentCollect.record_count"
:collect-id="currentCollect.id" :collect-id="currentCollect.id"
/> />
<div class="container max-w-screen-lg 2xl:max-w-screen-xl flex flex-col p-6"> <div class="container max-w-screen-lg 2xl:max-w-screen-xl flex flex-col p-6">
<div class="flex gap-10"> <div class="flex gap-10">
<div class="flex flex-col flex-grow"> <div class="flex flex-col flex-grow">
<div v-auto-animate class="flex flex-col gap-4"> <div v-auto-animate class="flex flex-col gap-4">
<ILibraryThread <ILibraryThread
v-for="item in themesTagList" v-for="item in themesTagList"
:key="item.id" :key="item.id"
:item="item" :item="item"
is-item is-item
@delete="handleDeletedThread" @delete="handleDeletedThread"
/> />
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</template> </template>
<script setup> <script setup>
const route = useRoute() const route = useRoute()
......
<template> <template>
<div class="w-full items-center flex flex-col"> <div class="w-full items-center flex flex-col">
<ILibraryHeader show-tabs :tab="tab" @change-tab="handleChangeTab" @search="handleSearch" @clear="getThreadData" /> <ILibraryHeader show-tabs :tab="tab" @change-tab="handleChangeTab" @search="handleSearch" @clear="getThreadData"/>
<div class="container max-w-screen-lg 2xl:max-w-screen-xl flex flex-col p-6 pt-0 lg:pt-6"> <div class="container max-w-screen-lg 2xl:max-w-screen-xl flex flex-col p-6 pt-0 lg:pt-6">
<div v-show="ready" class="flex gap-10"> <div v-show="ready" class="flex gap-10">
<div v-show="tab === 0 || tab === -1" class="flex flex-col flex-grow"> <div v-show="tab === 0 || tab === -1" class="flex flex-col flex-grow">
<div v-auto-animate class="flex flex-col gap-4"> <div v-auto-animate class="flex flex-col gap-4">
<ILibraryThread <ILibraryThread
v-for="item in threads" v-for="item in threads"
:key="item.c_id" :key="item.c_id"
:item="item" :item="item"
@delete="handleDeletedThread" @delete="handleDeletedThread"
/> />
<IEmpty v-if="!threads.length" /> <IEmpty v-if="!threads.length"/>
</div> </div>
</div> </div>
<div v-show="tab === 1 || tab === -1" class="flex flex-col flex-shrink-0 w-full lg:w-56"> <div v-show="tab === 1 || tab === -1" class="flex flex-col flex-shrink-0 w-full lg:w-56">
<div class="flex justify-between items-center"> <div class="flex justify-between items-center">
<div class="flex items-center text-lg gap-2"> <div class="flex items-center text-lg gap-2">
<UIcon name="i-heroicons-squares-2x2" /> <UIcon name="i-heroicons-squares-2x2"/>
<div>合集</div> <div>合集</div>
</div> </div>
<UButton <UButton
icon="i-heroicons-plus-20-solid" icon="i-heroicons-plus-20-solid"
variant="soft" variant="soft"
@click="handleOpenCreateLibrary" @click="handleOpenCreateLibrary"
/> />
</div> </div>
<div v-auto-animate class="flex flex-col gap-4 mt-4"> <div v-auto-animate class="flex flex-col gap-4 mt-4">
<ILibraryCollect <ILibraryCollect
v-for="item in $collection" v-for="item in $collection"
:key="item.id" :key="item.id"
:item="item" :item="item"
/> />
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</template> </template>
<script setup> <script setup>
import {LG} from '~/composables/useMQ.js'; import {LG} from '~/composables/useMQ.js';
......
<template> <template>
<div class="w-full p-6"> <div class="w-full p-6">
<IMdMdc :content="lineChart"/> <IMdMdc :content="lineChart"/>
<UDivider /> <UDivider/>
<IMdMdc :content="tableChart"/> <IMdMdc :content="tableChart"/>
</div> </div>
</template> </template>
<script setup> <script setup>
const lineChart = ` const lineChart = `
......
<template> <template>
<div class="w-full items-center flex flex-col"> <div class="w-full items-center flex flex-col">
<IException v-if="historyStatus !== 200" :code="historyStatus" /> <IException v-if="historyStatus !== 200" :code="historyStatus"/>
<template v-else> <template v-else>
<iSearchHeader <iSearchHeader
ref="refHeader" ref="refHeader"
:query="state.title" :query="state.title"
:is-public="state.isPublic" :is-public="state.isPublic"
:repo="state.repo" :repo="state.repo"
@update-query="handleUpdateQuery" @update-query="handleUpdateQuery"
/> />
<div ref="scrollElement" class="container min-h-svh max-w-screen-lg 2xl:max-w-screen-xl flex flex-col space-y-6 p-6 mb-6 pb-0"> <div ref="scrollElement"
<template v-for="(item, index) in data" :key="index"> class="container min-h-svh max-w-screen-lg 2xl:max-w-screen-xl flex flex-col space-y-6 p-6 mb-6 pb-0">
<ISearchArticle> <template v-for="(item, index) in data" :key="index">
<template #title> <ISearchArticle>
<ISearchTitle :id="index + 1" as="h2" :title="item.question" /> <template #title>
</template> <ISearchTitle :id="index + 1" as="h2" :title="item.question"/>
<ISearchContent </template>
:item="item" <ISearchContent
:asking="false" :item="item"
:is-last-index="false" :asking="false"
:index="index" :is-last-index="false"
:actions="item.actions" :index="index"
:collapse="false" :actions="item.actions"
process-status="finish" :collapse="false"
/> process-status="finish"
<template v-if="item.extra && item.extra.length > 0" #extra> />
<ISearchExtraInfo :data="item.extra" /> <template v-if="item.extra && item.extra.length > 0" #extra>
</template> <ISearchExtraInfo :data="item.extra"/>
</ISearchArticle> </template>
<UDivider v-if="data.length !== index + 1 || askingData.question" class="pt-3 pb-2" /> </ISearchArticle>
</template> <UDivider v-if="data.length !== index + 1 || askingData.question" class="pt-3 pb-2"/>
<template v-if="askingData.question"> </template>
<ISearchArticle> <template v-if="askingData.question">
<template #title> <ISearchArticle>
<ISearchTitle :id="data.length + 1" as="h2" :title="askingData.question" /> <template #title>
</template> <ISearchTitle :id="data.length + 1" as="h2" :title="askingData.question"/>
<ISearchContent </template>
:item="askingData" <ISearchContent
:asking="asking" :item="askingData"
:collapse="askingData.collapse" :asking="asking"
:is-last-index="true" :collapse="askingData.collapse"
:actions="askingData.actions" :is-last-index="true"
:process-status="askingData.processStatus" :actions="askingData.actions"
@regenerate="handleReGenerate" :process-status="askingData.processStatus"
/> @regenerate="handleReGenerate"
<template v-if="askingSidebarCards.length > 0" #extra> />
<ISearchExtraInfo :data="askingSidebarCards" /> <template v-if="askingSidebarCards.length > 0" #extra>
</template> <ISearchExtraInfo :data="askingSidebarCards"/>
</ISearchArticle> </template>
</template> </ISearchArticle>
<ISearchRecommendQuestion </template>
v-if="recommendQuestions.length > 0 && !asking" <ISearchRecommendQuestion
:recommend-questions="recommendQuestions" v-if="recommendQuestions.length > 0 && !asking"
@click="handleContinueAsk" :recommend-questions="recommendQuestions"
/> @click="handleContinueAsk"
</div> />
<div class="container max-w-screen-lg 2xl:max-w-screen-xl sticky bottom-4 flex pl-6 pr-6"> </div>
<ISearchAsk :asking="asking" @stop="handleStopGenerate" @ask="handleContinueAsk" /> <div class="container max-w-screen-lg 2xl:max-w-screen-xl sticky bottom-4 flex pl-6 pr-6">
</div> <ISearchAsk :asking="asking" @stop="handleStopGenerate" @ask="handleContinueAsk"/>
</template> </div>
</div> </template>
</div>
</template> </template>
<script setup> <script setup>
const route = useRoute() const route = useRoute()
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册