setting in better position

This commit is contained in:
2026-06-14 16:27:18 +03:30
parent 0c404ee3e1
commit 6d0601f464
4 changed files with 75 additions and 38 deletions
@@ -24,7 +24,7 @@
:setting-type="settingType" :setting-type="settingType"
:description="description" :description="description"
:disabled="readonly" :disabled="readonly"
:rows="fieldType === 'longtext' ? 4 : 6" :rows="fieldType === 'longtext' ? 6 : 6"
@update:value="emit('update:value', $event)" @update:value="emit('update:value', $event)"
/> />
</div> </div>
+63 -21
View File
@@ -262,7 +262,7 @@ const otherRows = computed(() =>
) )
// ============================================================================= // =============================================================================
// گروه‌بندی تنظیمات (برای کالپس جذاب + سرچ هوشمند) // گروه‌بندی تنظیمات — اولین match برنده است؛ misc فقط برای باقی‌مانده
// ============================================================================= // =============================================================================
const SETTING_GROUPS: Array<{ const SETTING_GROUPS: Array<{
id: string id: string
@@ -272,9 +272,12 @@ const SETTING_GROUPS: Array<{
}> = [ }> = [
{ {
id: 'general', id: 'general',
title: 'عمومی و اطلاعات اپ', title: 'عمومی و برند اپ',
icon: 'vuesax-linear:home-2', icon: 'vuesax-linear:home-2',
match: (k) => /^(name_fa|app_url|admin_url|metal_type|unit$|open_register|auto_active_customer|is_store)/.test(k) match: (k) =>
/^(name_fa|name_en|app_url|admin_url|bace_url|server_url|logo_|title_pwa|title_fav|metal_type|unit$|open_register|auto_active_customer|store_status|key$)/.test(
k
)
}, },
{ {
id: 'chart', id: 'chart',
@@ -284,37 +287,75 @@ const SETTING_GROUPS: Array<{
}, },
{ {
id: 'pricing', id: 'pricing',
title: 'قیمت‌گذاری و تابلو', title: 'قیمت‌گذاری، کارمزد و تابلو',
icon: 'vuesax-linear:dollar-circle', icon: 'vuesax-linear:dollar-circle',
match: (k) => match: (k) =>
/^(fee_|buy_fee|sell_fee|min_|price_provider|zaarbox_|main_product$|show_last_price|close_price|startDay|endDay)/.test(k) || /^(fee_|buy_fee|sell_fee|min_|minimum_|price_provider|zaarbox_|main_product$|show_last_price|close_price|startDay|endDay|up_price|down_price|price_extreme_date|balance_report_exclude)/.test(
k.includes('charge_percentage') k
) || k.includes('charge_percentage')
},
{
id: 'content',
title: 'متن‌های اپ (قوانین و درباره)',
icon: 'vuesax-linear:document-text',
match: (k) => /^text_/.test(k)
}, },
{ {
id: 'referral', id: 'referral',
title: 'معرف، پاداش و ثبت‌نام', title: 'معرف، پاداش و ثبت‌نام',
icon: 'vuesax-linear:people', icon: 'vuesax-linear:people',
match: (k) => match: (k) =>
/^(referral_|gift_for|register_referral|register_jibit|has_page_earn_money|jibit_verification)/.test(k) /^(referral_|gift_for|register_referral|register_jibit|has_page_earn_money|jibit_verification|referral_bonus)/.test(
k
)
}, },
{ {
id: 'montzar', id: 'montzar',
title: 'سرویس همکار (montzar)', title: 'همکار قیمت (Montzar)',
icon: 'vuesax-linear:link', icon: 'vuesax-linear:link-2',
match: (k) => k.startsWith('montzar_') match: (k) => k.startsWith('montzar_') || k === 'display_montzar'
},
{
id: 'store',
title: 'اتصال به فروشگاه (Montify)',
icon: 'vuesax-linear:shop',
match: (k) => /^(external_order|node_|montify_name)/.test(k)
},
{
id: 'payping',
title: 'درگاه Payping / Zify',
icon: 'vuesax-linear:card',
match: (k) => k.startsWith('payping_')
},
{
id: 'tahesab',
title: 'ته‌حساب',
icon: 'vuesax-linear:receipt-2',
match: (k) => k.startsWith('tahesab_') || k === 'send_to_tahesab'
},
{
id: 'support',
title: 'پشتیبانی اپ کاربر',
icon: 'vuesax-linear:headphone',
match: (k) => k.startsWith('support_messenger')
},
{
id: 'bots',
title: 'بات تلگرام و بله',
icon: 'vuesax-linear:messages-2',
match: (k) => /^(telegram_bot|bale_bot)/.test(k)
},
{
id: 'notifications',
title: 'پیامک و اعلان',
icon: 'vuesax-linear:notification',
match: (k) => /^(charge_notif|group_sms)/.test(k)
}, },
{ {
id: 'features', id: 'features',
title: 'ویژگی‌ها و اعلان‌ها', title: 'محصولات و قابلیت‌های سیستم',
icon: 'vuesax-linear:menu', icon: 'vuesax-linear:setting-2',
match: (k) => /^(charge_notif|group_sms|main_wallet_products|price_from_nasiryan)/.test(k) match: (k) => /^(product_|main_wallet_products|price_from_nasiryan|profit_gold)/.test(k)
},
{
id: 'integrations',
title: 'اتصالات خارجی و درگاه‌ها',
icon: 'vuesax-linear:card',
match: (k) =>
/^(tahesab_|payping_|telegram_|bale_|support_messenger|external_order|profit_gold|node_)/.test(k)
}, },
{ {
id: 'misc', id: 'misc',
@@ -326,6 +367,7 @@ const SETTING_GROUPS: Array<{
function getGroupId(key: string): string { function getGroupId(key: string): string {
for (const g of SETTING_GROUPS) { for (const g of SETTING_GROUPS) {
if (g.id === 'misc') continue
if (g.match(key)) return g.id if (g.match(key)) return g.id
} }
return 'misc' return 'misc'
@@ -346,7 +388,7 @@ const groupedFiltered = computed(() => {
}) })
// کالپس‌های باز — وقتی سرچ فعال است فقط گروه‌های دارای نتیجه باز می‌شوند // کالپس‌های باز — وقتی سرچ فعال است فقط گروه‌های دارای نتیجه باز می‌شوند
const defaultOpenGroups: string[] = [] const defaultOpenGroups = ['general', 'pricing', 'store', 'payping', 'tahesab']
const activeKeys = ref<string[]>(defaultOpenGroups) const activeKeys = ref<string[]>(defaultOpenGroups)
watch(search, (q) => { watch(search, (q) => {
@@ -80,8 +80,13 @@ const KEY_TYPE_FALLBACK: Record<string, SettingFieldType> = {
price_from_nasiryan: 'switch', price_from_nasiryan: 'switch',
node_client_id: 'text', node_client_id: 'text',
node_shared_secret: 'text', node_shared_secret: 'text',
tahesab_host: 'text',
tahesab_port: 'number',
tahesab_token: 'text',
tahesab_db: 'text',
tahesab_bank_account: 'text',
support_messenger_id: 'text', support_messenger_id: 'text',
support_messenger_text: 'text', support_messenger_text: 'longtext',
support_messenger: 'select', support_messenger: 'select',
zaarbox_price_key: 'select' zaarbox_price_key: 'select'
} }
@@ -4,6 +4,9 @@
<BaseButton :loading="syncing" @click="handleSync"> <BaseButton :loading="syncing" @click="handleSync">
همگام‌سازی از محصولات همگام‌سازی از محصولات
</BaseButton> </BaseButton>
<span class="text-sm text-gray-500">
تب فیلتر اپ خودکار از دسته‌های فعالی است که محصول دارند.
</span>
</div> </div>
<a-spin :spinning="loading"> <a-spin :spinning="loading">
@@ -24,12 +27,6 @@
@change="(checked: boolean) => toggleField(record, 'active', checked)" @change="(checked: boolean) => toggleField(record, 'active', checked)"
/> />
</template> </template>
<template v-else-if="column.key === 'show_in_filter'">
<a-switch
:checked="asBool(record.show_in_filter)"
@change="(checked: boolean) => toggleField(record, 'show_in_filter', checked)"
/>
</template>
<template v-else-if="column.key === 'show_in_select'"> <template v-else-if="column.key === 'show_in_select'">
<a-switch <a-switch
:checked="asBool(record.show_in_select)" :checked="asBool(record.show_in_select)"
@@ -62,7 +59,7 @@ const loading = ref(false)
const syncing = ref(false) const syncing = ref(false)
const items = ref<Category[]>([]) const items = ref<Category[]>([])
type CategoryField = 'active' | 'show_in_filter' | 'show_in_select' | 'sort_order' type CategoryField = 'active' | 'show_in_select' | 'sort_order'
const pendingPatches = new Map<number, Partial<Record<CategoryField, number>>>() const pendingPatches = new Map<number, Partial<Record<CategoryField, number>>>()
const debouncedFlush = new Map<number, ReturnType<typeof debounce>>() const debouncedFlush = new Map<number, ReturnType<typeof debounce>>()
@@ -76,12 +73,6 @@ const columns: TableColumnType<Category>[] = [
width: 160, width: 160,
align: 'center' align: 'center'
}, },
{
title: 'تب فیلتر اپ',
key: 'show_in_filter',
width: 120,
align: 'center'
},
{ {
title: 'سلکت افزودن محصول', title: 'سلکت افزودن محصول',
key: 'show_in_select', key: 'show_in_select',
@@ -137,7 +128,6 @@ async function flushSave(id: number) {
const snapshot = { const snapshot = {
active: record.active, active: record.active,
show_in_filter: record.show_in_filter,
show_in_select: record.show_in_select, show_in_select: record.show_in_select,
sort_order: record.sort_order sort_order: record.sort_order
} }
@@ -154,7 +144,7 @@ async function flushSave(id: number) {
function toggleField( function toggleField(
record: Category, record: Category,
field: 'active' | 'show_in_filter' | 'show_in_select', field: 'active' | 'show_in_select',
checked: boolean checked: boolean
) { ) {
if (asBool(record[field]) === checked) return if (asBool(record[field]) === checked) return