// @ts-check import { getList, getDetail, update, approveWithSmartRecord, getApprovalRecords, getApprovalRecordDetail, addApprovalRecord, updateApprovalRecord, saveApprovalRecord, getActivityAttachments } from '@/api/order/marketing-activity' import { formatFileSize } from '@/util/util' import { mapGetters } from 'vuex' import { ACTIVITY_TYPE, APPROVAL_STATUS, FILE_TYPE, ACTIVITY_TYPE_OPTIONS, APPROVAL_STATUS_OPTIONS, getApprovalStatusLabel, getApprovalStatusType as getStatusType, getFileTypeIcon as getFileIcon } from '@/constants/marketing-activity' import { getActivityTypeType, getApprovalStatusType } from '../../../constants' /** * @typedef {import('../types').MarketingActivityRecord} MarketingActivityRecord * @typedef {import('../types').ActivityAttachment} ActivityAttachment * @typedef {import('../types').ApprovalRecord} ApprovalRecord * @typedef {import('../types').MarketingActivityComponent} MarketingActivityComponent * @typedef {import('../types').PageInfo} PageInfo * @typedef {import('../types').MarketingActivityForm} MarketingActivityForm * @typedef {import('../types').MarketingActivityQueryParams} MarketingActivityQueryParams */ /** * @typedef {Object} ApprovalRecordAddParams * @property {string|number} activityId * @property {string} activityCode * @property {number} approvalStatus * @property {string} approvalRemark * @property {string|number} approverId * @property {string} approverName * @property {string} approvalTime */ /** * @typedef {Object} UserInfo * @property {string|number} user_id * @property {string|number} userId * @property {string} user_name * @property {string} userName * @property {string} name */ /** * 营销活动管理混入 * @this {MarketingActivityComponent & Vue} */ export default { data() { return { /** * 详情加载状态 * @type {boolean} */ detailLoading: false, /** * 图片预览弹窗配置 * @type {Object} */ imagePreviewDialog: { visible: false, imageUrl: '', fileName: '', currentAttachment: null }, /** * 查看弹窗显示状态 * @type {boolean} */ viewDialogVisible: false, /** * 当前查看的活动详情 * @type {MarketingActivityItem|null} */ currentViewActivity: null, /** * 附件列表数据 * @type {Array} */ attachmentsList: [], /** * 附件加载状态 * @type {boolean} */ attachmentsLoading: false, /** * 审批记录对话框配置 * @type {Object} */ approvalRecordsDialog: { visible: false, loading: false, activityId: '', activityCode: '', activityTitle: '', data: [], page: { current: 1, size: 10, total: 0 } }, /** * 表格数据 * @type {MarketingActivityRecord[]} */ data: [], /** * 查询参数 * @type {MarketingActivityQueryParams} */ query: {}, /** * 表单数据 * @type {MarketingActivityRecord} */ form: {}, /** * 选中的数据列表 * @type {MarketingActivityRecord[]} */ selectionList: [], /** * 表格加载状态 * @type {boolean} */ loading: true, /** * 分页配置 * @type {Object} */ page: { pageSize: 10, currentPage: 1, total: 0 }, /** * 审批对话框配置 * @type {Object} */ approvalDialog: { visible: false, loading: false, title: '' }, /** * 审批表单数据 * @type {Object} */ approvalForm: { id: '', title: '', customerName: '', approvalStatus: 1, approvalRemark: '' }, /** * 审批表单验证规则 * @type {Object} */ approvalRules: { approvalRemark: [ { required: true, message: '请输入审批意见', trigger: 'blur' }, { min: 5, message: '审批意见至少5个字符', trigger: 'blur' }, { max: 500, message: '审批意见不能超过500个字符', trigger: 'blur' } ] }, /** * 表格配置 * @type {Object} */ option: { height: 'auto', calcHeight: 30, tip: false, searchShow: true, searchMenuSpan: 18, searchIndex: 3, border: true, index: true, viewBtn: true, editBtn: false, delBtn: false, addBtn: false, column: [ { label: '活动编码', prop: 'activityCode', minWidth: 120, search: true, fixed: true }, { label: '活动标题', prop: 'title', minWidth: 200, search: true, overHidden: true }, { label: '客户名称', prop: 'customerName', minWidth: 150, search: true, overHidden: true }, { label: '联系人', prop: 'contactName', minWidth: 100, overHidden: true }, { label: '联系电话', prop: 'contactPhone', minWidth: 120, overHidden: true }, { label: '活动类型', prop: 'activityType', minWidth: 100, search: true, type: 'select', dicData: ACTIVITY_TYPE_OPTIONS }, { label: '活动时间', prop: 'activityPeriod', minWidth: 180, slot: true, sortable: false, search: false }, { label: '促销价格', prop: 'promotionPrice', minWidth: 120, slot: true, sortable: true }, { label: '审批状态', prop: 'approvalStatus', minWidth: 100, slot: true, search: true, type: 'select', dicData: APPROVAL_STATUS_OPTIONS }, { label: '审批人', prop: 'approverName', minWidth: 100, overHidden: true }, { label: '审批时间', prop: 'approvalTime', minWidth: 150, type: 'datetime', format: 'yyyy-MM-dd HH:mm:ss', valueFormat: 'yyyy-MM-dd HH:mm:ss' }, { label: '创建时间', prop: 'createTime', minWidth: 150, type: 'datetime', format: 'yyyy-MM-dd HH:mm:ss', valueFormat: 'yyyy-MM-dd HH:mm:ss', addDisplay: false, editDisplay: false, viewDisplay: true }, { label: '更新时间', prop: 'updateTime', minWidth: 150, type: 'datetime', format: 'yyyy-MM-dd HH:mm:ss', valueFormat: 'yyyy-MM-dd HH:mm:ss', addDisplay: false, editDisplay: false, viewDisplay: true }, { label: '活动描述', prop: 'description', minWidth: 200, type: 'textarea', overHidden: true, span: 24, addDisplay: false, editDisplay: false, viewDisplay: true }, { label: '审批备注', prop: 'approvalRemark', minWidth: 200, type: 'textarea', overHidden: true, span: 24, addDisplay: false, editDisplay: false, viewDisplay: true } ] }, /** * 权限列表 * @type {Object} */ permissionList: { addBtn: false, viewBtn: false, delBtn: false, editBtn: false } } }, computed: { ...mapGetters(['permission', 'userInfo']), /** * 选中的ID列表 * @returns {string} 逗号分隔的ID字符串 */ ids() { const ids = [] this.selectionList.forEach((ele) => { ids.push(ele.id) }) return ids.join(',') } }, methods: { /** * 判断是否为图片文件 * @this {MarketingActivityComponent & Vue} * @param {string} fileType - 文件类型 * @returns {boolean} 是否为图片文件 */ isImageFile(fileType) { if (!fileType) return false const imageTypes = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'svg'] return imageTypes.includes(fileType.toLowerCase()) }, /** * 预览图片 * @this {MarketingActivityComponent & Vue} * @param {ActivityAttachmentItem} attachment - 附件信息 * @returns {void} */ handlePreviewImage(attachment) { if (!this.isImageFile(attachment.fileType)) { this.$message.warning('该文件不是图片格式,无法预览') return } if (!attachment.fileUrl) { this.$message.warning('图片链接不存在') return } this.imagePreviewDialog = { visible: true, imageUrl: attachment.fileUrl.trim(), fileName: attachment.fileName, currentAttachment: attachment } }, /** * 关闭图片预览弹窗 * @this {MarketingActivityComponent & Vue} * @returns {void} */ handleCloseImagePreview() { this.imagePreviewDialog = { visible: false, imageUrl: '', fileName: '', currentAttachment: null } }, /** * 处理缩略图加载错误 * @this {MarketingActivityComponent & Vue} * @param {Event} event - 错误事件 * @returns {void} */ handleImageError(event) { const target = event.target if (target) { target.style.display = 'none' const parent = target.parentNode if (parent && !parent.querySelector('.error-icon')) { const errorIcon = document.createElement('i') errorIcon.className = 'el-icon-picture-outline error-icon' errorIcon.style.fontSize = '24px' errorIcon.style.color = '#ccc' parent.appendChild(errorIcon) } } }, /** * 处理预览图片加载错误 * @this {MarketingActivityComponent & Vue} * @param {Event} event - 错误事件 * @returns {void} */ handlePreviewImageError(event) { this.$message.error('图片加载失败') const target = event.target if (target) { target.style.display = 'none' } }, /** * 关闭查看弹窗 * @this {MarketingActivityComponent & Vue} * @returns {void} */ handleCloseViewDialog() { this.viewDialogVisible = false this.currentViewActivity = null this.attachmentsList = [] // 同时关闭图片预览弹窗 this.handleCloseImagePreview() }, /** * 加载活动附件列表 * @this {MarketingActivityComponent & Vue} * @param {string|number} activityId - 活动ID * @returns {Promise} */ async loadActivityAttachments(activityId) { if (!activityId) return this.attachmentsLoading = true try { const response = await getActivityAttachments(1, 100, activityId) if (response.data.success) { this.attachmentsList = response.data.data.records || [] } else { this.$message.error('获取附件列表失败') this.attachmentsList = [] } } catch (error) { console.error('获取附件列表失败:', error) this.$message.error('获取附件列表失败') this.attachmentsList = [] } finally { this.attachmentsLoading = false } }, /** * 预览附件 * @this {MarketingActivityComponent & Vue} * @param {ActivityAttachmentItem} attachment - 附件信息 * @returns {void} */ handleViewAttachment(attachment) { if (attachment.fileUrl) { window.open(attachment.fileUrl.trim(), '_blank') } else { this.$message.warning('文件链接不存在') } }, /** * 下载附件 * @this {MarketingActivityComponent & Vue} * @param {ActivityAttachmentItem} attachment - 附件信息 * @returns {void} */ handleDownloadAttachment(attachment) { if (attachment.fileUrl) { const link = document.createElement('a') link.href = attachment.fileUrl.trim() link.download = attachment.fileName link.target = '_blank' document.body.appendChild(link) link.click() document.body.removeChild(link) } else { this.$message.warning('文件链接不存在') } }, formatFileSize, /** * 获取文件类型图标 * @this {MarketingActivityComponent & Vue} * @param {string} fileType - 文件类型 * @returns {string} 图标类名 */ getFileTypeIcon(fileType) { return getFileIcon(fileType) }, /** * 获取审批状态文本 * @this {MarketingActivityComponent & Vue} * @param {number} status - 审批状态 * @returns {string} 状态文本 */ getApprovalStatusText(status) { return getApprovalStatusLabel(status) }, /** * 获取审批状态类型 * @this {MarketingActivityComponent & Vue} * @param {number} status - 审批状态 * @returns {string} 状态类型 */ getApprovalStatusType(status) { return getStatusType(status) }, /** * 查看审批记录 * @this {MarketingActivityComponent & Vue} * @param {MarketingActivityRecord} row - 营销活动记录 */ async handleViewApprovalRecords(row) { this.approvalRecordsDialog.visible = true this.approvalRecordsDialog.activityId = row.id this.approvalRecordsDialog.activityCode = row.activityCode this.approvalRecordsDialog.activityTitle = row.title this.approvalRecordsDialog.page.current = 1 this.approvalRecordsDialog.page.size = 10 await this.loadApprovalRecords() }, /** * 加载审批记录数据 * @this {MarketingActivityComponent & Vue} */ async loadApprovalRecords() { try { this.approvalRecordsDialog.loading = true const response = await getApprovalRecords( this.approvalRecordsDialog.page.current, this.approvalRecordsDialog.page.size, this.approvalRecordsDialog.activityId ) if (response.data.success) { const { records, total, current, size } = response.data.data this.approvalRecordsDialog.data = records || [] this.approvalRecordsDialog.page.total = total || 0 this.approvalRecordsDialog.page.current = current || 1 this.approvalRecordsDialog.page.size = size || 10 } else { this.$message.error(response.data.msg || '获取审批记录失败') this.approvalRecordsDialog.data = [] this.approvalRecordsDialog.page.total = 0 } } catch (error) { console.error('获取审批记录失败:', error) this.$message.error('获取审批记录失败,请稍后重试') this.approvalRecordsDialog.data = [] this.approvalRecordsDialog.page.total = 0 } finally { this.approvalRecordsDialog.loading = false } }, /** * 审批记录分页大小变化 * @this {MarketingActivityComponent & Vue} * @param {number} size - 新的分页大小 */ async handleApprovalRecordsSizeChange(size) { this.approvalRecordsDialog.page.size = size this.approvalRecordsDialog.page.current = 1 await this.loadApprovalRecords() }, /** * 审批记录当前页变化 * @this {MarketingActivityComponent & Vue} * @param {number} current - 新的当前页 */ async handleApprovalRecordsCurrentChange(current) { this.approvalRecordsDialog.page.current = current await this.loadApprovalRecords() }, /** * 重置审批记录对话框 * @this {MarketingActivityComponent & Vue} */ resetApprovalRecordsDialog() { this.approvalRecordsDialog.visible = false this.approvalRecordsDialog.loading = false this.approvalRecordsDialog.activityId = '' this.approvalRecordsDialog.activityCode = '' this.approvalRecordsDialog.activityTitle = '' this.approvalRecordsDialog.data = [] this.approvalRecordsDialog.page = { current: 1, size: 10, total: 0 } }, /** * 查看详情 * @this {MarketingActivityComponent & Vue} * @param {MarketingActivityRecord} row - 行数据 * @returns {Promise} */ async handleView(row) { this.viewDialogVisible = true this.currentViewActivity = null this.attachmentsList = [] this.detailLoading = true try { // 获取活动详情 const detailRes = await getDetail(row.id) if (detailRes.data.success) { this.currentViewActivity = detailRes.data.data // 同时加载附件数据 await this.loadActivityAttachments(row.id) } else { this.$message.error('获取活动详情失败') } } catch (error) { console.error('获取活动详情失败:', error) this.$message.error('获取活动详情失败') } finally { this.detailLoading = false } }, /** * 处理审批操作 * @this {MarketingActivityComponent & Vue} * @param {MarketingActivityRecord} row - 行数据 * @param {number} approvalStatus - 审批状态 2-通过 3-拒绝 * @returns {void} */ handleApprove(row, approvalStatus) { this.approvalForm = { id: row.id, title: row.title, customerName: row.customerName, approvalStatus, approvalRemark: '' } this.approvalDialog.title = approvalStatus === APPROVAL_STATUS.APPROVED ? getApprovalStatusLabel(APPROVAL_STATUS.APPROVED) : getApprovalStatusLabel(APPROVAL_STATUS.REJECTED) this.approvalDialog.visible = true }, /** * 提交审批(智能审批记录管理) * @this {MarketingActivityComponent & Vue} */ async submitApproval() { try { // 表单验证 const valid = await this.$refs.approvalForm.validate() if (!valid) { return } this.approvalDialog.loading = true // 构建审批参数 const approvalParams = { id: this.approvalForm.id, approvalStatus: this.approvalForm.approvalStatus, approvalRemark: this.approvalForm.approvalRemark } // 获取当前用户信息 const currentUserInfo = { userId: this.userInfo.user_id || this.userInfo.userId, userName: this.userInfo.user_name || this.userInfo.userName || this.userInfo.name } // 执行智能审批操作(包含智能审批记录管理) const response = await approveWithSmartRecord(approvalParams, currentUserInfo) if (response.data.success) { this.$message.success('审批操作成功') this.approvalDialog.visible = false this.resetApprovalDialog() // 刷新列表数据 await this.onLoad(this.page) } else { this.$message.error(response.data.msg || '审批操作失败') } } catch (error) { console.error('审批操作失败:', error) this.$message.error('审批操作失败,请稍后重试') } finally { this.approvalDialog.loading = false } }, /** * 重置审批对话框 * @this {MarketingActivityComponent & Vue} * @returns {void} */ resetApprovalDialog() { this.approvalForm = { id: '', title: '', customerName: '', approvalStatus: 1, approvalRemark: '' } if (this.$refs.approvalForm) { this.$refs.approvalForm.resetFields() } }, /** * 新增、编辑、查看前的回调 * @this {MarketingActivityComponent & Vue} * @param {Function} done - 完成回调 * @param {string} type - 操作类型 * @returns {Promise} */ async beforeOpen(done, type) { if (['edit', 'view'].includes(type)) { try { const res = await getDetail(this.form.id) this.form = res.data.data } catch (error) { console.error('获取详情失败:', error) this.$message.error('获取详情失败') } } done() }, /** * 删除操作 * @this {MarketingActivityComponent & Vue} * @param {MarketingActivityRecord} row - 行数据 * @returns {Promise} */ async rowDel(row) { try { await this.$confirm('确定将选择数据删除?', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }) // 注意:根据接口文档,没有删除接口,这里可能需要调用状态更新 this.$message.warning('删除功能暂未开放') } catch (error) { console.error('删除失败:', error) } }, /** * 批量删除 * @this {MarketingActivityComponent & Vue} * @returns {Promise} */ async handleDelete() { if (this.selectionList.length === 0) { this.$message.warning('请选择至少一条数据') return } try { await this.$confirm('确定将选择数据删除?', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }) // 注意:根据接口文档,没有删除接口,这里可能需要调用状态更新 this.$message.warning('删除功能暂未开放') } catch (error) { console.error('批量删除失败:', error) } }, /** * 更新操作 * @this {MarketingActivityComponent & Vue} * @param {MarketingActivityRecord} row - 行数据 * @param {number} index - 行索引 * @param {Function} done - 完成回调 * @param {Function} loading - 加载状态回调 * @returns {Promise} */ async rowUpdate(row, index, done, loading) { try { loading() await update(row) done() this.$message.success('操作成功') await this.onLoad(this.page) } catch (error) { loading() console.error('更新失败:', error) this.$message.error('操作失败') } }, /** * 新增操作 * @this {MarketingActivityComponent & Vue} * @param {MarketingActivityRecord} row - 行数据 * @param {Function} done - 完成回调 * @param {Function} loading - 加载状态回调 * @returns {Promise} */ async rowSave(row, done, loading) { // 根据接口文档,没有新增接口,这里暂不实现 loading() this.$message.warning('新增功能暂未开放') done() }, /** * 搜索回调 * @this {MarketingActivityComponent & Vue} * @param {MarketingActivityQueryParams} params - 搜索参数 * @param {Function} done - 完成回调 * @returns {void} */ searchChange(params, done) { this.query = params this.page.currentPage = 1 this.onLoad(this.page) done() }, /** * 搜索重置回调 * @this {MarketingActivityComponent & Vue} * @returns {void} */ searchReset() { this.query = {} this.page.currentPage = 1 this.onLoad(this.page) }, /** * 选择改变回调 * @this {MarketingActivityComponent & Vue} * @param {MarketingActivityRecord[]} list - 选中的数据列表 * @returns {void} */ selectionChange(list) { this.selectionList = list }, /** * 清空选择回调 * @this {MarketingActivityComponent & Vue} * @returns {void} */ selectionClear() { this.selectionList = [] this.$refs.crud.toggleSelection() }, /** * 当前页改变回调 * @this {MarketingActivityComponent & Vue} * @param {number} currentPage - 当前页码 * @returns {void} */ currentChange(currentPage) { this.page.currentPage = currentPage }, /** * 页大小改变回调 * @this {MarketingActivityComponent & Vue} * @param {number} pageSize - 页大小 * @returns {void} */ sizeChange(pageSize) { this.page.pageSize = pageSize }, /** * 刷新回调 * @this {MarketingActivityComponent & Vue} * @returns {void} */ refreshChange() { this.onLoad(this.page) }, /** * 数据加载 * @this {MarketingActivityComponent & Vue} * @param {Object} page - 分页参数 * @param {Object} [params] - 查询参数 * @returns {Promise} */ async onLoad(page, params) { this.loading = true try { const response = await getList( page.currentPage || 1, page.pageSize || 10, Object.assign(params || {}, this.query) ) if (response.data && response.data.success) { const data = response.data.data this.data = data.records || [] this.page.total = data.total || 0 } else { this.data = [] this.page.total = 0 this.$message.warning('获取数据失败') } } catch (error) { this.data = [] this.page.total = 0 console.error('加载数据失败:', error) this.$message.error('加载数据失败,请稍后重试') } finally { this.loading = false } }, /** * 手动保存审批记录(用于特殊场景) * @this {MarketingActivityComponent & Vue} * @param {string|number} activityId - 活动ID * @param {Object} approvalData - 审批数据 */ async handleSaveApprovalRecord(activityId, approvalData) { try { // 获取当前用户信息 const currentUserInfo = { userId: this.userInfo.user_id || this.userInfo.userId, userName: this.userInfo.user_name || this.userInfo.userName || this.userInfo.name } const response = await saveApprovalRecord( activityId, currentUserInfo.userId, approvalData ) if (response.data && response.data.success) { this.$message.success('审批记录保存成功') // 如果审批记录弹窗是打开的,刷新审批记录列表 if (this.approvalRecordsDialog.visible) { await this.loadApprovalRecords() } } else { this.$message.error(response.data?.msg || '审批记录保存失败') } } catch (error) { console.error('保存审批记录失败:', error) this.$message.error('保存审批记录失败,请稍后重试') } } }, /** * 组件挂载后初始化 * @returns {void} */ mounted() { this.onLoad(this.page) } }