ui(admin-panel): responsive users, offers, reports, finance, sms, config, notify and branch menus

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
s.esmaeili
2026-10-13 10:30:25 +03:30
co-authored by Cursor
parent c1b3e90b9b
commit 5a30024548
35 changed files with 260 additions and 81 deletions
@@ -166,17 +166,29 @@ body #app .ant-menu-item-selected {
margin: 0;
}
}
// date-range filter rows on report pages: the two dates side by side, the
// action buttons on their own row without the blank spacer label
.filter-grid {
grid-template-columns: 1fr 1fr;
.ant-form-item:last-child {
grid-column: 1 / -1;
.ant-form-item-label {
display: none;
}
}
}
// a nested section card inside the page card: drop the double frame
.page-card .ant-card .ant-card,
.page-card > .ant-card-body .ant-card {
box-shadow: none;
}
// a horizontally scrollable plain <a-table> inside a page card
.page-card .table-scroll .ant-table-content,
// a horizontally scrollable plain <a-table> (class="table-scroll" on it or
// on any ancestor)
.table-scroll .ant-table-content,
.detail-modal .ant-table-content {
overflow-x: auto;
}
.page-card .table-scroll .ant-table-content > table,
.table-scroll .ant-table-content > table,
.detail-modal .ant-table-content > table {
min-width: max-content;
}
@@ -77,7 +77,7 @@
<!-- route-based fallback for direct links to /category/add/:id? -->
<a-spin v-else :spinning="loading">
<a-form layout="vertical" @submit.prevent="handleSubmit">
<a-card :title="`دسته بندی ${typeSuffix}`" class="mb-base">
<a-card :title="`دسته بندی ${typeSuffix}`" class="mb-base page-card">
<a-form-item
label="نوع نمایش"
:validate-status="err.type ? 'error' : ''"
@@ -129,7 +129,7 @@
<a-textarea v-model:value="form.body_html" :auto-size="{ minRows: 3, maxRows: 8 }" />
</a-form-item>
<a-button type="primary" @click="handleSubmit">ثبت اطلاعات</a-button>
<a-button type="primary" class="form-submit" @click="handleSubmit">ثبت اطلاعات</a-button>
</a-card>
</a-form>
</a-spin>
@@ -5,8 +5,8 @@
slot in legacy stays absent.
-->
<div id="page-user-list">
<a-card title="لیست دسته بندی ها">
<XTable ref="tbl" :model="model">
<a-card title="لیست دسته بندی ها" class="page-card">
<XTable ref="tbl" :model="model" mobile-cards>
<template #add>
<ListPageHeader rid="collection.create" add-label="افزودن دسته" @add="openAdd" />
</template>
@@ -3,7 +3,7 @@
Ported from legacy henza_admin/src/views/branch/addCustomer.vue — a 19-line
wrapper whose entire template is <singleCustomer />. Kept as a wrapper.
-->
<div>
<div class="page-card">
<SingleCustomerForm />
</div>
</template>
@@ -7,8 +7,8 @@
only their own without the view having to filter.
-->
<div id="page-user-list">
<a-card title="فاکتور خرید">
<XTable ref="tbl" :model="model">
<a-card title="فاکتور خرید" class="page-card">
<XTable ref="tbl" :model="model" mobile-cards>
<template #opt="{ record }">
<a-tooltip title="مشاهده">
<EyeOutlined class="cursor-pointer mx-1 text-primary" @click="view(record)" />
@@ -16,9 +16,9 @@
</template>
</XTable>
<a-modal v-model:open="visible" title="مشاهده فاکتور" width="70%">
<a-modal v-model:open="visible" title="مشاهده فاکتور" width="70%" wrap-class-name="detail-modal">
<div v-if="tempRow">
<a-descriptions bordered size="small" :column="2">
<a-descriptions bordered size="small" :column="{ xxl: 2, xl: 2, lg: 2, md: 2, sm: 2, xs: 1 }">
<a-descriptions-item label="شعبه">{{ tempRow.name }}</a-descriptions-item>
<a-descriptions-item label="ثبت کننده">
{{ tempRow.allocator_user?.name ?? '-' }}
@@ -9,7 +9,7 @@
endpoints here, because a dashboard showing placeholder rows is worse than
one showing nothing. Recorded in docs/ADMIN-PORT-PLAN.md.
-->
<a-spin :spinning="loading">
<a-spin :spinning="loading" class="page-card table-scroll">
<a-card title="سفارشات هفته جاری">
<a-table
size="small"
@@ -89,4 +89,10 @@ onMounted(async () => {
.mt-4 {
margin-top: 1rem;
}
@media (max-width: 575px) {
.mt-4 {
margin-top: 12px;
}
}
</style>
@@ -11,7 +11,7 @@
branch mode gates the whole route instead. Preserved.
-->
<a-spin :spinning="loading">
<a-card title="ثبت سفارش">
<a-card title="ثبت سفارش" class="page-card">
<span>جهت ثبت سفارش مشتری را انتخاب نمایید</span>
<a-form layout="vertical" class="mt-4" @submit.prevent="submitOrder">
@@ -37,7 +37,7 @@
<div v-if="form.customer_id != null">
<h6>تعداد {{ items.length }} محصول انتخاب شده است.</h6>
<XTable ref="tblProducts" :model="cols">
<XTable ref="tblProducts" :model="cols" mobile-cards>
<template #image="{ record }">
<img
width="90px"
@@ -64,7 +64,7 @@
</template>
</XTable>
<a-card v-if="items.length > 0" title="سبد سفارش" class="mt-4">
<a-card v-if="items.length > 0" title="سبد سفارش" class="mt-4 table-scroll">
<a-table
:columns="columns"
:data-source="items"
@@ -107,7 +107,7 @@
<a-textarea v-model:value="form.note" :auto-size="{ minRows: 2, maxRows: 4 }" />
</a-form-item>
<a-button type="primary" :disabled="items.length < 1" @click="submitOrder">
<a-button type="primary" class="form-submit" :disabled="items.length < 1" @click="submitOrder">
ثبت سفارش
</a-button>
</a-card>
@@ -249,4 +249,20 @@ onMounted(async () => {
.totals {
margin: 1rem 0;
}
@media (max-width: 575px) {
.customer-field {
max-width: none;
}
.mt-4 {
margin-top: 12px;
}
.totals {
margin: 12px 0;
}
h6 {
font-size: 12px;
margin-bottom: 8px;
}
}
</style>
+2 -2
View File
@@ -6,8 +6,8 @@
city has none — so saving silently copied the parent's onto the child.
-->
<div id="page-user-list">
<a-card title="لیست شهر ها">
<XTable ref="citiesTable" :model="model">
<a-card title="لیست شهر ها" class="page-card">
<XTable ref="citiesTable" :model="model" mobile-cards>
<template #add>
<ListPageHeader rid="cities.create" add-label="افزودن شهر" @add="addOpen = true" />
</template>
@@ -37,7 +37,7 @@
<!-- route-based fallback for direct links to /city/create -->
<a-spin v-else :spinning="loading">
<a-form layout="vertical" @submit.prevent="handleSubmit">
<a-card title="افزودن شهر">
<a-card title="افزودن شهر" class="page-card">
<div class="grid-2">
<a-form-item label="نام شهر" :validate-status="err.title ? 'error' : ''" :help="err.title">
<a-input v-model:value="form.title" />
@@ -52,7 +52,7 @@
<a-input-number v-model:value="form.percent_aux" class="w-full" :min="0" :max="100" :step="0.1" />
</a-form-item>
</div>
<a-button type="primary" @click="handleSubmit">ثبت اطلاعات</a-button>
<a-button type="primary" class="form-submit" @click="handleSubmit">ثبت اطلاعات</a-button>
</a-card>
</a-form>
</a-spin>
@@ -7,8 +7,8 @@
longer exists) becomes the bundled logo.
-->
<div id="page-user-list">
<a-card title="لیست دیدگاه ها">
<XTable ref="tbl" :model="model">
<a-card title="لیست دیدگاه ها" class="page-card">
<XTable ref="tbl" :model="model" mobile-cards>
<template #customer="{ text }">
{{ text && text.fname && text.lname ? `${text.fname} ${text.lname}` : 'بدون نام' }}
</template>
@@ -92,7 +92,7 @@
</XTable>
<!-- مشاهده دیدگاه -->
<a-modal v-model:open="visibleComment" title="مشاهده دیدگاه" width="80%">
<a-modal v-model:open="visibleComment" title="مشاهده دیدگاه" width="80%" wrap-class-name="detail-modal">
<div v-if="tempRow" class="comments-list">
<ul>
<li class="comment-item">
@@ -270,4 +270,20 @@ async function submitChanges(row: Record<string, any>) {
border: 1px solid grey;
border-radius: 50%;
}
@media (max-width: 575px) {
.comment-item {
gap: 10px;
flex-wrap: nowrap;
margin-bottom: 12px;
}
.comment-item .img {
width: 40px;
height: 40px;
flex-shrink: 0;
}
.comment-body {
min-width: 0;
}
}
</style>
@@ -121,7 +121,7 @@
<!-- route-based fallback for direct links to /add/findoc and /edit/findoc/:id -->
<a-spin v-else :spinning="loading">
<a-form layout="vertical" @submit.prevent="handleSubmit">
<a-card title="ثبت سند مالی" class="mb-base">
<a-card title="ثبت سند مالی" class="mb-base page-card">
<div class="grid-3">
<a-form-item label="نوع سند">
<a-select v-model:value="form.type">
@@ -213,7 +213,7 @@
<a-textarea v-model:value="form.note" :auto-size="{ minRows: 3, maxRows: 5 }" />
</a-form-item>
<a-button type="primary" @click="handleSubmit">ثبت اطلاعات</a-button>
<a-button type="primary" class="form-submit" @click="handleSubmit">ثبت اطلاعات</a-button>
</a-card>
</a-form>
</a-spin>
+2 -2
View File
@@ -7,8 +7,8 @@
-->
<div id="page-user-list">
<a-spin :spinning="loading">
<a-card title="لیست اسناد مالی">
<XTable ref="tbl" :model="model">
<a-card title="لیست اسناد مالی" class="page-card">
<XTable ref="tbl" :model="model" mobile-cards>
<template #add>
<ListPageHeader rid="document.create" add-label="ثبت سند مالی" @add="openAdd" />
</template>
@@ -26,7 +26,7 @@
@submit="handleSubmit"
>
<a-card title="لیست محصولات">
<XTable ref="tblProducts" :model="productCols">
<XTable ref="tblProducts" :model="productCols" mobile-cards>
<template #image="{ record }">
<img
width="90px"
@@ -42,7 +42,7 @@
</XTable>
</a-card>
<a-card v-if="items.length > 0" title="ثبت سفارش" class="mt-5">
<a-card v-if="items.length > 0" title="ثبت سفارش" class="mt-5 table-scroll">
<a-table :columns="columns" :data-source="items" bordered :pagination="false" row-key="pid">
<template #bodyCell="{ column, record }">
<template v-if="column.dataIndex === 'delete'">
@@ -87,8 +87,8 @@
<!-- route-based fallback for direct links to /invoice/add and /invoice/edit/:id -->
<a-spin v-else :spinning="loading">
<a-card title="لیست محصولات">
<XTable ref="tblProducts" :model="productCols">
<a-card title="لیست محصولات" class="page-card">
<XTable ref="tblProducts" :model="productCols" mobile-cards>
<template #image="{ record }">
<img
width="90px"
@@ -103,7 +103,7 @@
</template>
</XTable>
<a-card v-if="items.length > 0" title="ثبت سفارش" class="mt-5">
<a-card v-if="items.length > 0" title="ثبت سفارش" class="mt-5 table-scroll">
<a-table
:columns="columns"
:data-source="items"
@@ -151,7 +151,7 @@
</a-form-item>
</div>
<a-button type="primary" :disabled="items.length < 1" @click="handleSubmit">
<a-button type="primary" class="form-submit" :disabled="items.length < 1" @click="handleSubmit">
ثبت تغییرات
</a-button>
</a-form>
@@ -4,8 +4,8 @@
branch-allocation grid.
-->
<div id="page-user-list">
<a-card title="لیست فاکتورها">
<XTable ref="tbl" :model="model">
<a-card title="لیست فاکتورها" class="page-card">
<XTable ref="tbl" :model="model" mobile-cards>
<template #add>
<ListPageHeader rid="invoice.create" add-label="افزودن فاکتور" @add="openAdd" />
</template>
@@ -39,9 +39,9 @@
</template>
</XTable>
<a-modal v-model:open="visible" title="مشاهده فاکتور" width="70%">
<a-modal v-model:open="visible" title="مشاهده فاکتور" width="70%" wrap-class-name="detail-modal">
<div v-if="tempRow">
<a-descriptions bordered size="small" :column="2">
<a-descriptions bordered size="small" :column="{ xxl: 2, xl: 2, lg: 2, md: 2, sm: 2, xs: 1 }">
<a-descriptions-item label="شعبه">{{ tempRow.name }}</a-descriptions-item>
<a-descriptions-item label="ثبت کننده">
{{ tempRow.allocator_user?.name ?? '-' }}
+18 -1
View File
@@ -12,7 +12,7 @@
one here too — each slide uses the shared ImageUploadInput, which posts to the
ported `file/create` endpoint and stores the returned URL.
-->
<a-card v-if="hasPermission('config.statics')" title="مدیریت ثابت ها">
<a-card v-if="hasPermission('config.statics')" title="مدیریت ثابت ها" class="page-card table-scroll">
<a-spin :spinning="loading">
<a-tabs>
<!-- برندها -->
@@ -380,4 +380,21 @@ onMounted(async () => {
.mt-4 {
margin-top: 1rem;
}
@media (max-width: 575px) {
/* the add-row input fills what the button leaves instead of a fixed 260px */
.row > .ant-input {
flex: 1 1 140px;
max-width: none !important;
}
.slide {
padding: 10px;
}
.slide .row > * {
flex: 1 1 100%;
}
.mt-4 {
margin-top: 12px;
}
}
</style>
@@ -7,7 +7,7 @@
the server only ever says whether one is set, never what it is.
-->
<div>
<a-card v-if="hasPermission('config.accounting')" title="اتصال به نرم‌افزار حسابداری">
<a-card v-if="hasPermission('config.accounting')" title="اتصال به نرم‌افزار حسابداری" class="page-card table-scroll">
<template #extra>
<a-space>
<a-tag v-if="overview?.busy" color="processing">همگام‌سازی در حال اجرا</a-tag>
@@ -766,4 +766,32 @@ pre {
white-space: pre-wrap;
word-break: break-all;
}
@media (max-width: 575px) {
.mb-4 {
margin-bottom: 12px;
}
.mt-4 {
margin-top: 12px;
}
/* toolbars above the log/links/movement tables: wrap instead of overflowing */
:deep(.ant-space) {
flex-wrap: wrap;
}
:deep(.ant-tabs-tabpane > .ant-space .ant-select),
:deep(.ant-tabs-tabpane > .ant-space .ant-input-search),
:deep(.ant-tabs-tabpane > .ant-space .ant-input) {
width: 100% !important;
}
:deep(.ant-tabs-tabpane > .ant-space > .ant-space-item) {
flex: 1 1 140px;
}
:deep(.ant-alert) {
padding: 10px 12px;
}
:deep(.ant-alert-with-description .ant-alert-icon) {
font-size: 18px;
margin-inline-end: 8px;
}
}
</style>
+13 -1
View File
@@ -3,7 +3,7 @@
Ported from legacy henza_admin/src/views/manage/report.vue — a shortcut board
of report links, read from the `dashboard.links` setting.
-->
<a-card title="مدیریت گزارشات">
<a-card title="مدیریت گزارشات" class="page-card">
<a-empty v-if="links.length === 0" description="هنوز لینکی تعریف نشده است" />
<div v-else class="links">
<a v-for="(l, i) in links" :key="i" :href="l.url" target="_blank" class="link-card">
@@ -39,4 +39,16 @@ onMounted(async () => {
color: #1c2d56;
}
.link-card:hover { border-color: #1c2d56; }
@media (max-width: 575px) {
.links {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 8px;
}
.link-card {
padding: 12px;
text-align: center;
}
}
</style>
+15 -1
View File
@@ -9,7 +9,7 @@
draft side by side → the admin confirms the sample is right → «تأیید و
ثبت». The approved sample is kept with the formula as its reference.
-->
<div v-if="hasPermission('config.wage')" class="wage">
<div v-if="hasPermission('config.wage')" class="wage page-card">
<a-spin :spinning="loading">
<!-- ── status ─────────────────────────────────────────── -->
<a-card class="mb-4" :bordered="false">
@@ -498,4 +498,18 @@ onMounted(async () => {
.hist { padding: 8px 0; border-bottom: 1px solid #f5f5f5; }
.hist__meta { font-size: 12px; color: #888; }
@media (max-width: 575px) {
.mb-4 { margin-bottom: 12px; }
.mt-4 { margin-top: 12px; }
.wage :deep(.ant-row) { row-gap: 12px !important; }
.status__title { font-size: 14px; }
.formula { padding: 10px 12px; font-size: 13px; line-height: 2; }
.chip { padding: 0 8px; line-height: 24px; }
.num { width: 100%; flex: 1 1 140px; }
.limit .num { width: auto; flex: 1 1 140px; }
.sample { grid-template-columns: 1fr 1fr; gap: 10px; }
.cmp { font-size: 12px; }
.cmp th, .cmp td { padding: 6px; }
}
</style>
+3 -3
View File
@@ -8,7 +8,7 @@
active tab — so the visually-second tab opens first.
-->
<div>
<a-card v-if="hasPermission('config.wallet')" title="مدیریت کیف پول">
<a-card v-if="hasPermission('config.wallet')" title="مدیریت کیف پول" class="page-card">
<a-tabs default-active-key="1">
<a-tab-pane key="2" tab="تاریخ تولد" force-render>
<a-spin :spinning="loading" tip="لطفا کمی تامل کنید">
@@ -29,7 +29,7 @@
<a-input-number v-model:value="form2.birthday_credit" class="w-full" :min="0" />
</a-form-item>
</div>
<a-button type="primary" class="mb-4 mt-4 mr-4" @click="setWallet2">ارسال</a-button>
<a-button type="primary" class="mb-4 mt-4 mr-4 form-submit" @click="setWallet2">ارسال</a-button>
</a-form>
</a-spin>
</a-tab-pane>
@@ -60,7 +60,7 @@
/>
</a-form-item>
</div>
<a-button type="primary" class="mb-4 mt-4 mr-4" @click="setWallet1">ارسال</a-button>
<a-button type="primary" class="mb-4 mt-4 mr-4 form-submit" @click="setWallet1">ارسال</a-button>
</a-form>
</a-spin>
</a-tab-pane>
@@ -3,8 +3,8 @@
Ported from legacy henza_admin/src/views/newsletters/newsletters.vue.
The delete action is COMMENTED OUT in legacy and stays absent.
-->
<a-card title="لیست خبرنامه">
<XTable ref="newsletter" :model="model">
<a-card title="لیست خبرنامه" class="page-card">
<XTable ref="newsletter" :model="model" mobile-cards>
<template #actions="{ record }">
<span class="muted">{{ record.email ?? '-' }}</span>
</template>
+2 -2
View File
@@ -1,7 +1,7 @@
<template>
<!-- Ported from legacy henza_admin/src/views/notify/create.vue. -->
<a-spin :spinning="loading">
<a-card title="ارسال نوتیفیکیشن">
<a-card title="ارسال نوتیفیکیشن" class="page-card">
<a-form layout="vertical" @submit.prevent="handleSubmit">
<div class="grid-2">
<a-form-item label="عنوان" :validate-status="err.title ? 'error' : ''" :help="err.title">
@@ -21,7 +21,7 @@
<a-textarea v-model:value="form.text" :auto-size="{ minRows: 4, maxRows: 8 }" />
</a-form-item>
<a-button type="primary" @click="handleSubmit">ارسال</a-button>
<a-button type="primary" class="form-submit" @click="handleSubmit">ارسال</a-button>
</a-form>
</a-card>
</a-spin>
+3 -3
View File
@@ -3,8 +3,8 @@
Ported from legacy henza_admin/src/views/notify/user.vue — the received
notifications list, with a read-state modal.
-->
<a-card title="لیست نوتیفیکیشن های دریافتی">
<XTable ref="tbl" :model="model">
<a-card title="لیست نوتیفیکیشن های دریافتی" class="page-card">
<XTable ref="tbl" :model="model" mobile-cards>
<template #opt="{ record }">
<a-tooltip title="مشاهده">
<EyeOutlined class="cursor-pointer mx-1 text-primary" @click="view(record)" />
@@ -12,7 +12,7 @@
</template>
</XTable>
<a-modal v-model:open="visible" title="مشاهده نوتیفیکیشن" width="60%">
<a-modal v-model:open="visible" title="مشاهده نوتیفیکیشن" width="60%" wrap-class-name="detail-modal">
<div v-if="tempRow">
<a-descriptions bordered size="small" :column="1">
<a-descriptions-item label="عنوان">{{ tempRow.title }}</a-descriptions-item>
@@ -10,7 +10,7 @@
The card title in legacy is "تعریف تخفیف" (the same string the promotion form
uses) even though this screen defines EXCLUSIONS — preserved, not corrected.
-->
<div id="page-user-view">
<div id="page-user-view" class="page-card">
<div id="user-data">
<a-spin :spinning="loading">
<a-form layout="vertical">
@@ -27,7 +27,7 @@
<template v-if="type === 1">
<h6>تعداد {{ selectedRow.length }} محصول انتخاب شده است</h6>
<XTable ref="tblProducts" v-model="selectedRow" :model="productCols" :has-selection="true">
<XTable ref="tblProducts" v-model="selectedRow" :model="productCols" :has-selection="true" mobile-cards>
<template #image="{ record }">
<img
width="90px"
@@ -42,24 +42,24 @@
<template v-if="type === 2">
<h6>تعداد {{ selectedRow.length }} دسته بندی انتخاب شده است</h6>
<XTable ref="tblCategory" v-model="selectedRow" :model="categoryCols" :has-selection="true" />
<XTable ref="tblCategory" v-model="selectedRow" :model="categoryCols" :has-selection="true" mobile-cards />
<h6>تعداد {{ selectedRow.length }} دسته بندی انتخاب شده است</h6>
</template>
<template v-if="type === 3">
<h6>تعداد {{ selectedRow.length }} مشتری انتخاب شده است</h6>
<XTable ref="tblCustomer" v-model="selectedRow" :model="customerCols" :has-selection="true" />
<XTable ref="tblCustomer" v-model="selectedRow" :model="customerCols" :has-selection="true" mobile-cards />
<h6>تعداد {{ selectedRow.length }} مشتری انتخاب شده است</h6>
</template>
<template v-if="type === 4">
<h6>تعداد {{ selectedRow.length }} برند انتخاب شده است</h6>
<XTable ref="tblBrand" v-model="selectedRow" :model="brandCols" :has-selection="true" />
<XTable ref="tblBrand" v-model="selectedRow" :model="brandCols" :has-selection="true" mobile-cards />
<h6>تعداد {{ selectedRow.length }} برند انتخاب شده است</h6>
</template>
<div class="mt-5">
<a-button type="primary" class="mr-4" @click="handleSubmit">ثبت</a-button>
<a-button type="primary" class="mr-4 form-submit" @click="handleSubmit">ثبت</a-button>
</div>
</a-card>
</a-form>
@@ -221,4 +221,17 @@ onMounted(getData);
.mt-5 {
margin-top: 1.25rem;
}
@media (max-width: 575px) {
.mb-10 {
margin-bottom: 12px;
}
.mt-5 {
margin-top: 12px;
}
h6 {
font-size: 12px;
margin-bottom: 8px;
}
}
</style>
@@ -128,7 +128,7 @@
<!-- route-based fallback for direct links to /major/promotion/(tak/)add and .../edit/:id -->
<a-spin v-else :spinning="loading">
<a-form layout="vertical" @submit.prevent="handleSubmit">
<a-card :title="title" class="mb-base">
<a-card :title="title" class="mb-base page-card">
<div class="grid-4 grid-4--tight">
<a-form-item label="نوع تخفیف">
<!-- legacy disables the type selector while editing -->
@@ -242,7 +242,7 @@
<a-textarea v-model:value="form.description" :auto-size="{ minRows: 3, maxRows: 6 }" />
</a-form-item>
<a-button type="primary" @click="handleSubmit">ثبت اطلاعات</a-button>
<a-button type="primary" class="form-submit" @click="handleSubmit">ثبت اطلاعات</a-button>
</a-card>
</a-form>
</a-spin>
@@ -3,7 +3,7 @@
Ported from legacy henza_admin/src/views/promotion/autopromotion.vue —
the one-shot welcome discount for new customers. State toggle + percentage.
-->
<a-form layout="vertical" @submit.prevent="handleSubmit">
<a-form layout="vertical" class="page-card" @submit.prevent="handleSubmit">
<a-spin :spinning="loading">
<a-card title="تخفیف اتوماتیک یکبار مصرف ویژه مشتریان جدید" class="mb-base">
<div class="grid-3">
@@ -30,7 +30,7 @@
</a-card>
</a-spin>
<a-button type="primary" class="mr-4" @click="handleSubmit">ثبت اطلاعات</a-button>
<a-button type="primary" class="mr-4 form-submit" @click="handleSubmit">ثبت اطلاعات</a-button>
</a-form>
</template>
@@ -7,8 +7,8 @@
commented-out `sts` and `confirmed` slots which stay absent.
-->
<div id="page-user-list">
<a-card title="لیست تخفیف ها">
<XTable ref="tbl" :model="model">
<a-card title="لیست تخفیف ها" class="page-card">
<XTable ref="tbl" :model="model" mobile-cards>
<template #add>
<div class="list-page-header-row">
<ListPageHeader rid="offers.create" add-label="افزودن تخفیف عمده" @add="openAdd('omde')" />
@@ -140,5 +140,12 @@ async function deletePromotion(record: Record<string, any>) {
display: flex;
gap: 0.5rem;
}
@media (max-width: 575px) {
.list-page-header-row {
flex-wrap: wrap;
justify-content: flex-end;
}
}
</style>
@@ -8,9 +8,9 @@
-->
<div id="page-user-list">
<a-spin :spinning="loading">
<a-card title="گزارش تجمیعی سفارشات و اسناد مالی">
<a-card title="گزارش تجمیعی سفارشات و اسناد مالی" class="page-card table-scroll">
<a-form layout="vertical">
<div class="grid-4">
<div class="grid-4 filter-grid">
<DateInput v-model="filters.start_date" label="از تاریخ" />
<DateInput v-model="filters.end_date" label="تا تاریخ" />
<a-form-item label=" ">
@@ -122,4 +122,15 @@ onMounted(load);
.mt-4 {
margin-top: 1rem;
}
@media (max-width: 575px) {
.summary {
flex-wrap: wrap;
row-gap: 6px;
margin-top: 0;
}
.mt-4 {
margin-top: 12px;
}
}
</style>
+13 -2
View File
@@ -5,9 +5,9 @@
-->
<div id="page-user-list">
<a-spin :spinning="loading">
<a-card title="گزارش محصولات">
<a-card title="گزارش محصولات" class="page-card table-scroll">
<a-form layout="vertical">
<div class="grid-4">
<div class="grid-4 filter-grid">
<DateInput v-model="filters.start_date" label="از تاریخ" />
<DateInput v-model="filters.end_date" label="تا تاریخ" />
<a-form-item label=" ">
@@ -80,4 +80,15 @@ onMounted(load);
.mt-4 {
margin-top: 1rem;
}
@media (max-width: 575px) {
.summary {
flex-wrap: wrap;
row-gap: 6px;
margin-top: 0;
}
.mt-4 {
margin-top: 12px;
}
}
</style>
+7 -3
View File
@@ -7,7 +7,7 @@
NOTE the "تک فروشی" audience has a rid (sms.create.tak) but NO option in the
legacy markup, so it is unreachable. Preserved as absent.
-->
<a-spin :spinning="loading">
<a-spin :spinning="loading" class="page-card">
<a-card title="ارسال پیامک">
<a-form layout="vertical" @submit.prevent="handleSubmit">
<div class="grid-2">
@@ -51,12 +51,12 @@
<a-textarea v-model:value="text" :auto-size="{ minRows: 4, maxRows: 8 }" />
</a-form-item>
<a-button type="primary" @click="handleSubmit">ارسال</a-button>
<a-button type="primary" class="form-submit" @click="handleSubmit">ارسال</a-button>
</a-form>
</a-card>
<a-card v-if="hasPermission('sms.list')" title="لیست پیامک ها" class="mt-4">
<XTable ref="tbl" :model="model" />
<XTable ref="tbl" :model="model" mobile-cards />
</a-card>
</a-spin>
</template>
@@ -111,4 +111,8 @@ async function handleSubmit() {
<style scoped>
/* .grid-2 now comes from the global utilities.less (dedup) */
.mt-4 { margin-top: 1rem; }
@media (max-width: 575px) {
.mt-4 { margin-top: 12px; }
}
</style>
+1 -1
View File
@@ -4,7 +4,7 @@
activity log ("آمار"). Pick a customer, see their recent actions.
-->
<a-spin :spinning="loading">
<a-card title="آمار">
<a-card title="آمار" class="page-card table-scroll">
<a-form layout="vertical">
<div class="grid-2">
<a-form-item label="مشتری">
+2 -2
View File
@@ -5,8 +5,8 @@
user-type list, as legacy did.
-->
<div id="page-user-list">
<a-card title="لیست مدیران">
<XTable ref="tbl" :model="model">
<a-card title="لیست مدیران" class="page-card">
<XTable ref="tbl" :model="model" mobile-cards>
<!-- legacy ListUser.vue:4 — the add-user button, gated on the same rid. -->
<template #add>
<ListPageHeader rid="user.list.create" add-label="افزودن کاربر" @add="openAdd" />
+13 -1
View File
@@ -13,7 +13,7 @@
is drawn with a rotated border that lands wrong under [dir=rtl].
-->
<a-form layout="vertical" @submit.prevent="handleSubmit">
<a-card id="rid" title="دسترسی ها">
<a-card id="rid" title="دسترسی ها" class="page-card">
<div class="grid-2">
<a-form-item
label="سطح کاربر"
@@ -52,6 +52,7 @@
<a-button
v-if="!newUT && hasPermission('user.permission.edit')"
type="primary"
class="form-submit"
html-type="submit"
>
ثبت تغییرات
@@ -60,6 +61,7 @@
<a-button
v-if="newUT && hasPermission('user.permission.create')"
type="primary"
class="form-submit"
html-type="submit"
>
افزودن
@@ -211,4 +213,14 @@ onMounted(async () => {
.tree-item {
grid-column: 1 / -1;
}
@media (max-width: 575px) {
/* the permission tree nests deep; a smaller indent keeps titles readable */
.tree-item :deep(.ant-tree-indent-unit) {
width: 14px;
}
.tree-item :deep(.ant-tree-node-content-wrapper) {
white-space: normal;
}
}
</style>
@@ -82,7 +82,7 @@
<!-- route-based fallback for direct links to /user/create and /user/edit/:id -->
<a-spin v-else :spinning="loading">
<a-form layout="vertical" @submit.prevent="handleSubmit">
<a-card :title="id ? 'ویرایش مدیر' : 'افزودن مدیر'" class="mb-base">
<a-card :title="id ? 'ویرایش مدیر' : 'افزودن مدیر'" class="mb-base page-card">
<div class="grid-3">
<a-form-item label="نام" :validate-status="err.fname ? 'error' : ''" :help="err.fname">
<a-input v-model:value="form.fname" />
@@ -139,7 +139,7 @@
<p v-if="id" class="hint">برای تغییر ندادن رمز عبور، هر دو فیلد رمز را خالی بگذارید.</p>
<a-button type="primary" @click="handleSubmit">ثبت اطلاعات</a-button>
<a-button type="primary" class="form-submit" @click="handleSubmit">ثبت اطلاعات</a-button>
</a-card>
</a-form>
</a-spin>
+2 -2
View File
@@ -9,8 +9,8 @@
real title is shown when present, with the same fallback — the fallback is
what legacy actually displayed.
-->
<a-card title="اطلاعات کاربری">
<a-descriptions>
<a-card title="اطلاعات کاربری" class="page-card">
<a-descriptions :column="{ xxl: 3, xl: 3, lg: 3, md: 2, sm: 2, xs: 1 }">
<a-descriptions-item label="نام">{{ user?.fname || '-' }}</a-descriptions-item>
<a-descriptions-item label="نام خانوادگی">{{ user?.lname || '-' }}</a-descriptions-item>
<a-descriptions-item label="شماره تلفن">{{ user?.mobile || '-' }}</a-descriptions-item>
+2 -2
View File
@@ -7,8 +7,8 @@
mismatch, preserved.
-->
<div>
<a-card v-if="hasPermission('wallet.percent')" title="لیست کیف پول های شارژ شده">
<XTable ref="tbl" :model="model">
<a-card v-if="hasPermission('wallet.percent')" title="لیست کیف پول های شارژ شده" class="page-card">
<XTable ref="tbl" :model="model" mobile-cards>
<template #time="{ text }">
{{ text ? jdateTime(text) : '' }}
</template>