feat(export): 增强SQL构建逻辑以支持ID过滤和时间快捷选项
- 添加isZeroID函数以处理ID过滤,确保在构建SQL时跳过无效ID - 更新BuildSQL函数,优化merchant_id_eq和creator_in的处理逻辑 - 在前端引入时间快捷选项,提升用户体验,简化时间范围选择 - 更新日期选择器以支持快捷选项,增强导出功能的灵活性
This commit is contained in:
parent
8e4d2b4790
commit
ec5322f602
|
|
@ -10,6 +10,22 @@ import (
|
|||
"strings"
|
||||
)
|
||||
|
||||
// isZeroID returns true when the value is effectively empty/zero for ID filters.
|
||||
func isZeroID(v interface{}) bool {
|
||||
switch t := v.(type) {
|
||||
case nil:
|
||||
return true
|
||||
case string:
|
||||
s := strings.TrimSpace(t)
|
||||
return s == "" || s == "0"
|
||||
case int, int32, int64:
|
||||
return fmt.Sprint(t) == "0"
|
||||
case float32, float64:
|
||||
return fmt.Sprint(t) == "0" || fmt.Sprint(t) == "0.0"
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type BuildRequest struct {
|
||||
MainTable string
|
||||
Datasource string
|
||||
|
|
@ -218,20 +234,56 @@ func BuildSQL(req BuildRequest, whitelist map[string]bool) (string, []interface{
|
|||
need["merchant_key_send"] = true
|
||||
}
|
||||
|
||||
// normalize merchant_id_eq: skip 0/空,非零转为 merchant_id_in 以便和 creator_in 做 OR
|
||||
if v, ok := req.Filters["merchant_id_eq"]; ok {
|
||||
if isZeroID(v) {
|
||||
delete(req.Filters, "merchant_id_eq")
|
||||
} else {
|
||||
if _, has := req.Filters["merchant_id_in"]; !has {
|
||||
req.Filters["merchant_id_in"] = []interface{}{v}
|
||||
}
|
||||
delete(req.Filters, "merchant_id_eq")
|
||||
}
|
||||
}
|
||||
|
||||
// helper: treat "0"/0/空 as未提供的 ID
|
||||
isZeroID := func(v interface{}) bool {
|
||||
switch t := v.(type) {
|
||||
case nil:
|
||||
return true
|
||||
case string:
|
||||
s := strings.TrimSpace(t)
|
||||
return s == "" || s == "0"
|
||||
case int, int32, int64:
|
||||
return fmt.Sprint(t) == "0"
|
||||
case float32, float64:
|
||||
return fmt.Sprint(t) == "0" || fmt.Sprint(t) == "0.0"
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Handle creator_in and merchant_id_in with OR logic if both exist
|
||||
var creatorArgs []interface{}
|
||||
hasCreator := false
|
||||
if v, ok := req.Filters["creator_in"]; ok {
|
||||
switch t := v.(type) {
|
||||
case []interface{}:
|
||||
creatorArgs = t
|
||||
for _, x := range t {
|
||||
if !isZeroID(x) {
|
||||
creatorArgs = append(creatorArgs, x)
|
||||
}
|
||||
}
|
||||
case []int:
|
||||
for _, x := range t {
|
||||
creatorArgs = append(creatorArgs, x)
|
||||
if !isZeroID(x) {
|
||||
creatorArgs = append(creatorArgs, x)
|
||||
}
|
||||
}
|
||||
case []string:
|
||||
for _, x := range t {
|
||||
creatorArgs = append(creatorArgs, x)
|
||||
if !isZeroID(x) {
|
||||
creatorArgs = append(creatorArgs, x)
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(creatorArgs) > 0 {
|
||||
|
|
@ -244,14 +296,22 @@ func BuildSQL(req BuildRequest, whitelist map[string]bool) (string, []interface{
|
|||
if v, ok := req.Filters["merchant_id_in"]; ok {
|
||||
switch t := v.(type) {
|
||||
case []interface{}:
|
||||
merchantArgs = t
|
||||
for _, x := range t {
|
||||
if !isZeroID(x) {
|
||||
merchantArgs = append(merchantArgs, x)
|
||||
}
|
||||
}
|
||||
case []int:
|
||||
for _, x := range t {
|
||||
merchantArgs = append(merchantArgs, x)
|
||||
if !isZeroID(x) {
|
||||
merchantArgs = append(merchantArgs, x)
|
||||
}
|
||||
}
|
||||
case []string:
|
||||
for _, x := range t {
|
||||
merchantArgs = append(merchantArgs, x)
|
||||
if !isZeroID(x) {
|
||||
merchantArgs = append(merchantArgs, x)
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(merchantArgs) > 0 {
|
||||
|
|
@ -618,6 +678,9 @@ func BuildCountSQL(req BuildRequest, whitelist map[string]bool) (string, []inter
|
|||
if k == "plan_id_eq" && utils.ToString(v) == "0" {
|
||||
continue
|
||||
}
|
||||
if k == "merchant_id_eq" && isZeroID(v) {
|
||||
continue
|
||||
}
|
||||
if tbl, col, ok := sch.FilterColumn(k); ok {
|
||||
switch k {
|
||||
case "create_time_between":
|
||||
|
|
|
|||
|
|
@ -240,7 +240,15 @@
|
|||
<el-row :gutter="8">
|
||||
<el-col :span="24">
|
||||
<el-form-item label="时间范围" required show-message prop="dateRange">
|
||||
<el-date-picker v-model="exportForm.dateRange" type="datetimerange" start-placeholder="开始时间" end-placeholder="结束时间" value-format="YYYY-MM-DD HH:mm:ss" style="width:100%" />
|
||||
<el-date-picker
|
||||
v-model="exportForm.dateRange"
|
||||
type="datetimerange"
|
||||
start-placeholder="开始时间"
|
||||
end-placeholder="结束时间"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
:shortcuts="dateShortcuts"
|
||||
style="width:100%"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
|
|
|||
67
web/main.js
67
web/main.js
|
|
@ -180,6 +180,72 @@ const app = createApp({
|
|||
const editRules = ValidationRules.createEditRules();
|
||||
const exportRules = ValidationRules.createExportRules();
|
||||
|
||||
// ==================== 时间快捷选项 ====================
|
||||
const dateShortcuts = [
|
||||
{
|
||||
text: '本日',
|
||||
value: () => {
|
||||
const start = new Date();
|
||||
start.setHours(0, 0, 0, 0);
|
||||
const end = new Date();
|
||||
end.setHours(23, 59, 59, 999);
|
||||
return [formatDateTime(start), formatDateTime(end)];
|
||||
},
|
||||
},
|
||||
{
|
||||
text: '本周',
|
||||
value: () => {
|
||||
const now = new Date();
|
||||
const day = now.getDay() || 7; // 周一为一周开始
|
||||
const start = new Date(now);
|
||||
start.setDate(start.getDate() - day + 1);
|
||||
start.setHours(0, 0, 0, 0);
|
||||
const end = new Date();
|
||||
end.setHours(23, 59, 59, 999);
|
||||
return [formatDateTime(start), formatDateTime(end)];
|
||||
},
|
||||
},
|
||||
{
|
||||
text: '本月',
|
||||
value: () => {
|
||||
const now = new Date();
|
||||
const start = new Date(now.getFullYear(), now.getMonth(), 1, 0, 0, 0, 0);
|
||||
const end = new Date(now);
|
||||
end.setHours(23, 59, 59, 999);
|
||||
return [formatDateTime(start), formatDateTime(end)];
|
||||
},
|
||||
},
|
||||
{
|
||||
text: '上个月',
|
||||
value: () => {
|
||||
const now = new Date();
|
||||
const start = new Date(now.getFullYear(), now.getMonth() - 1, 1, 0, 0, 0, 0);
|
||||
const end = new Date(now.getFullYear(), now.getMonth(), 0, 23, 59, 59, 999);
|
||||
return [formatDateTime(start), formatDateTime(end)];
|
||||
},
|
||||
},
|
||||
{
|
||||
text: '前3月',
|
||||
value: () => {
|
||||
const now = new Date();
|
||||
const end = new Date();
|
||||
end.setHours(23, 59, 59, 999);
|
||||
const start = new Date(now.getFullYear(), now.getMonth() - 3, now.getDate(), 0, 0, 0, 0);
|
||||
return [formatDateTime(start), formatDateTime(end)];
|
||||
},
|
||||
},
|
||||
{
|
||||
text: '今年',
|
||||
value: () => {
|
||||
const now = new Date();
|
||||
const start = new Date(now.getFullYear(), 0, 1, 0, 0, 0, 0);
|
||||
const end = new Date();
|
||||
end.setHours(23, 59, 59, 999);
|
||||
return [formatDateTime(start), formatDateTime(end)];
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
// ==================== 表单引用 ====================
|
||||
const createFormRef = Vue.ref(null);
|
||||
const editFormRef = Vue.ref(null);
|
||||
|
|
@ -910,6 +976,7 @@ const app = createApp({
|
|||
createRules,
|
||||
editRules,
|
||||
exportRules,
|
||||
dateShortcuts,
|
||||
// 表单引用
|
||||
createFormRef,
|
||||
editFormRef,
|
||||
|
|
|
|||
Loading…
Reference in New Issue