aigc-h5/src/views/chat/components/template-modal.vue

335 lines
7.6 KiB
Vue

<template>
<van-popup
v-bind="getBindValue"
centered
:title="null"
:footer="null"
:style="{ background: '#16171890' }"
wrapClassName="template-modal"
>
<div
class="text-white py-48px w-680px border border-[#5E6369] rounded-6px relative"
>
<div class="absolute right-30px top-30px">
<SvgIcon
@click="handleClose"
class="text-white text-50px cursor-pointer text-30px"
name="qx"
></SvgIcon>
</div>
<div class="flex items-center justify-center">
<img
class="w-31px"
src="@/assets/images/tip-icon-blue.png"
alt=""
srcset=""
/>
<div class="text-27px">海兔AIGC提示模板大全</div>
</div>
<div class="mt-30px text-22px opacity-40 text-center">
Haitu AIGC Writing Inspiration Complete Works
</div>
<div class="my-20px flex items-center justify-center">
<van-popover v-model:show="popovershow" class="cu-popover" overlay>
<div class="w-600px">
<van-cascader
@finish="onFinish"
v-model="value"
title=""
@close="popovershow = false"
:options="options"
/>
</div>
<template #reference>
<van-field
readonly
:border="false"
class="h-72px cu-field-se !w-600px"
v-model="fieldValue"
placeholder="请选择"
></van-field>
</template>
</van-popover>
</div>
<div class="flex items-center justify-center w-full my-20px">
<van-field
class="h-72px cu-field-se !w-600px"
v-model="filterValue"
right-icon="search"
autocomplete="off"
placeholder="搜索模版"
@click-right-icon="onFilter"
/>
</div>
<div
v-if="templates.length"
class="overflow-x-scroll flex px-34px"
ref="scrollbarRef"
>
<TemplateCard
class="mr-25px"
v-for="(item, i) in templates"
:key="i"
:data="item"
></TemplateCard>
</div>
<div v-else class="h-100px flex items-center justify-center">
<div class="text-22px">暂无搜索结果</div>
</div>
<div class="flex justify-center mt-20px">
<SvgIcon
:class="{ 'opacity-40': pageNum <= 1 }"
@click="handleP"
class="text-white text-50px cursor-pointer mx-60px"
name="right-arrow"
></SvgIcon>
<SvgIcon
:class="{ 'opacity-40': !isMore }"
@click="handleN"
class="text-white text-50px cursor-pointer transform rotate-180 mx-60px"
name="right-arrow"
></SvgIcon>
</div>
</div>
</van-popup>
</template>
<script>
import { ref, computed, unref, defineComponent, onMounted, nextTick } from 'vue'
import ScrollContainer from '@/components/ScrollContainer/index.vue'
import TemplateCard from './template-card.vue'
import http from '@/io/request'
export default defineComponent({
components: {
ScrollContainer,
TemplateCard,
},
setup(props, { attrs, emit }) {
const pageNum = ref(1)
const scrollbarRef = ref(null)
const filterValue = ref('')
const templates = ref([])
const popovershow = ref(false)
const options = ref([])
const value = ref('')
const fieldValue = ref('')
const isMore = ref(true)
const modelOpen = ref(false)
const getBindValue = computed(() => {
const attr = {
...attrs,
...unref(props),
open: unref(modelOpen),
maskClosable: false,
dialogClass: 'ttata',
}
return attr
})
const handleClose = () => {
emit('update:show', false)
}
const getCategories = () => {
http.get('/api/prompt-categories').then((res) => {
changeId2(res, 'id', 'value')
changeId2(res, 'title', 'text')
options.value = res
})
}
const onFinish = ({ selectedOptions }) => {
fieldValue.value = selectedOptions.map((option) => option.text).join('/')
popovershow.value = false
console.log(value.value)
changeCategories()
}
function changeId2(objAry, key, newkey) {
if (objAry != null) {
objAry.forEach((item) => {
Object.assign(item, {
[newkey]: item[key],
})
delete item[key]
changeId2(item.children, key, newkey)
})
}
}
function onFilter() {
pageNum.value = 1
getTemplates()
}
const getTemplates = () => {
http
.get('/api/prompt-templates', {
params: {
search: filterValue.value,
per_page: 10,
page: pageNum.value,
category_id: value.value,
},
})
.then((res) => {
templates.value = res.data
isMore.value = true
scrollbarRef.value.scrollLeft = 0
if (templates.value.length >= res.total) {
isMore.value = false
}
})
.catch((e) => {})
}
const changeCategories = async (e) => {
pageNum.value = 1
getTemplates()
await nextTick()
}
const handleP = () => {
if (pageNum.value == 1) return
pageNum.value--
getTemplates()
}
const handleN = () => {
if (!isMore.value) return
pageNum.value++
getTemplates()
}
const loadMore = () => {
getTemplates()
}
onMounted(() => {
getCategories()
getTemplates()
})
return {
popovershow,
value,
options,
getBindValue,
templates,
scrollbarRef,
handleN,
handleP,
isMore,
pageNum,
handleClose,
changeCategories,
fieldValue,
onFinish,
filterValue,
onFilter,
}
},
})
</script>
<style lang="scss">
.cu-cascader {
.ant-select-selector {
background-color: #414548 !important;
color: white !important;
}
.ant-select-selection-placeholder {
color: rgb(139, 138, 138) !important;
opacity: 20 !important;
}
.ant-select-clear {
background: transparent;
}
.ant-select-arrow {
color: white;
}
.ant-select-selector {
border: none !important;
}
}
.template-modal {
.ant-modal {
&-content {
background: #161718;
}
&-close {
color: #fff;
&:hover {
color: #afadad;
}
}
}
}
</style>
<style lang="scss">
.cu-cascader-popup {
background-color: #27292b;
.ant-cascader-dropdown
.ant-cascader-menu-item-active:not(.ant-cascader-menu-item-disabled),
.ant-cascader-dropdown
.ant-cascader-menu-item-active:not(.ant-cascader-menu-item-disabled):hover {
background-color: #242627;
}
.ant-cascader-menu-item,
.ant-cascader-menu-item-expand-icon {
color: white !important;
}
.ant-cascader-menu-item:hover {
background-color: #414548 !important;
}
.ant-cascader-menu-item-active {
background-color: #414548 !important;
}
.ant-select-dropdown {
color: white;
}
}
.cu-field-se {
padding: 0 20px;
display: flex;
align-items: center;
background-color: #414548;
input {
color: white !important;
}
}
.cu-popover {
.van-popover__arrow {
color: #27292b !important;
}
.van-cascader__options {
height: 500px;
}
.van-popover__content {
background: #27292b;
}
.van-tabs__nav {
background: #27292b;
}
.van-cascader__option {
color: white;
&:active {
background-color: transparent;
}
}
.van-cascader__tab {
color: white;
}
}
</style>