store2
This commit is contained in:
@@ -3,5 +3,10 @@ import useAxios from "@core/utils/useAxios"
|
|||||||
|
|
||||||
export const setConfiguration = async (obj: Const) => await useAxios.post<Const>(`/admin/get_settings`, obj)
|
export const setConfiguration = async (obj: Const) => await useAxios.post<Const>(`/admin/get_settings`, obj)
|
||||||
|
|
||||||
|
/** همه تنظیمات — برای خواندن داخلی (is_store، unit و ...) */
|
||||||
export const getConfiguration = async () =>
|
export const getConfiguration = async () =>
|
||||||
|
await useAxios.get<Array<Const>>(`/admin/get_settings`)
|
||||||
|
|
||||||
|
/** فقط تنظیمات قابل ویرایش — برای صفحه تنظیمات ادمین */
|
||||||
|
export const getEditableConfiguration = async () =>
|
||||||
await useAxios.get<Array<Const>>(`/admin/get_settings`, { params: { editable_only: 1 } })
|
await useAxios.get<Array<Const>>(`/admin/get_settings`, { params: { editable_only: 1 } })
|
||||||
@@ -13,6 +13,7 @@ import { setupRoutes } from '@/router'
|
|||||||
//import { resetRouter } from '@core/router'
|
//import { resetRouter } from '@core/router'
|
||||||
import { useUserStore } from '@/store/userStore'
|
import { useUserStore } from '@/store/userStore'
|
||||||
import { setupPinia } from '@core/plugins/pinia'
|
import { setupPinia } from '@core/plugins/pinia'
|
||||||
|
import { initStoreModeFromSettings } from '@/utils/config'
|
||||||
|
|
||||||
const init = async () => {
|
const init = async () => {
|
||||||
const app = createApp(App)
|
const app = createApp(App)
|
||||||
@@ -27,6 +28,7 @@ const init = async () => {
|
|||||||
const token = getToken()
|
const token = getToken()
|
||||||
if (token) {
|
if (token) {
|
||||||
await userStore.getMyInfo()
|
await userStore.getMyInfo()
|
||||||
|
await initStoreModeFromSettings()
|
||||||
setupRoutes(['*'])
|
setupRoutes(['*'])
|
||||||
//setupRoutes(['project'])
|
//setupRoutes(['project'])
|
||||||
/*router.removeRoute('usersMain')
|
/*router.removeRoute('usersMain')
|
||||||
|
|||||||
@@ -41,6 +41,8 @@ export interface Product{
|
|||||||
file_id?: number
|
file_id?: number
|
||||||
file?: File
|
file?: File
|
||||||
original_image?: File
|
original_image?: File
|
||||||
|
inventory?: number
|
||||||
|
description?: string | null
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface MethodePrices {
|
export interface MethodePrices {
|
||||||
|
|||||||
@@ -171,14 +171,16 @@ import type { FormInstance } from 'ant-design-vue'
|
|||||||
import { message } from 'ant-design-vue'
|
import { message } from 'ant-design-vue'
|
||||||
import type { Const } from '@/model/configuration'
|
import type { Const } from '@/model/configuration'
|
||||||
import { loading } from '@/utils'
|
import { loading } from '@/utils'
|
||||||
import { getConfiguration, setConfiguration } from '@/api/configuration'
|
import { getEditableConfiguration, setConfiguration } from '@/api/configuration'
|
||||||
import SettingValueField from './SettingValueField.vue'
|
import SettingValueField from './SettingValueField.vue'
|
||||||
import SettingCard from './SettingCard.vue'
|
import SettingCard from './SettingCard.vue'
|
||||||
|
import { setStoreModeFromSettings } from '@/utils/config'
|
||||||
import {
|
import {
|
||||||
SETTING_TYPE_OPTIONS,
|
SETTING_TYPE_OPTIONS,
|
||||||
formatValueForSave,
|
formatValueForSave,
|
||||||
helpText,
|
helpText,
|
||||||
isSettingVisible,
|
isSettingVisible,
|
||||||
|
isSwitchOn,
|
||||||
resolveSettingFieldType
|
resolveSettingFieldType
|
||||||
} from './settingTypes'
|
} from './settingTypes'
|
||||||
|
|
||||||
@@ -410,7 +412,11 @@ onMounted(() => {
|
|||||||
async function initConfig() {
|
async function initConfig() {
|
||||||
try {
|
try {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
baseData.value = (await getConfiguration()) ?? []
|
baseData.value = (await getEditableConfiguration()) ?? []
|
||||||
|
const storeRow = baseData.value.find((row) => row.key === 'is_store')
|
||||||
|
if (storeRow) {
|
||||||
|
setStoreModeFromSettings(isSwitchOn(storeRow.value))
|
||||||
|
}
|
||||||
syncDraftsFromBase()
|
syncDraftsFromBase()
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e)
|
console.error(e)
|
||||||
@@ -481,6 +487,9 @@ async function saveSettingRow(row: Const, overrides?: { isActive?: boolean }) {
|
|||||||
row.value = value
|
row.value = value
|
||||||
row.is_active = isActive
|
row.is_active = isActive
|
||||||
drafts.value[id] = value
|
drafts.value[id] = value
|
||||||
|
if (row.key === 'is_store') {
|
||||||
|
setStoreModeFromSettings(isSwitchOn(value))
|
||||||
|
}
|
||||||
savedFlashIds.value.add(id)
|
savedFlashIds.value.add(id)
|
||||||
if (saveTimers.has(id)) clearTimeout(saveTimers.get(id))
|
if (saveTimers.has(id)) clearTimeout(saveTimers.get(id))
|
||||||
saveTimers.set(
|
saveTimers.set(
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ export type SettingFieldType = 'text' | 'number' | 'switch' | 'select' | 'longte
|
|||||||
|
|
||||||
/** کلیدهای legacy — در پنل نمایش داده نمیشوند (جایگزین: price_provider) */
|
/** کلیدهای legacy — در پنل نمایش داده نمیشوند (جایگزین: price_provider) */
|
||||||
export const HIDDEN_LEGACY_SETTING_KEYS = new Set([
|
export const HIDDEN_LEGACY_SETTING_KEYS = new Set([
|
||||||
'tabanGohar_price',
|
|
||||||
'main_product_price',
|
'main_product_price',
|
||||||
'montzar_price',
|
'montzar_price',
|
||||||
'etehadie_api_url',
|
'etehadie_api_url',
|
||||||
@@ -149,7 +148,7 @@ export function parseSelectOptions(
|
|||||||
source = source.split('|').pop() || ''
|
source = source.split('|').pop() || ''
|
||||||
}
|
}
|
||||||
|
|
||||||
const deprecatedOpts = new Set(['taban_gohar', 'etehadie'])
|
const deprecatedOpts = new Set(['etehadie'])
|
||||||
const opts = source
|
const opts = source
|
||||||
.split(',')
|
.split(',')
|
||||||
.map((s) => s.trim())
|
.map((s) => s.trim())
|
||||||
|
|||||||
@@ -194,6 +194,14 @@
|
|||||||
<a-form-item label="واحد" name="unit" :rules="inputRules()">
|
<a-form-item label="واحد" name="unit" :rules="inputRules()">
|
||||||
<BasicSelect v-model:value="form.unit" :items="unitItems" valueName="value" keyName="value" />
|
<BasicSelect v-model:value="form.unit" :items="unitItems" valueName="value" keyName="value" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
<a-form-item
|
||||||
|
v-if="isStore && !isMeltedCategory"
|
||||||
|
label="تعداد موجودی"
|
||||||
|
name="inventory"
|
||||||
|
:rules="inputRules()"
|
||||||
|
>
|
||||||
|
<BasicInput v-model:value="form.inventory" type="number" />
|
||||||
|
</a-form-item>
|
||||||
<a-form-item label="هزینه نقدی موقع خرید" name="cash_fee_buy" :rules="inputRules()">
|
<a-form-item label="هزینه نقدی موقع خرید" name="cash_fee_buy" :rules="inputRules()">
|
||||||
<BasicInput v-model:value="form.cash_fee_buy" addon-before="ریال" type="price" />
|
<BasicInput v-model:value="form.cash_fee_buy" addon-before="ریال" type="price" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
@@ -249,6 +257,7 @@ import Icon from '@core/components/BaseIcon/src/Icon.vue'
|
|||||||
import BaseCollapse from '@/components/BaseCollapse.vue'
|
import BaseCollapse from '@/components/BaseCollapse.vue'
|
||||||
import IndexImageUploader from '@/components/ProductUploader/IndexImageUploader.vue'
|
import IndexImageUploader from '@/components/ProductUploader/IndexImageUploader.vue'
|
||||||
import { getConfiguration } from '@/api/configuration'
|
import { getConfiguration } from '@/api/configuration'
|
||||||
|
import { isSwitchOn } from '@/pages/menuPages/configuration/settingTypes'
|
||||||
import type { last } from '@/model/price'
|
import type { last } from '@/model/price'
|
||||||
import type { MethodePrices } from '@/model/product'
|
import type { MethodePrices } from '@/model/product'
|
||||||
import { usePrice } from '@core/utils/usePrice'
|
import { usePrice } from '@core/utils/usePrice'
|
||||||
@@ -275,8 +284,11 @@ const props = defineProps<{
|
|||||||
customLocale: any
|
customLocale: any
|
||||||
productIndexImage: any[]
|
productIndexImage: any[]
|
||||||
editId?: number
|
editId?: number
|
||||||
|
isStore?: boolean
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
|
const isStore = ref(Boolean(props.isStore))
|
||||||
|
|
||||||
const tradeWeightUnit = ref('گرم')
|
const tradeWeightUnit = ref('گرم')
|
||||||
const isMeltedCategory = computed(() => isMeltedTradeGroup(props.form.group_type))
|
const isMeltedCategory = computed(() => isMeltedTradeGroup(props.form.group_type))
|
||||||
|
|
||||||
@@ -314,6 +326,11 @@ onMounted(async () => {
|
|||||||
const rows = await getConfiguration()
|
const rows = await getConfiguration()
|
||||||
const unitRow = Array.isArray(rows) ? rows.find((row) => row.key === 'unit') : null
|
const unitRow = Array.isArray(rows) ? rows.find((row) => row.key === 'unit') : null
|
||||||
tradeWeightUnit.value = resolveTradeWeightUnit(unitRow?.value)
|
tradeWeightUnit.value = resolveTradeWeightUnit(unitRow?.value)
|
||||||
|
|
||||||
|
const storeRow = Array.isArray(rows) ? rows.find((row) => row.key === 'is_store') : null
|
||||||
|
if (storeRow) {
|
||||||
|
isStore.value = isSwitchOn(storeRow.value)
|
||||||
|
}
|
||||||
} catch {
|
} catch {
|
||||||
tradeWeightUnit.value = 'گرم'
|
tradeWeightUnit.value = 'گرم'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ import {
|
|||||||
getCustomerTable,
|
getCustomerTable,
|
||||||
setActiveTime
|
setActiveTime
|
||||||
} from '@/api/product'
|
} from '@/api/product'
|
||||||
import { cols } from '@/pages/menuPages/products/base/hooks/productColumns'
|
import { getProductColumns } from '@/pages/menuPages/products/base/hooks/productColumns'
|
||||||
import ProductMobileCardList from '@/pages/menuPages/products/base/components/ProductMobileCardList.vue'
|
import ProductMobileCardList from '@/pages/menuPages/products/base/components/ProductMobileCardList.vue'
|
||||||
import useBaseTable from '@core/components/BaseTable/hooks/useBaseTable'
|
import useBaseTable from '@core/components/BaseTable/hooks/useBaseTable'
|
||||||
import type { TableInput } from '@core/type/baseTable'
|
import type { TableInput } from '@core/type/baseTable'
|
||||||
@@ -148,7 +148,7 @@ const customLocale = ref({
|
|||||||
})
|
})
|
||||||
|
|
||||||
const tblProps = ref<any>({
|
const tblProps = ref<any>({
|
||||||
columns: cols,
|
columns: getProductColumns(),
|
||||||
api: async (params: TableInput) => {
|
api: async (params: TableInput) => {
|
||||||
const data = (await getCustomerTable(params)) as any
|
const data = (await getCustomerTable(params)) as any
|
||||||
startTime.value = dayjs(data?.auto_open_at, 'HH:mm:ss')
|
startTime.value = dayjs(data?.auto_open_at, 'HH:mm:ss')
|
||||||
|
|||||||
@@ -1,7 +1,16 @@
|
|||||||
import type { BaseTableColumn } from '@core/type/baseTable'
|
import type { BaseTableColumn } from '@core/type/baseTable'
|
||||||
import CustomTag from '@/components/CustomTag.vue'
|
import CustomTag from '@/components/CustomTag.vue'
|
||||||
|
import { isStoreApp } from '@/utils/config'
|
||||||
|
|
||||||
export const cols: BaseTableColumn[] = [
|
const inventoryColumn: BaseTableColumn = {
|
||||||
|
title: 'موجودی',
|
||||||
|
dataIndex: 'inventory',
|
||||||
|
key: 'inventory',
|
||||||
|
type: 'Number'
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getProductColumns(): BaseTableColumn[] {
|
||||||
|
return [
|
||||||
{
|
{
|
||||||
title: 'ردیف',
|
title: 'ردیف',
|
||||||
dataIndex: 'id',
|
dataIndex: 'id',
|
||||||
@@ -78,6 +87,7 @@ export const cols: BaseTableColumn[] = [
|
|||||||
key: 'cash_fee_sell',
|
key: 'cash_fee_sell',
|
||||||
type: 'Number'
|
type: 'Number'
|
||||||
},
|
},
|
||||||
|
...(isStoreApp() ? [inventoryColumn] : []),
|
||||||
{
|
{
|
||||||
title: 'وضعیت محصول',
|
title: 'وضعیت محصول',
|
||||||
dataIndex: 'active',
|
dataIndex: 'active',
|
||||||
@@ -102,4 +112,8 @@ export const cols: BaseTableColumn[] = [
|
|||||||
slot: 'action',
|
slot: 'action',
|
||||||
filterable: false
|
filterable: false
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @deprecated از getProductColumns استفاده کنید */
|
||||||
|
export const cols = getProductColumns()
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<CustomersStoreView v-if="isStoreApp()" />
|
<div class="h-full min-h-0 min-w-0 overflow-hidden">
|
||||||
<div v-else class="h-full min-h-0 min-w-0 overflow-hidden">
|
|
||||||
<tbl ref="table" class="h-full min-h-0 w-full" @edit="edit" @add="add" />
|
<tbl ref="table" class="h-full min-h-0 w-full" @edit="edit" @add="add" />
|
||||||
<BasicActionSheet
|
<BasicActionSheet
|
||||||
v-model:visible="addUserVisible"
|
v-model:visible="addUserVisible"
|
||||||
@@ -34,6 +33,7 @@
|
|||||||
:productIndexImage="ProductIndexImage"
|
:productIndexImage="ProductIndexImage"
|
||||||
:editId="editId"
|
:editId="editId"
|
||||||
:meltedPriceOption="meltedPriceOption"
|
:meltedPriceOption="meltedPriceOption"
|
||||||
|
:isStore="isStoreApp()"
|
||||||
@update:methodOption="methodOption = $event"
|
@update:methodOption="methodOption = $event"
|
||||||
@update:weightOption="weightOption = $event"
|
@update:weightOption="weightOption = $event"
|
||||||
@update:meltedPriceOption="meltedPriceOption = $event"
|
@update:meltedPriceOption="meltedPriceOption = $event"
|
||||||
@@ -57,7 +57,6 @@ import { cloneDeep } from 'lodash'
|
|||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
import customParseFormat from 'dayjs/plugin/customParseFormat'
|
import customParseFormat from 'dayjs/plugin/customParseFormat'
|
||||||
import { computed, nextTick, onMounted, onUnmounted, ref, watch } from 'vue'
|
import { computed, nextTick, onMounted, onUnmounted, ref, watch } from 'vue'
|
||||||
import CustomersStoreView from '@/pages/menuPages/customers/base/index.vue'
|
|
||||||
import { isStoreApp } from '@/utils/config'
|
import { isStoreApp } from '@/utils/config'
|
||||||
import { createProduct, getCustomerById, updateCustomer } from '@/api/product'
|
import { createProduct, getCustomerById, updateCustomer } from '@/api/product'
|
||||||
import { fetchProductImageUrl } from '@/api/file'
|
import { fetchProductImageUrl } from '@/api/file'
|
||||||
@@ -326,6 +325,7 @@ function resetData() {
|
|||||||
order_limit_enabled: false,
|
order_limit_enabled: false,
|
||||||
show_in_assets: false,
|
show_in_assets: false,
|
||||||
use_last_price_if_zero: false,
|
use_last_price_if_zero: false,
|
||||||
|
inventory: 0,
|
||||||
min_order_cash: undefined,
|
min_order_cash: undefined,
|
||||||
max_order_cash: undefined,
|
max_order_cash: undefined,
|
||||||
auto_open_at: dayjs('00:00:00', 'HH:mm:ss'),
|
auto_open_at: dayjs('00:00:00', 'HH:mm:ss'),
|
||||||
@@ -375,6 +375,10 @@ async function ok() {
|
|||||||
}
|
}
|
||||||
if (weightOption.value === '2') payload.amount = 1
|
if (weightOption.value === '2') payload.amount = 1
|
||||||
|
|
||||||
|
if (isStoreApp() && !isMeltedTradeGroup(payload.group_type)) {
|
||||||
|
payload.inventory = Math.max(0, Number(payload.inventory ?? 0))
|
||||||
|
}
|
||||||
|
|
||||||
payload.auto_open_at = payload.auto_open_at
|
payload.auto_open_at = payload.auto_open_at
|
||||||
? dayjs(payload.auto_open_at).format('HH:mm:ss')
|
? dayjs(payload.auto_open_at).format('HH:mm:ss')
|
||||||
: '00:00:00'
|
: '00:00:00'
|
||||||
|
|||||||
+29
-8
@@ -1,6 +1,5 @@
|
|||||||
|
|
||||||
export function getConfigApp(key: string) {
|
export function getConfigApp(key: string) {
|
||||||
const config = window.__APP_CONFIG__ ? window.__APP_CONFIG__.user:{}
|
const config = window.__APP_CONFIG__ ? window.__APP_CONFIG__.user : {}
|
||||||
|
|
||||||
if (config) {
|
if (config) {
|
||||||
return config[key]
|
return config[key]
|
||||||
@@ -8,11 +7,33 @@ export function getConfigApp(key: string) {
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let storeModeFromSettings: boolean | null = null
|
||||||
|
|
||||||
|
function isSwitchOn(value: string | undefined | null): boolean {
|
||||||
|
const v = (value ?? '').trim().toLowerCase()
|
||||||
|
return v === 'true' || v === '1' || v === 'yes'
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setStoreModeFromSettings(value: boolean): void {
|
||||||
|
storeModeFromSettings = value
|
||||||
|
}
|
||||||
|
|
||||||
|
/** is_store فقط از API تنظیمات (get_settings) خوانده میشود — نه از get_user */
|
||||||
|
export async function initStoreModeFromSettings(): Promise<boolean> {
|
||||||
|
if (storeModeFromSettings !== null) return storeModeFromSettings
|
||||||
|
|
||||||
|
try {
|
||||||
|
const { getConfiguration } = await import('@/api/configuration')
|
||||||
|
const rows = await getConfiguration()
|
||||||
|
const row = Array.isArray(rows) ? rows.find((item) => item.key === 'is_store') : null
|
||||||
|
storeModeFromSettings = row ? isSwitchOn(row.value) : false
|
||||||
|
} catch {
|
||||||
|
storeModeFromSettings = false
|
||||||
|
}
|
||||||
|
|
||||||
|
return storeModeFromSettings
|
||||||
|
}
|
||||||
|
|
||||||
export function isStoreApp(): boolean {
|
export function isStoreApp(): boolean {
|
||||||
const value = getConfigApp('is_store')
|
return storeModeFromSettings === true
|
||||||
if (value === true || value === 1) return true
|
|
||||||
if (typeof value === 'string') {
|
|
||||||
return ['true', '1', 'yes'].includes(value.trim().toLowerCase())
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user