feat: 保存字典值.

This commit is contained in:
lijiahangmax
2023-10-21 02:26:36 +08:00
parent bd02ce1dd0
commit eb2c8eb719
13 changed files with 168 additions and 41 deletions

View File

@@ -9,6 +9,10 @@ package com.orion.ops.framework.common.constant;
*/ */
public interface ValidConst { public interface ValidConst {
String CHAR_NUMBER_1_32_PATTERN = "^[a-zA-Z0-9]{1,32}$";
String CHAR_NUMBER_1_32_MESSAGE = "只能为 1-32 位的数字或字母";
String CHAR_NUMBER_2_32_PATTERN = "^[a-zA-Z0-9]{2,32}$"; String CHAR_NUMBER_2_32_PATTERN = "^[a-zA-Z0-9]{2,32}$";
String CHAR_NUMBER_2_32_MESSAGE = "只能为 2-32 位的数字或字母"; String CHAR_NUMBER_2_32_MESSAGE = "只能为 2-32 位的数字或字母";

View File

@@ -71,15 +71,15 @@ public class DictValueController {
@IgnoreLog(IgnoreLogMode.RET) @IgnoreLog(IgnoreLogMode.RET)
@GetMapping("/list") @GetMapping("/list")
@Operation(summary = "查询字典配置值") @Operation(summary = "查询字典配置值")
public List<DictValueVO> getDictValueList(@RequestParam("key") String key) { public List<DictValueVO> getDictValueList(@RequestParam("keyName") String keyName) {
return dictValueService.getDictValueList(key); return dictValueService.getDictValueList(keyName);
} }
@IgnoreLog(IgnoreLogMode.RET) @IgnoreLog(IgnoreLogMode.RET)
@GetMapping("/enum") @GetMapping("/enum")
@Operation(summary = "查询字典配置值枚举") @Operation(summary = "查询字典配置值枚举")
public Map<String, Map<String, Object>> getDictValueEnum(@RequestParam("key") String key) { public Map<String, Map<String, Object>> getDictValueEnum(@RequestParam("keyName") String keyName) {
return dictValueService.getDictValueEnum(key); return dictValueService.getDictValueEnum(keyName);
} }
@IgnoreLog(IgnoreLogMode.RET) @IgnoreLog(IgnoreLogMode.RET)

View File

@@ -33,7 +33,7 @@ public class DictValueCreateRequest implements Serializable {
@NotBlank @NotBlank
@Size(max = 32) @Size(max = 32)
@Pattern(regexp = ValidConst.CHAR_NUMBER_2_32_PATTERN, message = ValidConst.CHAR_NUMBER_2_32_MESSAGE) @Pattern(regexp = ValidConst.CHAR_NUMBER_1_32_PATTERN, message = ValidConst.CHAR_NUMBER_1_32_MESSAGE)
@Schema(description = "配置名称") @Schema(description = "配置名称")
private String name; private String name;

View File

@@ -37,7 +37,7 @@ public class DictValueUpdateRequest implements Serializable {
@NotBlank @NotBlank
@Size(max = 32) @Size(max = 32)
@Pattern(regexp = ValidConst.CHAR_NUMBER_2_32_PATTERN, message = ValidConst.CHAR_NUMBER_2_32_MESSAGE) @Pattern(regexp = ValidConst.CHAR_NUMBER_1_32_PATTERN, message = ValidConst.CHAR_NUMBER_1_32_MESSAGE)
@Schema(description = "配置名称") @Schema(description = "配置名称")
private String name; private String name;

View File

@@ -46,18 +46,18 @@ public interface DictValueService {
/** /**
* 查询全部字典配置值 * 查询全部字典配置值
* *
* @param key key * @param keyName keyName
* @return rows * @return rows
*/ */
List<DictValueVO> getDictValueList(String key); List<DictValueVO> getDictValueList(String keyName);
/** /**
* 查询全部字典配置值枚举 * 查询全部字典配置值枚举
* *
* @param key key * @param keyName keyName
* @return enum * @return enum
*/ */
Map<String, Map<String, Object>> getDictValueEnum(String key); Map<String, Map<String, Object>> getDictValueEnum(String keyName);
/** /**
* 分页查询字典配置值 * 分页查询字典配置值

View File

@@ -140,15 +140,15 @@ public class DictValueServiceImpl implements DictValueService {
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public List<DictValueVO> getDictValueList(String key) { public List<DictValueVO> getDictValueList(String keyName) {
// 查询缓存 // 查询缓存
String cacheKey = DictCacheKeyDefine.DICT_VALUE.format(key); String cacheKey = DictCacheKeyDefine.DICT_VALUE.format(keyName);
List<DictValueCacheDTO> list = RedisMaps.valuesJson(cacheKey, (Class<DictValueCacheDTO>) DictCacheKeyDefine.DICT_VALUE.getType()); List<DictValueCacheDTO> list = RedisMaps.valuesJson(cacheKey, (Class<DictValueCacheDTO>) DictCacheKeyDefine.DICT_VALUE.getType());
if (list.isEmpty()) { if (list.isEmpty()) {
// 查询数据库 // 查询数据库
list = dictValueDAO.of() list = dictValueDAO.of()
.createWrapper() .createWrapper()
.eq(DictValueDO::getKeyName, key) .eq(DictValueDO::getKeyName, keyName)
.then() .then()
.list(DictValueConvert.MAPPER::toCache); .list(DictValueConvert.MAPPER::toCache);
// 添加默认值 防止穿透 // 添加默认值 防止穿透
@@ -170,14 +170,14 @@ public class DictValueServiceImpl implements DictValueService {
} }
@Override @Override
public Map<String, Map<String, Object>> getDictValueEnum(String key) { public Map<String, Map<String, Object>> getDictValueEnum(String keyName) {
// 查询配置值 // 查询配置值
List<DictValueVO> values = this.getDictValueList(key); List<DictValueVO> values = this.getDictValueList(keyName);
if (values.isEmpty()) { if (values.isEmpty()) {
return Maps.empty(); return Maps.empty();
} }
// 查询配置项 // 查询配置项
Map<String, String> schema = dictKeyService.getDictSchema(key); Map<String, String> schema = dictKeyService.getDictSchema(keyName);
// 返回 // 返回
Map<String, Map<String, Object>> result = Maps.newLinkedMap(); Map<String, Map<String, Object>> result = Maps.newLinkedMap();
for (DictValueVO value : values) { for (DictValueVO value : values) {

View File

@@ -5,6 +5,7 @@
:loading="loading" :loading="loading"
:disabled="loading" :disabled="loading"
:filter-option="filterOption" :filter-option="filterOption"
:allow-create="allowCreate"
placeholder="请选择配置项" /> placeholder="请选择配置项" />
</template> </template>
@@ -23,6 +24,10 @@
const props = defineProps({ const props = defineProps({
modelValue: Number, modelValue: Number,
loading: Boolean, loading: Boolean,
allowCreate: {
type: Boolean,
default: false
}
}); });
const emits = defineEmits(['update:modelValue', 'change']); const emits = defineEmits(['update:modelValue', 'change']);
@@ -32,8 +37,21 @@
return props.modelValue; return props.modelValue;
}, },
set(e) { set(e) {
emits('update:modelValue', e); if (typeof e === 'string') {
emits('change', e); // 创建的值
emits('update:modelValue', undefined);
emits('change', {
id: undefined,
keyName: e
});
} else {
// 已有的值
emits('update:modelValue', e);
const find = cacheStore.dictKeys.find(s => s.id === e);
if (find) {
emits('change', find);
}
}
} }
}); });
@@ -44,7 +62,6 @@
return { return {
label: `${s.keyName} - ${s.description || ''}`, label: `${s.keyName} - ${s.description || ''}`,
value: s.id, value: s.id,
origin: s,
}; };
}); });
}; };

View File

@@ -16,14 +16,13 @@
</script> </script>
<script lang="ts" setup> <script lang="ts" setup>
import { computed } from 'vue'; import { computed, PropType } from 'vue';
import { useCacheStore } from '@/store'; import { useCacheStore } from '@/store';
import { SelectOptionData } from '@arco-design/web-vue'; import { SelectOptionData } from '@arco-design/web-vue';
import { RoleStatusEnum } from '@/views/user/role/types/enum.types'; import { RoleStatusEnum } from '@/views/user/role/types/enum.types';
const props = defineProps({ const props = defineProps({
// FIXME 拆出来单选多选 modelValue: Object as PropType<Array<number>> | PropType<number>,
modelValue: Array,
loading: Boolean, loading: Boolean,
multiple: Boolean, multiple: Boolean,
}); });

View File

@@ -101,7 +101,6 @@
import { definedExtraKeys, innerKeys, ExtraParamType } from '../types/const'; import { definedExtraKeys, innerKeys, ExtraParamType } from '../types/const';
import { ValueTypeEnum } from '../types/enum.types'; import { ValueTypeEnum } from '../types/enum.types';
import { toOptions } from '@/utils/enum'; import { toOptions } from '@/utils/enum';
import { FieldData } from '@arco-design/web-vue/es/form/interface';
const { visible, setVisible } = useVisible(); const { visible, setVisible } = useVisible();
const { loading, setLoading } = useLoading(); const { loading, setLoading } = useLoading();
@@ -113,7 +112,7 @@
return { return {
id: undefined, id: undefined,
keyName: undefined, keyName: undefined,
valueType: undefined, valueType: ValueTypeEnum.STRING.value,
extraSchema: undefined, extraSchema: undefined,
description: undefined, description: undefined,
}; };

View File

@@ -77,6 +77,12 @@
<!-- 操作 --> <!-- 操作 -->
<template #handle="{ record }"> <template #handle="{ record }">
<div class="table-handle-wrapper"> <div class="table-handle-wrapper">
<!-- 查看 -->
<a-button type="text"
size="mini"
@click="viewDictKey(record.keyName)">
查看
</a-button>
<!-- 修改 --> <!-- 修改 -->
<a-button type="text" <a-button type="text"
size="mini" size="mini"
@@ -117,13 +123,15 @@
import { usePagination } from '@/types/table'; import { usePagination } from '@/types/table';
import {} from '../types/const'; import {} from '../types/const';
import { ValueTypeEnum } from '../types/enum.types'; import { ValueTypeEnum } from '../types/enum.types';
import { toOptions, getEnumValue } from '@/utils/enum'; import { getEnumValue } from '@/utils/enum';
import { MenuStatusEnum } from '@/views/system/menu/types/enum.types'; import { getDictValueEnum } from '@/api/system/dict-value';
import useCopy from '@/hooks/copy';
const tableRenderData = ref<DictKeyQueryResponse[]>([]); const tableRenderData = ref<DictKeyQueryResponse[]>([]);
const { loading, setLoading } = useLoading(); const { loading, setLoading } = useLoading();
const emits = defineEmits(['openAdd', 'openUpdate']); const emits = defineEmits(['openAdd', 'openUpdate']);
const { copy } = useCopy();
const pagination = usePagination(); const pagination = usePagination();
const formModel = reactive<DictKeyQueryRequest>({ const formModel = reactive<DictKeyQueryRequest>({
@@ -163,6 +171,13 @@
addedCallback, updatedCallback addedCallback, updatedCallback
}); });
// 查看
const viewDictKey = async (keyName: string) => {
const { data } = await getDictValueEnum(keyName);
// fixme 后续改为 jsonView
await copy(JSON.stringify(data), '复制成功');
};
// 加载数据 // 加载数据
const doFetchTableData = async (request: DictKeyQueryRequest) => { const doFetchTableData = async (request: DictKeyQueryRequest) => {
try { try {

View File

@@ -36,7 +36,7 @@ const columns = [
}, { }, {
title: '操作', title: '操作',
slotName: 'handle', slotName: 'handle',
width: 130, width: 170,
align: 'center', align: 'center',
fixed: 'right', fixed: 'right',
}, },

View File

@@ -22,7 +22,7 @@
:rules="formRules"> :rules="formRules">
<!-- 配置项 --> <!-- 配置项 -->
<a-form-item field="keyId" label="配置项"> <a-form-item field="keyId" label="配置项">
<dict-key-selector v-model="formModel.keyId" /> <dict-key-selector v-model="formModel.keyId" @change="changeKey" />
</a-form-item> </a-form-item>
<!-- 配置名称 --> <!-- 配置名称 -->
<a-form-item field="name" label="配置名称"> <a-form-item field="name" label="配置名称">
@@ -42,6 +42,40 @@
placeholder="请输入排序" placeholder="请输入排序"
hide-button /> hide-button />
</a-form-item> </a-form-item>
<!-- 额外配置 -->
<a-form-item v-for="{ name, type } in keyExtraSchemas"
:key="name"
:field="name as string"
:label="name">
<!-- 字符串 -->
<a-input v-if="ValueTypeEnum.STRING.value === type"
v-model="extraValue[name]"
:placeholder="`请输入 ${name}`"
allow-clear />
<!-- 数字 -->
<a-input-number v-else-if="ValueTypeEnum.INTEGER.value === type || ValueTypeEnum.DECIMAL.value === type"
v-model="extraValue[name]"
:placeholder="`请输入 ${name}`"
allow-clear
hide-button />
<!-- 布尔值 -->
<a-switch v-else-if="ValueTypeEnum.BOOLEAN.value === type"
type="round"
v-model="extraValue[name]"
checked-text="TRUE"
unchecked-text="FALSE" />
<!-- 颜色 -->
<template v-else-if="ValueTypeEnum.COLOR.value === type">
<a-input v-model="extraValue[name]"
:placeholder="`请输入 ${name}`"
default-value="#"
allow-clear
hide-button />
<span class="color-block" :style="{
background: extraValue[name] === '#' ? undefined : (extraValue[name] || undefined)
}" />
</template>
</a-form-item>
</a-form> </a-form>
</a-spin> </a-spin>
</a-modal> </a-modal>
@@ -60,13 +94,16 @@
import formRules from '../types/form.rules'; import formRules from '../types/form.rules';
import { createDictValue, updateDictValue, DictValueUpdateRequest } from '@/api/system/dict-value'; import { createDictValue, updateDictValue, DictValueUpdateRequest } from '@/api/system/dict-value';
import { Message } from '@arco-design/web-vue'; import { Message } from '@arco-design/web-vue';
import {} from '../types/const'; import { ExtraParamType, innerKeys } from '../../dict-key/types/const';
import {} from '../types/enum.types'; import { ValueTypeEnum } from '../../dict-key/types/enum.types';
import { toOptions } from '@/utils/enum'; import {} from '@/utils/enum';
import DictKeySelector from '@/components/system/dict-key/dict-key-selector.vue'; import DictKeySelector from '@/components/system/dict-key/dict-key-selector.vue';
import { DictKeyQueryResponse } from '@/api/system/dict-key';
import { useCacheStore } from '@/store';
const { visible, setVisible } = useVisible(); const { visible, setVisible } = useVisible();
const { loading, setLoading } = useLoading(); const { loading, setLoading } = useLoading();
const cacheStore = useCacheStore();
const title = ref<string>(); const title = ref<string>();
const isAddHandle = ref<boolean>(true); const isAddHandle = ref<boolean>(true);
@@ -83,6 +120,8 @@
}; };
}; };
const keyExtraSchemas = ref<Array<ExtraParamType>>([]);
const extraValue = ref<Record<string, any>>({});
const formRef = ref<any>(); const formRef = ref<any>();
const formModel = ref<DictValueUpdateRequest>({}); const formModel = ref<DictValueUpdateRequest>({});
@@ -107,10 +146,20 @@
// 渲染表单 // 渲染表单
const renderForm = (record: any) => { const renderForm = (record: any) => {
formModel.value = Object.assign({}, record); formModel.value = Object.assign({}, record);
// schema
const find = record.keyId && cacheStore.dictKeys.find((item) => item.id === record.keyId);
keyExtraSchemas.value = (find && find.extraSchema && JSON.parse(find.extraSchema)) || [];
// 额外参数
extraValue.value = (formModel.value.extra && JSON.parse(formModel.value.extra)) || {};
}; };
defineExpose({ openAdd, openUpdate }); defineExpose({ openAdd, openUpdate });
// 切换 key
const changeKey = ({ extraSchema }: DictKeyQueryResponse) => {
keyExtraSchemas.value = (extraSchema && JSON.parse(extraSchema)) || [];
};
// 确定 // 确定
const handlerOk = async () => { const handlerOk = async () => {
setLoading(true); setLoading(true);
@@ -120,14 +169,34 @@
if (error) { if (error) {
return false; return false;
} }
// 验证额外参数
if (keyExtraSchemas.value.length) {
for (let { name, type } of keyExtraSchemas.value) {
const nameKey = name as string;
const value = extraValue.value[nameKey];
if (value === undefined) {
if (type === ValueTypeEnum.BOOLEAN.value) {
extraValue.value[nameKey] = false;
continue;
}
formRef.value.setFields({
[nameKey]: {
status: 'error',
message: `${name} 不能为空`
}
});
return false;
}
}
}
if (isAddHandle.value) { if (isAddHandle.value) {
// 新增 // 新增
await createDictValue(formModel.value); await createDictValue({ ...formModel.value, extra: JSON.stringify(extraValue.value) });
Message.success('创建成功'); Message.success('创建成功');
emits('added'); emits('added');
} else { } else {
// 修改 // 修改
await updateDictValue(formModel.value); await updateDictValue({ ...formModel.value, extra: JSON.stringify(extraValue.value) });
Message.success('修改成功'); Message.success('修改成功');
emits('updated'); emits('updated');
} }
@@ -154,5 +223,11 @@
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
.color-block {
width: 36px;
height: 30px;
margin-left: 8px;
border-radius: 4px;
background: var(--color-fill-2);
}
</style> </style>

View File

@@ -4,11 +4,13 @@
<a-query-header :model="formModel" <a-query-header :model="formModel"
label-align="left" label-align="left"
@submit="fetchTableData" @submit="fetchTableData"
@reset="fetchTableData" @reset="resetForm"
@keyup.enter="() => fetchTableData()"> @keyup.enter="() => fetchTableData()">
<!-- 配置项 --> <!-- 配置项 -->
<a-form-item field="keyName" label="配置项" label-col-flex="50px"> <a-form-item field="keyId" label="配置项" label-col-flex="50px">
<a-input v-model="formModel.keyName" placeholder="请输入配置项" allow-clear /> <dict-key-selector v-model="formModel.keyId"
@change="changeKey"
allow-create />
</a-form-item> </a-form-item>
<!-- 配置名称 --> <!-- 配置名称 -->
<a-form-item field="name" label="配置名称" label-col-flex="50px"> <a-form-item field="name" label="配置名称" label-col-flex="50px">
@@ -100,12 +102,12 @@
@click="emits('openUpdate', record)"> @click="emits('openUpdate', record)">
修改 修改
</a-button> </a-button>
<!-- 回滚 --> <!-- 历史 -->
<a-button type="text" <a-button type="text"
size="mini" size="mini"
v-permission="['infra:dict-value:update']" v-permission="['infra:dict-value:update']"
@click="emits('openUpdate', record)"> @click="emits('openHistory', record)">
回滚 历史
</a-button> </a-button>
<!-- 删除 --> <!-- 删除 -->
<a-popconfirm content="确认删除这条记录吗?" <a-popconfirm content="确认删除这条记录吗?"
@@ -142,11 +144,12 @@
import {} from '../types/enum.types'; import {} from '../types/enum.types';
import { toOptions, getEnumValue } from '@/utils/enum'; import { toOptions, getEnumValue } from '@/utils/enum';
import useCopy from '@/hooks/copy'; import useCopy from '@/hooks/copy';
import DictKeySelector from '@/components/system/dict-key/dict-key-selector.vue';
const { copy } = useCopy(); const { copy } = useCopy();
const tableRenderData = ref<DictValueQueryResponse[]>([]); const tableRenderData = ref<DictValueQueryResponse[]>([]);
const { loading, setLoading } = useLoading(); const { loading, setLoading } = useLoading();
const emits = defineEmits(['openAdd', 'openUpdate']); const emits = defineEmits(['openAdd', 'openUpdate', 'openHistory']);
const pagination = usePagination(); const pagination = usePagination();
const selectedKeys = ref<number[]>([]); const selectedKeys = ref<number[]>([]);
@@ -210,6 +213,21 @@
addedCallback, updatedCallback addedCallback, updatedCallback
}); });
// 修改 key
const changeKey = ({ id, keyName }: { id: number, keyName: string }) => {
if (id) {
formModel.keyId = id;
} else {
formModel.keyName = keyName;
}
};
// 清空表单
const resetForm = () => {
formModel.keyName = undefined;
fetchTableData();
};
// 加载数据 // 加载数据
const doFetchTableData = async (request: DictValueQueryRequest) => { const doFetchTableData = async (request: DictValueQueryRequest) => {
try { try {