feat: 完成会员消息触达模块页面与交互
This commit is contained in:
@@ -0,0 +1,396 @@
|
||||
import type { MemberMessageReachTabKey } from '../types';
|
||||
|
||||
import type {
|
||||
MemberMessageReachChannel,
|
||||
MemberMessageReachDetailDto,
|
||||
MemberMessageReachStatus,
|
||||
MemberMessageTemplateCategory,
|
||||
} from '#/api/member/message-reach';
|
||||
|
||||
import { computed, onActivated, onMounted, reactive, ref, watch } from 'vue';
|
||||
|
||||
import { useAccessStore } from '@vben/stores';
|
||||
|
||||
import {
|
||||
createDefaultMessageReachEditorForm,
|
||||
createDefaultMessageReachFilterForm,
|
||||
createDefaultMessageReachPager,
|
||||
createDefaultMessageReachStats,
|
||||
createDefaultMessageTemplateEditorForm,
|
||||
createDefaultMessageTemplateFilterForm,
|
||||
createDefaultMessageTemplatePager,
|
||||
} from '../types';
|
||||
import {
|
||||
MEMBER_MESSAGE_REACH_MANAGE_PERMISSION,
|
||||
MEMBER_MESSAGE_REACH_VIEW_PERMISSION,
|
||||
MESSAGE_REACH_TAB_OPTIONS,
|
||||
} from './message-reach-page/constants';
|
||||
import { createDataActions } from './message-reach-page/data-actions';
|
||||
import {
|
||||
resetMessageEditorForm,
|
||||
resetTemplateEditorForm,
|
||||
} from './message-reach-page/helpers';
|
||||
import { createMessageActions } from './message-reach-page/message-actions';
|
||||
import { createTemplateActions } from './message-reach-page/template-actions';
|
||||
|
||||
export function useMemberMessageReachPage() {
|
||||
const accessStore = useAccessStore();
|
||||
|
||||
const activeTab = ref<MemberMessageReachTabKey>('list');
|
||||
|
||||
const stats = ref(createDefaultMessageReachStats());
|
||||
const isStatsLoading = ref(false);
|
||||
|
||||
const messageFilterForm = reactive(createDefaultMessageReachFilterForm());
|
||||
const messagePager = ref(createDefaultMessageReachPager());
|
||||
const isMessageLoading = ref(false);
|
||||
|
||||
const templateFilterForm = reactive(createDefaultMessageTemplateFilterForm());
|
||||
const templatePager = ref(createDefaultMessageTemplatePager());
|
||||
const isTemplateLoading = ref(false);
|
||||
|
||||
const detail = ref<MemberMessageReachDetailDto | null>(null);
|
||||
const isDetailLoading = ref(false);
|
||||
const isDetailDrawerOpen = ref(false);
|
||||
const detailDrawerMessageId = ref('');
|
||||
|
||||
const messageDrawerMode = ref<'create' | 'edit'>('create');
|
||||
const form = reactive(createDefaultMessageReachEditorForm());
|
||||
const isMessageDrawerOpen = ref(false);
|
||||
const isMessageSubmitting = ref(false);
|
||||
const audienceEstimateCount = ref(0);
|
||||
const isEstimatingAudience = ref(false);
|
||||
|
||||
const templateEditorMode = ref<'create' | 'edit'>('create');
|
||||
const templateForm = reactive(createDefaultMessageTemplateEditorForm());
|
||||
const isTemplateEditorOpen = ref(false);
|
||||
const isTemplateEditorLoading = ref(false);
|
||||
const isTemplateSubmitting = ref(false);
|
||||
|
||||
const accessCodeSet = computed(
|
||||
() => new Set((accessStore.accessCodes ?? []).map(String)),
|
||||
);
|
||||
const canManage = computed(() =>
|
||||
accessCodeSet.value.has(MEMBER_MESSAGE_REACH_MANAGE_PERMISSION),
|
||||
);
|
||||
const canView = computed(
|
||||
() =>
|
||||
canManage.value ||
|
||||
accessCodeSet.value.has(MEMBER_MESSAGE_REACH_VIEW_PERMISSION),
|
||||
);
|
||||
|
||||
const messageDrawerTitle = computed(() =>
|
||||
messageDrawerMode.value === 'create' ? '创建消息' : '编辑消息',
|
||||
);
|
||||
|
||||
const templateEditorTitle = computed(() =>
|
||||
templateEditorMode.value === 'create' ? '新建模板' : '编辑模板',
|
||||
);
|
||||
|
||||
const templateEditorSubmitText = computed(() =>
|
||||
templateEditorMode.value === 'create' ? '创建' : '保存',
|
||||
);
|
||||
|
||||
const {
|
||||
estimateAudience,
|
||||
loadMessageDetail,
|
||||
loadMessageList,
|
||||
loadStats,
|
||||
loadTemplateList,
|
||||
} = createDataActions({
|
||||
audienceEstimateCount,
|
||||
detail,
|
||||
isDetailLoading,
|
||||
isEstimatingAudience,
|
||||
isMessageLoading,
|
||||
isStatsLoading,
|
||||
isTemplateLoading,
|
||||
messageFilterForm,
|
||||
messagePager,
|
||||
stats,
|
||||
templateFilterForm,
|
||||
templatePager,
|
||||
});
|
||||
|
||||
const {
|
||||
openCreateMessageDrawer,
|
||||
openDetailDrawer,
|
||||
openEditMessageDrawer,
|
||||
removeMessage,
|
||||
setAudienceType,
|
||||
setDetailDrawerOpen,
|
||||
setMessageContent,
|
||||
setMessageDrawerOpen,
|
||||
setMessageChannel,
|
||||
setMessageTitle,
|
||||
setScheduleType,
|
||||
setScheduledAt,
|
||||
submitMessage,
|
||||
switchToTemplateTab,
|
||||
toggleAudienceTag,
|
||||
useTemplateToCreateMessage,
|
||||
} = createMessageActions({
|
||||
activeTab,
|
||||
audienceEstimateCount,
|
||||
canManage,
|
||||
detail,
|
||||
detailDrawerMessageId,
|
||||
form,
|
||||
isDetailDrawerOpen,
|
||||
isMessageDrawerOpen,
|
||||
isMessageSubmitting,
|
||||
messageDrawerMode,
|
||||
loadMessageDetail,
|
||||
loadMessageList,
|
||||
loadStats,
|
||||
});
|
||||
|
||||
const {
|
||||
openCreateTemplateModal,
|
||||
openEditTemplateModal,
|
||||
removeTemplate,
|
||||
setTemplateCategory,
|
||||
setTemplateContent,
|
||||
setTemplateEditorOpen,
|
||||
setTemplateName,
|
||||
submitTemplate,
|
||||
} = createTemplateActions({
|
||||
canManage,
|
||||
form: templateForm,
|
||||
isTemplateEditorLoading,
|
||||
isTemplateEditorOpen,
|
||||
isTemplateSubmitting,
|
||||
loadTemplateList,
|
||||
mode: templateEditorMode,
|
||||
});
|
||||
|
||||
function setActiveTab(value: MemberMessageReachTabKey) {
|
||||
activeTab.value = value;
|
||||
}
|
||||
|
||||
function setMessageStatusFilter(value: string) {
|
||||
messageFilterForm.status = (value || undefined) as
|
||||
| MemberMessageReachStatus
|
||||
| undefined;
|
||||
}
|
||||
|
||||
function setMessageChannelFilter(value: string) {
|
||||
messageFilterForm.channel = (value || undefined) as
|
||||
| MemberMessageReachChannel
|
||||
| undefined;
|
||||
}
|
||||
|
||||
function setMessageKeyword(value: string) {
|
||||
messageFilterForm.keyword = value;
|
||||
}
|
||||
|
||||
async function applyMessageFilters() {
|
||||
messagePager.value = {
|
||||
...messagePager.value,
|
||||
page: 1,
|
||||
};
|
||||
await loadMessageList();
|
||||
}
|
||||
|
||||
async function resetMessageFilters() {
|
||||
messageFilterForm.status = undefined;
|
||||
messageFilterForm.channel = undefined;
|
||||
messageFilterForm.keyword = '';
|
||||
messagePager.value = {
|
||||
...messagePager.value,
|
||||
page: 1,
|
||||
};
|
||||
await loadMessageList();
|
||||
}
|
||||
|
||||
async function handleMessagePageChange(page: number, pageSize: number) {
|
||||
messagePager.value = {
|
||||
...messagePager.value,
|
||||
page,
|
||||
pageSize,
|
||||
};
|
||||
await loadMessageList();
|
||||
}
|
||||
|
||||
function setTemplateCategoryFilter(value: string) {
|
||||
templateFilterForm.category = (value || undefined) as
|
||||
| MemberMessageTemplateCategory
|
||||
| undefined;
|
||||
}
|
||||
|
||||
function setTemplateKeyword(value: string) {
|
||||
templateFilterForm.keyword = value;
|
||||
}
|
||||
|
||||
async function applyTemplateFilters() {
|
||||
templatePager.value = {
|
||||
...templatePager.value,
|
||||
page: 1,
|
||||
};
|
||||
await loadTemplateList();
|
||||
}
|
||||
|
||||
async function resetTemplateFilters() {
|
||||
templateFilterForm.category = undefined;
|
||||
templateFilterForm.keyword = '';
|
||||
templatePager.value = {
|
||||
...templatePager.value,
|
||||
page: 1,
|
||||
};
|
||||
await loadTemplateList();
|
||||
}
|
||||
|
||||
async function handleTemplatePageChange(page: number, pageSize: number) {
|
||||
templatePager.value = {
|
||||
...templatePager.value,
|
||||
page,
|
||||
pageSize,
|
||||
};
|
||||
await loadTemplateList();
|
||||
}
|
||||
|
||||
async function setAudienceTypeAndEstimate(value: 'all' | 'tag') {
|
||||
setAudienceType(value);
|
||||
if (value === 'all') {
|
||||
audienceEstimateCount.value = 0;
|
||||
return;
|
||||
}
|
||||
await estimateAudience('tag', form.audienceTags);
|
||||
}
|
||||
|
||||
async function toggleAudienceTagAndEstimate(tag: string) {
|
||||
toggleAudienceTag(tag);
|
||||
if (form.audienceType !== 'tag') {
|
||||
return;
|
||||
}
|
||||
await estimateAudience('tag', form.audienceTags);
|
||||
}
|
||||
|
||||
async function submitDraftMessage() {
|
||||
await submitMessage('draft');
|
||||
}
|
||||
|
||||
async function submitSendMessage() {
|
||||
await submitMessage('send');
|
||||
}
|
||||
|
||||
function clearByPermission() {
|
||||
stats.value = createDefaultMessageReachStats();
|
||||
messagePager.value = createDefaultMessageReachPager();
|
||||
templatePager.value = createDefaultMessageTemplatePager();
|
||||
detail.value = null;
|
||||
isDetailDrawerOpen.value = false;
|
||||
detailDrawerMessageId.value = '';
|
||||
resetMessageEditorForm(form);
|
||||
audienceEstimateCount.value = 0;
|
||||
isMessageDrawerOpen.value = false;
|
||||
resetTemplateEditorForm(templateForm);
|
||||
isTemplateEditorOpen.value = false;
|
||||
}
|
||||
|
||||
async function bootstrapPageData() {
|
||||
await Promise.all([loadStats(), loadMessageList(), loadTemplateList()]);
|
||||
}
|
||||
|
||||
watch(canView, async (value, oldValue) => {
|
||||
if (value === oldValue) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!value) {
|
||||
clearByPermission();
|
||||
return;
|
||||
}
|
||||
|
||||
await bootstrapPageData();
|
||||
});
|
||||
|
||||
onMounted(async () => {
|
||||
if (!canView.value) {
|
||||
clearByPermission();
|
||||
return;
|
||||
}
|
||||
|
||||
await bootstrapPageData();
|
||||
});
|
||||
|
||||
onActivated(() => {
|
||||
if (!canView.value) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
messagePager.value.totalCount === 0 &&
|
||||
templatePager.value.totalCount === 0
|
||||
) {
|
||||
void bootstrapPageData();
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
activeTab,
|
||||
applyMessageFilters,
|
||||
applyTemplateFilters,
|
||||
audienceEstimateCount,
|
||||
canManage,
|
||||
canView,
|
||||
detail,
|
||||
form,
|
||||
handleMessagePageChange,
|
||||
handleTemplatePageChange,
|
||||
isDetailDrawerOpen,
|
||||
isDetailLoading,
|
||||
isEstimatingAudience,
|
||||
isMessageDrawerOpen,
|
||||
isMessageLoading,
|
||||
isMessageSubmitting,
|
||||
isStatsLoading,
|
||||
isTemplateEditorLoading,
|
||||
isTemplateEditorOpen,
|
||||
isTemplateLoading,
|
||||
isTemplateSubmitting,
|
||||
messageDrawerTitle,
|
||||
messageFilterForm,
|
||||
messagePager,
|
||||
openCreateMessageDrawer,
|
||||
openCreateTemplateModal,
|
||||
openDetailDrawer,
|
||||
openEditMessageDrawer,
|
||||
openEditTemplateModal,
|
||||
removeMessage,
|
||||
removeTemplate,
|
||||
resetMessageFilters,
|
||||
resetTemplateFilters,
|
||||
setActiveTab,
|
||||
setAudienceTypeAndEstimate,
|
||||
setDetailDrawerOpen,
|
||||
setMessageChannel,
|
||||
setMessageChannelFilter,
|
||||
setMessageContent,
|
||||
setMessageDrawerOpen,
|
||||
setMessageKeyword,
|
||||
setMessageStatusFilter,
|
||||
setMessageTitle,
|
||||
setScheduleType,
|
||||
setScheduledAt,
|
||||
setTemplateCategory,
|
||||
setTemplateCategoryFilter,
|
||||
setTemplateContent,
|
||||
setTemplateEditorOpen,
|
||||
setTemplateKeyword,
|
||||
setTemplateName,
|
||||
stats,
|
||||
submitDraftMessage,
|
||||
submitSendMessage,
|
||||
submitTemplate,
|
||||
switchToTemplateTab,
|
||||
tabOptions: MESSAGE_REACH_TAB_OPTIONS,
|
||||
templateEditorSubmitText,
|
||||
templateEditorTitle,
|
||||
templateFilterForm,
|
||||
templateForm,
|
||||
templatePager,
|
||||
toggleAudienceTagAndEstimate,
|
||||
useTemplateToCreateMessage,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user