Merge branch 'ts' into future/flowable

This commit is contained in:
gssong 2023-09-22 23:23:38 +08:00
commit f4684fb0dc
45 changed files with 241 additions and 187 deletions

View File

@ -30,7 +30,7 @@ module.exports = {
extendDefaults: true,
types: {
'{}': false,
'Function': false
Function: false
}
}
]

View File

@ -2,45 +2,45 @@
* 代码格式化配置
*/
module.exports = {
// 一行最多多少个字符
printWidth: 150,
// 指定每个缩进级别的空格数
tabWidth: 2,
// 使用制表符而不是空格缩进行
useTabs: false,
// 在语句末尾是否需要分号
semi: true,
// 是否使用单引号
singleQuote: true,
// 更改引用对象属性的时间 可选值"<as-needed|consistent|preserve>"
quoteProps: 'as-needed',
// 在JSX中使用单引号而不是双引号
jsxSingleQuote: false,
// 多行时尽可能打印尾随逗号。(例如,单行数组永远不会出现逗号结尾。) 可选值"<none|es5|all>"默认none
trailingComma: 'none',
// 在对象文字中的括号之间打印空格
bracketSpacing: true,
// jsx 标签的反尖括号需要换行
jsxBracketSameLine: false,
embeddedLanguageFormatting: 'off',
// 在单独的箭头函数参数周围包括括号 always(x) => x \ avoidx => x
arrowParens: 'always',
// 这两个选项可用于格式化以给定字符偏移量(分别包括和不包括)开始和结束的代码
rangeStart: 0,
rangeEnd: Infinity,
// 指定要使用的解析器,不需要写文件开头的 @prettier
requirePragma: false,
// 不需要自动在文件开头插入 @prettier
insertPragma: false,
// 使用默认的折行标准 always\never\preserve
proseWrap: 'preserve',
// 指定HTML文件的全局空格敏感度 css\strict\ignore
htmlWhitespaceSensitivity: 'css',
// Vue文件脚本和样式标签缩进
vueIndentScriptAndStyle: false,
// 在 windows 操作系统中换行符通常是回车 (CR) 加换行分隔符 (LF),也就是回车换行(CRLF)
// 然而在 Linux 和 Unix 中只使用简单的换行分隔符 (LF)。
// 对应的控制字符为 "\n" (LF) 和 "\r\n"(CRLF)。auto意为保持现有的行尾
// 换行符使用 lf 结尾是 可选值"<auto|lf|crlf|cr>"
endOfLine: 'auto'
// 一行最多多少个字符
printWidth: 150,
// 指定每个缩进级别的空格数
tabWidth: 2,
// 使用制表符而不是空格缩进行
useTabs: false,
// 在语句末尾是否需要分号
semi: true,
// 是否使用单引号
singleQuote: true,
// 更改引用对象属性的时间 可选值"<as-needed|consistent|preserve>"
quoteProps: 'as-needed',
// 在JSX中使用单引号而不是双引号
jsxSingleQuote: false,
// 多行时尽可能打印尾随逗号。(例如,单行数组永远不会出现逗号结尾。) 可选值"<none|es5|all>"默认none
trailingComma: 'none',
// 在对象文字中的括号之间打印空格
bracketSpacing: true,
// jsx 标签的反尖括号需要换行
jsxBracketSameLine: false,
embeddedLanguageFormatting: 'off',
// 在单独的箭头函数参数周围包括括号 always(x) => x \ avoidx => x
arrowParens: 'always',
// 这两个选项可用于格式化以给定字符偏移量(分别包括和不包括)开始和结束的代码
rangeStart: 0,
rangeEnd: Infinity,
// 指定要使用的解析器,不需要写文件开头的 @prettier
requirePragma: false,
// 不需要自动在文件开头插入 @prettier
insertPragma: false,
// 使用默认的折行标准 always\never\preserve
proseWrap: 'preserve',
// 指定HTML文件的全局空格敏感度 css\strict\ignore
htmlWhitespaceSensitivity: 'css',
// Vue文件脚本和样式标签缩进
vueIndentScriptAndStyle: false,
// 在 windows 操作系统中换行符通常是回车 (CR) 加换行分隔符 (LF),也就是回车换行(CRLF)
// 然而在 Linux 和 Unix 中只使用简单的换行分隔符 (LF)。
// 对应的控制字符为 "\n" (LF) 和 "\r\n"(CRLF)。auto意为保持现有的行尾
// 换行符使用 lf 结尾是 可选值"<auto|lf|crlf|cr>"
endOfLine: 'auto'
};

20
LICENSE Normal file
View File

@ -0,0 +1,20 @@
The MIT License (MIT)
Copyright (c) 2019 RuoYi-Vue-Plus
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@ -76,7 +76,7 @@
"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",
"unplugin-vue-setup-extend-plus": "0.4.9",
"vitest": "^0.29.7",
"vue-eslint-parser": "9.1.0",
"vue-tsc": "0.35.0"

View File

@ -32,7 +32,8 @@ export function register(data: any) {
return request({
url: '/auth/register',
headers: {
isToken: false
isToken: false,
isEncrypt: true
},
method: 'post',
data: data

View File

@ -43,7 +43,6 @@ export interface ClientVO {
* 0 1
*/
status: string;
}
export interface ClientForm extends BaseEntity {
@ -91,7 +90,6 @@ export interface ClientForm extends BaseEntity {
* 0 1
*/
status?: string;
}
export interface ClientQuery extends PageQuery {
@ -134,5 +132,4 @@ export interface ClientQuery extends PageQuery {
* 0 1
*/
status?: string;
}

View File

@ -24,6 +24,9 @@ export function addTenant(data: TenantForm) {
return request({
url: '/system/tenant',
method: 'post',
headers: {
isEncrypt: true
},
data: data
});
}

View File

@ -74,6 +74,9 @@ export const resetUserPwd = (userId: string | number, password: string) => {
return request({
url: '/system/user/resetPwd',
method: 'put',
headers: {
isEncrypt: true
},
data: data
});
};
@ -130,6 +133,9 @@ export const updateUserPwd = (oldPassword: string, newPassword: string) => {
return request({
url: '/system/user/profile/updatePwd',
method: 'put',
headers: {
isEncrypt: true
},
params: data
});
};
@ -175,8 +181,8 @@ export const updateAuthRole = (data: { userId: string; roleIds: string }) => {
*/
export const listUserByDeptId = (deptId: string | number): AxiosPromise<UserVO[]> => {
return request({
url: "/system/user/list/dept/" + deptId,
method: "get"
url: '/system/user/list/dept/' + deptId,
method: 'get'
});
};

View File

@ -37,7 +37,7 @@ export const updateGenTable = (data: DbTableForm) => {
};
// 导入表
export const importTable = (data: { tables: string, dataName: string }) => {
export const importTable = (data: { tables: string; dataName: string }) => {
return request({
url: '/tool/gen/importTable',
method: 'post',
@ -83,4 +83,4 @@ export const getDataNames = () => {
url: '/tool/gen/getDataNames',
method: 'get'
});
};
};

View File

@ -78,8 +78,6 @@
overflow-x: hidden;
}
// refine element ui upload
.upload-container {
.el-upload {
@ -109,10 +107,10 @@
box-sizing: content-box;
}
.el-menu--collapse>div>.el-submenu>.el-submenu__title .el-submenu__icon-arrow {
.el-menu--collapse > div > .el-submenu > .el-submenu__title .el-submenu__icon-arrow {
display: none;
}
.el-dropdown .el-dropdown-link {
color: var(--el-color-primary) !important;
}
}

View File

@ -26,7 +26,8 @@ html {
box-sizing: border-box;
}
html.dark .svg-icon, html.dark svg {
html.dark .svg-icon,
html.dark svg {
fill: var(--el-text-color-regular);
}

View File

@ -81,10 +81,16 @@
}
// menu hover
.theme-dark .sub-menu-title-noDropdown,
.theme-dark .el-sub-menu__title {
&:hover {
background-color: $base-sub-menu-title-hover !important;
}
}
.sub-menu-title-noDropdown,
.el-sub-menu__title {
&:hover {
background-color: $base-sub-menu-title-hover !important;
background-color: rgba(0, 0, 0, 0.05) !important;
}
}
@ -95,12 +101,12 @@
& .nest-menu .el-sub-menu > .el-sub-menu__title,
& .el-sub-menu .el-menu-item {
min-width: $base-sidebar-width !important;
&:hover {
background-color: rgba(0, 0, 0, 0.06) !important;
background-color: rgba(0, 0, 0, 0.1) !important;
}
}
& .theme-dark .nest-menu .el-sub-menu > .el-sub-menu__title,
& .theme-dark .el-sub-menu .el-menu-item {
background-color: $base-sub-menu-background !important;
@ -109,6 +115,21 @@
background-color: $base-sub-menu-hover !important;
}
}
& .theme-dark .nest-menu .el-sub-menu > .el-sub-menu__title,
& .theme-dark .el-menu-item {
&:hover {
// you can use $sub-menuHover
background-color: $base-menu-hover !important;
}
}
& .nest-menu .el-sub-menu > .el-sub-menu__title,
& .el-menu-item {
&:hover {
// you can use $sub-menuHover
background-color: rgba(0, 0, 0, 0.04) !important;
}
}
}
.hideSidebar {
@ -207,14 +228,6 @@
}
}
.nest-menu .el-sub-menu > .el-sub-menu__title,
.el-menu-item {
&:hover {
// you can use $sub-menuHover
background-color: $base-menu-hover !important;
}
}
// the scroll bar appears when the sub-menu is too long
> .el-menu--popup {
max-height: 100vh;

View File

@ -4,11 +4,11 @@
const props = defineProps({
formJson: {
type: [String, Object],
default: {}
default: ""
},
formData: {
type: [String, Object],
default: {}
default: ""
},
isView: {
type: Boolean,

View File

@ -2,7 +2,8 @@
<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">
<span v-if="(item.elTagType == 'default' || item.elTagType == '') && (item.elTagClass == '' || item.elTagClass == null)"
:key="item.value" :index="index" :class="item.elTagClass">
{{ item.label + " " }}
</span>
<el-tag
@ -37,46 +38,33 @@ const props = defineProps({
value: [Number, String, Array] as PropType<number | string | Array<number | string>>,
// value
showValue: propTypes.bool.def(true),
separator: propTypes.string.def(","),
});
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 === '' || props.value === null || typeof props.value === "undefined") return []
return Array.isArray(props.value) ? props.value.map(item => '' + item) : String(props.value).split(props.separator);
});
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;
if (props.options?.length == 0 || props.value === '' || props.value === null || typeof props.value === "undefined") return false
//
values.value.forEach(item => {
if (!props.options.some(v => v.value === item)) {
return true // true
}
return true;
}
// value
return false;
})
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);
}
});
}
if (props.value !== '' && props.value !== null && typeof props.value !== "undefined") {
values.value.forEach(item => {
if (!props.options.some(v => v.value === item)) {
itemUnmatchArray.push(item);
}
})
}
// value
return handleArray(itemUnmatchArray);

View File

@ -68,6 +68,10 @@ const selectedIcon = (iconName: string) => {
</script>
<style scoped lang="scss">
.el-scrollbar {
max-height: calc(50vh - 100px)!important;
overflow-y: auto;
}
.el-divider--horizontal {
margin: 10px auto !important;
}

View File

@ -2,7 +2,9 @@
<el-menu :default-active="activeMenu" mode="horizontal" @select="handleSelect" :ellipsis="false">
<template v-for="(item, index) in topMenus">
<el-menu-item :style="{'--theme': theme}" :index="item.path" :key="index" v-if="index < visibleNumber"
><svg-icon :icon-class="item.meta ? item.meta.icon : '' " /> {{ item.meta?.title }}</el-menu-item
><svg-icon
v-if="item.meta && item.meta.icon && item.meta.icon !== '#'"
:icon-class="item.meta ? item.meta.icon : '' " /> {{ item.meta?.title }}</el-menu-item
>
</template>
@ -180,4 +182,14 @@ onMounted(() => {
padding: 0 5px !important;
margin: 0 10px !important;
}
/* 背景色隐藏 */
.topmenu-container.el-menu--horizontal>.el-menu-item:not(.is-disabled):focus, .topmenu-container.el-menu--horizontal>.el-menu-item:not(.is-disabled):hover, .topmenu-container.el-menu--horizontal>.el-submenu .el-submenu__title:hover {
background-color: #ffffff !important;
}
/* 图标右间距 */
.topmenu-container .svg-icon {
margin-right: 4px;
}
</style>

View File

@ -0,0 +1,4 @@
export enum SideThemeEnum {
DARK = 'theme-dark',
LIGHT = 'theme-light'
}

View File

@ -15,4 +15,4 @@ const props = defineProps({
}
});
const height = ref(document.documentElement.clientHeight - 94.5 + "px");
</script>
</script>

View File

@ -58,7 +58,7 @@
<router-link to="/user/profile" v-if="!dynamic">
<el-dropdown-item>{{ $t('navbar.personalCenter') }}</el-dropdown-item>
</router-link>
<el-dropdown-item command="setLayout">
<el-dropdown-item command="setLayout" v-if="settingsStore.showSettings">
<span>{{ $t('navbar.layoutSetting') }}</span>
</el-dropdown-item>
<el-dropdown-item divided command="logout">
@ -73,7 +73,7 @@
</template>
<script setup lang="ts">
import SearchMenu from './topBar/search.vue';
import SearchMenu from './TopBar/search.vue';
import useAppStore from '@/store/modules/app';
import useUserStore from '@/store/modules/user';
import useSettingsStore from '@/store/modules/settings';

View File

@ -3,7 +3,7 @@
<h3 class="drawer-title">主题风格设置</h3>
<div class="setting-drawer-block-checbox">
<div class="setting-drawer-block-checbox-item" @click="handleTheme('theme-dark')">
<div class="setting-drawer-block-checbox-item" @click="handleTheme(SideThemeEnum.DARK)">
<img src="@/assets/images/dark.svg" alt="dark" />
<div v-if="sideTheme === 'theme-dark'" class="setting-drawer-block-checbox-selectIcon" style="display: block;">
<i aria-label="图标: check" class="anticon anticon-check">
@ -15,7 +15,7 @@
</i>
</div>
</div>
<div class="setting-drawer-block-checbox-item" @click="handleTheme('theme-light')">
<div class="setting-drawer-block-checbox-item" @click="handleTheme(SideThemeEnum.LIGHT)">
<img src="@/assets/images/light.svg" alt="light" />
<div v-if="sideTheme === 'theme-light'" class="setting-drawer-block-checbox-selectIcon" style="display: block;">
<i aria-label="图标: check" class="anticon anticon-check">
@ -95,6 +95,7 @@ import usePermissionStore from '@/store/modules/permission'
import { handleThemeStyle } from '@/utils/theme'
import { ComponentInternalInstance } from "vue";
import { SettingTypeEnum } from "@/enums/SettingTypeEnum";
import { SideThemeEnum } from "@/enums/SideThemeEnum";
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const appStore = useAppStore()
@ -114,6 +115,13 @@ const isDark = useDark({
valueDark: 'dark',
valueLight: 'light',
});
watch(isDark, ()=> {
if (isDark.value) {
settingsStore.changeSetting({ key: SettingTypeEnum.SIDE_THEME, value: SideThemeEnum.DARK })
} else {
settingsStore.changeSetting({ key: SettingTypeEnum.SIDE_THEME, value: sideTheme.value })
}
})
const toggleDark = () => useToggle(isDark);
/** 是否需要topNav */
@ -166,8 +174,13 @@ const themeChange = (val: string | null) => {
}
}
const handleTheme = (val: string) => {
settingsStore.changeSetting({ key: SettingTypeEnum.SIDE_THEME, value: val })
sideTheme.value = val;
if (isDark.value && val === SideThemeEnum.LIGHT) {
//
settingsStore.changeSetting({ key: SettingTypeEnum.SIDE_THEME, value: SideThemeEnum.DARK })
return
}
settingsStore.changeSetting({ key: SettingTypeEnum.SIDE_THEME, value: val })
}
const saveSetting = () => {
proxy?.$modal.loading("正在保存到本地,请稍候...");

View File

@ -27,7 +27,6 @@ import variables from '@/assets/styles/variables.module.scss'
import useAppStore from '@/store/modules/app'
import useSettingsStore from '@/store/modules/settings'
import usePermissionStore from '@/store/modules/permission'
import { ComponentInternalInstance } from "vue";
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const route = useRoute();

View File

@ -4,9 +4,7 @@
<script setup lang="ts">
import { login, callback } from '@/api/login';
import { setToken } from '@/utils/auth';
import Cookies from 'js-cookie';
import { getToken } from '@/utils/auth';
import { setToken, getToken } from '@/utils/auth';
import { LoginData } from '@/api/types';
const route = useRoute();
@ -20,7 +18,7 @@ const loading = ref(true);
const code = route.query.code as string;
const state = route.query.state as string;
const source = route.query.source as string;
const tenantId = Cookies.get("tenantId") ? Cookies.get("tenantId") as string : '000000';
const tenantId = localStorage.getItem("tenantId") ? localStorage.getItem("tenantId") as string : '000000';
const processResponse = async (res: any) => {

View File

@ -278,7 +278,7 @@ onMounted(() => {
height: 8px;
border-radius: 50%;
position: relative;
margin-right: 2px;
margin-right: 5px;
}
}
}

View File

@ -3,7 +3,7 @@ import FileSaver from 'file-saver';
import errorCode from '@/utils/errorCode';
import { blobValidate } from '@/utils/ruoyi';
import { LoadingInstance } from 'element-plus/es/components/loading/src/loading';
import { globalHeaders } from "@/utils/request";
import { globalHeaders } from '@/utils/request';
const baseURL = import.meta.env.VITE_APP_BASE_API;
let downloadLoadingInstance: LoadingInstance;
@ -16,7 +16,7 @@ export default {
method: 'get',
url: url,
responseType: 'blob',
headers: globalHeaders(),
headers: globalHeaders()
});
const isBlob = blobValidate(res.data);
if (isBlob) {
@ -40,7 +40,7 @@ export default {
method: 'get',
url: url,
responseType: 'blob',
headers: globalHeaders(),
headers: globalHeaders()
});
const isBlob = blobValidate(res.data);
if (isBlob) {

View File

@ -181,5 +181,4 @@ const router = createRouter({
}
});
export default router;

View File

@ -13,7 +13,7 @@ const setting: DefaultSettings = {
/**
*
*/
showSettings: false,
showSettings: true,
/**
*

View File

@ -11,13 +11,13 @@ export const useSettingsStore = defineStore('setting', () => {
title: ref<string>(''),
theme: ref<string>(storageSetting.theme || defaultSettings.theme),
sideTheme: ref<string>(storageSetting.sideTheme || defaultSettings.sideTheme),
showSettings: ref<boolean>(storageSetting.showSettings),
topNav: ref<boolean>(storageSetting.topNav || defaultSettings.topNav),
tagsView: ref<boolean>(storageSetting.tagsView || defaultSettings.tagsView),
fixedHeader: ref<boolean>(storageSetting.fixedHeader || defaultSettings.fixedHeader),
sidebarLogo: ref<boolean>(storageSetting.sidebarLogo || defaultSettings.sidebarLogo),
dynamicTitle: ref<boolean>(storageSetting.dynamicTitle || defaultSettings.dynamicTitle),
animationEnable: ref<boolean>(storageSetting.animationEnable || defaultSettings.animationEnable),
showSettings: ref<boolean>(storageSetting.showSettings || defaultSettings.showSettings),
topNav: ref<boolean>(storageSetting.topNav === undefined ? defaultSettings.topNav : storageSetting.topNav),
tagsView: ref<boolean>(storageSetting.tagsView === undefined ? defaultSettings.tagsView : storageSetting.tagsView),
fixedHeader: ref<boolean>(storageSetting.fixedHeader === undefined ? defaultSettings.fixedHeader : storageSetting.fixedHeader),
sidebarLogo: ref<boolean>(storageSetting.sidebarLogo === undefined ? defaultSettings.sidebarLogo : storageSetting.sidebarLogo),
dynamicTitle: ref<boolean>(storageSetting.dynamicTitle === undefined ? defaultSettings.dynamicTitle : storageSetting.dynamicTitle),
animationEnable: ref<boolean>(storageSetting.animationEnable === undefined ? defaultSettings.animationEnable : storageSetting.animationEnable),
dark: ref<boolean>(storageSetting.dark || defaultSettings.dark)
};

View File

@ -16,10 +16,10 @@ let downloadLoadingInstance: LoadingInstance;
export const isRelogin = { show: false };
export const globalHeaders = () => {
return {
Authorization: "Bearer " + getToken(),
Authorization: 'Bearer ' + getToken(),
clientid: import.meta.env.VITE_APP_CLIENT_ID
}
}
};
};
axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8';
axios.defaults.headers['clientid'] = import.meta.env.VITE_APP_CLIENT_ID;

View File

@ -68,7 +68,7 @@ export const validAlphabets = (str: string) => {
*/
export const validEmail = (email: string) => {
const reg =
/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
/^(([^<>()\]\\.,;:\s@"]+(\.[^<>()\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
return reg.test(email);
};

View File

@ -5,19 +5,19 @@
<el-card shadow="hover">
<el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
<el-form-item label="部门id" prop="deptId">
<el-input v-model="queryParams.deptId" placeholder="请输入部门id" clearable @keyup.enter="handleQuery" />
<el-input v-model="queryParams.deptId" placeholder="请输入部门id" clearable style="width: 240px" @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="用户id" prop="userId">
<el-input v-model="queryParams.userId" placeholder="请输入用户id" clearable @keyup.enter="handleQuery" />
<el-input v-model="queryParams.userId" placeholder="请输入用户id" clearable style="width: 240px" @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="排序号" prop="orderNum">
<el-input v-model="queryParams.orderNum" placeholder="请输入排序号" clearable @keyup.enter="handleQuery" />
<el-input v-model="queryParams.orderNum" placeholder="请输入排序号" clearable style="width: 240px" @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="key键" prop="testKey">
<el-input v-model="queryParams.testKey" placeholder="请输入key键" clearable @keyup.enter="handleQuery" />
<el-input v-model="queryParams.testKey" placeholder="请输入key键" clearable style="width: 240px" @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="值" prop="value">
<el-input v-model="queryParams.value" placeholder="请输入值" clearable @keyup.enter="handleQuery" />
<el-input v-model="queryParams.value" placeholder="请输入值" clearable style="width: 240px" @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>

View File

@ -5,7 +5,7 @@
<el-card shadow="hover">
<el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
<el-form-item label="树节点名" prop="treeName">
<el-input v-model="queryParams.treeName" placeholder="请输入树节点名" clearable @keyup.enter="handleQuery" />
<el-input v-model="queryParams.treeName" placeholder="请输入树节点名" clearable style="width: 240px" @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>

View File

@ -61,7 +61,6 @@
<script setup lang="ts">
import { getCodeImg, getTenantList } from '@/api/login';
import { authBinding } from '@/api/system/social/auth';
import Cookies from 'js-cookie';
import { useUserStore } from '@/store/modules/user';
import { LoginData, TenantVO } from '@/api/types';
import { to } from 'await-to-js';
@ -101,27 +100,32 @@ const loginRef = ref<ElFormInstance>();
//
const tenantList = ref<TenantVO[]>([]);
watch(() => router.currentRoute.value, (newRoute: any) => {
redirect.value = newRoute.query && newRoute.query.redirect;
}, { immediate: true });
const handleLogin = () => {
loginRef.value?.validate(async (valid: boolean, fields: any) => {
if (valid) {
loading.value = true;
// cookie
// localStorage
if (loginForm.value.rememberMe) {
Cookies.set("tenantId", String(loginForm.value.tenantId), { expires: 30 });
Cookies.set('username', String(loginForm.value.username), { expires: 30 });
Cookies.set('password', String(loginForm.value.password), { expires: 30 });
Cookies.set('rememberMe', String(loginForm.value.rememberMe), { expires: 30 });
localStorage.setItem("tenantId", String(loginForm.value.tenantId));
localStorage.setItem('username', String(loginForm.value.username));
localStorage.setItem('password', String(loginForm.value.password));
localStorage.setItem('rememberMe', String(loginForm.value.rememberMe));
} else {
//
Cookies.remove("tenantId");
Cookies.remove('username');
Cookies.remove('password');
Cookies.remove('rememberMe');
localStorage.removeItem("tenantId");
localStorage.removeItem('username');
localStorage.removeItem('password');
localStorage.removeItem('rememberMe');
}
// action
const [err] = await to(userStore.login(loginForm.value));
if (!err) {
await router.push({ path: redirect.value || '/' });
loading.value = false;
} else {
loading.value = false;
//
@ -148,16 +152,16 @@ const getCode = async () => {
}
};
const getCookie = () => {
const tenantId = Cookies.get("tenantId");
const username = Cookies.get('username');
const password = Cookies.get('password');
const rememberMe = Cookies.get('rememberMe');
const getLoginData = () => {
const tenantId = localStorage.getItem("tenantId");
const username = localStorage.getItem('username');
const password = localStorage.getItem('password');
const rememberMe = localStorage.getItem('rememberMe');
loginForm.value = {
tenantId: tenantId === undefined ? String(loginForm.value.tenantId) : tenantId,
username: username === undefined ? String(loginForm.value.username) : username,
password: password === undefined ? String(loginForm.value.password) : String(password),
rememberMe: rememberMe === undefined ? false : Boolean(rememberMe)
tenantId: tenantId === null ? String(loginForm.value.tenantId) : tenantId,
username: username === null ? String(loginForm.value.username) : username,
password: password === null ? String(loginForm.value.password) : String(password),
rememberMe: rememberMe === null ? false : Boolean(rememberMe)
} as LoginData;
}
@ -178,7 +182,7 @@ const initTenantList = async () => {
//
watch(() => loginForm.value.tenantId, () => {
Cookies.set("tenantId", String(loginForm.value.tenantId), { expires: 30 })
localStorage.setItem("tenantId", String(loginForm.value.tenantId))
});
/**
@ -201,7 +205,7 @@ const doSocialLogin = (type: string) => {
onMounted(() => {
getCode();
initTenantList();
getCookie();
getLoginData();
});
</script>

View File

@ -4,10 +4,10 @@
<div class="search" v-show="showSearch">
<el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="100px">
<el-form-item label="客户端key" prop="clientKey">
<el-input v-model="queryParams.clientKey" placeholder="请输入客户端key" clearable @keyup.enter="handleQuery" />
<el-input v-model="queryParams.clientKey" placeholder="请输入客户端key" clearable style="width: 240px" @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="客户端秘钥" prop="clientSecret">
<el-input v-model="queryParams.clientSecret" placeholder="请输入客户端秘钥" clearable @keyup.enter="handleQuery" />
<el-input v-model="queryParams.clientSecret" placeholder="请输入客户端秘钥" clearable style="width: 240px" @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select v-model="queryParams.status" placeholder="状态" clearable>
@ -53,11 +53,7 @@
<el-table-column label="客户端秘钥" align="center" prop="clientSecret" />
<el-table-column label="授权类型" align="center">
<template #default="scope">
<div>
<template v-for="(type, index) in scope.row.grantTypeList" :key="index">
<dict-tag class="el-check-tag" :options="sys_grant_type" :value="type" />
</template>
</div>
<dict-tag :options="sys_grant_type" :value="scope.row.grantTypeList" />
</template>
</el-table-column>
<el-table-column label="设备类型" align="center">

View File

@ -5,7 +5,7 @@
<el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" :inline="true" label-width="68px">
<el-form-item label="部门名称" prop="deptName">
<el-input v-model="queryParams.deptName" placeholder="请输入部门名称" clearable @keyup.enter="handleQuery" />
<el-input v-model="queryParams.deptName" placeholder="请输入部门名称" clearable style="width: 240px" @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select v-model="queryParams.status" placeholder="部门状态" clearable>
@ -116,7 +116,7 @@
<el-form-item label="部门状态">
<el-radio-group v-model="form.status">
<el-radio v-for="dict in sys_normal_disable" :key="dict.value" :label="dict.value">{{ dict.label
}}</el-radio>
}}</el-radio>
</el-radio-group>
</el-form-item>
</el-col>

View File

@ -49,9 +49,8 @@
<el-table-column label="字典编码" align="center" prop="dictCode" v-if="false" />
<el-table-column label="字典标签" align="center" prop="dictLabel">
<template #default="scope">
<span v-if="scope.row.listClass === '' || scope.row.listClass === 'default'">{{ scope.row.dictLabel }}</span>
<el-tag v-else :type="scope.row.listClass === 'primary' ? '' : scope.row.listClass">{{ scope.row.dictLabel
}}</el-tag>
<span v-if="(scope.row.listClass == '' || scope.row.listClass == 'default') && (scope.row.cssClass == '' || scope.row.cssClass == null)">{{ scope.row.dictLabel }}</span>
<el-tag v-else :type="scope.row.listClass == 'primary' ? '' : scope.row.listClass" :class="scope.row.cssClass">{{ scope.row.dictLabel }}</el-tag>
</template>
</el-table-column>
<el-table-column label="字典键值" align="center" prop="dictValue" />

View File

@ -5,7 +5,7 @@
<el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" :inline="true" label-width="68px">
<el-form-item label="菜单名称" prop="menuName">
<el-input v-model="queryParams.menuName" placeholder="请输入菜单名称" clearable @keyup.enter="handleQuery" />
<el-input v-model="queryParams.menuName" placeholder="请输入菜单名称" clearable style="width: 240px" @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select v-model="queryParams.status" placeholder="菜单状态" clearable>

View File

@ -5,16 +5,16 @@
<el-card shadow="hover">
<el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
<el-form-item label="租户编号" prop="tenantId">
<el-input v-model="queryParams.tenantId" placeholder="请输入租户编号" clearable @keyup.enter="handleQuery" />
<el-input v-model="queryParams.tenantId" placeholder="请输入租户编号" clearable style="width: 240px" @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="联系人" prop="contactUserName">
<el-input v-model="queryParams.contactUserName" placeholder="请输入联系人" clearable @keyup.enter="handleQuery" />
<el-input v-model="queryParams.contactUserName" placeholder="请输入联系人" clearable style="width: 240px" @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="联系电话" prop="contactPhone">
<el-input v-model="queryParams.contactPhone" placeholder="请输入联系电话" clearable @keyup.enter="handleQuery" />
<el-input v-model="queryParams.contactPhone" placeholder="请输入联系电话" clearable style="width: 240px" @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="企业名称" prop="companyName">
<el-input v-model="queryParams.companyName" placeholder="请输入企业名称" clearable @keyup.enter="handleQuery" />
<el-input v-model="queryParams.companyName" placeholder="请输入企业名称" clearable style="width: 240px" @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>

View File

@ -5,7 +5,7 @@
<el-card shadow="hover">
<el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
<el-form-item label="套餐名称" prop="packageName">
<el-input v-model="queryParams.packageName" placeholder="请输入套餐名称" clearable @keyup.enter="handleQuery" />
<el-input v-model="queryParams.packageName" placeholder="请输入套餐名称" clearable style="width: 240px" @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>

View File

@ -299,7 +299,6 @@
<script setup name="User" lang="ts">
import api from "@/api/system/user"
import { UserForm, UserQuery, UserVO } from '@/api/system/user/types';
import { getToken } from "@/utils/auth";
import { treeselect } from "@/api/system/dept";
import { DeptVO } from "@/api/system/dept/types";
import { RoleVO } from "@/api/system/role/types";

View File

@ -10,7 +10,7 @@
</template>
<div>
<div class="text-center">
<userAvatar :user="state.user" />
<userAvatar/>
</div>
<ul class="list-group list-group-striped">
<li class="list-group-item">
@ -66,10 +66,10 @@
</template>
<script setup name="Profile" lang="ts">
import userAvatar from "./userAvatar.vue";
import userInfo from "./userInfo.vue";
import resetPwd from "./resetPwd.vue";
import thirdParty from "./thirdParty.vue";
import UserAvatar from "./userAvatar.vue";
import UserInfo from "./userInfo.vue";
import ResetPwd from "./resetPwd.vue";
import ThirdParty from "./thirdParty.vue";
import { getAuthList } from "@/api/system/social/auth";
import { getUserProfile } from "@/api/system/user";

View File

@ -5,7 +5,7 @@ import createComponents from './components';
import createIcons from './icons';
import createSvgIconsPlugin from './svg-icon';
import createCompression from './compression';
import createVueSetupExtend from './vue-setup-extend';
import createSetupExtend from './setup-extend';
import path from 'path';
export default (viteEnv: any, isBuild = false): [] => {
@ -17,6 +17,6 @@ export default (viteEnv: any, isBuild = false): [] => {
vitePlusgins.push(createCompression(viteEnv));
vitePlusgins.push(createIcons());
vitePlusgins.push(createSvgIconsPlugin(path, isBuild));
vitePlusgins.push(createVueSetupExtend());
vitePlusgins.push(createSetupExtend());
return vitePlusgins;
};

View File

@ -0,0 +1,5 @@
import setupExtend from 'unplugin-vue-setup-extend-plus/vite'
export default () => {
return setupExtend({})
};

View File

@ -9,6 +9,6 @@ export default () => {
'panel-title':
'pb-[5px] font-sans leading-[1.1] font-medium text-base text-[#6379bb] border-b border-b-solid border-[var(--el-border-color-light)] mb-5 mt-0'
},
hmrTopLevelAwait: false, // unocss默认是true低版本浏览器是不支持的启动后会报错
hmrTopLevelAwait: false // unocss默认是true低版本浏览器是不支持的启动后会报错
});
};

View File

@ -1,5 +0,0 @@
import VueSetupExtend from 'vite-plugin-vue-setup-extend';
export default () => {
return VueSetupExtend();
};