<script lang="ts" setup>
|
import type { WxCpActivityApi } from '#/api/wxcp/activity';
|
|
import { computed, ref } from 'vue';
|
|
import { useVbenModal } from '@vben/common-ui';
|
import { Alert, Button, message } from 'ant-design-vue';
|
|
import { ACTIVITY_TYPE, pushActivity } from '#/api/wxcp/activity';
|
|
import PushScopePicker from '../../components/push-scope-picker.vue';
|
import { PUSH_SCOPE } from '../../data';
|
|
defineOptions({ name: 'WxCpActivityPushModal' });
|
|
const emit = defineEmits<{ success: [] }>();
|
|
const activity = ref<WxCpActivityApi.Activity>({});
|
const scope = ref<number>(PUSH_SCOPE.ALL);
|
const target = ref<string>('');
|
const pushing = ref(false);
|
const resultMessage = ref('');
|
const resultSuccess = ref(true);
|
|
/** 按模板说明本次推送会发什么 */
|
const pushHint = computed(() => {
|
switch (activity.value.activityType) {
|
case ACTIVITY_TYPE.TEXT:
|
return '成员会收到一条纯文本消息,内容为活动标题 + 活动详情。';
|
case ACTIVITY_TYPE.MESSAGE:
|
return '成员会收到一张可点击的卡片消息,点击打开活动详情页。';
|
case ACTIVITY_TYPE.IMAGE:
|
return '成员会先收到文字说明,再逐张收到上传的图片消息。';
|
case ACTIVITY_TYPE.FILE:
|
return '成员会先收到文字说明,再逐个收到附件,可直接下载查看。';
|
default:
|
return '成员会收到卡片消息,点击按钮打开采集页填写并提交评价。';
|
}
|
});
|
|
const [Modal, modalApi] = useVbenModal({
|
onOpenChange(isOpen: boolean) {
|
if (!isOpen) {
|
activity.value = {};
|
resultMessage.value = '';
|
return;
|
}
|
const data = modalApi.getData<{ activity: WxCpActivityApi.Activity }>();
|
activity.value = data.activity ?? {};
|
// 沿用活动上已配置的推送范围与目标,避免每次都要重选
|
scope.value = data.activity?.pushScope ?? PUSH_SCOPE.ALL;
|
target.value = data.activity?.pushTarget ?? '';
|
},
|
});
|
|
async function handlePush() {
|
if (!activity.value.id) {
|
return;
|
}
|
if (scope.value !== PUSH_SCOPE.ALL && !target.value.trim()) {
|
message.warning('选择「指定部门」或「指定成员」时,请先选择推送目标');
|
return;
|
}
|
pushing.value = true;
|
resultMessage.value = '';
|
try {
|
const res = await pushActivity({
|
id: activity.value.id,
|
pushScope: scope.value,
|
pushTarget: scope.value === PUSH_SCOPE.ALL ? '' : target.value,
|
});
|
resultSuccess.value = !!res?.success;
|
if (res?.success) {
|
message.success('推送成功');
|
emit('success');
|
await modalApi.close();
|
} else {
|
// 推送失败不抛异常,把企业微信给的原因直接展示给用户
|
resultMessage.value = res?.message || '推送失败';
|
}
|
} catch (error: unknown) {
|
resultSuccess.value = false;
|
resultMessage.value = (error as Error)?.message || '推送失败';
|
} finally {
|
pushing.value = false;
|
}
|
}
|
</script>
|
|
<template>
|
<Modal title="推送活动" class="w-2/5">
|
<div class="px-4">
|
<div class="mb-4 rounded bg-gray-50 p-3 text-sm dark:bg-gray-800">
|
<div class="mb-1 font-medium">
|
{{ activity.title }}
|
<span v-if="activity.activityTypeName" class="ml-2 text-xs text-gray-400">
|
{{ activity.activityTypeName }}
|
</span>
|
</div>
|
<div class="text-gray-500">{{ pushHint }}</div>
|
</div>
|
|
<div class="mb-2 text-sm font-medium">推送范围</div>
|
<PushScopePicker v-model:scope="scope" v-model:target="target" />
|
|
<Alert
|
v-if="resultMessage"
|
class="mt-4"
|
:type="resultSuccess ? 'success' : 'error'"
|
:message="resultMessage"
|
show-icon
|
/>
|
</div>
|
|
<template #footer>
|
<div class="flex justify-end gap-2">
|
<Button @click="modalApi.close()">取消</Button>
|
<Button type="primary" :loading="pushing" @click="handlePush">
|
确认推送
|
</Button>
|
</div>
|
</template>
|
</Modal>
|
</template>
|