初始化

This commit is contained in:
2025-07-28 15:52:07 +08:00
commit cd0e77b332
1304 changed files with 302802 additions and 0 deletions

View File

@@ -0,0 +1,558 @@
<!-- 搜索帮助 -->
<template>
<div>
<!--输入框-->
<el-autocomplete
v-bind="$attrs"
v-on="$listeners"
v-model="childValue"
clearable
v-if="filterable"
:fetch-suggestions="querySuggestions"
:trigger-on-focus="false"
@select="handleSelectSuggestion"
@clear="handleClear"
ref="autoRef"
>
<template slot-scope="{ item }">
{{ item.text }}
</template>
<i
slot="suffix"
class="el-input__icon el-icon-search"
@click="handleSelector"
:class="$attrs.disabled ? 'disabled' : ''"
></i>
</el-autocomplete>
<el-input
ref="inputLabel"
class="input-cursor"
v-bind="$attrs"
v-on="$listeners"
v-model="childLabel"
@focus="onInputFocus"
:clearable="clearable"
@clear="handleClear"
v-else-if="showLabel"
>
<i
slot="suffix"
class="el-input__icon el-icon-search"
@click="handleSelector"
:class="$attrs.disabled ? 'disabled' : ''"
></i>
</el-input>
<el-input
ref="inputValue"
class="input-cursor"
v-bind="$attrs"
v-on="$listeners"
v-model="childValue"
@focus="onInputFocus"
clearable
@clear="handleClear"
v-else
>
<i
slot="suffix"
class="el-input__icon el-icon-search"
@click="handleSelector"
:class="$attrs.disabled ? 'disabled' : ''"
></i>
</el-input>
<!--弹出框-->
<vxe-modal
v-model="open"
:title="dialogTitle || $t('generic.selectPlaceHolder')"
type="confirm"
:width="dialogWidth"
:height="dialogHeight"
:transfer="true"
:zIndex="3044"
resize
show-zoom
show-footer
>
<template #default>
<vxe-grid
ref="xGrid"
id="dataTableValueHelper"
class="grid-scrollbar"
:border="true"
:stripe="true"
:show-overflow="true"
:row-config="{
isHover: true,
}"
:column-config="{
resizable: true,
}"
:height="tableHeight"
:radio-config="{
trigger: 'row',
highlight: true,
}"
:columns="
[
{
title: '序号',
type: 'seq',
width: 50,
align: 'center',
},
].concat(columns)
"
:pager-config="tablePage"
:proxy-config="tableProxy"
:sort-config="{
remote: true,
trigger: 'cell',
defaultSort: defaultSort,
orders: ['desc', 'asc', null],
}"
@cell-dblclick="handleDbSelected"
>
<!--使用 form 插槽-->
<template #form>
<el-form :model="queryParams" ref="dialogQueryForm" :inline="true">
<el-form-item
v-for="domain in dynamicDomains"
:label="domain.label"
:key="domain.key"
:prop="domain.prop"
>
<el-input
v-model="domain.value"
:disabled="domain.disabled"
clearable
@keyup.enter.native="handleQuery"
></el-input>
</el-form-item>
<el-form-item>
<el-button
type="primary"
icon="el-icon-search"
@click="handleQuery"
>{{ $t("generic.search") }}</el-button
>
<el-button icon="el-icon-refresh" @click="resetQuery">{{
$t("generic.reset")
}}</el-button>
</el-form-item>
</el-form>
</template>
</vxe-grid>
</template>
<template #footer>
<vxe-button @click="cancel">{{ $t("generic.cancel") }}</vxe-button>
<vxe-button status="primary" @click="handleSelectionSubmit">{{
$t("generic.confirm")
}}</vxe-button>
</template>
</vxe-modal>
</div>
</template>
<script>
export default {
name: "ValueHelper",
components: {},
props: {
//值
value: {
type: [String, Number],
default: null,
},
//是否可搜索
filterable: {
type: Boolean,
default: false,
},
//显示value还是label,默认Value(不管显示哪个,实际值还是value),filterable=true时不支持
showLabel: {
type: Boolean,
default: false,
},
//输入框是否显示清空图标
clearable: {
type: Boolean,
default: true,
},
//值的配置选项
valueProps: {
type: Object,
default: () => {
return { value: "value", label: "label" };
},
},
//对话框标题
dialogTitle: {
type: String,
default: undefined,
},
//对话框宽度
dialogWidth: {
type: String,
default: "700px",
},
//对话框高度
dialogHeight: {
type: String,
default: "470px",
},
//对话框高度
tableHeight: {
type: [String, Number],
default: "auto",
},
//搜索条件,例子[{key:0,label:'货币编码',prop:'currencyCode'},{key:1,label:'货币名称', prop:'currencyName'},]
searchCriteria: {
type: Array,
default: () => [],
},
//额外的查询参数
otherParam: {
type: Object,
default: () => {},
},
//搜索方法
searchMethod: {
type: Function,
default: undefined,
},
//显示字段,例子[{key: 0,label: '货币编码',prop: 'currencyCode',align: 'center',sortable: true,},
// { key: 1, label: '货币名称', prop: 'currencyName', sortable: true },]
columns: {
type: Array,
default: () => [],
},
//默认的排序列的 prop 和顺序.例子{prop: "name",order: "ascending"}
defaultSort: {
type: Object,
default: () => {},
},
//校验方法
checkMethod: {
type: Function,
default: undefined,
},
//选项分隔符
separator: {
type: String,
default: "/",
},
},
data() {
return {
//选择参数
queryParams: {},
//选择值
childValue: this.value,
//选择文本
childLabel: undefined,
//是否显示弹出层
open: false,
// 配置分页信息
tablePage: {
background: true,
pagerCount: 5,
pageSize: 10,
pageSizes: [10, 20, 50, 100],
},
// 配置数据代理
tableProxy: {
autoLoad: false, //是否自动加载查询数据
sort: true, // 启用排序代理
props: {
result: "rows", // 配置响应结果列表字段
total: "total", // 配置响应结果总页数字段
},
ajax: {
// 接收 Promise 对象
query: ({ page, sorts, filters }) => {
//查询
return this.searchMethod(
this.buildParams(page, sorts, filters)
).then((response) => response);
},
},
},
// 动态查询参数
dynamicDomains: [],
};
},
watch: {
//父组件值变更
value(val) {
if (this.childValue !== val) {
// console.log("value change0:", val, this.childValue, this.childLabel);
this.childValue = val;
//有值,非Filterable模式,且是Show label时,获取文本
if (val && !this.filterable && this.showLabel) {
// console.log("value change1:", val, this.childValue, this.childLabel);
this.queryMappingLabel(val);
} else {
this.childLabel = undefined;
}
// console.log("value change2:", val, this.childValue, this.childLabel);
} else {
// console.log("value change3:", val, this.childValue, this.childLabel);
}
},
//搜索条件变更
searchCriteria(val, oldVal) {
if (JSON.stringify(val) !== JSON.stringify(oldVal)) {
this.criteriaToDynamicDomain(val);
}
},
},
created() {
//当显示文本模式时,通过初始值获取初始文本
if (this.value && !this.filterable && this.showLabel) {
this.queryMappingLabel(this.value);
}
//搜索条件转为动态输入框
this.criteriaToDynamicDomain(this.searchCriteria);
},
methods: {
//构建查询条件
buildParams(page, sorts, filters) {
//分页
const pageParams = {
pageNum: page.currentPage,
pageSize: page.pageSize,
reasonable: true,
};
//查询条件
const selectParams = this.addDynamicDomains(
pageParams,
this.dynamicDomains
);
// 处理排序条件
if (sorts && sorts.length > 0) {
const firstSort = sorts[0];
if (firstSort) {
selectParams.orderByColumn = firstSort.property;
selectParams.isAsc = firstSort.order;
}
}
// 处理筛选条件
if (filters) {
filters.forEach(({ property, values }) => {
selectParams[property] = values.join(",");
});
}
//额外的参数
if (this.otherParam) {
for (let key in this.otherParam) {
selectParams[key] = this.otherParam[key];
}
}
//模糊查询Code
selectParams.params = { fuzzyQueryCode: true };
console.log("buildQueryParams: ", selectParams);
return selectParams;
},
/**
* 输入条件转为动态输入框
*/
criteriaToDynamicDomain(val) {
this.dynamicDomains = val.map((item, i) => {
return {
key: i,
label: item.label,
prop: item.prop,
value: item.value,
disabled: item.disabled || false,
};
});
},
//获取值对应的文本
queryMappingLabel(val) {
var conditions = { pageNum: 1, pageSize: 1, reasonable: true };
conditions[this.valueProps.value] = val;
this.searchMethod(conditions).then((response) => {
if (response.rows && response.rows.length > 0) {
this.childLabel = response.rows[0][this.valueProps.label]; //文本
}
});
},
//根据用户输入远程搜索(暂时不支持Label)
querySuggestions(queryString, callback) {
var conditions = {
reasonable: true,
orderByColumn: this.defaultSort.field,
isAsc: this.defaultSort.order,
params: { fuzzyQueryCode: true }, //模糊查询Code
};
conditions[this.valueProps.value] = queryString; //暂时不支持Label
//远程查询
this.searchMethod(conditions).then((response) => {
//结果转换
var results = response.rows.map((item, i) => {
var values = [];
if (this.columns && this.columns.length > 0) {
for (var index = 0; index < this.columns.length; index++) {
values.push(item[this.columns[index].field]);
}
} else {
values.push(item[this.valueProps.value]);
values.push(item[this.valueProps.label]);
}
return {
value: item[this.valueProps.value], //暂时不支持Label
text: values.join(this.separator),
raw: item,
};
});
//结果回调
callback(results);
});
},
//选择建议
handleSelectSuggestion(item) {
this.$emit("selectSubmit", item.raw); //提交事件,传递值给父组件
},
//不允许输入框输入,但又支持Clear事件
onInputFocus(event) {
if (this.showLabel) {
this.$refs.inputLabel.blur();
} else {
this.$refs.inputValue.blur();
}
this.handleSelector();
},
//增加动态查询字段
addDynamicDomains(params, domains) {
let search = params;
if (domains && domains.length > 0) {
for (var i = 0; i < domains.length; i++) {
search[domains[i].prop] = domains[i].value;
}
}
return search;
},
//弹出选择框
handleSelector() {
this.open = true;
this.$nextTick(() => {
// console.log(this.$refs.xGrid);
this.$refs.xGrid.commitProxy("query");
});
},
//关闭选择框
cancel() {
this.open = false;
},
/** 搜索按钮操作 */
handleQuery() {
console.log(this.$refs.xGrid);
// this.queryParams.pageNum = 1;
this.$refs.xGrid.commitProxy("query");
},
/** 重置按钮操作 */
resetQuery() {
if (this.dynamicDomains && this.dynamicDomains.length > 0) {
for (var i = 0; i < this.dynamicDomains.length; i++) {
this.dynamicDomains[i].value = undefined;
}
}
this.handleQuery();
},
/**
* 双击选择
*/
handleDbSelected({ row }) {
this.childValue = row[this.valueProps.value]; //值
this.childLabel = row[this.valueProps.label]; //文本
this.$emit("input", row[this.valueProps.value]); //传递值给父组件
this.$emit("selectSubmit", row); //提交事件,传递值给父组件
this.cancel();
},
/**
* 点击确定提交
*/
handleSelectionSubmit() {
const selectionObject = this.$refs.xGrid.getRadioRecord();
if (selectionObject) {
this.childValue = selectionObject[this.valueProps.value]; //值
this.childLabel = selectionObject[this.valueProps.label]; //文本
this.$emit("input", selectionObject[this.valueProps.value]); //传递值给父组件
this.$emit("selectSubmit", selectionObject); //提交事件,传递值给父组件
this.cancel();
} else {
this.$message.info("请选择任意一行");
}
},
//清空事件
handleClear() {
if (this.filterable) {
this.$refs.autoRef.activated = true; //使用clearable清除,点击输入框下拉条件不再显示
}
this.$emit("clearSelect");
},
},
};
</script>
<style lang="scss" scoped>
.disabled {
pointer-events: none;
}
::v-deep {
.el-input__suffix {
&-inner {
flex-direction: row-reverse;
-webkit-flex-direction: row-reverse;
display: flex;
}
}
.el-icon-search {
position: relative;
&:hover {
cursor: pointer;
color: rgb(147, 149, 153);
}
&::after {
width: 1px;
height: 50%;
left: -1.5px;
position: absolute;
top: 25%;
background-color: rgb(233, 233, 233);
}
}
}
.input-cursor ::v-deep .el-input__inner {
cursor: pointer;
}
/*滚动条整体部分*/
.grid-scrollbar ::-webkit-scrollbar {
width: 10px;
height: 10px;
}
/*滚动条的轨道*/
.grid-scrollbar ::-webkit-scrollbar-track {
background-color: #ffffff;
}
/*滚动条里面的小方块,能向上向下移动*/
.grid-scrollbar ::-webkit-scrollbar-thumb {
background-color: #bfbfbf;
border-radius: 5px;
border: 1px solid #f1f1f1;
box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3);
}
.grid-scrollbar ::-webkit-scrollbar-thumb:hover {
background-color: #a8a8a8;
}
.grid-scrollbar ::-webkit-scrollbar-thumb:active {
background-color: #787878;
}
/*边角,即两个滚动条的交汇处*/
.grid-scrollbar ::-webkit-scrollbar-corner {
background-color: #ffffff;
}
</style>