😎1、优化前端下拉组件 2、优化访问日志保存
This commit is contained in:
parent
085c8c8dba
commit
adf3251895
@ -4,8 +4,6 @@
|
|||||||
//
|
//
|
||||||
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
||||||
|
|
||||||
using Furion.Shapeless;
|
|
||||||
|
|
||||||
namespace Admin.NET.Core;
|
namespace Admin.NET.Core;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -13,13 +11,16 @@ namespace Admin.NET.Core;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class DatabaseLoggingWriter : IDatabaseLoggingWriter, IDisposable
|
public class DatabaseLoggingWriter : IDatabaseLoggingWriter, IDisposable
|
||||||
{
|
{
|
||||||
private readonly IServiceScope _serviceScope;
|
|
||||||
private readonly IEventPublisher _eventPublisher;
|
|
||||||
private readonly ILogger<DatabaseLoggingWriter> _logger;
|
private readonly ILogger<DatabaseLoggingWriter> _logger;
|
||||||
private readonly SysConfigService _sysConfigService;
|
private readonly SysConfigService _sysConfigService;
|
||||||
|
private readonly IEventPublisher _eventPublisher;
|
||||||
|
private readonly IServiceScope _serviceScope;
|
||||||
private readonly SqlSugarScopeProvider _db;
|
private readonly SqlSugarScopeProvider _db;
|
||||||
|
|
||||||
public DatabaseLoggingWriter(IServiceScopeFactory serviceScopeFactory, IEventPublisher eventPublisher, ILogger<DatabaseLoggingWriter> logger)
|
public DatabaseLoggingWriter(
|
||||||
|
IServiceScopeFactory serviceScopeFactory,
|
||||||
|
ILogger<DatabaseLoggingWriter> logger,
|
||||||
|
IEventPublisher eventPublisher)
|
||||||
{
|
{
|
||||||
_serviceScope = serviceScopeFactory.CreateScope();
|
_serviceScope = serviceScopeFactory.CreateScope();
|
||||||
_sysConfigService = _serviceScope.ServiceProvider.GetRequiredService<SysConfigService>();
|
_sysConfigService = _serviceScope.ServiceProvider.GetRequiredService<SysConfigService>();
|
||||||
@ -94,33 +95,24 @@ public class DatabaseLoggingWriter : IDatabaseLoggingWriter, IDisposable
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var loggingMonitor = JSON.Deserialize<dynamic>(jsonStr);
|
|
||||||
// 获取当前操作者
|
// 获取当前操作者
|
||||||
string account = "", realName = "", userId = "", tenantId = "";
|
var loggingMonitor = JSON.Deserialize<LoggingMonitorDto>(jsonStr);
|
||||||
if (loggingMonitor.authorizationClaims != null)
|
var userInfo = GetUserInfo(loggingMonitor);
|
||||||
{
|
|
||||||
var authDict = (loggingMonitor.authorizationClaims as IEnumerable<dynamic>)!.ToDictionary(u => u.type.ToString(), u => u.value.ToString());
|
|
||||||
account = authDict?.GetValueOrDefault(ClaimConst.Account);
|
|
||||||
realName = authDict?.GetValueOrDefault(ClaimConst.RealName);
|
|
||||||
tenantId = authDict?.GetValueOrDefault(ClaimConst.TenantId);
|
|
||||||
userId = authDict?.GetValueOrDefault(ClaimConst.UserId);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 优先获取 X-Forwarded-For 头部信息携带的IP地址(如nginx代理配置转发)
|
// 优先获取 X-Forwarded-For 头部信息携带的IP地址(如nginx代理配置转发)
|
||||||
var remoteIPv4 = ((JArray)loggingMonitor.requestHeaders).OfType<JObject>()
|
var reqHeaders = loggingMonitor.RequestHeaders.ToDictionary(u => u.Key, u => u.Value);
|
||||||
.FirstOrDefault(header => (string)header["key"] == "X-Forwarded-For")?["value"]?.ToString();
|
var remoteIPv4 = reqHeaders.GetValueOrDefault("X-Forwarded-For")?.ToString();
|
||||||
|
|
||||||
// 获取IP地理位置
|
// 获取IP地理位置
|
||||||
if (string.IsNullOrEmpty(remoteIPv4))
|
if (string.IsNullOrEmpty(remoteIPv4)) remoteIPv4 = loggingMonitor.RemoteIPv4;
|
||||||
remoteIPv4 = loggingMonitor.remoteIPv4;
|
|
||||||
(string ipLocation, double? longitude, double? latitude) = CommonHelper.GetIpAddress(remoteIPv4);
|
(string ipLocation, double? longitude, double? latitude) = CommonHelper.GetIpAddress(remoteIPv4);
|
||||||
|
|
||||||
// 获取设备信息
|
// 获取设备信息
|
||||||
var browser = "";
|
|
||||||
var os = "";
|
var os = "";
|
||||||
if (loggingMonitor.userAgent != null)
|
var browser = "";
|
||||||
|
if (loggingMonitor.UserAgent != null)
|
||||||
{
|
{
|
||||||
var client = Parser.GetDefault().Parse(loggingMonitor.userAgent.ToString());
|
var client = Parser.GetDefault().Parse(loggingMonitor.UserAgent);
|
||||||
browser = $"{client.UA.Family} {client.UA.Major}.{client.UA.Minor} / {client.Device.Family}";
|
browser = $"{client.UA.Family} {client.UA.Major}.{client.UA.Minor} / {client.Device.Family}";
|
||||||
os = $"{client.OS.Family} {client.OS.Major} {client.OS.Minor}";
|
os = $"{client.OS.Family} {client.OS.Major} {client.OS.Minor}";
|
||||||
}
|
}
|
||||||
@ -128,120 +120,100 @@ public class DatabaseLoggingWriter : IDatabaseLoggingWriter, IDisposable
|
|||||||
// 捕捉异常,否则会由于 unhandled exception 导致程序崩溃
|
// 捕捉异常,否则会由于 unhandled exception 导致程序崩溃
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// 记录异常日志-发送邮件
|
var logEntity = new SysLogOp
|
||||||
if (logMsg.Exception != null || loggingMonitor.exception != null)
|
|
||||||
{
|
{
|
||||||
await _db.Insertable(new SysLogEx
|
ControllerName = loggingMonitor.DisplayName,
|
||||||
{
|
ActionName = loggingMonitor.ActionTypeName,
|
||||||
ControllerName = loggingMonitor.controllerName,
|
DisplayTitle = loggingMonitor.DisplayTitle,
|
||||||
ActionName = loggingMonitor.actionTypeName,
|
Status = loggingMonitor.ReturnInformation?.HttpStatusCode?.ToString(),
|
||||||
DisplayTitle = loggingMonitor.displayTitle,
|
RemoteIp = remoteIPv4,
|
||||||
Status = loggingMonitor.returnInformation?.httpStatusCode,
|
Location = ipLocation,
|
||||||
RemoteIp = remoteIPv4,
|
Longitude = longitude,
|
||||||
Location = ipLocation,
|
Latitude = latitude,
|
||||||
Longitude = longitude,
|
Browser = browser,
|
||||||
Latitude = latitude,
|
Os = os,
|
||||||
Browser = browser, // loggingMonitor.userAgent,
|
Elapsed = loggingMonitor.TimeOperationElapsedMilliseconds,
|
||||||
Os = os, // loggingMonitor.osDescription + " " + loggingMonitor.osArchitecture,
|
Message = logMsg.Message,
|
||||||
Elapsed = loggingMonitor.timeOperationElapsedMilliseconds,
|
HttpMethod = loggingMonitor.HttpMethod,
|
||||||
LogDateTime = logMsg.LogDateTime,
|
RequestUrl = loggingMonitor.RequestUrl,
|
||||||
Account = account,
|
RequestParam = loggingMonitor.Parameters is { Count: > 0 } ? JSON.Serialize(loggingMonitor.Parameters[0].Value) : null,
|
||||||
RealName = realName,
|
ReturnResult = loggingMonitor.ReturnInformation?.Value != null ? JSON.Serialize(loggingMonitor.ReturnInformation?.Value) : null,
|
||||||
HttpMethod = loggingMonitor.httpMethod,
|
Exception = loggingMonitor.Exception == null ? JSON.Serialize(logMsg.Exception) : JSON.Serialize(loggingMonitor.Exception),
|
||||||
RequestUrl = loggingMonitor.requestUrl,
|
LogDateTime = logMsg.LogDateTime,
|
||||||
RequestParam = (loggingMonitor.parameters == null || loggingMonitor.parameters.Count == 0) ? null : JSON.Serialize(loggingMonitor.parameters[0].value),
|
EventId = logMsg.EventId.Id,
|
||||||
ReturnResult = loggingMonitor.returnInformation == null ? null : JSON.Serialize(loggingMonitor.returnInformation),
|
ThreadId = logMsg.ThreadId,
|
||||||
EventId = logMsg.EventId.Id,
|
TraceId = logMsg.TraceId,
|
||||||
ThreadId = logMsg.ThreadId,
|
Account = userInfo.Account,
|
||||||
TraceId = logMsg.TraceId,
|
RealName = userInfo.RealName,
|
||||||
Exception = JSON.Serialize(loggingMonitor.exception),
|
CreateUserId = userInfo.UserId,
|
||||||
Message = logMsg.Message,
|
CreateUserName = userInfo.RealName,
|
||||||
CreateUserId = string.IsNullOrWhiteSpace(userId) ? 0 : long.Parse(userId),
|
TenantId = userInfo.TenantId,
|
||||||
TenantId = string.IsNullOrWhiteSpace(tenantId) ? 0 : long.Parse(tenantId),
|
LogLevel = logMsg.LogLevel,
|
||||||
LogLevel = logMsg.LogLevel
|
};
|
||||||
}).ExecuteCommandAsync();
|
|
||||||
|
|
||||||
|
// 记录异常日志-发送邮件
|
||||||
|
if (logMsg.Exception != null || loggingMonitor.Exception != null)
|
||||||
|
{
|
||||||
|
await _db.Insertable(logEntity.Adapt<SysLogEx>()).ExecuteCommandAsync();
|
||||||
// 将异常日志发送到邮件
|
// 将异常日志发送到邮件
|
||||||
await _eventPublisher.PublishAsync(CommonConst.SendErrorMail, logMsg.Exception ?? loggingMonitor.exception);
|
await _eventPublisher.PublishAsync(CommonConst.SendErrorMail, logMsg.Exception ?? loggingMonitor.Exception);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 记录访问日志-登录退出
|
// 记录访问日志-登录退出
|
||||||
if (loggingMonitor.actionName == "login" || loggingMonitor.actionName == "loginPhone" || loggingMonitor.actionName == "logout")
|
if (loggingMonitor.ActionName == "login" || loggingMonitor.ActionName == "loginPhone" || loggingMonitor.ActionName == "logout")
|
||||||
{
|
{
|
||||||
if (loggingMonitor.actionName != "logout")
|
await _db.Insertable(logEntity.Adapt<SysLogVis>()).ExecuteCommandAsync();
|
||||||
{
|
|
||||||
dynamic para = Clay.Parse((loggingMonitor.parameters == null) ? null : JSON.Serialize(loggingMonitor.parameters[0].value));
|
|
||||||
if (loggingMonitor.actionName == "login")
|
|
||||||
account = para.account;
|
|
||||||
else if (loggingMonitor.actionName == "loginPhone")
|
|
||||||
account = para.phone;
|
|
||||||
}
|
|
||||||
|
|
||||||
await _db.Insertable(new SysLogVis
|
|
||||||
{
|
|
||||||
ControllerName = loggingMonitor.displayName,
|
|
||||||
ActionName = loggingMonitor.actionTypeName,
|
|
||||||
DisplayTitle = loggingMonitor.displayTitle,
|
|
||||||
Status = loggingMonitor.returnInformation?.httpStatusCode,
|
|
||||||
RemoteIp = remoteIPv4,
|
|
||||||
Location = ipLocation,
|
|
||||||
Longitude = longitude,
|
|
||||||
Latitude = latitude,
|
|
||||||
Browser = browser, // loggingMonitor.userAgent,
|
|
||||||
Os = os, // loggingMonitor.osDescription + " " + loggingMonitor.osArchitecture,
|
|
||||||
Elapsed = loggingMonitor.timeOperationElapsedMilliseconds,
|
|
||||||
LogDateTime = logMsg.LogDateTime,
|
|
||||||
Account = account,
|
|
||||||
RealName = realName,
|
|
||||||
CreateUserId = string.IsNullOrWhiteSpace(userId) ? 0 : long.Parse(userId),
|
|
||||||
TenantId = string.IsNullOrWhiteSpace(tenantId) ? 0 : long.Parse(tenantId),
|
|
||||||
LogLevel = logMsg.LogLevel
|
|
||||||
}).ExecuteCommandAsync();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 记录操作日志
|
// 记录操作日志
|
||||||
if (!await _sysConfigService.GetConfigValueByCode<bool>(ConfigConst.SysOpLog)) return;
|
if (!await _sysConfigService.GetConfigValueByCode<bool>(ConfigConst.SysOpLog)) return;
|
||||||
await _db.Insertable(new SysLogOp
|
await _db.Insertable(logEntity.Adapt<SysLogOp>()).ExecuteCommandAsync();
|
||||||
{
|
|
||||||
ControllerName = loggingMonitor.controllerName,
|
|
||||||
ActionName = loggingMonitor.actionTypeName,
|
|
||||||
DisplayTitle = loggingMonitor.displayTitle,
|
|
||||||
Status = loggingMonitor.returnInformation?.httpStatusCode,
|
|
||||||
RemoteIp = remoteIPv4,
|
|
||||||
Location = ipLocation,
|
|
||||||
Longitude = longitude,
|
|
||||||
Latitude = latitude,
|
|
||||||
Browser = browser, // loggingMonitor.userAgent,
|
|
||||||
Os = os, // loggingMonitor.osDescription + " " + loggingMonitor.osArchitecture,
|
|
||||||
Elapsed = loggingMonitor.timeOperationElapsedMilliseconds,
|
|
||||||
LogDateTime = logMsg.LogDateTime,
|
|
||||||
Account = account,
|
|
||||||
RealName = realName,
|
|
||||||
HttpMethod = loggingMonitor.httpMethod,
|
|
||||||
RequestUrl = loggingMonitor.requestUrl,
|
|
||||||
RequestParam = (loggingMonitor.parameters == null || loggingMonitor.parameters.Count == 0) ? null : JSON.Serialize(loggingMonitor.parameters[0].value),
|
|
||||||
ReturnResult = loggingMonitor.returnInformation == null ? null : JSON.Serialize(loggingMonitor.returnInformation),
|
|
||||||
EventId = logMsg.EventId.Id,
|
|
||||||
ThreadId = logMsg.ThreadId,
|
|
||||||
TraceId = logMsg.TraceId,
|
|
||||||
Exception = loggingMonitor.exception == null ? null : JSON.Serialize(loggingMonitor.exception),
|
|
||||||
Message = logMsg.Message,
|
|
||||||
CreateUserId = string.IsNullOrWhiteSpace(userId) ? 0 : long.Parse(userId),
|
|
||||||
TenantId = string.IsNullOrWhiteSpace(tenantId) ? 0 : long.Parse(tenantId),
|
|
||||||
LogLevel = logMsg.LogLevel
|
|
||||||
}).ExecuteCommandAsync();
|
|
||||||
|
|
||||||
await Task.Delay(50); // 延迟 0.05 秒写入数据库,有效减少高频写入数据库导致死锁问题
|
await Task.Delay(50); // 延迟 0.05 秒写入数据库,有效减少高频写入数据库导致死锁问题
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.LogError(ex, "操作日志入库");
|
_logger.LogError(ex, "操作日志入库");
|
||||||
|
// 将异常日志发送到邮件
|
||||||
|
await _eventPublisher.PublishAsync(CommonConst.SendErrorMail, ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 从日志消息中获取用户信息
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="loggingMonitor"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private LoggingUserInfo GetUserInfo(LoggingMonitorDto loggingMonitor)
|
||||||
|
{
|
||||||
|
LoggingUserInfo result = new();
|
||||||
|
if (loggingMonitor.AuthorizationClaims != null)
|
||||||
|
{
|
||||||
|
var authDict = loggingMonitor.AuthorizationClaims.ToDictionary(u => u.Type, u => u.Value);
|
||||||
|
result.UserId = long.TryParse(authDict?.GetValueOrDefault(ClaimConst.UserId) ?? "", out var userId) ? userId : null;
|
||||||
|
result.Account = authDict?.GetValueOrDefault(ClaimConst.Account);
|
||||||
|
result.RealName = authDict?.GetValueOrDefault(ClaimConst.RealName);
|
||||||
|
result.TenantId = long.TryParse(authDict?.GetValueOrDefault(ClaimConst.TenantId) ?? "", out var tenantId) ? tenantId : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 登陆时没有用户Id,需要根据入参获取
|
||||||
|
if (result.UserId == null && loggingMonitor.ActionName == "login" && loggingMonitor.Parameters is { Count: > 0 })
|
||||||
|
{
|
||||||
|
result.Account = (loggingMonitor.Parameters[0].Value as JObject)!.GetValue("account")?.ToString();
|
||||||
|
if (!string.IsNullOrEmpty(result.Account))
|
||||||
|
{
|
||||||
|
var db = SqlSugarSetup.ITenant.GetConnectionScope(SqlSugarConst.MainConfigId);
|
||||||
|
var user = db.Queryable<SysUser>().First(u => u.Account == result.Account);
|
||||||
|
result.TenantId = user?.TenantId;
|
||||||
|
result.RealName = user?.RealName;
|
||||||
|
result.UserId = user?.Id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 释放服务作用域
|
/// 释放服务作用域
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
||||||
//
|
//
|
||||||
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
|
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
|
||||||
//
|
//
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
<!-- 下拉选择组件,支持远程搜索、分页、自定义查询表单等功能 -->
|
<!-- 下拉选择组件,支持远程搜索、分页、自定义查询表单等功能 -->
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { inject, onMounted, onUnmounted, reactive, ref, watch } from 'vue';
|
import { useSlots, onMounted, onUnmounted, reactive, ref, watch } from 'vue';
|
||||||
import { debounce } from 'xe-utils';
|
import { debounce } from 'xe-utils';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
@ -16,7 +16,6 @@ const props = defineProps({
|
|||||||
* :label-prop="realName"
|
* :label-prop="realName"
|
||||||
* :value-prop="id"
|
* :value-prop="id"
|
||||||
* @@change="handelChange"
|
* @@change="handelChange"
|
||||||
* allow-create
|
|
||||||
* filterable
|
* filterable
|
||||||
* clearable
|
* clearable
|
||||||
* class="w100"
|
* class="w100"
|
||||||
@ -176,6 +175,7 @@ const props = defineProps({
|
|||||||
|
|
||||||
const tableRef = ref();
|
const tableRef = ref();
|
||||||
const selectRef = ref();
|
const selectRef = ref();
|
||||||
|
const slots = useSlots();
|
||||||
const emit = defineEmits(['update:modelValue', 'change']);
|
const emit = defineEmits(['update:modelValue', 'change']);
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
selectedValues: '' as string | string[],
|
selectedValues: '' as string | string[],
|
||||||
@ -260,7 +260,12 @@ const remoteMethod = debounce((query: any) => {
|
|||||||
}
|
}
|
||||||
}, 800);
|
}, 800);
|
||||||
|
|
||||||
const handleQuery = () => {
|
const handleQuery = (clearKeyword: boolean = false) => {
|
||||||
|
if (clearKeyword) {
|
||||||
|
state.tableQuery[props.keywordProp] = undefined;
|
||||||
|
const input = selectRef.value.$el.querySelector('input');
|
||||||
|
if (input) input.value = '';
|
||||||
|
}
|
||||||
remoteMethod(state.tableQuery);
|
remoteMethod(state.tableQuery);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -291,12 +296,12 @@ const handleChange = (row: any) => {
|
|||||||
|
|
||||||
// 选择器下拉框显示隐藏事件
|
// 选择器下拉框显示隐藏事件
|
||||||
const selectVisibleChange = (visible: boolean) => {
|
const selectVisibleChange = (visible: boolean) => {
|
||||||
if (!visible) return;
|
if (visible) {
|
||||||
|
state.tableData.items = [];
|
||||||
state.tableData.items = [];
|
state.tableData.total = 0;
|
||||||
state.tableData.total = 0;
|
state.tableQuery = Object.assign({ page: 1 }, props.queryParams) as any;
|
||||||
state.tableQuery[props.keywordProp] = undefined;
|
handleQuery();
|
||||||
handleQuery();
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 设置默认选项
|
// 设置默认选项
|
||||||
@ -333,6 +338,17 @@ const setValue = (option: any | any[], row: any) => {
|
|||||||
emit('change', state.selectedValues, row);
|
emit('change', state.selectedValues, row);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 选中值改变事件
|
||||||
|
const selectedValuesChange = (val: any) => {
|
||||||
|
// 通知父组件更新值
|
||||||
|
emit('update:modelValue', val);
|
||||||
|
emit(
|
||||||
|
'change',
|
||||||
|
val,
|
||||||
|
state.tableData?.items?.find((item) => item[props.valueProp] === val)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => props.modelValue,
|
() => props.modelValue,
|
||||||
(val: any) => (state.selectedValues = val),
|
(val: any) => (state.selectedValues = val),
|
||||||
@ -354,6 +370,7 @@ defineExpose({
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<el-select
|
<el-select
|
||||||
|
v-bind="$attrs"
|
||||||
v-model="state.selectedValues"
|
v-model="state.selectedValues"
|
||||||
:clearable="clearable"
|
:clearable="clearable"
|
||||||
:multiple="multiple"
|
:multiple="multiple"
|
||||||
@ -361,6 +378,7 @@ defineExpose({
|
|||||||
:placeholder="placeholder"
|
:placeholder="placeholder"
|
||||||
:remote-method="remoteMethod"
|
:remote-method="remoteMethod"
|
||||||
@visible-change="selectVisibleChange"
|
@visible-change="selectVisibleChange"
|
||||||
|
@change="selectedValuesChange"
|
||||||
:style="{ width: dropdownWidth }"
|
:style="{ width: dropdownWidth }"
|
||||||
popper-class="popper-class"
|
popper-class="popper-class"
|
||||||
ref="selectRef"
|
ref="selectRef"
|
||||||
@ -379,7 +397,7 @@ defineExpose({
|
|||||||
<el-form :model="state.tableQuery" v-if="$slots.queryForm" class="mg5 query-form" :label-width="queryLabelWidth ?? ''" @click.stop>
|
<el-form :model="state.tableQuery" v-if="$slots.queryForm" class="mg5 query-form" :label-width="queryLabelWidth ?? ''" @click.stop>
|
||||||
<el-row :gutter="10">
|
<el-row :gutter="10">
|
||||||
<!-- 查询表单插槽内容 -->
|
<!-- 查询表单插槽内容 -->
|
||||||
<slot name="queryForm" :query="state.tableQuery" :handleQuery="handleQuery"></slot>
|
<slot name="queryForm" :query="state.tableQuery" :handleQuery="() => handleQuery(true)"></slot>
|
||||||
<!-- 查询和重置按钮 -->
|
<!-- 查询和重置按钮 -->
|
||||||
<el-button-group style="position: absolute; right: 10px">
|
<el-button-group style="position: absolute; right: 10px">
|
||||||
<el-button type="primary" icon="ele-Search" @click="remoteMethod(state.tableQuery)" v-reclick="1000"> 查询 </el-button>
|
<el-button type="primary" icon="ele-Search" @click="remoteMethod(state.tableQuery)" v-reclick="1000"> 查询 </el-button>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user