parent
7f38933e37
commit
66100d44b2
@ -0,0 +1,53 @@
|
||||
import { requestClient } from './request';
|
||||
|
||||
export type ID = number | string;
|
||||
export type IDS = (number | string)[];
|
||||
|
||||
export interface BaseEntity {
|
||||
createBy?: string;
|
||||
createDept?: string;
|
||||
createTime?: string;
|
||||
updateBy?: string;
|
||||
updateTime?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询参数
|
||||
* @param pageNum 当前页
|
||||
* @param pageSize 每页大小
|
||||
* @param orderByColumn 排序字段
|
||||
* @param isAsc 是否升序
|
||||
*/
|
||||
export interface PageQuery {
|
||||
isAsc?: boolean;
|
||||
orderByColumn?: string;
|
||||
pageNum?: number;
|
||||
pageSize?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: contentType
|
||||
*/
|
||||
export enum ContentTypeEnum {
|
||||
// form-data upload
|
||||
FORM_DATA = 'multipart/form-data;charset=UTF-8',
|
||||
// form-data qs
|
||||
FORM_URLENCODED = 'application/x-www-form-urlencoded;charset=UTF-8',
|
||||
// json
|
||||
JSON = 'application/json;charset=UTF-8',
|
||||
}
|
||||
|
||||
/**
|
||||
* 通用下载接口 封装一层
|
||||
* @param url 请求地址
|
||||
* @param data 请求参数
|
||||
* @returns blob二进制
|
||||
*/
|
||||
export function commonExport(url: string, data: Record<string, any>) {
|
||||
return requestClient.post<Blob>(url, data, {
|
||||
data,
|
||||
headers: { 'Content-Type': ContentTypeEnum.FORM_URLENCODED },
|
||||
isTransformResponse: false,
|
||||
responseType: 'blob',
|
||||
});
|
||||
}
|
||||
@ -0,0 +1,17 @@
|
||||
export interface DictData {
|
||||
createBy: string;
|
||||
createTime: string;
|
||||
cssClass: string;
|
||||
default: boolean;
|
||||
dictCode: number;
|
||||
dictLabel: string;
|
||||
dictSort: number;
|
||||
dictType: string;
|
||||
dictValue: string;
|
||||
isDefault: string;
|
||||
listClass: string;
|
||||
remark: string;
|
||||
status: string;
|
||||
updateBy?: any;
|
||||
updateTime?: any;
|
||||
}
|
||||
@ -0,0 +1,75 @@
|
||||
import type { DictData } from './dict-data-model';
|
||||
|
||||
import type { ID, IDS, PageQuery } from '#/api/base';
|
||||
|
||||
import { commonExport } from '#/api/base';
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
enum Api {
|
||||
dictDataExport = '/system/dict/data/export',
|
||||
dictDataList = '/system/dict/data/list',
|
||||
root = '/system/dict/data',
|
||||
}
|
||||
|
||||
/**
|
||||
* 主要是DictTag组件使用
|
||||
* @param dictType 字典类型
|
||||
* @returns 字典数据
|
||||
*/
|
||||
export function dictDataInfo(dictType: string) {
|
||||
return requestClient.get<DictData[]>(`${Api.root}/type/${dictType}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 字典数据
|
||||
* @param params 查询参数
|
||||
* @returns 字典数据列表
|
||||
*/
|
||||
export function dictDataList(params?: PageQuery) {
|
||||
return requestClient.get<DictData[]>(Api.dictDataList, { params });
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出字典数据
|
||||
* @param data 表单参数
|
||||
* @returns blob
|
||||
*/
|
||||
export function dictDataExport(data: any) {
|
||||
return commonExport(Api.dictDataExport, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除
|
||||
* @param dictIds 字典ID Array
|
||||
* @returns void
|
||||
*/
|
||||
export function dictDataRemove(dictIds: IDS) {
|
||||
return requestClient.deleteWithMsg<void>(`${Api.root}/${dictIds.join(',')}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增
|
||||
* @param data 表单参数
|
||||
* @returns void
|
||||
*/
|
||||
export function dictDataAdd(data: any) {
|
||||
return requestClient.postWithMsg<void>(Api.root, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改
|
||||
* @param data 表单参数
|
||||
* @returns void
|
||||
*/
|
||||
export function dictDataUpdate(data: any) {
|
||||
return requestClient.putWithMsg<void>(Api.root, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询字典数据详细
|
||||
* @param dictCode 字典编码
|
||||
* @returns 字典数据
|
||||
*/
|
||||
export function dictDetailInfo(dictCode: ID) {
|
||||
return requestClient.get<DictData>(`${Api.root}/${dictCode}`);
|
||||
}
|
||||
@ -0,0 +1,8 @@
|
||||
export interface DictType {
|
||||
createTime: string;
|
||||
dictId: number;
|
||||
dictName: string;
|
||||
dictType: string;
|
||||
remark: string;
|
||||
status: string;
|
||||
}
|
||||
@ -0,0 +1,84 @@
|
||||
import type { DictType } from './dict-type-model';
|
||||
|
||||
import type { ID, IDS, PageQuery } from '#/api/base';
|
||||
|
||||
import { commonExport } from '#/api/base';
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
enum Api {
|
||||
dictOptionSelectList = '/system/dict/type/optionselect',
|
||||
dictTypeExport = '/system/dict/type/export',
|
||||
dictTypeList = '/system/dict/type/list',
|
||||
dictTypeRefreshCache = '/system/dict/type/refreshCache',
|
||||
root = '/system/dict/type',
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取字典类型列表
|
||||
* @param params 请求参数
|
||||
* @returns list
|
||||
*/
|
||||
export function dictList(params?: PageQuery) {
|
||||
return requestClient.get<DictType[]>(Api.dictTypeList, { params });
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出字典类型列表
|
||||
* @param data 表单参数
|
||||
* @returns blob
|
||||
*/
|
||||
export function dictExport(data: any) {
|
||||
return commonExport(Api.dictTypeExport, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除字典类型
|
||||
* @param dictIds 字典类型id数组
|
||||
* @returns void
|
||||
*/
|
||||
export function dictTypeRemove(dictIds: IDS) {
|
||||
return requestClient.deleteWithMsg<void>(`${Api.root}/${dictIds.join(',')}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新字典缓存
|
||||
* @returns void
|
||||
*/
|
||||
export function refreshDictTypeCache() {
|
||||
return requestClient.deleteWithMsg<void>(Api.dictTypeRefreshCache);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增
|
||||
* @param data 表单参数
|
||||
* @returns void
|
||||
*/
|
||||
export function dictTypeAdd(data: any) {
|
||||
return requestClient.postWithMsg<void>(Api.root, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改
|
||||
* @param data 表单参数
|
||||
* @returns void
|
||||
*/
|
||||
export function dictTypeUpdate(data: any) {
|
||||
return requestClient.putWithMsg<void>(Api.root, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询详情
|
||||
* @param dictId 字典类型id
|
||||
* @returns 信息
|
||||
*/
|
||||
export function dictTypeInfo(dictId: ID) {
|
||||
return requestClient.get<DictType>(`${Api.root}/${dictId}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 下拉框 返回值和list一样
|
||||
* @returns options
|
||||
*/
|
||||
export function dictOptionSelectList() {
|
||||
return requestClient.get<DictType[]>(Api.dictOptionSelectList);
|
||||
}
|
||||
@ -0,0 +1,5 @@
|
||||
import { withInstall } from '#/utils';
|
||||
|
||||
import dictTag from './src/index.vue';
|
||||
|
||||
export const DictTag = withInstall(dictTag);
|
||||
@ -0,0 +1,44 @@
|
||||
import { type VNode } from 'vue';
|
||||
|
||||
import { Tag } from 'ant-design-vue';
|
||||
|
||||
interface TagType {
|
||||
[key: string]: { color: string; label: string };
|
||||
}
|
||||
|
||||
export const tagTypes: TagType = {
|
||||
cyan: { color: 'cyan', label: 'cyan' },
|
||||
danger: { color: 'error', label: '危险(danger)' },
|
||||
/** 由于和elementUI不同 用于替换颜色 */
|
||||
default: { color: 'default', label: '默认(default)' },
|
||||
green: { color: 'green', label: 'green' },
|
||||
info: { color: 'default', label: '信息(info)' },
|
||||
orange: { color: 'orange', label: 'orange' },
|
||||
/** 自定义预设 color可以为16进制颜色 */
|
||||
pink: { color: 'pink', label: 'pink' },
|
||||
primary: { color: 'processing', label: '主要(primary)' },
|
||||
purple: { color: 'purple', label: 'purple' },
|
||||
red: { color: 'red', label: 'red' },
|
||||
success: { color: 'success', label: '成功(success)' },
|
||||
warning: { color: 'warning', label: '警告(warning)' },
|
||||
};
|
||||
|
||||
// 字典选择使用 { label: string; value: string }[]
|
||||
interface Options {
|
||||
label: string | VNode;
|
||||
value: string;
|
||||
}
|
||||
|
||||
export function tagSelectOptions() {
|
||||
const selectArray: Options[] = [];
|
||||
Object.keys(tagTypes).forEach((key) => {
|
||||
if (!tagTypes[key]) return;
|
||||
const label = tagTypes[key].label;
|
||||
const color = tagTypes[key].color;
|
||||
selectArray.push({
|
||||
label: <Tag color={color}>{label}</Tag>,
|
||||
value: key,
|
||||
});
|
||||
});
|
||||
return selectArray;
|
||||
}
|
||||
@ -0,0 +1,61 @@
|
||||
<script setup lang="ts">
|
||||
import type { DictData } from '#/api/system/dict/dict-data-model';
|
||||
|
||||
import { computed, watch } from 'vue';
|
||||
|
||||
import { Tag } from 'ant-design-vue';
|
||||
|
||||
import { tagTypes } from './data';
|
||||
|
||||
defineOptions({ name: 'DictTag' });
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
dicts: DictData[]; // dict数组
|
||||
value: number | string; // value
|
||||
}>(),
|
||||
{
|
||||
dicts: undefined,
|
||||
},
|
||||
);
|
||||
|
||||
watch(
|
||||
() => props.dicts,
|
||||
(value) => {
|
||||
console.log('dicts change', value);
|
||||
},
|
||||
);
|
||||
|
||||
const color = computed<string>(() => {
|
||||
// eslint-disable-next-line eqeqeq
|
||||
const current = props.dicts.find((item) => item.dictValue == props.value);
|
||||
const listClass = current?.listClass ?? '';
|
||||
// 是否为默认的颜色
|
||||
const isDefault = Reflect.has(tagTypes, listClass);
|
||||
// 判断是默认还是自定义颜色
|
||||
if (isDefault) {
|
||||
// 这里做了antd - element-plus的兼容
|
||||
return tagTypes[listClass]!.color;
|
||||
}
|
||||
return listClass;
|
||||
});
|
||||
|
||||
const cssClass = computed<string>(() => {
|
||||
// eslint-disable-next-line eqeqeq
|
||||
const current = props.dicts.find((item) => item.dictValue == props.value);
|
||||
return current?.cssClass ?? '';
|
||||
});
|
||||
|
||||
const label = computed<number | string>(() => {
|
||||
// eslint-disable-next-line eqeqeq
|
||||
const current = props.dicts.find((item) => item.dictValue == props.value);
|
||||
return current?.dictLabel ?? 'unknown';
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<Tag v-if="color" :class="cssClass" :color="color">{{ label }}</Tag>
|
||||
<div v-if="!color" :class="cssClass">{{ label }}</div>
|
||||
</div>
|
||||
</template>
|
||||
@ -0,0 +1,99 @@
|
||||
import type { DictData } from '#/api/system/dict/dict-data-model';
|
||||
|
||||
import { reactive } from 'vue';
|
||||
|
||||
import { defineStore } from 'pinia';
|
||||
|
||||
/**
|
||||
* antd使用 select和radio通用
|
||||
*/
|
||||
export interface Option {
|
||||
disabled?: boolean;
|
||||
label: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
export function dictToOptions(data: DictData[]): Option[] {
|
||||
return data.map((item) => ({
|
||||
label: item.dictLabel,
|
||||
value: item.dictValue,
|
||||
}));
|
||||
}
|
||||
|
||||
export const useDictStore = defineStore('app-dict', () => {
|
||||
/**
|
||||
* 一般是dictTag使用
|
||||
*/
|
||||
const dictMap = reactive(new Map<string, DictData[]>());
|
||||
/**
|
||||
* select radio radioButton使用 只能为固定格式(Option)
|
||||
*/
|
||||
const dictOptionsMap = reactive(new Map<string, Option[]>());
|
||||
|
||||
function getDict(dictName: string): DictData[] {
|
||||
if (!dictName) return [];
|
||||
// 没有key 添加一个空数组
|
||||
if (!dictMap.has(dictName)) {
|
||||
dictMap.set(dictName, reactive([]));
|
||||
}
|
||||
// 这里拿到的就不可能为空了
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
return dictMap.get(dictName)!;
|
||||
}
|
||||
|
||||
function getDictOptions(dictName: string): Option[] {
|
||||
if (!dictName) return [];
|
||||
// 没有key 添加一个空数组
|
||||
if (!dictOptionsMap.has(dictName)) {
|
||||
dictOptionsMap.set(dictName, []);
|
||||
}
|
||||
// 这里拿到的就不可能为空了
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
return dictOptionsMap.get(dictName)!;
|
||||
}
|
||||
|
||||
function resetCache() {
|
||||
dictMap.clear();
|
||||
dictOptionsMap.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* 核心逻辑
|
||||
*
|
||||
* 不能直接粗暴使用set 会导致之前return的空数组跟现在的数组指向不是同一个地址 数据也就为空了
|
||||
*
|
||||
* 判断是否已经存在key 并且数组长度为0 说明该次要处理的数据是return的空数组 直接push(不修改指向)
|
||||
* 否则 直接set
|
||||
*
|
||||
*/
|
||||
function setDictInfo(dictName: string, dictValue: DictData[]) {
|
||||
if (dictMap.has(dictName) && dictMap.get(dictName)?.length === 0) {
|
||||
dictMap.get(dictName)?.push(...dictValue);
|
||||
} else {
|
||||
dictMap.set(dictName, dictValue);
|
||||
}
|
||||
if (
|
||||
dictOptionsMap.has(dictName) &&
|
||||
dictOptionsMap.get(dictName)?.length === 0
|
||||
) {
|
||||
dictOptionsMap.get(dictName)?.push(...dictToOptions(dictValue));
|
||||
} else {
|
||||
dictOptionsMap.set(dictName, dictToOptions(dictValue));
|
||||
}
|
||||
}
|
||||
|
||||
function $reset() {
|
||||
dictMap.clear();
|
||||
dictOptionsMap.clear();
|
||||
}
|
||||
|
||||
return {
|
||||
$reset,
|
||||
dictMap,
|
||||
dictOptionsMap,
|
||||
getDict,
|
||||
getDictOptions,
|
||||
resetCache,
|
||||
setDictInfo,
|
||||
};
|
||||
});
|
||||
@ -0,0 +1,55 @@
|
||||
import type { DictData } from '#/api/system/dict/dict-data-model';
|
||||
|
||||
import { dictDataInfo } from '#/api/system/dict/dict-data';
|
||||
import { type Option, useDictStore } from '#/store/dict';
|
||||
// todo 重复代码的封装
|
||||
/**
|
||||
* 添加一个字典请求状态的缓存
|
||||
*
|
||||
* 主要解决多次请求重复api的问题(不能用abortController 会导致除了第一个其他的获取的全为空)
|
||||
* 比如在一个页面 index表单 modal drawer总共会请求三次 但是获取的都是一样的数据
|
||||
*/
|
||||
const dictRequestCache = new Map<string, Promise<DictData[] | void>>();
|
||||
|
||||
export function getDict(dictName: string): DictData[] {
|
||||
const { getDict, setDictInfo } = useDictStore();
|
||||
// 这里拿到
|
||||
const dictList = getDict(dictName);
|
||||
if (
|
||||
dictList.length === 0 && // 检查请求状态缓存
|
||||
!dictRequestCache.has(dictName)
|
||||
) {
|
||||
dictRequestCache.set(
|
||||
dictName,
|
||||
dictDataInfo(dictName).then((resp) => {
|
||||
// 缓存到store 这样就不用重复获取了
|
||||
// 内部处理了push的逻辑 这里不用push
|
||||
setDictInfo(dictName, resp);
|
||||
// 移除请求状态缓存
|
||||
dictRequestCache.delete(dictName);
|
||||
}),
|
||||
);
|
||||
}
|
||||
return dictList;
|
||||
}
|
||||
|
||||
export function getDictOptions(dictName: string): Option[] {
|
||||
const { getDictOptions, setDictInfo } = useDictStore();
|
||||
const dictOptionList = getDictOptions(dictName);
|
||||
if (
|
||||
dictOptionList.length === 0 && // 检查请求状态缓存
|
||||
!dictRequestCache.has(dictName)
|
||||
) {
|
||||
dictRequestCache.set(
|
||||
dictName,
|
||||
dictDataInfo(dictName).then((resp) => {
|
||||
// 缓存到store 这样就不用重复获取了
|
||||
// 内部处理了push的逻辑 这里不用push
|
||||
setDictInfo(dictName, resp);
|
||||
// 移除请求状态缓存
|
||||
dictRequestCache.delete(dictName);
|
||||
}),
|
||||
);
|
||||
}
|
||||
return dictOptionList;
|
||||
}
|
||||
Loading…
Reference in new issue