310 lines
9.4 KiB
Vue
310 lines
9.4 KiB
Vue
<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>
|