Merge branch 'main' of https://github.com/vbenjs/vue-vben-admin into dev
This commit is contained in:
commit
379778412b
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben/docs",
|
||||
"version": "5.5.2",
|
||||
"version": "5.5.3",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "vitepress build",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben/commitlint-config",
|
||||
"version": "5.5.2",
|
||||
"version": "5.5.3",
|
||||
"private": true,
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben/stylelint-config",
|
||||
"version": "5.5.2",
|
||||
"version": "5.5.3",
|
||||
"private": true,
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben/node-utils",
|
||||
"version": "5.5.2",
|
||||
"version": "5.5.3",
|
||||
"private": true,
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben/tailwind-config",
|
||||
"version": "5.5.2",
|
||||
"version": "5.5.3",
|
||||
"private": true,
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben/tsconfig",
|
||||
"version": "5.5.2",
|
||||
"version": "5.5.3",
|
||||
"private": true,
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben/vite-config",
|
||||
"version": "5.5.2",
|
||||
"version": "5.5.3",
|
||||
"private": true,
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "vben-admin-monorepo",
|
||||
"version": "5.5.2",
|
||||
"version": "5.5.3",
|
||||
"private": true,
|
||||
"keywords": [
|
||||
"monorepo",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben-core/design",
|
||||
"version": "5.5.2",
|
||||
"version": "5.5.3",
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
"repository": {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben-core/icons",
|
||||
"version": "5.5.2",
|
||||
"version": "5.5.3",
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
"repository": {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben-core/shared",
|
||||
"version": "5.5.2",
|
||||
"version": "5.5.3",
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
"repository": {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben-core/typings",
|
||||
"version": "5.5.2",
|
||||
"version": "5.5.3",
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
"repository": {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben-core/composables",
|
||||
"version": "5.5.2",
|
||||
"version": "5.5.3",
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
"repository": {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben-core/preferences",
|
||||
"version": "5.5.2",
|
||||
"version": "5.5.3",
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
"repository": {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben-core/form-ui",
|
||||
"version": "5.5.2",
|
||||
"version": "5.5.3",
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
"repository": {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben-core/layout-ui",
|
||||
"version": "5.5.2",
|
||||
"version": "5.5.3",
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
"repository": {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben-core/menu-ui",
|
||||
"version": "5.5.2",
|
||||
"version": "5.5.3",
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
"repository": {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben-core/shadcn-ui",
|
||||
"version": "5.5.2",
|
||||
"version": "5.5.3",
|
||||
"#main": "./dist/index.mjs",
|
||||
"#module": "./dist/index.mjs",
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben-core/tabs-ui",
|
||||
"version": "5.5.2",
|
||||
"version": "5.5.3",
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
"repository": {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben/constants",
|
||||
"version": "5.5.2",
|
||||
"version": "5.5.3",
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
"repository": {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben/access",
|
||||
"version": "5.5.2",
|
||||
"version": "5.5.3",
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
"repository": {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben/common-ui",
|
||||
"version": "5.5.2",
|
||||
"version": "5.5.3",
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
"repository": {
|
||||
|
@ -1,11 +1,15 @@
|
||||
<script setup lang="ts">
|
||||
import type { VNode } from 'vue';
|
||||
|
||||
import { computed, ref, watch, watchEffect } from 'vue';
|
||||
|
||||
import { usePagination } from '@vben/hooks';
|
||||
import { EmptyIcon, Grip, listIcons } from '@vben/icons';
|
||||
import { $t } from '@vben/locales';
|
||||
|
||||
import {
|
||||
Button,
|
||||
Input,
|
||||
Pagination,
|
||||
PaginationEllipsis,
|
||||
PaginationFirst,
|
||||
@ -18,12 +22,17 @@ import {
|
||||
VbenIconButton,
|
||||
VbenPopover,
|
||||
} from '@vben-core/shadcn-ui';
|
||||
import { refDebounced } from '@vueuse/core';
|
||||
import { computed, h, ref, watch, watchEffect } from 'vue';
|
||||
|
||||
import { refDebounced, watchDebounced } from '@vueuse/core';
|
||||
|
||||
import { fetchIconsData } from './icons';
|
||||
|
||||
interface Props {
|
||||
pageSize?: number;
|
||||
/** 图标集的名字 */
|
||||
prefix?: string;
|
||||
/** 是否自动请求API以获得图标集的数据.提供prefix时有效 */
|
||||
autoFetchApi?: boolean;
|
||||
/**
|
||||
* 图标列表
|
||||
*/
|
||||
@ -36,16 +45,19 @@ interface Props {
|
||||
modelValueProp?: string;
|
||||
/** 图标样式 */
|
||||
iconClass?: string;
|
||||
type?: 'icon' | 'input';
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
prefix: 'ant-design',
|
||||
pageSize: 36,
|
||||
icons: () => [],
|
||||
inputComponent: () => h('div'),
|
||||
iconSlot: 'default',
|
||||
iconClass: 'size-4',
|
||||
modelValueProp: 'value',
|
||||
autoFetchApi: true,
|
||||
modelValueProp: 'modelValue',
|
||||
inputComponent: undefined,
|
||||
type: 'input',
|
||||
});
|
||||
|
||||
const emit = defineEmits<{
|
||||
@ -59,9 +71,28 @@ const currentSelect = ref('');
|
||||
const currentPage = ref(1);
|
||||
const keyword = ref('');
|
||||
const keywordDebounce = refDebounced(keyword, 300);
|
||||
const innerIcons = ref<string[]>([]);
|
||||
|
||||
watchDebounced(
|
||||
() => props.prefix,
|
||||
async (prefix) => {
|
||||
if (prefix && prefix !== 'svg' && props.autoFetchApi) {
|
||||
innerIcons.value = await fetchIconsData(prefix);
|
||||
}
|
||||
},
|
||||
{ immediate: true, debounce: 500, maxWait: 1000 },
|
||||
);
|
||||
|
||||
const currentList = computed(() => {
|
||||
try {
|
||||
if (props.prefix) {
|
||||
if (
|
||||
props.prefix !== 'svg' &&
|
||||
props.autoFetchApi &&
|
||||
props.icons.length === 0
|
||||
) {
|
||||
return innerIcons.value;
|
||||
}
|
||||
const icons = listIcons('', props.prefix);
|
||||
if (icons.length === 0) {
|
||||
console.warn(`No icons found for prefix: ${props.prefix}`);
|
||||
@ -143,18 +174,61 @@ defineExpose({ toggleOpenState, open, close });
|
||||
content-class="p-0 pt-3"
|
||||
>
|
||||
<template #trigger>
|
||||
<component
|
||||
:is="inputComponent"
|
||||
:[modelValueProp]="currentSelect"
|
||||
:placeholder="$t('ui.iconPicker.placeholder')"
|
||||
>
|
||||
<template #[iconSlot]>
|
||||
<VbenIcon :icon="currentSelect || Grip" class="size-4" />
|
||||
</template>
|
||||
</component>
|
||||
<template v-if="props.type === 'input'">
|
||||
<component
|
||||
v-if="props.inputComponent"
|
||||
:is="inputComponent"
|
||||
:[modelValueProp]="currentSelect"
|
||||
:placeholder="$t('ui.iconPicker.placeholder')"
|
||||
role="combobox"
|
||||
:aria-label="$t('ui.iconPicker.placeholder')"
|
||||
aria-expanded="visible"
|
||||
v-bind="$attrs"
|
||||
>
|
||||
<template #[iconSlot]>
|
||||
<VbenIcon
|
||||
:icon="currentSelect || Grip"
|
||||
class="size-4"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</template>
|
||||
</component>
|
||||
<div class="relative w-full" v-else>
|
||||
<Input
|
||||
v-bind="$attrs"
|
||||
v-model="currentSelect"
|
||||
:placeholder="$t('ui.iconPicker.placeholder')"
|
||||
class="h-8 w-full pr-8"
|
||||
role="combobox"
|
||||
:aria-label="$t('ui.iconPicker.placeholder')"
|
||||
aria-expanded="visible"
|
||||
/>
|
||||
<VbenIcon
|
||||
:icon="currentSelect || Grip"
|
||||
class="absolute right-1 top-1 size-6"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<VbenIcon
|
||||
:icon="currentSelect || Grip"
|
||||
v-else
|
||||
class="size-4"
|
||||
v-bind="$attrs"
|
||||
/>
|
||||
</template>
|
||||
<div class="mb-2 flex w-full">
|
||||
<component :is="inputComponent" v-bind="searchInputProps" />
|
||||
<component
|
||||
v-if="inputComponent"
|
||||
:is="inputComponent"
|
||||
v-bind="searchInputProps"
|
||||
/>
|
||||
<Input
|
||||
v-else
|
||||
class="mx-2 h-8 w-full"
|
||||
:placeholder="$t('ui.iconPicker.search')"
|
||||
v-model="keyword"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<template v-if="paginationList.length > 0">
|
||||
|
@ -0,0 +1,56 @@
|
||||
import type { Recordable } from '@vben/types';
|
||||
|
||||
/**
|
||||
* 一个缓存对象,在不刷新页面时,无需重复请求远程接口
|
||||
*/
|
||||
export const ICONS_MAP: Recordable<string[]> = {};
|
||||
|
||||
interface IconifyResponse {
|
||||
prefix: string;
|
||||
total: number;
|
||||
title: string;
|
||||
uncategorized?: string[];
|
||||
categories?: Recordable<string[]>;
|
||||
aliases?: Recordable<string>;
|
||||
}
|
||||
|
||||
const PENDING_REQUESTS: Recordable<Promise<string[]>> = {};
|
||||
|
||||
/**
|
||||
* 通过Iconify接口获取图标集数据。
|
||||
* 同一时间多个图标选择器同时请求同一个图标集时,实际上只会发起一次请求(所有请求共享同一份结果)。
|
||||
* 请求结果会被缓存,刷新页面前同一个图标集不会再次请求
|
||||
* @param prefix 图标集名称
|
||||
* @returns 图标集中包含的所有图标名称
|
||||
*/
|
||||
export async function fetchIconsData(prefix: string): Promise<string[]> {
|
||||
if (Reflect.has(ICONS_MAP, prefix) && ICONS_MAP[prefix]) {
|
||||
return ICONS_MAP[prefix];
|
||||
}
|
||||
if (Reflect.has(PENDING_REQUESTS, prefix) && PENDING_REQUESTS[prefix]) {
|
||||
return PENDING_REQUESTS[prefix];
|
||||
}
|
||||
PENDING_REQUESTS[prefix] = (async () => {
|
||||
try {
|
||||
const controller = new AbortController();
|
||||
const timeoutId = setTimeout(() => controller.abort(), 1000 * 10);
|
||||
const response: IconifyResponse = await fetch(
|
||||
`https://api.iconify.design/collection?prefix=${prefix}`,
|
||||
{ signal: controller.signal },
|
||||
).then((res) => res.json());
|
||||
clearTimeout(timeoutId);
|
||||
const list = response.uncategorized || [];
|
||||
if (response.categories) {
|
||||
for (const category in response.categories) {
|
||||
list.push(...(response.categories[category] || []));
|
||||
}
|
||||
}
|
||||
ICONS_MAP[prefix] = list.map((v) => `${prefix}:${v}`);
|
||||
} catch (error) {
|
||||
console.error(`Failed to fetch icons for prefix ${prefix}:`, error);
|
||||
return [] as string[];
|
||||
}
|
||||
return ICONS_MAP[prefix];
|
||||
})();
|
||||
return PENDING_REQUESTS[prefix];
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben/hooks",
|
||||
"version": "5.5.2",
|
||||
"version": "5.5.3",
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
"repository": {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben/layouts",
|
||||
"version": "5.5.2",
|
||||
"version": "5.5.3",
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
"repository": {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben/plugins",
|
||||
"version": "5.5.2",
|
||||
"version": "5.5.3",
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
"repository": {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben/request",
|
||||
"version": "5.5.2",
|
||||
"version": "5.5.3",
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
"repository": {
|
||||
|
@ -31,6 +31,7 @@ describe('fileDownloader', () => {
|
||||
expect(result).toEqual(mockBlob);
|
||||
expect(mockAxiosInstance.get).toHaveBeenCalledWith(url, {
|
||||
responseType: 'blob',
|
||||
responseReturn: 'body',
|
||||
});
|
||||
});
|
||||
|
||||
@ -51,6 +52,7 @@ describe('fileDownloader', () => {
|
||||
expect(mockAxiosInstance.get).toHaveBeenCalledWith(url, {
|
||||
...customConfig,
|
||||
responseType: 'blob',
|
||||
responseReturn: 'body',
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -1,7 +1,14 @@
|
||||
import type { AxiosRequestConfig } from 'axios';
|
||||
|
||||
import type { RequestClient } from '../request-client';
|
||||
import type { RequestResponse } from '../types';
|
||||
import type { RequestClientConfig } from '../types';
|
||||
|
||||
type DownloadRequestConfig = {
|
||||
/**
|
||||
* 定义期望获得的数据类型。
|
||||
* raw: 原始的AxiosResponse,包括headers、status等。
|
||||
* body: 只返回响应数据的BODY部分(Blob)
|
||||
*/
|
||||
responseReturn?: 'body' | 'raw';
|
||||
} & Omit<RequestClientConfig, 'responseReturn'>;
|
||||
|
||||
class FileDownloader {
|
||||
private client: RequestClient;
|
||||
@ -9,20 +16,23 @@ class FileDownloader {
|
||||
constructor(client: RequestClient) {
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
public async download(
|
||||
/**
|
||||
* 下载文件
|
||||
* @param url 文件的完整链接
|
||||
* @param config 配置信息,可选。
|
||||
* @returns 如果config.responseReturn为'body',则返回Blob(默认),否则返回RequestResponse<Blob>
|
||||
*/
|
||||
public async download<T = Blob>(
|
||||
url: string,
|
||||
config?: AxiosRequestConfig,
|
||||
): Promise<RequestResponse<Blob>> {
|
||||
const finalConfig: AxiosRequestConfig = {
|
||||
config?: DownloadRequestConfig,
|
||||
): Promise<T> {
|
||||
const finalConfig: DownloadRequestConfig = {
|
||||
responseReturn: 'body',
|
||||
...config,
|
||||
responseType: 'blob',
|
||||
};
|
||||
|
||||
const response = await this.client.get<RequestResponse<Blob>>(
|
||||
url,
|
||||
finalConfig,
|
||||
);
|
||||
const response = await this.client.get<T>(url, finalConfig);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
import type { AxiosRequestConfig, AxiosResponse } from 'axios';
|
||||
|
||||
import type { RequestClient } from '../request-client';
|
||||
import type { RequestClientConfig } from '../types';
|
||||
|
||||
class FileUploader {
|
||||
private client: RequestClient;
|
||||
@ -9,18 +8,18 @@ class FileUploader {
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
public async upload(
|
||||
public async upload<T = any>(
|
||||
url: string,
|
||||
data: { file: Blob | File } & Record<string, any>,
|
||||
config?: AxiosRequestConfig,
|
||||
): Promise<AxiosResponse> {
|
||||
data: Record<string, any> & { file: Blob | File },
|
||||
config?: RequestClientConfig,
|
||||
): Promise<T> {
|
||||
const formData = new FormData();
|
||||
|
||||
Object.entries(data).forEach(([key, value]) => {
|
||||
formData.append(key, value);
|
||||
});
|
||||
|
||||
const finalConfig: AxiosRequestConfig = {
|
||||
const finalConfig: RequestClientConfig = {
|
||||
...config,
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data',
|
||||
|
@ -25,15 +25,15 @@ export const defaultResponseInterceptor = ({
|
||||
if (config.responseReturn === 'raw') {
|
||||
return response;
|
||||
}
|
||||
const code = responseData[codeField];
|
||||
if (
|
||||
status >= 200 && status < 400 && isFunction(successCode)
|
||||
? successCode(code)
|
||||
: code === successCode
|
||||
) {
|
||||
|
||||
if (status >= 200 && status < 400) {
|
||||
if (config.responseReturn === 'body') {
|
||||
return responseData;
|
||||
} else {
|
||||
} else if (
|
||||
isFunction(successCode)
|
||||
? successCode(responseData[codeField])
|
||||
: responseData[codeField] === successCode
|
||||
) {
|
||||
return isFunction(dataField)
|
||||
? dataField(responseData)
|
||||
: responseData[dataField];
|
||||
|
@ -7,9 +7,9 @@ import type {
|
||||
|
||||
type ExtendOptions = {
|
||||
/** 响应数据的返回方式。
|
||||
* raw: 原始的AxiosResponse,包括headers、status等。
|
||||
* body: 返回响应数据的BODY部分。
|
||||
* data: 解构响应的BODY数据,只返回其中的data节点数据。
|
||||
* raw: 原始的AxiosResponse,包括headers、status等,不做是否成功请求的检查。
|
||||
* body: 返回响应数据的BODY部分(只会根据status检查请求是否成功,忽略对code的判断,这种情况下应由调用方检查请求是否成功)。
|
||||
* data: 解构响应的BODY数据,只返回其中的data节点数据(会检查status和code是否为成功状态)。
|
||||
*/
|
||||
responseReturn?: 'body' | 'data' | 'raw';
|
||||
};
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben/icons",
|
||||
"version": "5.5.2",
|
||||
"version": "5.5.3",
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
"repository": {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben/locales",
|
||||
"version": "5.5.2",
|
||||
"version": "5.5.3",
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
"repository": {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben/preferences",
|
||||
"version": "5.5.2",
|
||||
"version": "5.5.3",
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
"repository": {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben/stores",
|
||||
"version": "5.5.2",
|
||||
"version": "5.5.3",
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
"repository": {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben/styles",
|
||||
"version": "5.5.2",
|
||||
"version": "5.5.3",
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
"repository": {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben/types",
|
||||
"version": "5.5.2",
|
||||
"version": "5.5.3",
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
"repository": {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben/utils",
|
||||
"version": "5.5.2",
|
||||
"version": "5.5.3",
|
||||
"homepage": "https://github.com/vbenjs/vue-vben-admin",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
"repository": {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben/playground",
|
||||
"version": "5.5.2",
|
||||
"version": "5.5.3",
|
||||
"homepage": "https://vben.pro",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
"repository": {
|
||||
|
28
playground/src/api/examples/download.ts
Normal file
28
playground/src/api/examples/download.ts
Normal file
@ -0,0 +1,28 @@
|
||||
import type { RequestResponse } from '@vben/request';
|
||||
|
||||
import { requestClient } from '../request';
|
||||
|
||||
/**
|
||||
* 下载文件,获取Blob
|
||||
* @returns Blob
|
||||
*/
|
||||
async function downloadFile1() {
|
||||
return requestClient.download<Blob>(
|
||||
'https://unpkg.com/@vbenjs/static-source@0.1.7/source/logo-v1.webp',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载文件,获取完整的Response
|
||||
* @returns RequestResponse<Blob>
|
||||
*/
|
||||
async function downloadFile2() {
|
||||
return requestClient.download<RequestResponse<Blob>>(
|
||||
'https://unpkg.com/@vbenjs/static-source@0.1.7/source/logo-v1.webp',
|
||||
{
|
||||
responseReturn: 'raw',
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
export { downloadFile1, downloadFile2 };
|
@ -1,4 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
|
||||
import { Page } from '@vben/common-ui';
|
||||
import {
|
||||
downloadFileFromBase64,
|
||||
@ -9,7 +11,23 @@ import {
|
||||
|
||||
import { Button, Card } from 'ant-design-vue';
|
||||
|
||||
import { downloadFile1, downloadFile2 } from '#/api/examples/download';
|
||||
|
||||
import imageBase64 from './base64';
|
||||
|
||||
const downloadResult = ref('');
|
||||
|
||||
function getBlob() {
|
||||
downloadFile1().then((res) => {
|
||||
downloadResult.value = `获取Blob成功,长度:${res.size}`;
|
||||
});
|
||||
}
|
||||
|
||||
function getResponse() {
|
||||
downloadFile2().then((res) => {
|
||||
downloadResult.value = `获取Response成功,headers:${JSON.stringify(res.headers)},长度:${res.data.size}`;
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@ -70,5 +88,13 @@ import imageBase64 from './base64';
|
||||
Download TxT
|
||||
</Button>
|
||||
</Card>
|
||||
|
||||
<Card class="my-5" title="Request download">
|
||||
<Button type="primary" @click="getBlob"> 获取Blob </Button>
|
||||
<Button type="primary" class="ml-4" @click="getResponse">
|
||||
获取Response
|
||||
</Button>
|
||||
<div class="mt-4">{{ downloadResult }}</div>
|
||||
</Card>
|
||||
</Page>
|
||||
</template>
|
||||
|
@ -20,7 +20,10 @@ import {
|
||||
|
||||
import { Card, Input } from 'ant-design-vue';
|
||||
|
||||
const iconValue = ref('ant-design:trademark-outlined');
|
||||
const iconValue1 = ref('ant-design:trademark-outlined');
|
||||
const iconValue2 = ref('svg:avatar-1');
|
||||
const iconValue3 = ref('mdi:alien-outline');
|
||||
const iconValue4 = ref('mdi-light:book-multiple');
|
||||
|
||||
const inputComponent = h(Input);
|
||||
</script>
|
||||
@ -78,26 +81,32 @@ const inputComponent = h(Input);
|
||||
<Card class="mb-5" title="图标选择器">
|
||||
<div class="mb-5 flex items-center gap-5">
|
||||
<span>原始样式(Iconify):</span>
|
||||
<IconPicker class="w-[200px]" />
|
||||
<IconPicker v-model="iconValue1" class="w-[200px]" />
|
||||
</div>
|
||||
<div class="mb-5 flex items-center gap-5">
|
||||
<span>原始样式(svg):</span>
|
||||
<IconPicker class="w-[200px]" prefix="svg" />
|
||||
<IconPicker v-model="iconValue2" class="w-[200px]" prefix="svg" />
|
||||
</div>
|
||||
<div class="mb-5 flex items-center gap-5">
|
||||
<span>使用Input:</span>
|
||||
<IconPicker :input-component="inputComponent" icon-slot="addonAfter" />
|
||||
<span>自定义Input:</span>
|
||||
<IconPicker
|
||||
:input-component="inputComponent"
|
||||
v-model="iconValue3"
|
||||
icon-slot="addonAfter"
|
||||
model-value-prop="value"
|
||||
prefix="mdi"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex items-center gap-5">
|
||||
<span>可手动输入,只能点击图标打开弹窗:</span>
|
||||
<span>显示为一个Icon:</span>
|
||||
<Input
|
||||
v-model:value="iconValue"
|
||||
v-model:value="iconValue4"
|
||||
allow-clear
|
||||
placeholder="点击这里选择图标"
|
||||
style="width: 300px"
|
||||
>
|
||||
<template #addonAfter>
|
||||
<IconPicker v-model="iconValue" class="w-[200px]" />
|
||||
<IconPicker v-model="iconValue4" prefix="mdi-light" type="icon" />
|
||||
</template>
|
||||
</Input>
|
||||
</div>
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben/turbo-run",
|
||||
"version": "5.5.2",
|
||||
"version": "5.5.3",
|
||||
"private": true,
|
||||
"license": "MIT",
|
||||
"type": "module",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vben/vsh",
|
||||
"version": "5.5.2",
|
||||
"version": "5.5.3",
|
||||
"private": true,
|
||||
"license": "MIT",
|
||||
"type": "module",
|
||||
|
Loading…
Reference in New Issue
Block a user