fix some bugs 4
This commit is contained in:
@@ -0,0 +1,145 @@
|
||||
<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>
|
||||
@@ -28,6 +28,7 @@
|
||||
@chargeWallet="forwardAndClose('chargeWallet', $event)"
|
||||
@toggleTrade="forward('toggleTrade', $event)"
|
||||
@confirmUser="forwardAndClose('confirmUser', $event)"
|
||||
@sendSms="forwardAndClose('sendSms', $event)"
|
||||
/>
|
||||
</template>
|
||||
|
||||
@@ -57,6 +58,7 @@ const emit = defineEmits<{
|
||||
(e: 'chargeWallet', item: Customer): void
|
||||
(e: 'toggleTrade', item: Customer): void
|
||||
(e: 'confirmUser', item: Customer): void
|
||||
(e: 'sendSms', item: Customer): void
|
||||
}>()
|
||||
|
||||
const { sheetVisible, selectedItem, openSheet, syncSelectedItem } = useMobileDetailSheet<Customer>()
|
||||
@@ -69,6 +71,7 @@ type SheetAction =
|
||||
| 'chargeWallet'
|
||||
| 'toggleTrade'
|
||||
| 'confirmUser'
|
||||
| 'sendSms'
|
||||
|
||||
function forward(action: SheetAction, item: Customer) {
|
||||
emit(action, item)
|
||||
|
||||
@@ -46,6 +46,15 @@
|
||||
<BaseButton size="small" type="default" icon="vuesax-linear:archive-tick" @click="closeAndEmit('archive', row)">
|
||||
بایگانی
|
||||
</BaseButton>
|
||||
<BaseButton
|
||||
v-if="customerDirectSmsEnabled"
|
||||
size="small"
|
||||
type="default"
|
||||
icon="vuesax-linear:sms"
|
||||
@click="closeAndEmit('sendSms', row)"
|
||||
>
|
||||
پیامک
|
||||
</BaseButton>
|
||||
<BaseButton
|
||||
v-if="!row.is_legal"
|
||||
size="small"
|
||||
@@ -96,6 +105,7 @@ import MobileDetailSheet from '@/components/mobile/MobileDetailSheet.vue'
|
||||
import MobileInfoGrid from '@/components/mobile/MobileInfoGrid.vue'
|
||||
import CustomerWalletBalancePanel from '@/components/customer/CustomerWalletBalancePanel.vue'
|
||||
import { toJalali } from '@core/utils/useDataTime'
|
||||
import { customerDirectSmsEnabledSetting } from '@/utils/config'
|
||||
|
||||
const props = defineProps<{
|
||||
visible: boolean
|
||||
@@ -111,9 +121,11 @@ const emit = defineEmits<{
|
||||
(e: 'chargeWallet', item: Customer): void
|
||||
(e: 'toggleTrade', item: Customer): void
|
||||
(e: 'confirmUser', item: Customer): void
|
||||
(e: 'sendSms', item: Customer): void
|
||||
}>()
|
||||
|
||||
const chargeTargets = ref<ChargeTarget[]>([])
|
||||
const customerDirectSmsEnabled = customerDirectSmsEnabledSetting
|
||||
|
||||
const visibleProxy = computed({
|
||||
get: () => props.visible,
|
||||
@@ -122,7 +134,7 @@ const visibleProxy = computed({
|
||||
|
||||
const sheetTitle = computed(() => props.item?.name?.trim() || 'مشتری')
|
||||
|
||||
type SheetEmit = 'archive' | 'chargeWallet' | 'info' | 'confirmUser' | 'edit'
|
||||
type SheetEmit = 'archive' | 'chargeWallet' | 'info' | 'confirmUser' | 'edit' | 'sendSms'
|
||||
|
||||
function closeAndEmit(event: SheetEmit, row: Customer) {
|
||||
visibleProxy.value = false
|
||||
|
||||
@@ -93,6 +93,15 @@
|
||||
:color="record.trade_active === 1 ? '#54AD06' : '#ad0627'"
|
||||
/>
|
||||
</a-tooltip>
|
||||
<a-tooltip
|
||||
v-if="customerDirectSmsEnabled"
|
||||
placement="bottom"
|
||||
class="cursor-pointer"
|
||||
@click="openDirectSms(record)"
|
||||
>
|
||||
<template #title><span>ارسال پیامک</span></template>
|
||||
<Icon icon="vuesax-linear:sms" color="#0ea5e9" />
|
||||
</a-tooltip>
|
||||
<a-tooltip
|
||||
v-if="!record.is_legal"
|
||||
placement="bottom"
|
||||
@@ -117,9 +126,12 @@
|
||||
@chargeWallet="emits('chargeWallet', $event)"
|
||||
@toggleTrade="(item) => changeCustomerOrderActivationFunction(item.id)"
|
||||
@confirmUser="openConfirmUser"
|
||||
@sendSms="openDirectSms"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<CustomerDirectSmsModal v-model:visible="directSmsVisible" :customer="directSmsCustomer" />
|
||||
|
||||
<BasicModal
|
||||
v-model:visible="confirmVisible"
|
||||
:width="isMobile ? '92vw' : '50vw'"
|
||||
@@ -176,6 +188,7 @@ import {
|
||||
} from '@/api/customer'
|
||||
import { buildCustomerColumns } from '@/pages/menuPages/customers/base/hooks/customerColumns'
|
||||
import CustomerMobileCardList from '@/pages/menuPages/customers/base/components/CustomerMobileCardList.vue'
|
||||
import CustomerDirectSmsModal from '@/pages/menuPages/customers/base/components/CustomerDirectSmsModal.vue'
|
||||
import Icon from '@core/components/BaseIcon/src/Icon.vue'
|
||||
import useBaseTable from '@core/components/BaseTable/hooks/useBaseTable'
|
||||
import type { TableInput } from '@core/type/baseTable'
|
||||
@@ -185,7 +198,13 @@ import { MODAL_ABOVE_ACTION_SHEET_Z_INDEX } from '@/constants/overlayZIndex'
|
||||
import { isMobile } from '@core/utils/is'
|
||||
import TahesabRetryModal from '@/components/TahesabRetryModal.vue'
|
||||
import PargarRetryModal from '@/components/PargarRetryModal.vue'
|
||||
import { tahesabEnabledSetting, pargarEnabledSetting, initAccountingSettingsFromApi } from '@/utils/config'
|
||||
import {
|
||||
tahesabEnabledSetting,
|
||||
pargarEnabledSetting,
|
||||
customerDirectSmsEnabledSetting,
|
||||
initAccountingSettingsFromApi,
|
||||
initWalletSettingsFromApi
|
||||
} from '@/utils/config'
|
||||
|
||||
const [submit, reload] = useBaseTable()
|
||||
const emits = defineEmits(['delete', 'edit', 'add', 'info', 'chargeWallet'])
|
||||
@@ -199,6 +218,9 @@ const tahesabEnabled = tahesabEnabledSetting
|
||||
const pargarRegisterVisible = ref(false)
|
||||
const pargarCustomer = ref<Customer>()
|
||||
const pargarEnabled = pargarEnabledSetting
|
||||
const customerDirectSmsEnabled = customerDirectSmsEnabledSetting
|
||||
const directSmsVisible = ref(false)
|
||||
const directSmsCustomer = ref<Customer | null>(null)
|
||||
const mobileListRef = ref<null | { fetch: () => Promise<void> }>(null)
|
||||
|
||||
const tblProps = ref<any>({
|
||||
@@ -219,8 +241,14 @@ defineExpose({ fetch })
|
||||
|
||||
onMounted(() => {
|
||||
void initAccountingSettingsFromApi()
|
||||
void initWalletSettingsFromApi()
|
||||
})
|
||||
|
||||
function openDirectSms(user: Customer) {
|
||||
directSmsCustomer.value = user
|
||||
directSmsVisible.value = true
|
||||
}
|
||||
|
||||
async function changeCustomerActivationFunction(id: number) {
|
||||
try {
|
||||
loading.value = true
|
||||
|
||||
Reference in New Issue
Block a user