useTopupPopup.ts 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. import { computed, reactive, readonly } from 'vue'
  2. export interface TopupPackage {
  3. id: string | number
  4. /** Displayed coins amount, e.g. 200 */
  5. coins: number
  6. /** Displayed price label, e.g. "20.000" */
  7. priceLabel: string
  8. }
  9. export interface TopupPaymentMethod {
  10. id: string
  11. /** Displayed method name, e.g. "GoPay" */
  12. name: string
  13. /** Displayed method icon */
  14. icon: string
  15. }
  16. export interface TopupPopupOptions {
  17. /** Current user balance (coins) */
  18. balance: number
  19. /** Available coin packages */
  20. packages: TopupPackage[]
  21. /** Available payment methods */
  22. methods: TopupPaymentMethod[]
  23. /** Default selected package id */
  24. defaultPackageId?: TopupPackage['id']
  25. /** Default selected method id */
  26. defaultMethodId?: TopupPaymentMethod['id']
  27. }
  28. export interface TopupPopupState {
  29. visible: boolean
  30. balance: number
  31. packages: TopupPackage[]
  32. methods: TopupPaymentMethod[]
  33. selectedPackageId: TopupPackage['id'] | null
  34. selectedMethodId: TopupPaymentMethod['id'] | null
  35. }
  36. const state = reactive<TopupPopupState>({
  37. visible: false,
  38. balance: 0,
  39. // 实际档位和支付方式由上层(useRecharge)在 open 时注入
  40. packages: [],
  41. methods: [],
  42. selectedPackageId: null,
  43. selectedMethodId: null,
  44. })
  45. const selectedPackage = computed(() =>
  46. state.packages.find(item => item.id === state.selectedPackageId) ?? null,
  47. )
  48. const selectedMethod = computed(() =>
  49. state.methods.find(item => item.id === state.selectedMethodId) ?? null,
  50. )
  51. const open = (options?: TopupPopupOptions) => {
  52. if (options) {
  53. state.balance = options.balance
  54. state.packages = options.packages ?? []
  55. state.methods = options.methods ?? []
  56. const defaultPackageId
  57. = options.defaultPackageId ?? options.packages?.[0]?.id ?? null
  58. const defaultMethodId
  59. = options.defaultMethodId ?? options.methods?.[0]?.id ?? null
  60. state.selectedPackageId = defaultPackageId
  61. state.selectedMethodId = defaultMethodId
  62. }
  63. state.visible = true
  64. }
  65. const close = () => {
  66. state.visible = false
  67. }
  68. const selectPackage = (id: TopupPackage['id']) => {
  69. state.selectedPackageId = id
  70. }
  71. const selectMethod = (id: TopupPaymentMethod['id']) => {
  72. state.selectedMethodId = id
  73. }
  74. export const useTopupPopup = () => {
  75. return {
  76. state: readonly(state),
  77. selectedPackage,
  78. selectedMethod,
  79. open,
  80. close,
  81. selectPackage,
  82. selectMethod,
  83. }
  84. }