系统动态设置.

This commit is contained in:
lijiahang
2024-10-10 18:32:40 +08:00
parent 76aa64fe75
commit c229029c1d
27 changed files with 751 additions and 44 deletions

View File

@@ -61,6 +61,8 @@ public interface FieldConst {
String TIME = "time";
String TEXT = "text";
String ISSUE = "issue";
String EXPIRE = "expire";

View File

@@ -1,28 +1,34 @@
package com.orion.visor.module.infra.controller;
import com.orion.visor.framework.biz.operator.log.core.annotation.OperatorLog;
import com.orion.visor.framework.log.core.annotation.IgnoreLog;
import com.orion.visor.framework.log.core.enums.IgnoreLogMode;
import com.orion.visor.framework.web.core.annotation.DemoDisableApi;
import com.orion.visor.framework.web.core.annotation.RestWrapper;
import com.orion.visor.module.infra.define.operator.SystemSettingOperatorType;
import com.orion.visor.module.infra.entity.request.system.SystemSettingUpdatePartialRequest;
import com.orion.visor.module.infra.entity.request.system.SystemSettingUpdateRequest;
import com.orion.visor.module.infra.entity.vo.AppInfoVO;
import com.orion.visor.module.infra.service.SystemSettingService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.Map;
/**
* 系统服务
* 系统设置服务
*
* @author Jiahang Li
* @version 1.0.0
* @since 2023-7-17 11:39
*/
@Tag(name = "infra - 系统服务")
@Tag(name = "infra - 系统设置服务")
@Slf4j
@Validated
@RestWrapper
@@ -40,5 +46,32 @@ public class SystemSettingController {
return systemSettingService.getAppInfo();
}
}
@IgnoreLog(IgnoreLogMode.RET)
@GetMapping("/setting")
@Operation(summary = "查询系统设置")
@Parameter(name = "type", description = "type", required = true)
@PreAuthorize("@ss.hasPermission('infra:system-setting:query')")
public Map<String, Object> getSystemSettingByType(@RequestParam("type") String type) {
return systemSettingService.getSystemSettingByType(type);
}
@DemoDisableApi
@OperatorLog(SystemSettingOperatorType.UPDATE)
@PutMapping("/update")
@Operation(summary = "更新系统设置")
@PreAuthorize("@ss.hasPermission('infra:system-setting:update')")
public Integer updateSystemSetting(@Validated @RequestBody SystemSettingUpdateRequest request) {
return systemSettingService.updateSystemSetting(request);
}
@DemoDisableApi
@OperatorLog(SystemSettingOperatorType.UPDATE)
@PutMapping("/update-partial")
@Operation(summary = "更新部分系统设置")
@PreAuthorize("@ss.hasPermission('infra:system-setting:update')")
public Boolean updatePartialSystemSetting(@Validated @RequestBody SystemSettingUpdatePartialRequest request) {
systemSettingService.updatePartialSystemSetting(request);
return true;
}
}

View File

@@ -32,7 +32,6 @@ import java.util.List;
@RestWrapper
@RestController
@RequestMapping("/infra/user-permission")
@SuppressWarnings({"ELValidationInJSP", "SpringElInspection"})
public class UserPermissionController {
@Resource

View File

@@ -0,0 +1,24 @@
package com.orion.visor.module.infra.convert;
import com.orion.visor.module.infra.entity.domain.SystemSettingDO;
import com.orion.visor.module.infra.entity.request.system.SystemSettingUpdateRequest;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.factory.Mappers;
/**
* 系统设置 内部对象转换器
*
* @author Jiahang Li
* @version 3.0.0
* @since 2024-9-27 18:52
*/
@Mapper
public interface SystemSettingConvert {
SystemSettingConvert MAPPER = Mappers.getMapper(SystemSettingConvert.class);
@Mapping(target = "value", ignore = true)
SystemSettingDO to(SystemSettingUpdateRequest request);
}

View File

@@ -0,0 +1,17 @@
package com.orion.visor.module.infra.dao;
import com.orion.visor.framework.mybatis.core.mapper.IMapper;
import com.orion.visor.module.infra.entity.domain.SystemSettingDO;
import org.apache.ibatis.annotations.Mapper;
/**
* 系统设置 Mapper 接口
*
* @author Jiahang Li
* @version 3.0.0
* @since 2024-9-27 18:52
*/
@Mapper
public interface SystemSettingDAO extends IMapper<SystemSettingDO> {
}

View File

@@ -0,0 +1,27 @@
package com.orion.visor.module.infra.define.cache;
import com.orion.lang.define.cache.key.CacheKeyBuilder;
import com.orion.lang.define.cache.key.CacheKeyDefine;
import com.orion.lang.define.cache.key.struct.RedisCacheStruct;
import com.orion.lang.define.wrapper.Ref;
import java.util.concurrent.TimeUnit;
/**
* 系统配置缓存 key
*
* @author Jiahang Li
* @version 1.0.0
* @since 2023-9-27 18:37
*/
public interface SystemSettingKeyDefine {
CacheKeyDefine SETTING = new CacheKeyBuilder()
.key("system:setting:{}")
.desc("系统设置 ${type}")
.type(Ref.class)
.struct(RedisCacheStruct.HASH)
.timeout(8, TimeUnit.HOURS)
.build();
}

View File

@@ -0,0 +1,32 @@
package com.orion.visor.module.infra.define.operator;
import com.orion.visor.framework.biz.operator.log.core.annotation.Module;
import com.orion.visor.framework.biz.operator.log.core.factory.InitializingOperatorTypes;
import com.orion.visor.framework.biz.operator.log.core.model.OperatorType;
import static com.orion.visor.framework.biz.operator.log.core.enums.OperatorRiskLevel.M;
/**
* 系统设置 操作日志类型
*
* @author Jiahang Li
* @version 3.0.0
* @since 2024-9-27 18:52
*/
@Module("infra:system-setting")
public class SystemSettingOperatorType extends InitializingOperatorTypes {
public static final String UPDATE_TEXT = "<sb>{}</sb> - <sb>{}</sb> - <sb>{}</sb>";
public static final String UPDATE_PARTIAL_TEXT = "<sb>{}</sb>";
public static final String UPDATE = "system-setting:update";
@Override
public OperatorType[] types() {
return new OperatorType[]{
new OperatorType(M, UPDATE, "更新系统设置 ${text}"),
};
}
}

View File

@@ -0,0 +1,45 @@
package com.orion.visor.module.infra.entity.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.orion.visor.framework.mybatis.core.domain.BaseDO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
/**
* 系统设置 实体对象
*
* @author Jiahang Li
* @version 3.0.0
* @since 2024-9-27 18:52
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = true)
@TableName(value = "system_setting", autoResultMap = true)
@Schema(name = "SystemSettingDO", description = "系统设置 实体对象")
public class SystemSettingDO extends BaseDO {
private static final long serialVersionUID = 1L;
@Schema(description = "id")
@TableId(value = "id", type = IdType.AUTO)
private Long id;
@Schema(description = "配置类型")
@TableField("type")
private String type;
@Schema(description = "配置项")
@TableField("item")
private String item;
@Schema(description = "配置值")
@TableField("value")
private String value;
}

View File

@@ -0,0 +1,40 @@
package com.orion.visor.module.infra.entity.request.system;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.Size;
import java.io.Serializable;
import java.util.Map;
/**
* 系统设置部分 更新请求对象
*
* @author Jiahang Li
* @version 3.0.0
* @since 2024-9-27 18:52
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Schema(name = "SystemSettingUpdatePartialRequest", description = "系统设置部分 更新请求对象")
public class SystemSettingUpdatePartialRequest implements Serializable {
private static final long serialVersionUID = 1L;
@NotBlank
@Size(max = 16)
@Schema(description = "配置类型")
private String type;
@NotEmpty
@Schema(description = "配置")
private Map<String, Object> settings;
}

View File

@@ -0,0 +1,42 @@
package com.orion.visor.module.infra.entity.request.system;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;
import java.io.Serializable;
/**
* 系统设置 更新请求对象
*
* @author Jiahang Li
* @version 3.0.0
* @since 2024-9-27 18:52
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Schema(name = "SystemSettingUpdateRequest", description = "系统设置 更新请求对象")
public class SystemSettingUpdateRequest implements Serializable {
private static final long serialVersionUID = 1L;
@NotBlank
@Size(max = 16)
@Schema(description = "配置类型")
private String type;
@NotBlank
@Size(max = 32)
@Schema(description = "配置项")
private String item;
@Schema(description = "配置值")
private Object value;
}

View File

@@ -0,0 +1,49 @@
package com.orion.visor.module.infra.enums;
import com.orion.visor.framework.common.handler.data.GenericsDataDefinition;
import com.orion.visor.framework.common.handler.data.model.GenericsDataModel;
import com.orion.visor.framework.common.handler.data.strategy.GenericsDataStrategy;
import com.orion.visor.module.infra.handler.setting.strategy.SftpSystemSettingStrategy;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 系统配置类型枚举
*
* @author Jiahang Li
* @version 1.0.0
* @since 2024/9/27 19:07
*/
@Getter
@AllArgsConstructor
public enum SystemSettingTypeEnum implements GenericsDataDefinition {
/**
* SFTP 配置
*/
SFTP(SftpSystemSettingStrategy.class),
;
SystemSettingTypeEnum(Class<? extends GenericsDataStrategy<? extends GenericsDataModel>> strategyClass) {
this.type = this.name();
this.strategyClass = strategyClass;
}
private final String type;
private final Class<? extends GenericsDataStrategy<? extends GenericsDataModel>> strategyClass;
public static SystemSettingTypeEnum of(String type) {
if (type == null) {
return null;
}
for (SystemSettingTypeEnum value : values()) {
if (value.type.equals(type)) {
return value;
}
}
return null;
}
}

View File

@@ -0,0 +1,27 @@
package com.orion.visor.module.infra.handler.setting.model;
import com.orion.visor.framework.common.handler.data.model.GenericsDataModel;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* SFTP 系统配置模型
*
* @author Jiahang Li
* @version 1.0.0
* @since 2024/10/9 11:45
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class SftpSystemSettingModel implements GenericsDataModel {
/**
* 预览大小
*/
private Integer previewSize;
}

View File

@@ -0,0 +1,34 @@
package com.orion.visor.module.infra.handler.setting.strategy;
import com.orion.lang.utils.Exceptions;
import com.orion.visor.framework.common.handler.data.strategy.AbstractGenericsDataStrategy;
import com.orion.visor.module.infra.handler.setting.model.SftpSystemSettingModel;
import org.springframework.stereotype.Component;
/**
* SFTP 系统配置策略
*
* @author Jiahang Li
* @version 1.0.0
* @since 2024/10/9 11:44
*/
@Component
public class SftpSystemSettingStrategy extends AbstractGenericsDataStrategy<SftpSystemSettingModel> {
public SftpSystemSettingStrategy() {
super(SftpSystemSettingModel.class);
}
@Override
public SftpSystemSettingModel getDefault() {
return SftpSystemSettingModel.builder()
.previewSize(2)
.build();
}
@Override
public SftpSystemSettingModel parse(String serialModel) {
throw Exceptions.unsupported();
}
}

View File

@@ -1,13 +1,17 @@
package com.orion.visor.module.infra.service;
import com.orion.visor.module.infra.entity.request.system.SystemSettingUpdatePartialRequest;
import com.orion.visor.module.infra.entity.request.system.SystemSettingUpdateRequest;
import com.orion.visor.module.infra.entity.vo.AppInfoVO;
import java.util.Map;
/**
* 系统服务
* 系统设置服务
*
* @author Jiahang Li
* @version 1.0.0
* @since 2024/6/17 18:10
* @since 2024/6/16 0:18
*/
public interface SystemSettingService {
@@ -18,4 +22,27 @@ public interface SystemSettingService {
*/
AppInfoVO getAppInfo();
/**
* 更新系统设置
*
* @param request request
* @return effect
*/
Integer updateSystemSetting(SystemSettingUpdateRequest request);
/**
* 更新部分系统设置
*
* @param request request
*/
void updatePartialSystemSetting(SystemSettingUpdatePartialRequest request);
/**
* 通过类型查询系统设置
*
* @param type type
* @return row
*/
Map<String, Object> getSystemSettingByType(String type);
}

View File

@@ -240,7 +240,7 @@ public class PreferenceServiceImpl implements PreferenceService {
if (setCache) {
RedisMaps.putAll(key, PreferenceCacheKeyDefine.PREFERENCE, config);
}
// unref
// unRef
return Maps.map(config, Function.identity(), Refs::unref);
}

View File

@@ -1,18 +1,39 @@
package com.orion.visor.module.infra.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.orion.ext.process.ProcessAwaitExecutor;
import com.orion.lang.function.Functions;
import com.orion.lang.support.Attempt;
import com.orion.lang.utils.Arrays1;
import com.orion.lang.utils.Refs;
import com.orion.lang.utils.Strings;
import com.orion.lang.utils.collect.Maps;
import com.orion.lang.utils.crypto.Signatures;
import com.orion.lang.utils.io.Streams;
import com.orion.visor.framework.biz.operator.log.core.utils.OperatorLogs;
import com.orion.visor.framework.common.constant.AppConst;
import com.orion.visor.framework.common.constant.Const;
import com.orion.visor.framework.common.constant.ErrorMessage;
import com.orion.visor.framework.common.utils.Valid;
import com.orion.visor.framework.redis.core.utils.RedisMaps;
import com.orion.visor.framework.redis.core.utils.RedisUtils;
import com.orion.visor.module.infra.dao.SystemSettingDAO;
import com.orion.visor.module.infra.define.cache.SystemSettingKeyDefine;
import com.orion.visor.module.infra.define.operator.SystemSettingOperatorType;
import com.orion.visor.module.infra.entity.domain.SystemSettingDO;
import com.orion.visor.module.infra.entity.request.system.SystemSettingUpdatePartialRequest;
import com.orion.visor.module.infra.entity.request.system.SystemSettingUpdateRequest;
import com.orion.visor.module.infra.entity.vo.AppInfoVO;
import com.orion.visor.module.infra.enums.SystemSettingTypeEnum;
import com.orion.visor.module.infra.service.SystemSettingService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.io.ByteArrayOutputStream;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* 系统服务 实现类
@@ -26,6 +47,9 @@ public class SystemSettingServiceImpl implements SystemSettingService {
private String uuid;
@Resource
private SystemSettingDAO systemSettingDAO;
@Override
public AppInfoVO getAppInfo() {
return AppInfoVO.builder()
@@ -34,6 +58,99 @@ public class SystemSettingServiceImpl implements SystemSettingService {
.build();
}
@Override
public Integer updateSystemSetting(SystemSettingUpdateRequest request) {
String type = request.getType();
String item = request.getItem();
Object value = request.getValue();
// 更新
SystemSettingDO update = new SystemSettingDO();
update.setValue(Refs.json(value));
LambdaQueryWrapper<SystemSettingDO> wrapper = systemSettingDAO.lambda()
.eq(SystemSettingDO::getType, type)
.eq(SystemSettingDO::getItem, item);
int effect = systemSettingDAO.update(update, wrapper);
// 删除缓存
RedisUtils.delete(SystemSettingKeyDefine.SETTING.format(type));
// 设置日志参数
OperatorLogs.add(OperatorLogs.TEXT, Strings.format(SystemSettingOperatorType.UPDATE_TEXT, type, item, value));
return effect;
}
@Override
public void updatePartialSystemSetting(SystemSettingUpdatePartialRequest request) {
String type = request.getType();
Map<String, Object> settings = request.getSettings();
// 删除
LambdaQueryWrapper<SystemSettingDO> deleteWrapper = systemSettingDAO.lambda()
.eq(SystemSettingDO::getType, type)
.in(SystemSettingDO::getItem, settings.keySet());
systemSettingDAO.delete(deleteWrapper);
// 插入
List<SystemSettingDO> rows = settings.entrySet()
.stream()
.map(s -> SystemSettingDO.builder()
.type(type)
.item(s.getKey())
.value(Refs.json(s.getValue()))
.build())
.collect(Collectors.toList());
// 插入
systemSettingDAO.insertBatch(rows);
// 删除缓存
RedisUtils.delete(SystemSettingKeyDefine.SETTING.format(type));
// 设置日志参数
OperatorLogs.add(OperatorLogs.TEXT, Strings.format(SystemSettingOperatorType.UPDATE_PARTIAL_TEXT, type));
}
@Override
public Map<String, Object> getSystemSettingByType(String type) {
SystemSettingTypeEnum settingType = SystemSettingTypeEnum.of(type);
Valid.notNull(settingType, ErrorMessage.ERROR_TYPE);
// 查询缓存
String key = SystemSettingKeyDefine.SETTING.format(type);
Map<String, String> settings = RedisMaps.entities(key);
boolean setCache = Maps.isEmpty(settings);
// 查询数据库
if (Maps.isEmpty(settings)) {
settings = systemSettingDAO.of()
.createWrapper()
.eq(SystemSettingDO::getType, type)
.then()
.stream()
.collect(Collectors.toMap(
SystemSettingDO::getItem,
SystemSettingDO::getValue,
Functions.right()));
}
// 初始化
if (Maps.isEmpty(settings)) {
// 获取默认值
Map<String, Object> defaultConfig = settingType.getStrategy()
.getDefault()
.toMap();
settings = Maps.map(defaultConfig, Function.identity(), Refs::json);
// 插入默认值
List<SystemSettingDO> entities = settings
.entrySet()
.stream()
.map(s -> {
SystemSettingDO entity = new SystemSettingDO();
entity.setType(type);
entity.setItem(s.getKey());
entity.setValue(s.getValue());
return entity;
}).collect(Collectors.toList());
systemSettingDAO.insertBatch(entities);
}
// 设置缓存
if (setCache) {
RedisMaps.putAll(key, SystemSettingKeyDefine.SETTING, settings);
}
// unRef
return Maps.map(settings, Function.identity(), Refs::unref);
}
/**
* 获取系统 uuid
*

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.orion.visor.module.infra.dao.SystemSettingDAO">
<!-- 通用查询映射结果 -->
<resultMap id="BaseResultMap" type="com.orion.visor.module.infra.entity.domain.SystemSettingDO">
<id column="id" property="id"/>
<result column="type" property="type"/>
<result column="item" property="item"/>
<result column="value" property="value"/>
<result column="create_time" property="createTime"/>
<result column="update_time" property="updateTime"/>
<result column="creator" property="creator"/>
<result column="updater" property="updater"/>
<result column="deleted" property="deleted"/>
</resultMap>
<!-- 通用查询结果列 -->
<sql id="Base_Column_List">
id, type, item, value, create_time, update_time, creator, updater, deleted
</sql>
</mapper>

View File

@@ -2,5 +2,4 @@ VITE_API_BASE_URL= 'http://127.0.0.1:9200/orion-visor/api'
VITE_WS_BASE_URL= 'ws://127.0.0.1:9200/orion-visor/keep-alive'
VITE_APP_VERSION= '2.1.7'
VITE_APP_RELEASE= 'community'
VITE_SFTP_PREVIEW_MB= 2
VITE_DEMO_MODE= false

View File

@@ -2,5 +2,4 @@ VITE_API_BASE_URL= '/orion-visor/api'
VITE_WS_BASE_URL= '/orion-visor/keep-alive'
VITE_APP_VERSION= '2.1.7'
VITE_APP_RELEASE= 'community'
VITE_SFTP_PREVIEW_MB= 2
VITE_DEMO_MODE= false

View File

@@ -1,5 +1,20 @@
import axios from 'axios';
/**
* 系统配置类型
*/
export type SystemSettingType = 'SFTP';
/**
* 系统设置更新请求
*/
export interface SystemSettingUpdateRequest {
type?: SystemSettingType;
item?: string;
value?: any;
settings?: Record<string, any>;
}
/**
* 应用信息查询响应
*/
@@ -31,10 +46,10 @@ export interface AppReleaseResponse {
}
/**
* 查询 license 信息
* SFTP 配置
*/
export function getSystemLicenseInfo() {
return axios.get<SystemLicenseResponse>('/infra/system-setting/license');
export interface SftpSetting {
previewSize: number;
}
/**
@@ -57,3 +72,24 @@ export function getAppLatestRelease() {
promptRequestErrorMessage: false,
});
}
/**
* 更新系统设置
*/
export function updateSystemSetting(request: SystemSettingUpdateRequest) {
return axios.put<number>('/infra/system-setting/update', request);
}
/**
* 更新部分系统设置
*/
export function updatePartialSystemSetting(request: SystemSettingUpdateRequest) {
return axios.put<number>('/infra/system-setting/update-partial', request);
}
/**
* 查询系统设置
*/
export function getSystemSetting<T>(type: SystemSettingType) {
return axios.get<T>('/infra/system-setting/setting', { params: { type } });
}

View File

@@ -20,7 +20,6 @@ interface ImportMetaEnv {
readonly VITE_WS_BASE_URL: string;
readonly VITE_APP_VERSION: string;
readonly VITE_APP_RELEASE: string;
readonly VITE_SFTP_PREVIEW_MB: string;
readonly VITE_DEMO_MODE: string;
}

View File

@@ -2,6 +2,8 @@ import type { CacheState, CacheType } from './types';
import type { AxiosResponse } from 'axios';
import type { TagType } from '@/api/meta/tag';
import { getTagList } from '@/api/meta/tag';
import type { SystemSettingType } from '@/api/system/setting';
import { getSystemSetting } from '@/api/system/setting';
import type { HostType } from '@/api/asset/host';
import { getHostList } from '@/api/asset/host';
import type { PreferenceType } from '@/api/user/preference';
@@ -167,5 +169,10 @@ export default defineStore('cache', {
return await this.load(`preference_${type}_${item}`, () => getPreference<T>(type, [item]), undefined, force, {});
},
// 加载系统配置
async loadSystemSetting<T>(type: SystemSettingType, force = false) {
return await this.load(`system_setting_${type}`, () => getSystemSetting<T>(type), undefined, force, {});
},
}
});

View File

@@ -141,18 +141,18 @@
</script>
<script lang="ts" setup>
import type { VNodeRef } from 'vue';
import type { TableData } from '@arco-design/web-vue/es/table/interface';
import type { SftpFile, ISftpSession } from '../../types/define';
import type { VNodeRef } from 'vue';
import { ref, computed, watch, inject } from 'vue';
import type { SftpSetting } from '@/api/system/setting';
import { ref, computed, watch, inject, onMounted } from 'vue';
import { useRowSelection } from '@/hooks/table';
import { dateFormat } from '@/utils';
import { setAutoFocus } from '@/utils/dom';
import { copy } from '@/hooks/copy';
import columns from './types/table.columns';
import { FILE_TYPE, openSftpChmodModalKey, openSftpMoveModalKey } from '../../types/const';
const previewSize = Number.parseInt(import.meta.env.VITE_SFTP_PREVIEW_MB);
import { useCacheStore } from '@/store';
const props = defineProps<{
session?: ISftpSession;
@@ -168,6 +168,8 @@
const rowSelection = useRowSelection({ width: 40 });
const previewSize = ref(0);
// 切换页面自动清空过滤
watch(() => props.list, () => {
tableRef.value?.clearFilters();
@@ -206,7 +208,7 @@
const canEditable = (size: number, attr: string) => {
// 是普通文件 && 文件小于 配置大小(MB) 可以编辑
return FILE_TYPE.NORMAL_FILE.value == formatFileType(attr).value
&& size <= previewSize * 1024 * 1024;
&& size <= (previewSize.value || 0) * 1024 * 1024;
};
// 点击文件名称
@@ -276,6 +278,12 @@
}) || FILE_TYPE.NORMAL_FILE;
};
// 加载配置
onMounted(async () => {
const data = await useCacheStore().loadSystemSetting<SftpSetting>('SFTP');
previewSize.value = data?.previewSize;
});
</script>
<style lang="less" scoped>

View File

@@ -1,8 +1,9 @@
<template>
<div class="main-container">
<h3>关于 Orion Visor</h3>
<a-spin class="main-container" :loading="loading">
<h3 class="setting-header">关于</h3>
<!-- 不一致提示 -->
<a-alert v-if="app.version && webVersion !== app.version"
type="warning"
class="alert-wrapper">
当前前端版本与后端版本不一致, 请使用 Ctrl + F5 强制刷新页面
</a-alert>
@@ -19,7 +20,7 @@
<a-descriptions class="detail-container"
size="large"
:align="{ label: 'right', value: 'left' }"
:label-style="{ width: '134px' }"
:label-style="{ width: '138px' }"
:column="1">
<!-- 机器码 -->
<a-descriptions-item label="机器码">
@@ -37,23 +38,22 @@
</a-descriptions-item>
<!-- 当前后端版本 -->
<a-descriptions-item label="最新发布版本">
{{ repo.tagName }}
{{ repo.tagName || '-' }}
</a-descriptions-item>
<!-- 当前后端版本 -->
<a-descriptions-item label="最新更新日志">
<a-textarea class="release-node"
v-model="repo.body"
<a-textarea v-model="repo.body"
:auto-size="{ minRows: 3, maxRows: 16 }"
readonly>
</a-textarea>
</a-descriptions-item>
</a-descriptions>
</div>
</a-spin>
</template>
<script lang="ts">
export default {
name: 'systemSettingAbout',
name: 'systemSettingAboutSetting',
};
</script>
@@ -62,7 +62,9 @@
import { onMounted, reactive } from 'vue';
import { getAppLatestRelease, getSystemAppInfo } from '@/api/system/setting';
import { copy } from '@/hooks/copy';
import { Message } from '@arco-design/web-vue';
import useLoading from '@/hooks/loading';
const { loading, setLoading } = useLoading();
const webVersion = import.meta.env.VITE_APP_VERSION;
@@ -78,11 +80,14 @@
//
onMounted(async () => {
setLoading(true);
try {
const { data } = await getSystemAppInfo();
app.version = data.version;
app.uuid = data.uuid;
} catch (e) {
} finally {
setLoading(false);
}
});
@@ -93,25 +98,27 @@
repo.tagName = data.tagName;
repo.body = data.body;
} catch (e) {
Message.error('获取应用最新版本失败, 请等待后重试');
}
});
</script>
<style lang="less" scoped>
@release-node-width: 528px;
@label-width: 134px;
@form-width: 628px;
.main-container {
padding-left: 16px;
width: @form-width;
padding-left: 24px;
.setting-header {
color: var(--color-text-1);
}
.alert-href {
text-decoration: none;
}
.alert-wrapper {
width: @release-node-width + @label-width;
margin-bottom: 12px;
}
@@ -119,9 +126,5 @@
color: rgb(var(--arcoblue-6));
font-weight: 600;
}
.release-node {
width: @release-node-width;
}
}
</style>

View File

@@ -0,0 +1,113 @@
<template>
<a-spin class="main-container" :loading="loading">
<h3 class="setting-header">SFTP 设置</h3>
<!-- 系统信息 -->
<a-descriptions class="detail-container"
size="large"
:align="{ label: 'right', value: 'left' }"
:label-style="{ width: '128px' }"
:column="1">
<!-- 文件预览大小 -->
<a-descriptions-item label="文件预览大小">
<a-input-number v-model="setting.previewSize"
class="input-wrapper"
:min="0"
:max="200"
placeholder="请输入文件预览大小"
allow-clear
hide-button>
<template #suffix>
MB
</template>
</a-input-number>
</a-descriptions-item>
</a-descriptions>
<!-- 按钮 -->
<a-space v-permission="['infra:system-setting:update']"
class="button-container">
<!-- 保存 -->
<a-button type="primary"
size="small"
@click="save">
保存
</a-button>
</a-space>
</a-spin>
</template>
<script lang="ts">
export default {
name: 'systemSettingSftpSetting',
};
</script>
<script lang="ts" setup>
import type { SftpSetting } from '@/api/system/setting';
import { onMounted, ref } from 'vue';
import { getSystemSetting, updatePartialSystemSetting } from '@/api/system/setting';
import useLoading from '@/hooks/loading';
import { Message } from '@arco-design/web-vue';
const { loading, setLoading } = useLoading();
const setting = ref<SftpSetting>({} as SftpSetting);
// 保存
const save = async () => {
setLoading(true);
try {
await updatePartialSystemSetting({
type: 'SFTP',
settings: setting.value
});
Message.success('修改成功');
} catch (e) {
} finally {
setLoading(false);
}
};
// 加载配置
onMounted(async () => {
setLoading(true);
try {
const { data } = await getSystemSetting<SftpSetting>('SFTP');
setting.value = data;
} catch (e) {
} finally {
setLoading(false);
}
});
</script>
<style lang="less" scoped>
@form-width: 628px;
@input-width: 328px;
.main-container {
width: @form-width;
padding-left: 24px;
.setting-header {
color: var(--color-text-1);
}
.alert-href {
text-decoration: none;
}
.alert-wrapper {
margin-bottom: 12px;
}
.input-wrapper {
width: @input-width;
}
.button-container {
margin-left: 128px;
margin-bottom: 12px;
}
}
</style>

View File

@@ -5,9 +5,13 @@
size="medium"
position="left"
:lazy-load="true">
<!-- SFTP -->
<a-tab-pane key="sftp" title="SFTP">
<sftp-setting />
</a-tab-pane>
<!-- 关于 -->
<a-tab-pane key="about" title="关于">
<about />
<about-setting />
</a-tab-pane>
</a-tabs>
</div>
@@ -15,18 +19,19 @@
<script lang="ts">
export default {
name: 'systemSetting'
name: 'systemSetting',
};
</script>
<script lang="ts" setup>
import { onBeforeMount, ref } from 'vue';
import { useRoute } from 'vue-router';
import About from './components/about.vue';
import SftpSetting from './components/sftp-setting.vue';
import AboutSetting from './components/about-setting.vue';
const route = useRoute();
const activeKey = ref('about');
const activeKey = ref('sftp');
// 跳转到指定页
onBeforeMount(() => {

View File

@@ -9,7 +9,7 @@ INSERT INTO `system_role` VALUES (1, '管理员', 'admin', 1, '2023-07-16 21:13:
INSERT INTO `system_user_role` VALUES (1, 1, 1, '2023-07-16 21:15:49', '2023-07-17 18:18:02', '1', '1', 0);
-- 系统设置
INSERT INTO `system_setting` VALUES (1, 'SFTP', 'preview', '{\"size\": 2}', '2024-09-27 17:33:05', '2024-09-27 17:33:21', '1', '1', 0);
INSERT INTO `system_setting` VALUES (1, 'SFTP', 'previewSize', '{\"value\": 2}', '2024-09-27 17:33:05', '2024-09-27 17:33:05', '1', '1', 0);
-- 字典项
INSERT INTO `dict_key` VALUES (1, 'operatorLogModule', 'STRING', '[]', '操作日志模块', '2023-10-21 02:04:22', '2023-10-30 14:11:38', '1', '1', 0);