events.ts 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. import { loadBackendAuthTokens, loadBackendBaseUrl } from '../../utils/backendAuth'
  2. import {
  3. getEntryHome,
  4. type BackendCardResult,
  5. type BackendContentBundleSummary,
  6. type BackendPresentationSummary,
  7. } from '../../utils/backendApi'
  8. import { reportBackendClientLog } from '../../utils/backendClientLogs'
  9. const DEFAULT_CHANNEL_CODE = 'mini-demo'
  10. const DEFAULT_CHANNEL_TYPE = 'wechat_mini'
  11. type EventListFilter = 'all' | 'experience'
  12. type EventCardView = {
  13. id: string
  14. eventId: string
  15. titleText: string
  16. subtitleText: string
  17. summaryText: string
  18. statusText: string
  19. timeWindowText: string
  20. ctaText: string
  21. badgeText: string
  22. eventTypeText: string
  23. presentationText: string
  24. contentBundleText: string
  25. coverUrl: string
  26. disabled: boolean
  27. }
  28. type EventsPageData = {
  29. loading: boolean
  30. statusText: string
  31. currentFilter: EventListFilter
  32. cards: EventCardView[]
  33. }
  34. function requireAuthToken(): string | null {
  35. const app = getApp<IAppOption>()
  36. const tokens = app.globalData && app.globalData.backendAuthTokens
  37. ? app.globalData.backendAuthTokens
  38. : loadBackendAuthTokens()
  39. return tokens && tokens.accessToken ? tokens.accessToken : null
  40. }
  41. function formatPresentationSummary(summary?: BackendPresentationSummary | null): string {
  42. if (!summary) {
  43. return '当前未声明展示版本'
  44. }
  45. return summary.version || summary.templateKey || summary.presentationId || '当前未声明展示版本'
  46. }
  47. function formatContentBundleSummary(summary?: BackendContentBundleSummary | null): string {
  48. if (!summary) {
  49. return '当前未声明内容包版本'
  50. }
  51. return summary.version || summary.bundleType || summary.bundleId || '当前未声明内容包版本'
  52. }
  53. function buildCardView(card: BackendCardResult): EventCardView {
  54. const eventId = card.event && card.event.id ? card.event.id : ''
  55. const statusText = card.status || card.statusCode || '状态待确认'
  56. const badgeText = card.isDefaultExperience ? '体验' : '活动'
  57. const eventTypeText = card.eventType || '类型待确认'
  58. const subtitleText = card.subtitle || (card.event && card.event.displayName ? card.event.displayName : '')
  59. return {
  60. id: card.id,
  61. eventId,
  62. titleText: card.title || '未命名活动',
  63. subtitleText,
  64. summaryText: card.summary || (card.event && card.event.summary ? card.event.summary : '当前暂无活动摘要'),
  65. statusText,
  66. timeWindowText: card.timeWindow || '时间待公布',
  67. ctaText: card.ctaText || '查看详情',
  68. badgeText,
  69. eventTypeText,
  70. presentationText: formatPresentationSummary(card.currentPresentation),
  71. contentBundleText: formatContentBundleSummary(card.currentContentBundle),
  72. coverUrl: card.coverUrl || '',
  73. disabled: !eventId,
  74. }
  75. }
  76. function applyFilter(cards: BackendCardResult[], filter: EventListFilter): EventCardView[] {
  77. const filtered = filter === 'experience'
  78. ? cards.filter((item) => item.isDefaultExperience === true)
  79. : cards
  80. return filtered
  81. .slice()
  82. .sort((left, right) => {
  83. const leftPriority = typeof left.displayPriority === 'number' ? left.displayPriority : 0
  84. const rightPriority = typeof right.displayPriority === 'number' ? right.displayPriority : 0
  85. return rightPriority - leftPriority
  86. })
  87. .map(buildCardView)
  88. }
  89. Page({
  90. data: {
  91. loading: false,
  92. statusText: '准备加载活动列表',
  93. currentFilter: 'all',
  94. cards: [],
  95. } as EventsPageData,
  96. onLoad() {
  97. this.loadCards()
  98. },
  99. onShow() {
  100. this.loadCards()
  101. },
  102. async loadCards() {
  103. const accessToken = requireAuthToken()
  104. if (!accessToken) {
  105. wx.redirectTo({ url: '/pages/login/login' })
  106. return
  107. }
  108. this.setData({
  109. loading: true,
  110. statusText: '正在加载活动列表',
  111. })
  112. try {
  113. const result = await getEntryHome({
  114. baseUrl: loadBackendBaseUrl(),
  115. accessToken,
  116. channelCode: DEFAULT_CHANNEL_CODE,
  117. channelType: DEFAULT_CHANNEL_TYPE,
  118. })
  119. this.applyCards(result.cards || [])
  120. } catch (error) {
  121. const message = error && (error as { message?: string }).message ? (error as { message: string }).message : '未知错误'
  122. this.setData({
  123. loading: false,
  124. statusText: `活动列表加载失败:${message}`,
  125. cards: [],
  126. })
  127. }
  128. },
  129. applyCards(cards: BackendCardResult[]) {
  130. reportBackendClientLog({
  131. level: 'info',
  132. category: 'event-cards',
  133. message: 'event cards loaded',
  134. details: {
  135. filter: this.data.currentFilter,
  136. cardCount: cards.length,
  137. experienceCount: cards.filter((item) => item.isDefaultExperience === true).length,
  138. cardEventIds: cards.map((item) => (item.event && item.event.id ? item.event.id : '')),
  139. },
  140. })
  141. const filteredCards = applyFilter(cards, this.data.currentFilter)
  142. this.setData({
  143. loading: false,
  144. statusText: filteredCards.length ? '活动列表加载完成' : '当前没有可显示活动',
  145. cards: filteredCards,
  146. })
  147. const pageInstance = this as unknown as WechatMiniprogram.Page.Instance<EventsPageData, Record<string, never>> & {
  148. rawCards?: BackendCardResult[]
  149. }
  150. pageInstance.rawCards = cards
  151. },
  152. handleSwitchFilter(event: WechatMiniprogram.TouchEvent) {
  153. const filter = event.currentTarget.dataset.filter as EventListFilter | undefined
  154. if (!filter || filter === this.data.currentFilter) {
  155. return
  156. }
  157. const pageInstance = this as unknown as WechatMiniprogram.Page.Instance<EventsPageData, Record<string, never>> & {
  158. rawCards?: BackendCardResult[]
  159. }
  160. const rawCards = pageInstance.rawCards || []
  161. const filteredCards = applyFilter(rawCards, filter)
  162. this.setData({
  163. currentFilter: filter,
  164. statusText: filteredCards.length ? '活动列表加载完成' : '当前筛选下没有活动',
  165. cards: filteredCards,
  166. })
  167. },
  168. handleRefresh() {
  169. this.loadCards()
  170. },
  171. handleOpenCard(event: WechatMiniprogram.TouchEvent) {
  172. const eventId = event.currentTarget.dataset.eventId as string | undefined
  173. reportBackendClientLog({
  174. level: 'info',
  175. category: 'event-cards',
  176. message: 'event card clicked',
  177. eventId: eventId || '',
  178. details: {
  179. clickedEventId: eventId || '',
  180. filter: this.data.currentFilter,
  181. },
  182. })
  183. if (!eventId) {
  184. wx.showToast({
  185. title: '该卡片暂无活动入口',
  186. icon: 'none',
  187. })
  188. return
  189. }
  190. wx.navigateTo({
  191. url: `/pages/event/event?eventId=${encodeURIComponent(eventId)}`,
  192. })
  193. },
  194. })