20260712212917

This commit is contained in:
oneao committed 2026-07-12 21:29:17 +08:00
1 parent 4677f6c519
commit 00472688ab
361 files changed
-153949

No files matched your search

@@ -1,207 +0,0 @@
<script setup>
import { ElMessage } from "element-plus";
import { onMounted, ref, watch } from "vue";
import axios from "@/utils/axios";
import { isNotEmpty } from "@/utils/g3Funlib.js";
const props = defineProps({
moduleId: { type: String },
});
const emit = defineEmits(["update:search"]);
const querys = ref([]);
const sqllable = ref("");
const sqlvalue = ref("");
// 列配置
async function addQuery(moduleId) {
let searchsql = `select ROW_NUMBER() OVER (ORDER BY col_SearchOrder) AS b_id,col_caption as lable, col_fieldname from s_columnlib where col_TableName='${moduleId}' and col_CanSearch ='1' and isnull(col_type,'') <> 'date' order by col_SearchOrder`;
const response = await axios.get("/selectlistbysql", { params: { sql: searchsql } });
if (response.data?.success) {
const records = response.data.data.records || [];
if (records.length > 0) {
querys.value = records;
sqllable.value = records[0].lable;
} else {
const columnsDefault = [
{ b_id: 1, col_fieldname: "b_id", lable: "代码" },
{ b_id: 2, col_fieldname: "b_name", lable: "名称" },
];
querys.value = columnsDefault;
sqllable.value = columnsDefault[0].lable;
ElMessage.warning("没有查询条件,默认条件");
}
}
}
function handleSearch() {
let sql = "";
if (isNotEmpty(sqlvalue.value)) {
const selected = querys.value.find((i) => i.lable?.trim() === sqllable.value?.trim());
if (selected) {
sql += ` ${selected.col_fieldname} like '%${sqlvalue.value}%'`;
}
}
emit("update:search", sql);
}
watch(sqllable, (val) => {
sqllable.value = val;
});
watch(
() => props.moduleId,
async (newModuleId) => {
if (!newModuleId) return;
await addQuery(newModuleId);
},
{
immediate: true, // 第一次进入组件也会执行
},
);
onMounted(async () => {
if (!props.moduleId) return;
await addQuery(props.moduleId);
});
</script>
<template>
<div class="g3pagecontainer">
<div class="main">
<div class="g3cell">
<div class="g3celllabel">
<el-select v-model="sqllable" class="g3select">
<el-option
v-for="item in querys"
:key="item.b_id"
:label="item.lable"
:value="item.lable"
/>
</el-select>
</div>
</div>
<el-input v-model="sqlvalue" />
</div>
<div class="g3toolbar" @click="handleSearch">
<div class="g3svg">
<svg
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
aria-hidden="true"
role="img"
width="18px"
height="18px"
viewBox="0 0 24 24"
class="iconify iconify--stash"
>
<path
fill="currentColor"
fill-rule="evenodd"
d="M10.44 2.75a7.69 7.69 0 1 0 4.615 13.842c.058.17.154.329.29.464l3.84 3.84a1.21 1.21 0 0 0 1.71-1.712l-3.84-3.84a1.2 1.2 0 0 0-.463-.289A7.69 7.69 0 0 0 10.44 2.75m-5.75 7.69a5.75 5.75 0 1 1 11.5 0a5.75 5.75 0 0 1-11.5 0"
clip-rule="evenodd"
></path>
</svg>
</div>
<div class="lable">查询</div>
</div>
</div>
</template>
<style lang="scss" scoped>
.g3pagecontainer {
display: flex;
align-items: center;
margin-right: 30px;
background-color: #fff !important;
}
.main {
display: flex;
align-items: center;
height: 32px;
width: 271px;
box-sizing: border-box;
}
.g3cell {
display: flex;
align-items: center;
background: #fff;
color: #333639;
font-size: 14px;
height: 26px;
}
.g3celllabel {
border: 1px solid #e0e0e6;
background: #f9f9f9;
border-top-left-radius: 8px;
border-bottom-left-radius: 8px;
border-right: 0px;
}
.g3toolbar {
display: flex;
align-items: center;
justify-content: center;
width: 80px;
height: 34px;
background-color: #2d8cf0;
border: 0px;
border-top-right-radius: 8px;
border-bottom-right-radius: 8px;
cursor: pointer;
transition:
color 0.3s cubic-bezier(0.4, 0, 0.2, 1),
background-color 0.3s cubic-bezier(0.4, 0, 0.2, 1),
opacity 0.3s cubic-bezier(0.4, 0, 0.2, 1),
border-color 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}
.g3toolbar:hover {
background-color: #0f4da3;
color: #fff;
}
.g3toolbar .g3svg {
color: #fff;
width: 18px;
height: 18px;
margin: 6px 6px 6px 0px;
}
.g3toolbar .lable {
display: flex;
align-items: center;
height: 14px;
font-size: 14px;
color: #fff;
font-family:
v-sans,
system-ui,
-apple-system,
BlinkMacSystemFont,
"Segoe UI",
sans-serif,
"Apple Color Emoji",
"Segoe UI Emoji",
"Segoe UI Symbol";
}
.g3select {
width: 100px;
}
:deep(.g3select .el-select__wrapper) {
height: 32px !important;
line-height: 32px !important;
min-height: 32px;
border: 0px !important;
box-shadow: unset;
border-radius: 0px !important;
border-top-left-radius: 8px !important;
border-bottom-left-radius: 8px !important;
padding: 0px 6px;
}
:deep(.el-input__wrapper) {
border-radius: 0px !important;
padding: 0px 12px !important;
}
:deep(.el-input__inner) {
height: 34px;
line-height: 34px;
}
</style>
@@ -1,532 +0,0 @@
<script setup>
import dayjs from "dayjs";
import { ElMessage } from "element-plus";
import { onMounted, ref } from "vue";
import g3Select from "@/components/g3Select.vue";
import axios from "@/utils/axios";
import { Search } from "@element-plus/icons-vue";
const props = defineProps({
moduleId: { type: String },
resultPreviewVisible: { type: Boolean, default: false },
// 特殊处理字段,不参与sql拼接
excludeFields: {
type: Array,
default: () => [],
},
});
const emit = defineEmits(["update:search"]);
const loading = ref(false);
const querys = ref([]);
const colNum = ref(4);
// 列配置
async function addQuery(moduleId) {
let searchsql = `select ROW_NUMBER() OVER (ORDER BY col_position) AS b_id,subid,col_caption as lable,col_fieldname,col_operator,col_option,col_type,col_pycode,col_source_field,col_source_table,col_defaultvalue_end,col_defaultvalue_start from s_search_sub where mx_module_id='${moduleId}' and col_visible ='1' order by col_position`;
const response = await axios.get("/selectlistbysql", { params: { sql: searchsql } });
if (response.data?.success) {
const records = response.data.data.records || [];
// console.log('records=-=-=-=-=-')
// console.log(records)
if (records.length > 0) {
querys.value = records.map((item) => {
if (typeof item.col_option === "string") {
try {
const fixed = item.col_option.replace(/"/g, '"');
item.col_option = JSON.parse(fixed);
} catch (e) {
item.col_option = [];
}
}
const field = item.col_fieldname || "";
if (item.col_type === "date") {
return {
...item,
[`${field}start`]: parseDateConfig(item.col_defaultvalue_start),
[`${field}end`]: parseDateConfig(item.col_defaultvalue_end),
};
} else if (item.col_type === "number") {
return {
...item,
[`${field}min`]: Number(item.col_defaultvalue_start) || "",
[`${field}max`]: Number(item.col_defaultvalue_end) || "",
};
} else {
return {
...item,
_value: item.col_defaultvalue_start || "",
[`${field}value`]: item.col_defaultvalue_start || "",
};
}
});
} else {
ElMessage.warning("没有查询条件");
}
}
}
const operatorMap = {
等于: (item) => `${item.col_fieldname} = '${item[`${item.col_fieldname}value`]}'`,
不等于: (item) => `${item.col_fieldname} <> '${item[`${item.col_fieldname}value`]}'`,
为空: (item) => `(${item.col_fieldname} IS NULL OR ${item.col_fieldname} = '')`,
不为空: (item) => `(${item.col_fieldname} IS NOT NULL AND ${item.col_fieldname} <> '')`,
包含: (item) => `${item.col_fieldname} LIKE '%${item[`${item.col_fieldname}value`]}%'`,
};
const hasVal = (v) => v !== undefined && v !== null && v !== "";
function handleSearch() {
let whereList = [];
querys.value.forEach((item) => {
if (props.excludeFields.includes(item.col_fieldname)) {
return;
}
if (item.col_type === "date") {
const start = item[`${item.col_fieldname}start`];
const end = item[`${item.col_fieldname}end`];
if (start) {
whereList.push(`${item.col_fieldname} >= '${start} 00:00:00'`);
}
if (end) {
whereList.push(`${item.col_fieldname} < DATEADD(day, 1, '${end}')`);
}
} else if (item.col_type === "number") {
const min = item[`${item.col_fieldname}min`];
const max = item[`${item.col_fieldname}max`];
if (hasVal(min)) {
whereList.push(
item.col_operator == "等于"
? `${item.col_fieldname} >= ${min}`
: `${item.col_fieldname} > ${min}`,
);
}
if (hasVal(max)) {
whereList.push(
item.col_operator == "等于"
? `${item.col_fieldname} <= ${max}`
: `${item.col_fieldname} < ${max}`,
);
}
} else {
let val = item[`${item.col_fieldname}value`];
if ((item.col_operator === "为空" || item.col_operator === "不为空") && !val) {
whereList.push(operatorMap[item.col_operator](item));
return;
}
if (!hasVal(val)) return;
if (item.col_type == "option") {
if (val != "all") {
whereList.push(val);
}
} else if (item.col_type == "radio") {
if (val != "all") {
whereList.push(val);
}
} else if (item.col_type == "checkbox") {
if (val == "1") {
whereList.push(item.col_option?.[0]?.all);
}
} else if (operatorMap[item.col_operator]) {
whereList.push(operatorMap[item.col_operator](item));
} else {
whereList.push(`${item.col_fieldname} LIKE '%${val}%'`);
}
}
});
let sql = whereList.length > 0 ? " " + whereList.join(" AND ") : "";
emit("update:search", sql, querys.value);
}
function handleReset() {
querys.value.forEach((item) => {
const valueKey = `${item.col_fieldname}value`;
item._value = null;
switch (item.col_type) {
case "text":
case "input":
item[valueKey] = ""; // 文本输入
break;
case "date":
item[`${item.col_fieldname}start`] = ""; // 开始日期
item[`${item.col_fieldname}end`] = ""; // 结束日期
break;
case "select":
case "option":
item[valueKey] = ""; // 下拉/选项
break;
case "radio":
item[valueKey] = "all"; // 下拉/选项
break;
case "number":
item[`${item.col_fieldname}min`] = ""; // 值
item[`${item.col_fieldname}max`] = ""; // 值
break;
case "checkbox":
item[valueKey] = ""; // 如果你希望默认 false 可以改为 0
break;
default:
item[valueKey] = ""; // 其他类型默认清空
}
});
}
function childMethod(flag, field, value) {
querys.value.forEach((item) => {
const valueKey = `${item.col_fieldname}value`;
if (valueKey == field && flag == "1") {
item[valueKey] = value;
item._value = value;
}
});
handleSearch();
}
// 暴露给父组件
defineExpose({
childMethod,
});
function parseDateConfig(configStr) {
if (!configStr) return "";
const arr = configStr
.replace(/[()]/g, "")
.replace(/"/g, "")
.split(",")
.map((i) => i.trim());
const [base, yearOffset, monthOffset, dayOffset, dateType] = arr;
let date = dayjs();
// 1️⃣ 基准
if (base === "当前时间") {
date = dayjs();
} else {
return "";
}
// 2️⃣ 偏移
if (yearOffset) date = date.add(Number(yearOffset), "year");
if (monthOffset) date = date.add(Number(monthOffset), "month");
if (dayOffset) date = date.add(Number(dayOffset), "day");
if (dateType === "月初") {
date = date.startOf("month");
} else if (dateType === "月末") {
date = date.endOf("month");
}
return date.format("YYYY-MM-DD");
}
async function addSQL(moduleId) {
let searchsql = `select * from s_search where b_module_id='${moduleId}'`;
const response = await axios.get("/selectlistbysql", { params: { sql: searchsql } });
if (response.data?.success) {
const records = response.data.data.records || [];
if (records.length > 0) {
colNum.value = records[0].b_col_num;
} else {
ElMessage.warning("没有查询语句");
}
}
}
const handleSetdata = (val, col_fieldname) => {
const query = querys.value.find((item) => item.col_fieldname === col_fieldname);
if (!query) return;
query._value = val;
};
onMounted(async () => {
await addSQL(props.moduleId);
await addQuery(props.moduleId);
});
</script>
<template>
<div style="display: flex; align-items: center">
<div
class="g3-grid"
:style="{
height: querys.length < colNum ? '28px' : '',
gridTemplateColumns: `repeat(${colNum} , 260px)`,
}"
>
<div v-for="item in querys" :key="item.b_id" class="g3-cell">
<div class="g3-cell-label">
<el-input v-model="item.lable" class="caption-input" style="width: 66px" readonly />
</div>
<template v-if="item.col_type === 'select'">
<g3Select
v-model="item[`${item.col_fieldname}value`]"
:query-params="{ dataset: item.col_source_table }"
:in-table="true"
:mustmatch="true"
:pycode="item.col_pycode === 'true'"
@select="(val) => handleSetdata(val, item.col_fieldname)"
/>
</template>
<template v-else-if="item.col_type === 'date'">
<el-date-picker
v-model="item[`${item.col_fieldname}start`]"
type="date"
format="YYYY-MM-DD"
value-format="YYYY-MM-DD"
style="width: 100px"
:clearable="false"
class="g3-prefix"
size="small"
/>
<span class="g3-query-span">---</span>
<el-date-picker
v-model="item[`${item.col_fieldname}end`]"
type="date"
format="YYYY-MM-DD"
value-format="YYYY-MM-DD"
style="width: 101px"
:clearable="false"
class="g3-prefix"
size="small"
/>
</template>
<template v-else-if="item.col_type === 'option'">
<el-select
v-model="item[`${item.col_fieldname}value`]"
clearable
placeholder=""
size="small"
@change="(val) => handleSetdata(val, item.col_fieldname)"
>
<el-option
v-for="op in item.col_option"
:key="op.value"
:label="op.label"
:value="op.value"
/>
</el-select>
</template>
<template v-else-if="item.col_type === 'radio'">
<el-radio-group v-model="item[`${item.col_fieldname}value`]" class="g3-query-radio">
<el-radio v-for="op in item.col_option" :key="op.value" :value="op.value" size="small">
{{ op.label }}
</el-radio>
</el-radio-group>
</template>
<template v-else-if="item.col_type === 'number'">
<el-input v-model="item[`${item.col_fieldname}min`]" style="width: 100px" size="small" />
<span class="g3-query-span">~</span>
<el-input v-model="item[`${item.col_fieldname}max`]" style="width: 100px" size="small" />
</template>
<el-checkbox
v-else-if="item.col_type === 'checkbox'"
v-model="item[`${item.col_fieldname}value`]"
true-value="1"
false-value=""
size="large"
/>
<el-input
v-else
v-model="item[`${item.col_fieldname}value`]"
size="small"
:placeholder="
['为空', '不为空'].includes(item.col_operator) ? `查询${item.col_operator}` : ''
"
:disabled="item.col_operator == '为空' || item.col_operator == '不为空'"
/>
</div>
</div>
<div v-if="!props.resultPreviewVisible" class="g3toolbar">
<div class="g3search" @click="handleSearch">
<div class="g3svg">
<svg
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
aria-hidden="true"
role="img"
width="18px"
height="18px"
viewBox="0 0 24 24"
class="iconify iconify--stash"
>
<path
fill="currentColor"
fill-rule="evenodd"
d="M10.44 2.75a7.69 7.69 0 1 0 4.615 13.842c.058.17.154.329.29.464l3.84 3.84a1.21 1.21 0 0 0 1.71-1.712l-3.84-3.84a1.2 1.2 0 0 0-.463-.289A7.69 7.69 0 0 0 10.44 2.75m-5.75 7.69a5.75 5.75 0 1 1 11.5 0a5.75 5.75 0 0 1-11.5 0"
clip-rule="evenodd"
></path>
</svg>
</div>
<div class="lable">查询</div>
</div>
<div class="g3reset" @click="handleReset">重置</div>
<!-- <el-button > 查询 </el-button>
<el-button style="margin-left: 10px" @click="handleReset"> 重置 </el-button> -->
</div>
</div>
</template>
<style scoped>
.g3-grid {
display: grid;
grid-template-columns: repeat(4, 260px);
gap: 2px;
box-sizing: border-box;
}
.g3-cell {
display: flex;
align-items: center;
color: #333;
font-size: 14px;
height: 24px;
background: #fff;
}
:deep(.caption-input .el-input__inner) {
text-align: right;
}
.g3-query-span {
background: #fff;
height: 24px;
width: 21px;
color: #ddd;
display: flex;
align-items: center;
justify-content: center;
}
:deep(.el-input__inner) {
height: 24px !important;
line-height: 24px !important;
}
:deep(.el-input__wrapper) {
padding: 0px 4px;
}
:deep(.g3-cell-label .el-input__wrapper) {
border: 0px !important;
box-shadow: unset;
border-radius: 0px !important;
padding: 0px 4px 0px 0px;
}
:deep(.el-select .el-select__wrapper) {
height: 24px !important;
line-height: 24px !important;
min-height: 24px;
padding: 0px 4px;
}
.el-radio {
margin-right: 4px;
height: 22px;
margin-left: 2px;
}
:deep(.el-radio__label) {
padding-left: 3px;
}
.g3-query-radio {
width: 100%;
padding: 0px 4px;
box-shadow: 0 0 0 1px #dcdfe6 inset;
border-radius: 4px;
}
.g3-query-radio .el-radio {
margin-right: 8px;
font-size: 12px;
}
:deep(.el-input.is-disabled .el-input__wrapper) {
box-shadow: unset;
}
/* ----------------------------- */
.g3toolbar {
display: flex;
align-items: center;
}
.g3search {
display: flex;
align-items: center;
justify-content: center;
width: 80px;
height: 34px;
margin-left: 25px;
background-color: #2d8cf0;
border: 0px;
border-radius: 8px;
cursor: pointer;
transition:
color 0.3s cubic-bezier(0.4, 0, 0.2, 1),
background-color 0.3s cubic-bezier(0.4, 0, 0.2, 1),
opacity 0.3s cubic-bezier(0.4, 0, 0.2, 1),
border-color 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}
.g3search:hover {
background-color: #0f4da3;
color: #fff;
}
.g3search .g3svg {
color: #fff;
width: 18px;
height: 18px;
margin: 6px 6px 6px 0px;
}
.g3search .lable {
display: flex;
align-items: center;
height: 14px;
font-size: 14px;
color: #fff;
font-family:
v-sans,
system-ui,
-apple-system,
BlinkMacSystemFont,
"Segoe UI",
sans-serif,
"Apple Color Emoji",
"Segoe UI Emoji",
"Segoe UI Symbol";
}
.g3reset {
display: flex;
justify-content: center;
align-items: center;
width: 56px;
height: 34px;
color: #2080f0;
font-size: 14px;
font-weight: 400;
cursor: pointer;
font-family:
v-sans,
system-ui,
-apple-system,
BlinkMacSystemFont,
"Segoe UI",
sans-serif,
"Apple Color Emoji",
"Segoe UI Emoji",
"Segoe UI Symbol";
}
.g3reset:hover {
color: #2080f0;
background-color: rgba(46, 51, 56, 0.13);
border-radius: 8px;
}
/* -------------------------- */
</style>