209 lines
6.4 KiB
Vue
209 lines
6.4 KiB
Vue
<template>
|
|
<div class="p-4">
|
|
<AdminFieldHelp :text="bannersPageIntro" root-class="mb-4 text-xs md:text-sm" />
|
|
|
|
<BaseButton size="small" type="primary" @click="addRow">
|
|
<span>افزودن بنر</span>
|
|
<BaseIcon icon="vuesax-linear:add" size="17" />
|
|
</BaseButton>
|
|
<AdminFieldHelp
|
|
text="هر بار «افزودن بنر» یک اسلاید جدید به انتهای لیست اضافه میکند."
|
|
root-class="mt-2"
|
|
/>
|
|
|
|
<div class="my-4 flex flex-col gap-2">
|
|
<div
|
|
class="grid max-h-52vh grid-cols-1 gap-4 overflow-y-scroll md:max-h-75vh md:grid-cols-3"
|
|
>
|
|
<Card v-for="(item, index) in benefitsList" :key="index">
|
|
<div class="mt-3 grid grid-cols-1 gap-4">
|
|
<div class="my-2 flex items-center justify-between gap-2">
|
|
<div class="flex flex-col gap-0.5">
|
|
<div class="text-sm font-medium">نسبت تصویر ۱۶:۹</div>
|
|
<AdminFieldHelp :text="bannersAspectHelp" />
|
|
</div>
|
|
<div class="flex shrink-0 flex-col items-end gap-0.5">
|
|
<div class="flex items-center gap-2">
|
|
<span>نمایش:</span>
|
|
<a-switch v-model:checked="item.show" />
|
|
</div>
|
|
<AdminFieldHelp :text="bannersShowHelp" root-class="text-left" />
|
|
</div>
|
|
</div>
|
|
|
|
<div class="text-center">
|
|
<AdminFieldHelp :text="bannersImageHelp" root-class="mb-2 text-center" />
|
|
<UploadPic
|
|
:compressed="true"
|
|
@upload="handleUpload($event, index, 'icon')"
|
|
@remove="handelRemoveFile(index, 'icon')"
|
|
:imageUrl="item.icon"
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="mt-3 flex flex-col gap-1">
|
|
<div class="text-sm font-medium">انتخاب رویداد (پس از کلیک):</div>
|
|
<AdminFieldHelp :text="bannersEventHelp" />
|
|
<BasicSelect
|
|
v-model:value="item.typeClick"
|
|
:items="typeList"
|
|
value-name="lable"
|
|
key-name="value"
|
|
/>
|
|
<AdminFieldHelp v-if="item.typeClick === 'link'" :text="bannersLinkHelp" />
|
|
<AdminFieldHelp v-else-if="item.typeClick === 'modal'" :text="bannersModalHelp" />
|
|
<AdminFieldHelp v-else-if="item.typeClick === 'share'" :text="bannersShareHelp" />
|
|
<AdminFieldHelp v-else :text="bannersNoEventHelp" />
|
|
</div>
|
|
|
|
<div v-if="item.typeClick == 'link'" class="mt-2 flex flex-col gap-1">
|
|
<div class="text-sm font-medium">آدرس لینک</div>
|
|
<BasicInput v-model:value="item.link" placeholder="https://..." />
|
|
</div>
|
|
|
|
<div v-if="item.typeClick == 'modal'" class="mt-2 flex flex-col gap-1">
|
|
<div class="text-sm font-medium">متن پیام</div>
|
|
<QuillEditor
|
|
placeholder="متن پیام"
|
|
v-model:content="item.modalText"
|
|
toolbar="full"
|
|
theme="snow"
|
|
content-type="html"
|
|
class="editor-box2"
|
|
/>
|
|
</div>
|
|
</Card>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="mt-5 text-left md:mt-0">
|
|
<BaseButton type="primary" @click="handleSubmit">
|
|
<span>ذخیره تغییرات</span>
|
|
</BaseButton>
|
|
<AdminFieldHelp
|
|
text="بدون زدن این دکمه، هیچکدام از تغییرات بالا در اپ مشتری دیده نمیشود."
|
|
root-class="mt-2"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { Card, message } from 'ant-design-vue'
|
|
import type { IBenefits } from '@/model/banner'
|
|
import UploadPic from '@/components/UploadPic.vue'
|
|
import AdminFieldHelp from '@/components/AdminFieldHelp.vue'
|
|
import { updateBannerConst, getHeaderBannerConst } from '@/api/consts'
|
|
import {
|
|
bannersAspectHelp,
|
|
bannersEventHelp,
|
|
bannersImageHelp,
|
|
bannersLinkHelp,
|
|
bannersModalHelp,
|
|
bannersNoEventHelp,
|
|
bannersPageIntro,
|
|
bannersShareHelp,
|
|
bannersShowHelp,
|
|
} from '@/utils/adminHelpCopy'
|
|
import '@vueup/vue-quill/dist/vue-quill.snow.css'
|
|
import { QuillEditor } from '@vueup/vue-quill'
|
|
import { normalizeUploadFileResponse } from '@/utils/file'
|
|
|
|
const benefitsList = ref<IBenefits[]>([])
|
|
let id: number | null = null
|
|
const typeList = ref([
|
|
{ lable: 'باز شدن لینک', value: 'link' },
|
|
{ lable: 'پنجره بازشو', value: 'modal' },
|
|
{ lable: 'اشتراک گذاری', value: 'share' },
|
|
{ lable: 'بدون رویداد', value: null },
|
|
])
|
|
|
|
function parseBannerList(value: string | null | undefined): IBenefits[] {
|
|
if (!value) return []
|
|
try {
|
|
const parsed = JSON.parse(value)
|
|
return Array.isArray(parsed) ? parsed : []
|
|
} catch {
|
|
return []
|
|
}
|
|
}
|
|
|
|
function addRow() {
|
|
if (!Array.isArray(benefitsList.value)) {
|
|
benefitsList.value = []
|
|
}
|
|
benefitsList.value.push({
|
|
icon: null,
|
|
show: true,
|
|
caption: null,
|
|
link: null,
|
|
typeClick: null,
|
|
modalText: null,
|
|
})
|
|
}
|
|
|
|
function handleUpload(response: unknown, index: number, field: keyof IBenefits) {
|
|
const fileResource = normalizeUploadFileResponse(response)
|
|
|
|
if (!fileResource?.full_src) {
|
|
message.error('خطا در ساخت آدرس تصویر')
|
|
return
|
|
}
|
|
|
|
benefitsList.value[index][field] = fileResource.full_src
|
|
}
|
|
|
|
function handelRemoveFile(index: number, field: keyof IBenefits) {
|
|
benefitsList.value[index][field] = null
|
|
}
|
|
|
|
async function handleSubmit() {
|
|
if (!id) {
|
|
message.error('شناسه بنر یافت نشد؛ صفحه را رفرش کنید')
|
|
return
|
|
}
|
|
|
|
try {
|
|
await updateBannerConst({
|
|
id,
|
|
value: JSON.stringify(benefitsList.value),
|
|
key: 'header_banner',
|
|
})
|
|
message.success('اطلاعات با موفقیت ذخیره شد')
|
|
} catch (error) {
|
|
message.error('خطا در ذخیره اطلاعات')
|
|
}
|
|
}
|
|
|
|
onMounted(async () => {
|
|
try {
|
|
const res = await getHeaderBannerConst()
|
|
if (!res) {
|
|
return
|
|
}
|
|
|
|
id = res.id ?? res.const_id ?? null
|
|
benefitsList.value = parseBannerList(res.value)
|
|
} catch (error) {
|
|
console.error('خطا در دریافت بنرها:', error)
|
|
}
|
|
})
|
|
</script>
|
|
|
|
<style lang="less">
|
|
.editor-box2 {
|
|
max-height: 40vh;
|
|
overflow-y: auto;
|
|
border: 1px solid #ddd;
|
|
border-radius: 8px;
|
|
padding: 10px;
|
|
}
|
|
|
|
.editor-box2 .ql-editor {
|
|
min-height: 10vh;
|
|
overflow-y: auto;
|
|
box-sizing: border-box;
|
|
}
|
|
</style>
|