store 3
This commit is contained in:
@@ -100,7 +100,7 @@ import { useStaticApiListsStore } from '@/store/staticApisStore'
|
||||
import OtpInput from 'vue3-otp-input'
|
||||
import { useUserStore } from '@/store/userStore'
|
||||
import { setupRoutes } from '@/router'
|
||||
import {getConfigApp} from "@/utils/config";
|
||||
import { getConfigApp, initStoreModeFromSettings } from '@/utils/config'
|
||||
|
||||
//define emit
|
||||
const emits = defineEmits(['enter'])
|
||||
@@ -160,7 +160,10 @@ const onUserPassFormFinish = async () => {
|
||||
await setToken(access_token)
|
||||
}
|
||||
await userStore.getMyInfo()
|
||||
await initStoreModeFromSettings()
|
||||
setupRoutes(['*'], router)
|
||||
const { refreshAppModeMenu } = await import('@/router')
|
||||
refreshAppModeMenu()
|
||||
// const info = await getMyInformation()
|
||||
// await setMyInfo(JSON.stringify(info))
|
||||
// emits('enter')
|
||||
|
||||
@@ -174,6 +174,7 @@ import { loading } from '@/utils'
|
||||
import { getEditableConfiguration, setConfiguration } from '@/api/configuration'
|
||||
import SettingValueField from './SettingValueField.vue'
|
||||
import SettingCard from './SettingCard.vue'
|
||||
import { refreshAppModeMenu } from '@/router'
|
||||
import { setStoreModeFromSettings } from '@/utils/config'
|
||||
import {
|
||||
SETTING_TYPE_OPTIONS,
|
||||
@@ -416,6 +417,7 @@ async function initConfig() {
|
||||
const storeRow = baseData.value.find((row) => row.key === 'is_store')
|
||||
if (storeRow) {
|
||||
setStoreModeFromSettings(isSwitchOn(storeRow.value))
|
||||
refreshAppModeMenu()
|
||||
}
|
||||
syncDraftsFromBase()
|
||||
} catch (e) {
|
||||
@@ -489,6 +491,7 @@ async function saveSettingRow(row: Const, overrides?: { isActive?: boolean }) {
|
||||
drafts.value[id] = value
|
||||
if (row.key === 'is_store') {
|
||||
setStoreModeFromSettings(isSwitchOn(value))
|
||||
refreshAppModeMenu()
|
||||
}
|
||||
savedFlashIds.value.add(id)
|
||||
if (saveTimers.has(id)) clearTimeout(saveTimers.get(id))
|
||||
|
||||
@@ -79,7 +79,13 @@ import {
|
||||
unwrapApiRecord
|
||||
} from '@/utils/file'
|
||||
import { normalizeProductOrderLimitForm, validateProductOrderLimitForm } from '@/utils/productOrderLimit'
|
||||
import { buildCategorySelectItems, isMeltedTradeGroup, resolveMeltedPriceSource } from '@/utils/productCategories'
|
||||
import {
|
||||
buildCategorySelectItems,
|
||||
isMeltedTradeGroup,
|
||||
PRODUCT_CATEGORY_ABSHODE,
|
||||
resolveMeltedPriceSource
|
||||
} from '@/utils/productCategories'
|
||||
import { getCategories } from '@/api/category'
|
||||
|
||||
dayjs.extend(customParseFormat)
|
||||
|
||||
@@ -122,7 +128,13 @@ const metalItems: Array<Item> = [
|
||||
{ key: 2, value: 'نقره' },
|
||||
{ key: 3, value: 'مس' },
|
||||
]
|
||||
const categorySelectItems = computed(() => buildCategorySelectItems(metalItems))
|
||||
const storeCategorySelectItems = ref<Array<{ key: string; value: string }>>([])
|
||||
const categorySelectItems = computed(() => {
|
||||
if (isStoreApp() && storeCategorySelectItems.value.length) {
|
||||
return storeCategorySelectItems.value
|
||||
}
|
||||
return buildCategorySelectItems(metalItems)
|
||||
})
|
||||
const priceItems: Array<Item> = [
|
||||
{ key: 0, value: 'متغیر' },
|
||||
{ key: 1, value: 'ثابت' }
|
||||
@@ -185,8 +197,28 @@ watch(addUserVisible, (visible) => {
|
||||
|
||||
onMounted(() => {
|
||||
void refreshLivePrices()
|
||||
void loadStoreCategories()
|
||||
})
|
||||
|
||||
async function loadStoreCategories() {
|
||||
if (!isStoreApp()) return
|
||||
|
||||
try {
|
||||
const rows = await getCategories({ select_only: true })
|
||||
const metalHint = metalItems.map((item) => item.value).join('، ')
|
||||
storeCategorySelectItems.value = rows.map((category) => ({
|
||||
key: category.name,
|
||||
value:
|
||||
category.name === PRODUCT_CATEGORY_ABSHODE
|
||||
? `${category.name} (${metalHint})`
|
||||
: category.name
|
||||
}))
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
storeCategorySelectItems.value = []
|
||||
}
|
||||
}
|
||||
|
||||
onUnmounted(() => {
|
||||
stopPricePolling()
|
||||
})
|
||||
|
||||
@@ -0,0 +1,162 @@
|
||||
<template>
|
||||
<div class="flex h-full min-h-0 flex-col gap-4 p-4">
|
||||
<div class="flex flex-wrap items-center gap-2">
|
||||
<BaseButton :loading="syncing" @click="handleSync">
|
||||
همگامسازی از محصولات
|
||||
</BaseButton>
|
||||
</div>
|
||||
|
||||
<a-spin :spinning="loading">
|
||||
<a-table
|
||||
:columns="columns"
|
||||
:data-source="items"
|
||||
:pagination="false"
|
||||
row-key="id"
|
||||
size="middle"
|
||||
class="min-h-0 flex-1"
|
||||
>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.key === 'active'">
|
||||
<a-switch
|
||||
:checked="asBool(record.active)"
|
||||
checked-children="فعال"
|
||||
un-checked-children="مخفی"
|
||||
@change="(checked: boolean) => toggleField(record, 'active', checked)"
|
||||
/>
|
||||
</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'">
|
||||
<a-switch
|
||||
:checked="asBool(record.show_in_select)"
|
||||
@change="(checked: boolean) => toggleField(record, 'show_in_select', checked)"
|
||||
/>
|
||||
</template>
|
||||
<template v-else-if="column.key === 'sort_order'">
|
||||
<BasicInput
|
||||
class="!w-16"
|
||||
type="number"
|
||||
v-model:value="record.sort_order"
|
||||
@blur="() => saveSortOrder(record)"
|
||||
/>
|
||||
</template>
|
||||
</template>
|
||||
</a-table>
|
||||
</a-spin>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { message } from 'ant-design-vue'
|
||||
import type { TableColumnType } from 'ant-design-vue'
|
||||
import { onMounted, ref } from 'vue'
|
||||
import { getCategories, syncCategoriesFromProducts, updateCategory } from '@/api/category'
|
||||
import type { Category } from '@/model/category'
|
||||
|
||||
const loading = ref(false)
|
||||
const syncing = ref(false)
|
||||
const items = ref<Category[]>([])
|
||||
|
||||
const columns: TableColumnType<Category>[] = [
|
||||
{ title: 'نام دسته', dataIndex: 'name', key: 'name' },
|
||||
{
|
||||
title: 'نمایش محصولات در اپ',
|
||||
key: 'active',
|
||||
width: 160,
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: 'تب فیلتر اپ',
|
||||
key: 'show_in_filter',
|
||||
width: 120,
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: 'سلکت افزودن محصول',
|
||||
key: 'show_in_select',
|
||||
width: 150,
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: 'ترتیب',
|
||||
key: 'sort_order',
|
||||
width: 90,
|
||||
align: 'center'
|
||||
}
|
||||
]
|
||||
|
||||
/** پیشفرض: روشن — فقط صفر یا false یعنی خاموش */
|
||||
function asBool(value: boolean | number | undefined | null) {
|
||||
return value !== false && value !== 0
|
||||
}
|
||||
|
||||
async function fetchList() {
|
||||
loading.value = true
|
||||
try {
|
||||
items.value = await getCategories()
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
message.error('خطا در دریافت دستهبندیها')
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
async function toggleField(record: Category, field: 'active' | 'show_in_filter' | 'show_in_select', checked: boolean) {
|
||||
const prev = record[field]
|
||||
record[field] = checked ? 1 : 0
|
||||
try {
|
||||
await updateCategory(record.id, { [field]: checked ? 1 : 0 })
|
||||
message.success('ذخیره شد')
|
||||
} catch (e) {
|
||||
record[field] = prev
|
||||
console.error(e)
|
||||
message.error('خطا در ذخیره')
|
||||
}
|
||||
}
|
||||
|
||||
async function saveSortOrder(record: Category) {
|
||||
const order = Number(record.sort_order)
|
||||
if (Number.isNaN(order)) return
|
||||
|
||||
try {
|
||||
await updateCategory(record.id, { sort_order: order })
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
message.error('خطا در ذخیره ترتیب')
|
||||
await fetchList()
|
||||
}
|
||||
}
|
||||
|
||||
async function syncList(showMessage = false) {
|
||||
syncing.value = true
|
||||
try {
|
||||
const res = await syncCategoriesFromProducts()
|
||||
items.value = res.items ?? (await getCategories())
|
||||
if (showMessage) {
|
||||
message.success(res.message || 'همگامسازی انجام شد')
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
if (showMessage) {
|
||||
message.error('خطا در همگامسازی')
|
||||
} else {
|
||||
await fetchList()
|
||||
}
|
||||
} finally {
|
||||
syncing.value = false
|
||||
}
|
||||
}
|
||||
|
||||
async function handleSync() {
|
||||
await syncList(true)
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
void syncList()
|
||||
})
|
||||
</script>
|
||||
@@ -18,10 +18,12 @@
|
||||
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 menu = computed(() => {
|
||||
const item = routerStore.routes.find((item) => item.name === 'products')
|
||||
return get(item, 'children[0].children', [])
|
||||
const children = get(item, 'children[0].children', []) as RouteRecordRaw[]
|
||||
return children.filter((child) => !child.meta?.hideMenu)
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
@@ -21,22 +21,13 @@
|
||||
import BasicMenu from '@/components/BasicMenu/index.vue'
|
||||
import { useRouterStore } from '@core/stores/router'
|
||||
import { get } from 'lodash'
|
||||
//import Nature from '@/pages/menuPages/setting/limitedOrder/index.vue'
|
||||
//s import test from './limitedOrder'
|
||||
//import Budget from '@/pages/menuPages/setting/budget/index.vue'
|
||||
//import ProjectType from '@/pages/menuPages/setting/projectType/index.vue'
|
||||
//import DocumentType from '@/pages/menuPages/setting/documentType/index.vue'
|
||||
// import Management from '@/pages/menuPages/setting/management/index.vue'
|
||||
//import Accessibility from '@/pages/menuPages/setting/accessibility/index.vue'
|
||||
//import SubmitProcess from '@/pages/menuPages/setting/submitProcess/index.vue'
|
||||
//import documentGroup from '@/pages/menuPages/setting/documentGroup/index.vue'
|
||||
//import userType from '@/pages/menuPages/setting/userType/index.vue'
|
||||
import type { RouteRecordRaw } from 'vue-router'
|
||||
|
||||
const routerStore = useRouterStore()
|
||||
const menu = computed(() => {
|
||||
const item = routerStore.routes.find((item) => item.name === 'settings')
|
||||
//console.log('aaaa', get(item, 'children[0].children', []))
|
||||
return get(item, 'children[0].children', [])
|
||||
const children = get(item, 'children[0].children', []) as RouteRecordRaw[]
|
||||
return children.filter((child) => !child.meta?.hideMenu)
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user