mirror of
https://github.com/thousmile/molly-multi-tenant.git
synced 2025-12-30 04:32:26 +00:00
修改,操作其他租户时,无法修改密码和个人信息
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,6 +1,5 @@
|
||||
HELP.md
|
||||
target/
|
||||
server/molly-service/src/main/resources/application-dev.yml
|
||||
|
||||
### STS ###
|
||||
.apt_generated
|
||||
|
||||
31
server/.gitignore
vendored
31
server/.gitignore
vendored
@@ -1,31 +0,0 @@
|
||||
HELP.md
|
||||
target/
|
||||
molly-service/src/main/resources/application-dev.yml
|
||||
|
||||
### STS ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
build/
|
||||
!**/src/main/**/build/
|
||||
!**/src/test/**/build/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
@@ -2,6 +2,7 @@ package com.xaaef.molly.perms.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.xaaef.molly.auth.jwt.JwtLoginUser;
|
||||
import com.xaaef.molly.auth.jwt.JwtSecurityUtils;
|
||||
import com.xaaef.molly.common.domain.Pagination;
|
||||
import com.xaaef.molly.common.util.JsonResult;
|
||||
import com.xaaef.molly.perms.entity.PmsUser;
|
||||
@@ -22,6 +23,9 @@ import org.springframework.web.bind.annotation.*;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static com.xaaef.molly.auth.jwt.JwtSecurityUtils.getTenantId;
|
||||
import static com.xaaef.molly.tenant.util.DelegateUtils.delegate;
|
||||
|
||||
|
||||
/**
|
||||
* <p>
|
||||
@@ -89,6 +93,19 @@ public class PmsUserController {
|
||||
}
|
||||
|
||||
|
||||
@Operation(summary = "修改", description = "修改必须要id")
|
||||
@PutMapping("/info")
|
||||
public JsonResult<Boolean> updateInfo(@RequestBody PmsUser entity) {
|
||||
try {
|
||||
var flag = delegate(JwtSecurityUtils.getTenantId(),
|
||||
() -> baseService.updateById(entity));
|
||||
return JsonResult.success(flag);
|
||||
} catch (Exception e) {
|
||||
return JsonResult.fail(e.getMessage(), Boolean.FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Operation(summary = "删除", description = "修改必须要id")
|
||||
@DeleteMapping("/{id}")
|
||||
public JsonResult<Boolean> delete(@PathVariable Long id) {
|
||||
|
||||
@@ -29,7 +29,6 @@ import com.xaaef.molly.perms.service.PmsDeptService;
|
||||
import com.xaaef.molly.perms.service.PmsRoleService;
|
||||
import com.xaaef.molly.perms.service.PmsUserService;
|
||||
import com.xaaef.molly.perms.vo.*;
|
||||
import com.xaaef.molly.common.util.TenantUtils;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
@@ -286,27 +285,33 @@ public class PmsUserServiceImpl extends BaseServiceImpl<PmsUserMapper, PmsUser>
|
||||
}).collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public boolean updatePassword(UpdatePasswordVO pwd) {
|
||||
var sysUser = baseMapper.selectById(pwd.getUserId());
|
||||
if (!StringUtils.equals(pwd.getNewPwd(), pwd.getConfirmPwd())) {
|
||||
throw new RuntimeException("新密码与确认密码不一致,请重新输入!");
|
||||
}
|
||||
// 判断 老密码是否正确。
|
||||
if (matchesPassword(pwd.getOldPwd(), sysUser.getPassword())) {
|
||||
// 判断 新密码 和 老密码是否相同
|
||||
if (matchesPassword(pwd.getNewPwd(), sysUser.getPassword())) {
|
||||
throw new RuntimeException("新密码与旧密码相同,请重新输入!");
|
||||
} else {
|
||||
// 新密码 加密
|
||||
var newPassword = encryptPassword(pwd.getNewPwd());
|
||||
// 修改
|
||||
var pmsUser = PmsUser.builder().userId(pwd.getUserId()).password(newPassword).build();
|
||||
return super.updateById(pmsUser);
|
||||
// 修改密码。要切换到当前登录用户所在的租户
|
||||
// 否则,当平台用户在操作其他租户时,选择修改自己的用户名密码。就查不到自己的用户信息
|
||||
return delegate(getTenantId(), () -> {
|
||||
var sysUser = baseMapper.selectById(pwd.getUserId());
|
||||
if (!StringUtils.equals(pwd.getNewPwd(), pwd.getConfirmPwd())) {
|
||||
throw new RuntimeException("新密码与确认密码不一致,请重新输入!");
|
||||
}
|
||||
}
|
||||
throw new RuntimeException("旧密码错误,请重新输入!");
|
||||
// 判断 旧的密码是否正确。
|
||||
if (matchesPassword(pwd.getOldPwd(), sysUser.getPassword())) {
|
||||
// 判断 新密码 和 老密码是否相同
|
||||
if (matchesPassword(pwd.getNewPwd(), sysUser.getPassword())) {
|
||||
throw new RuntimeException("新密码与旧密码相同,请重新输入!");
|
||||
} else {
|
||||
// 新密码 加密
|
||||
var newPassword = encryptPassword(pwd.getNewPwd());
|
||||
// 修改
|
||||
var pmsUser = PmsUser.builder().userId(pwd.getUserId()).password(newPassword).build();
|
||||
return super.updateById(pmsUser);
|
||||
}
|
||||
} else {
|
||||
throw new RuntimeException("旧密码错误,请重新输入!");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
spring:
|
||||
datasource:
|
||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
url: jdbc:mysql://192.168.0.188:3306/${multi.tenant.db-name:molly_master}?useSSL=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&allowMultiQueries=true
|
||||
url: jdbc:mysql://molly.mysql.com:3306/${multi.tenant.db-name:molly_master}?useSSL=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&allowMultiQueries=true
|
||||
username: root
|
||||
password: mht123456
|
||||
password: root
|
||||
type: com.zaxxer.hikari.HikariDataSource
|
||||
|
||||
|
||||
data:
|
||||
redis:
|
||||
host: 192.168.0.188
|
||||
host: molly.redis.com
|
||||
database: 6
|
||||
port: 6379
|
||||
timeout: 5000
|
||||
@@ -35,10 +35,10 @@ spring:
|
||||
qiniu-kodo: # 七牛云 kodo
|
||||
- platform: qiniu-kodo-1 # 存储平台标识
|
||||
enable-storage: true # 启用存储
|
||||
access-key: cyMiqN72iVBoNiY8nWW-d0JQ8Oyoz9wvRvbWzHTt
|
||||
secret-key: TePPDwQarZ2rWxHMCn8iuMLOSbzh0JYXZZjCRt_N
|
||||
bucket-name: 7qj4ztoh
|
||||
domain: https://oss.xaaef.com/ # 访问域名,注意“/”结尾,例如:http://abc.hn-bkt.clouddn.com/
|
||||
access-key: 123456
|
||||
secret-key: 123456
|
||||
bucket-name: 123456
|
||||
domain: https://oss.baidu.com/ # 访问域名,注意“/”结尾,例如:http://abc.hn-bkt.clouddn.com/
|
||||
base-path: molly/ # 基础路径
|
||||
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import cn.hutool.core.bean.copier.CopyOptions;
|
||||
import cn.hutool.core.lang.tree.Tree;
|
||||
import cn.hutool.core.lang.tree.TreeNode;
|
||||
import cn.hutool.core.lang.tree.TreeUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.xaaef.molly.tenant.base.service.impl.BaseServiceImpl;
|
||||
import com.xaaef.molly.system.entity.SysMenu;
|
||||
@@ -42,6 +43,27 @@ public class SysMenuServiceImpl extends BaseServiceImpl<SysMenuMapper, SysMenu>
|
||||
implements SysMenuService {
|
||||
|
||||
|
||||
@Override
|
||||
public boolean save(SysMenu entity) {
|
||||
if (this.exist(SysMenu::getPerms, entity.getPerms())) {
|
||||
throw new RuntimeException(StrUtil.format("权限标识: {} 已经存在了", entity.getPerms()));
|
||||
}
|
||||
return super.save(entity);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean updateById(SysMenu entity) {
|
||||
var wrapper = new LambdaQueryWrapper<SysMenu>()
|
||||
.eq(SysMenu::getPerms, entity.getPerms())
|
||||
.ne(SysMenu::getMenuId, entity.getMenuId());
|
||||
if (this.exist(wrapper)) {
|
||||
throw new RuntimeException(StrUtil.format("权限标识: {} 已经存在了", entity.getPerms()));
|
||||
}
|
||||
return super.updateById(entity);
|
||||
}
|
||||
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public boolean removeById(Serializable id) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.xaaef.molly.tenant.base.service;
|
||||
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.Wrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
@@ -118,6 +119,15 @@ public interface BaseService<T extends BaseEntity> extends IService<T> {
|
||||
boolean exist(SFunction<T, ?> column, Object value);
|
||||
|
||||
|
||||
/**
|
||||
* 根据 字段 判断,是否存在
|
||||
*
|
||||
* @author Wang Chen Chen
|
||||
* @date 2021/8/25 9:41
|
||||
*/
|
||||
boolean exist(Wrapper<T> wrapper);
|
||||
|
||||
|
||||
/**
|
||||
* 根据 字段 判断,数量
|
||||
*
|
||||
|
||||
@@ -78,6 +78,12 @@ public class BaseServiceImpl<M extends BaseMapper<T>, T extends BaseEntity> exte
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean exist(Wrapper<T> wrapper) {
|
||||
return super.count(wrapper) > 0;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public long count(SFunction<T, ?> column, Object value) {
|
||||
var wrapper = new LambdaQueryWrapper<T>().eq(column, value);
|
||||
|
||||
30
web-ui/.vscode/settings.json
vendored
30
web-ui/.vscode/settings.json
vendored
@@ -1,30 +0,0 @@
|
||||
{
|
||||
"editor.tabSize": 2,
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll.eslint": true
|
||||
},
|
||||
"[vue]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[javascript]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[typescript]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[json]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[jsonc]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[html]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[css]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[scss]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
}
|
||||
}
|
||||
@@ -32,6 +32,11 @@ export const updateUserApi = (data: any) => {
|
||||
return httpPut<any, IJsonResult<boolean>>("/pms/user", data)
|
||||
}
|
||||
|
||||
/** 修改当前登录的用户信息 */
|
||||
export const updateUserInfoApi = (data: any) => {
|
||||
return httpPut<any, IJsonResult<boolean>>("/pms/user/info", data)
|
||||
}
|
||||
|
||||
/** 删除 */
|
||||
export const deleteUserApi = (id: number) => {
|
||||
return httpDelete<number, IJsonResult<boolean>>(`/pms/user/${id}`)
|
||||
|
||||
@@ -14,6 +14,7 @@ import Screenfull from "@/components/Screenfull/index.vue"
|
||||
import Notify from "@/components/Notify/index.vue"
|
||||
import { ElMessageBox } from "element-plus"
|
||||
import { jumpToLogin } from "@/router"
|
||||
import { computed } from "vue"
|
||||
|
||||
const appStore = useAppStore()
|
||||
const userStore = useUserStore()
|
||||
@@ -41,6 +42,8 @@ const logout = () => {
|
||||
})
|
||||
.catch(() => console.log("取消退出登录.. :>> "))
|
||||
}
|
||||
|
||||
const nickname = computed(() => userInfo?.nickname)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -57,7 +60,7 @@ const logout = () => {
|
||||
<el-dropdown class="right-menu-item">
|
||||
<div class="right-menu-avatar">
|
||||
<el-avatar :src="userInfo?.avatar" :icon="UserFilled" :size="36" />
|
||||
<span>{{ userInfo?.nickname }}</span>
|
||||
<span>{{ nickname }}</span>
|
||||
</div>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
@@ -79,6 +82,7 @@ const logout = () => {
|
||||
height: var(--v3-navigationbar-height);
|
||||
overflow: hidden;
|
||||
background: #fff;
|
||||
|
||||
.hamburger {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -87,13 +91,16 @@ const logout = () => {
|
||||
padding: 0 15px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.breadcrumb {
|
||||
float: left;
|
||||
|
||||
// 参考 Bootstrap 的响应式设计将宽度设置为 576
|
||||
@media screen and (max-width: 576px) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.right-menu {
|
||||
float: right;
|
||||
margin-right: 10px;
|
||||
@@ -101,15 +108,19 @@ const logout = () => {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: #606266;
|
||||
|
||||
.right-menu-item {
|
||||
padding: 0 10px;
|
||||
cursor: pointer;
|
||||
|
||||
.right-menu-avatar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.el-avatar {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
span {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ const title = ref("切换租户")
|
||||
|
||||
const dialogVisible = ref(false)
|
||||
|
||||
const value = ref(tenantStore.getCurrentTenant().name)
|
||||
const value = computed(() => tenantStore.getCurrentTenant().name)
|
||||
|
||||
// 获取 input 焦点
|
||||
const inputFocus = () => {
|
||||
@@ -99,7 +99,6 @@ const handleSwitchClick = (t: ISimpleTenant) => {
|
||||
name: t.name,
|
||||
linkman: t.linkman
|
||||
}
|
||||
value.value = tenant.name
|
||||
tenantStore.setCurrentTenant(tenant)
|
||||
dialogVisible.value = false
|
||||
}
|
||||
|
||||
@@ -181,14 +181,14 @@ onMounted(() => {
|
||||
@contextmenu.prevent="openMenu(tag, $event)"
|
||||
>
|
||||
{{ tag.meta?.title }}
|
||||
<el-icon v-if="!isAffix(tag)" :size="12" @click.prevent.stop="closeSelectedTag(tag)">
|
||||
<el-icon v-if="!isAffix(tag)" :size="14" @click.prevent.stop="closeSelectedTag(tag)">
|
||||
<Close />
|
||||
</el-icon>
|
||||
</router-link>
|
||||
</ScrollPane>
|
||||
<ul v-show="visible" class="contextmenu" :style="{ left: left + 'px', top: top + 'px' }">
|
||||
<li @click="refreshSelectedTag(selectedTag)">刷新</li>
|
||||
<li v-if="!isAffix(selectedTag)" @click="closeSelectedTag(selectedTag)">关闭</li>
|
||||
<li @click="refreshSelectedTag(selectedTag)">刷新此页</li>
|
||||
<li v-if="!isAffix(selectedTag)" @click="closeSelectedTag(selectedTag)">关闭此页</li>
|
||||
<li @click="closeOthersTags">关闭其它</li>
|
||||
<li @click="closeAllTags(selectedTag)">关闭所有</li>
|
||||
</ul>
|
||||
|
||||
@@ -33,8 +33,6 @@ router.beforeEach((to, _from, next) => {
|
||||
// 将'有访问权限的动态路由' 添加到 Router 中
|
||||
dynamicRoutes.forEach((route) => router.addRoute(route))
|
||||
|
||||
console.log("dynamicRoutes :>> ", dynamicRoutes)
|
||||
|
||||
// hack方法 确保addRoute已完成 设置 replace: true, 因此导航将不会留下历史记录
|
||||
next({ path: to.path, query: to.query, replace: true })
|
||||
} else {
|
||||
|
||||
@@ -80,6 +80,11 @@ export const useNoticeStore = defineStore("notice", () => {
|
||||
})
|
||||
}
|
||||
|
||||
const stopWebSocket = () => {
|
||||
// 停止
|
||||
stompClient.value!.deactivate()
|
||||
}
|
||||
|
||||
const getStompClientActive = (): boolean => {
|
||||
return stompClientActive.value
|
||||
}
|
||||
@@ -100,6 +105,7 @@ export const useNoticeStore = defineStore("notice", () => {
|
||||
getBroadcast,
|
||||
getPushNotices,
|
||||
startWebSocket,
|
||||
stopWebSocket,
|
||||
getStompClientActive
|
||||
}
|
||||
})
|
||||
|
||||
@@ -26,7 +26,6 @@ export const useTagsViewStore = defineStore("tags-view", () => {
|
||||
if (typeof view.name !== "string") return
|
||||
if (cachedViews.value.includes(view.name)) return
|
||||
if (view.meta?.keepAlive) cachedViews.value.push(view.name)
|
||||
console.log("cachedViews.value :>> ", cachedViews.value)
|
||||
}
|
||||
//#endregion
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import { loginApi, getUserInfoApi, getUserPermsApi, logoutApi } from "@/api/logi
|
||||
import { type IPermsButton, ILoginData, IPermsMenus, ILoginUserInfo } from "@/types/pms"
|
||||
import { ElMessage } from "element-plus"
|
||||
import { getAccessToken, removeAccessToken, setAccessToken } from "@/utils/cache/local-storage"
|
||||
import { useNoticeStoreHook } from "./notice"
|
||||
|
||||
export const useUserStore = defineStore("user", () => {
|
||||
// token信息
|
||||
@@ -105,6 +106,8 @@ export const useUserStore = defineStore("user", () => {
|
||||
userInfo.value = undefined
|
||||
accessToken.value = ""
|
||||
resetRouter()
|
||||
// 关闭 WebSocket
|
||||
useNoticeStoreHook().stopWebSocket()
|
||||
buttons.value = []
|
||||
menus.value = []
|
||||
_resetTagsView()
|
||||
|
||||
@@ -51,6 +51,7 @@ function createService() {
|
||||
return resetTenant(service, response)
|
||||
case 400446:
|
||||
// 此用户不包含此租户ID
|
||||
ElMessage.error(`您没有操作 ${useTenantStoreHook().getCurrentTenant().name} 租户的权限`)
|
||||
useTenantStoreHook().setCurrentTenant(apiData.data as ISimpleTenant)
|
||||
return resetTenant(service, response)
|
||||
default:
|
||||
@@ -136,7 +137,6 @@ function resetTenant(service: AxiosInstance, response: AxiosResponse) {
|
||||
const config = response.config
|
||||
const tenant = useTenantStoreHook().getCurrentTenant()
|
||||
config.headers["x-tenant-id"] = tenant.tenantId
|
||||
console.log("reset tenant id to :>> ", tenant.tenantId)
|
||||
// 获取当前失败的请求,重新发起请求
|
||||
return service(config)
|
||||
}
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
import { useUserStoreHook } from "@/store/modules/user"
|
||||
|
||||
/** 全局权限判断函数,和权限指令 v-permission 功能类似 */
|
||||
export const checkPermission = (permissionRoles: string[]): boolean => {
|
||||
if (Array.isArray(permissionRoles) && permissionRoles.length > 0) {
|
||||
const { roles } = useUserStoreHook()
|
||||
return roles.some((role) => permissionRoles.includes(role))
|
||||
} else {
|
||||
console.error("need roles! Like checkPermission(['admin','editor'])")
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -129,7 +129,7 @@ import { useUserStore } from "@/store/modules/user"
|
||||
import UserAvatar from "@/components/UserAvatar/index.vue"
|
||||
import { ref, reactive } from "vue"
|
||||
import { type FormInstance, FormRules, ElMessageBox } from "element-plus"
|
||||
import { updatePasswordApi, updateUserApi } from "@/api/user"
|
||||
import { updatePasswordApi, updateUserInfoApi } from "@/api/user"
|
||||
import { testEmail, testPassword, testPhone } from "@/utils/validate"
|
||||
import { useRouter } from "vue-router"
|
||||
import { ILoginUserInfo } from "@/types/pms"
|
||||
@@ -194,13 +194,14 @@ const onUpdateUserInfo = () => {
|
||||
loading.value = true
|
||||
const params = {
|
||||
userId: userInfoForm.userId,
|
||||
username: userInfoForm.username,
|
||||
mobile: userInfoForm.mobile,
|
||||
avatar: userInfoForm.avatar,
|
||||
nickname: userInfoForm.nickname,
|
||||
gender: userInfoForm.gender,
|
||||
email: userInfoForm.email
|
||||
}
|
||||
updateUserApi(params)
|
||||
updateUserInfoApi(params)
|
||||
.then(() => userStore.getUserInfo())
|
||||
.catch((err) => {
|
||||
console.log("err", err)
|
||||
|
||||
6
web-ui/types/api.d.ts
vendored
Normal file
6
web-ui/types/api.d.ts
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
/** 所有 api 接口的响应数据都应该准守该格式 */
|
||||
interface IApiResponseData<T> {
|
||||
code: number
|
||||
data: T
|
||||
message: string
|
||||
}
|
||||
116
web-ui/types/element-plus.d.ts
vendored
Normal file
116
web-ui/types/element-plus.d.ts
vendored
Normal file
@@ -0,0 +1,116 @@
|
||||
/**
|
||||
* Copy https://github.com/element-plus/element-plus/blob/dev/global.d.ts
|
||||
* 为了解决某些依赖(比如 vxe-table 4.2.7-beta.0 ~ 4.3.11 和 vue-router 4.2.0)导致的没有 Element Plus 组件类型提示的问题
|
||||
*/
|
||||
|
||||
declare module "vue" {
|
||||
export interface GlobalComponents {
|
||||
ElAffix: typeof import("element-plus")["ElAffix"]
|
||||
ElAlert: typeof import("element-plus")["ElAlert"]
|
||||
ElAside: typeof import("element-plus")["ElAside"]
|
||||
ElAutocomplete: typeof import("element-plus")["ElAutocomplete"]
|
||||
ElAvatar: typeof import("element-plus")["ElAvatar"]
|
||||
ElBacktop: typeof import("element-plus")["ElBacktop"]
|
||||
ElBadge: typeof import("element-plus")["ElBadge"]
|
||||
ElBreadcrumb: typeof import("element-plus")["ElBreadcrumb"]
|
||||
ElBreadcrumbItem: typeof import("element-plus")["ElBreadcrumbItem"]
|
||||
ElButton: typeof import("element-plus")["ElButton"]
|
||||
ElButtonGroup: typeof import("element-plus")["ElButtonGroup"]
|
||||
ElCalendar: typeof import("element-plus")["ElCalendar"]
|
||||
ElCard: typeof import("element-plus")["ElCard"]
|
||||
ElCarousel: typeof import("element-plus")["ElCarousel"]
|
||||
ElCarouselItem: typeof import("element-plus")["ElCarouselItem"]
|
||||
ElCascader: typeof import("element-plus")["ElCascader"]
|
||||
ElCascaderPanel: typeof import("element-plus")["ElCascaderPanel"]
|
||||
ElCheckbox: typeof import("element-plus")["ElCheckbox"]
|
||||
ElCheckboxButton: typeof import("element-plus")["ElCheckboxButton"]
|
||||
ElCheckboxGroup: typeof import("element-plus")["ElCheckboxGroup"]
|
||||
ElCol: typeof import("element-plus")["ElCol"]
|
||||
ElCollapse: typeof import("element-plus")["ElCollapse"]
|
||||
ElCollapseItem: typeof import("element-plus")["ElCollapseItem"]
|
||||
ElCollapseTransition: typeof import("element-plus")["ElCollapseTransition"]
|
||||
ElColorPicker: typeof import("element-plus")["ElColorPicker"]
|
||||
ElContainer: typeof import("element-plus")["ElContainer"]
|
||||
ElConfigProvider: typeof import("element-plus")["ElConfigProvider"]
|
||||
ElDatePicker: typeof import("element-plus")["ElDatePicker"]
|
||||
ElDialog: typeof import("element-plus")["ElDialog"]
|
||||
ElDivider: typeof import("element-plus")["ElDivider"]
|
||||
ElDrawer: typeof import("element-plus")["ElDrawer"]
|
||||
ElDropdown: typeof import("element-plus")["ElDropdown"]
|
||||
ElDropdownItem: typeof import("element-plus")["ElDropdownItem"]
|
||||
ElDropdownMenu: typeof import("element-plus")["ElDropdownMenu"]
|
||||
ElEmpty: typeof import("element-plus")["ElEmpty"]
|
||||
ElFooter: typeof import("element-plus")["ElFooter"]
|
||||
ElForm: typeof import("element-plus")["ElForm"]
|
||||
ElFormItem: typeof import("element-plus")["ElFormItem"]
|
||||
ElHeader: typeof import("element-plus")["ElHeader"]
|
||||
ElIcon: typeof import("element-plus")["ElIcon"]
|
||||
ElImage: typeof import("element-plus")["ElImage"]
|
||||
ElImageViewer: typeof import("element-plus")["ElImageViewer"]
|
||||
ElInput: typeof import("element-plus")["ElInput"]
|
||||
ElInputNumber: typeof import("element-plus")["ElInputNumber"]
|
||||
ElLink: typeof import("element-plus")["ElLink"]
|
||||
ElMain: typeof import("element-plus")["ElMain"]
|
||||
ElMenu: typeof import("element-plus")["ElMenu"]
|
||||
ElMenuItem: typeof import("element-plus")["ElMenuItem"]
|
||||
ElMenuItemGroup: typeof import("element-plus")["ElMenuItemGroup"]
|
||||
ElOption: typeof import("element-plus")["ElOption"]
|
||||
ElOptionGroup: typeof import("element-plus")["ElOptionGroup"]
|
||||
ElPageHeader: typeof import("element-plus")["ElPageHeader"]
|
||||
ElPagination: typeof import("element-plus")["ElPagination"]
|
||||
ElPopconfirm: typeof import("element-plus")["ElPopconfirm"]
|
||||
ElPopper: typeof import("element-plus")["ElPopper"]
|
||||
ElPopover: typeof import("element-plus")["ElPopover"]
|
||||
ElProgress: typeof import("element-plus")["ElProgress"]
|
||||
ElRadio: typeof import("element-plus")["ElRadio"]
|
||||
ElRadioButton: typeof import("element-plus")["ElRadioButton"]
|
||||
ElRadioGroup: typeof import("element-plus")["ElRadioGroup"]
|
||||
ElRate: typeof import("element-plus")["ElRate"]
|
||||
ElRow: typeof import("element-plus")["ElRow"]
|
||||
ElScrollbar: typeof import("element-plus")["ElScrollbar"]
|
||||
ElSelect: typeof import("element-plus")["ElSelect"]
|
||||
ElSlider: typeof import("element-plus")["ElSlider"]
|
||||
ElStep: typeof import("element-plus")["ElStep"]
|
||||
ElSteps: typeof import("element-plus")["ElSteps"]
|
||||
ElSubMenu: typeof import("element-plus")["ElSubMenu"]
|
||||
ElSwitch: typeof import("element-plus")["ElSwitch"]
|
||||
ElTabPane: typeof import("element-plus")["ElTabPane"]
|
||||
ElTable: typeof import("element-plus")["ElTable"]
|
||||
ElTableColumn: typeof import("element-plus")["ElTableColumn"]
|
||||
ElTabs: typeof import("element-plus")["ElTabs"]
|
||||
ElTag: typeof import("element-plus")["ElTag"]
|
||||
ElText: typeof import("element-plus")["ElText"]
|
||||
ElTimePicker: typeof import("element-plus")["ElTimePicker"]
|
||||
ElTimeSelect: typeof import("element-plus")["ElTimeSelect"]
|
||||
ElTimeline: typeof import("element-plus")["ElTimeline"]
|
||||
ElTimelineItem: typeof import("element-plus")["ElTimelineItem"]
|
||||
ElTooltip: typeof import("element-plus")["ElTooltip"]
|
||||
ElTransfer: typeof import("element-plus")["ElTransfer"]
|
||||
ElTree: typeof import("element-plus")["ElTree"]
|
||||
ElTreeV2: typeof import("element-plus")["ElTreeV2"]
|
||||
ElTreeSelect: typeof import("element-plus")["ElTreeSelect"]
|
||||
ElUpload: typeof import("element-plus")["ElUpload"]
|
||||
ElSpace: typeof import("element-plus")["ElSpace"]
|
||||
ElSkeleton: typeof import("element-plus")["ElSkeleton"]
|
||||
ElSkeletonItem: typeof import("element-plus")["ElSkeletonItem"]
|
||||
ElStatistic: typeof import("element-plus")["ElStatistic"]
|
||||
ElCheckTag: typeof import("element-plus")["ElCheckTag"]
|
||||
ElDescriptions: typeof import("element-plus")["ElDescriptions"]
|
||||
ElDescriptionsItem: typeof import("element-plus")["ElDescriptionsItem"]
|
||||
ElResult: typeof import("element-plus")["ElResult"]
|
||||
ElSelectV2: typeof import("element-plus")["ElSelectV2"]
|
||||
}
|
||||
|
||||
interface ComponentCustomProperties {
|
||||
$message: typeof import("element-plus")["ElMessage"]
|
||||
$notify: typeof import("element-plus")["ElNotification"]
|
||||
$msgbox: typeof import("element-plus")["ElMessageBox"]
|
||||
$messageBox: typeof import("element-plus")["ElMessageBox"]
|
||||
$alert: typeof import("element-plus")["ElMessageBox"]["alert"]
|
||||
$confirm: typeof import("element-plus")["ElMessageBox"]["confirm"]
|
||||
$prompt: typeof import("element-plus")["ElMessageBox"]["prompt"]
|
||||
$loading: typeof import("element-plus")["ElLoadingService"]
|
||||
}
|
||||
}
|
||||
|
||||
export {}
|
||||
Reference in New Issue
Block a user