fix moshtari code
This commit is contained in:
+38
-30
@@ -6,6 +6,8 @@ import {
|
||||
LEGACY_SLIDER_BANNERS_CONST_KEY,
|
||||
LEGACY_THEME_BANNERS_CONST_KEY,
|
||||
emptyAppBanners,
|
||||
isThemeBannersEmpty,
|
||||
mergeAppBannersFromLegacy,
|
||||
parseAppBanners,
|
||||
serializeAppBanners,
|
||||
type AppBannersValue,
|
||||
@@ -51,6 +53,8 @@ export type AppBannersConstState = {
|
||||
/** فقط وقتی رکورد واقعاً با key=app_banners است؛ وگرنه null تا create شود */
|
||||
id: number | null
|
||||
data: AppBannersValue
|
||||
/** از settings_profile_banners پر شده — بهتر است یکبار ذخیره شود */
|
||||
healedFromLegacy?: boolean
|
||||
}
|
||||
|
||||
async function loadLegacySliderInto(merged: AppBannersValue): Promise<void> {
|
||||
@@ -67,9 +71,22 @@ async function loadLegacySliderInto(merged: AppBannersValue): Promise<void> {
|
||||
}
|
||||
}
|
||||
|
||||
async function loadLegacyThemeBanners(): Promise<AppBannersValue> {
|
||||
try {
|
||||
const themeRes = await useAxios.get<Const | Const[]>(
|
||||
`/api/const/key/${LEGACY_THEME_BANNERS_CONST_KEY}`
|
||||
)
|
||||
const themeRow = pickConstRow(themeRes)
|
||||
if (!themeRow) return emptyAppBanners()
|
||||
return parseAppBanners(themeRow.value)
|
||||
} catch {
|
||||
return emptyAppBanners()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* یک API واحد برای همهٔ بنرها.
|
||||
* اگر `app_banners` نبود یا اسلایدر خالی بود، از کلیدهای قدیمی migrate میکند (فقط خواندن).
|
||||
* اگر `app_banners` نبود یا اسلاتهای تم خالی بود، از settings_profile_banners پر میکند.
|
||||
*/
|
||||
export async function loadAppBannersConst(): Promise<AppBannersConstState> {
|
||||
let appRow: Const | null = null
|
||||
@@ -81,44 +98,36 @@ export async function loadAppBannersConst(): Promise<AppBannersConstState> {
|
||||
}
|
||||
|
||||
if (appRow) {
|
||||
const data = parseAppBanners(appRow.value)
|
||||
// رکورد جدید خالی: اسلایدر را از header_banner پر کن
|
||||
if (!data.slider.length) {
|
||||
await loadLegacySliderInto(data)
|
||||
let data = parseAppBanners(appRow.value)
|
||||
let healedFromLegacy = false
|
||||
|
||||
// رکورد پوچ app_banners روی URLهای واقعی legacy سایه نیندازد
|
||||
if (isThemeBannersEmpty(data) || !data.slider.length) {
|
||||
const before = serializeAppBanners(data)
|
||||
if (isThemeBannersEmpty(data)) {
|
||||
const legacyTheme = await loadLegacyThemeBanners()
|
||||
data = mergeAppBannersFromLegacy(data, legacyTheme)
|
||||
}
|
||||
if (!data.slider.length) {
|
||||
await loadLegacySliderInto(data)
|
||||
}
|
||||
healedFromLegacy = serializeAppBanners(data) !== before
|
||||
}
|
||||
|
||||
return {
|
||||
id: appRow.id ?? appRow.const_id ?? null,
|
||||
data,
|
||||
healedFromLegacy,
|
||||
}
|
||||
}
|
||||
|
||||
const merged = emptyAppBanners()
|
||||
|
||||
try {
|
||||
const themeRes = await useAxios.get<Const | Const[]>(
|
||||
`/api/const/key/${LEGACY_THEME_BANNERS_CONST_KEY}`
|
||||
)
|
||||
const themeRow = pickConstRow(themeRes)
|
||||
if (themeRow) {
|
||||
const themes = parseAppBanners(themeRow.value)
|
||||
Object.assign(merged, {
|
||||
homeAsset: themes.homeAsset,
|
||||
piggyCreate: themes.piggyCreate,
|
||||
productsHero: themes.productsHero?.length ? themes.productsHero : merged.productsHero,
|
||||
referral: themes.referral,
|
||||
share: themes.share,
|
||||
invite: themes.invite,
|
||||
slider: themes.slider?.length ? themes.slider : merged.slider,
|
||||
})
|
||||
}
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
|
||||
const legacyTheme = await loadLegacyThemeBanners()
|
||||
Object.assign(merged, mergeAppBannersFromLegacy(merged, legacyTheme))
|
||||
await loadLegacySliderInto(merged)
|
||||
|
||||
// id=null → اولین ذخیره، رکورد جدید با key=app_banners میسازد
|
||||
return { id: null, data: merged }
|
||||
const hasLegacy = !isThemeBannersEmpty(merged) || merged.slider.length > 0
|
||||
return { id: null, data: merged, healedFromLegacy: hasLegacy }
|
||||
}
|
||||
|
||||
async function syncLegacySliderConst(slides: IBenefits[]): Promise<void> {
|
||||
@@ -177,7 +186,6 @@ export async function saveAppBannersConst(
|
||||
nextId = created?.id ?? created?.const_id ?? null
|
||||
}
|
||||
|
||||
// اپ مشتری هنوز header_banner میخواند — اسلایدر را همگام نگه دار
|
||||
try {
|
||||
await syncLegacySliderConst(data.slider ?? [])
|
||||
} catch (error) {
|
||||
|
||||
@@ -82,6 +82,7 @@ async function load(force = false) {
|
||||
constId.value = res.id
|
||||
applyLoadedData(res.data)
|
||||
loaded.value = true
|
||||
// عمداً auto-save نمیکنیم: URLهای legacy ممکن است ۴۰۴ باشند و app_banners را خراب کنند
|
||||
} catch (error) {
|
||||
if (rev !== localRevision) {
|
||||
return
|
||||
|
||||
@@ -74,6 +74,43 @@ function pairHasImage(pair: ThemeImagePair): boolean {
|
||||
return Boolean(pair.light || pair.dark)
|
||||
}
|
||||
|
||||
/** همهٔ اسلاتهای تم خالیاند (رکورد app_banners پوچ که روی legacy سایه انداخته) */
|
||||
export function isThemeBannersEmpty(data: AppBannersValue): boolean {
|
||||
return (
|
||||
!pairHasImage(data.homeAsset) &&
|
||||
!pairHasImage(data.piggyCreate) &&
|
||||
!(data.productsHero ?? []).some(pairHasImage) &&
|
||||
!pairHasImage(data.referral) &&
|
||||
!pairHasImage(data.share) &&
|
||||
!pairHasImage(data.invite)
|
||||
)
|
||||
}
|
||||
|
||||
function mergePair(primary: ThemeImagePair, legacy: ThemeImagePair): ThemeImagePair {
|
||||
return {
|
||||
light: primary.light || legacy.light,
|
||||
dark: primary.dark || legacy.dark,
|
||||
}
|
||||
}
|
||||
|
||||
/** اسلات خالی primary را از legacy پر میکند؛ اسلایدر/محصولات اگر آرایه خالی باشد از legacy میآید */
|
||||
export function mergeAppBannersFromLegacy(
|
||||
primary: AppBannersValue,
|
||||
legacy: AppBannersValue,
|
||||
): AppBannersValue {
|
||||
return {
|
||||
slider: primary.slider.length ? primary.slider : legacy.slider,
|
||||
homeAsset: mergePair(primary.homeAsset, legacy.homeAsset),
|
||||
piggyCreate: mergePair(primary.piggyCreate, legacy.piggyCreate),
|
||||
productsHero: (primary.productsHero ?? []).some(pairHasImage)
|
||||
? primary.productsHero
|
||||
: legacy.productsHero ?? [],
|
||||
referral: mergePair(primary.referral, legacy.referral),
|
||||
share: mergePair(primary.share, legacy.share),
|
||||
invite: mergePair(primary.invite, legacy.invite),
|
||||
}
|
||||
}
|
||||
|
||||
/** آرایهٔ جدید یا سه اسلات قدیمی productsHero1/2/3 */
|
||||
export function normalizeProductsHero(parsed: Record<string, unknown>): ThemeImagePair[] {
|
||||
if (Array.isArray(parsed.productsHero)) {
|
||||
|
||||
@@ -239,7 +239,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { message, Modal } from 'ant-design-vue'
|
||||
import { onMounted, ref, computed } from 'vue'
|
||||
import { onMounted, ref, computed, watch } from 'vue'
|
||||
import {
|
||||
changeCustomerActivation,
|
||||
changeCustomerArchive,
|
||||
@@ -323,10 +323,15 @@ function rebuildColumns(metals = catalogMetals.value) {
|
||||
})
|
||||
}
|
||||
|
||||
watch(accountingProviderSetting, () => {
|
||||
rebuildColumns()
|
||||
})
|
||||
|
||||
const tblProps = ref<any>({
|
||||
columns: buildCustomerColumns([], { accountingProvider: accountingProviderSetting.value }),
|
||||
api: async (params: TableInput) => {
|
||||
await initAccountingSettingsFromApi()
|
||||
rebuildColumns(catalogMetals.value)
|
||||
const data = await getCustomerTable(params)
|
||||
const metals = data?.catalogMetals ?? []
|
||||
rebuildColumns(metals)
|
||||
@@ -341,8 +346,11 @@ const fetch = async () => {
|
||||
defineExpose({ fetch })
|
||||
|
||||
onMounted(() => {
|
||||
void initAccountingSettingsFromApi()
|
||||
void initWalletSettingsFromApi()
|
||||
void (async () => {
|
||||
await initAccountingSettingsFromApi()
|
||||
rebuildColumns()
|
||||
await initWalletSettingsFromApi()
|
||||
})()
|
||||
})
|
||||
|
||||
function openDirectSms(user: Customer) {
|
||||
|
||||
@@ -15,12 +15,16 @@ export type CustomerColumnOptions = {
|
||||
|
||||
function accountingCodeColumn(provider: AccountingProvider | undefined): BaseTableColumn | null {
|
||||
if (provider === 'pargar' || provider === 'tahesab' || provider === 'zarin') {
|
||||
const field = provider === 'pargar' ? 'pargar_account_id' : 'moshtari_code'
|
||||
return {
|
||||
title: 'کد حسابداری',
|
||||
dataIndex: provider === 'pargar' ? 'pargar_account_id' : 'moshtari_code',
|
||||
dataIndex: field,
|
||||
key: 'accounting_code',
|
||||
filterField: field,
|
||||
sortField: field,
|
||||
type: 'Text',
|
||||
filterable: false,
|
||||
filterable: true,
|
||||
sortable: true,
|
||||
slot: 'accountingCode'
|
||||
}
|
||||
}
|
||||
@@ -74,6 +78,8 @@ export function buildCustomerColumns(
|
||||
dataIndex: 'wallet.cash',
|
||||
key: 'wallet.cash',
|
||||
type: 'Number',
|
||||
filterable: false,
|
||||
sortable: false,
|
||||
customRender(data) {
|
||||
return usePrice(getCashBalance(data.record?.wallet, { walletCash: data.record?.wallet_cash }), true, '')
|
||||
}
|
||||
@@ -116,18 +122,18 @@ export function buildCustomerColumns(
|
||||
key: 'last_seen_at',
|
||||
type: 'DateTime',
|
||||
width: 130,
|
||||
filterable: false,
|
||||
filterable: true,
|
||||
sortable: true,
|
||||
customRender: ({ record }) => <CustomerPresenceCell lastSeenAt={record.last_seen_at} />
|
||||
},
|
||||
{
|
||||
title: 'وضعیت',
|
||||
title: 'وضعیت حساب',
|
||||
dataIndex: 'active',
|
||||
key: 'status',
|
||||
type: 'Boolean',
|
||||
width: 132,
|
||||
filterable: false,
|
||||
sortable: false,
|
||||
filterable: true,
|
||||
sortable: true,
|
||||
customRender: ({ record }) => {
|
||||
const userOk = Boolean(record.active)
|
||||
const tradeOk = Boolean(record.trade_active)
|
||||
@@ -151,6 +157,15 @@ export function buildCustomerColumns(
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'وضعیت سفارش',
|
||||
dataIndex: 'trade_active',
|
||||
key: 'trade_active',
|
||||
type: 'Boolean',
|
||||
filterable: true,
|
||||
sortable: true,
|
||||
show: false
|
||||
},
|
||||
{
|
||||
title: 'عملیات',
|
||||
dataIndex: 'action',
|
||||
|
||||
Reference in New Issue
Block a user