fix(settings): fix variable slot dropdown and saving multi-variables
This commit is contained in:
@@ -14,7 +14,7 @@
|
|||||||
<div class="flex-grow-1">
|
<div class="flex-grow-1">
|
||||||
<h2 class="text-lg font-bold text-color m-0 mb-1">قالبهای پیامک</h2>
|
<h2 class="text-lg font-bold text-color m-0 mb-1">قالبهای پیامک</h2>
|
||||||
<p class="text-sm text-muted m-0 line-height-3">
|
<p class="text-sm text-muted m-0 line-height-3">
|
||||||
شناسه قالب و تعداد و نام متغیرهای sms.ir را بر اساس قالب تعریف شده در پنل پیامک تنظیم کنید. میتوانید هر تعداد متغیر که میخواهید تعریف یا حذف نمایید.
|
شناسه قالب و تعداد و نام متغیرهای sms.ir را بر اساس قالب پنل پیامک تنظیم کنید. میتوانید هر تعداد متغیر که میخواهید تعریف یا حذف نمایید.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -77,7 +77,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
v-if="!templateForm[template.key].variables || templateForm[template.key].variables.length === 0"
|
v-if="!templateForm[template.key]?.variables || templateForm[template.key]?.variables.length === 0"
|
||||||
class="p-3 text-center border-1 border-dashed border-round surface-card text-muted text-xs line-height-3"
|
class="p-3 text-center border-1 border-dashed border-round surface-card text-muted text-xs line-height-3"
|
||||||
>
|
>
|
||||||
هیچ متغیری برای این قالب تعریف نشده است. پیامک بدون متغیر ارسال خواهد شد.
|
هیچ متغیری برای این قالب تعریف نشده است. پیامک بدون متغیر ارسال خواهد شد.
|
||||||
@@ -87,13 +87,13 @@
|
|||||||
<div
|
<div
|
||||||
v-for="(variable, vIdx) in templateForm[template.key].variables"
|
v-for="(variable, vIdx) in templateForm[template.key].variables"
|
||||||
:key="variable.id || vIdx"
|
:key="variable.id || vIdx"
|
||||||
class="flex flex-column sm:flex-row sm:align-items-center gap-2 p-2 border-round surface-card border-1 border-color"
|
class="flex flex-column md:flex-row md:align-items-center gap-3 p-3 border-round surface-card border-1 border-color"
|
||||||
>
|
>
|
||||||
<div class="flex align-items-center gap-2 sm:w-14rem flex-shrink-0">
|
<div class="flex flex-column gap-1 md:w-16rem flex-shrink-0">
|
||||||
<span class="text-xs text-muted font-bold ml-1">{{ vIdx + 1 }}.</span>
|
<span class="text-xs text-muted font-semibold">مقدار ارسالی از سیستم:</span>
|
||||||
<Select
|
<Select
|
||||||
v-model="variable.slot"
|
v-model="variable.slot"
|
||||||
:options="template.availableSlots || []"
|
:options="getAvailableSlots(template.key)"
|
||||||
optionLabel="label"
|
optionLabel="label"
|
||||||
optionValue="slot"
|
optionValue="slot"
|
||||||
placeholder="انتخاب مقدار داده"
|
placeholder="انتخاب مقدار داده"
|
||||||
@@ -102,16 +102,18 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex-grow-1 flex align-items-center gap-2">
|
<div class="flex-grow-1 flex flex-column gap-1">
|
||||||
|
<span class="text-xs text-muted font-semibold">نام متغیر در sms.ir:</span>
|
||||||
|
<div class="flex align-items-center gap-2">
|
||||||
<InputText
|
<InputText
|
||||||
v-model.trim="variable.name"
|
v-model.trim="variable.name"
|
||||||
class="w-full text-sm"
|
class="w-full text-sm"
|
||||||
dir="ltr"
|
dir="ltr"
|
||||||
:placeholder="getSlotDefaultName(template, variable.slot) || 'نام متغیر در sms.ir'"
|
:placeholder="getSlotDefaultName(template.key, variable.slot) || 'نام متغیر در sms.ir'"
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
/>
|
/>
|
||||||
<Tag
|
<Tag
|
||||||
:value="`#${variable.name || getSlotDefaultName(template, variable.slot) || '...'}#`"
|
:value="`#${variable.name || getSlotDefaultName(template.key, variable.slot) || '...'}#`"
|
||||||
severity="secondary"
|
severity="secondary"
|
||||||
class="text-xs flex-shrink-0 font-mono"
|
class="text-xs flex-shrink-0 font-mono"
|
||||||
/>
|
/>
|
||||||
@@ -129,6 +131,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -278,6 +281,45 @@ const selectedFileName = ref('');
|
|||||||
const isImporting = ref(false);
|
const isImporting = ref(false);
|
||||||
const importResult = ref(null);
|
const importResult = ref(null);
|
||||||
|
|
||||||
|
const TEMPLATE_SLOT_DEFS = {
|
||||||
|
accountCreated: [
|
||||||
|
{ slot: 'username', label: 'نام کاربری', defaultName: 'user' },
|
||||||
|
{ slot: 'password', label: 'رمز عبور', defaultName: 'password' },
|
||||||
|
{ slot: 'fullName', label: 'نام و نام خانوادگی', defaultName: 'name' },
|
||||||
|
{ slot: 'phoneNumber', label: 'شماره همراه', defaultName: 'mobile' }
|
||||||
|
],
|
||||||
|
classRegistered: [
|
||||||
|
{ slot: 'className', label: 'نام کلاس', defaultName: 'className' },
|
||||||
|
{ slot: 'courseName', label: 'نام دوره', defaultName: 'courseName' },
|
||||||
|
{ slot: 'fullName', label: 'نام کارآموز', defaultName: 'fullName' },
|
||||||
|
{ slot: 'phoneNumber', label: 'شماره همراه', defaultName: 'mobile' }
|
||||||
|
],
|
||||||
|
classReminder: [
|
||||||
|
{ slot: 'className', label: 'نام کلاس', defaultName: 'className' },
|
||||||
|
{ slot: 'time', label: 'ساعت برگزاری', defaultName: 'time' },
|
||||||
|
{ slot: 'place', label: 'مکان برگزاری', defaultName: 'place' },
|
||||||
|
{ slot: 'courseName', label: 'نام دوره', defaultName: 'courseName' },
|
||||||
|
{ slot: 'fullName', label: 'نام کاربر', defaultName: 'fullName' },
|
||||||
|
{ slot: 'phoneNumber', label: 'شماره همراه', defaultName: 'mobile' }
|
||||||
|
],
|
||||||
|
invoiceCreated: [
|
||||||
|
{ slot: 'amount', label: 'مبلغ صورتحساب (تومان)', defaultName: 'PAYMENT_PRICE' },
|
||||||
|
{ slot: 'fullName', label: 'نام کارآموز', defaultName: 'FULLNAME' },
|
||||||
|
{ slot: 'course', label: 'نام دوره / کلاس', defaultName: 'COURSE' },
|
||||||
|
{ slot: 'phoneNumber', label: 'شماره همراه', defaultName: 'MOBILE' }
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
const getAvailableSlots = (templateKey) => {
|
||||||
|
return TEMPLATE_SLOT_DEFS[templateKey] || [];
|
||||||
|
};
|
||||||
|
|
||||||
|
const getSlotDefaultName = (templateKey, slotKey) => {
|
||||||
|
const slots = getAvailableSlots(templateKey);
|
||||||
|
const found = slots.find((s) => s.slot === slotKey);
|
||||||
|
return found?.defaultName || '';
|
||||||
|
};
|
||||||
|
|
||||||
const lockedAtLabel = computed(() => {
|
const lockedAtLabel = computed(() => {
|
||||||
if (!lockedAt.value) return '';
|
if (!lockedAt.value) return '';
|
||||||
const date = new Date(lockedAt.value);
|
const date = new Date(lockedAt.value);
|
||||||
@@ -285,30 +327,24 @@ const lockedAtLabel = computed(() => {
|
|||||||
return `قفل شده در ${date.toLocaleString('fa-IR')}`;
|
return `قفل شده در ${date.toLocaleString('fa-IR')}`;
|
||||||
});
|
});
|
||||||
|
|
||||||
const getSlotDefaultName = (template, slotKey) => {
|
|
||||||
const slot = (template?.availableSlots || []).find((s) => s.slot === slotKey);
|
|
||||||
return slot?.defaultName || '';
|
|
||||||
};
|
|
||||||
|
|
||||||
const onSlotChange = (templateKey, vIdx) => {
|
const onSlotChange = (templateKey, vIdx) => {
|
||||||
const form = templateForm.value[templateKey];
|
const form = templateForm.value[templateKey];
|
||||||
if (!form || !form.variables[vIdx]) return;
|
if (!form || !form.variables[vIdx]) return;
|
||||||
const template = smsTemplates.value.find((t) => t.key === templateKey);
|
|
||||||
const currentVar = form.variables[vIdx];
|
const currentVar = form.variables[vIdx];
|
||||||
if (!currentVar.name) {
|
const defaultName = getSlotDefaultName(templateKey, currentVar.slot);
|
||||||
currentVar.name = getSlotDefaultName(template, currentVar.slot);
|
if (!currentVar.name || currentVar.name === 'param') {
|
||||||
|
currentVar.name = defaultName;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const addVariable = (templateKey) => {
|
const addVariable = (templateKey) => {
|
||||||
const form = templateForm.value[templateKey];
|
const form = templateForm.value[templateKey];
|
||||||
if (!form) return;
|
if (!form) return;
|
||||||
const template = smsTemplates.value.find((t) => t.key === templateKey);
|
const availableSlots = getAvailableSlots(templateKey);
|
||||||
const availableSlots = template?.availableSlots || [];
|
|
||||||
|
|
||||||
const existingSlots = new Set((form.variables || []).map((v) => v.slot));
|
const existingSlots = new Set((form.variables || []).map((v) => v.slot));
|
||||||
const unusedSlot = availableSlots.find((s) => !existingSlots.has(s.slot));
|
const unusedSlot = availableSlots.find((s) => !existingSlots.has(s.slot));
|
||||||
const selectedSlot = unusedSlot || availableSlots[0] || { slot: 'param', defaultName: 'param' };
|
const selectedSlot = unusedSlot || availableSlots[0] || { slot: 'amount', defaultName: 'PAYMENT_PRICE' };
|
||||||
|
|
||||||
form.variables.push({
|
form.variables.push({
|
||||||
id: `var_${Date.now()}_${Math.random().toString(36).substring(2, 7)}`,
|
id: `var_${Date.now()}_${Math.random().toString(36).substring(2, 7)}`,
|
||||||
@@ -408,16 +444,28 @@ const confirmImport = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const emptyFormEntry = (template) => ({
|
const emptyFormEntry = (template) => {
|
||||||
templateId: template?.templateId || '',
|
const slots = getAvailableSlots(template?.key);
|
||||||
variables: Array.isArray(template?.variables)
|
let vars = [];
|
||||||
? template.variables.map((variable) => ({
|
if (Array.isArray(template?.variables) && template.variables.length > 0) {
|
||||||
|
vars = template.variables.map((variable) => ({
|
||||||
id: `var_${Date.now()}_${Math.random().toString(36).substring(2, 7)}`,
|
id: `var_${Date.now()}_${Math.random().toString(36).substring(2, 7)}`,
|
||||||
slot: variable.slot,
|
slot: variable.slot || slots[0]?.slot || 'amount',
|
||||||
name: variable.name || ''
|
name: variable.name || getSlotDefaultName(template?.key, variable.slot) || ''
|
||||||
}))
|
}));
|
||||||
: []
|
} else if (!template?.variables) {
|
||||||
});
|
vars = slots.map((s) => ({
|
||||||
|
id: `var_${Date.now()}_${Math.random().toString(36).substring(2, 7)}`,
|
||||||
|
slot: s.slot,
|
||||||
|
name: s.defaultName
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
templateId: template?.templateId || '',
|
||||||
|
variables: vars
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
const applySmsTemplates = (payload) => {
|
const applySmsTemplates = (payload) => {
|
||||||
const data = payload?.data?.data || payload?.data || payload || {};
|
const data = payload?.data?.data || payload?.data || payload || {};
|
||||||
@@ -449,12 +497,12 @@ const saveSmsTemplates = async () => {
|
|||||||
smsTemplates.value.forEach((template) => {
|
smsTemplates.value.forEach((template) => {
|
||||||
const entry = templateForm.value[template.key] || emptyFormEntry(template);
|
const entry = templateForm.value[template.key] || emptyFormEntry(template);
|
||||||
smsTemplatesPayload[template.key] = {
|
smsTemplatesPayload[template.key] = {
|
||||||
templateId: entry.templateId || '',
|
templateId: String(entry.templateId || '').trim(),
|
||||||
variables: (entry.variables || [])
|
variables: (entry.variables || [])
|
||||||
.filter((v) => v.slot)
|
.filter((v) => v.slot && String(v.name || '').trim())
|
||||||
.map((v) => ({
|
.map((v) => ({
|
||||||
slot: v.slot,
|
slot: v.slot,
|
||||||
name: v.name || getSlotDefaultName(template, v.slot) || v.slot
|
name: String(v.name).trim().replace(/^#+|#+$/g, '')
|
||||||
}))
|
}))
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user