feat: 新增公共上传接口,完善系统配置 Logo、favicon 上传
This commit is contained in:
parent
adf7ec5dda
commit
ff14ceb53f
@ -38,3 +38,7 @@ export function listRoleDict(params: RoleParam) {
|
|||||||
export function listDict(code: string) {
|
export function listDict(code: string) {
|
||||||
return axios.get<LabelValueState[]>(`${BASE_URL}/dict/${code}`);
|
return axios.get<LabelValueState[]>(`${BASE_URL}/dict/${code}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function upload(data: FormData) {
|
||||||
|
return axios.post(`${BASE_URL}/file`, data);
|
||||||
|
}
|
||||||
|
13
continew-admin-ui/src/utils/file.ts
Normal file
13
continew-admin-ui/src/utils/file.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
export default function getFile(file: string | undefined) {
|
||||||
|
if (file) {
|
||||||
|
const baseUrl = import.meta.env.VITE_API_BASE_URL;
|
||||||
|
if (
|
||||||
|
!file.startsWith('http://') &&
|
||||||
|
!file.startsWith('https://') &&
|
||||||
|
!file.startsWith('blob:')
|
||||||
|
) {
|
||||||
|
return `${baseUrl}/file/${file}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return file;
|
||||||
|
}
|
@ -16,6 +16,7 @@
|
|||||||
<br />
|
<br />
|
||||||
<a-upload
|
<a-upload
|
||||||
:file-list="faviconFile ? [faviconFile] : []"
|
:file-list="faviconFile ? [faviconFile] : []"
|
||||||
|
accept="image/*"
|
||||||
:show-file-list="false"
|
:show-file-list="false"
|
||||||
:custom-request="handleUploadFavicon"
|
:custom-request="handleUploadFavicon"
|
||||||
@change="handleChangeFavicon"
|
@change="handleChangeFavicon"
|
||||||
@ -32,7 +33,7 @@
|
|||||||
v-if="faviconFile && faviconFile.url"
|
v-if="faviconFile && faviconFile.url"
|
||||||
class="arco-upload-list-picture custom-upload-avatar favicon"
|
class="arco-upload-list-picture custom-upload-avatar favicon"
|
||||||
>
|
>
|
||||||
<img :src="faviconFile.url" />
|
<img :src="getFile(faviconFile.url)" />
|
||||||
<div
|
<div
|
||||||
v-if="isEdit"
|
v-if="isEdit"
|
||||||
class="arco-upload-list-picture-mask favicon"
|
class="arco-upload-list-picture-mask favicon"
|
||||||
@ -59,6 +60,7 @@
|
|||||||
<br />
|
<br />
|
||||||
<a-upload
|
<a-upload
|
||||||
:file-list="logoFile ? [logoFile] : []"
|
:file-list="logoFile ? [logoFile] : []"
|
||||||
|
accept="image/*"
|
||||||
:show-file-list="false"
|
:show-file-list="false"
|
||||||
:custom-request="handleUploadLogo"
|
:custom-request="handleUploadLogo"
|
||||||
@change="handleChangeLogo"
|
@change="handleChangeLogo"
|
||||||
@ -75,7 +77,7 @@
|
|||||||
v-if="logoFile && logoFile.url"
|
v-if="logoFile && logoFile.url"
|
||||||
class="arco-upload-list-picture custom-upload-avatar logo"
|
class="arco-upload-list-picture custom-upload-avatar logo"
|
||||||
>
|
>
|
||||||
<img :src="logoFile.url" />
|
<img :src="getFile(logoFile.url)" />
|
||||||
<div
|
<div
|
||||||
v-if="isEdit"
|
v-if="isEdit"
|
||||||
class="arco-upload-list-picture-mask logo"
|
class="arco-upload-list-picture-mask logo"
|
||||||
@ -109,8 +111,15 @@
|
|||||||
>
|
>
|
||||||
<a-input v-model="form.site_copyright" placeholder="请输入版权信息" />
|
<a-input v-model="form.site_copyright" placeholder="请输入版权信息" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<div>
|
<div style="margin-top: 20px">
|
||||||
<a-space>
|
<a-space>
|
||||||
|
<a-button
|
||||||
|
v-if="!isEdit"
|
||||||
|
v-permission="['system:config:reset']"
|
||||||
|
@click="toResetValue"
|
||||||
|
>
|
||||||
|
<template #icon><icon-redo /></template>恢复默认
|
||||||
|
</a-button>
|
||||||
<a-button
|
<a-button
|
||||||
v-if="!isEdit"
|
v-if="!isEdit"
|
||||||
v-permission="['system:config:update']"
|
v-permission="['system:config:update']"
|
||||||
@ -119,13 +128,6 @@
|
|||||||
>
|
>
|
||||||
<template #icon><icon-edit /></template>修改
|
<template #icon><icon-edit /></template>修改
|
||||||
</a-button>
|
</a-button>
|
||||||
<a-button
|
|
||||||
v-if="!isEdit"
|
|
||||||
v-permission="['system:config:reset']"
|
|
||||||
@click="toResetValue"
|
|
||||||
>
|
|
||||||
<template #icon><icon-redo /></template>恢复默认
|
|
||||||
</a-button>
|
|
||||||
<a-button
|
<a-button
|
||||||
v-if="isEdit"
|
v-if="isEdit"
|
||||||
v-permission="['system:config:update']"
|
v-permission="['system:config:update']"
|
||||||
@ -166,6 +168,8 @@
|
|||||||
save,
|
save,
|
||||||
resetValue,
|
resetValue,
|
||||||
} from '@/api/system/config';
|
} from '@/api/system/config';
|
||||||
|
import { upload } from '@/api/common';
|
||||||
|
import getFile from '@/utils/file';
|
||||||
|
|
||||||
const { proxy } = getCurrentInstance() as any;
|
const { proxy } = getCurrentInstance() as any;
|
||||||
const dataList = ref<DataRecord[]>([]);
|
const dataList = ref<DataRecord[]>([]);
|
||||||
@ -189,6 +193,20 @@
|
|||||||
});
|
});
|
||||||
const { queryParams, form, rules } = toRefs(data);
|
const { queryParams, form, rules } = toRefs(data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重置表单
|
||||||
|
*/
|
||||||
|
const reset = () => {
|
||||||
|
form.value = {
|
||||||
|
site_title: siteTitle.value?.value,
|
||||||
|
site_copyright: siteCopyright.value?.value,
|
||||||
|
site_logo: siteLogo.value?.value,
|
||||||
|
site_favicon: siteFavicon.value?.value,
|
||||||
|
};
|
||||||
|
logoFile.value.url = siteLogo.value?.value;
|
||||||
|
faviconFile.value.url = siteFavicon.value?.value;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询配置
|
* 查询配置
|
||||||
*/
|
*/
|
||||||
@ -207,14 +225,7 @@
|
|||||||
siteFavicon.value = dataList.value.find(
|
siteFavicon.value = dataList.value.find(
|
||||||
(option) => option.code === 'site_favicon'
|
(option) => option.code === 'site_favicon'
|
||||||
);
|
);
|
||||||
form.value = {
|
reset();
|
||||||
site_title: siteTitle.value?.value,
|
|
||||||
site_copyright: siteCopyright.value?.value,
|
|
||||||
site_logo: siteLogo.value?.value,
|
|
||||||
site_favicon: siteFavicon.value?.value,
|
|
||||||
};
|
|
||||||
logoFile.value.url = siteLogo.value?.value;
|
|
||||||
faviconFile.value.url = siteFavicon.value?.value;
|
|
||||||
};
|
};
|
||||||
getConfig();
|
getConfig();
|
||||||
|
|
||||||
@ -254,8 +265,28 @@
|
|||||||
* @param options /
|
* @param options /
|
||||||
*/
|
*/
|
||||||
const handleUploadLogo = (options: RequestOption) => {
|
const handleUploadLogo = (options: RequestOption) => {
|
||||||
console.log(options);
|
|
||||||
const controller = new AbortController();
|
const controller = new AbortController();
|
||||||
|
(async function requestWrap() {
|
||||||
|
const {
|
||||||
|
onProgress,
|
||||||
|
onError,
|
||||||
|
onSuccess,
|
||||||
|
fileItem,
|
||||||
|
name = 'file',
|
||||||
|
} = options;
|
||||||
|
onProgress(20);
|
||||||
|
const formData = new FormData();
|
||||||
|
formData.append(name as string, fileItem.file as Blob);
|
||||||
|
upload(formData)
|
||||||
|
.then((res) => {
|
||||||
|
onSuccess(res);
|
||||||
|
form.value.site_logo = res.data;
|
||||||
|
proxy.$message.success(res.msg);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
onError(error);
|
||||||
|
});
|
||||||
|
})();
|
||||||
return {
|
return {
|
||||||
abort() {
|
abort() {
|
||||||
controller.abort();
|
controller.abort();
|
||||||
@ -269,8 +300,28 @@
|
|||||||
* @param options /
|
* @param options /
|
||||||
*/
|
*/
|
||||||
const handleUploadFavicon = (options: RequestOption) => {
|
const handleUploadFavicon = (options: RequestOption) => {
|
||||||
console.log(options);
|
|
||||||
const controller = new AbortController();
|
const controller = new AbortController();
|
||||||
|
(async function requestWrap() {
|
||||||
|
const {
|
||||||
|
onProgress,
|
||||||
|
onError,
|
||||||
|
onSuccess,
|
||||||
|
fileItem,
|
||||||
|
name = 'file',
|
||||||
|
} = options;
|
||||||
|
onProgress(20);
|
||||||
|
const formData = new FormData();
|
||||||
|
formData.append(name as string, fileItem.file as Blob);
|
||||||
|
upload(formData)
|
||||||
|
.then((res) => {
|
||||||
|
onSuccess(res);
|
||||||
|
form.value.site_favicon = res.data;
|
||||||
|
proxy.$message.success(res.msg);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
onError(error);
|
||||||
|
});
|
||||||
|
})();
|
||||||
return {
|
return {
|
||||||
abort() {
|
abort() {
|
||||||
controller.abort();
|
controller.abort();
|
||||||
@ -287,7 +338,6 @@
|
|||||||
const handleChangeLogo = (_: any, currentFile: any) => {
|
const handleChangeLogo = (_: any, currentFile: any) => {
|
||||||
logoFile.value = {
|
logoFile.value = {
|
||||||
...currentFile,
|
...currentFile,
|
||||||
// url: URL.createObjectURL(currentFile.file),
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -300,7 +350,6 @@
|
|||||||
const handleChangeFavicon = (_: any, currentFile: any) => {
|
const handleChangeFavicon = (_: any, currentFile: any) => {
|
||||||
faviconFile.value = {
|
faviconFile.value = {
|
||||||
...currentFile,
|
...currentFile,
|
||||||
// url: URL.createObjectURL(currentFile.file),
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -335,13 +384,6 @@
|
|||||||
const toEdit = () => {
|
const toEdit = () => {
|
||||||
isEdit.value = true;
|
isEdit.value = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* 重置表单
|
|
||||||
*/
|
|
||||||
const reset = () => {
|
|
||||||
proxy.$refs.formRef?.resetFields();
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="less">
|
<style scoped lang="less">
|
||||||
@ -359,7 +401,8 @@
|
|||||||
line-height: 16px;
|
line-height: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.arco-form .image-item {
|
.arco-form .image-item,
|
||||||
|
.input-item {
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
export default {
|
export default {
|
||||||
'menu.system.config': '系统配置(开发中)',
|
'menu.system.config': '系统配置',
|
||||||
};
|
};
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
<a-space :size="54">
|
<a-space :size="54">
|
||||||
<a-upload
|
<a-upload
|
||||||
:file-list="avatarList"
|
:file-list="avatarList"
|
||||||
|
accept="image/*"
|
||||||
:show-file-list="false"
|
:show-file-list="false"
|
||||||
list-type="picture-card"
|
list-type="picture-card"
|
||||||
:show-upload-button="true"
|
:show-upload-button="true"
|
||||||
|
@ -16,12 +16,15 @@
|
|||||||
|
|
||||||
package top.charles7c.cnadmin.webapi.controller.common;
|
package top.charles7c.cnadmin.webapi.controller.common;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
@ -31,21 +34,23 @@ import io.swagger.v3.oas.annotations.tags.Tag;
|
|||||||
|
|
||||||
import org.springframework.cache.annotation.Cacheable;
|
import org.springframework.cache.annotation.Cacheable;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.*;
|
||||||
import org.springframework.web.bind.annotation.PathVariable;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
|
|
||||||
import cn.hutool.core.lang.tree.Tree;
|
import cn.hutool.core.lang.tree.Tree;
|
||||||
import cn.hutool.core.util.ClassUtil;
|
import cn.hutool.core.util.ClassUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
|
||||||
import top.charles7c.cnadmin.common.base.BaseEnum;
|
import top.charles7c.cnadmin.common.base.BaseEnum;
|
||||||
|
import top.charles7c.cnadmin.common.config.properties.LocalStorageProperties;
|
||||||
import top.charles7c.cnadmin.common.config.properties.ProjectProperties;
|
import top.charles7c.cnadmin.common.config.properties.ProjectProperties;
|
||||||
import top.charles7c.cnadmin.common.constant.CacheConsts;
|
import top.charles7c.cnadmin.common.constant.CacheConsts;
|
||||||
import top.charles7c.cnadmin.common.model.query.SortQuery;
|
import top.charles7c.cnadmin.common.model.query.SortQuery;
|
||||||
import top.charles7c.cnadmin.common.model.vo.LabelValueVO;
|
import top.charles7c.cnadmin.common.model.vo.LabelValueVO;
|
||||||
import top.charles7c.cnadmin.common.model.vo.R;
|
import top.charles7c.cnadmin.common.model.vo.R;
|
||||||
|
import top.charles7c.cnadmin.common.util.FileUtils;
|
||||||
|
import top.charles7c.cnadmin.common.util.validate.CheckUtils;
|
||||||
|
import top.charles7c.cnadmin.common.util.validate.ValidationUtils;
|
||||||
import top.charles7c.cnadmin.monitor.annotation.Log;
|
import top.charles7c.cnadmin.monitor.annotation.Log;
|
||||||
import top.charles7c.cnadmin.system.model.query.DeptQuery;
|
import top.charles7c.cnadmin.system.model.query.DeptQuery;
|
||||||
import top.charles7c.cnadmin.system.model.query.MenuQuery;
|
import top.charles7c.cnadmin.system.model.query.MenuQuery;
|
||||||
@ -72,6 +77,20 @@ public class CommonController {
|
|||||||
private final RoleService roleService;
|
private final RoleService roleService;
|
||||||
private final DictItemService dictItemService;
|
private final DictItemService dictItemService;
|
||||||
private final ProjectProperties projectProperties;
|
private final ProjectProperties projectProperties;
|
||||||
|
private final LocalStorageProperties localStorageProperties;
|
||||||
|
|
||||||
|
@Operation(summary = "上传文件", description = "上传文件")
|
||||||
|
@PostMapping("/file")
|
||||||
|
public R<String> upload(@NotNull(message = "文件不能为空") MultipartFile file) {
|
||||||
|
ValidationUtils.throwIf(file::isEmpty, "文件不能为空");
|
||||||
|
Long maxSizeInMb = localStorageProperties.getMaxSizeInMb();
|
||||||
|
CheckUtils.throwIf(file.getSize() > maxSizeInMb * 1024 * 1024, "请上传小于 {}MB 的文件", maxSizeInMb);
|
||||||
|
String filePath = localStorageProperties.getPath().getFile();
|
||||||
|
File newFile = FileUtils.upload(file, filePath, false);
|
||||||
|
CheckUtils.throwIfNull(newFile, "上传文件失败");
|
||||||
|
assert null != newFile;
|
||||||
|
return R.ok("上传成功", newFile.getName());
|
||||||
|
}
|
||||||
|
|
||||||
@Operation(summary = "查询部门树", description = "查询树结构的部门列表")
|
@Operation(summary = "查询部门树", description = "查询树结构的部门列表")
|
||||||
@GetMapping("/tree/dept")
|
@GetMapping("/tree/dept")
|
||||||
|
Loading…
Reference in New Issue
Block a user