初始化
This commit is contained in:
558
src/components/ValueHelper/index.vue
Normal file
558
src/components/ValueHelper/index.vue
Normal 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>
|
||||
Reference in New Issue
Block a user