refactor(payment): use string[] for supported_types throughout frontend+backend API

- Backend API returns/accepts supported_types as string[] (converts to/from DB comma string)
- Frontend ProviderInstance.supported_types is string[], no more parseTypes
- Remove all split/join conversions for supported_types
- payment_enabled_types also uses string[] consistently
This commit is contained in:
erio
2026-04-07 02:54:03 +08:00
parent 18107819da
commit 57cb01cd49
6 changed files with 46 additions and 31 deletions
+1 -1
View File
@@ -1 +1 @@
0.1.108.57
0.1.108.58
@@ -91,7 +91,7 @@ type CreateProviderInstanceRequest struct {
ProviderKey string `json:"providerKey"`
Name string `json:"name"`
Config map[string]string `json:"config"`
SupportedTypes string `json:"supportedTypes"`
SupportedTypes []string `json:"supportedTypes"`
Enabled bool `json:"enabled"`
SortOrder int `json:"sortOrder"`
Limits string `json:"limits"`
@@ -101,7 +101,7 @@ type CreateProviderInstanceRequest struct {
type UpdateProviderInstanceRequest struct {
Name *string `json:"name"`
Config map[string]string `json:"config"`
SupportedTypes *string `json:"supportedTypes"`
SupportedTypes []string `json:"supportedTypes"`
Enabled *bool `json:"enabled"`
SortOrder *int `json:"sortOrder"`
Limits *string `json:"limits"`
@@ -257,6 +257,25 @@ func derefStr(v *string) string {
return *v
}
func splitTypes(s string) []string {
if s == "" {
return nil
}
parts := strings.Split(s, ",")
result := make([]string, 0, len(parts))
for _, p := range parts {
p = strings.TrimSpace(p)
if p != "" {
result = append(result, p)
}
}
return result
}
func joinTypes(types []string) string {
return strings.Join(types, ",")
}
// --- Provider Instance CRUD ---
func (s *PaymentConfigService) ListProviderInstances(ctx context.Context) ([]*dbent.PaymentProviderInstance, error) {
@@ -270,7 +289,7 @@ type ProviderInstanceResponse struct {
ProviderKey string `json:"provider_key"`
Name string `json:"name"`
Config map[string]string `json:"config"`
SupportedTypes string `json:"supported_types"`
SupportedTypes []string `json:"supported_types"`
Limits string `json:"limits"`
Enabled bool `json:"enabled"`
RefundEnabled bool `json:"refund_enabled"`
@@ -289,7 +308,7 @@ func (s *PaymentConfigService) ListProviderInstancesWithConfig(ctx context.Conte
for _, inst := range instances {
resp := ProviderInstanceResponse{
ID: int64(inst.ID), ProviderKey: inst.ProviderKey, Name: inst.Name,
SupportedTypes: inst.SupportedTypes, Limits: inst.Limits,
SupportedTypes: splitTypes(inst.SupportedTypes), Limits: inst.Limits,
Enabled: inst.Enabled, RefundEnabled: inst.RefundEnabled, SortOrder: inst.SortOrder,
}
resp.Config = s.decryptAndMaskConfig(inst.Config)
@@ -349,7 +368,8 @@ var validProviderKeys = map[string]bool{
}
func (s *PaymentConfigService) CreateProviderInstance(ctx context.Context, req CreateProviderInstanceRequest) (*dbent.PaymentProviderInstance, error) {
if err := validateProviderRequest(req.ProviderKey, req.Name, req.SupportedTypes); err != nil {
typesStr := joinTypes(req.SupportedTypes)
if err := validateProviderRequest(req.ProviderKey, req.Name, typesStr); err != nil {
return nil, err
}
enc, err := s.encryptConfig(req.Config)
@@ -358,7 +378,7 @@ func (s *PaymentConfigService) CreateProviderInstance(ctx context.Context, req C
}
return s.entClient.PaymentProviderInstance.Create().
SetProviderKey(req.ProviderKey).SetName(req.Name).SetConfig(enc).
SetSupportedTypes(req.SupportedTypes).SetEnabled(req.Enabled).
SetSupportedTypes(typesStr).SetEnabled(req.Enabled).
SetSortOrder(req.SortOrder).SetLimits(req.Limits).SetRefundEnabled(req.RefundEnabled).
Save(ctx)
}
@@ -427,7 +447,7 @@ func (s *PaymentConfigService) UpdateProviderInstance(ctx context.Context, id in
u.SetConfig(enc)
}
if req.SupportedTypes != nil {
u.SetSupportedTypes(*req.SupportedTypes)
u.SetSupportedTypes(joinTypes(req.SupportedTypes))
}
if req.Enabled != nil {
u.SetEnabled(*req.Enabled)
@@ -209,7 +209,6 @@ import {
PROVIDER_SUPPORTED_TYPES,
PROVIDER_CALLBACK_PATHS,
WEBHOOK_PATHS,
parseTypes,
getAvailableTypes,
extractBaseUrl,
} from './providerConfig'
@@ -243,7 +242,7 @@ const { t } = useI18n()
const form = reactive({
name: '',
provider_key: 'easypay',
supported_types: '',
supported_types: [] as string[],
enabled: true,
refund_enabled: false,
})
@@ -282,7 +281,7 @@ const resolvedFields = computed(() => {
})
const limitableTypes = computed(() => {
const selected = parseTypes(form.supported_types).filter(t => t !== 'easypay')
const selected = form.supported_types.filter(t => t !== 'easypay')
return selected.map(v => {
const found = props.allPaymentTypes.find(pt => pt.value === v)
return found || { value: v, label: v }
@@ -291,18 +290,19 @@ const limitableTypes = computed(() => {
// --- Methods ---
function isTypeSelected(type: string): boolean {
return parseTypes(form.supported_types).includes(type)
return form.supported_types.includes(type)
}
function toggleType(type: string) {
const current = parseTypes(form.supported_types)
form.supported_types = current.includes(type)
? current.filter(t => t !== type).join(',')
: [...current, type].join(',')
if (form.supported_types.includes(type)) {
form.supported_types = form.supported_types.filter(t => t !== type)
} else {
form.supported_types = [...form.supported_types, type]
}
}
function onKeyChange() {
form.supported_types = (PROVIDER_SUPPORTED_TYPES[form.provider_key] || []).join(',')
form.supported_types = [...(PROVIDER_SUPPORTED_TYPES[form.provider_key] || [])]
clearConfig()
applyDefaults()
}
@@ -357,7 +357,7 @@ function handleSave() {
emitValidationError(t('admin.settings.payment.validationNameRequired'))
return
}
if (!form.supported_types.trim()) {
if (form.supported_types.length === 0) {
emitValidationError(t('admin.settings.payment.validationTypesRequired'))
return
}
@@ -408,7 +408,7 @@ function emitValidationError(msg: string) {
function reset(defaultKey: string) {
form.name = ''
form.provider_key = defaultKey
form.supported_types = (PROVIDER_SUPPORTED_TYPES[defaultKey] || []).join(',')
form.supported_types = [...(PROVIDER_SUPPORTED_TYPES[defaultKey] || [])]
form.enabled = true
form.refund_enabled = false
clearConfig()
@@ -66,7 +66,6 @@ import Icon from '@/components/icons/Icon.vue'
import ToggleSwitch from './ToggleSwitch.vue'
import type { ProviderInstance } from '@/types/payment'
import type { TypeOption } from './providerConfig'
import { parseTypes } from './providerConfig'
const PROVIDER_KEY_LABELS: Record<string, string> = {
easypay: 'admin.settings.payment.providerEasypay',
@@ -93,6 +92,6 @@ const { t } = useI18n()
const keyLabel = computed(() => t(PROVIDER_KEY_LABELS[props.provider.provider_key] || props.provider.provider_key))
function isSelected(type: string): boolean {
return parseTypes(props.provider.supported_types).includes(type)
return props.provider.supported_types.includes(type)
}
</script>
+1 -1
View File
@@ -104,7 +104,7 @@ export interface ProviderInstance {
provider_key: string
name: string
config: Record<string, string>
supported_types: string
supported_types: string[]
enabled: boolean
refund_enabled: boolean
limits: string
+5 -9
View File
@@ -2800,8 +2800,6 @@ async function saveBetaPolicySettings() {
// ==================== Provider Management ====================
import { parseTypes } from '@/components/payment/providerConfig'
const allPaymentTypes = computed(() => [
{ value: 'easypay', label: t('payment.methods.easypay') },
{ value: 'alipay', label: t('payment.methods.alipay') },
@@ -2901,18 +2899,16 @@ async function handleToggleField(provider: ProviderInstance, field: 'enabled' |
}
async function handleToggleType(provider: ProviderInstance, type: string) {
const current = parseTypes(provider.supported_types)
const updated = current.includes(type)
? current.filter(t => t !== type)
: [...current, type]
const updated = provider.supported_types.includes(type)
? provider.supported_types.filter(t => t !== type)
: [...provider.supported_types, type]
if (updated.length === 0) {
appStore.showError(t('admin.settings.payment.validationTypesRequired'))
return
}
const newVal = updated.join(',')
try {
await adminAPI.payment.updateProvider(provider.id, { supportedTypes: newVal } as any)
provider.supported_types = newVal
await adminAPI.payment.updateProvider(provider.id, { supportedTypes: updated } as any)
provider.supported_types = updated
} catch (err: unknown) { appStore.showError(extractApiErrorMessage(err, t('common.error'))) }
}