| | |
| | | import type { VxeTableGridOptions } from '#/adapter/vxe-table'; |
| | | import type { WxCpActivityApi } from '#/api/wxcp/activity'; |
| | | |
| | | import { ACTIVITY_TYPE } from '#/api/wxcp/activity'; |
| | | |
| | | import { |
| | | ACTIVITY_STATUS_OPTIONS, |
| | | PUSH_SCOPE_OPTIONS, |
| | |
| | | /** 表单类型 */ |
| | | export type ActivityFormType = 'create' | 'update' | 'detail'; |
| | | |
| | | /** 活动模板类型选项 */ |
| | | export const ACTIVITY_TYPE_OPTIONS = [ |
| | | { |
| | | label: '纯通知(只推一条文本)', |
| | | value: ACTIVITY_TYPE.TEXT, |
| | | }, |
| | | { |
| | | label: '单条消息(可点击卡片)', |
| | | value: ACTIVITY_TYPE.MESSAGE, |
| | | }, |
| | | { |
| | | label: '图片通知(上传图片推送)', |
| | | value: ACTIVITY_TYPE.IMAGE, |
| | | }, |
| | | { |
| | | label: '附件通知(推送文件供下载)', |
| | | value: ACTIVITY_TYPE.FILE, |
| | | }, |
| | | { |
| | | label: '数据采集/评价(填写表单)', |
| | | value: ACTIVITY_TYPE.FORM, |
| | | }, |
| | | ]; |
| | | |
| | | /** 采集字段类型选项 */ |
| | | export const FIELD_TYPE_OPTIONS = [ |
| | | { label: '单行文本', value: 'text' }, |
| | | { label: '多行文本', value: 'textarea' }, |
| | | { label: '数字', value: 'number' }, |
| | | { label: '日期', value: 'date' }, |
| | | { label: '下拉选择', value: 'select' }, |
| | | { label: '单选', value: 'radio' }, |
| | | { label: '多选', value: 'checkbox' }, |
| | | { label: '评分', value: 'rating' }, |
| | | ]; |
| | | |
| | | const DATETIME_PROPS = { |
| | | showTime: true, |
| | | valueFormat: 'YYYY-MM-DD HH:mm:ss', |
| | | format: 'YYYY-MM-DD HH:mm:ss', |
| | | } as const; |
| | | |
| | | /** 仅数据采集模板需要报名时间与名额 */ |
| | | function isFormType(values: Record<string, unknown>) { |
| | | return values.activityType === ACTIVITY_TYPE.FORM; |
| | | } |
| | | |
| | | /** 活动表单 */ |
| | | export function useActivityFormSchema( |
| | |
| | | dependencies: { triggerFields: [''], show: () => false }, |
| | | }, |
| | | { |
| | | fieldName: 'activityType', |
| | | label: '活动模板', |
| | | component: 'Select', |
| | | componentProps: { |
| | | options: ACTIVITY_TYPE_OPTIONS, |
| | | placeholder: '请选择活动模板', |
| | | disabled: readonly, |
| | | }, |
| | | rules: 'required', |
| | | help: '不同模板决定推送形态:纯通知/单条消息/图片/附件,或带表单的数据采集', |
| | | formItemClass: 'col-span-2', |
| | | }, |
| | | { |
| | | fieldName: 'title', |
| | | label: '活动标题', |
| | | component: 'Input', |
| | |
| | | disabled: readonly, |
| | | }, |
| | | rules: 'required', |
| | | formItemClass: 'col-span-2', |
| | | }, |
| | | { |
| | | fieldName: 'buttonText', |
| | | label: '按钮文案', |
| | | component: 'Input', |
| | | componentProps: { |
| | | placeholder: '如:查看详情 / 立即报名', |
| | | disabled: readonly, |
| | | }, |
| | | dependencies: { |
| | | triggerFields: ['activityType'], |
| | | show: (values) => |
| | | values.activityType === ACTIVITY_TYPE.MESSAGE || |
| | | values.activityType === ACTIVITY_TYPE.FORM, |
| | | }, |
| | | formItemClass: 'col-span-2', |
| | | }, |
| | | { |
| | |
| | | label: '报名开始', |
| | | component: 'DatePicker', |
| | | componentProps: { ...DATETIME_PROPS, disabled: readonly }, |
| | | dependencies: { |
| | | triggerFields: ['activityType'], |
| | | show: isFormType, |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'signupEndTime', |
| | | label: '报名截止', |
| | | component: 'DatePicker', |
| | | componentProps: { ...DATETIME_PROPS, disabled: readonly }, |
| | | dependencies: { |
| | | triggerFields: ['activityType'], |
| | | show: isFormType, |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'signupLimit', |
| | |
| | | class: 'w-full', |
| | | disabled: readonly, |
| | | }, |
| | | defaultValue: 0, |
| | | rules: 'required', |
| | | help: '填 0 表示不限名额', |
| | | dependencies: { |
| | | triggerFields: ['activityType'], |
| | | show: isFormType, |
| | | }, |
| | | }, |
| | | { |
| | | // 封面走附件中间表:这里提交 blobIds,回显读 attachmentList(见 form.vue 的映射函数) |
| | |
| | | disabled: readonly, |
| | | }, |
| | | formItemClass: 'col-span-2', |
| | | }, |
| | | { |
| | | // 详情图片走另一套附件关系(recordType = wxcp_activity_detail),与封面互不影响。 |
| | | // 报名页把它排在「活动详情」文字下方、按原图比例完整展示(不裁剪), |
| | | // 所以二维码/海报这类被裁就失效的图必须放这里,别放封面。 |
| | | fieldName: 'detailBlobIds', |
| | | label: '详情图片', |
| | | component: 'ImageUpload', |
| | | componentProps: { |
| | | valueKey: 'id', |
| | | resultField: 'id', |
| | | maxNumber: 5, |
| | | multiple: true, |
| | | disabled: readonly, |
| | | }, |
| | | help: '选填,最多 5 张;活动页按原图比例完整显示不裁剪,二维码建议放这里', |
| | | formItemClass: 'col-span-2', |
| | | }, |
| | | { |
| | | // 图片通知模板:推送时逐张发图片消息(企业微信图片消息) |
| | | fieldName: 'imageBlobIds', |
| | | label: '推送图片', |
| | | component: 'ImageUpload', |
| | | componentProps: { |
| | | valueKey: 'id', |
| | | resultField: 'id', |
| | | maxNumber: 9, |
| | | multiple: true, |
| | | disabled: readonly, |
| | | }, |
| | | dependencies: { |
| | | triggerFields: ['activityType'], |
| | | show: (values) => values.activityType === ACTIVITY_TYPE.IMAGE, |
| | | }, |
| | | help: '推送时逐张发送图片消息,最多 9 张', |
| | | formItemClass: 'col-span-2', |
| | | }, |
| | | { |
| | | // 附件通知模板:推送时逐个发文件消息,接收人可直接下载 |
| | | fieldName: 'fileBlobIds', |
| | | label: '推送附件', |
| | | component: 'FileUpload', |
| | | componentProps: { |
| | | valueKey: 'id', |
| | | maxNumber: 5, |
| | | multiple: true, |
| | | showDescription: !readonly, |
| | | disabled: readonly, |
| | | }, |
| | | dependencies: { |
| | | triggerFields: ['activityType'], |
| | | show: (values) => values.activityType === ACTIVITY_TYPE.FILE, |
| | | }, |
| | | help: '推送时逐个发送文件消息,单个不超过 20MB,最多 5 个', |
| | | formItemClass: 'col-span-2', |
| | | }, |
| | | { |
| | | fieldName: 'ratingEnabled', |
| | | label: '开启评价', |
| | | component: 'Switch', |
| | | componentProps: { disabled: readonly }, |
| | | dependencies: { |
| | | triggerFields: ['activityType'], |
| | | show: isFormType, |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'ratingTitle', |
| | | label: '评价标题', |
| | | component: 'Input', |
| | | componentProps: { |
| | | placeholder: '如:活动满意度评价', |
| | | disabled: readonly, |
| | | }, |
| | | dependencies: { |
| | | triggerFields: ['activityType', 'ratingEnabled'], |
| | | show: (values) => isFormType(values) && values.ratingEnabled === true, |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'ratingMax', |
| | | label: '最高星级', |
| | | component: 'InputNumber', |
| | | componentProps: { |
| | | min: 1, |
| | | max: 10, |
| | | class: 'w-full', |
| | | disabled: readonly, |
| | | }, |
| | | defaultValue: 5, |
| | | dependencies: { |
| | | triggerFields: ['activityType', 'ratingEnabled'], |
| | | show: (values) => isFormType(values) && values.ratingEnabled === true, |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'remark', |
| | |
| | | /** 活动列表字段 */ |
| | | export function useActivityGridColumns(): VxeTableGridOptions<WxCpActivityApi.Activity>['columns'] { |
| | | return [ |
| | | { |
| | | field: 'activityTypeName', |
| | | title: '模板', |
| | | width: 150, |
| | | }, |
| | | { |
| | | field: 'title', |
| | | title: '活动标题', |
| | |
| | | slots: { default: 'content' }, |
| | | }, |
| | | { |
| | | field: 'fieldValues', |
| | | title: '采集内容', |
| | | minWidth: 200, |
| | | slots: { default: 'fieldValues' }, |
| | | }, |
| | | { |
| | | field: 'ratingScore', |
| | | title: '评价', |
| | | width: 80, |
| | | slots: { default: 'ratingScore' }, |
| | | }, |
| | | { |
| | | field: 'attachment', |
| | | title: '附件', |
| | | width: 80, |