feat(admin-panel): responsive branches, workshops, products and orders
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -171,4 +171,36 @@ body #app .ant-menu-item-selected {
|
||||
.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,
|
||||
.detail-modal .ant-table-content {
|
||||
overflow-x: auto;
|
||||
}
|
||||
.page-card .table-scroll .ant-table-content > table,
|
||||
.detail-modal .ant-table-content > table {
|
||||
min-width: max-content;
|
||||
}
|
||||
|
||||
// View/status modals (wrap-class-name="detail-modal"): near full width on
|
||||
// phones instead of a percentage of an already narrow screen.
|
||||
.detail-modal .ant-modal {
|
||||
width: calc(100vw - 16px) !important;
|
||||
max-width: none;
|
||||
top: 8px;
|
||||
margin: 0 auto;
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
.detail-modal .ant-modal-content {
|
||||
padding: 14px 12px;
|
||||
}
|
||||
.detail-modal .ant-card-head {
|
||||
min-height: 40px;
|
||||
padding: 0 12px;
|
||||
}
|
||||
.detail-modal .ant-card-body {
|
||||
padding: 12px;
|
||||
}
|
||||
.detail-modal .ant-descriptions-item {
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,9 +124,31 @@
|
||||
<div v-if="cardMode" class="x-table__cards">
|
||||
<a-spin :spinning="loading">
|
||||
<a-empty v-if="!data.length && !loading" :description="locale.emptyText" />
|
||||
<div v-for="record in data" :key="String(record.id)" class="x-card">
|
||||
<a-checkbox
|
||||
v-if="hasSelection && data.length"
|
||||
class="x-table__select-all"
|
||||
:checked="allOnPageSelected"
|
||||
:indeterminate="someOnPageSelected && !allOnPageSelected"
|
||||
@change="(e: any) => selectPage(e.target.checked)"
|
||||
>
|
||||
انتخاب همه در این صفحه
|
||||
</a-checkbox>
|
||||
<div
|
||||
v-for="record in data"
|
||||
:key="String(record.id)"
|
||||
class="x-card"
|
||||
:class="{ 'x-card--selected': hasSelection && isSelected(record) }"
|
||||
>
|
||||
<div class="x-card__head">
|
||||
<div class="x-card__title">
|
||||
<a-checkbox
|
||||
v-if="hasSelection"
|
||||
:checked="isSelected(record)"
|
||||
@change="(e: any) => toggleRow(record, e.target.checked)"
|
||||
/>
|
||||
<span v-if="cardMediaCol" class="x-card__media">
|
||||
<slot :name="cardMediaCol.slot" :text="cellValue(record, cardMediaCol)" :record="record" />
|
||||
</span>
|
||||
<span v-if="cardIdCol" class="x-card__id">#{{ cellValue(record, cardIdCol) }}</span>
|
||||
<span class="x-card__name">
|
||||
<template v-for="col in cardTitleCols" :key="col.key">
|
||||
@@ -216,8 +238,7 @@ const props = withDefaults(
|
||||
);
|
||||
|
||||
const layout = useLayoutStore();
|
||||
// row selection needs the table's checkbox column, so it always keeps the table
|
||||
const cardMode = computed(() => props.mobileCards && !props.hasSelection && layout.isMobile);
|
||||
const cardMode = computed(() => props.mobileCards && layout.isMobile);
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'query', q: unknown): void;
|
||||
@@ -321,8 +342,11 @@ const cardCols = computed<CardCol[]>(() =>
|
||||
);
|
||||
const cardActionCol = computed(() => cardCols.value.find((c) => ACTION_KEYS.includes(c.key) && c.slot));
|
||||
const cardIdCol = computed(() => cardCols.value.find((c) => c.key === 'id'));
|
||||
const cardMediaCol = computed(() => cardCols.value.find((c) => c.slot === 'image'));
|
||||
const cardTitleCols = computed<CardCol[]>(() => {
|
||||
const rest = cardCols.value.filter((c) => c !== cardActionCol.value && c !== cardIdCol.value);
|
||||
const rest = cardCols.value.filter(
|
||||
(c) => c !== cardActionCol.value && c !== cardIdCol.value && c !== cardMediaCol.value,
|
||||
);
|
||||
const named = rest.find((c) => c.key === 'name' || c.key === 'title');
|
||||
if (named) return [named];
|
||||
const fname = rest.find((c) => c.key === 'fname');
|
||||
@@ -331,10 +355,30 @@ const cardTitleCols = computed<CardCol[]>(() => {
|
||||
});
|
||||
const cardBodyCols = computed(() =>
|
||||
cardCols.value.filter(
|
||||
(c) => c !== cardActionCol.value && c !== cardIdCol.value && !cardTitleCols.value.includes(c),
|
||||
(c) =>
|
||||
c !== cardActionCol.value &&
|
||||
c !== cardIdCol.value &&
|
||||
c !== cardMediaCol.value &&
|
||||
!cardTitleCols.value.includes(c),
|
||||
),
|
||||
);
|
||||
|
||||
// card-mode selection, same v-model contract as the table's rowSelection
|
||||
function isSelected(record: Record<string, unknown>) {
|
||||
return props.modelValue.some((r) => r.id === record.id);
|
||||
}
|
||||
function toggleRow(record: Record<string, unknown>, checked: boolean) {
|
||||
const rest = props.modelValue.filter((r) => r.id !== record.id);
|
||||
emit('update:modelValue', checked ? [...rest, record] : rest);
|
||||
}
|
||||
const allOnPageSelected = computed(() => data.value.length > 0 && data.value.every(isSelected));
|
||||
const someOnPageSelected = computed(() => data.value.some(isSelected));
|
||||
function selectPage(checked: boolean) {
|
||||
const pageIds = new Set(data.value.map((r) => r.id));
|
||||
const rest = props.modelValue.filter((r) => !pageIds.has(r.id));
|
||||
emit('update:modelValue', checked ? [...rest, ...data.value] : rest);
|
||||
}
|
||||
|
||||
function cellValue(record: Record<string, unknown>, col: CardCol): unknown {
|
||||
return col.path.reduce<unknown>(
|
||||
(v, k) => (v && typeof v === 'object' ? (v as Record<string, unknown>)[k] : undefined),
|
||||
@@ -604,6 +648,26 @@ defineExpose({ fetch });
|
||||
flex-shrink: 0;
|
||||
font-size: 16px;
|
||||
}
|
||||
.x-card--selected {
|
||||
border-color: #91caff;
|
||||
}
|
||||
.x-card--selected .x-card__head {
|
||||
background: #f0f7ff;
|
||||
}
|
||||
.x-card__media {
|
||||
flex-shrink: 0;
|
||||
display: inline-flex;
|
||||
}
|
||||
.x-card__media :deep(img) {
|
||||
width: 44px !important;
|
||||
height: 44px !important;
|
||||
object-fit: cover !important;
|
||||
border-radius: 6px;
|
||||
}
|
||||
.x-table__select-all {
|
||||
font-size: 12px;
|
||||
color: #8a909c;
|
||||
}
|
||||
.x-card__body {
|
||||
margin: 0;
|
||||
padding: 4px 12px;
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
column on ProductImage and is dropped, same as the other schema-less fields
|
||||
noted above.
|
||||
-->
|
||||
<div id="page-user-view">
|
||||
<div id="page-user-view" class="page-card">
|
||||
<a-form layout="vertical" @submit.prevent="handleSubmit">
|
||||
<a-spin :spinning="loading">
|
||||
<a-card title="تصاویر محصول" class="mb-base">
|
||||
@@ -150,7 +150,7 @@
|
||||
</a-card>
|
||||
|
||||
<!-- تنوع ها -->
|
||||
<a-card v-if="hasPermission('product.list.variants')" class="mb-8 overflow-auto">
|
||||
<a-card v-if="hasPermission('product.list.variants')" class="mb-8 overflow-auto table-scroll">
|
||||
<template #title>
|
||||
<div class="flex">
|
||||
<div class="flex-1">تنوع ها</div>
|
||||
@@ -199,7 +199,7 @@
|
||||
</a-card>
|
||||
|
||||
<div>
|
||||
<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-spin>
|
||||
</a-form>
|
||||
@@ -583,4 +583,10 @@ onMounted(async () => {
|
||||
.overflow-auto {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
@media (max-width: 575px) {
|
||||
.mb-8 {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
wage percentage to all of them. Farsi copy preserved.
|
||||
-->
|
||||
<div id="page-user-list">
|
||||
<a-card title="تغییر درصد محصولات">
|
||||
<a-card title="تغییر درصد محصولات" class="page-card">
|
||||
<a-form layout="vertical">
|
||||
<div class="grid-3">
|
||||
<a-form-item label="دسته بندی">
|
||||
@@ -53,7 +53,7 @@
|
||||
cancel-text="خیر"
|
||||
@confirm="applyChange"
|
||||
>
|
||||
<a-button type="primary" :loading="changeLoading">اعمال تغییرات</a-button>
|
||||
<a-button type="primary" class="form-submit" :loading="changeLoading">اعمال تغییرات</a-button>
|
||||
</a-popconfirm>
|
||||
</a-form>
|
||||
</a-card>
|
||||
|
||||
@@ -5,18 +5,19 @@
|
||||
preserved. The commented-out "تنوع ها" action stays absent, as in legacy.
|
||||
-->
|
||||
<div id="page-user-list">
|
||||
<a-card title="لیست محصولات">
|
||||
<a-card title="لیست محصولات" class="page-card">
|
||||
<template #extra>
|
||||
<!-- D27 §12: کارساخته و موجودی از حسابداری -->
|
||||
<AccountingSyncButton v-if="hasPermission('product.list')" endpoint="admin/products/accounting-sync" @done="tblProducts?.fetch()" />
|
||||
</template>
|
||||
<h6>تعداد {{ selectedRows.length }} محصول انتخاب شده است.</h6>
|
||||
<h6 class="selected-count">تعداد {{ selectedRows.length }} محصول انتخاب شده است.</h6>
|
||||
|
||||
<XTable
|
||||
ref="tblProducts"
|
||||
v-model="selectedRows"
|
||||
:model="model"
|
||||
:has-selection="true"
|
||||
mobile-cards
|
||||
>
|
||||
<template #image="{ record }">
|
||||
<img
|
||||
@@ -72,9 +73,9 @@
|
||||
</XTable>
|
||||
|
||||
<!-- اطلاعات جامع -->
|
||||
<a-modal v-model:open="visibleProduct" title="اطلاعات جامع محصول" width="70%">
|
||||
<a-modal v-model:open="visibleProduct" 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.title }}</a-descriptions-item>
|
||||
<a-descriptions-item label="کد محصول">{{ tempRow.product_code || '-' }}</a-descriptions-item>
|
||||
<a-descriptions-item label="برند">{{ tempRow.brand?.title || '-' }}</a-descriptions-item>
|
||||
@@ -182,4 +183,15 @@ function toEdit(id: string) {
|
||||
object-fit: cover;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
@media (max-width: 575px) {
|
||||
/* the actions sit in the card header on phones; a fixed 12rem would crowd the title */
|
||||
.w-48 {
|
||||
width: auto;
|
||||
}
|
||||
.selected-count {
|
||||
font-size: 12px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
<!-- route-based fallback for direct links to /branch/add and /branch/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-2">
|
||||
<a-form-item label="نام شعبه" :validate-status="err.name ? 'error' : ''" :help="err.name">
|
||||
<a-input v-model:value="form.name" />
|
||||
@@ -81,7 +81,7 @@
|
||||
<a-textarea v-model:value="form.address" :auto-size="{ minRows: 2, 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>
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
workshop use different forms), so this component stays generic instead of
|
||||
growing a v-if per caller.
|
||||
-->
|
||||
<a-card :title="title">
|
||||
<XTable ref="tbl" :model="model">
|
||||
<a-card :title="title" class="page-card">
|
||||
<XTable ref="tbl" :model="model" mobile-cards>
|
||||
<template v-if="addRid" #add>
|
||||
<ListPageHeader :rid="addRid" :add-label="addLabel" @add="openAdd()" />
|
||||
</template>
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
syntax becomes Vue 3 named slots.
|
||||
-->
|
||||
<div id="page-user-list">
|
||||
<a-card :title="is_branch ? 'لیست سفارش' : 'لیست سفارش های تک فروشی'">
|
||||
<XTable ref="tbl" :model="model">
|
||||
<a-card :title="is_branch ? 'لیست سفارش' : 'لیست سفارش های تک فروشی'" class="page-card">
|
||||
<XTable ref="tbl" :model="model" mobile-cards>
|
||||
<template #opt="{ record }">
|
||||
<div class="flex">
|
||||
<TooltipBtn
|
||||
@@ -51,7 +51,7 @@
|
||||
</XTable>
|
||||
|
||||
<!-- وضعیت سفارش -->
|
||||
<a-modal v-model:open="visibleSts" title="وضعیت سفارش">
|
||||
<a-modal v-model:open="visibleSts" title="وضعیت سفارش" wrap-class-name="detail-modal">
|
||||
<a-timeline v-if="tempRow">
|
||||
<a-timeline-item
|
||||
v-for="(item, index) in tempRow.activity"
|
||||
@@ -93,7 +93,7 @@
|
||||
</a-modal>
|
||||
|
||||
<!-- مشاهده سفارش -->
|
||||
<a-modal v-model:open="visibleList" title="مشاهده سفارش" width="80%">
|
||||
<a-modal v-model:open="visibleList" title="مشاهده سفارش" width="80%" wrap-class-name="detail-modal">
|
||||
<div v-if="tempRow">
|
||||
<a-descriptions>
|
||||
<a-descriptions-item label="مشتری">
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
delete action and the report link are COMMENTED OUT in legacy and 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 #name="{ record }">
|
||||
{{ record.customer?.name }}
|
||||
</template>
|
||||
@@ -41,6 +41,7 @@
|
||||
v-model:open="visibleList"
|
||||
title="مشاهده سفارش"
|
||||
width="80%"
|
||||
wrap-class-name="detail-modal"
|
||||
@cancel="onCloseDetail"
|
||||
>
|
||||
<div v-if="tempRow">
|
||||
@@ -69,7 +70,7 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div class="flex gap-8">
|
||||
<div class="flex gap-8 make-detail">
|
||||
<div>
|
||||
<img
|
||||
v-if="tempRow.designImageUrl"
|
||||
@@ -220,4 +221,14 @@ function onCloseDetail() {
|
||||
.mr-3 {
|
||||
margin-left: 0.75rem;
|
||||
}
|
||||
|
||||
@media (max-width: 575px) {
|
||||
.make-detail {
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
.make-detail > .flex {
|
||||
min-width: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
report endpoint directly) but now points at the new API.
|
||||
-->
|
||||
<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 #city="{ text }">
|
||||
<div v-if="text">{{ getCity(text) }}</div>
|
||||
<div v-else>-</div>
|
||||
@@ -55,7 +55,7 @@
|
||||
</XTable>
|
||||
|
||||
<!-- وضعیت سفارش -->
|
||||
<a-modal v-model:open="visibleSts" title="وضعیت سفارش">
|
||||
<a-modal v-model:open="visibleSts" title="وضعیت سفارش" wrap-class-name="detail-modal">
|
||||
<a-timeline v-if="tempRow">
|
||||
<a-timeline-item
|
||||
v-for="(item, index) in tempRow.activity"
|
||||
@@ -97,7 +97,7 @@
|
||||
</a-modal>
|
||||
|
||||
<!-- مشاهده سفارش -->
|
||||
<a-modal v-model:open="visibleList" title="مشاهده سفارش" width="80%">
|
||||
<a-modal v-model:open="visibleList" title="مشاهده سفارش" width="80%" wrap-class-name="detail-modal">
|
||||
<div v-if="tempRow">
|
||||
<a-descriptions>
|
||||
<a-descriptions-item label="مشتری">
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
the legacy markup but is COMMENTED OUT — preserved as absent, not re-added.
|
||||
-->
|
||||
<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 }">
|
||||
<div class="flex">
|
||||
<TooltipBtn
|
||||
@@ -42,7 +42,7 @@
|
||||
</XTable>
|
||||
|
||||
<!-- وضعیت سفارش -->
|
||||
<a-modal v-model:open="visibleSts" title="وضعیت سفارش">
|
||||
<a-modal v-model:open="visibleSts" title="وضعیت سفارش" wrap-class-name="detail-modal">
|
||||
<a-timeline v-if="tempRow">
|
||||
<a-timeline-item
|
||||
v-for="(item, index) in tempRow.activity"
|
||||
@@ -84,7 +84,7 @@
|
||||
</a-modal>
|
||||
|
||||
<!-- مشاهده سفارش -->
|
||||
<a-modal v-model:open="visibleList" title="مشاهده سفارش" width="80%">
|
||||
<a-modal v-model:open="visibleList" title="مشاهده سفارش" width="80%" wrap-class-name="detail-modal">
|
||||
<div v-if="tempRow">
|
||||
<a-descriptions>
|
||||
<a-descriptions-item label="مشتری">
|
||||
|
||||
@@ -13,8 +13,8 @@
|
||||
inventing a Rial figure — see docs/ADMIN-PORT-PLAN.md.
|
||||
-->
|
||||
<a-spin v-if="hasPermission('order.create')" :spinning="loading">
|
||||
<a-card title="لیست محصولات">
|
||||
<XTable ref="tblProducts" :model="cols">
|
||||
<a-card title="لیست محصولات" class="page-card">
|
||||
<XTable ref="tblProducts" :model="cols" mobile-cards>
|
||||
<template #image="{ record }">
|
||||
<img
|
||||
width="90px"
|
||||
@@ -42,7 +42,15 @@
|
||||
</XTable>
|
||||
|
||||
<a-card v-if="items.length > 0" title="ثبت سفارش" class="mt-5">
|
||||
<a-table :columns="columns" :data-source="items" bordered :pagination="false" row-key="vid">
|
||||
<a-table
|
||||
:columns="columns"
|
||||
:data-source="items"
|
||||
bordered
|
||||
:pagination="false"
|
||||
row-key="vid"
|
||||
:size="layout.isMobile ? 'small' : 'middle'"
|
||||
:scroll="layout.isSmallScreen ? { x: 'max-content' } : undefined"
|
||||
>
|
||||
<template #bodyCell="{ column, record, index }">
|
||||
<template v-if="column.dataIndex === 'delete'">
|
||||
<CloseOutlined class="cursor-pointer" @click="cart.remove(record)" />
|
||||
@@ -170,7 +178,7 @@
|
||||
|
||||
<a-button
|
||||
type="primary"
|
||||
class="mt-4"
|
||||
class="mt-4 form-submit"
|
||||
:disabled="!items || items.length < 1"
|
||||
@click="submitOrder"
|
||||
>
|
||||
@@ -197,9 +205,11 @@ import { buildProductListModel } from '../apps/product/productListModel';
|
||||
import { useCartStore, type CartItem, type CartVariant } from '../../stores/cart';
|
||||
import { useUsersStore } from '../../stores/users';
|
||||
import { useAuthStore } from '../../stores/auth';
|
||||
import { useLayoutStore } from '../../stores/layout';
|
||||
import api from '../../api/client';
|
||||
|
||||
const router = useRouter();
|
||||
const layout = useLayoutStore();
|
||||
const users = useUsersStore();
|
||||
const auth = useAuthStore();
|
||||
const cart = useCartStore();
|
||||
@@ -421,4 +431,24 @@ onMounted(async () => {
|
||||
.totals {
|
||||
margin: 1rem 0;
|
||||
}
|
||||
|
||||
@media (max-width: 575px) {
|
||||
.grid-5 {
|
||||
grid-template-columns: 1fr 1fr;
|
||||
column-gap: 12px;
|
||||
row-gap: 0;
|
||||
}
|
||||
.grid-5 > :first-child {
|
||||
grid-column: 1 / -1;
|
||||
}
|
||||
.mt-5 {
|
||||
margin-top: 12px;
|
||||
}
|
||||
.mt-4 {
|
||||
margin-top: 12px;
|
||||
}
|
||||
.totals {
|
||||
margin: 0 0 12px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
<!-- route-based fallback for direct links to /workshop/add and /workshop/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="نام کارگاه"
|
||||
@@ -96,7 +96,7 @@
|
||||
<a-textarea v-model:value="form.workshop_address" :auto-size="{ minRows: 2, 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>
|
||||
|
||||
Reference in New Issue
Block a user