marketingActivityIndex.js 33 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031
  1. // @ts-check
  2. import {
  3. getList,
  4. getDetail,
  5. update,
  6. approveWithSmartRecord,
  7. getApprovalRecords,
  8. getApprovalRecordDetail,
  9. addApprovalRecord,
  10. updateApprovalRecord,
  11. saveApprovalRecord,
  12. getActivityAttachments
  13. } from '@/api/order/marketing-activity'
  14. import { formatFileSize } from '@/util/util'
  15. import { mapGetters } from 'vuex'
  16. import {
  17. ACTIVITY_TYPE,
  18. APPROVAL_STATUS,
  19. FILE_TYPE,
  20. ACTIVITY_TYPE_OPTIONS,
  21. APPROVAL_STATUS_OPTIONS,
  22. getApprovalStatusLabel,
  23. getApprovalStatusType as getStatusType,
  24. getFileTypeIcon as getFileIcon
  25. } from '@/constants/marketing-activity'
  26. import { getActivityTypeType, getApprovalStatusType } from '../../../constants'
  27. /**
  28. * @typedef {import('../types').MarketingActivityRecord} MarketingActivityRecord
  29. * @typedef {import('../types').ActivityAttachment} ActivityAttachment
  30. * @typedef {import('../types').ApprovalRecord} ApprovalRecord
  31. * @typedef {import('../types').MarketingActivityComponent} MarketingActivityComponent
  32. * @typedef {import('../types').PageInfo} PageInfo
  33. * @typedef {import('../types').MarketingActivityForm} MarketingActivityForm
  34. * @typedef {import('../types').MarketingActivityQueryParams} MarketingActivityQueryParams
  35. */
  36. /**
  37. * @typedef {Object} ApprovalRecordAddParams
  38. * @property {string|number} activityId
  39. * @property {string} activityCode
  40. * @property {number} approvalStatus
  41. * @property {string} approvalRemark
  42. * @property {string|number} approverId
  43. * @property {string} approverName
  44. * @property {string} approvalTime
  45. */
  46. /**
  47. * @typedef {Object} UserInfo
  48. * @property {string|number} user_id
  49. * @property {string|number} userId
  50. * @property {string} user_name
  51. * @property {string} userName
  52. * @property {string} name
  53. */
  54. /**
  55. * 营销活动管理混入
  56. * @this {MarketingActivityComponent & Vue}
  57. */
  58. export default {
  59. data() {
  60. return {
  61. /**
  62. * 详情加载状态
  63. * @type {boolean}
  64. */
  65. detailLoading: false,
  66. /**
  67. * 图片预览弹窗配置
  68. * @type {Object}
  69. */
  70. imagePreviewDialog: {
  71. visible: false,
  72. imageUrl: '',
  73. fileName: '',
  74. currentAttachment: null
  75. },
  76. /**
  77. * 查看弹窗显示状态
  78. * @type {boolean}
  79. */
  80. viewDialogVisible: false,
  81. /**
  82. * 当前查看的活动详情
  83. * @type {MarketingActivityItem|null}
  84. */
  85. currentViewActivity: null,
  86. /**
  87. * 附件列表数据
  88. * @type {Array<ActivityAttachmentItem>}
  89. */
  90. attachmentsList: [],
  91. /**
  92. * 附件加载状态
  93. * @type {boolean}
  94. */
  95. attachmentsLoading: false,
  96. /**
  97. * 审批记录对话框配置
  98. * @type {Object}
  99. */
  100. approvalRecordsDialog: {
  101. visible: false,
  102. loading: false,
  103. activityId: '',
  104. activityCode: '',
  105. activityTitle: '',
  106. data: [],
  107. page: {
  108. current: 1,
  109. size: 10,
  110. total: 0
  111. }
  112. },
  113. /**
  114. * 表格数据
  115. * @type {MarketingActivityRecord[]}
  116. */
  117. data: [],
  118. /**
  119. * 查询参数
  120. * @type {MarketingActivityQueryParams}
  121. */
  122. query: {},
  123. /**
  124. * 表单数据
  125. * @type {MarketingActivityRecord}
  126. */
  127. form: {},
  128. /**
  129. * 选中的数据列表
  130. * @type {MarketingActivityRecord[]}
  131. */
  132. selectionList: [],
  133. /**
  134. * 表格加载状态
  135. * @type {boolean}
  136. */
  137. loading: true,
  138. /**
  139. * 分页配置
  140. * @type {Object}
  141. */
  142. page: {
  143. pageSize: 10,
  144. currentPage: 1,
  145. total: 0
  146. },
  147. /**
  148. * 审批对话框配置
  149. * @type {Object}
  150. */
  151. approvalDialog: {
  152. visible: false,
  153. loading: false,
  154. title: ''
  155. },
  156. /**
  157. * 审批表单数据
  158. * @type {Object}
  159. */
  160. approvalForm: {
  161. id: '',
  162. title: '',
  163. customerName: '',
  164. approvalStatus: 1,
  165. approvalRemark: ''
  166. },
  167. /**
  168. * 审批表单验证规则
  169. * @type {Object}
  170. */
  171. approvalRules: {
  172. approvalRemark: [
  173. { required: true, message: '请输入审批意见', trigger: 'blur' },
  174. { min: 5, message: '审批意见至少5个字符', trigger: 'blur' },
  175. { max: 500, message: '审批意见不能超过500个字符', trigger: 'blur' }
  176. ]
  177. },
  178. /**
  179. * 表格配置
  180. * @type {Object}
  181. */
  182. option: {
  183. height: 'auto',
  184. calcHeight: 30,
  185. tip: false,
  186. searchShow: true,
  187. searchIcon: true,
  188. searchMenuSpan: 18,
  189. searchIndex: 3,
  190. border: true,
  191. index: true,
  192. viewBtn: true,
  193. editBtn: false,
  194. delBtn: false,
  195. addBtn: false,
  196. column: [
  197. {
  198. label: '活动编码',
  199. prop: 'activityCode',
  200. minWidth: 120,
  201. search: true,
  202. fixed: true
  203. },
  204. {
  205. label: '活动标题',
  206. prop: 'title',
  207. minWidth: 200,
  208. search: true,
  209. overHidden: true
  210. },
  211. {
  212. label: '客户名称',
  213. prop: 'customerName',
  214. minWidth: 150,
  215. search: true,
  216. overHidden: true
  217. },
  218. {
  219. label: '联系人',
  220. prop: 'contactName',
  221. minWidth: 100,
  222. overHidden: true
  223. },
  224. {
  225. label: '联系电话',
  226. prop: 'contactPhone',
  227. minWidth: 120,
  228. overHidden: true
  229. },
  230. {
  231. label: '活动类型',
  232. prop: 'activityType',
  233. minWidth: 100,
  234. search: true,
  235. type: 'select',
  236. dicData: ACTIVITY_TYPE_OPTIONS
  237. },
  238. {
  239. label: '活动时间',
  240. prop: 'activityPeriod',
  241. minWidth: 180,
  242. slot: true,
  243. sortable: false,
  244. search: false
  245. },
  246. {
  247. label: '促销价格',
  248. prop: 'promotionPrice',
  249. minWidth: 120,
  250. slot: true,
  251. sortable: true
  252. },
  253. {
  254. label: '审批状态',
  255. prop: 'approvalStatus',
  256. minWidth: 100,
  257. slot: true,
  258. search: true,
  259. type: 'select',
  260. dicData: APPROVAL_STATUS_OPTIONS
  261. },
  262. {
  263. label: '审批人',
  264. prop: 'approverName',
  265. minWidth: 100,
  266. overHidden: true
  267. },
  268. {
  269. label: '审批时间',
  270. prop: 'approvalTime',
  271. minWidth: 150,
  272. type: 'datetime',
  273. format: 'yyyy-MM-dd HH:mm:ss',
  274. valueFormat: 'yyyy-MM-dd HH:mm:ss'
  275. },
  276. {
  277. label: '创建时间',
  278. prop: 'createTime',
  279. minWidth: 150,
  280. type: 'datetime',
  281. format: 'yyyy-MM-dd HH:mm:ss',
  282. valueFormat: 'yyyy-MM-dd HH:mm:ss',
  283. addDisplay: false,
  284. editDisplay: false,
  285. viewDisplay: true
  286. },
  287. {
  288. label: '更新时间',
  289. prop: 'updateTime',
  290. minWidth: 150,
  291. type: 'datetime',
  292. format: 'yyyy-MM-dd HH:mm:ss',
  293. valueFormat: 'yyyy-MM-dd HH:mm:ss',
  294. addDisplay: false,
  295. editDisplay: false,
  296. viewDisplay: true
  297. },
  298. {
  299. label: '活动描述',
  300. prop: 'description',
  301. minWidth: 200,
  302. type: 'textarea',
  303. overHidden: true,
  304. span: 24,
  305. addDisplay: false,
  306. editDisplay: false,
  307. viewDisplay: true
  308. },
  309. {
  310. label: '审批备注',
  311. prop: 'approvalRemark',
  312. minWidth: 200,
  313. type: 'textarea',
  314. overHidden: true,
  315. span: 24,
  316. addDisplay: false,
  317. editDisplay: false,
  318. viewDisplay: true
  319. }
  320. ]
  321. },
  322. /**
  323. * 权限列表
  324. * @type {Object}
  325. */
  326. permissionList: {
  327. addBtn: false,
  328. viewBtn: false,
  329. delBtn: false,
  330. editBtn: false
  331. }
  332. }
  333. },
  334. computed: {
  335. ...mapGetters(['permission', 'userInfo']),
  336. /**
  337. * 选中的ID列表
  338. * @returns {string} 逗号分隔的ID字符串
  339. */
  340. ids() {
  341. const ids = []
  342. this.selectionList.forEach((ele) => {
  343. ids.push(ele.id)
  344. })
  345. return ids.join(',')
  346. }
  347. },
  348. methods: {
  349. /**
  350. * 判断是否为图片文件
  351. * @this {MarketingActivityComponent & Vue}
  352. * @param {string} fileType - 文件类型
  353. * @returns {boolean} 是否为图片文件
  354. */
  355. isImageFile(fileType) {
  356. if (!fileType) return false
  357. const imageTypes = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'svg']
  358. return imageTypes.includes(fileType.toLowerCase())
  359. },
  360. /**
  361. * 预览图片
  362. * @this {MarketingActivityComponent & Vue}
  363. * @param {ActivityAttachmentItem} attachment - 附件信息
  364. * @returns {void}
  365. */
  366. handlePreviewImage(attachment) {
  367. if (!this.isImageFile(attachment.fileType)) {
  368. this.$message.warning('该文件不是图片格式,无法预览')
  369. return
  370. }
  371. if (!attachment.fileUrl) {
  372. this.$message.warning('图片链接不存在')
  373. return
  374. }
  375. this.imagePreviewDialog = {
  376. visible: true,
  377. imageUrl: attachment.fileUrl.trim(),
  378. fileName: attachment.fileName,
  379. currentAttachment: attachment
  380. }
  381. },
  382. /**
  383. * 关闭图片预览弹窗
  384. * @this {MarketingActivityComponent & Vue}
  385. * @returns {void}
  386. */
  387. handleCloseImagePreview() {
  388. this.imagePreviewDialog = {
  389. visible: false,
  390. imageUrl: '',
  391. fileName: '',
  392. currentAttachment: null
  393. }
  394. },
  395. /**
  396. * 处理缩略图加载错误
  397. * @this {MarketingActivityComponent & Vue}
  398. * @param {Event} event - 错误事件
  399. * @returns {void}
  400. */
  401. handleImageError(event) {
  402. const target = event.target
  403. if (target) {
  404. target.style.display = 'none'
  405. const parent = target.parentNode
  406. if (parent && !parent.querySelector('.error-icon')) {
  407. const errorIcon = document.createElement('i')
  408. errorIcon.className = 'el-icon-picture-outline error-icon'
  409. errorIcon.style.fontSize = '24px'
  410. errorIcon.style.color = '#ccc'
  411. parent.appendChild(errorIcon)
  412. }
  413. }
  414. },
  415. /**
  416. * 处理预览图片加载错误
  417. * @this {MarketingActivityComponent & Vue}
  418. * @param {Event} event - 错误事件
  419. * @returns {void}
  420. */
  421. handlePreviewImageError(event) {
  422. this.$message.error('图片加载失败')
  423. const target = event.target
  424. if (target) {
  425. target.style.display = 'none'
  426. }
  427. },
  428. /**
  429. * 关闭查看弹窗
  430. * @this {MarketingActivityComponent & Vue}
  431. * @returns {void}
  432. */
  433. handleCloseViewDialog() {
  434. this.viewDialogVisible = false
  435. this.currentViewActivity = null
  436. this.attachmentsList = []
  437. // 同时关闭图片预览弹窗
  438. this.handleCloseImagePreview()
  439. },
  440. /**
  441. * 加载活动附件列表
  442. * @this {MarketingActivityComponent & Vue}
  443. * @param {string|number} activityId - 活动ID
  444. * @returns {Promise<void>}
  445. */
  446. async loadActivityAttachments(activityId) {
  447. if (!activityId) return
  448. this.attachmentsLoading = true
  449. try {
  450. const response = await getActivityAttachments(1, 100, activityId)
  451. if (response.data.success) {
  452. this.attachmentsList = response.data.data.records || []
  453. } else {
  454. this.$message.error('获取附件列表失败')
  455. this.attachmentsList = []
  456. }
  457. } catch (error) {
  458. console.error('获取附件列表失败:', error)
  459. this.$message.error('获取附件列表失败')
  460. this.attachmentsList = []
  461. } finally {
  462. this.attachmentsLoading = false
  463. }
  464. },
  465. /**
  466. * 预览附件
  467. * @this {MarketingActivityComponent & Vue}
  468. * @param {ActivityAttachmentItem} attachment - 附件信息
  469. * @returns {void}
  470. */
  471. handleViewAttachment(attachment) {
  472. if (attachment.fileUrl) {
  473. window.open(attachment.fileUrl.trim(), '_blank')
  474. } else {
  475. this.$message.warning('文件链接不存在')
  476. }
  477. },
  478. /**
  479. * 下载附件
  480. * @this {MarketingActivityComponent & Vue}
  481. * @param {ActivityAttachmentItem} attachment - 附件信息
  482. * @returns {void}
  483. */
  484. handleDownloadAttachment(attachment) {
  485. if (attachment.fileUrl) {
  486. const link = document.createElement('a')
  487. link.href = attachment.fileUrl.trim()
  488. link.download = attachment.fileName
  489. link.target = '_blank'
  490. document.body.appendChild(link)
  491. link.click()
  492. document.body.removeChild(link)
  493. } else {
  494. this.$message.warning('文件链接不存在')
  495. }
  496. },
  497. formatFileSize,
  498. /**
  499. * 获取文件类型图标
  500. * @this {MarketingActivityComponent & Vue}
  501. * @param {string} fileType - 文件类型
  502. * @returns {string} 图标类名
  503. */
  504. getFileTypeIcon(fileType) {
  505. return getFileIcon(fileType)
  506. },
  507. /**
  508. * 获取审批状态文本
  509. * @this {MarketingActivityComponent & Vue}
  510. * @param {number} status - 审批状态
  511. * @returns {string} 状态文本
  512. */
  513. getApprovalStatusText(status) {
  514. return getApprovalStatusLabel(status)
  515. },
  516. /**
  517. * 获取审批状态类型
  518. * @this {MarketingActivityComponent & Vue}
  519. * @param {number} status - 审批状态
  520. * @returns {string} 状态类型
  521. */
  522. getApprovalStatusType(status) {
  523. return getStatusType(status)
  524. },
  525. /**
  526. * 查看审批记录
  527. * @this {MarketingActivityComponent & Vue}
  528. * @param {MarketingActivityRecord} row - 营销活动记录
  529. */
  530. async handleViewApprovalRecords(row) {
  531. this.approvalRecordsDialog.visible = true
  532. this.approvalRecordsDialog.activityId = row.id
  533. this.approvalRecordsDialog.activityCode = row.activityCode
  534. this.approvalRecordsDialog.activityTitle = row.title
  535. this.approvalRecordsDialog.page.current = 1
  536. this.approvalRecordsDialog.page.size = 10
  537. await this.loadApprovalRecords()
  538. },
  539. /**
  540. * 加载审批记录数据
  541. * @this {MarketingActivityComponent & Vue}
  542. */
  543. async loadApprovalRecords() {
  544. try {
  545. this.approvalRecordsDialog.loading = true
  546. const response = await getApprovalRecords(
  547. this.approvalRecordsDialog.page.current,
  548. this.approvalRecordsDialog.page.size,
  549. this.approvalRecordsDialog.activityId
  550. )
  551. if (response.data.success) {
  552. const { records, total, current, size } = response.data.data
  553. this.approvalRecordsDialog.data = records || []
  554. this.approvalRecordsDialog.page.total = total || 0
  555. this.approvalRecordsDialog.page.current = current || 1
  556. this.approvalRecordsDialog.page.size = size || 10
  557. } else {
  558. this.$message.error(response.data.msg || '获取审批记录失败')
  559. this.approvalRecordsDialog.data = []
  560. this.approvalRecordsDialog.page.total = 0
  561. }
  562. } catch (error) {
  563. console.error('获取审批记录失败:', error)
  564. this.$message.error('获取审批记录失败,请稍后重试')
  565. this.approvalRecordsDialog.data = []
  566. this.approvalRecordsDialog.page.total = 0
  567. } finally {
  568. this.approvalRecordsDialog.loading = false
  569. }
  570. },
  571. /**
  572. * 审批记录分页大小变化
  573. * @this {MarketingActivityComponent & Vue}
  574. * @param {number} size - 新的分页大小
  575. */
  576. async handleApprovalRecordsSizeChange(size) {
  577. this.approvalRecordsDialog.page.size = size
  578. this.approvalRecordsDialog.page.current = 1
  579. await this.loadApprovalRecords()
  580. },
  581. /**
  582. * 审批记录当前页变化
  583. * @this {MarketingActivityComponent & Vue}
  584. * @param {number} current - 新的当前页
  585. */
  586. async handleApprovalRecordsCurrentChange(current) {
  587. this.approvalRecordsDialog.page.current = current
  588. await this.loadApprovalRecords()
  589. },
  590. /**
  591. * 重置审批记录对话框
  592. * @this {MarketingActivityComponent & Vue}
  593. */
  594. resetApprovalRecordsDialog() {
  595. this.approvalRecordsDialog.visible = false
  596. this.approvalRecordsDialog.loading = false
  597. this.approvalRecordsDialog.activityId = ''
  598. this.approvalRecordsDialog.activityCode = ''
  599. this.approvalRecordsDialog.activityTitle = ''
  600. this.approvalRecordsDialog.data = []
  601. this.approvalRecordsDialog.page = {
  602. current: 1,
  603. size: 10,
  604. total: 0
  605. }
  606. },
  607. /**
  608. * 查看详情
  609. * @this {MarketingActivityComponent & Vue}
  610. * @param {MarketingActivityRecord} row - 行数据
  611. * @returns {Promise<void>}
  612. */
  613. async handleView(row) {
  614. this.viewDialogVisible = true
  615. this.currentViewActivity = null
  616. this.attachmentsList = []
  617. this.detailLoading = true
  618. try {
  619. // 获取活动详情
  620. const detailRes = await getDetail(row.id)
  621. if (detailRes.data.success) {
  622. this.currentViewActivity = detailRes.data.data
  623. // 同时加载附件数据
  624. await this.loadActivityAttachments(row.id)
  625. } else {
  626. this.$message.error('获取活动详情失败')
  627. }
  628. } catch (error) {
  629. console.error('获取活动详情失败:', error)
  630. this.$message.error('获取活动详情失败')
  631. } finally {
  632. this.detailLoading = false
  633. }
  634. },
  635. /**
  636. * 处理审批操作
  637. * @this {MarketingActivityComponent & Vue}
  638. * @param {MarketingActivityRecord} row - 行数据
  639. * @param {number} approvalStatus - 审批状态 2-通过 3-拒绝
  640. * @returns {void}
  641. */
  642. handleApprove(row, approvalStatus) {
  643. this.approvalForm = {
  644. id: row.id,
  645. title: row.title,
  646. customerName: row.customerName,
  647. approvalStatus,
  648. approvalRemark: ''
  649. }
  650. this.approvalDialog.title = approvalStatus === APPROVAL_STATUS.APPROVED
  651. ? getApprovalStatusLabel(APPROVAL_STATUS.APPROVED)
  652. : getApprovalStatusLabel(APPROVAL_STATUS.REJECTED)
  653. this.approvalDialog.visible = true
  654. },
  655. /**
  656. * 提交审批(智能审批记录管理)
  657. * @this {MarketingActivityComponent & Vue}
  658. */
  659. async submitApproval() {
  660. try {
  661. // 表单验证
  662. const valid = await this.$refs.approvalForm.validate()
  663. if (!valid) {
  664. return
  665. }
  666. this.approvalDialog.loading = true
  667. // 构建审批参数
  668. const approvalParams = {
  669. id: this.approvalForm.id,
  670. approvalStatus: this.approvalForm.approvalStatus,
  671. approvalRemark: this.approvalForm.approvalRemark
  672. }
  673. // 获取当前用户信息
  674. const currentUserInfo = {
  675. userId: this.userInfo.user_id || this.userInfo.userId,
  676. userName: this.userInfo.user_name || this.userInfo.userName || this.userInfo.name
  677. }
  678. // 执行智能审批操作(包含智能审批记录管理)
  679. const response = await approveWithSmartRecord(approvalParams, currentUserInfo)
  680. if (response.data.success) {
  681. this.$message.success('审批操作成功')
  682. this.approvalDialog.visible = false
  683. this.resetApprovalDialog()
  684. // 刷新列表数据
  685. await this.onLoad(this.page)
  686. } else {
  687. this.$message.error(response.data.msg || '审批操作失败')
  688. }
  689. } catch (error) {
  690. console.error('审批操作失败:', error)
  691. this.$message.error('审批操作失败,请稍后重试')
  692. } finally {
  693. this.approvalDialog.loading = false
  694. }
  695. },
  696. /**
  697. * 重置审批对话框
  698. * @this {MarketingActivityComponent & Vue}
  699. * @returns {void}
  700. */
  701. resetApprovalDialog() {
  702. this.approvalForm = {
  703. id: '',
  704. title: '',
  705. customerName: '',
  706. approvalStatus: 1,
  707. approvalRemark: ''
  708. }
  709. if (this.$refs.approvalForm) {
  710. this.$refs.approvalForm.resetFields()
  711. }
  712. },
  713. /**
  714. * 新增、编辑、查看前的回调
  715. * @this {MarketingActivityComponent & Vue}
  716. * @param {Function} done - 完成回调
  717. * @param {string} type - 操作类型
  718. * @returns {Promise<void>}
  719. */
  720. async beforeOpen(done, type) {
  721. if (['edit', 'view'].includes(type)) {
  722. try {
  723. const res = await getDetail(this.form.id)
  724. this.form = res.data.data
  725. } catch (error) {
  726. console.error('获取详情失败:', error)
  727. this.$message.error('获取详情失败')
  728. }
  729. }
  730. done()
  731. },
  732. /**
  733. * 删除操作
  734. * @this {MarketingActivityComponent & Vue}
  735. * @param {MarketingActivityRecord} row - 行数据
  736. * @returns {Promise<void>}
  737. */
  738. async rowDel(row) {
  739. try {
  740. await this.$confirm('确定将选择数据删除?', {
  741. confirmButtonText: '确定',
  742. cancelButtonText: '取消',
  743. type: 'warning'
  744. })
  745. // 注意:根据接口文档,没有删除接口,这里可能需要调用状态更新
  746. this.$message.warning('删除功能暂未开放')
  747. } catch (error) {
  748. console.error('删除失败:', error)
  749. }
  750. },
  751. /**
  752. * 批量删除
  753. * @this {MarketingActivityComponent & Vue}
  754. * @returns {Promise<void>}
  755. */
  756. async handleDelete() {
  757. if (this.selectionList.length === 0) {
  758. this.$message.warning('请选择至少一条数据')
  759. return
  760. }
  761. try {
  762. await this.$confirm('确定将选择数据删除?', {
  763. confirmButtonText: '确定',
  764. cancelButtonText: '取消',
  765. type: 'warning'
  766. })
  767. // 注意:根据接口文档,没有删除接口,这里可能需要调用状态更新
  768. this.$message.warning('删除功能暂未开放')
  769. } catch (error) {
  770. console.error('批量删除失败:', error)
  771. }
  772. },
  773. /**
  774. * 更新操作
  775. * @this {MarketingActivityComponent & Vue}
  776. * @param {MarketingActivityRecord} row - 行数据
  777. * @param {number} index - 行索引
  778. * @param {Function} done - 完成回调
  779. * @param {Function} loading - 加载状态回调
  780. * @returns {Promise<void>}
  781. */
  782. async rowUpdate(row, index, done, loading) {
  783. try {
  784. loading()
  785. await update(row)
  786. done()
  787. this.$message.success('操作成功')
  788. await this.onLoad(this.page)
  789. } catch (error) {
  790. loading()
  791. console.error('更新失败:', error)
  792. this.$message.error('操作失败')
  793. }
  794. },
  795. /**
  796. * 新增操作
  797. * @this {MarketingActivityComponent & Vue}
  798. * @param {MarketingActivityRecord} row - 行数据
  799. * @param {Function} done - 完成回调
  800. * @param {Function} loading - 加载状态回调
  801. * @returns {Promise<void>}
  802. */
  803. async rowSave(row, done, loading) {
  804. // 根据接口文档,没有新增接口,这里暂不实现
  805. loading()
  806. this.$message.warning('新增功能暂未开放')
  807. done()
  808. },
  809. /**
  810. * 搜索回调
  811. * @this {MarketingActivityComponent & Vue}
  812. * @param {MarketingActivityQueryParams} params - 搜索参数
  813. * @param {Function} done - 完成回调
  814. * @returns {void}
  815. */
  816. searchChange(params, done) {
  817. this.query = params
  818. this.page.currentPage = 1
  819. this.onLoad(this.page)
  820. done()
  821. },
  822. /**
  823. * 搜索重置回调
  824. * @this {MarketingActivityComponent & Vue}
  825. * @returns {void}
  826. */
  827. searchReset() {
  828. this.query = {}
  829. this.page.currentPage = 1
  830. this.onLoad(this.page)
  831. },
  832. /**
  833. * 选择改变回调
  834. * @this {MarketingActivityComponent & Vue}
  835. * @param {MarketingActivityRecord[]} list - 选中的数据列表
  836. * @returns {void}
  837. */
  838. selectionChange(list) {
  839. this.selectionList = list
  840. },
  841. /**
  842. * 清空选择回调
  843. * @this {MarketingActivityComponent & Vue}
  844. * @returns {void}
  845. */
  846. selectionClear() {
  847. this.selectionList = []
  848. this.$refs.crud.toggleSelection()
  849. },
  850. /**
  851. * 当前页改变回调
  852. * @this {MarketingActivityComponent & Vue}
  853. * @param {number} currentPage - 当前页码
  854. * @returns {void}
  855. */
  856. currentChange(currentPage) {
  857. this.page.currentPage = currentPage
  858. },
  859. /**
  860. * 页大小改变回调
  861. * @this {MarketingActivityComponent & Vue}
  862. * @param {number} pageSize - 页大小
  863. * @returns {void}
  864. */
  865. sizeChange(pageSize) {
  866. this.page.pageSize = pageSize
  867. },
  868. /**
  869. * 刷新回调
  870. * @this {MarketingActivityComponent & Vue}
  871. * @returns {void}
  872. */
  873. refreshChange() {
  874. this.onLoad(this.page)
  875. },
  876. /**
  877. * 数据加载
  878. * @this {MarketingActivityComponent & Vue}
  879. * @param {Object} page - 分页参数
  880. * @param {Object} [params] - 查询参数
  881. * @returns {Promise<void>}
  882. */
  883. async onLoad(page, params) {
  884. this.loading = true
  885. try {
  886. const response = await getList(
  887. page.currentPage || 1,
  888. page.pageSize || 10,
  889. Object.assign(params || {}, this.query)
  890. )
  891. if (response.data && response.data.success) {
  892. const data = response.data.data
  893. this.data = data.records || []
  894. this.page.total = data.total || 0
  895. } else {
  896. this.data = []
  897. this.page.total = 0
  898. this.$message.warning('获取数据失败')
  899. }
  900. } catch (error) {
  901. this.data = []
  902. this.page.total = 0
  903. console.error('加载数据失败:', error)
  904. this.$message.error('加载数据失败,请稍后重试')
  905. } finally {
  906. this.loading = false
  907. }
  908. },
  909. /**
  910. * 手动保存审批记录(用于特殊场景)
  911. * @this {MarketingActivityComponent & Vue}
  912. * @param {string|number} activityId - 活动ID
  913. * @param {Object} approvalData - 审批数据
  914. */
  915. async handleSaveApprovalRecord(activityId, approvalData) {
  916. try {
  917. // 获取当前用户信息
  918. const currentUserInfo = {
  919. userId: this.userInfo.user_id || this.userInfo.userId,
  920. userName: this.userInfo.user_name || this.userInfo.userName || this.userInfo.name
  921. }
  922. const response = await saveApprovalRecord(
  923. activityId,
  924. currentUserInfo.userId,
  925. approvalData
  926. )
  927. if (response.data && response.data.success) {
  928. this.$message.success('审批记录保存成功')
  929. // 如果审批记录弹窗是打开的,刷新审批记录列表
  930. if (this.approvalRecordsDialog.visible) {
  931. await this.loadApprovalRecords()
  932. }
  933. } else {
  934. this.$message.error(response.data?.msg || '审批记录保存失败')
  935. }
  936. } catch (error) {
  937. console.error('保存审批记录失败:', error)
  938. this.$message.error('保存审批记录失败,请稍后重试')
  939. }
  940. }
  941. },
  942. /**
  943. * 组件挂载后初始化
  944. * @returns {void}
  945. */
  946. mounted() {
  947. this.onLoad(this.page)
  948. }
  949. }