134 lines
3.9 KiB
JavaScript
134 lines
3.9 KiB
JavaScript
// 模块数据驱动列表的「查询条件」工具:构建查询 SQL 片段、解析查询输入/默认值。
|
|
// 供 fms-module-list / fms-module-edit 等按模块元数据渲染的组件共用;
|
|
// 展示格式化(parseOptions / formatDateValue)见 fieldUtils.js。
|
|
|
|
export const identifierRe = /^[A-Za-z_][A-Za-z0-9_]*$/
|
|
|
|
export function escapeSqlText(value) {
|
|
return String(value).replaceAll("'", "''")
|
|
}
|
|
|
|
export function requireModuleId(value) {
|
|
const id = String(value ?? '')
|
|
if (!/^\d+$/.test(id)) throw new Error('模块 ID 格式不正确')
|
|
return id
|
|
}
|
|
|
|
export function isEmptyValue(value) {
|
|
return value === undefined || value === null || value === ''
|
|
}
|
|
|
|
export function isRangeQuery(item) {
|
|
return (
|
|
item.config.b_operator === 'between' ||
|
|
item.config.b_component === 'number-range' ||
|
|
item.field.b_type === 'datetime'
|
|
)
|
|
}
|
|
|
|
export function isNumericField(item) {
|
|
return item.field.b_type === 'number' || item.field.b_type === 'money'
|
|
}
|
|
|
|
export function isDateQuery(item) {
|
|
return (
|
|
item.config.b_component === 'date-picker' ||
|
|
item.field.b_type === 'date' ||
|
|
item.field.b_type === 'datetime'
|
|
)
|
|
}
|
|
|
|
export function emptyQueryValue(item) {
|
|
if (item.field.b_type === 'checkbox') return ''
|
|
if (isRangeQuery(item) || item.config.b_operator === 'in') return []
|
|
return undefined
|
|
}
|
|
|
|
export function defaultQueryValue(item) {
|
|
const value = item.config.b_default_value
|
|
if (value === null || value === undefined || value === '') return emptyQueryValue(item)
|
|
if (isRangeQuery(item) || item.config.b_operator === 'in') {
|
|
try {
|
|
const parsed = JSON.parse(value)
|
|
if (Array.isArray(parsed)) return parsed
|
|
} catch {
|
|
// 非 JSON 默认值继续按逗号分隔处理。
|
|
}
|
|
return String(value)
|
|
.split(',')
|
|
.map((part) => part.trim())
|
|
.filter(Boolean)
|
|
}
|
|
if (isNumericField(item)) {
|
|
const number = Number(value)
|
|
return Number.isFinite(number) ? number : undefined
|
|
}
|
|
return value
|
|
}
|
|
|
|
export function sqlLiteral(value, field, endOfRange = false) {
|
|
if (isEmptyValue(value)) return null
|
|
|
|
if (field.b_type === 'number' || field.b_type === 'money') {
|
|
const number = Number(value)
|
|
return Number.isFinite(number) ? String(number) : null
|
|
}
|
|
|
|
if (field.b_type === 'checkbox') {
|
|
return value === true || Number(value) === 1 ? '1' : '0'
|
|
}
|
|
|
|
let normalized = String(value)
|
|
const isDate = field.b_type === 'date' || field.b_type === 'datetime'
|
|
if (isDate && value && typeof value.format === 'function') {
|
|
normalized = value.format('YYYY-MM-DD')
|
|
} else if (isDate) {
|
|
normalized = String(value).slice(0, 10)
|
|
}
|
|
|
|
if (field.b_type === 'datetime') {
|
|
normalized += endOfRange ? ' 23:59:59' : ' 00:00:00'
|
|
}
|
|
|
|
return `N'${escapeSqlText(normalized)}'`
|
|
}
|
|
|
|
export function buildQueryCondition(item, value) {
|
|
const fieldName = item.field.b_field
|
|
if (!identifierRe.test(fieldName)) return ''
|
|
|
|
const field = `[${fieldName}]`
|
|
if (isRangeQuery(item)) {
|
|
const values = Array.isArray(value) ? value : []
|
|
const start = sqlLiteral(values[0], item.field)
|
|
const end = sqlLiteral(values[1], item.field, true)
|
|
if (start && end) return `${field} BETWEEN ${start} AND ${end}`
|
|
if (start) return `${field} >= ${start}`
|
|
if (end) return `${field} <= ${end}`
|
|
return ''
|
|
}
|
|
|
|
if (item.config.b_operator === 'in') {
|
|
let values = value
|
|
if (!Array.isArray(values)) {
|
|
values = String(value ?? '')
|
|
.split(',')
|
|
.map((part) => part.trim())
|
|
.filter(Boolean)
|
|
}
|
|
const literals = []
|
|
for (const entry of values) {
|
|
const literal = sqlLiteral(entry, item.field)
|
|
if (literal) literals.push(literal)
|
|
}
|
|
return literals.length ? `${field} IN (${literals.join(', ')})` : ''
|
|
}
|
|
|
|
const literal = sqlLiteral(value, item.field)
|
|
if (!literal) return ''
|
|
if (item.config.b_operator === 'like') {
|
|
return `${field} LIKE N'%${escapeSqlText(String(value))}%'`
|
|
}
|
|
return `${field} = ${literal}`
|
|
}
|