146 lines
3.9 KiB
Vue
146 lines
3.9 KiB
Vue
<template>
|
||||
|
|
<BasicModal
|
|||
|
|
v-model:visible="visibleProxy"
|
|||
|
|
:width="isMobile ? '94vw' : '36rem'"
|
|||
|
|
:title="modalTitle"
|
|||
|
|
ok-text="ارسال پیامک"
|
|||
|
|
:loading="loading"
|
|||
|
|
:ok-button-props="{ disabled: !canSubmit }"
|
|||
|
|
@ok="submit"
|
|||
|
|
@close="close"
|
|||
|
|
>
|
|||
|
|
<div class="customer-sms-modal flex flex-col gap-3">
|
|||
|
|
<p class="m-0 text-xs" style="color: var(--admin-text-secondary)">
|
|||
|
|
گیرنده:
|
|||
|
|
<strong dir="ltr" class="text-primary">{{ customer?.mobile || '—' }}</strong>
|
|||
|
|
</p>
|
|||
|
|
|
|||
|
|
<div class="flex flex-wrap gap-2">
|
|||
|
|
<a-button
|
|||
|
|
v-for="snippet in snippets"
|
|||
|
|
:key="snippet.key"
|
|||
|
|
size="small"
|
|||
|
|
@click="appendSnippet(snippet.insert)"
|
|||
|
|
>
|
|||
|
|
{{ snippet.label }}
|
|||
|
|
</a-button>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<a-textarea
|
|||
|
|
v-model:value="message"
|
|||
|
|
:rows="6"
|
|||
|
|
:maxlength="700"
|
|||
|
|
show-count
|
|||
|
|
placeholder="متن پیامک را بنویسید…"
|
|||
|
|
class="customer-sms-modal__textarea"
|
|||
|
|
/>
|
|||
|
|
|
|||
|
|
<p v-if="profanityHit" class="m-0 text-xs text-red-500">
|
|||
|
|
متن حاوی عبارت نامناسب است — قبل از ارسال اصلاح کنید.
|
|||
|
|
</p>
|
|||
|
|
<p class="m-0 text-xs" style="color: var(--admin-text-secondary)">
|
|||
|
|
متغیرها در سرور جایگزین میشوند: %نام% · %نام_اپ% · %لینک_اپ%
|
|||
|
|
</p>
|
|||
|
|
</div>
|
|||
|
|
</BasicModal>
|
|||
|
|
</template>
|
|||
|
|
|
|||
|
|
<script setup lang="ts">
|
|||
|
|
import { computed, ref, watch } from 'vue'
|
|||
|
|
import { message as antMessage } from 'ant-design-vue'
|
|||
|
|
import type { Customer } from '@/model/customer'
|
|||
|
|
import { isMobile } from '@core/utils/is'
|
|||
|
|
import BasicModal from '@/components/BasicModal.vue'
|
|||
|
|
import {
|
|||
|
|
buildDirectSmsSnippets,
|
|||
|
|
findProfanity,
|
|||
|
|
sendCustomerDirectSms
|
|||
|
|
} from '@/api/customerDirectSms'
|
|||
|
|
import { getConfiguration } from '@/api/configuration'
|
|||
|
|
|
|||
|
|
const props = defineProps<{
|
|||
|
|
visible: boolean
|
|||
|
|
customer: Customer | null
|
|||
|
|
}>()
|
|||
|
|
|
|||
|
|
const emit = defineEmits<{
|
|||
|
|
(e: 'update:visible', value: boolean): void
|
|||
|
|
(e: 'sent'): void
|
|||
|
|
}>()
|
|||
|
|
|
|||
|
|
const visibleProxy = computed({
|
|||
|
|
get: () => props.visible,
|
|||
|
|
set: (v: boolean) => emit('update:visible', v)
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
const loading = ref(false)
|
|||
|
|
const message = ref('')
|
|||
|
|
const appName = ref('')
|
|||
|
|
const appUrl = ref('')
|
|||
|
|
|
|||
|
|
const modalTitle = computed(() =>
|
|||
|
|
props.customer?.name ? `پیامک به ${props.customer.name}` : 'ارسال پیامک به مشتری'
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
const snippets = computed(() =>
|
|||
|
|
buildDirectSmsSnippets(props.customer, appName.value, appUrl.value)
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
const profanityHit = computed(() => findProfanity(message.value))
|
|||
|
|
|
|||
|
|
const canSubmit = computed(
|
|||
|
|
() => message.value.trim().length > 0 && !profanityHit.value && !loading.value
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
watch(
|
|||
|
|
() => props.visible,
|
|||
|
|
async (open) => {
|
|||
|
|
if (!open) return
|
|||
|
|
message.value = ''
|
|||
|
|
try {
|
|||
|
|
const rows = await getConfiguration()
|
|||
|
|
const list = Array.isArray(rows) ? rows : []
|
|||
|
|
appName.value = String(list.find((r) => r.key === 'name_fa')?.value ?? '').trim()
|
|||
|
|
appUrl.value = String(list.find((r) => r.key === 'app_url')?.value ?? '').trim()
|
|||
|
|
} catch {
|
|||
|
|
appName.value = ''
|
|||
|
|
appUrl.value = ''
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
function appendSnippet(text: string) {
|
|||
|
|
if (!text) return
|
|||
|
|
const current = message.value
|
|||
|
|
const needsSpace = current.length > 0 && !/\s$/.test(current)
|
|||
|
|
message.value = current + (needsSpace ? ' ' : '') + text
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function close() {
|
|||
|
|
visibleProxy.value = false
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async function submit() {
|
|||
|
|
if (!props.customer?.id || !canSubmit.value) return
|
|||
|
|
const hit = findProfanity(message.value)
|
|||
|
|
if (hit) {
|
|||
|
|
antMessage.error('متن حاوی محتوای نامناسب است')
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
try {
|
|||
|
|
loading.value = true
|
|||
|
|
await sendCustomerDirectSms({
|
|||
|
|
customer_id: Number(props.customer.id),
|
|||
|
|
message: message.value.trim()
|
|||
|
|
})
|
|||
|
|
antMessage.success('پیامک ارسال شد')
|
|||
|
|
emit('sent')
|
|||
|
|
close()
|
|||
|
|
} catch (e) {
|
|||
|
|
console.error(e)
|
|||
|
|
} finally {
|
|||
|
|
loading.value = false
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
</script>
|