diff --git a/apps/web-antd/src/views/store/list/components/StoreEditorDrawer.vue b/apps/web-antd/src/views/store/list/components/StoreEditorDrawer.vue new file mode 100644 index 0000000..c9e096b --- /dev/null +++ b/apps/web-antd/src/views/store/list/components/StoreEditorDrawer.vue @@ -0,0 +1,160 @@ + + + diff --git a/apps/web-antd/src/views/store/list/components/StoreFilterBar.vue b/apps/web-antd/src/views/store/list/components/StoreFilterBar.vue new file mode 100644 index 0000000..541ef76 --- /dev/null +++ b/apps/web-antd/src/views/store/list/components/StoreFilterBar.vue @@ -0,0 +1,105 @@ + + + diff --git a/apps/web-antd/src/views/store/list/components/StoreListTable.vue b/apps/web-antd/src/views/store/list/components/StoreListTable.vue new file mode 100644 index 0000000..e59f2f8 --- /dev/null +++ b/apps/web-antd/src/views/store/list/components/StoreListTable.vue @@ -0,0 +1,150 @@ + + + diff --git a/apps/web-antd/src/views/store/list/components/StoreStatsCards.vue b/apps/web-antd/src/views/store/list/components/StoreStatsCards.vue new file mode 100644 index 0000000..acefb01 --- /dev/null +++ b/apps/web-antd/src/views/store/list/components/StoreStatsCards.vue @@ -0,0 +1,30 @@ + + + diff --git a/apps/web-antd/src/views/store/list/composables/store-list-page/constants.ts b/apps/web-antd/src/views/store/list/composables/store-list-page/constants.ts new file mode 100644 index 0000000..b4a44f6 --- /dev/null +++ b/apps/web-antd/src/views/store/list/composables/store-list-page/constants.ts @@ -0,0 +1,132 @@ +/** + * 门店列表页常量集合: + * - 色值与文案映射 + * - 选项数据 + * - 默认状态 + * - 表格列定义 + */ +import type { + PagePaginationState, + SelectOptionItem, + StatusTagMeta, + StoreFilterState, + StoreFormState, +} from '../../types'; + +import type { + ServiceType, + StoreAuditStatus, + StoreBusinessStatus, + StoreStatsDto, +} from '#/api/store'; + +import { + ServiceType as ServiceTypeEnum, + StoreAuditStatus as StoreAuditStatusEnum, + StoreBusinessStatus as StoreBusinessStatusEnum, +} from '#/api/store'; + +export const THEME_COLORS = { + danger: '#ef4444', + success: '#22c55e', + text: '#1f1f1f', + warning: '#f59e0b', +} as const; + +export const AVATAR_COLORS = [ + '#3b82f6', + '#f59e0b', + '#8b5cf6', + '#ef4444', + '#22c55e', + '#06b6d4', + '#ec4899', + '#f97316', + '#14b8a6', + '#6366f1', +] as const; + +export const DEFAULT_STATS: StoreStatsDto = { + operating: 0, + pendingAudit: 0, + resting: 0, + total: 0, +}; + +export const DEFAULT_PAGINATION: PagePaginationState = { + current: 1, + pageSize: 10, + total: 0, +}; + +export const DEFAULT_FILTERS: StoreFilterState = { + auditStatus: undefined, + businessStatus: undefined, + keyword: '', + serviceType: undefined, +}; + +export const DEFAULT_FORM_STATE: StoreFormState = { + address: '', + businessStatus: StoreBusinessStatusEnum.Operating, + code: '', + contactPhone: '', + coverImage: '', + id: '', + managerName: '', + name: '', + serviceTypes: [ServiceTypeEnum.Delivery], +}; + +export const businessStatusMap: Record = { + [StoreBusinessStatusEnum.ForceClosed]: { color: 'red', text: '强制关闭' }, + [StoreBusinessStatusEnum.Operating]: { color: 'green', text: '营业中' }, + [StoreBusinessStatusEnum.Resting]: { color: 'default', text: '休息中' }, +}; + +export const auditStatusMap: Record = { + [StoreAuditStatusEnum.Approved]: { color: 'green', text: '已通过' }, + [StoreAuditStatusEnum.Pending]: { color: 'orange', text: '待审核' }, + [StoreAuditStatusEnum.Rejected]: { color: 'red', text: '已拒绝' }, +}; + +export const serviceTypeMap: Record = { + [ServiceTypeEnum.Delivery]: { color: 'blue', text: '外卖' }, + [ServiceTypeEnum.DineIn]: { color: 'orange', text: '堂食' }, + [ServiceTypeEnum.Pickup]: { color: 'green', text: '自提' }, +}; + +export const businessStatusOptions: SelectOptionItem[] = [ + { label: '营业中', value: StoreBusinessStatusEnum.Operating }, + { label: '休息中', value: StoreBusinessStatusEnum.Resting }, + { label: '强制关闭', value: StoreBusinessStatusEnum.ForceClosed }, +]; + +export const auditStatusOptions: SelectOptionItem[] = [ + { label: '待审核', value: StoreAuditStatusEnum.Pending }, + { label: '已通过', value: StoreAuditStatusEnum.Approved }, + { label: '已拒绝', value: StoreAuditStatusEnum.Rejected }, +]; + +export const serviceTypeOptions: SelectOptionItem[] = [ + { label: '外卖配送', value: ServiceTypeEnum.Delivery }, + { label: '到店自提', value: ServiceTypeEnum.Pickup }, + { label: '堂食', value: ServiceTypeEnum.DineIn }, +]; + +export const columns = [ + { key: 'storeInfo', title: '门店信息', width: 240 }, + { + dataIndex: 'contactPhone', + key: 'contactPhone', + title: '联系电话', + width: 120, + }, + { dataIndex: 'managerName', key: 'managerName', title: '店长', width: 80 }, + { dataIndex: 'address', ellipsis: true, key: 'address', title: '地址' }, + { key: 'serviceTypes', title: '服务方式', width: 180 }, + { key: 'businessStatus', title: '营业状态', width: 100 }, + { key: 'auditStatus', title: '审核状态', width: 100 }, + { dataIndex: 'createdAt', key: 'createdAt', title: '创建时间', width: 120 }, + { fixed: 'right' as const, key: 'action', title: '操作', width: 180 }, +]; diff --git a/apps/web-antd/src/views/store/list/composables/store-list-page/data-actions.ts b/apps/web-antd/src/views/store/list/composables/store-list-page/data-actions.ts new file mode 100644 index 0000000..0c66b5c --- /dev/null +++ b/apps/web-antd/src/views/store/list/composables/store-list-page/data-actions.ts @@ -0,0 +1,61 @@ +/** + * 门店列表数据加载动作: + * - 列表查询 + * - 统计查询 + */ +import type { Ref } from 'vue'; + +import type { PagePaginationState, StoreFilterState } from '../../types'; + +import type { StoreListItemDto, StoreStatsDto } from '#/api/store'; + +import { getStoreListApi, getStoreStatsApi } from '#/api/store'; + +interface CreateDataActionsOptions { + filters: StoreFilterState; + isLoading: Ref; + pagination: PagePaginationState; + stats: Ref; + storeList: Ref; +} + +export function createDataActions(options: CreateDataActionsOptions) { + /** 加载门店列表并同步分页总数。 */ + async function loadList() { + // 1. 开启加载态。 + options.isLoading.value = true; + try { + // 2. 按当前筛选与分页请求列表。 + const res = await getStoreListApi({ + auditStatus: options.filters.auditStatus, + businessStatus: options.filters.businessStatus, + keyword: options.filters.keyword || undefined, + page: options.pagination.current, + pageSize: options.pagination.pageSize, + serviceType: options.filters.serviceType, + }); + + // 3. 同步结果到页面状态。 + options.storeList.value = res.items; + options.pagination.total = res.total; + } catch (error) { + console.error(error); + } finally { + options.isLoading.value = false; + } + } + + /** 加载门店统计数据。 */ + async function loadStats() { + try { + options.stats.value = await getStoreStatsApi(); + } catch (error) { + console.error(error); + } + } + + return { + loadList, + loadStats, + }; +} diff --git a/apps/web-antd/src/views/store/list/composables/store-list-page/drawer-actions.ts b/apps/web-antd/src/views/store/list/composables/store-list-page/drawer-actions.ts new file mode 100644 index 0000000..ef276e7 --- /dev/null +++ b/apps/web-antd/src/views/store/list/composables/store-list-page/drawer-actions.ts @@ -0,0 +1,89 @@ +/** + * 门店抽屉与删除动作: + * - 打开抽屉(新增/编辑) + * - 提交保存 + * - 删除门店 + */ +import type { Ref } from 'vue'; + +import type { DrawerMode, StoreFormState } from '../../types'; + +import type { StoreListItemDto } from '#/api/store'; + +import { message } from 'ant-design-vue'; + +import { createStoreApi, deleteStoreApi, updateStoreApi } from '#/api/store'; + +import { applyRecordToForm, resetStoreForm, toSavePayload } from './helpers'; + +interface CreateDrawerActionsOptions { + drawerMode: Ref; + formState: StoreFormState; + isDrawerVisible: Ref; + isSubmitting: Ref; + loadList: () => Promise; + loadStats: () => Promise; +} + +export function createDrawerActions(options: CreateDrawerActionsOptions) { + /** 打开抽屉并准备对应模式的数据。 */ + function openDrawer(mode: DrawerMode, record?: StoreListItemDto) { + // 1. 记录当前抽屉模式。 + options.drawerMode.value = mode; + + // 2. 根据模式回填或重置表单。 + if (mode === 'edit' && record) { + applyRecordToForm(options.formState, record); + } else { + resetStoreForm(options.formState); + } + + // 3. 打开抽屉。 + options.isDrawerVisible.value = true; + } + + /** 提交新增/编辑门店。 */ + async function handleSubmit() { + // 1. 开启提交加载态。 + options.isSubmitting.value = true; + try { + // 2. 根据模式调用对应保存接口。 + const payload = toSavePayload(options.formState); + if (options.drawerMode.value === 'edit') { + await updateStoreApi(payload); + message.success('更新成功'); + } else { + await createStoreApi(payload); + message.success('创建成功'); + } + + // 3. 关闭抽屉并刷新页面数据。 + options.isDrawerVisible.value = false; + await Promise.all([options.loadList(), options.loadStats()]); + } catch (error) { + console.error(error); + } finally { + options.isSubmitting.value = false; + } + } + + /** 删除门店并刷新数据。 */ + async function handleDelete(record: StoreListItemDto) { + try { + // 1. 调用删除接口。 + await deleteStoreApi(record.id); + message.success('删除成功'); + + // 2. 同步刷新列表与统计。 + await Promise.all([options.loadList(), options.loadStats()]); + } catch (error) { + console.error(error); + } + } + + return { + handleDelete, + handleSubmit, + openDrawer, + }; +} diff --git a/apps/web-antd/src/views/store/list/composables/store-list-page/helpers.ts b/apps/web-antd/src/views/store/list/composables/store-list-page/helpers.ts new file mode 100644 index 0000000..5aeefad --- /dev/null +++ b/apps/web-antd/src/views/store/list/composables/store-list-page/helpers.ts @@ -0,0 +1,66 @@ +/** + * 门店列表页纯函数工具: + * - 颜色计算 + * - 过滤与表单重置 + * - 保存参数转换 + */ +import type { StoreFilterState, StoreFormState } from '../../types'; + +import type { SaveStoreDto, StoreListItemDto } from '#/api/store'; + +import { + AVATAR_COLORS, + DEFAULT_FILTERS, + DEFAULT_FORM_STATE, +} from './constants'; + +/** 获取门店头像装饰色。 */ +export function getAvatarColor(index: number) { + return AVATAR_COLORS[index % AVATAR_COLORS.length] ?? AVATAR_COLORS[0]; +} + +/** 重置筛选条件为默认值。 */ +export function resetFilters(filters: StoreFilterState) { + Object.assign(filters, DEFAULT_FILTERS); +} + +/** 重置抽屉表单为默认值。 */ +export function resetStoreForm(formState: StoreFormState) { + Object.assign(formState, { + ...DEFAULT_FORM_STATE, + serviceTypes: [...DEFAULT_FORM_STATE.serviceTypes], + }); +} + +/** 按门店记录回填抽屉表单。 */ +export function applyRecordToForm( + formState: StoreFormState, + store: StoreListItemDto, +) { + Object.assign(formState, { + address: store.address, + businessStatus: store.businessStatus, + code: store.code, + contactPhone: store.contactPhone, + coverImage: store.coverImage || '', + id: store.id, + managerName: store.managerName, + name: store.name, + serviceTypes: [...store.serviceTypes], + }); +} + +/** 将表单状态转换为保存接口参数。 */ +export function toSavePayload(formState: StoreFormState): SaveStoreDto { + return { + address: formState.address.trim(), + businessStatus: formState.businessStatus, + code: formState.code.trim(), + contactPhone: formState.contactPhone.trim(), + coverImage: formState.coverImage.trim(), + id: formState.id || undefined, + managerName: formState.managerName.trim(), + name: formState.name.trim(), + serviceTypes: [...formState.serviceTypes], + }; +} diff --git a/apps/web-antd/src/views/store/list/composables/store-list-page/list-actions.ts b/apps/web-antd/src/views/store/list/composables/store-list-page/list-actions.ts new file mode 100644 index 0000000..d4c65fb --- /dev/null +++ b/apps/web-antd/src/views/store/list/composables/store-list-page/list-actions.ts @@ -0,0 +1,56 @@ +/** + * 门店列表交互动作: + * - 查询 + * - 重置 + * - 分页变更 + */ +import type { + PagePaginationState, + StoreFilterState, + TablePagination, +} from '../../types'; + +import { resetFilters } from './helpers'; + +interface CreateListActionsOptions { + filters: StoreFilterState; + loadList: () => Promise; + pagination: PagePaginationState; +} + +export function createListActions(options: CreateListActionsOptions) { + /** 按当前筛选条件查询列表。 */ + async function handleSearch() { + // 1. 查询时回到第一页。 + options.pagination.current = 1; + + // 2. 刷新列表数据。 + await options.loadList(); + } + + /** 重置筛选并刷新列表。 */ + async function handleReset() { + // 1. 清空筛选条件。 + resetFilters(options.filters); + + // 2. 重置页码并刷新列表。 + options.pagination.current = 1; + await options.loadList(); + } + + /** 分页参数变化后刷新列表。 */ + async function handleTableChange(pagination: TablePagination) { + // 1. 同步分页参数。 + options.pagination.current = pagination.current ?? 1; + options.pagination.pageSize = pagination.pageSize ?? 10; + + // 2. 使用新分页重新加载。 + await options.loadList(); + } + + return { + handleReset, + handleSearch, + handleTableChange, + }; +} diff --git a/apps/web-antd/src/views/store/list/composables/useStoreListPage.ts b/apps/web-antd/src/views/store/list/composables/useStoreListPage.ts new file mode 100644 index 0000000..29290ec --- /dev/null +++ b/apps/web-antd/src/views/store/list/composables/useStoreListPage.ts @@ -0,0 +1,224 @@ +/** + * 门店列表页面主编排: + * - 维护页面状态 + * - 组合数据与动作模块 + * - 对外暴露组件可消费的数据与方法 + */ +import type { + DrawerMode, + PagePaginationState, + StatCardItem, + StoreFilterState, + StoreFormState, + StoreTablePagination, +} from '../types'; + +import type { + ServiceType, + StoreAuditStatus, + StoreBusinessStatus, + StoreListItemDto, + StoreStatsDto, +} from '#/api/store'; + +import { computed, onMounted, reactive, ref } from 'vue'; + +import { + auditStatusMap, + auditStatusOptions, + businessStatusMap, + businessStatusOptions, + columns, + DEFAULT_FILTERS, + DEFAULT_FORM_STATE, + DEFAULT_PAGINATION, + DEFAULT_STATS, + serviceTypeMap, + serviceTypeOptions, + THEME_COLORS, +} from './store-list-page/constants'; +import { createDataActions } from './store-list-page/data-actions'; +import { createDrawerActions } from './store-list-page/drawer-actions'; +import { getAvatarColor } from './store-list-page/helpers'; +import { createListActions } from './store-list-page/list-actions'; + +export function useStoreListPage() { + // 1. 列表与筛选状态。 + const isLoading = ref(false); + const storeList = ref([]); + const stats = ref({ ...DEFAULT_STATS }); + const pagination = reactive({ ...DEFAULT_PAGINATION }); + const filters = reactive({ ...DEFAULT_FILTERS }); + + // 2. 抽屉与表单状态。 + const isDrawerVisible = ref(false); + const drawerMode = ref('create'); + const formState = reactive({ + ...DEFAULT_FORM_STATE, + serviceTypes: [...DEFAULT_FORM_STATE.serviceTypes], + }); + const isSubmitting = ref(false); + + // 3. 视图衍生数据。 + const drawerTitle = computed(() => + drawerMode.value === 'edit' ? '编辑门店' : '添加门店', + ); + + const statCards = computed(() => [ + { color: THEME_COLORS.text, title: '门店总数', value: stats.value.total }, + { + color: THEME_COLORS.success, + title: '营业中', + value: stats.value.operating, + }, + { + color: THEME_COLORS.warning, + title: '休息中', + value: stats.value.resting, + }, + { + color: THEME_COLORS.danger, + title: '待审核', + value: stats.value.pendingAudit, + }, + ]); + + const tablePagination = computed(() => ({ + current: pagination.current, + pageSize: pagination.pageSize, + showSizeChanger: true, + showTotal: (total: number) => `共 ${total} 条`, + total: pagination.total, + })); + + // 4. 组装数据加载动作。 + const { loadList, loadStats } = createDataActions({ + filters, + isLoading, + pagination, + stats, + storeList, + }); + + // 5. 组装列表交互动作。 + const { handleReset, handleSearch, handleTableChange } = createListActions({ + filters, + loadList, + pagination, + }); + + // 6. 组装抽屉与删除动作。 + const { handleDelete, handleSubmit, openDrawer } = createDrawerActions({ + drawerMode, + formState, + isDrawerVisible, + isSubmitting, + loadList, + loadStats, + }); + + // 7. 筛选字段更新方法。 + function setKeyword(value: string) { + filters.keyword = value; + } + + function setBusinessStatus(value?: StoreBusinessStatus) { + filters.businessStatus = value; + } + + function setAuditStatus(value?: StoreAuditStatus) { + filters.auditStatus = value; + } + + function setServiceType(value?: ServiceType) { + filters.serviceType = value; + } + + // 8. 抽屉表单字段更新方法。 + function setDrawerVisible(value: boolean) { + isDrawerVisible.value = value; + } + + function setFormName(value: string) { + formState.name = value; + } + + function setFormCode(value: string) { + formState.code = value; + } + + function setFormContactPhone(value: string) { + formState.contactPhone = value; + } + + function setFormManagerName(value: string) { + formState.managerName = value; + } + + function setFormAddress(value: string) { + formState.address = value; + } + + function setFormBusinessStatus(value: StoreBusinessStatus) { + formState.businessStatus = value; + } + + function setFormServiceTypes(value: ServiceType[]) { + formState.serviceTypes = value; + } + + // 9. 抽屉便捷入口。 + function openCreateDrawer() { + openDrawer('create'); + } + + function openEditDrawer(record: StoreListItemDto) { + openDrawer('edit', record); + } + + // 10. 页面初始化。 + onMounted(() => { + loadList(); + loadStats(); + }); + + return { + auditStatusMap, + auditStatusOptions, + businessStatusMap, + businessStatusOptions, + columns, + drawerTitle, + filters, + formState, + getAvatarColor, + handleDeleteStore: handleDelete, + handleReset, + handleSearch, + handleSubmitStore: handleSubmit, + handleTableChange, + isDrawerVisible, + isLoading, + isSubmitting, + openCreateDrawer, + openEditDrawer, + pagination, + serviceTypeMap, + serviceTypeOptions, + setAuditStatus, + setBusinessStatus, + setDrawerVisible, + setFormAddress, + setFormBusinessStatus, + setFormCode, + setFormContactPhone, + setFormManagerName, + setFormName, + setFormServiceTypes, + setKeyword, + setServiceType, + statCards, + storeList, + tablePagination, + }; +} diff --git a/apps/web-antd/src/views/store/list/index.vue b/apps/web-antd/src/views/store/list/index.vue index 297955c..a9bd700 100644 --- a/apps/web-antd/src/views/store/list/index.vue +++ b/apps/web-antd/src/views/store/list/index.vue @@ -1,557 +1,129 @@ + + diff --git a/apps/web-antd/src/views/store/list/styles/base.less b/apps/web-antd/src/views/store/list/styles/base.less new file mode 100644 index 0000000..f7729b0 --- /dev/null +++ b/apps/web-antd/src/views/store/list/styles/base.less @@ -0,0 +1,35 @@ +/* 门店列表页基础布局(头部、筛选、统计)样式。 */ +.page-store-list { + .store-list-page-extra { + display: flex; + gap: 8px; + align-items: center; + } + + .store-filter-card .ant-card-body { + padding: 12px 16px; + } + + .store-filter-row { + display: flex; + flex-wrap: wrap; + gap: 12px; + align-items: center; + } + + .filter-search { + width: 260px; + } + + .filter-select { + width: 130px; + } + + .store-stats-row .ant-card { + transition: transform 0.2s ease; + } + + .store-stats-row .ant-card:hover { + transform: translateY(-1px); + } +} diff --git a/apps/web-antd/src/views/store/list/styles/drawer.less b/apps/web-antd/src/views/store/list/styles/drawer.less new file mode 100644 index 0000000..0569778 --- /dev/null +++ b/apps/web-antd/src/views/store/list/styles/drawer.less @@ -0,0 +1,50 @@ +/* 门店编辑抽屉样式。 */ +.store-editor-drawer-wrap { + .ant-drawer-content-wrapper { + box-shadow: + 0 8px 24px rgb(0 0 0 / 8%), + 0 2px 6px rgb(0 0 0 / 4%); + } + + .ant-drawer-header { + min-height: 56px; + padding: 0 24px; + border-bottom: 1px solid #f0f0f0; + } + + .ant-drawer-title { + font-size: 16px; + font-weight: 600; + color: #1f1f1f; + } + + .ant-drawer-body { + padding: 20px 24px; + } + + .ant-drawer-footer { + padding: 14px 24px; + border-top: 1px solid #f0f0f0; + } +} + +.page-store-list { + .store-drawer-form .store-drawer-section-title { + margin: 0 0 16px; + padding-left: 10px; + font-size: 15px; + font-weight: 600; + color: #1f1f1f; + border-left: 3px solid #1677ff; + } + + .store-drawer-form .store-drawer-section-title + .ant-form-item { + margin-top: 2px; + } + + .store-drawer-footer { + display: flex; + gap: 8px; + justify-content: flex-end; + } +} diff --git a/apps/web-antd/src/views/store/list/styles/index.less b/apps/web-antd/src/views/store/list/styles/index.less new file mode 100644 index 0000000..4deea49 --- /dev/null +++ b/apps/web-antd/src/views/store/list/styles/index.less @@ -0,0 +1,5 @@ +/* 门店列表页面样式聚合入口(仅负责分片导入)。 */ +@import './base.less'; +@import './table.less'; +@import './drawer.less'; +@import './responsive.less'; diff --git a/apps/web-antd/src/views/store/list/styles/responsive.less b/apps/web-antd/src/views/store/list/styles/responsive.less new file mode 100644 index 0000000..6be9d88 --- /dev/null +++ b/apps/web-antd/src/views/store/list/styles/responsive.less @@ -0,0 +1,18 @@ +/* 门店列表页响应式样式。 */ +@media (max-width: 768px) { + .page-store-list { + .store-list-page-extra { + gap: 6px; + } + + .filter-search { + width: 100%; + min-width: 0; + } + + .filter-select { + width: calc(50% - 6px); + min-width: 0; + } + } +} diff --git a/apps/web-antd/src/views/store/list/styles/table.less b/apps/web-antd/src/views/store/list/styles/table.less new file mode 100644 index 0000000..3307e71 --- /dev/null +++ b/apps/web-antd/src/views/store/list/styles/table.less @@ -0,0 +1,50 @@ +/* 门店列表表格区样式。 */ +.page-store-list { + .store-list-table .store-info-cell { + display: flex; + gap: 12px; + align-items: center; + } + + .store-list-table .store-avatar { + display: flex; + flex-shrink: 0; + align-items: center; + justify-content: center; + width: 36px; + height: 36px; + color: #fff; + border-radius: 10px; + } + + .store-list-table .store-info-text { + min-width: 0; + } + + .store-list-table .store-name { + overflow: hidden; + font-size: 14px; + font-weight: 500; + color: #1f1f1f; + text-overflow: ellipsis; + white-space: nowrap; + } + + .store-list-table .store-code { + margin-top: 2px; + font-size: 12px; + color: #9ca3af; + } + + .store-list-table .service-tag { + margin-inline-end: 6px; + margin-bottom: 4px; + } + + .store-list-table .store-action-row { + display: flex; + gap: 8px; + align-items: center; + white-space: nowrap; + } +} diff --git a/apps/web-antd/src/views/store/list/types.ts b/apps/web-antd/src/views/store/list/types.ts new file mode 100644 index 0000000..69ef862 --- /dev/null +++ b/apps/web-antd/src/views/store/list/types.ts @@ -0,0 +1,75 @@ +/** + * 门店列表页专属类型定义: + * - 页面状态(筛选、分页、抽屉表单) + * - 组件交互参数 + */ +import type { + ServiceType, + StoreAuditStatus, + StoreBusinessStatus, +} from '#/api/store'; + +/** 表格分页变更参数。 */ +export interface TablePagination { + current?: number; + pageSize?: number; +} + +/** 下拉选项通用结构。 */ +export interface SelectOptionItem { + label: string; + value: T; +} + +/** 页面分页状态。 */ +export interface PagePaginationState { + current: number; + pageSize: number; + total: number; +} + +/** 页面筛选条件。 */ +export interface StoreFilterState { + auditStatus?: StoreAuditStatus; + businessStatus?: StoreBusinessStatus; + keyword: string; + serviceType?: ServiceType; +} + +/** 抽屉表单状态。 */ +export interface StoreFormState { + address: string; + businessStatus: StoreBusinessStatus; + code: string; + contactPhone: string; + coverImage: string; + id: string; + managerName: string; + name: string; + serviceTypes: ServiceType[]; +} + +/** 状态标签元信息。 */ +export interface StatusTagMeta { + color: string; + text: string; +} + +/** 统计卡片项。 */ +export interface StatCardItem { + color: string; + title: string; + value: number; +} + +/** 抽屉模式。 */ +export type DrawerMode = 'create' | 'edit'; + +/** 表格分页展示对象。 */ +export interface StoreTablePagination { + current: number; + pageSize: number; + showSizeChanger: boolean; + showTotal: (total: number) => string; + total: number; +}