Merge branch 'ts' into dev

# Conflicts:
#	package.json
#	src/layout/components/TagsView/index.vue
This commit is contained in:
LiuHao 2023-05-06 09:25:05 +08:00
commit bf4a8543ca
23 changed files with 239 additions and 164 deletions

View File

@ -70,11 +70,11 @@
"unplugin-auto-import": "0.13.0",
"unplugin-icons": "0.15.1",
"unplugin-vue-components": "0.23.0",
"vite": "4.3.1",
"vite-plugin-compression": "0.5.1",
"vite-plugin-svg-icons": "2.0.1",
"vite-plugin-vue-setup-extend": "^0.4.0",
"vitest": "^0.29.7",
"vite": "4.3.1",
"vue-eslint-parser": "9.1.0",
"vue-tsc": "0.35.0"
}

View File

@ -5,7 +5,7 @@ import { AxiosPromise } from 'axios';
// 查询OSS对象存储列表
export function listOss(query: OssQuery): AxiosPromise<OssVO[]> {
return request({
url: '/system/oss/list',
url: '/resource/oss/list',
method: 'get',
params: query
});
@ -14,7 +14,7 @@ export function listOss(query: OssQuery): AxiosPromise<OssVO[]> {
// 查询OSS对象基于id串
export function listByIds(ossId: string | number): AxiosPromise<OssVO[]> {
return request({
url: '/system/oss/listByIds/' + ossId,
url: '/resource/oss/listByIds/' + ossId,
method: 'get'
});
}
@ -22,7 +22,7 @@ export function listByIds(ossId: string | number): AxiosPromise<OssVO[]> {
// 删除OSS对象存储
export function delOss(ossId: string | number | Array<string | number>) {
return request({
url: '/system/oss/' + ossId,
url: '/resource/oss/' + ossId,
method: 'delete'
});
}

View File

@ -5,7 +5,7 @@ import { AxiosPromise } from 'axios';
// 查询对象存储配置列表
export function listOssConfig(query: OssConfigQuery): AxiosPromise<OssConfigVO[]> {
return request({
url: '/system/oss/config/list',
url: '/resource/oss/config/list',
method: 'get',
params: query
});
@ -14,7 +14,7 @@ export function listOssConfig(query: OssConfigQuery): AxiosPromise<OssConfigVO[]
// 查询对象存储配置详细
export function getOssConfig(ossConfigId: string | number): AxiosPromise<OssConfigVO> {
return request({
url: '/system/oss/config/' + ossConfigId,
url: '/resource/oss/config/' + ossConfigId,
method: 'get'
});
}
@ -22,7 +22,7 @@ export function getOssConfig(ossConfigId: string | number): AxiosPromise<OssConf
// 新增对象存储配置
export function addOssConfig(data: OssConfigForm) {
return request({
url: '/system/oss/config',
url: '/resource/oss/config',
method: 'post',
data: data
});
@ -31,7 +31,7 @@ export function addOssConfig(data: OssConfigForm) {
// 修改对象存储配置
export function updateOssConfig(data: OssConfigForm) {
return request({
url: '/system/oss/config',
url: '/resource/oss/config',
method: 'put',
data: data
});
@ -40,7 +40,7 @@ export function updateOssConfig(data: OssConfigForm) {
// 删除对象存储配置
export function delOssConfig(ossConfigId: string | number | Array<string | number>) {
return request({
url: '/system/oss/config/' + ossConfigId,
url: '/resource/oss/config/' + ossConfigId,
method: 'delete'
});
}
@ -53,7 +53,7 @@ export function changeOssConfigStatus(ossConfigId: string | number, status: stri
configKey
};
return request({
url: '/system/oss/config/changeStatus',
url: '/resource/oss/config/changeStatus',
method: 'put',
data: data
});

View File

@ -1,6 +1,6 @@
#app {
.main-container {
min-height: 100%;
height: 100%;
transition: margin-left 0.28s;
margin-left: $base-sidebar-width;
position: relative;

View File

@ -2,13 +2,9 @@
<div>
<template v-for="(item, index) in options">
<template v-if="values.includes(item.value)">
<span
v-if="item.elTagType == 'default' || item.elTagType == ''"
:key="item.value"
:index="index"
:class="item.elTagClass"
>{{ item.label }}</span
>
<span v-if="item.elTagType == 'default' || item.elTagType == ''" :key="item.value" :index="index" :class="item.elTagClass">
{{ item.label + " " }}
</span>
<el-tag
v-else
:disable-transitions="true"
@ -16,33 +12,85 @@
:index="index"
:type="item.elTagType === 'primary' ? '' : item.elTagType"
:class="item.elTagClass"
>{{ item.label }}</el-tag
>
{{ item.label + " " }}
</el-tag>
</template>
</template>
<template v-if="unmatch && showValue">
{{ unmatchArray }}
</template>
</div>
</template>
<script setup lang="ts">
import { PropType } from 'vue';
const props = defineProps({
//
options: {
type: Array as PropType<DictDataOption[]>,
default: null,
},
//
value: [Number, String, Array],
})
//
options: {
type: Array as PropType<DictDataOption[]>,
default: null,
},
//
value: [Number, String, Array] as PropType<number | string | Array<number | string>>,
// value
showValue: {
type: Boolean as PropType<boolean>,
default: true,
},
});
const values = computed(() => {
if (props.value !== null && typeof props.value !== 'undefined') {
return Array.isArray(props.value) ? props.value : [String(props.value)];
} else {
return [];
if (props.value !== null && typeof props.value !== "undefined") {
return Array.isArray(props.value) ? props.value : [String(props.value)];
} else {
return [];
}
});
const unmatch = computed(() => {
if (props.value !== null && typeof props.value !== "undefined") {
//
if (!Array.isArray(props.value)) {
if (props.options.some((v) => v.value == props.value)) {
return false;
}
return true;
}
})
return true;
}
// value
return false;
});
const unmatchArray = computed(() => {
//
const itemUnmatchArray: Array<string | number> = [];
if (props.value !== null && typeof props.value !== "undefined") {
//
if (!Array.isArray(props.value)) {
itemUnmatchArray.push(props.value);
} else {
// Array
props.value.forEach((item) => {
if (!props.options.some((v) => v.value == item)) {
itemUnmatchArray.push(item);
}
});
}
}
// value
return handleArray(itemUnmatchArray);
});
const handleArray = (array: Array<string | number>) => {
if (array.length === 0) return "";
return array.reduce((pre, cur) => {
return pre + " " + cur;
});
}
</script>
<style scoped>

View File

@ -68,7 +68,7 @@ const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const upload = reactive<UploadOption>({
headers: { Authorization: "Bearer " + getToken() },
url: import.meta.env.VITE_APP_BASE_API + '/system/oss/upload'
url: import.meta.env.VITE_APP_BASE_API + '/resource/oss/upload'
})
const myQuillEditor = ref();

View File

@ -78,7 +78,7 @@ const number = ref(0);
const uploadList = ref<any[]>([]);
const baseUrl = import.meta.env.VITE_APP_BASE_API;
const uploadFileUrl = ref(baseUrl + "/system/oss/upload"); //
const uploadFileUrl = ref(baseUrl + "/resource/oss/upload"); //
const headers = ref({ Authorization: "Bearer " + getToken() });
const fileList = ref<any[]>([]);

View File

@ -2,7 +2,7 @@
<div class="relative" :style="{ width: width }">
<el-input v-model="modelValue" readonly @click="visible = !visible" placeholder="点击选择图标">
<template #prepend>
<svg-icon :icon-class="modelValue as string"></svg-icon>
<svg-icon :icon-class="modelValue as string" />
</template>
</el-input>
@ -19,7 +19,7 @@
<el-scrollbar height="w-[200px]">
<ul class="icon-list">
<el-tooltip v-for="(iconName, index) in iconNames" :key="index" :content="iconName" placement="bottom" effect="light">
<li class="icon-item" @click="selectedIcon(iconName)">
<li :class="['icon-item', {active: modelValue == iconName}]" @click="selectedIcon(iconName)">
<svg-icon color="var(--el-text-color-regular)" :icon-class="iconName" />
</li>
</el-tooltip>
@ -33,15 +33,15 @@
import icons from '@/components/IconSelect/requireIcons';
const props = defineProps({
modelValue: {
type: String,
require: true
},
width: {
type: String,
require: false,
default: '400px'
}
modelValue: {
type: String,
require: true
},
width: {
type: String,
require: false,
default: '400px'
}
});
const emit = defineEmits(['update:modelValue']);
@ -55,22 +55,21 @@ const filterValue = ref('');
* 筛选图标
*/
const filterIcons = () => {
if (filterValue.value) {
iconNames.value = icons.filter(iconName =>
iconName.includes(filterValue.value)
);
} else {
iconNames.value = icons;
}
if (filterValue.value) {
iconNames.value = icons.filter(iconName =>
iconName.includes(filterValue.value)
);
} else {
iconNames.value = icons;
}
}
/**
* 选择图标
* @param iconName 选择的图标名称
*/
const selectedIcon = (iconName: string) => {
emit('update:modelValue', iconName);
visible.value = false;
emit('update:modelValue', iconName);
visible.value = false;
}
</script>
@ -101,5 +100,9 @@ const selectedIcon = (iconName: string) => {
transform: scaleX(1.1);
}
}
.active {
border-color: var(--el-color-primary);
color: var(--el-color-primary);
}
}
</style>

View File

@ -76,7 +76,7 @@ const dialogImageUrl = ref("");
const dialogVisible = ref(false);
const baseUrl = import.meta.env.VITE_APP_BASE_API;
const uploadImgUrl = ref(baseUrl + "/system/oss/upload"); //
const uploadImgUrl = ref(baseUrl + "/resource/oss/upload"); //
const headers = ref({ Authorization: "Bearer " + getToken() });
const fileList = ref<any[]>([]);

View File

@ -104,7 +104,7 @@ const setVisibleNumber = () => {
visibleNumber.value = parseInt(String(width / 85));
}
const handleSelect = (key: string, keyPath: string[]) => {
const handleSelect = (key: string) => {
currentIndex.value = key;
const route = routers.value.find(item => item.path === key);
if (isHttp(key)) {
@ -112,7 +112,13 @@ const handleSelect = (key: string, keyPath: string[]) => {
window.open(key, "_blank");
} else if (!route || !route.children) {
//
router.push({ path: key, fullPath: '' });
const routeMenu = childrenMenus.value.find(item => item.path === key);
if (routeMenu && routeMenu.query) {
let query = JSON.parse(routeMenu.query);
router.push({ path: key, query: query });
} else {
router.push({ path: key });
}
appStore.toggleSideBarHide(true);
} else {
//

View File

@ -56,3 +56,25 @@ watch(()=> useSettingsStore().animationEnable, (val) => {
}
}
</style>
<style lang="scss">
// fix css style bug in open el-dialog
.el-popup-parent--hidden {
.fixed-header {
padding-right: 6px;
}
}
::-webkit-scrollbar {
width: 6px;
height: 6px;
}
::-webkit-scrollbar-track {
background-color: #f1f1f1;
}
::-webkit-scrollbar-thumb {
background-color: #c0c0c0;
border-radius: 3px;
}
</style>

View File

@ -96,7 +96,7 @@ defineExpose({
bottom: 0px;
}
:deep(.el-scrollbar__wrap) {
height: 49px;
height: 39px;
}
}
</style>

View File

@ -246,9 +246,10 @@ onMounted(() => {
position: relative;
cursor: pointer;
height: 26px;
line-height: 26px;
line-height: 23px;
background-color: var(--el-bg-color);
border: 1px solid var(--el-border-color-light);
color: #495060;
padding: 0 8px;
font-size: 12px;
margin-left: 5px;

View File

@ -1,17 +1,23 @@
<template>
<div :class="classObj" class="app-wrapper" :style="{ '--current-color': theme }">
<el-scrollbar>
<div v-if="device === 'mobile' && sidebar.opened" class="drawer-bg" @click="handleClickOutside"/>
<side-bar v-if="!sidebar.hide" class="sidebar-container" />
<div :class="{ hasTagsView: needTagsView, sidebarHide: sidebar.hide }" class="main-container">
<div v-if="device === 'mobile' && sidebar.opened" class="drawer-bg" @click="handleClickOutside" />
<side-bar v-if="!sidebar.hide" class="sidebar-container" />
<div :class="{ hasTagsView: needTagsView, sidebarHide: sidebar.hide }" class="main-container">
<!-- <el-scrollbar>
<div :class="{ 'fixed-header': fixedHeader }">
<navbar ref="navbarRef" @setLayout="setLayout" />
<tags-view v-if="needTagsView" />
<navbar ref="navbarRef" @setLayout="setLayout" />
<tags-view v-if="needTagsView" />
</div>
<app-main />
<settings ref="settingRef" />
</el-scrollbar> -->
<div :class="{ 'fixed-header': fixedHeader }">
<navbar ref="navbarRef" @setLayout="setLayout" />
<tags-view v-if="needTagsView" />
</div>
</el-scrollbar>
<app-main />
<settings ref="settingRef" />
</div>
</div>
</template>
@ -54,17 +60,17 @@ const navbarRef = ref(Navbar);
const settingRef = ref(Settings);
onMounted(() => {
nextTick(() => {
navbarRef.value.initTenantList();
})
nextTick(() => {
navbarRef.value.initTenantList();
})
})
const handleClickOutside = () => {
useAppStore().closeSideBar({ withoutAnimation: false })
useAppStore().closeSideBar({ withoutAnimation: false })
}
const setLayout = () => {
settingRef.value.openSetting();
settingRef.value.openSetting();
}
</script>
@ -78,18 +84,6 @@ const setLayout = () => {
height: 100%;
width: 100%;
.el-scrollbar {
height: 100%;
}
:deep(.el-scrollbar__bar).is-vertical {
z-index: 10;
}
:deep(.el-scrollbar__wrap) {
overflow-x: hidden;
}
&.mobile.openSidebar {
position: fixed;
top: 0;

View File

@ -9,7 +9,7 @@ const baseURL = import.meta.env.VITE_APP_BASE_API;
let downloadLoadingInstance: LoadingInstance;
export default {
async oss(ossId: string | number) {
const url = baseURL + '/system/oss/download/' + ossId;
const url = baseURL + '/resource/oss/download/' + ossId;
downloadLoadingInstance = ElLoading.service({ text: '正在下载数据,请稍候', background: 'rgba(0, 0, 0, 0.7)' });
try {
const res = await axios({

View File

@ -134,7 +134,7 @@ export const dynamicRoutes: RouteOption[] = [
path: '/system/oss-config',
component: Layout,
hidden: true,
permissions: ['monitor:job:list'],
permissions: ['system:oss:list'],
children: [
{
path: 'index',

View File

@ -13,6 +13,7 @@ declare module 'vue-router' {
title: string;
icon: string;
};
query?: string;
} & RouteRecordRaw;
interface _RouteLocationBase {

View File

@ -232,7 +232,7 @@ const handleAdd = (row?: DeptVO) => {
nextTick(() => {
reset();
if (row && row.deptId) {
form.value.parentId = row?.parentId;
form.value.parentId = row?.deptId;
}
})
}

View File

@ -63,7 +63,7 @@
:total="total"
v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize"
@pagination="handleQuery"
@pagination="getList"
/>
<select-user ref="selectRef" :roleId="queryParams.roleId" @ok="handleQuery" />
</el-card>

View File

@ -95,7 +95,7 @@
v-model:total="total"
v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize"
@pagination="handleQuery"
@pagination="getList"
/>
</el-card>

View File

@ -146,7 +146,7 @@
:total="total"
v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize"
@pagination="handleQuery"
@pagination="getList"
/>
</el-card>
</el-col>

View File

@ -136,54 +136,53 @@ const genInfo = ref(genInfoForm);
/** 提交按钮 */
const submitForm = () => {
const basicForm = basicInfo.value.$refs.basicInfoForm;
const genForm = genInfo.value.$refs.genInfoForm;
const basicForm = basicInfo.value.$refs.basicInfoForm;
const genForm = genInfo.value.$refs.genInfoForm;
Promise.all([basicForm, genForm].map(getFormPromise)).then(async res => {
const validateResult = res.every(item => !!item);
if (validateResult) {
const genTable: any = Object.assign({}, info.value);
genTable.columns = columns.value;
genTable.params = {
treeCode: info.value?.treeCode,
treeName: info.value.treeName,
treeParentCode: info.value.treeParentCode,
parentMenuId: info.value.parentMenuId
};
const response = await updateGenTable(genTable);
proxy?.$modal.msgSuccess(response.msg);
if (response.code === 200) {
close();
}
} else {
proxy?.$modal.msgError("表单校验未通过,请重新检查提交内容");
}
});
Promise.all([basicForm, genForm].map(getFormPromise)).then(async res => {
const validateResult = res.every(item => !!item);
if (validateResult) {
const genTable: any = Object.assign({}, info.value);
genTable.columns = columns.value;
genTable.params = {
treeCode: info.value?.treeCode,
treeName: info.value.treeName,
treeParentCode: info.value.treeParentCode,
parentMenuId: info.value.parentMenuId
};
const response = await updateGenTable(genTable);
proxy?.$modal.msgSuccess(response.msg);
if (response.code === 200) {
close();
}
} else {
proxy?.$modal.msgError("表单校验未通过,请重新检查提交内容");
}
});
}
const getFormPromise = (form: any) => {
return new Promise(resolve => {
form.validate((res: any) => {
resolve(res);
});
return new Promise(resolve => {
form.validate((res: any) => {
resolve(res);
});
});
}
const close = () => {
const obj = { path: "/tool/gen", query: { t: Date.now(), pageNum: route.query.pageNum } };
proxy?.$tab.closeOpenPage(obj);
const obj = {path: "/tool/gen", query: {t: Date.now(), pageNum: route.query.pageNum}};
proxy?.$tab.closeOpenPage(obj);
}
(async () => {
const tableId = route.params && route.params.tableId as string;
if (tableId) {
//
const res = await getGenTable(tableId);
res.data.info.parentMenuId = Number(res.data.info.parentMenuId);
columns.value = res.data.rows;
info.value = res.data.info;
tables.value = res.data.tables;
/** 查询字典下拉列表 */
const response = await getDictOptionselect();
dictOptions.value = response.data;
}
const tableId = route.params && route.params.tableId as string;
if (tableId) {
//
const res = await getGenTable(tableId);
columns.value = res.data.rows;
info.value = res.data.info;
tables.value = res.data.tables;
/** 查询字典下拉列表 */
const response = await getDictOptionselect();
dictOptions.value = response.data;
}
})();
</script>

View File

@ -226,9 +226,9 @@ import { listMenu } from '@/api/system/menu';
import { ComponentInternalInstance, PropType } from 'vue';
interface MenuOptionsType {
menuId: number;
menuName: string;
children: MenuOptionsType[] | undefined;
menuId: number | string;
menuName: string;
children: MenuOptionsType[] | undefined;
}
const subColumns = ref<any>([]);
@ -236,14 +236,14 @@ const menuOptions = ref<Array<MenuOptionsType>>([]);
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const props = defineProps({
info: {
type: Object as PropType<any>,
default: null
},
tables: {
type: Array as PropType<any[]>,
default: null
}
info: {
type: Object as PropType<any>,
default: null
},
tables: {
type: Array as PropType<any[]>,
default: null
}
});
const infoForm = computed(() => props.info);
@ -252,45 +252,46 @@ const table = computed(() => props.tables);
//
const rules = ref({
tplCategory: [{ required: true, message: "请选择生成模板", trigger: "blur" }],
packageName: [{ required: true, message: "请输入生成包路径", trigger: "blur" }],
moduleName: [{ required: true, message: "请输入生成模块名", trigger: "blur" }],
businessName: [{ required: true, message: "请输入生成业务名", trigger: "blur" }],
functionName: [{ required: true, message: "请输入生成功能名", trigger: "blur" }]
tplCategory: [{required: true, message: "请选择生成模板", trigger: "blur"}],
packageName: [{required: true, message: "请输入生成包路径", trigger: "blur"}],
moduleName: [{required: true, message: "请输入生成模块名", trigger: "blur"}],
businessName: [{required: true, message: "请输入生成业务名", trigger: "blur"}],
functionName: [{required: true, message: "请输入生成功能名", trigger: "blur"}]
});
const subSelectChange = () => {
infoForm.value.subTableFkName = "";
infoForm.value.subTableFkName = "";
}
const tplSelectChange = (value: string) => {
if (value !== "sub") {
infoForm.value.subTableName = "";
infoForm.value.subTableFkName = "";
}
if (value !== "sub") {
infoForm.value.subTableName = "";
infoForm.value.subTableFkName = "";
}
}
const setSubTableColumns = (value: string) => {
table.value.forEach(item => {
const name = item.tableName;
if (value === name) {
subColumns.value = item.columns;
return;
}
})
table.value.forEach(item => {
const name = item.tableName;
if (value === name) {
subColumns.value = item.columns;
return;
}
})
}
/** 查询菜单下拉树结构 */
const getMenuTreeselect = async () => {
const res = await listMenu();
const data = proxy?.handleTree<MenuOptionsType>(res.data, "menuId");
const res = await listMenu();
res.data.forEach(m => m.menuId = m.menuId.toString());
const data = proxy?.handleTree<MenuOptionsType>(res.data, "menuId");
if (data) {
menuOptions.value = data
}
menuOptions.value = data
}
}
watch(() => props.info.subTableName, val => {
setSubTableColumns(val);
setSubTableColumns(val);
});
onMounted(() => {
getMenuTreeselect();
getMenuTreeselect();
})
</script>