diff --git a/src/views/settings/SettingsView.vue b/src/views/settings/SettingsView.vue
index c9c9852..dc183a7 100644
--- a/src/views/settings/SettingsView.vue
+++ b/src/views/settings/SettingsView.vue
@@ -3,10 +3,21 @@
-
+
+
+ کانالها
+ اطلاعرسانی
+ قالبهای پیامک
+ راهاندازی
+ وارد کردن داده
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
تنظیمات اطلاعرسانی
+
+ برای هر نوع رویداد، کانالهای پیامک، ایمیل و ربات را جداگانه فعال یا غیرفعال کنید. اگر رکوردی در پایگاه داده نباشد، هنگام بارگذاری مقادیر پیشفرض اعمال میشود.
+
+
+
+
+
+
+ در حال بارگذاری تنظیمات اطلاعرسانی…
+
+
+
+
+
{{ group.label }}
+
+
+
+
+
{{ action.label }}
+
{{ action.description }}
+
{{ action.key }}
+
+
+
+
+
+
+
+
+ {{ channel.label }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
@@ -251,9 +340,11 @@
این عملیات فقط یکبار قابل اجرا است.
-
+
+
-
+
+
+
@@ -330,6 +424,11 @@ import InputSwitch from 'primevue/toggleswitch';
import InputText from 'primevue/inputtext';
import Select from 'primevue/select';
import Tag from 'primevue/tag';
+import Tabs from 'primevue/tabs';
+import TabList from 'primevue/tablist';
+import Tab from 'primevue/tab';
+import TabPanels from 'primevue/tabpanels';
+import TabPanel from 'primevue/tabpanel';
import PageHeader from '@/components/common/PageHeader.vue';
import { seedApi } from '@/api/seedApi';
import { settingsApi } from '@/api/settingsApi';
@@ -341,8 +440,11 @@ const { showSuccess, showError } = useToast();
const isSettingsLoading = ref(true);
const isSavingSettings = ref(false);
const isSavingMessaging = ref(false);
+const isSavingNotifications = ref(false);
const smsTemplates = ref([]);
const templateForm = ref({});
+const notificationSettings = ref([]);
+const notificationForm = ref({});
const messagingForm = ref({
smsEnabled: true,
emailEnabled: true,
@@ -360,6 +462,12 @@ const messagingChannels = [
{ key: 'bot', flag: 'botEnabled', label: 'پیام ربات', icon: 'pi pi-comments', envName: 'BOT_ENABLED' }
];
+const notificationChannelDefs = [
+ { key: 'sms', label: 'پیامک', icon: 'pi pi-mobile' },
+ { key: 'email', label: 'ایمیل', icon: 'pi pi-envelope' },
+ { key: 'bot', label: 'ربات', icon: 'pi pi-comments' }
+];
+
const channelStatus = (channelKey) => {
const flag = `${channelKey}Enabled`;
const dbOn = messagingForm.value[flag] !== false;
@@ -385,7 +493,15 @@ const TEMPLATE_SLOT_DEFS = {
{ value: 'username', label: 'نام کاربری', defaultName: 'user' },
{ value: 'password', label: 'رمز عبور', defaultName: 'password' },
{ value: 'fullName', label: 'نام و نام خانوادگی', defaultName: 'name' },
- { value: 'phoneNumber', label: 'شماره همراه', defaultName: 'mobile' }
+ { value: 'phoneNumber', label: 'شماره همراه', defaultName: 'mobile' },
+ { value: 'userCode', label: 'کد کاربری', defaultName: 'userCode' }
+ ],
+ passwordReset: [
+ { value: 'username', label: 'نام کاربری', defaultName: 'user' },
+ { value: 'password', label: 'رمز عبور', defaultName: 'password' },
+ { value: 'fullName', label: 'نام کاربر', defaultName: 'name' },
+ { value: 'phoneNumber', label: 'شماره همراه', defaultName: 'mobile' },
+ { value: 'userCode', label: 'کد کاربری', defaultName: 'userCode' }
],
classRegistered: [
{ value: 'className', label: 'نام کلاس', defaultName: 'className' },
@@ -393,19 +509,24 @@ const TEMPLATE_SLOT_DEFS = {
{ value: 'fullName', label: 'نام کارآموز', defaultName: 'fullName' },
{ value: 'phoneNumber', label: 'شماره همراه', defaultName: 'mobile' },
{ value: 'classStartDate', label: 'تاریخ شروع کلاس', defaultName: 'classStartDate' },
- { value: 'classDays', label: 'روزهای برگزاری (مثلاً شنبه و دوشنبه)', defaultName: 'classDays' },
- { value: 'courseTime', label: 'ساعت دوره (مثلاً از ۱۹ تا ۲۱)', defaultName: 'courseTime' }
+ { value: 'classDays', label: 'روزهای برگزاری', defaultName: 'classDays' },
+ { value: 'courseTime', label: 'ساعت دوره', defaultName: 'courseTime' },
+ { value: 'classCode', label: 'کد کلاس', defaultName: 'classCode' }
],
classReminder: [
{ value: 'className', label: 'نام کلاس', defaultName: 'className' },
- { value: 'time', label: 'ساعت برگزاری', defaultName: 'time' },
- { value: 'place', label: 'مکان برگزاری', defaultName: 'place' },
{ value: 'courseName', label: 'نام دوره', defaultName: 'courseName' },
+ { value: 'topic', label: 'موضوع جلسه', defaultName: 'topic' },
+ { value: 'time', label: 'ساعت برگزاری', defaultName: 'time' },
+ { value: 'classTime', label: 'ساعت کلاس', defaultName: 'classTime' },
+ { value: 'sessionDate', label: 'تاریخ جلسه', defaultName: 'sessionDate' },
+ { value: 'place', label: 'مکان برگزاری', defaultName: 'place' },
{ value: 'fullName', label: 'نام کاربر', defaultName: 'fullName' },
{ value: 'phoneNumber', label: 'شماره همراه', defaultName: 'mobile' },
{ value: 'classStartDate', label: 'تاریخ شروع کلاس', defaultName: 'classStartDate' },
- { value: 'classDays', label: 'روزهای برگزاری (مثلاً شنبه و دوشنبه)', defaultName: 'classDays' },
- { value: 'courseTime', label: 'ساعت دوره (مثلاً از ۱۹ تا ۲۱)', defaultName: 'courseTime' }
+ { value: 'classDays', label: 'روزهای برگزاری', defaultName: 'classDays' },
+ { value: 'courseTime', label: 'ساعت دوره', defaultName: 'courseTime' },
+ { value: 'classCode', label: 'کد کلاس', defaultName: 'classCode' }
],
invoiceCreated: [
{ value: 'amount', label: 'مبلغ صورتحساب (تومان)', defaultName: 'PAYMENT_PRICE' },
@@ -413,8 +534,79 @@ const TEMPLATE_SLOT_DEFS = {
{ value: 'course', label: 'نام دوره / کلاس', defaultName: 'COURSE' },
{ value: 'phoneNumber', label: 'شماره همراه', defaultName: 'MOBILE' },
{ value: 'classStartDate', label: 'تاریخ شروع کلاس', defaultName: 'classStartDate' },
- { value: 'classDays', label: 'روزهای برگزاری (مثلاً شنبه و دوشنبه)', defaultName: 'classDays' },
- { value: 'courseTime', label: 'ساعت دوره (مثلاً از ۱۹ تا ۲۱)', defaultName: 'courseTime' }
+ { value: 'classDays', label: 'روزهای برگزاری', defaultName: 'classDays' },
+ { value: 'courseTime', label: 'ساعت دوره', defaultName: 'courseTime' },
+ { value: 'invoiceCode', label: 'کد صورتحساب', defaultName: 'invoiceCode' }
+ ],
+ paymentStatusChanged: [
+ { value: 'fullName', label: 'نام کارآموز', defaultName: 'fullName' },
+ { value: 'status', label: 'وضعیت', defaultName: 'status' },
+ { value: 'amount', label: 'مبلغ', defaultName: 'amount' },
+ { value: 'invoiceCode', label: 'کد صورتحساب', defaultName: 'invoiceCode' },
+ { value: 'course', label: 'نام دوره', defaultName: 'course' },
+ { value: 'phoneNumber', label: 'شماره همراه', defaultName: 'mobile' }
+ ],
+ paymentReminder: [
+ { value: 'fullName', label: 'نام کارآموز', defaultName: 'fullName' },
+ { value: 'amount', label: 'مبلغ باقیمانده', defaultName: 'amount' },
+ { value: 'dueDate', label: 'تاریخ سررسید', defaultName: 'dueDate' },
+ { value: 'invoiceCode', label: 'کد صورتحساب', defaultName: 'invoiceCode' },
+ { value: 'course', label: 'نام دوره', defaultName: 'course' },
+ { value: 'phoneNumber', label: 'شماره همراه', defaultName: 'mobile' }
+ ],
+ transactionRecorded: [
+ { value: 'fullName', label: 'نام کارآموز', defaultName: 'fullName' },
+ { value: 'amount', label: 'مبلغ', defaultName: 'amount' },
+ { value: 'invoiceCode', label: 'کد صورتحساب', defaultName: 'invoiceCode' },
+ { value: 'transactionCode', label: 'کد تراکنش', defaultName: 'transactionCode' },
+ { value: 'receiptNumber', label: 'شماره رسید', defaultName: 'receiptNumber' },
+ { value: 'phoneNumber', label: 'شماره همراه', defaultName: 'mobile' }
+ ],
+ sessionCancelled: [
+ { value: 'fullName', label: 'نام کارآموز', defaultName: 'fullName' },
+ { value: 'className', label: 'نام کلاس', defaultName: 'className' },
+ { value: 'topic', label: 'موضوع جلسه', defaultName: 'topic' },
+ { value: 'sessionDate', label: 'تاریخ جلسه', defaultName: 'sessionDate' },
+ { value: 'reason', label: 'دلیل لغو', defaultName: 'reason' },
+ { value: 'classCode', label: 'کد کلاس', defaultName: 'classCode' },
+ { value: 'phoneNumber', label: 'شماره همراه', defaultName: 'mobile' }
+ ],
+ sessionHolding: [
+ { value: 'fullName', label: 'نام کارآموز', defaultName: 'FULLNAME' },
+ { value: 'topic', label: 'موضوع جلسه', defaultName: 'TOPIC' },
+ { value: 'className', label: 'نام کلاس', defaultName: 'CLASSNAME' },
+ { value: 'sessionDate', label: 'تاریخ جلسه', defaultName: 'SESSIONDATE' },
+ { value: 'classTime', label: 'ساعت کلاس', defaultName: 'CLASSTIME' },
+ { value: 'courseName', label: 'نام دوره', defaultName: 'courseName' },
+ { value: 'classCode', label: 'کد کلاس', defaultName: 'classCode' },
+ { value: 'place', label: 'مکان', defaultName: 'place' },
+ { value: 'phoneNumber', label: 'شماره همراه', defaultName: 'mobile' }
+ ],
+ classRequestApproved: [
+ { value: 'fullName', label: 'نام کارآموز', defaultName: 'fullName' },
+ { value: 'courseName', label: 'نام دوره', defaultName: 'courseName' },
+ { value: 'classCode', label: 'کد کلاس', defaultName: 'classCode' },
+ { value: 'phoneNumber', label: 'شماره همراه', defaultName: 'mobile' }
+ ],
+ classRequestRejected: [
+ { value: 'fullName', label: 'نام کارآموز', defaultName: 'fullName' },
+ { value: 'courseName', label: 'نام دوره', defaultName: 'courseName' },
+ { value: 'reason', label: 'دلیل', defaultName: 'reason' },
+ { value: 'registrationCode', label: 'کد درخواست', defaultName: 'registrationCode' },
+ { value: 'phoneNumber', label: 'شماره همراه', defaultName: 'mobile' }
+ ],
+ pendingRegistration: [
+ { value: 'fullName', label: 'نام کارآموز', defaultName: 'fullName' },
+ { value: 'className', label: 'نام کلاس', defaultName: 'className' },
+ { value: 'registrationCode', label: 'کد درخواست', defaultName: 'registrationCode' },
+ { value: 'phoneNumber', label: 'شماره همراه', defaultName: 'mobile' }
+ ],
+ certificateIssued: [
+ { value: 'fullName', label: 'نام کارآموز', defaultName: 'fullName' },
+ { value: 'certificateTitle', label: 'عنوان گواهینامه', defaultName: 'certificateTitle' },
+ { value: 'certificateCode', label: 'کد گواهینامه', defaultName: 'certificateCode' },
+ { value: 'courseName', label: 'نام دوره', defaultName: 'courseName' },
+ { value: 'phoneNumber', label: 'شماره همراه', defaultName: 'mobile' }
]
};
@@ -600,9 +792,28 @@ const applyMessaging = (payload) => {
};
};
+const applyNotificationSettings = (payload) => {
+ const data = payload?.data?.data || payload?.data || payload || {};
+ const groups = Array.isArray(data.notificationSettings) ? data.notificationSettings : [];
+ notificationSettings.value = groups;
+
+ const form = {};
+ groups.forEach((group) => {
+ (group.actions || []).forEach((action) => {
+ form[action.key] = {
+ sms: action.channels?.sms !== false,
+ email: action.channels?.email === true,
+ bot: action.channels?.bot === true
+ };
+ });
+ });
+ notificationForm.value = form;
+};
+
const applySettings = (payload) => {
applySmsTemplates(payload);
applyMessaging(payload);
+ applyNotificationSettings(payload);
};
const loadSettings = async () => {
@@ -636,6 +847,30 @@ const saveMessaging = async () => {
}
};
+const saveNotificationSettings = async () => {
+ isSavingNotifications.value = true;
+ try {
+ const payload = {};
+ notificationSettings.value.forEach((group) => {
+ (group.actions || []).forEach((action) => {
+ const channels = notificationForm.value[action.key] || {};
+ payload[action.key] = {
+ sms: Boolean(channels.sms),
+ email: Boolean(channels.email),
+ bot: Boolean(channels.bot)
+ };
+ });
+ });
+ const response = await settingsApi.save({ notificationSettings: payload });
+ applySettings(response);
+ showSuccess('تنظیمات اطلاعرسانی با موفقیت ذخیره شد.');
+ } catch (err) {
+ showError(err);
+ } finally {
+ isSavingNotifications.value = false;
+ }
+};
+
const saveSmsTemplates = async () => {
isSavingSettings.value = true;
try {