Merge remote-tracking branch 'origin/modular' into modular

This commit is contained in:
2026-06-04 22:33:41 +03:30
9 changed files with 123 additions and 30 deletions
+2
View File
@@ -50,6 +50,7 @@
:closable="false"
:destroy-on-close="true"
:height="drawerHeight"
:z-index="ACTION_SHEET_Z_INDEX"
class="basic-action-sheet"
>
<div class="basic-action-sheet__container">
@@ -95,6 +96,7 @@ import { computed } from 'vue'
import BasicModal from '@/components/BasicModal.vue'
import { ACTION_SHEET_HEIGHT } from '@/constants/actionSheet'
import { ACTION_SHEET_Z_INDEX } from '@/constants/overlayZIndex'
import { isMobile } from '@core/utils/is'
interface Props {
+6 -1
View File
@@ -3,6 +3,7 @@
<a-modal
v-model:visible="localValue"
:title="props.title"
:z-index="props.zIndex"
centered
@ok="emits('ok')"
@cancel="emits('close')"
@@ -26,6 +27,8 @@
</template>
<script setup lang="ts">
import { MODAL_ABOVE_ACTION_SHEET_Z_INDEX } from '@/constants/overlayZIndex'
//define emit
const emits = defineEmits(['ok', 'close', 'update:visible'])
@@ -40,6 +43,7 @@ interface Prop {
confirmLoading?: boolean
loading?: boolean
wrapClassName?: string
zIndex?: number
}
const props = withDefaults(defineProps<Prop>(), {
@@ -49,7 +53,8 @@ const props = withDefaults(defineProps<Prop>(), {
customFooter: false,
confirmLoading: false,
loading: false,
wrapClassName: ''
wrapClassName: '',
zIndex: MODAL_ABOVE_ACTION_SHEET_Z_INDEX
})
const localValue = computed({
+4
View File
@@ -12,6 +12,7 @@
:mode="props.mode"
:style="props.style"
:multiple="props.multiple"
:dropdown-style="dropdownStyle"
@change="handleChange"
:placeholder="props.placeholder"
:allowClear="props.allowClear"
@@ -39,6 +40,9 @@
<script setup lang="ts">
import { usePrefix } from '@core/composable/usePrefix'
import { SELECT_DROPDOWN_Z_INDEX } from '@/constants/overlayZIndex'
const dropdownStyle = { zIndex: SELECT_DROPDOWN_Z_INDEX }
//Props
interface Prop {
@@ -4,6 +4,9 @@
<div v-if="showTitle" class="text-lg font-700 text-gray-900">
<slot name="title">{{ title }}</slot>
</div>
<div v-if="$slots.actions" class="flex flex-wrap items-center justify-end gap-2 pt-1">
<slot name="actions" />
</div>
<div v-if="subtitle || $slots.subtitle" class="text-xs text-gray-500">
<slot name="subtitle">{{ subtitle }}</slot>
</div>
+8
View File
@@ -0,0 +1,8 @@
/** z-index برای bottom action sheet (Ant Drawer پیش‌فرض: 1000) */
export const ACTION_SHEET_Z_INDEX = 1000
/** z-index برای مودال‌ها و دیالوگ‌هایی که باید روی action sheet باشند */
export const MODAL_ABOVE_ACTION_SHEET_Z_INDEX = 1100
/** z-index برای dropdown سلکت‌ها داخل مودال (باید بالاتر از مودال باشد) */
export const SELECT_DROPDOWN_Z_INDEX = MODAL_ABOVE_ACTION_SHEET_Z_INDEX + 100
+5
View File
@@ -74,6 +74,11 @@
@apply px-1 py-3;
}
// مودال‌ها و Modal.confirm بالای bottom action sheet (drawer: 1000)
.ant-modal-wrap {
z-index: 1100 !important;
}
@@ -3,22 +3,23 @@
<template #default="{ item: row }">
<MobileSheetHeader :title="row.name || '-'" :show-title="isMobile">
<template #actions>
<MobileIconButton plain icon="vuesax-linear:archive-tick" color="#e3bf00" :size="22" @click="$emit('archive', row)" />
<MobileIconButton plain icon="vuesax-linear:archive-tick" color="#e3bf00" :size="22" @click="closeAndEmit('archive', row)" />
<MobileIconButton
plain
:icon="row.active ? 'vuesax-linear:user-tick' : 'vuesax-linear:user-remove'"
:color="row.active ? '#54AD06' : '#ad0627'"
:size="22"
@click="$emit('toggleActive', row)"
@click="confirmToggleActive(row)"
/>
<MobileIconButton plain icon="vuesax-linear:wallet-add" color="#9333ea" :size="22" @click="$emit('chargeMoney', row)" />
<MobileIconButton plain icon="vuesax-linear:wallet-money" color="#ea580c" :size="22" @click="$emit('chargeGold', row)" />
<MobileIconButton plain icon="vuesax-linear:wallet-add" color="#9333ea" :size="22" @click="closeAndEmit('chargeMoney', row)" />
<MobileIconButton plain icon="vuesax-linear:wallet-money" color="#ea580c" :size="22" @click="closeAndEmit('chargeGold', row)" />
<MobileIconButton plain icon="vuesax-linear:stickynote" color="#10913A" :size="22" @click="closeAndEmit('info', row)" />
<MobileIconButton
plain
:icon="row.trade_active ? 'vuesax-linear:box-tick' : 'vuesax-linear:box-remove'"
:color="row.trade_active ? '#54AD06' : '#ad0627'"
:size="22"
@click="$emit('toggleTrade', row)"
@click="confirmToggleTrade(row)"
/>
<MobileIconButton
v-if="!(row as any).is_legal"
@@ -26,7 +27,7 @@
icon="vuesax-linear:user-search"
color="#0d9488"
:size="22"
@click="$emit('confirmUser', row)"
@click="closeAndEmit('confirmUser', row)"
/>
</template>
</MobileSheetHeader>
@@ -72,7 +73,9 @@
</template>
<script setup lang="ts">
import { Modal } from 'ant-design-vue'
import type { Customer } from '@/model/customer'
import { MODAL_ABOVE_ACTION_SHEET_Z_INDEX } from '@/constants/overlayZIndex'
import MobileDetailRow from '@/components/mobile/MobileDetailRow.vue'
import MobileStatCard from '@/components/mobile/MobileStatCard.vue'
import MobileDetailSheet from '@/components/mobile/MobileDetailSheet.vue'
@@ -116,4 +119,40 @@ function goldBalance(row: Customer) {
function lastSeen(row: Customer) {
return row.last_seen_at ? toJalali(row.last_seen_at) : '-'
}
type SheetEmit =
| 'archive'
| 'chargeMoney'
| 'chargeGold'
| 'info'
| 'confirmUser'
function closeAndEmit(event: SheetEmit, row: Customer) {
visibleProxy.value = false
emit(event, row)
}
function confirmToggleActive(row: Customer) {
Modal.confirm({
title: row.active ? 'آیا حساب کاربری را غیرفعال می‌کنید؟' : 'آیا حساب کاربری را فعال می‌کنید؟',
okText: 'تایید',
cancelText: 'رد',
centered: true,
zIndex: MODAL_ABOVE_ACTION_SHEET_Z_INDEX,
onOk: () => emit('toggleActive', row)
})
}
function confirmToggleTrade(row: Customer) {
Modal.confirm({
title: row.trade_active
? 'آیا سفارش دهی را غیرمجاز می‌کنید؟'
: 'آیا سفارش دهی را مجاز می‌کنید؟',
okText: 'تایید',
cancelText: 'رد',
centered: true,
zIndex: MODAL_ABOVE_ACTION_SHEET_Z_INDEX,
onOk: () => emit('toggleTrade', row)
})
}
</script>
@@ -69,7 +69,7 @@
<a-form-item v-if="getConfigApp('name') === 'boursecu'" label="دسته بندی" name="group_type" :rules="inputRules()">
<BasicSelect v-model:value="form.group_type" :items="boursemesCategoryItems" valueName="value" keyName="value" />
</a-form-item>
<a-form-item v-if="getConfigApp('name') === 'garoosi'" label="دسته بندی" name="group_type" :rules="inputRules()">
<a-form-item v-else-if="getConfigApp('name') === 'garoosi'" label="دسته بندی" name="group_type" :rules="inputRules()">
<BasicSelect v-model:value="form.group_type" :items="garoosiCategoryItems" valueName="value" keyName="value" />
</a-form-item>
<a-form-item v-else label="دسته بندی" name="group_type" :rules="inputRules()">
@@ -1,26 +1,37 @@
<template>
<div class="flex h-full min-h-0 min-w-0 max-w-full flex-col overflow-hidden">
<div class="shrink-0 pr-3 md:flex">
<div class="content-center">فعال سازی محصولات:</div>
<div class="ml-2 content-center mt-1 md:mt-unset md:mr-4">زمان شروع</div>
<div>
<TimePicker
v-model:value="startTime"
:locale="customLocale"
placeholder="انتخاب زمان"
:defaultValue="dayjs('00:00:00', 'HH:mm:ss')"
/>
</div>
<div class="md:mr-4 ml-2 mt-2 md:mt-unset content-center">زمان پایان</div>
<div>
<TimePicker
v-model:value="endTime"
:locale="customLocale"
placeholder="انتخاب زمان"
:defaultValue="dayjs('00:00:00', 'HH:mm:ss')"
/>
</div>
<BaseButton class="mt-2 md:mt-unset md:mr-2" @click="setTimeActive(startTime, endTime)">ثبت</BaseButton>
<div class="shrink-0">
<Collapse
class="product-activation-collapse"
:activeKey="activationActiveKey"
@update:activeKey="activationActiveKey = $event as (string | number)[]"
>
<BaseCollapse title="فعال سازی محصولات" active-key="activation" :actives="activationActiveKey">
<template #content>
<div class="flex flex-col gap-2 md:flex-row md:flex-wrap md:items-center">
<div class="content-center md:mr-4">زمان شروع</div>
<div>
<TimePicker
v-model:value="startTime"
:locale="customLocale"
placeholder="انتخاب زمان"
:defaultValue="dayjs('00:00:00', 'HH:mm:ss')"
/>
</div>
<div class="content-center md:mr-4">زمان پایان</div>
<div>
<TimePicker
v-model:value="endTime"
:locale="customLocale"
placeholder="انتخاب زمان"
:defaultValue="dayjs('00:00:00', 'HH:mm:ss')"
/>
</div>
<BaseButton class="md:mr-2" @click="setTimeActive(startTime, endTime)">ثبت</BaseButton>
</div>
</template>
</BaseCollapse>
</Collapse>
</div>
<BasicShowContext title="لیست محصولات" class="min-h-0 flex-1">
@@ -97,7 +108,8 @@
</template>
<script setup lang="ts">
import { message, Modal, TimePicker } from 'ant-design-vue'
import { Collapse, message, Modal, TimePicker } from 'ant-design-vue'
import BaseCollapse from '@/components/BaseCollapse.vue'
import locale from 'ant-design-vue/es/date-picker/locale/fa_IR'
import dayjs from 'dayjs'
import customParseFormat from 'dayjs/plugin/customParseFormat'
@@ -122,6 +134,7 @@ const [submit, reload] = useBaseTable()
const emits = defineEmits(['edit', 'add'])
const mobileListRef = ref<null | { fetch: () => Promise<void> }>(null)
const activationActiveKey = ref<(string | number)[]>(isMobile.value ? [] : ['activation'])
const startTime = ref(dayjs('00:00:00', 'HH:mm:ss'))
const endTime = ref(dayjs('00:00:00', 'HH:mm:ss'))
@@ -195,4 +208,18 @@ async function setTimeActive(start: dayjs.Dayjs | string, end: dayjs.Dayjs | str
.ant-tooltip {
z-index: 1001 !important;
}
.product-activation-collapse.ant-collapse {
:deep(> .ant-collapse-item > .ant-collapse-header) {
padding: 0 !important;
}
:deep(.ant-collapse-content-box) {
padding: 0 !important;
}
:deep(.ant-collapse-header .mb-3) {
margin-bottom: 0 !important;
}
}
</style>