feat: website settings menu gated by has_landing
Add تنظیمات وبسایت before پیکربندی with landing_* subsections, and show unit addon on numeric setting fields. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -29,7 +29,7 @@ import BasicMobileOverflowMenu from '@/components/BasicMobileOverflowMenu.vue'
|
|||||||
import { sortBy } from 'lodash'
|
import { sortBy } from 'lodash'
|
||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
import type { RouteRecordName, RouteRecordRaw } from 'vue-router'
|
import type { RouteRecordName, RouteRecordRaw } from 'vue-router'
|
||||||
import { supportChatMenuEnabledSetting } from '@/utils/config'
|
import { hasLandingSetting, supportChatMenuEnabledSetting } from '@/utils/config'
|
||||||
|
|
||||||
const BOTTOM_NAV_PRIORITY: (string | symbol)[] = ['dashboard', 'customers', 'orders', 'transactions']
|
const BOTTOM_NAV_PRIORITY: (string | symbol)[] = ['dashboard', 'customers', 'orders', 'transactions']
|
||||||
|
|
||||||
@@ -44,6 +44,7 @@ const allMenuItems = computed(() =>
|
|||||||
if (item.name === 'support' || item.meta?.permissionsKey === 'support') {
|
if (item.name === 'support' || item.meta?.permissionsKey === 'support') {
|
||||||
return supportChatMenuEnabledSetting.value
|
return supportChatMenuEnabledSetting.value
|
||||||
}
|
}
|
||||||
|
if (item.name === 'websiteSettings') return hasLandingSetting.value
|
||||||
return true
|
return true
|
||||||
}),
|
}),
|
||||||
(item) => item.meta?.order
|
(item) => item.meta?.order
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ import BaseMenuItem from '@core/layouts/composnts/BaseMenuItem.vue'
|
|||||||
import type { RouteRecordName, RouteRecordRaw } from 'vue-router'
|
import type { RouteRecordName, RouteRecordRaw } from 'vue-router'
|
||||||
import { useRouterStore } from '@core/stores/router'
|
import { useRouterStore } from '@core/stores/router'
|
||||||
import { useAdminTheme } from '@core/composable/useAdminTheme'
|
import { useAdminTheme } from '@core/composable/useAdminTheme'
|
||||||
import { supportChatMenuEnabledSetting } from '@/utils/config'
|
import { hasLandingSetting, supportChatMenuEnabledSetting } from '@/utils/config'
|
||||||
|
|
||||||
const { prefixCls } = usePrefix('basic-menu')
|
const { prefixCls } = usePrefix('basic-menu')
|
||||||
const layoutStore = useLayoutStore()
|
const layoutStore = useLayoutStore()
|
||||||
@@ -79,6 +79,7 @@ const menu: ComputedRef<RouteRecordRaw[]> = computed(() => {
|
|||||||
}).filter((item) => {
|
}).filter((item) => {
|
||||||
if (item.meta?.hideMenu) return false
|
if (item.meta?.hideMenu) return false
|
||||||
if (isSupportMenuRoute(item)) return supportChatMenuEnabledSetting.value
|
if (isSupportMenuRoute(item)) return supportChatMenuEnabledSetting.value
|
||||||
|
if (item.name === 'websiteSettings') return hasLandingSetting.value
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -97,6 +97,7 @@
|
|||||||
:value="priceValue"
|
:value="priceValue"
|
||||||
:disabled="disabled"
|
:disabled="disabled"
|
||||||
class="w-full"
|
class="w-full"
|
||||||
|
:addon-after="unitLabel || undefined"
|
||||||
:formatter="(v: string) => `${v}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')"
|
:formatter="(v: string) => `${v}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')"
|
||||||
:parser="(v: string) => sanitizeNumericString(v, { allowDecimal: false })"
|
:parser="(v: string) => sanitizeNumericString(v, { allowDecimal: false })"
|
||||||
@update:value="onPriceChange"
|
@update:value="onPriceChange"
|
||||||
@@ -109,6 +110,7 @@
|
|||||||
inputmode="numeric"
|
inputmode="numeric"
|
||||||
allow-clear
|
allow-clear
|
||||||
class="w-full"
|
class="w-full"
|
||||||
|
:addon-after="unitLabel || undefined"
|
||||||
@update:value="onPlainNumberChange"
|
@update:value="onPlainNumberChange"
|
||||||
@blur="emit('blur')"
|
@blur="emit('blur')"
|
||||||
/>
|
/>
|
||||||
@@ -144,6 +146,7 @@ import TemplateTextField from './TemplateTextField.vue'
|
|||||||
import ZaarboxPriceKeyField from './ZaarboxPriceKeyField.vue'
|
import ZaarboxPriceKeyField from './ZaarboxPriceKeyField.vue'
|
||||||
import { hasTemplateField } from './templateFields'
|
import { hasTemplateField } from './templateFields'
|
||||||
import {
|
import {
|
||||||
|
getSettingUnitLabel,
|
||||||
normalizeTimeValue,
|
normalizeTimeValue,
|
||||||
parseSelectOptions,
|
parseSelectOptions,
|
||||||
resolveSettingFieldType,
|
resolveSettingFieldType,
|
||||||
@@ -182,6 +185,8 @@ const fieldType = computed<SettingFieldType>(() =>
|
|||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const unitLabel = computed(() => getSettingUnitLabel(props.settingKey, fieldType.value))
|
||||||
|
|
||||||
const isZaarboxPriceKey = computed(() => props.settingKey === 'zaarbox_price_key')
|
const isZaarboxPriceKey = computed(() => props.settingKey === 'zaarbox_price_key')
|
||||||
const isMontzarProductId = computed(() => props.settingKey === 'montzar_product_id')
|
const isMontzarProductId = computed(() => props.settingKey === 'montzar_product_id')
|
||||||
const isMainWalletProducts = computed(() => props.settingKey === 'main_wallet_products')
|
const isMainWalletProducts = computed(() => props.settingKey === 'main_wallet_products')
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="h-full min-h-0">
|
<div class="h-full min-h-0">
|
||||||
<BasicShowContent :title="pageTitle" :help="configurationPageIntro" class="h-full">
|
<BasicShowContent :title="pageTitle" :help="pageHelp" class="h-full">
|
||||||
<div class="settings-toolbar">
|
<div class="settings-toolbar">
|
||||||
<a-input
|
<a-input
|
||||||
v-model:value="search"
|
v-model:value="search"
|
||||||
@@ -207,10 +207,10 @@ import { loading } from '@/utils'
|
|||||||
import { getEditableConfiguration, getSystemConfiguration, setConfiguration, setSystemConfiguration, refreshSuperAdminSettings } from '@/api/configuration'
|
import { getEditableConfiguration, getSystemConfiguration, setConfiguration, setSystemConfiguration, refreshSuperAdminSettings } from '@/api/configuration'
|
||||||
import SettingValueField from './SettingValueField.vue'
|
import SettingValueField from './SettingValueField.vue'
|
||||||
import SettingCard from './SettingCard.vue'
|
import SettingCard from './SettingCard.vue'
|
||||||
import { configurationPageIntro } from '@/utils/adminHelpCopy'
|
import { configurationPageIntro, websiteSettingsPageIntro } from '@/utils/adminHelpCopy'
|
||||||
import { refreshAppModeMenu } from '@/router'
|
import { refreshAppModeMenu } from '@/router'
|
||||||
import { useUserStore } from '@/store/userStore'
|
import { useUserStore } from '@/store/userStore'
|
||||||
import { applyBannerEnabledFromRows, applyTrackingSystemsEnabledFromRows, applyConditionalOrderEnabledFromRows, applyAutomationEnabledFromRows, applyProductFundsEnabledFromRows, applyPriceTriggerEnabledFromRows, applyAppNotificationEnabledFromRows, applyPriceProviderFromRows, applyPriceChannelAccessFromRows, applySupportChatMenuEnabledFromRows, applyGroupSmsFromRows, applyCustomerSpecialPricingFromRows, applyGoldCreditEnabledFromRows, applyCustomerDirectSmsFromRows, applyCustomerLevelProfitEnabledFromRows, applySuperAdminAccessFlagsFromItems, invalidateSettingsBootstrap, setBannerEnabledFromSettings, setConditionalOrderEnabledFromSettings, setAutomationEnabledFromSettings, setProductFundsEnabledFromSettings, setPriceTriggerEnabledFromSettings, setAppNotificationEnabledFromSettings, setPriceProviderFromSettings, setPriceChannelAccessFromSettings, setStoreModeFromSettings, setTrackingSystemsEnabledFromSettings, setGroupSmsEnabledFromSettings, setCustomerSpecialPricingEnabledFromSettings, setGoldCreditEnabledFromSettings } from '@/utils/config'
|
import { applyBannerEnabledFromRows, applyTrackingSystemsEnabledFromRows, applyConditionalOrderEnabledFromRows, applyAutomationEnabledFromRows, applyProductFundsEnabledFromRows, applyPriceTriggerEnabledFromRows, applyAppNotificationEnabledFromRows, applyPriceProviderFromRows, applyPriceChannelAccessFromRows, applySupportChatMenuEnabledFromRows, applyGroupSmsFromRows, applyCustomerSpecialPricingFromRows, applyGoldCreditEnabledFromRows, applyCustomerDirectSmsFromRows, applyCustomerLevelProfitEnabledFromRows, applySuperAdminAccessFlagsFromItems, invalidateSettingsBootstrap, setBannerEnabledFromSettings, setConditionalOrderEnabledFromSettings, setAutomationEnabledFromSettings, setProductFundsEnabledFromSettings, setPriceTriggerEnabledFromSettings, setAppNotificationEnabledFromSettings, setPriceProviderFromSettings, setPriceChannelAccessFromSettings, setStoreModeFromSettings, setTrackingSystemsEnabledFromSettings, setGroupSmsEnabledFromSettings, setCustomerSpecialPricingEnabledFromSettings, setGoldCreditEnabledFromSettings, applyHasLandingFromRows, setHasLandingFromSettings } from '@/utils/config'
|
||||||
import {
|
import {
|
||||||
EDITABLE_SETTING_GROUPS,
|
EDITABLE_SETTING_GROUPS,
|
||||||
SYSTEM_SETTING_GROUPS,
|
SYSTEM_SETTING_GROUPS,
|
||||||
@@ -218,6 +218,12 @@ import {
|
|||||||
OTHER_PAGE_SETTING_MENUS,
|
OTHER_PAGE_SETTING_MENUS,
|
||||||
type SettingGroupDef
|
type SettingGroupDef
|
||||||
} from './settingGroups'
|
} from './settingGroups'
|
||||||
|
import {
|
||||||
|
LANDING_SETTING_GROUPS,
|
||||||
|
isLandingContentKey,
|
||||||
|
landingSectionByPrefix,
|
||||||
|
matchesLandingPrefix
|
||||||
|
} from './landingSettings'
|
||||||
import {
|
import {
|
||||||
SETTING_TYPE_OPTIONS,
|
SETTING_TYPE_OPTIONS,
|
||||||
formatValueForSave,
|
formatValueForSave,
|
||||||
@@ -233,8 +239,9 @@ import {
|
|||||||
} from './settingTypes'
|
} from './settingTypes'
|
||||||
import { TRADING_HOURS_SETTING_KEY_SET } from './tradingHoursKeys'
|
import { TRADING_HOURS_SETTING_KEY_SET } from './tradingHoursKeys'
|
||||||
|
|
||||||
const props = withDefaults(defineProps<{ mode?: 'editable' | 'system' }>(), {
|
const props = withDefaults(defineProps<{ mode?: 'editable' | 'system' | 'landing'; landingPrefix?: string }>(), {
|
||||||
mode: 'editable'
|
mode: 'editable',
|
||||||
|
landingPrefix: ''
|
||||||
})
|
})
|
||||||
|
|
||||||
const userStore = useUserStore()
|
const userStore = useUserStore()
|
||||||
@@ -243,11 +250,24 @@ function refreshMenuAfterStoreChange() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const isSystemMode = computed(() => props.mode === 'system')
|
const isSystemMode = computed(() => props.mode === 'system')
|
||||||
const pageTitle = computed(() => (isSystemMode.value ? 'تنظیمات پیشرفته' : 'تنظیمات'))
|
const isLandingMode = computed(() => props.mode === 'landing')
|
||||||
|
const pageTitle = computed(() => {
|
||||||
|
if (isLandingMode.value) {
|
||||||
|
return landingSectionByPrefix(props.landingPrefix)?.title ?? 'تنظیمات وبسایت'
|
||||||
|
}
|
||||||
|
return isSystemMode.value ? 'تنظیمات پیشرفته' : 'تنظیمات'
|
||||||
|
})
|
||||||
|
const pageHelp = computed(() => (isLandingMode.value ? websiteSettingsPageIntro : configurationPageIntro))
|
||||||
const refreshingSuperAdmin = ref(false)
|
const refreshingSuperAdmin = ref(false)
|
||||||
const settingGroups = computed(() =>
|
const settingGroups = computed(() => {
|
||||||
isSystemMode.value ? SYSTEM_SETTING_GROUPS : EDITABLE_SETTING_GROUPS
|
if (isLandingMode.value) {
|
||||||
)
|
const prefix = props.landingPrefix || ''
|
||||||
|
return prefix
|
||||||
|
? LANDING_SETTING_GROUPS.filter((g) => g.id === prefix)
|
||||||
|
: LANDING_SETTING_GROUPS
|
||||||
|
}
|
||||||
|
return isSystemMode.value ? SYSTEM_SETTING_GROUPS : EDITABLE_SETTING_GROUPS
|
||||||
|
})
|
||||||
|
|
||||||
const settingTypeOptions = SETTING_TYPE_OPTIONS
|
const settingTypeOptions = SETTING_TYPE_OPTIONS
|
||||||
|
|
||||||
@@ -327,6 +347,13 @@ const filteredRows = computed(() =>
|
|||||||
(baseData.value || []).filter((row) => {
|
(baseData.value || []).filter((row) => {
|
||||||
if (row.id == null || !matchesFilter(row)) return false
|
if (row.id == null || !matchesFilter(row)) return false
|
||||||
if (!isSettingVisible(row.key)) return false
|
if (!isSettingVisible(row.key)) return false
|
||||||
|
if (isLandingMode.value) {
|
||||||
|
if (!isEditable(row)) return false
|
||||||
|
const prefix = props.landingPrefix || ''
|
||||||
|
if (prefix) return matchesLandingPrefix(row.key || '', prefix)
|
||||||
|
return isLandingContentKey(row.key)
|
||||||
|
}
|
||||||
|
if (isLandingContentKey(row.key)) return false
|
||||||
const menu = String(row.menu ?? '').trim()
|
const menu = String(row.menu ?? '').trim()
|
||||||
if (OTHER_PAGE_SETTING_MENUS.has(menu)) return false
|
if (OTHER_PAGE_SETTING_MENUS.has(menu)) return false
|
||||||
if (!menu && !isSystemMode.value && TRADING_HOURS_SETTING_KEY_SET.has(row.key || '')) {
|
if (!menu && !isSystemMode.value && TRADING_HOURS_SETTING_KEY_SET.has(row.key || '')) {
|
||||||
@@ -486,7 +513,7 @@ onMounted(() => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => props.mode,
|
() => [props.mode, props.landingPrefix],
|
||||||
() => {
|
() => {
|
||||||
search.value = ''
|
search.value = ''
|
||||||
filterType.value = undefined
|
filterType.value = undefined
|
||||||
@@ -608,6 +635,7 @@ async function initConfig() {
|
|||||||
applyPriceProviderFromRows(baseData.value)
|
applyPriceProviderFromRows(baseData.value)
|
||||||
applyPriceChannelAccessFromRows(baseData.value)
|
applyPriceChannelAccessFromRows(baseData.value)
|
||||||
applySupportChatMenuEnabledFromRows(baseData.value)
|
applySupportChatMenuEnabledFromRows(baseData.value)
|
||||||
|
applyHasLandingFromRows(baseData.value)
|
||||||
applyGroupSmsFromRows(baseData.value)
|
applyGroupSmsFromRows(baseData.value)
|
||||||
applyCustomerSpecialPricingFromRows(baseData.value)
|
applyCustomerSpecialPricingFromRows(baseData.value)
|
||||||
applyGoldCreditEnabledFromRows(baseData.value)
|
applyGoldCreditEnabledFromRows(baseData.value)
|
||||||
@@ -616,6 +644,7 @@ async function initConfig() {
|
|||||||
!isSystemMode.value ||
|
!isSystemMode.value ||
|
||||||
!baseData.value.some((row) => row.key === 'price_provider') ||
|
!baseData.value.some((row) => row.key === 'price_provider') ||
|
||||||
!baseData.value.some((row) => row.key === 'show_to_users_chat') ||
|
!baseData.value.some((row) => row.key === 'show_to_users_chat') ||
|
||||||
|
!baseData.value.some((row) => row.key === 'has_landing') ||
|
||||||
!baseData.value.some((row) => row.key === 'price_channel_access') ||
|
!baseData.value.some((row) => row.key === 'price_channel_access') ||
|
||||||
!baseData.value.some((row) => row.key === 'group_sms') ||
|
!baseData.value.some((row) => row.key === 'group_sms') ||
|
||||||
!baseData.value.some((row) => row.key === 'customer_special_pricing') ||
|
!baseData.value.some((row) => row.key === 'customer_special_pricing') ||
|
||||||
@@ -627,6 +656,7 @@ async function initConfig() {
|
|||||||
const rows = Array.isArray(all) ? all : []
|
const rows = Array.isArray(all) ? all : []
|
||||||
applyPriceProviderFromRows(rows)
|
applyPriceProviderFromRows(rows)
|
||||||
applySupportChatMenuEnabledFromRows(rows)
|
applySupportChatMenuEnabledFromRows(rows)
|
||||||
|
applyHasLandingFromRows(rows)
|
||||||
applyPriceChannelAccessFromRows(rows)
|
applyPriceChannelAccessFromRows(rows)
|
||||||
applyGroupSmsFromRows(rows)
|
applyGroupSmsFromRows(rows)
|
||||||
applyCustomerSpecialPricingFromRows(rows)
|
applyCustomerSpecialPricingFromRows(rows)
|
||||||
@@ -701,6 +731,14 @@ function syncMenuFlagsFromSetting(key: string | undefined, value: string) {
|
|||||||
if (row) row.value = value
|
if (row) row.value = value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (key === 'has_landing') {
|
||||||
|
setHasLandingFromSettings(isSwitchOn(value))
|
||||||
|
const list = userStore.userInfo?.settings
|
||||||
|
if (Array.isArray(list)) {
|
||||||
|
const row = list.find((s: any) => s?.key === key)
|
||||||
|
if (row) row.value = value
|
||||||
|
}
|
||||||
|
}
|
||||||
if (key === 'price_channel_access') {
|
if (key === 'price_channel_access') {
|
||||||
setPriceChannelAccessFromSettings(isSwitchOn(value))
|
setPriceChannelAccessFromSettings(isSwitchOn(value))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
export type LandingSection = {
|
||||||
|
prefix: string
|
||||||
|
title: string
|
||||||
|
icon: string
|
||||||
|
name: string
|
||||||
|
path: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export const LANDING_SETTING_SECTIONS: LandingSection[] = [
|
||||||
|
{ prefix: 'landing_site', title: 'تنظیمات کلی سایت', icon: 'vuesax-linear:global', name: 'websiteLandingSite', path: 'site' },
|
||||||
|
{ prefix: 'landing_header', title: 'هدر و ناوبری', icon: 'vuesax-linear:menu', name: 'websiteLandingHeader', path: 'header' },
|
||||||
|
{ prefix: 'landing_hero', title: 'هیرو', icon: 'vuesax-linear:image', name: 'websiteLandingHero', path: 'hero' },
|
||||||
|
{ prefix: 'landing_live_price', title: 'لیبلهای قیمت لحظهای', icon: 'vuesax-linear:chart-2', name: 'websiteLandingLivePrice', path: 'live-price' },
|
||||||
|
{ prefix: 'landing_calculator', title: 'عنوان ماشین حساب', icon: 'vuesax-linear:calculator', name: 'websiteLandingCalculator', path: 'calculator' },
|
||||||
|
{ prefix: 'landing_feature', title: 'امکانات (چرا نیازی طلا)', icon: 'vuesax-linear:star', name: 'websiteLandingFeature', path: 'feature' },
|
||||||
|
{ prefix: 'landing_steps', title: 'مراحل شروع', icon: 'vuesax-linear:ranking', name: 'websiteLandingSteps', path: 'steps' },
|
||||||
|
{ prefix: 'landing_trust', title: 'اعتماد و مجوزها', icon: 'vuesax-linear:shield-tick', name: 'websiteLandingTrust', path: 'trust' },
|
||||||
|
{ prefix: 'landing_faq', title: 'سوالات متداول', icon: 'vuesax-linear:message-question', name: 'websiteLandingFaq', path: 'faq' },
|
||||||
|
{ prefix: 'landing_buttom_cta', title: 'سکشن پایین صفحه لندینگ برای معرفی', icon: 'vuesax-linear:arrow-down', name: 'websiteLandingBottomCta', path: 'bottom-cta' },
|
||||||
|
{ prefix: 'landing_footer', title: 'فوتر', icon: 'vuesax-linear:document', name: 'websiteLandingFooter', path: 'footer' }
|
||||||
|
]
|
||||||
|
|
||||||
|
export function matchesLandingPrefix(key: string, prefix: string): boolean {
|
||||||
|
return key === prefix || key.startsWith(`${prefix}_`)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isLandingContentKey(key?: string | null): boolean {
|
||||||
|
return String(key ?? '').trim().startsWith('landing_')
|
||||||
|
}
|
||||||
|
|
||||||
|
export function landingSectionByPrefix(prefix: string): LandingSection | undefined {
|
||||||
|
return LANDING_SETTING_SECTIONS.find((s) => s.prefix === prefix)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const LANDING_SETTING_GROUPS = LANDING_SETTING_SECTIONS.map((section) => ({
|
||||||
|
id: section.prefix,
|
||||||
|
title: section.title,
|
||||||
|
icon: section.icon,
|
||||||
|
match: (key: string) => matchesLandingPrefix(key, section.prefix)
|
||||||
|
}))
|
||||||
@@ -158,7 +158,7 @@ export const SYSTEM_SETTING_GROUPS: SettingGroupDef[] = [
|
|||||||
icon: 'vuesax-linear:people',
|
icon: 'vuesax-linear:people',
|
||||||
// فقط فلگهای مالک سوپرادمین — banner/tracking/نمایش محصول در «تنظیمات» عادیاند
|
// فقط فلگهای مالک سوپرادمین — banner/tracking/نمایش محصول در «تنظیمات» عادیاند
|
||||||
match: (k) =>
|
match: (k) =>
|
||||||
/^(enable_automation|enable_conditional_order|enable_product_funds|has_page_price_trigger|has_page_notification|has_page_gift_card|enable_customer_level_profit|jibit_enabled|customer_direct_sms|has_page_earn_money|group_sms|customer_special_pricing|enable_gold_credit|permision__enabled|show_to_users_chat)$/.test(
|
/^(enable_automation|enable_conditional_order|enable_product_funds|has_page_price_trigger|has_page_notification|has_page_gift_card|enable_customer_level_profit|jibit_enabled|customer_direct_sms|has_page_earn_money|group_sms|customer_special_pricing|enable_gold_credit|permision__enabled|show_to_users_chat|has_landing)$/.test(
|
||||||
k
|
k
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
@@ -310,7 +310,7 @@ export function resolveSettingMenu(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** این کلیدها صفحهٔ جدا دارند و در لیست تنظیمات عادی/پیشرفته نمیآیند */
|
/** این کلیدها صفحهٔ جدا دارند و در لیست تنظیمات عادی/پیشرفته نمیآیند */
|
||||||
export const OTHER_PAGE_SETTING_MENUS = new Set(['trading_hours', 'capture_sites'])
|
export const OTHER_PAGE_SETTING_MENUS = new Set(['trading_hours', 'capture_sites', 'website_settings'])
|
||||||
|
|
||||||
export function getSettingSubsectionId(
|
export function getSettingSubsectionId(
|
||||||
key: string,
|
key: string,
|
||||||
|
|||||||
@@ -207,6 +207,7 @@ export const SUPERADMIN_OWNED_SETTING_KEYS = new Set([
|
|||||||
'jibit_enabled',
|
'jibit_enabled',
|
||||||
'permision__enabled',
|
'permision__enabled',
|
||||||
'show_to_users_chat',
|
'show_to_users_chat',
|
||||||
|
'has_landing',
|
||||||
])
|
])
|
||||||
|
|
||||||
export function isSuperAdminOwnedSettingKey(key?: string | null): boolean {
|
export function isSuperAdminOwnedSettingKey(key?: string | null): boolean {
|
||||||
@@ -324,7 +325,7 @@ const KEY_TYPE_FALLBACK: Record<string, SettingFieldType> = {
|
|||||||
minimum_sell: 'price',
|
minimum_sell: 'price',
|
||||||
gift_for_referrer: 'number',
|
gift_for_referrer: 'number',
|
||||||
gift_for_referral: 'number',
|
gift_for_referral: 'number',
|
||||||
referral_bonus_amount: 'text',
|
referral_bonus_amount: 'price',
|
||||||
montzar_product_id: 'number',
|
montzar_product_id: 'number',
|
||||||
montzar_account_zarin: 'text',
|
montzar_account_zarin: 'text',
|
||||||
montzar_account_tahesab: 'text',
|
montzar_account_tahesab: 'text',
|
||||||
@@ -429,7 +430,19 @@ const KEY_TYPE_FALLBACK: Record<string, SettingFieldType> = {
|
|||||||
pargar_item_id_gold: 'number',
|
pargar_item_id_gold: 'number',
|
||||||
support_messengers: 'longtext',
|
support_messengers: 'longtext',
|
||||||
show_to_users_chat: 'switch',
|
show_to_users_chat: 'switch',
|
||||||
|
has_landing: 'switch',
|
||||||
has_chat: 'switch',
|
has_chat: 'switch',
|
||||||
|
landing_site: 'longtext',
|
||||||
|
landing_header: 'longtext',
|
||||||
|
landing_hero: 'longtext',
|
||||||
|
landing_live_price: 'longtext',
|
||||||
|
landing_calculator: 'longtext',
|
||||||
|
landing_feature: 'longtext',
|
||||||
|
landing_steps: 'longtext',
|
||||||
|
landing_trust: 'longtext',
|
||||||
|
landing_faq: 'longtext',
|
||||||
|
landing_buttom_cta: 'longtext',
|
||||||
|
landing_footer: 'longtext',
|
||||||
chat_api: 'text',
|
chat_api: 'text',
|
||||||
chat_api_key: 'text',
|
chat_api_key: 'text',
|
||||||
chat_upload_url: 'text',
|
chat_upload_url: 'text',
|
||||||
@@ -623,6 +636,45 @@ export function formatValueForSave(
|
|||||||
return value ?? ''
|
return value ?? ''
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** واحد نمایش روی فیلدهای عددی — شناسه/پورت واحد ندارند */
|
||||||
|
const SETTING_UNIT_BY_KEY: Record<string, string> = {
|
||||||
|
buy_fee: 'ریال',
|
||||||
|
sell_fee: 'ریال',
|
||||||
|
fee_single: 'ریال',
|
||||||
|
fee_conditional_order: 'ریال',
|
||||||
|
min_withdraw: 'ریال',
|
||||||
|
min_deposit: 'ریال',
|
||||||
|
min_first_buy: 'ریال',
|
||||||
|
minimum_sell: 'ریال',
|
||||||
|
price_channel_diff: 'ریال',
|
||||||
|
referral_bonus_amount: 'ریال',
|
||||||
|
gold_credit_penalty_amount: 'ریال / گرم',
|
||||||
|
gift_for_referrer: 'گرم',
|
||||||
|
gift_for_referral: 'گرم',
|
||||||
|
gold_credit_min_balance_gram: 'گرم',
|
||||||
|
change_mesghal: 'گرم',
|
||||||
|
fee_service_charge_percentage: 'درصد (اعشاری)',
|
||||||
|
gold_credit_grace_hours: 'ساعت',
|
||||||
|
gold_credit_default_months: 'ماه',
|
||||||
|
price_channel_min_seconds: 'ثانیه',
|
||||||
|
referral_limit: 'دعوت',
|
||||||
|
fee_free: 'سفارش',
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getSettingUnitLabel(
|
||||||
|
key?: string,
|
||||||
|
type?: SettingFieldType,
|
||||||
|
): string {
|
||||||
|
const k = (key ?? '').trim()
|
||||||
|
if (k && SETTING_UNIT_BY_KEY[k]) {
|
||||||
|
return SETTING_UNIT_BY_KEY[k]
|
||||||
|
}
|
||||||
|
if (type === 'price') {
|
||||||
|
return 'ریال'
|
||||||
|
}
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
|
||||||
export function switchLabels(key: string | undefined): { on: string; off: string } {
|
export function switchLabels(key: string | undefined): { on: string; off: string } {
|
||||||
if (key === REFERRAL_REQUIRED_KEY) {
|
if (key === REFERRAL_REQUIRED_KEY) {
|
||||||
return { on: 'اجباری', off: 'اختیاری' }
|
return { on: 'اجباری', off: 'اختیاری' }
|
||||||
@@ -800,7 +852,7 @@ const KEY_HELP_FALLBACK: Record<string, string> = {
|
|||||||
referral_limit:
|
referral_limit:
|
||||||
'حداکثر تعداد دعوت مجاز برای هر کاربر. خالی = بدون محدودیت.',
|
'حداکثر تعداد دعوت مجاز برای هر کاربر. خالی = بدون محدودیت.',
|
||||||
referral_bonus_amount:
|
referral_bonus_amount:
|
||||||
'مبلغ یا مقدار پاداش معرف برای نمایش در پیامکها و متنهای دعوت.',
|
'مبلغ پاداش معرف (ریال) برای نمایش در پیامکها و متنهای دعوت. واحد روی خود فیلد مشخص است.',
|
||||||
jibit_verification:
|
jibit_verification:
|
||||||
'روشن: هنگام ثبت یا ویرایش کارت بانکی، تطبیق با سرویس احراز هویت جیبیت انجام میشود. خاموش: کارت بدون تطبیق جیبیت ثبت میشود.',
|
'روشن: هنگام ثبت یا ویرایش کارت بانکی، تطبیق با سرویس احراز هویت جیبیت انجام میشود. خاموش: کارت بدون تطبیق جیبیت ثبت میشود.',
|
||||||
register_jibit_verify:
|
register_jibit_verify:
|
||||||
@@ -863,6 +915,19 @@ const KEY_HELP_FALLBACK: Record<string, string> = {
|
|||||||
'فقط مواردی که در این لیست ثبت شوند در منوی شناور پشتیبانی اپ مشتری نمایش داده میشوند. برای تماس تلفنی یا پیامک، نوع «تماس تلفنی» / «پیامک» را با شماره اضافه کنید. لیست میتواند خالی باشد؛ اگر چت فعال باشد، پشتیبانی مستقیم به صفحه چت میرود.',
|
'فقط مواردی که در این لیست ثبت شوند در منوی شناور پشتیبانی اپ مشتری نمایش داده میشوند. برای تماس تلفنی یا پیامک، نوع «تماس تلفنی» / «پیامک» را با شماره اضافه کنید. لیست میتواند خالی باشد؛ اگر چت فعال باشد، پشتیبانی مستقیم به صفحه چت میرود.',
|
||||||
show_to_users_chat:
|
show_to_users_chat:
|
||||||
'روشن: قابلیت چت پشتیبانی برای این دیپلوی فعال است (منوی ادمین و پیشنیاز نمایش به کاربر). خاموش: چت در ادمین و اپ کاربر مخفی است و سوییچ «چت پشتیبانی» (has_chat) از تنظیمات عادی هم برداشته میشود.',
|
'روشن: قابلیت چت پشتیبانی برای این دیپلوی فعال است (منوی ادمین و پیشنیاز نمایش به کاربر). خاموش: چت در ادمین و اپ کاربر مخفی است و سوییچ «چت پشتیبانی» (has_chat) از تنظیمات عادی هم برداشته میشود.',
|
||||||
|
has_landing:
|
||||||
|
'روشن: منوی تنظیمات وبسایت در ادمین و تنظیمات لندینگ برای اپ کاربر فعال است. خاموش: منو مخفی است.',
|
||||||
|
landing_site: 'محتوای تنظیمات کلی لندینگ وبسایت.',
|
||||||
|
landing_header: 'محتوای هدر و ناوبری لندینگ.',
|
||||||
|
landing_hero: 'محتوای سکشن هیرو لندینگ.',
|
||||||
|
landing_live_price: 'لیبلها و متن قیمت لحظهای لندینگ.',
|
||||||
|
landing_calculator: 'عنوان و متن ماشین حساب لندینگ.',
|
||||||
|
landing_feature: 'متن امکانات لندینگ (چرا نیازی طلا).',
|
||||||
|
landing_steps: 'متن مراحل شروع لندینگ.',
|
||||||
|
landing_trust: 'متن اعتماد و مجوزها (بدون اینماد).',
|
||||||
|
landing_faq: 'سوالات متداول لندینگ.',
|
||||||
|
landing_buttom_cta: 'متن دعوت به اقدام پایین صفحه لندینگ.',
|
||||||
|
landing_footer: 'محتوای فوتر لندینگ.',
|
||||||
has_chat:
|
has_chat:
|
||||||
'روشن: چت پشتیبانی در اپ مشتری نمایش داده میشود (فقط وقتی show_to_users_chat هم روشن باشد). خاموش: دکمه و صفحه چت برای کاربر مخفی است.',
|
'روشن: چت پشتیبانی در اپ مشتری نمایش داده میشود (فقط وقتی show_to_users_chat هم روشن باشد). خاموش: دکمه و صفحه چت برای کاربر مخفی است.',
|
||||||
chat_api:
|
chat_api:
|
||||||
@@ -1119,6 +1184,8 @@ export const KEY_LABEL_FALLBACK: Record<string, string> = {
|
|||||||
minimum_sell: 'حداقل مبلغ فروش (ریال)',
|
minimum_sell: 'حداقل مبلغ فروش (ریال)',
|
||||||
referral_id: 'کد معرف اجباری',
|
referral_id: 'کد معرف اجباری',
|
||||||
referral_bonus_amount: 'مقدار پاداش معرف',
|
referral_bonus_amount: 'مقدار پاداش معرف',
|
||||||
|
gift_for_referrer: 'پاداش معرف',
|
||||||
|
gift_for_referral: 'پاداش معرفشونده',
|
||||||
referral_gift_on_first_order: 'پاداش معرف پس از اولین سفارش',
|
referral_gift_on_first_order: 'پاداش معرف پس از اولین سفارش',
|
||||||
referral_gift_buy_from_montzar: 'خرید پاداش معرفی از همکار',
|
referral_gift_buy_from_montzar: 'خرید پاداش معرفی از همکار',
|
||||||
open_register: 'ثبتنام باز',
|
open_register: 'ثبتنام باز',
|
||||||
@@ -1187,7 +1254,19 @@ export const KEY_LABEL_FALLBACK: Record<string, string> = {
|
|||||||
zarin_idbank: 'کد حساب بانک زرین',
|
zarin_idbank: 'کد حساب بانک زرین',
|
||||||
support_messengers: 'پیامرسانهای پشتیبانی',
|
support_messengers: 'پیامرسانهای پشتیبانی',
|
||||||
show_to_users_chat: 'نمایش چت به کاربران',
|
show_to_users_chat: 'نمایش چت به کاربران',
|
||||||
|
has_landing: 'لندینگ وبسایت',
|
||||||
has_chat: 'چت پشتیبانی',
|
has_chat: 'چت پشتیبانی',
|
||||||
|
landing_site: 'تنظیمات کلی سایت',
|
||||||
|
landing_header: 'هدر و ناوبری',
|
||||||
|
landing_hero: 'هیرو',
|
||||||
|
landing_live_price: 'لیبلهای قیمت لحظهای',
|
||||||
|
landing_calculator: 'عنوان ماشین حساب',
|
||||||
|
landing_feature: 'امکانات (چرا نیازی طلا)',
|
||||||
|
landing_steps: 'مراحل شروع',
|
||||||
|
landing_trust: 'اعتماد و مجوزها',
|
||||||
|
landing_faq: 'سوالات متداول',
|
||||||
|
landing_buttom_cta: 'سکشن پایین صفحه لندینگ برای معرفی',
|
||||||
|
landing_footer: 'فوتر',
|
||||||
chat_api: 'API چت',
|
chat_api: 'API چت',
|
||||||
chat_api_key: 'کلید API چت',
|
chat_api_key: 'کلید API چت',
|
||||||
chat_upload_url: 'آدرس آپلود فایل چت',
|
chat_upload_url: 'آدرس آپلود فایل چت',
|
||||||
@@ -1286,7 +1365,7 @@ export const SETTING_LOCKED_KEYS = new Set([
|
|||||||
'price_channel_bale_to', 'price_channel_telegram_to', 'price_channel_rubika_to',
|
'price_channel_bale_to', 'price_channel_telegram_to', 'price_channel_rubika_to',
|
||||||
'unit',
|
'unit',
|
||||||
'wss_enabled',
|
'wss_enabled',
|
||||||
'show_to_users_chat', 'chat_api', 'chat_api_key', 'chat_upload_url', 'chat_download_url'
|
'show_to_users_chat', 'has_landing', 'chat_api', 'chat_api_key', 'chat_upload_url', 'chat_download_url'
|
||||||
])
|
])
|
||||||
|
|
||||||
/** قابل ویرایش در پنل عادی — همتراز deploy_settings_const.sql */
|
/** قابل ویرایش در پنل عادی — همتراز deploy_settings_const.sql */
|
||||||
@@ -1326,6 +1405,8 @@ export const SETTING_EDITABLE_KEYS = new Set([
|
|||||||
'support_messengers', 'support_messenger_text',
|
'support_messengers', 'support_messenger_text',
|
||||||
'do_send_liman',
|
'do_send_liman',
|
||||||
'has_chat',
|
'has_chat',
|
||||||
|
'landing_site', 'landing_header', 'landing_hero', 'landing_live_price', 'landing_calculator',
|
||||||
|
'landing_feature', 'landing_steps', 'landing_trust', 'landing_faq', 'landing_buttom_cta', 'landing_footer',
|
||||||
'text_about', 'text_rule', 'about_software', 'enamad_url', 'enamad_logo',
|
'text_about', 'text_rule', 'about_software', 'enamad_url', 'enamad_logo',
|
||||||
'login_hero_eyebrow', 'login_hero_title',
|
'login_hero_eyebrow', 'login_hero_title',
|
||||||
'login_hero_feature_1', 'login_hero_feature_2', 'login_hero_feature_3', 'login_hero_feature_4',
|
'login_hero_feature_1', 'login_hero_feature_2', 'login_hero_feature_3', 'login_hero_feature_4',
|
||||||
@@ -1336,10 +1417,14 @@ export const SETTING_EDITABLE_KEYS = new Set([
|
|||||||
])
|
])
|
||||||
|
|
||||||
/** عنوان فارسی — کاتالوگ پنل بر title_fa دیتابیس اولویت دارد */
|
/** عنوان فارسی — کاتالوگ پنل بر title_fa دیتابیس اولویت دارد */
|
||||||
export function resolveSettingTitle(row: Pick<Const, 'key' | 'title_fa'>): string {
|
export function resolveSettingTitle(row: Pick<Const, 'key' | 'title_fa' | 'type'>): string {
|
||||||
const key = (row.key ?? '').trim()
|
const key = (row.key ?? '').trim()
|
||||||
if (key && KEY_LABEL_FALLBACK[key]) return KEY_LABEL_FALLBACK[key]
|
const base = (key && KEY_LABEL_FALLBACK[key]) ? KEY_LABEL_FALLBACK[key] : (row.title_fa?.trim() || key || '—')
|
||||||
return row.title_fa?.trim() || key || '—'
|
const unit = getSettingUnitLabel(key, resolveSettingFieldType(row))
|
||||||
|
if (!unit || base.includes(unit) || base.includes(`(${unit})`)) {
|
||||||
|
return base
|
||||||
|
}
|
||||||
|
return `${base} (${unit})`
|
||||||
}
|
}
|
||||||
|
|
||||||
/** توضیح — کاتالوگ پنل بر description دیتابیس اولویت دارد */
|
/** توضیح — کاتالوگ پنل بر description دیتابیس اولویت دارد */
|
||||||
|
|||||||
@@ -0,0 +1,63 @@
|
|||||||
|
<template>
|
||||||
|
<div class="website-settings">
|
||||||
|
<BasicMainCard>
|
||||||
|
<div class="flex h-full min-h-0 flex-col md:flex-row">
|
||||||
|
<BasicMenu
|
||||||
|
width="100%"
|
||||||
|
:menu="menu"
|
||||||
|
mode="horizontal"
|
||||||
|
class="website-settings__menu website-settings__menu--mobile overflow-auto md:hidden"
|
||||||
|
/>
|
||||||
|
<BasicMenu
|
||||||
|
width="17rem"
|
||||||
|
:menu="menu"
|
||||||
|
class="website-settings__menu website-settings__menu--side hidden min-w-[17rem] overflow-auto md:inline"
|
||||||
|
/>
|
||||||
|
<RouterView
|
||||||
|
:key="route.name"
|
||||||
|
class="mt-5 min-h-0 w-full flex-1 overflow-hidden md:mr-5 md:mt-0"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</BasicMainCard>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { computed } from 'vue'
|
||||||
|
import { useRoute } from 'vue-router'
|
||||||
|
import BasicMenu from '@/components/BasicMenu/index.vue'
|
||||||
|
import { useRouterStore } from '@core/stores/router'
|
||||||
|
import { get } from 'lodash'
|
||||||
|
import type { RouteRecordRaw } from 'vue-router'
|
||||||
|
|
||||||
|
const routerStore = useRouterStore()
|
||||||
|
const route = useRoute()
|
||||||
|
|
||||||
|
const menu = computed(() => {
|
||||||
|
const item = routerStore.routes.find((row) => row.name === 'websiteSettings')
|
||||||
|
const children = get(item, 'children[0].children', []) as RouteRecordRaw[]
|
||||||
|
return children
|
||||||
|
.filter((child) => !child.meta?.hideMenu)
|
||||||
|
.sort((a, b) => (Number(a.meta?.order) || 99) - (Number(b.meta?.order) || 99))
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="less">
|
||||||
|
.website-settings__menu {
|
||||||
|
:deep(.ant-menu-item),
|
||||||
|
:deep(.ant-menu-submenu-title) {
|
||||||
|
height: auto !important;
|
||||||
|
min-height: 2.5rem;
|
||||||
|
line-height: 1.35 !important;
|
||||||
|
white-space: normal !important;
|
||||||
|
padding-block: 0.55rem !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.ant-menu-title-content) {
|
||||||
|
white-space: normal !important;
|
||||||
|
overflow: visible !important;
|
||||||
|
text-overflow: clip !important;
|
||||||
|
line-height: 1.35;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
import type { RouteRecordRaw } from 'vue-router'
|
||||||
|
import { hasLandingSetting } from '@/utils/config'
|
||||||
|
import { LANDING_SETTING_SECTIONS } from '@/pages/menuPages/configuration/landingSettings'
|
||||||
|
|
||||||
|
const websiteSettings: RouteRecordRaw = {
|
||||||
|
name: 'websiteSettings',
|
||||||
|
path: '/website-settings',
|
||||||
|
component: () => import('@core/layouts/BasicLayout.vue'),
|
||||||
|
redirect: { name: 'websiteLandingSite' },
|
||||||
|
meta: {
|
||||||
|
icon: 'vuesax-linear:global',
|
||||||
|
permissionsKey: 'config',
|
||||||
|
title: 'تنظیمات وبسایت',
|
||||||
|
disabled: false,
|
||||||
|
hideMenu: false,
|
||||||
|
hideChildren: true,
|
||||||
|
order: 7.4
|
||||||
|
},
|
||||||
|
beforeEnter() {
|
||||||
|
if (!hasLandingSetting.value) {
|
||||||
|
return { name: 'configuration' }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
name: 'websiteSettingsMain',
|
||||||
|
path: '',
|
||||||
|
component: () => import('@/pages/menuPages/websiteSettings/index.vue'),
|
||||||
|
redirect: { name: 'websiteLandingSite' },
|
||||||
|
meta: {
|
||||||
|
permissionsKey: 'config',
|
||||||
|
icon: 'vuesax-linear:global',
|
||||||
|
title: 'تنظیمات وبسایت',
|
||||||
|
disabled: false,
|
||||||
|
hideMenu: true
|
||||||
|
},
|
||||||
|
children: LANDING_SETTING_SECTIONS.map((section, index) => ({
|
||||||
|
name: section.name,
|
||||||
|
path: section.path,
|
||||||
|
component: () => import('@/pages/menuPages/configuration/index.vue'),
|
||||||
|
props: { mode: 'landing' as const, landingPrefix: section.prefix },
|
||||||
|
meta: {
|
||||||
|
icon: section.icon,
|
||||||
|
title: section.title,
|
||||||
|
order: index + 1
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
export default websiteSettings
|
||||||
@@ -246,6 +246,9 @@ export const captureSitesPageIntro =
|
|||||||
export const configurationPageIntro =
|
export const configurationPageIntro =
|
||||||
'تنظیمات کلی سامانه (کلید–مقدار). با جستجو و فیلتر نوع فیلد، مورد را پیدا کنید؛ بعد از تغییر ذخیره کنید. روی آیکون i کنار هر تنظیم توضیح همان فیلد را ببینید.'
|
'تنظیمات کلی سامانه (کلید–مقدار). با جستجو و فیلتر نوع فیلد، مورد را پیدا کنید؛ بعد از تغییر ذخیره کنید. روی آیکون i کنار هر تنظیم توضیح همان فیلد را ببینید.'
|
||||||
|
|
||||||
|
export const websiteSettingsPageIntro =
|
||||||
|
'متن و تنظیمات صفحهٔ لندینگ وبسایت. هر زیرمنو کلیدهای همان بخش را نشان میدهد؛ بعد از تغییر ذخیره میشود و در اپ کاربر با get_settings در دسترس است.'
|
||||||
|
|
||||||
export const accountingReportsPageIntro =
|
export const accountingReportsPageIntro =
|
||||||
'گزارشهای حسابداری داخلی پنل. برای اسناد و همگامسازی مشتریان از تبهای تهحساب / زرین / پرگار استفاده کنید.'
|
'گزارشهای حسابداری داخلی پنل. برای اسناد و همگامسازی مشتریان از تبهای تهحساب / زرین / پرگار استفاده کنید.'
|
||||||
|
|
||||||
|
|||||||
+17
-1
@@ -86,6 +86,9 @@ export const supportChatMenuEnabledSetting = ref(false)
|
|||||||
/** reactive — سوییچ دیپلوی show_to_users_chat (برای مخفی کردن has_chat در تنظیمات عادی) */
|
/** reactive — سوییچ دیپلوی show_to_users_chat (برای مخفی کردن has_chat در تنظیمات عادی) */
|
||||||
export const showToUsersChatSetting = ref(false)
|
export const showToUsersChatSetting = ref(false)
|
||||||
|
|
||||||
|
/** reactive — منوی تنظیمات وبسایت وقتی has_landing روشن است */
|
||||||
|
export const hasLandingSetting = ref(false)
|
||||||
|
|
||||||
/** reactive — سوییچ دیپلوی price_channel_access (گروه کانال در تنظیمات عادی) */
|
/** reactive — سوییچ دیپلوی price_channel_access (گروه کانال در تنظیمات عادی) */
|
||||||
export const priceChannelAccessSetting = ref(false)
|
export const priceChannelAccessSetting = ref(false)
|
||||||
|
|
||||||
@@ -215,6 +218,10 @@ export function setShowToUsersChatFromSettings(value: boolean): void {
|
|||||||
showToUsersChatSetting.value = value
|
showToUsersChatSetting.value = value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function setHasLandingFromSettings(value: boolean): void {
|
||||||
|
hasLandingSetting.value = value
|
||||||
|
}
|
||||||
|
|
||||||
export function setPriceChannelAccessFromSettings(value: boolean): void {
|
export function setPriceChannelAccessFromSettings(value: boolean): void {
|
||||||
priceChannelAccessSetting.value = value
|
priceChannelAccessSetting.value = value
|
||||||
}
|
}
|
||||||
@@ -313,7 +320,7 @@ export function invalidateSettingsBootstrap(): void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* اعمال مستقیم ۱۵ دسترسی سوپرادمین روی فلگهای منو/UI
|
* اعمال مستقیم ۱۶ دسترسی سوپرادمین روی فلگهای منو/UI
|
||||||
* (پاسخ refresh-superadmin.items یا ردیفهای get_settings).
|
* (پاسخ refresh-superadmin.items یا ردیفهای get_settings).
|
||||||
*/
|
*/
|
||||||
export function applySuperAdminAccessFlagsFromItems(
|
export function applySuperAdminAccessFlagsFromItems(
|
||||||
@@ -333,6 +340,7 @@ export function applySuperAdminAccessFlagsFromItems(
|
|||||||
applyPriceTriggerEnabledFromRows(rows)
|
applyPriceTriggerEnabledFromRows(rows)
|
||||||
applyAppNotificationEnabledFromRows(rows)
|
applyAppNotificationEnabledFromRows(rows)
|
||||||
applySupportChatMenuEnabledFromRows(rows)
|
applySupportChatMenuEnabledFromRows(rows)
|
||||||
|
applyHasLandingFromRows(rows)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function applyConditionalOrderEnabledFromRows(
|
export function applyConditionalOrderEnabledFromRows(
|
||||||
@@ -377,6 +385,13 @@ export function applyAppNotificationEnabledFromRows(
|
|||||||
if (row) setAppNotificationEnabledFromSettings(isSwitchOn(row.value))
|
if (row) setAppNotificationEnabledFromSettings(isSwitchOn(row.value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function applyHasLandingFromRows(
|
||||||
|
rows: Array<{ key?: string; value?: string | null }>
|
||||||
|
) {
|
||||||
|
const row = rows.find((item) => item.key === 'has_landing')
|
||||||
|
if (row) setHasLandingFromSettings(isSwitchOn(row.value))
|
||||||
|
}
|
||||||
|
|
||||||
export function applyPriceProviderFromRows(
|
export function applyPriceProviderFromRows(
|
||||||
rows: Array<{ key?: string; value?: string | null }>
|
rows: Array<{ key?: string; value?: string | null }>
|
||||||
) {
|
) {
|
||||||
@@ -419,6 +434,7 @@ async function bootstrapSettingsFromApi(): Promise<void> {
|
|||||||
applyPriceTriggerEnabledFromRows(list)
|
applyPriceTriggerEnabledFromRows(list)
|
||||||
applyAppNotificationEnabledFromRows(list)
|
applyAppNotificationEnabledFromRows(list)
|
||||||
applySupportChatMenuEnabledFromRows(list)
|
applySupportChatMenuEnabledFromRows(list)
|
||||||
|
applyHasLandingFromRows(list)
|
||||||
applyPriceProviderFromRows(list)
|
applyPriceProviderFromRows(list)
|
||||||
applyPriceChannelAccessFromRows(list)
|
applyPriceChannelAccessFromRows(list)
|
||||||
setCachedMainMetal(mainMetalRow?.value)
|
setCachedMainMetal(mainMetalRow?.value)
|
||||||
|
|||||||
Reference in New Issue
Block a user