根据对接实施方案文档修改
This commit is contained in:
45
web/src/components/table/fieldRender/date.vue
Normal file
45
web/src/components/table/fieldRender/date.vue
Normal file
@@ -0,0 +1,45 @@
|
||||
<template>
|
||||
<div>{{ formattedValue }}</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { TableColumnCtx } from 'element-plus'
|
||||
import { getCellValue } from '/@/components/table/index'
|
||||
|
||||
interface Props {
|
||||
row: TableRow
|
||||
field: TableColumn
|
||||
column: TableColumnCtx<TableRow>
|
||||
index: number
|
||||
}
|
||||
|
||||
const props = defineProps<Props>()
|
||||
|
||||
const cellValue = getCellValue(props.row, props.field, props.column, props.index)
|
||||
|
||||
const formattedValue = computed(() => {
|
||||
if (cellValue === null || cellValue === undefined || cellValue === '') return '-'
|
||||
|
||||
// PlayX “业务日期”在后端为 YYYY-MM-DD(或 YYYY-MM-DDTHH:mm:ssZ)。
|
||||
// 这里尽量“按字符串原样”处理,避免 new Date('YYYY-MM-DD') 的时区差导致日期偏移 1 天。
|
||||
const s = typeof cellValue === 'string' ? cellValue : String(cellValue)
|
||||
|
||||
// 常见 ISO/日期字符串截取
|
||||
const m = s.match(/^(\d{4}-\d{2}-\d{2})/)
|
||||
if (m) return m[1]
|
||||
|
||||
// 如果后端返回的是秒级时间戳,做兜底:用本地日期组件拼出 YYYY-MM-DD
|
||||
const n = Number(cellValue)
|
||||
if (Number.isFinite(n) && s.length === 10) {
|
||||
const d = new Date(n * 1000)
|
||||
const y = d.getFullYear()
|
||||
const mm = String(d.getMonth() + 1).padStart(2, '0')
|
||||
const dd = String(d.getDate()).padStart(2, '0')
|
||||
return `${y}-${mm}-${dd}`
|
||||
}
|
||||
|
||||
return s
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -8,6 +8,10 @@ export default {
|
||||
'type 1': 'type 1',
|
||||
'type 2': 'type 2',
|
||||
'type 3': 'type 3',
|
||||
amount: 'amount',
|
||||
multiplier: 'multiplier',
|
||||
category: 'category',
|
||||
category_title: 'category_title',
|
||||
admin_id: 'admin_id',
|
||||
admin__username: 'username',
|
||||
image: 'show image',
|
||||
|
||||
@@ -5,9 +5,13 @@ export default {
|
||||
remark: '备注',
|
||||
score: '兑换积分',
|
||||
type: '类型',
|
||||
'type 1': '奖励',
|
||||
'type 2': '充值',
|
||||
'type 3': '实物',
|
||||
'type 1': '红利(BONUS)',
|
||||
'type 2': '实物(PHYSICAL)',
|
||||
'type 3': '提现(WITHDRAW)',
|
||||
amount: '现金面值',
|
||||
multiplier: '流水倍数',
|
||||
category: '红利业务类别',
|
||||
category_title: '类别展示名',
|
||||
admin_id: '创建管理员',
|
||||
admin__username: '创建管理员',
|
||||
image: '展示图',
|
||||
|
||||
@@ -1,11 +1,5 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
class="ba-operate-dialog"
|
||||
:close-on-click-modal="false"
|
||||
:model-value="!!row"
|
||||
:title="t('channel.manage.whitelist')"
|
||||
@close="close"
|
||||
>
|
||||
<el-dialog class="ba-operate-dialog" :close-on-click-modal="false" :model-value="!!row" :title="t('channel.manage.whitelist')" @close="close">
|
||||
<el-scrollbar v-loading="loading" class="ba-table-form-scrollbar">
|
||||
<div class="ba-operate-form">
|
||||
<div class="ba-ip-white-list">
|
||||
@@ -47,7 +41,7 @@ const submitLoading = ref(false)
|
||||
/** 将后端数据转为 IP 字符串数组(兼容旧格式 [{key,value}] 和新格式 [ip]) */
|
||||
function normalizeIpWhite(val: unknown): string[] {
|
||||
if (!val || !Array.isArray(val)) return []
|
||||
return val.map((item) => (typeof item === 'string' ? item : item?.value ?? ''))
|
||||
return val.map((item) => (typeof item === 'string' ? item : (item?.value ?? '')))
|
||||
}
|
||||
|
||||
const ipWhiteList = ref<string[]>([])
|
||||
|
||||
@@ -67,6 +67,7 @@ const baTable = new baTableClass(
|
||||
label: t('mall.item.type'),
|
||||
prop: 'type',
|
||||
align: 'center',
|
||||
minWidth: 140,
|
||||
effect: 'dark',
|
||||
custom: { 1: 'success', 2: 'primary', 3: 'info' },
|
||||
operator: 'eq',
|
||||
@@ -74,6 +75,36 @@ const baTable = new baTableClass(
|
||||
render: 'tag',
|
||||
replaceValue: { '1': t('mall.item.type 1'), '2': t('mall.item.type 2'), '3': t('mall.item.type 3') },
|
||||
},
|
||||
{
|
||||
label: t('mall.item.amount'),
|
||||
prop: 'amount',
|
||||
align: 'center',
|
||||
sortable: false,
|
||||
operator: 'RANGE',
|
||||
},
|
||||
{
|
||||
label: t('mall.item.multiplier'),
|
||||
prop: 'multiplier',
|
||||
align: 'center',
|
||||
sortable: false,
|
||||
operator: 'eq',
|
||||
},
|
||||
{
|
||||
label: t('mall.item.category'),
|
||||
prop: 'category',
|
||||
align: 'center',
|
||||
sortable: false,
|
||||
operator: 'LIKE',
|
||||
operatorPlaceholder: t('Fuzzy query'),
|
||||
},
|
||||
{
|
||||
label: t('mall.item.category_title'),
|
||||
prop: 'category_title',
|
||||
align: 'center',
|
||||
sortable: false,
|
||||
operator: 'LIKE',
|
||||
operatorPlaceholder: t('Fuzzy query'),
|
||||
},
|
||||
{
|
||||
label: t('mall.item.status'),
|
||||
prop: 'status',
|
||||
@@ -139,7 +170,15 @@ const baTable = new baTableClass(
|
||||
width: 160,
|
||||
timeFormat: 'yyyy-mm-dd hh:MM:ss',
|
||||
},
|
||||
{ label: t('Operate'), align: 'center', width: 100, render: 'buttons', buttons: optButtons, operator: false },
|
||||
{
|
||||
label: t('Operate'),
|
||||
align: 'center',
|
||||
width: 100,
|
||||
render: 'buttons',
|
||||
buttons: optButtons,
|
||||
operator: false,
|
||||
fixed: 'right',
|
||||
},
|
||||
],
|
||||
dblClickNotEditColumn: [undefined, 'status'],
|
||||
},
|
||||
|
||||
@@ -72,6 +72,40 @@
|
||||
:input-attr="{ content: { '1': t('mall.item.type 1'), '2': t('mall.item.type 2'), '3': t('mall.item.type 3') } }"
|
||||
:placeholder="t('Please select field', { field: t('mall.item.type') })"
|
||||
/>
|
||||
<FormItem
|
||||
:label="t('mall.item.amount')"
|
||||
type="number"
|
||||
v-model="baTable.form.items!.amount"
|
||||
prop="amount"
|
||||
:input-attr="{ step: 0.01 }"
|
||||
:placeholder="t('Please input field', { field: t('mall.item.amount') })"
|
||||
v-if="isBonusOrWithdraw"
|
||||
/>
|
||||
<FormItem
|
||||
:label="t('mall.item.multiplier')"
|
||||
type="number"
|
||||
v-model="baTable.form.items!.multiplier"
|
||||
prop="multiplier"
|
||||
:input-attr="{ step: 1 }"
|
||||
:placeholder="t('Please input field', { field: t('mall.item.multiplier') })"
|
||||
v-if="isBonusOrWithdraw"
|
||||
/>
|
||||
<FormItem
|
||||
:label="t('mall.item.category')"
|
||||
type="string"
|
||||
v-model="baTable.form.items!.category"
|
||||
prop="category"
|
||||
:placeholder="t('Please input field', { field: t('mall.item.category') })"
|
||||
v-if="isBonusOrWithdraw"
|
||||
/>
|
||||
<FormItem
|
||||
:label="t('mall.item.category_title')"
|
||||
type="string"
|
||||
v-model="baTable.form.items!.category_title"
|
||||
prop="category_title"
|
||||
:placeholder="t('Please input field', { field: t('mall.item.category_title') })"
|
||||
v-if="isBonusOrWithdraw"
|
||||
/>
|
||||
<FormItem :label="t('mall.item.image')" type="image" v-model="baTable.form.items!.image" />
|
||||
<FormItem
|
||||
:label="t('mall.item.stock')"
|
||||
@@ -80,6 +114,7 @@
|
||||
prop="stock"
|
||||
:input-attr="{ step: 1 }"
|
||||
:placeholder="t('Please input field', { field: t('mall.item.stock') })"
|
||||
v-if="isPhysical"
|
||||
/>
|
||||
<FormItem
|
||||
:label="t('mall.item.sort')"
|
||||
@@ -112,7 +147,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import type { FormItemRule } from 'element-plus'
|
||||
import { inject, reactive, useTemplateRef } from 'vue'
|
||||
import { computed, inject, reactive, useTemplateRef, watch } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import FormItem from '/@/components/formItem/index.vue'
|
||||
import { useConfig } from '/@/stores/config'
|
||||
@@ -125,6 +160,35 @@ const baTable = inject('baTable') as baTableClass
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
const itemType = computed(() => baTable.form.items!.type)
|
||||
const isBonus = computed(() => itemType.value === 1 || itemType.value === '1')
|
||||
const isPhysical = computed(() => itemType.value === 2 || itemType.value === '2')
|
||||
const isWithdraw = computed(() => itemType.value === 3 || itemType.value === '3')
|
||||
const isBonusOrWithdraw = computed(() => isBonus.value || isWithdraw.value)
|
||||
|
||||
// 切换类型后,清理不适用的字段,避免“隐藏字段仍保留上一次的值”导致提交脏数据
|
||||
watch(
|
||||
itemType,
|
||||
(n, o) => {
|
||||
if (o === undefined) return
|
||||
if (!baTable.form.items) return
|
||||
|
||||
const typeNum = Number(n)
|
||||
if (!Number.isFinite(typeNum)) return
|
||||
|
||||
if (typeNum === 2) {
|
||||
baTable.form.items.amount = 0
|
||||
baTable.form.items.multiplier = 0
|
||||
baTable.form.items.category = ''
|
||||
baTable.form.items.category_title = ''
|
||||
} else {
|
||||
// BONUS / WITHDRAW
|
||||
baTable.form.items.stock = 0
|
||||
}
|
||||
},
|
||||
{ flush: 'post' },
|
||||
)
|
||||
|
||||
const rules: Partial<Record<string, FormItemRule[]>> = reactive({
|
||||
title: [buildValidatorData({ name: 'required', title: t('mall.item.title') })],
|
||||
description: [buildValidatorData({ name: 'required', title: t('mall.item.description') })],
|
||||
@@ -133,6 +197,87 @@ const rules: Partial<Record<string, FormItemRule[]>> = reactive({
|
||||
buildValidatorData({ name: 'required', title: t('mall.item.score') }),
|
||||
],
|
||||
type: [buildValidatorData({ name: 'required', title: t('mall.item.type') })],
|
||||
amount: [
|
||||
{
|
||||
validator: (rule: any, val: any, callback: Function) => {
|
||||
if (!isBonusOrWithdraw.value) return callback()
|
||||
if (val === '' || val === null || val === undefined) {
|
||||
return callback(new Error(t('Please input field', { field: t('mall.item.amount') })))
|
||||
}
|
||||
const num = Number(val)
|
||||
if (!Number.isFinite(num)) {
|
||||
return callback(new Error(t('Please enter the correct field', { field: t('mall.item.amount') })))
|
||||
}
|
||||
if (num < 0) {
|
||||
return callback(new Error(t('Please enter the correct field', { field: t('mall.item.amount') })))
|
||||
}
|
||||
return callback()
|
||||
},
|
||||
trigger: 'blur',
|
||||
},
|
||||
],
|
||||
multiplier: [
|
||||
{
|
||||
validator: (rule: any, val: any, callback: Function) => {
|
||||
if (!isBonusOrWithdraw.value) return callback()
|
||||
if (val === '' || val === null || val === undefined) {
|
||||
return callback(new Error(t('Please input field', { field: t('mall.item.multiplier') })))
|
||||
}
|
||||
const num = Number(val)
|
||||
if (!Number.isFinite(num) || !Number.isInteger(num)) {
|
||||
return callback(new Error(t('Please enter the correct field', { field: t('mall.item.multiplier') })))
|
||||
}
|
||||
if (num < 0) {
|
||||
return callback(new Error(t('Please enter the correct field', { field: t('mall.item.multiplier') })))
|
||||
}
|
||||
return callback()
|
||||
},
|
||||
trigger: 'blur',
|
||||
},
|
||||
],
|
||||
category: [
|
||||
{
|
||||
validator: (rule: any, val: any, callback: Function) => {
|
||||
if (!isBonusOrWithdraw.value) return callback()
|
||||
if (!val) {
|
||||
return callback(new Error(t('Please input field', { field: t('mall.item.category') })))
|
||||
}
|
||||
return callback()
|
||||
},
|
||||
trigger: 'blur',
|
||||
},
|
||||
],
|
||||
category_title: [
|
||||
{
|
||||
validator: (rule: any, val: any, callback: Function) => {
|
||||
if (!isBonusOrWithdraw.value) return callback()
|
||||
if (!val) {
|
||||
return callback(new Error(t('Please input field', { field: t('mall.item.category_title') })))
|
||||
}
|
||||
return callback()
|
||||
},
|
||||
trigger: 'blur',
|
||||
},
|
||||
],
|
||||
stock: [
|
||||
{
|
||||
validator: (rule: any, val: any, callback: Function) => {
|
||||
if (!isPhysical.value) return callback()
|
||||
if (val === '' || val === null || val === undefined) {
|
||||
return callback(new Error(t('Please input field', { field: t('mall.item.stock') })))
|
||||
}
|
||||
const num = Number(val)
|
||||
if (!Number.isFinite(num) || !Number.isInteger(num)) {
|
||||
return callback(new Error(t('Please enter the correct field', { field: t('mall.item.stock') })))
|
||||
}
|
||||
if (num < 0) {
|
||||
return callback(new Error(t('Please enter the correct field', { field: t('mall.item.stock') })))
|
||||
}
|
||||
return callback()
|
||||
},
|
||||
trigger: 'blur',
|
||||
},
|
||||
],
|
||||
sort: [buildValidatorData({ name: 'number', title: t('mall.item.sort') })],
|
||||
create_time: [buildValidatorData({ name: 'date', title: t('mall.item.create_time') })],
|
||||
update_time: [buildValidatorData({ name: 'date', title: t('mall.item.update_time') })],
|
||||
|
||||
Reference in New Issue
Block a user