mirror of
https://gitee.com/JavaLionLi/plus-ui.git
synced 2026-09-16 00:38:19 +08:00
Pre Merge pull request !282 from Blizzard/6.X-Vue
This commit is contained in:
commit
43c75fade1
@ -12,6 +12,7 @@ export interface DictDataVO extends BaseEntity {
|
|||||||
listClass: ElTagType;
|
listClass: ElTagType;
|
||||||
dictSort: number;
|
dictSort: number;
|
||||||
remark: string;
|
remark: string;
|
||||||
|
enumName: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DictDataForm {
|
export interface DictDataForm {
|
||||||
@ -23,4 +24,5 @@ export interface DictDataForm {
|
|||||||
listClass: ElTagType;
|
listClass: ElTagType;
|
||||||
dictSort: number;
|
dictSort: number;
|
||||||
remark: string;
|
remark: string;
|
||||||
|
enumName: string;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,9 @@
|
|||||||
import type { PageResult } from '@/api/types';
|
import type { PageResult } from '@/api/types';
|
||||||
import type { AxiosPromise } from '@/utils/api-types';
|
import errorCode from '@/utils/errorCode';
|
||||||
import request from '@/utils/request';
|
import request from '@/utils/request';
|
||||||
|
import type { AxiosPromise } from '@/utils/api-types';
|
||||||
|
import { blobValidate } from '@/utils/ruoyi';
|
||||||
|
import { saveBlob } from '@/utils/save';
|
||||||
import type { DictTypeForm, DictTypeQuery, DictTypeVO } from './types';
|
import type { DictTypeForm, DictTypeQuery, DictTypeVO } from './types';
|
||||||
|
|
||||||
// 查询字典类型列表
|
// 查询字典类型列表
|
||||||
@ -61,3 +64,29 @@ export function optionselect(): AxiosPromise<DictTypeVO[]> {
|
|||||||
method: 'get'
|
method: 'get'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 生成字典枚举类压缩包
|
||||||
|
export function genEnum(dictTypes: string[]) {
|
||||||
|
const loading = ElLoading.service({
|
||||||
|
text: '正在下载数据,请稍候',
|
||||||
|
background: 'rgba(0, 0, 0, 0.7)'
|
||||||
|
});
|
||||||
|
return request({
|
||||||
|
url: '/system/dict/type/genEnum',
|
||||||
|
method: 'post',
|
||||||
|
data: dictTypes,
|
||||||
|
responseType: 'blob'
|
||||||
|
})
|
||||||
|
.then(async (data: any) => {
|
||||||
|
if (blobValidate(data)) {
|
||||||
|
const blob = new Blob([data], { type: 'application/zip' });
|
||||||
|
saveBlob(blob, 'dict_enum.zip');
|
||||||
|
} else {
|
||||||
|
const resText = await new Blob([data]).text();
|
||||||
|
const rspObj = JSON.parse(resText);
|
||||||
|
const errMsg = errorCode[rspObj.code] || rspObj.msg || errorCode['default'];
|
||||||
|
ElMessage.error(errMsg);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.finally(() => loading.close());
|
||||||
|
}
|
||||||
|
|||||||
147
src/components/RemoteSelect/index.vue
Normal file
147
src/components/RemoteSelect/index.vue
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
<template>
|
||||||
|
<el-select
|
||||||
|
v-model="selectedValue"
|
||||||
|
:placeholder="placeholder"
|
||||||
|
:clearable="clearable"
|
||||||
|
filterable
|
||||||
|
:remote="isRemote"
|
||||||
|
:remote-method="remoteMethod"
|
||||||
|
:loading="loading"
|
||||||
|
style="width: 100%"
|
||||||
|
@change="handleChange"
|
||||||
|
>
|
||||||
|
<el-option v-for="item in options" :key="item[valueKey]" :label="item[labelKey]" :value="item[valueKey]" />
|
||||||
|
</el-select>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import request from '@/utils/request';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
/** 列表数据请求地址 */
|
||||||
|
url: string;
|
||||||
|
/** 选项显示文字的字段名 */
|
||||||
|
labelKey?: string;
|
||||||
|
/** 选项值的字段名 */
|
||||||
|
valueKey?: string;
|
||||||
|
/** 远程搜索时的查询参数字段名 */
|
||||||
|
searchKey?: string;
|
||||||
|
/** 额外的固定请求参数 */
|
||||||
|
params?: Record<string, any>;
|
||||||
|
/** 绑定值 */
|
||||||
|
modelValue?: string | number;
|
||||||
|
/** 占位提示文字 */
|
||||||
|
placeholder?: string;
|
||||||
|
/** 是否可清空 */
|
||||||
|
clearable?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
|
labelKey: 'label',
|
||||||
|
valueKey: 'value',
|
||||||
|
searchKey: 'keyword',
|
||||||
|
params: () => ({}),
|
||||||
|
placeholder: '请选择',
|
||||||
|
clearable: true
|
||||||
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits(['update:modelValue', 'change']);
|
||||||
|
|
||||||
|
const selectedValue = ref<string | number | undefined>(props.modelValue);
|
||||||
|
const options = ref<Record<string, any>[]>([]);
|
||||||
|
const originalOptions = ref<Record<string, any>[]>([]);
|
||||||
|
const loading = ref(false);
|
||||||
|
const isRemote = ref(false);
|
||||||
|
|
||||||
|
let searchTimer: ReturnType<typeof setTimeout> | null = null;
|
||||||
|
|
||||||
|
/** 获取列表数据 */
|
||||||
|
const fetchData = async (keyword?: string) => {
|
||||||
|
if (!props.url) return;
|
||||||
|
|
||||||
|
loading.value = true;
|
||||||
|
try {
|
||||||
|
const queryParams: Record<string, any> = {
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 500,
|
||||||
|
...props.params
|
||||||
|
};
|
||||||
|
if (keyword) {
|
||||||
|
queryParams[props.searchKey] = keyword;
|
||||||
|
}
|
||||||
|
|
||||||
|
const res: any = await request({
|
||||||
|
url: props.url,
|
||||||
|
method: 'get',
|
||||||
|
params: queryParams
|
||||||
|
});
|
||||||
|
|
||||||
|
const rows = res.data.rows || res.data || [];
|
||||||
|
options.value = rows;
|
||||||
|
|
||||||
|
// 首次加载(无关键词)时判断是否启用远程搜索
|
||||||
|
if (keyword === undefined) {
|
||||||
|
isRemote.value = res.total > 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 缓存无关键词时的数据,用于远程搜索清空时恢复
|
||||||
|
if (!keyword) {
|
||||||
|
originalOptions.value = rows;
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 远程搜索方法 */
|
||||||
|
const remoteMethod = (query: string) => {
|
||||||
|
if (!isRemote.value) return;
|
||||||
|
|
||||||
|
// 空查询时恢复原始数据,不发起新请求
|
||||||
|
if (!query) {
|
||||||
|
options.value = originalOptions.value;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (searchTimer) {
|
||||||
|
clearTimeout(searchTimer);
|
||||||
|
}
|
||||||
|
|
||||||
|
searchTimer = setTimeout(() => {
|
||||||
|
fetchData(query);
|
||||||
|
}, 300);
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 值变化事件 */
|
||||||
|
const handleChange = (val: any) => {
|
||||||
|
emit('update:modelValue', val);
|
||||||
|
const selected = options.value.find((item) => item[props.valueKey] === val);
|
||||||
|
emit('change', val, selected);
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 监听外部 modelValue 变化 */
|
||||||
|
watch(
|
||||||
|
() => props.modelValue,
|
||||||
|
(newVal) => {
|
||||||
|
selectedValue.value = newVal;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
/** 监听 url 或 params 变化,重新加载数据 */
|
||||||
|
watch(
|
||||||
|
() => `${props.url}|${JSON.stringify(props.params)}`,
|
||||||
|
() => {
|
||||||
|
fetchData();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
fetchData();
|
||||||
|
});
|
||||||
|
|
||||||
|
// 暴露方法
|
||||||
|
defineExpose({
|
||||||
|
options,
|
||||||
|
loading
|
||||||
|
});
|
||||||
|
</script>
|
||||||
@ -81,6 +81,17 @@
|
|||||||
>
|
>
|
||||||
导出
|
导出
|
||||||
</el-button>
|
</el-button>
|
||||||
|
<el-button
|
||||||
|
v-if="isDev"
|
||||||
|
v-hasPermi="['system:dict:list']"
|
||||||
|
type="primary"
|
||||||
|
plain
|
||||||
|
icon="Download"
|
||||||
|
:disabled="typeMultiple"
|
||||||
|
@click="handleGenEnum"
|
||||||
|
>
|
||||||
|
生成枚举
|
||||||
|
</el-button>
|
||||||
<el-button
|
<el-button
|
||||||
v-hasPermi="['system:dict:remove']"
|
v-hasPermi="['system:dict:remove']"
|
||||||
type="danger"
|
type="danger"
|
||||||
@ -280,6 +291,7 @@
|
|||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="字典键值" align="center" prop="dictValue" width="100" />
|
<el-table-column label="字典键值" align="center" prop="dictValue" width="100" />
|
||||||
|
<el-table-column label="枚举名称" align="center" prop="enumName" width="100" />
|
||||||
<el-table-column label="字典排序" align="center" prop="dictSort" width="80" />
|
<el-table-column label="字典排序" align="center" prop="dictSort" width="80" />
|
||||||
<el-table-column label="备注" align="center" prop="remark" width="100" />
|
<el-table-column label="备注" align="center" prop="remark" width="100" />
|
||||||
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
|
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
|
||||||
@ -386,6 +398,9 @@
|
|||||||
></el-option>
|
></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item label="枚举名称" prop="enumName">
|
||||||
|
<el-input v-model="dataForm.enumName" placeholder="请输入枚举名称(如: yes)" />
|
||||||
|
</el-form-item>
|
||||||
<el-form-item label="备注" prop="remark">
|
<el-form-item label="备注" prop="remark">
|
||||||
<el-input v-model="dataForm.remark" type="textarea" placeholder="请输入内容"></el-input>
|
<el-input v-model="dataForm.remark" type="textarea" placeholder="请输入内容"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@ -403,17 +418,21 @@
|
|||||||
<script setup name="Dict" lang="ts">
|
<script setup name="Dict" lang="ts">
|
||||||
import { listData, getData, delData, addData, updateData } from '@/api/system/dict/data';
|
import { listData, getData, delData, addData, updateData } from '@/api/system/dict/data';
|
||||||
import { DictDataForm, DictDataQuery, DictDataVO } from '@/api/system/dict/data/types';
|
import { DictDataForm, DictDataQuery, DictDataVO } from '@/api/system/dict/data/types';
|
||||||
import { listType, getType, delType, addType, updateType, refreshCache } from '@/api/system/dict/type';
|
import { listType, getType, delType, addType, updateType, refreshCache, genEnum } from '@/api/system/dict/type';
|
||||||
import { DictTypeForm, DictTypeQuery, DictTypeVO } from '@/api/system/dict/type/types';
|
import { DictTypeForm, DictTypeQuery, DictTypeVO } from '@/api/system/dict/type/types';
|
||||||
import modal from '@/plugins/modal';
|
import modal from '@/plugins/modal';
|
||||||
import { useDictStore } from '@/store/modules/dict';
|
import { useDictStore } from '@/store/modules/dict';
|
||||||
import { download as requestDownload } from '@/utils/request';
|
import { download as requestDownload } from '@/utils/request';
|
||||||
import { parseTime } from '@/utils/ruoyi';
|
import { parseTime } from '@/utils/ruoyi';
|
||||||
|
|
||||||
|
/** 是否开发环境(仅开发环境显示生成枚举按钮) */
|
||||||
|
const isDev = import.meta.env.DEV;
|
||||||
|
|
||||||
const typeList = ref<DictTypeVO[]>([]);
|
const typeList = ref<DictTypeVO[]>([]);
|
||||||
const typeLoading = ref(true);
|
const typeLoading = ref(true);
|
||||||
const showTypeSearch = ref(true);
|
const showTypeSearch = ref(true);
|
||||||
const typeIds = ref<Array<number | string>>([]);
|
const typeIds = ref<Array<number | string>>([]);
|
||||||
|
const typeSelections = ref<DictTypeVO[]>([]);
|
||||||
const typeSingle = ref(true);
|
const typeSingle = ref(true);
|
||||||
const typeMultiple = ref(true);
|
const typeMultiple = ref(true);
|
||||||
const typeTotal = ref(0);
|
const typeTotal = ref(0);
|
||||||
@ -489,7 +508,8 @@ const dataInitFormData: DictDataForm = {
|
|||||||
cssClass: '',
|
cssClass: '',
|
||||||
listClass: 'primary',
|
listClass: 'primary',
|
||||||
dictSort: 0,
|
dictSort: 0,
|
||||||
remark: ''
|
remark: '',
|
||||||
|
enumName: ''
|
||||||
};
|
};
|
||||||
|
|
||||||
const dataState = reactive<PageData<DictDataForm, DictDataQuery>>({
|
const dataState = reactive<PageData<DictDataForm, DictDataQuery>>({
|
||||||
@ -504,7 +524,8 @@ const dataState = reactive<PageData<DictDataForm, DictDataQuery>>({
|
|||||||
rules: {
|
rules: {
|
||||||
dictLabel: [{ required: true, message: '数据标签不能为空', trigger: 'blur' }],
|
dictLabel: [{ required: true, message: '数据标签不能为空', trigger: 'blur' }],
|
||||||
dictValue: [{ required: true, message: '数据键值不能为空', trigger: 'blur' }],
|
dictValue: [{ required: true, message: '数据键值不能为空', trigger: 'blur' }],
|
||||||
dictSort: [{ required: true, message: '数据顺序不能为空', trigger: 'blur' }]
|
dictSort: [{ required: true, message: '数据顺序不能为空', trigger: 'blur' }],
|
||||||
|
enumName: [{ pattern: /^[A-Za-z_]+$/, message: '枚举名称只能包含英文字母和下划线', trigger: 'blur' }]
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -574,6 +595,7 @@ const handleTypeAdd = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleTypeSelectionChange = (selection: DictTypeVO[]) => {
|
const handleTypeSelectionChange = (selection: DictTypeVO[]) => {
|
||||||
|
typeSelections.value = selection;
|
||||||
typeIds.value = selection.map(item => item.dictId);
|
typeIds.value = selection.map(item => item.dictId);
|
||||||
typeSingle.value = selection.length != 1;
|
typeSingle.value = selection.length != 1;
|
||||||
typeMultiple.value = !selection.length;
|
typeMultiple.value = !selection.length;
|
||||||
@ -617,6 +639,16 @@ const handleTypeExport = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** 生成枚举类 */
|
||||||
|
const handleGenEnum = () => {
|
||||||
|
const dictTypes = typeSelections.value.map(item => item.dictType);
|
||||||
|
if (!dictTypes.length) {
|
||||||
|
modal.msgWarning('请选择要生成枚举的字典');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
genEnum(dictTypes);
|
||||||
|
};
|
||||||
|
|
||||||
const handleRefreshCache = async () => {
|
const handleRefreshCache = async () => {
|
||||||
await refreshCache();
|
await refreshCache();
|
||||||
modal.msgSuccess('刷新成功');
|
modal.msgSuccess('刷新成功');
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user