feat(member): implement points mall module pages
This commit is contained in:
309
apps/web-antd/src/views/member/points-mall/index.vue
Normal file
309
apps/web-antd/src/views/member/points-mall/index.vue
Normal file
@@ -0,0 +1,309 @@
|
||||
<script setup lang="ts">
|
||||
import { Page } from '@vben/common-ui';
|
||||
|
||||
import { Empty, Select, Spin } from 'ant-design-vue';
|
||||
|
||||
import PointsMallProductCard from './components/PointsMallProductCard.vue';
|
||||
import PointsMallProductEditorDrawer from './components/PointsMallProductEditorDrawer.vue';
|
||||
import PointsMallProductPickerModal from './components/PointsMallProductPickerModal.vue';
|
||||
import PointsMallProductToolbar from './components/PointsMallProductToolbar.vue';
|
||||
import PointsMallRecordDetailDrawer from './components/PointsMallRecordDetailDrawer.vue';
|
||||
import PointsMallRecordStatsCards from './components/PointsMallRecordStatsCards.vue';
|
||||
import PointsMallRecordTable from './components/PointsMallRecordTable.vue';
|
||||
import PointsMallRecordToolbar from './components/PointsMallRecordToolbar.vue';
|
||||
import PointsMallRulePanel from './components/PointsMallRulePanel.vue';
|
||||
import PointsMallRuleStatsCards from './components/PointsMallRuleStatsCards.vue';
|
||||
import PointsMallVerifyDrawer from './components/PointsMallVerifyDrawer.vue';
|
||||
import { useMemberPointsMallPage } from './composables/useMemberPointsMallPage';
|
||||
|
||||
const {
|
||||
activeTab,
|
||||
applyProductFilters,
|
||||
applyRecordFilters,
|
||||
canManage,
|
||||
canView,
|
||||
couponOptions,
|
||||
detailRecord,
|
||||
drawerSubmitText,
|
||||
drawerTitle,
|
||||
exportRecords,
|
||||
hasStore,
|
||||
handleRecordPageChange,
|
||||
isDetailLoading,
|
||||
isDetailOpen,
|
||||
isDrawerLoading,
|
||||
isDrawerOpen,
|
||||
isDrawerSubmitting,
|
||||
isExporting,
|
||||
isPickerLoading,
|
||||
isPickerOpen,
|
||||
isProductLoading,
|
||||
isRecordLoading,
|
||||
isRuleLoading,
|
||||
isRuleSubmitting,
|
||||
isStoreLoading,
|
||||
isVerifyLoading,
|
||||
isVerifyOpen,
|
||||
isVerifySubmitting,
|
||||
openCreateProduct,
|
||||
openDetailDrawer,
|
||||
openEditProduct,
|
||||
openProductPickerDrawer,
|
||||
openVerifyDrawer,
|
||||
pickerKeyword,
|
||||
pickerRows,
|
||||
pickerSelectedId,
|
||||
productFilterForm,
|
||||
productForm,
|
||||
productRows,
|
||||
recordFilterForm,
|
||||
recordPager,
|
||||
recordStats,
|
||||
removeProduct,
|
||||
resetProductFilters,
|
||||
resetRecordFilters,
|
||||
ruleForm,
|
||||
ruleStats,
|
||||
saveRule,
|
||||
selectedStoreId,
|
||||
setActiveTab,
|
||||
setDetailOpen,
|
||||
setDrawerOpen,
|
||||
setFormCashAmount,
|
||||
setFormCouponTemplateId,
|
||||
setFormDescription,
|
||||
setFormExchangeType,
|
||||
setFormImageUrl,
|
||||
setFormName,
|
||||
setFormPerMemberLimit,
|
||||
setFormPhysicalName,
|
||||
setFormPickupMethod,
|
||||
setFormRedeemType,
|
||||
setFormRequiredPoints,
|
||||
setFormStatus,
|
||||
setFormStockTotal,
|
||||
setPickedProductId,
|
||||
setPickerKeyword,
|
||||
setPickerOpen,
|
||||
setProductKeyword,
|
||||
setProductStatusFilter,
|
||||
setRecordKeyword,
|
||||
setRecordRedeemType,
|
||||
setRecordStatus,
|
||||
setRuleConsumeAmountPerStep,
|
||||
setRuleConsumeRewardEnabled,
|
||||
setRuleConsumeRewardPointsPerStep,
|
||||
setRuleExpiryMode,
|
||||
setRuleRegisterRewardEnabled,
|
||||
setRuleRegisterRewardPoints,
|
||||
setRuleReviewRewardEnabled,
|
||||
setRuleReviewRewardPoints,
|
||||
setRuleSigninRewardEnabled,
|
||||
setRuleSigninRewardPoints,
|
||||
setSelectedStoreId,
|
||||
setVerifyMethod,
|
||||
setVerifyOpen,
|
||||
setVerifyRemark,
|
||||
searchCouponOptions,
|
||||
searchPickerProducts,
|
||||
storeOptions,
|
||||
submitDrawer,
|
||||
submitProductPicker,
|
||||
submitVerify,
|
||||
tabOptions,
|
||||
toggleNotifyChannel,
|
||||
toggleStatus,
|
||||
verifyForm,
|
||||
} = useMemberPointsMallPage();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Page title="积分商城" content-class="page-member-points-mall">
|
||||
<div class="mpm-page">
|
||||
<div class="mpm-toolbar mpm-toolbar-top">
|
||||
<Select
|
||||
class="mpm-store-select"
|
||||
:value="selectedStoreId"
|
||||
:options="storeOptions"
|
||||
:loading="isStoreLoading"
|
||||
placeholder="请选择门店"
|
||||
@update:value="(value) => setSelectedStoreId(String(value ?? ''))"
|
||||
/>
|
||||
|
||||
<div class="mpm-segments">
|
||||
<button
|
||||
v-for="item in tabOptions"
|
||||
:key="item.value"
|
||||
type="button"
|
||||
class="mpm-segment-item"
|
||||
:class="{ active: activeTab === item.value }"
|
||||
@click="setActiveTab(item.value)"
|
||||
>
|
||||
{{ item.label }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<span v-if="canView && !canManage" class="mpm-readonly-tip">
|
||||
当前为只读权限
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<Empty v-if="!canView" description="暂无积分商城页面访问权限" />
|
||||
|
||||
<div v-else-if="!hasStore" class="mpm-empty">
|
||||
<Empty description="暂无门店,请先创建门店" />
|
||||
</div>
|
||||
|
||||
<template v-else>
|
||||
<section v-show="activeTab === 'rules'" class="mpm-tab-panel">
|
||||
<Spin :spinning="isRuleLoading">
|
||||
<PointsMallRuleStatsCards :stats="ruleStats" />
|
||||
<PointsMallRulePanel
|
||||
:form="ruleForm"
|
||||
:can-manage="canManage"
|
||||
:loading="isRuleLoading"
|
||||
:submitting="isRuleSubmitting"
|
||||
@set-consume-reward-enabled="setRuleConsumeRewardEnabled"
|
||||
@set-consume-amount-per-step="setRuleConsumeAmountPerStep"
|
||||
@set-consume-reward-points-per-step="
|
||||
setRuleConsumeRewardPointsPerStep
|
||||
"
|
||||
@set-review-reward-enabled="setRuleReviewRewardEnabled"
|
||||
@set-review-reward-points="setRuleReviewRewardPoints"
|
||||
@set-register-reward-enabled="setRuleRegisterRewardEnabled"
|
||||
@set-register-reward-points="setRuleRegisterRewardPoints"
|
||||
@set-signin-reward-enabled="setRuleSigninRewardEnabled"
|
||||
@set-signin-reward-points="setRuleSigninRewardPoints"
|
||||
@set-expiry-mode="setRuleExpiryMode"
|
||||
@save="saveRule"
|
||||
/>
|
||||
</Spin>
|
||||
</section>
|
||||
|
||||
<section v-show="activeTab === 'products'" class="mpm-tab-panel">
|
||||
<PointsMallProductToolbar
|
||||
:filters="productFilterForm"
|
||||
:can-manage="canManage"
|
||||
:loading="isProductLoading"
|
||||
@set-status="setProductStatusFilter"
|
||||
@set-keyword="setProductKeyword"
|
||||
@search="applyProductFilters"
|
||||
@reset="resetProductFilters"
|
||||
@create="openCreateProduct"
|
||||
/>
|
||||
|
||||
<Spin :spinning="isProductLoading">
|
||||
<div v-if="productRows.length > 0" class="mpm-product-grid">
|
||||
<PointsMallProductCard
|
||||
v-for="item in productRows"
|
||||
:key="item.pointMallProductId"
|
||||
:item="item"
|
||||
:can-manage="canManage"
|
||||
@edit="openEditProduct"
|
||||
@toggle-status="toggleStatus"
|
||||
@remove="removeProduct"
|
||||
/>
|
||||
</div>
|
||||
<div v-else class="mpm-empty">
|
||||
<Empty description="暂无兑换商品" />
|
||||
</div>
|
||||
</Spin>
|
||||
</section>
|
||||
|
||||
<section v-show="activeTab === 'records'" class="mpm-tab-panel">
|
||||
<PointsMallRecordToolbar
|
||||
:filters="recordFilterForm"
|
||||
:can-manage="canManage"
|
||||
:loading="isRecordLoading"
|
||||
:exporting="isExporting"
|
||||
@set-redeem-type="setRecordRedeemType"
|
||||
@set-status="setRecordStatus"
|
||||
@set-keyword="setRecordKeyword"
|
||||
@search="applyRecordFilters"
|
||||
@reset="resetRecordFilters"
|
||||
@export="exportRecords"
|
||||
/>
|
||||
|
||||
<PointsMallRecordStatsCards :stats="recordStats" />
|
||||
|
||||
<div class="mpm-table-panel">
|
||||
<PointsMallRecordTable
|
||||
:can-manage="canManage"
|
||||
:loading="isRecordLoading"
|
||||
:pager="recordPager"
|
||||
@page-change="handleRecordPageChange"
|
||||
@verify="openVerifyDrawer"
|
||||
@detail="openDetailDrawer"
|
||||
/>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<PointsMallProductEditorDrawer
|
||||
:open="isDrawerOpen"
|
||||
:title="drawerTitle"
|
||||
:submit-text="drawerSubmitText"
|
||||
:submitting="isDrawerSubmitting"
|
||||
:loading="isDrawerLoading"
|
||||
:can-manage="canManage"
|
||||
:form="productForm"
|
||||
:coupon-options="couponOptions"
|
||||
@close="setDrawerOpen(false)"
|
||||
@set-name="setFormName"
|
||||
@set-image-url="setFormImageUrl"
|
||||
@set-redeem-type="setFormRedeemType"
|
||||
@set-coupon-template-id="setFormCouponTemplateId"
|
||||
@set-physical-name="setFormPhysicalName"
|
||||
@set-pickup-method="setFormPickupMethod"
|
||||
@set-description="setFormDescription"
|
||||
@set-exchange-type="setFormExchangeType"
|
||||
@set-required-points="setFormRequiredPoints"
|
||||
@set-cash-amount="setFormCashAmount"
|
||||
@set-stock-total="setFormStockTotal"
|
||||
@set-per-member-limit="setFormPerMemberLimit"
|
||||
@set-status="setFormStatus"
|
||||
@toggle-notify-channel="toggleNotifyChannel"
|
||||
@submit="submitDrawer"
|
||||
@open-product-picker="openProductPickerDrawer"
|
||||
@search-coupon="searchCouponOptions"
|
||||
/>
|
||||
|
||||
<PointsMallProductPickerModal
|
||||
:open="isPickerOpen"
|
||||
:loading="isPickerLoading"
|
||||
:keyword="pickerKeyword"
|
||||
:rows="pickerRows"
|
||||
:selected-id="pickerSelectedId"
|
||||
@close="setPickerOpen(false)"
|
||||
@set-keyword="setPickerKeyword"
|
||||
@search="searchPickerProducts"
|
||||
@select="setPickedProductId"
|
||||
@submit="submitProductPicker"
|
||||
/>
|
||||
|
||||
<PointsMallVerifyDrawer
|
||||
:open="isVerifyOpen"
|
||||
:loading="isVerifyLoading"
|
||||
:submitting="isVerifySubmitting"
|
||||
:can-manage="canManage"
|
||||
:record="detailRecord"
|
||||
:form="verifyForm"
|
||||
@close="setVerifyOpen(false)"
|
||||
@set-verify-method="setVerifyMethod"
|
||||
@set-verify-remark="setVerifyRemark"
|
||||
@submit="submitVerify"
|
||||
/>
|
||||
|
||||
<PointsMallRecordDetailDrawer
|
||||
:open="isDetailOpen"
|
||||
:loading="isDetailLoading"
|
||||
:record="detailRecord"
|
||||
@close="setDetailOpen(false)"
|
||||
/>
|
||||
</Page>
|
||||
</template>
|
||||
|
||||
<style lang="less">
|
||||
@import './styles/index.less';
|
||||
</style>
|
||||
Reference in New Issue
Block a user