Implement comprehensive event tracking system for TeleCart Pulse that ensures all user interactions and order events are reliably captured and delivered to the analytics platform, even in case of network failures or service outages. Business Value: - Guaranteed event delivery: All events are stored in database before sending, ensuring no data loss even if SaaS service is temporarily unavailable - Automatic retry mechanism: Failed events are automatically retried with configurable attempts, reducing manual intervention - Real-time monitoring: Admin dashboard displays event statistics (pending, sent, failed) to track system health and delivery status - Data integrity: Idempotency keys prevent duplicate events, ensuring accurate analytics and metrics - Performance optimization: Statistics are cached for 1 hour to reduce database load while maintaining visibility Key Features: - Event queue system: Events are queued in database with status tracking (pending/sent/failed) - Asynchronous processing: Events are sent via background tasks, not blocking user interactions - Error tracking: Failed events include detailed error reasons for debugging - Campaign tracking: Only events with valid campaign_id and tracking_id are stored, ensuring data quality - Admin visibility: Statistics dashboard shows delivery status at a glance This system ensures reliable data collection for campaign analytics, A/B testing, and performance metrics, providing accurate insights for business decisions.
153 lines
3.9 KiB
JavaScript
153 lines
3.9 KiB
JavaScript
import {defineStore} from "pinia";
|
|
import {apiGet, apiPost} from "@/utils/http.js";
|
|
import {toastBus} from "@/utils/toastHelper.js";
|
|
import {md5} from "js-md5";
|
|
|
|
export const useSettingsStore = defineStore('settings', {
|
|
state: () => ({
|
|
isLoading: false,
|
|
error: null,
|
|
originalItemsHash: null,
|
|
|
|
items: {
|
|
app: {
|
|
app_enabled: true,
|
|
app_name: '',
|
|
app_icon: null,
|
|
theme_light: 'light',
|
|
theme_dark: 'dark',
|
|
app_debug: false,
|
|
privacy_policy_link: null,
|
|
},
|
|
|
|
telegram: {
|
|
mini_app_url: '',
|
|
bot_token: '',
|
|
chat_id: '',
|
|
owner_notification_template: '',
|
|
customer_notification_template: '',
|
|
},
|
|
|
|
metrics: {
|
|
yandex_metrika_enabled: false,
|
|
yandex_metrika_counter: '',
|
|
},
|
|
|
|
store: {
|
|
enable_store: true,
|
|
feature_coupons: true,
|
|
feature_vouchers: true,
|
|
},
|
|
|
|
orders: {
|
|
order_default_status_id: 1,
|
|
},
|
|
|
|
texts: {
|
|
text_no_more_products: '',
|
|
text_empty_cart: '',
|
|
text_order_created_success: '',
|
|
zero_price_text: '',
|
|
},
|
|
|
|
sliders: {
|
|
mainpage_slider: {
|
|
is_enabled: false,
|
|
effect: "slide",
|
|
pagination: true,
|
|
scrollbar: false,
|
|
free_mode: false,
|
|
space_between: 30,
|
|
autoplay: false,
|
|
loop: false,
|
|
slides: [],
|
|
},
|
|
},
|
|
|
|
mainpage_blocks: [],
|
|
|
|
forms: {
|
|
checkout: {
|
|
alias: '',
|
|
friendly_name: '',
|
|
is_custom: false,
|
|
schema: [],
|
|
}
|
|
},
|
|
|
|
pulse: {
|
|
api_key: '',
|
|
batch_size: 50,
|
|
},
|
|
|
|
cron: {
|
|
mode: 'disabled',
|
|
},
|
|
},
|
|
}),
|
|
|
|
getters: {
|
|
app_icon_preview: (state) => {
|
|
if (!state.items.app.app_icon) return '/image/cache/no_image-100x100.png';
|
|
const extIndex = state.items.app.app_icon.lastIndexOf('.');
|
|
const ext = state.items.app.app_icon.substring(extIndex);
|
|
const filename = state.items.app.app_icon.substring(0, extIndex);
|
|
return `/image/cache/${filename}-100x100${ext}`;
|
|
},
|
|
hasUnsavedChanges: (state) => {
|
|
if (!state.originalItemsHash) return false;
|
|
return md5(JSON.stringify(state.items)) !== state.originalItemsHash;
|
|
},
|
|
},
|
|
|
|
actions: {
|
|
async fetchSettings() {
|
|
this.isLoading = true;
|
|
this.error = null;
|
|
const response = await apiGet('getSettingsForm');
|
|
if (response.success) {
|
|
this.items = {
|
|
...this.items,
|
|
...response.data,
|
|
};
|
|
// Сохраняем хеш исходного состояния после загрузки
|
|
this.originalItemsHash = md5(JSON.stringify(this.items));
|
|
} else {
|
|
this.error = 'Возникли проблемы при загрузке настроек.';
|
|
}
|
|
this.isLoading = false;
|
|
},
|
|
|
|
async saveSettings() {
|
|
this.isLoading = true;
|
|
const settings = this.transformSettingsToStore(this.items);
|
|
const response = await apiPost('saveSettingsForm', settings);
|
|
|
|
if (response.success === true) {
|
|
toastBus.emit('show', {
|
|
severity: 'success',
|
|
summary: 'Готово!',
|
|
detail: 'Настройки сохранены.',
|
|
life: 2000,
|
|
});
|
|
// Обновляем хеш исходного состояния после успешного сохранения
|
|
this.originalItemsHash = md5(JSON.stringify(this.items));
|
|
} else {
|
|
toastBus.emit('show', {
|
|
severity: 'error',
|
|
summary: 'Ошибка',
|
|
detail: 'Возникли проблемы при сохранении настроек на сервере.',
|
|
life: 2000,
|
|
});
|
|
}
|
|
|
|
|
|
this.isLoading = false;
|
|
},
|
|
|
|
transformSettingsToStore(items) {
|
|
return items;
|
|
},
|
|
},
|
|
});
|