feat: 在查询元数据键中添加 _where 支持,并实现自定义过滤器功能
This commit is contained in:
parent
756213f9af
commit
121a46ce33
@ -479,7 +479,6 @@ function mapOutpatientVisit(row, options = {}) {
|
||||
const registerType = pick(row, ["ST_REG_TYPE_NAME", "ST_REG_CATEGORY_NAME"]);
|
||||
const visitType = pick(row, ["VISIT_TYPE", "ST_VISIT_TYPE"]);
|
||||
const chargeType = pick(row, ["ST_CHARGE_TYPE", "SC_CHARGE_TYPE"]);
|
||||
const serviceItems = joinPicked(row, ["ST_REG_TYPE_NAME", "ST_REG_CATEGORY_NAME", "ST_VISIT_TYPE", "VISIT_TYPE", "ST_CHARGE_TYPE"]);
|
||||
const amount = pick(row, [
|
||||
"TREATMENT_COST",
|
||||
"REGISTER_TOTAL_COST",
|
||||
@ -522,8 +521,6 @@ function mapOutpatientVisit(row, options = {}) {
|
||||
visitType,
|
||||
chargeType,
|
||||
insuranceType: pick(row, ["INSURANCE_TYPE"]),
|
||||
serviceItems,
|
||||
serviceItem: serviceItems,
|
||||
amount,
|
||||
treatmentCost: pick(row, ["TREATMENT_COST"]),
|
||||
registerCost: pick(row, ["REGISTER_COST"]),
|
||||
|
||||
@ -2,7 +2,7 @@ const sql = require("mssql");
|
||||
const { getConfig, parsePositiveInteger } = require("../../core/config");
|
||||
|
||||
const pools = new Map();
|
||||
const QUERY_META_KEYS = new Set(["page", "pageSize", "saveSnapshot"]);
|
||||
const QUERY_META_KEYS = new Set(["page", "pageSize", "saveSnapshot", "_where"]);
|
||||
const RANGE_FILTERS = {
|
||||
startCreateTime: { field: "create_time", op: ">=" },
|
||||
endCreateTime: { field: "create_time", op: "<=" },
|
||||
@ -97,6 +97,7 @@ function buildWhereClause({ query, fields, fieldMapping, resourceConfig }) {
|
||||
const standardFields = new Set(fields);
|
||||
const inputs = [];
|
||||
const clauses = [];
|
||||
addCustomFilters({ clauses, inputs, where: query && query._where, standardFields, fieldMapping });
|
||||
|
||||
for (const [key, rawValue] of Object.entries(query || {})) {
|
||||
if (QUERY_META_KEYS.has(key) || isEmpty(rawValue)) continue;
|
||||
@ -123,6 +124,14 @@ function buildWhereClause({ query, fields, fieldMapping, resourceConfig }) {
|
||||
function addFilter({ clauses, inputs, standardField, value, fieldMapping, op }) {
|
||||
const sourceField = assertIdentifier(fieldMapping[standardField] || standardField, `filter.${standardField}`);
|
||||
const paramName = `p${inputs.length}`;
|
||||
if (op === "notEmpty") {
|
||||
clauses.push(`(${quoteName(sourceField)} IS NOT NULL AND LTRIM(RTRIM(CONVERT(NVARCHAR(MAX), ${quoteName(sourceField)}))) <> '')`);
|
||||
return;
|
||||
}
|
||||
if (op === "isEmpty") {
|
||||
clauses.push(`(${quoteName(sourceField)} IS NULL OR LTRIM(RTRIM(CONVERT(NVARCHAR(MAX), ${quoteName(sourceField)}))) = '')`);
|
||||
return;
|
||||
}
|
||||
if (op === "like") {
|
||||
clauses.push(`${quoteName(sourceField)} LIKE @${paramName}`);
|
||||
inputs.push({ name: paramName, value: `%${String(value).trim()}%` });
|
||||
@ -132,6 +141,28 @@ function addFilter({ clauses, inputs, standardField, value, fieldMapping, op })
|
||||
inputs.push({ name: paramName, value });
|
||||
}
|
||||
|
||||
function addCustomFilters({ clauses, inputs, where, standardFields, fieldMapping }) {
|
||||
if (!Array.isArray(where)) return;
|
||||
for (const item of where) {
|
||||
const standardField = item && String(item.field || item.column || "").trim();
|
||||
if (!standardField || !standardFields.has(standardField)) continue;
|
||||
const op = normalizeCustomOperator(item.op || item.operator || item.type);
|
||||
if (!op) continue;
|
||||
if (op !== "notEmpty" && op !== "isEmpty" && isEmpty(item.value)) continue;
|
||||
addFilter({ clauses, inputs, standardField, value: item.value, fieldMapping, op });
|
||||
}
|
||||
}
|
||||
|
||||
function normalizeCustomOperator(op) {
|
||||
const text = String(op || "eq").trim().toLowerCase();
|
||||
if (["notempty", "not_empty", "isnotempty", "is_not_empty"].includes(text)) return "notEmpty";
|
||||
if (["isempty", "is_empty", "empty"].includes(text)) return "isEmpty";
|
||||
if (["like", "contains"].includes(text)) return "like";
|
||||
if (["ne", "neq", "!=", "<>"].includes(text)) return "<>";
|
||||
if (["eq", "="].includes(text)) return "=";
|
||||
return "";
|
||||
}
|
||||
|
||||
function getFilterOperator(resourceConfig, standardField) {
|
||||
const configured = resourceConfig.filterOperators && resourceConfig.filterOperators[standardField];
|
||||
if (!configured) return "=";
|
||||
|
||||
@ -2,7 +2,7 @@ const { spawn } = require("child_process");
|
||||
const iconv = require("iconv-lite");
|
||||
const { getConfig, parsePositiveInteger } = require("../../core/config");
|
||||
|
||||
const QUERY_META_KEYS = new Set(["page", "pageSize", "saveSnapshot"]);
|
||||
const QUERY_META_KEYS = new Set(["page", "pageSize", "saveSnapshot", "_where"]);
|
||||
const RANGE_FILTERS = {
|
||||
startCreateTime: { field: "create_time", op: ">=" },
|
||||
endCreateTime: { field: "create_time", op: "<=" },
|
||||
@ -182,6 +182,7 @@ function parseSqlplusOutput(output, fields) {
|
||||
function buildWhereClause({ query, fields, fieldMapping, resourceConfig }) {
|
||||
const standardFields = new Set(fields);
|
||||
const clauses = [];
|
||||
addCustomFilters({ clauses, where: query && query._where, standardFields, fieldMapping });
|
||||
for (const [key, rawValue] of Object.entries(query || {})) {
|
||||
if (QUERY_META_KEYS.has(key) || isEmpty(rawValue)) continue;
|
||||
|
||||
@ -202,10 +203,34 @@ function buildWhereClause({ query, fields, fieldMapping, resourceConfig }) {
|
||||
|
||||
function buildFilterSql({ standardField, value, fieldMapping, op }) {
|
||||
const sourceField = assertIdentifier(fieldMapping[standardField] || standardField, `filter.${standardField}`);
|
||||
if (op === "notEmpty") return `${cleanSqlValue(identifier(sourceField))} <> ''`;
|
||||
if (op === "isEmpty") return `${cleanSqlValue(identifier(sourceField))} = ''`;
|
||||
if (op === "like") return `${cleanSqlValue(identifier(sourceField))} LIKE ${literal(`%${String(value).trim()}%`)}`;
|
||||
return `${cleanSqlValue(identifier(sourceField))} ${op || "="} ${literal(value)}`;
|
||||
}
|
||||
|
||||
function addCustomFilters({ clauses, where, standardFields, fieldMapping }) {
|
||||
if (!Array.isArray(where)) return;
|
||||
for (const item of where) {
|
||||
const standardField = item && String(item.field || item.column || "").trim();
|
||||
if (!standardField || !standardFields.has(standardField)) continue;
|
||||
const op = normalizeCustomOperator(item.op || item.operator || item.type);
|
||||
if (!op) continue;
|
||||
if (op !== "notEmpty" && op !== "isEmpty" && isEmpty(item.value)) continue;
|
||||
clauses.push(buildFilterSql({ standardField, value: item.value, fieldMapping, op }));
|
||||
}
|
||||
}
|
||||
|
||||
function normalizeCustomOperator(op) {
|
||||
const text = String(op || "eq").trim().toLowerCase();
|
||||
if (["notempty", "not_empty", "isnotempty", "is_not_empty"].includes(text)) return "notEmpty";
|
||||
if (["isempty", "is_empty", "empty"].includes(text)) return "isEmpty";
|
||||
if (["like", "contains"].includes(text)) return "like";
|
||||
if (["ne", "neq", "!=", "<>"].includes(text)) return "<>";
|
||||
if (["eq", "="].includes(text)) return "=";
|
||||
return "";
|
||||
}
|
||||
|
||||
function getFilterOperator(resourceConfig, standardField) {
|
||||
const configured = resourceConfig.filterOperators && resourceConfig.filterOperators[standardField];
|
||||
if (!configured) return "=";
|
||||
|
||||
@ -4,7 +4,7 @@ const { getConfig, parsePositiveInteger } = require("../../core/config");
|
||||
oracledb.outFormat = oracledb.OUT_FORMAT_OBJECT;
|
||||
|
||||
const pools = new Map();
|
||||
const QUERY_META_KEYS = new Set(["page", "pageSize", "saveSnapshot"]);
|
||||
const QUERY_META_KEYS = new Set(["page", "pageSize", "saveSnapshot", "_where"]);
|
||||
const RANGE_FILTERS = {
|
||||
startCreateTime: { field: "create_time", op: ">=" },
|
||||
endCreateTime: { field: "create_time", op: "<=" },
|
||||
@ -96,6 +96,7 @@ function buildWhereClause({ query, fields, fieldMapping, resourceConfig }) {
|
||||
const standardFields = new Set(fields);
|
||||
const binds = {};
|
||||
const clauses = [];
|
||||
addCustomFilters({ clauses, binds, where: query && query._where, standardFields, fieldMapping });
|
||||
|
||||
for (const [key, rawValue] of Object.entries(query || {})) {
|
||||
if (QUERY_META_KEYS.has(key) || isEmpty(rawValue)) continue;
|
||||
@ -122,6 +123,14 @@ function buildWhereClause({ query, fields, fieldMapping, resourceConfig }) {
|
||||
function addFilter({ clauses, binds, standardField, value, fieldMapping, op }) {
|
||||
const sourceField = assertIdentifier(fieldMapping[standardField] || standardField, `filter.${standardField}`);
|
||||
const paramName = `p${Object.keys(binds).length}`;
|
||||
if (op === "notEmpty") {
|
||||
clauses.push(`((${identifier(sourceField)} IS NOT NULL) AND TRIM(TO_CHAR(${identifier(sourceField)})) <> '')`);
|
||||
return;
|
||||
}
|
||||
if (op === "isEmpty") {
|
||||
clauses.push(`((${identifier(sourceField)} IS NULL) OR TRIM(TO_CHAR(${identifier(sourceField)})) = '')`);
|
||||
return;
|
||||
}
|
||||
if (op === "like") {
|
||||
clauses.push(`${identifier(sourceField)} LIKE :${paramName}`);
|
||||
binds[paramName] = `%${String(value).trim()}%`;
|
||||
@ -131,6 +140,28 @@ function addFilter({ clauses, binds, standardField, value, fieldMapping, op }) {
|
||||
binds[paramName] = value;
|
||||
}
|
||||
|
||||
function addCustomFilters({ clauses, binds, where, standardFields, fieldMapping }) {
|
||||
if (!Array.isArray(where)) return;
|
||||
for (const item of where) {
|
||||
const standardField = item && String(item.field || item.column || "").trim();
|
||||
if (!standardField || !standardFields.has(standardField)) continue;
|
||||
const op = normalizeCustomOperator(item.op || item.operator || item.type);
|
||||
if (!op) continue;
|
||||
if (op !== "notEmpty" && op !== "isEmpty" && isEmpty(item.value)) continue;
|
||||
addFilter({ clauses, binds, standardField, value: item.value, fieldMapping, op });
|
||||
}
|
||||
}
|
||||
|
||||
function normalizeCustomOperator(op) {
|
||||
const text = String(op || "eq").trim().toLowerCase();
|
||||
if (["notempty", "not_empty", "isnotempty", "is_not_empty"].includes(text)) return "notEmpty";
|
||||
if (["isempty", "is_empty", "empty"].includes(text)) return "isEmpty";
|
||||
if (["like", "contains"].includes(text)) return "like";
|
||||
if (["ne", "neq", "!=", "<>"].includes(text)) return "<>";
|
||||
if (["eq", "="].includes(text)) return "=";
|
||||
return "";
|
||||
}
|
||||
|
||||
function getFilterOperator(resourceConfig, standardField) {
|
||||
const configured = resourceConfig.filterOperators && resourceConfig.filterOperators[standardField];
|
||||
if (!configured) return "=";
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user