master
zhengqingya 2 years ago
parent 2ba43e56bc
commit 345ec09be5
  1. 9
      smallboot-api/common/auth/pom.xml
  2. 2
      smallboot-api/common/auth/src/main/java/com/zhengqing/common/auth/api/TestController.java
  3. 27
      smallboot-api/common/auth/src/main/java/com/zhengqing/common/auth/config/SaTokenConfig.java
  4. 30
      smallboot-api/common/auth/src/main/java/com/zhengqing/common/auth/config/SaTokenCustomConfig.java
  5. 6
      smallboot-api/common/auth/src/main/java/com/zhengqing/common/auth/config/SaTokenProperty.java
  6. 13
      smallboot-api/common/auth/src/main/java/com/zhengqing/common/auth/config/SaTokenWebMvcConfig.java
  7. 2
      smallboot-api/common/auth/src/main/resources/application-auth.yml
  8. 12
      smallboot-api/common/base/src/main/java/com/zhengqing/common/base/context/JwtUserContext.java
  9. 48
      smallboot-api/common/base/src/main/java/com/zhengqing/common/base/model/bo/JwtCustomUserBO.java
  10. 23
      smallboot-api/common/base/src/main/java/com/zhengqing/common/base/model/bo/JwtUserBO.java
  11. 21
      smallboot-api/common/core/src/main/java/com/zhengqing/common/core/config/interceptor/HandlerInterceptorForTokenUser.java
  12. 15
      smallboot-api/common/db/src/main/java/com/zhengqing/common/db/config/mybatis/MyMetaObjectHandler.java
  13. 6
      smallboot-api/system/src/main/java/com/zhengqing/system/service/impl/AuthServiceImpl.java
  14. 26
      smallboot-web/src/components/base/BaseTableP.vue
  15. 1
      smallboot-web/src/components/base/BaseTitleCard.vue
  16. 2
      smallboot-web/src/layout/components/TagsView/ScrollPane.vue
  17. 15
      smallboot-web/src/layout/components/TagsView/index.vue
  18. 4
      smallboot-web/src/store/modules/settings.ts
  19. 11
      smallboot-web/src/views/system/dict/edit-dict.vue
  20. 15
      smallboot-web/src/views/system/dict/index.vue

@ -29,7 +29,14 @@
<dependency> <dependency>
<groupId>cn.dev33</groupId> <groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-boot-starter</artifactId> <artifactId>sa-token-spring-boot-starter</artifactId>
<version>1.27.0</version> <version>1.34.0</version>
</dependency>
<!-- Sa-Token 整合 jwt -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-jwt</artifactId>
<version>1.34.0</version>
</dependency> </dependency>
<!-- Sa-Token 整合 Redis (使用jackson序列化方式) --> <!-- Sa-Token 整合 Redis (使用jackson序列化方式) -->

@ -62,7 +62,7 @@ public class TestController {
@GetMapping("logout") @GetMapping("logout")
@ApiOperation("退出登录") @ApiOperation("退出登录")
public String logout(String loginId) { public String logout(String loginId) {
StpUtil.logoutByLoginId(loginId); StpUtil.logout(loginId);
return "SUCCESS"; return "SUCCESS";
} }

@ -0,0 +1,27 @@
package com.zhengqing.common.auth.config;
import cn.dev33.satoken.jwt.StpLogicJwtForSimple;
import cn.dev33.satoken.stp.StpLogic;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* <p> Sa-Token 配置类 </p>
*
* @author zhengqingya
* @description
* @date 2021/11/3 12:06
*/
@Configuration
public class SaTokenConfig {
/**
* Sa-Token 整合 jwt (Simple 简单模式)
* 参考 https://sa-token.cc/doc.html#/plugin/jwt-extend
*/
@Bean
public StpLogic getStpLogicJwt() {
return new StpLogicJwtForSimple();
}
}

@ -1,30 +0,0 @@
package com.zhengqing.common.auth.config;
import cn.dev33.satoken.strategy.SaStrategy;
import cn.dev33.satoken.util.SaFoxUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
/**
* <p> 自定义sa-token生成策略 </p>
*
* @author zhengqingya
* @description
* @date 2021/11/3 12:06
*/
@Configuration
public class SaTokenCustomConfig {
/**
* 重写 Sa-Token 框架内部算法策略
*/
@Autowired
public void rewriteSaStrategy() {
// 重写 Token 生成策略
SaStrategy.me.createToken = (loginId, loginType) -> {
// 随机60位长度字符串
return SaFoxUtil.getRandomString(60);
};
}
}

@ -8,16 +8,16 @@ import java.util.List;
/** /**
* <p> Sa-Token 拦截/开放 URL 配置类 </p> * <p> Sa-Token 配置属性 </p>
* *
* @author zhengqingya * @author zhengqingya
* @description * @description 拦截/开放 URL
* @date 2021/11/3 8:54 下午 * @date 2021/11/3 8:54 下午
*/ */
@Data @Data
@Configuration @Configuration
@ConfigurationProperties(prefix = "sa-token", ignoreUnknownFields = true) @ConfigurationProperties(prefix = "sa-token", ignoreUnknownFields = true)
public class SaTokenUrlConfig { public class SaTokenProperty {
/** /**
* 拦截url * 拦截url

@ -1,6 +1,7 @@
package com.zhengqing.common.auth.config; package com.zhengqing.common.auth.config;
import cn.dev33.satoken.interceptor.SaRouteInterceptor; import cn.dev33.satoken.interceptor.SaInterceptor;
import cn.dev33.satoken.stp.StpUtil;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@ -18,14 +19,14 @@ import javax.annotation.Resource;
public class SaTokenWebMvcConfig implements WebMvcConfigurer { public class SaTokenWebMvcConfig implements WebMvcConfigurer {
@Resource @Resource
private SaTokenUrlConfig saTokenUrlConfig; private SaTokenProperty saTokenProperty;
@Override @Override
public void addInterceptors(InterceptorRegistry registry) { public void addInterceptors(InterceptorRegistry registry) {
// 注册1个登录认证拦截器 // 注册1个登录认证拦截器 -- 参考: https://sa-token.cc/doc.html#/use/route-check
registry.addInterceptor(new SaRouteInterceptor()) registry.addInterceptor(new SaInterceptor(handle -> StpUtil.checkLogin()))
.addPathPatterns(this.saTokenUrlConfig.getInterceptUrlList()) .addPathPatterns(this.saTokenProperty.getInterceptUrlList())
.excludePathPatterns(this.saTokenUrlConfig.getOpenUrlList()); .excludePathPatterns(this.saTokenProperty.getOpenUrlList());
} }
} }

@ -2,6 +2,8 @@
sa-token: sa-token:
# token名称 (同时也是cookie名称) 注意不能带冒号: # token名称 (同时也是cookie名称) 注意不能带冒号:
token-name: Authorization-smallboot token-name: Authorization-smallboot
# jwt秘钥
jwt-secret-key: smallboot
# token值前缀 # token值前缀
# token-prefix: Bearer # token-prefix: Bearer
# token有效期,单位s 这里设置1天, -1代表永不过期 # token有效期,单位s 这里设置1天, -1代表永不过期

@ -1,7 +1,7 @@
package com.zhengqing.common.base.context; package com.zhengqing.common.base.context;
import com.zhengqing.common.base.model.bo.JwtCustomUserBO; import com.zhengqing.common.base.model.bo.JwtUserBO;
/** /**
* <p> jwt自定义用户信息上下文 </p> * <p> jwt自定义用户信息上下文 </p>
@ -10,16 +10,16 @@ import com.zhengqing.common.base.model.bo.JwtCustomUserBO;
* @description 请务必在请求结束时, 调用 @Method remove() * @description 请务必在请求结束时, 调用 @Method remove()
* @date 2020/8/1 19:07 * @date 2020/8/1 19:07
*/ */
public class JwtCustomUserContext { public class JwtUserContext {
public static final ThreadLocal<JwtCustomUserBO> THREAD_LOCAL = new ThreadLocal<>(); public static final ThreadLocal<JwtUserBO> THREAD_LOCAL = new ThreadLocal<>();
public static JwtCustomUserBO get() { public static JwtUserBO get() {
return THREAD_LOCAL.get(); return THREAD_LOCAL.get();
} }
public static void set(JwtCustomUserBO jwtCustomUserBO) { public static void set(JwtUserBO jwtUserBO) {
THREAD_LOCAL.set(jwtCustomUserBO); THREAD_LOCAL.set(jwtUserBO);
} }
public static void remove() { public static void remove() {

@ -1,48 +0,0 @@
package com.zhengqing.common.base.model.bo;
import com.zhengqing.common.base.enums.AuthSourceEnum;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
/**
* <p> jwt中自定义的用户信息 </p>
*
* @author zhengqingya
* @description {@link com.zhengqing.auth.security.config.CustomAdditionalInformation}
* @date 2022/6/15 10:34
*/
@Data
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
public class JwtCustomUserBO {
/**
* {@link AuthSourceEnum}
*/
@ApiModelProperty(value = "认证来源")
private String authSource;
@ApiModelProperty(value = "jwt")
private String token;
@ApiModelProperty(value = "jwt的唯一身份标识")
private String jti;
@ApiModelProperty(value = "过期时间(2022-06-01 23:06:53)")
private String expireTime;
@ApiModelProperty(value = "租户ID")
private String tenantId;
@ApiModelProperty(value = "B端系统用户ID")
private String sysUserId;
@ApiModelProperty(value = "C端用户ID")
private String umsUserId;
@ApiModelProperty(value = "用户名")
private String username;
}

@ -1,6 +1,6 @@
package com.zhengqing.common.auth.model.bo; package com.zhengqing.common.base.model.bo;
import com.zhengqing.common.base.model.bo.BaseBO; import com.zhengqing.common.base.enums.AuthSourceEnum;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
@ -22,10 +22,27 @@ import lombok.experimental.SuperBuilder;
@AllArgsConstructor @AllArgsConstructor
public class JwtUserBO extends BaseBO { public class JwtUserBO extends BaseBO {
@ApiModelProperty(value = "认证来源")
private AuthSourceEnum authSourceEnum;
@ApiModelProperty(value = "用户ID") @ApiModelProperty(value = "用户ID")
private Integer userId; private String userId;
@ApiModelProperty(value = "用户名") @ApiModelProperty(value = "用户名")
private String userName; private String userName;
/**
* 获取B端用户ID
*/
public Integer getUserIdForB() {
return Integer.valueOf(this.userId);
}
/**
* 获取C端用户ID
*/
public Long getUserIdForC() {
return Long.valueOf(this.userId);
}
} }

@ -2,11 +2,11 @@ package com.zhengqing.common.core.config.interceptor;
import cn.dev33.satoken.stp.StpUtil; import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.json.JSONUtil; import cn.hutool.json.JSONUtil;
import com.zhengqing.common.auth.model.bo.JwtUserBO;
import com.zhengqing.common.base.constant.AppConstant; import com.zhengqing.common.base.constant.AppConstant;
import com.zhengqing.common.base.context.JwtCustomUserContext; import com.zhengqing.common.base.context.JwtUserContext;
import com.zhengqing.common.base.context.SysUserContext; import com.zhengqing.common.base.context.SysUserContext;
import com.zhengqing.common.base.context.UmsUserContext; import com.zhengqing.common.base.context.UmsUserContext;
import com.zhengqing.common.base.model.bo.JwtUserBO;
import com.zhengqing.common.core.config.WebAppConfig; import com.zhengqing.common.core.config.WebAppConfig;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.HandlerInterceptor;
@ -35,8 +35,19 @@ public class HandlerInterceptorForTokenUser implements HandlerInterceptor {
return true; return true;
} }
JwtUserBO jwtUserBO = JSONUtil.toBean(StpUtil.getLoginId().toString(), JwtUserBO.class); JwtUserBO jwtUserBO = JSONUtil.toBean(StpUtil.getLoginId().toString(), JwtUserBO.class);
SysUserContext.setUserId(jwtUserBO.getUserId()); JwtUserContext.set(jwtUserBO);
SysUserContext.setUsername(jwtUserBO.getUserName()); switch (jwtUserBO.getAuthSourceEnum()) {
case B:
SysUserContext.setUserId(Integer.valueOf(jwtUserBO.getUserId()));
SysUserContext.setUsername(jwtUserBO.getUserName());
break;
case C:
UmsUserContext.setUserId(Long.valueOf(jwtUserBO.getUserId()));
UmsUserContext.setUsername(jwtUserBO.getUserName());
break;
default:
break;
}
return true; return true;
} }
@ -57,7 +68,7 @@ public class HandlerInterceptorForTokenUser implements HandlerInterceptor {
HandlerInterceptor.super.afterCompletion(request, response, handler, ex); HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
SysUserContext.remove(); SysUserContext.remove();
UmsUserContext.remove(); UmsUserContext.remove();
JwtCustomUserContext.remove(); JwtUserContext.remove();
} }
} }

@ -2,9 +2,8 @@ package com.zhengqing.common.db.config.mybatis;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import com.zhengqing.common.base.constant.BaseConstant; import com.zhengqing.common.base.constant.BaseConstant;
import com.zhengqing.common.base.context.JwtCustomUserContext; import com.zhengqing.common.base.context.JwtUserContext;
import com.zhengqing.common.base.enums.AuthSourceEnum; import com.zhengqing.common.base.model.bo.JwtUserBO;
import com.zhengqing.common.base.model.bo.JwtCustomUserBO;
import com.zhengqing.common.db.constant.MybatisConstant; import com.zhengqing.common.db.constant.MybatisConstant;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject; import org.apache.ibatis.reflection.MetaObject;
@ -74,13 +73,9 @@ public class MyMetaObjectHandler implements MetaObjectHandler {
* @date 2022/7/8 18:15 * @date 2022/7/8 18:15
*/ */
private Long getUserId() { private Long getUserId() {
JwtCustomUserBO jwtCustomUserBO = JwtCustomUserContext.get(); JwtUserBO jwtUserBO = JwtUserContext.get();
if (jwtCustomUserBO != null) { if (jwtUserBO != null) {
if (AuthSourceEnum.B.getValue().equals(jwtCustomUserBO.getAuthSource())) { return Long.valueOf(jwtUserBO.getUserId());
return Long.valueOf(jwtCustomUserBO.getSysUserId());
} else {
return Long.valueOf(jwtCustomUserBO.getUmsUserId());
}
} }
return Long.valueOf(BaseConstant.DEFAULT_CONTEXT_KEY_USER_ID); return Long.valueOf(BaseConstant.DEFAULT_CONTEXT_KEY_USER_ID);
} }

@ -3,10 +3,11 @@ package com.zhengqing.common.auth.service.impl;
import cn.dev33.satoken.stp.StpUtil; import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.lang.Assert; import cn.hutool.core.lang.Assert;
import cn.hutool.json.JSONUtil; import cn.hutool.json.JSONUtil;
import com.zhengqing.common.auth.model.bo.JwtUserBO;
import com.zhengqing.common.auth.model.dto.AuthLoginDTO; import com.zhengqing.common.auth.model.dto.AuthLoginDTO;
import com.zhengqing.common.auth.model.vo.AuthLoginVO; import com.zhengqing.common.auth.model.vo.AuthLoginVO;
import com.zhengqing.common.auth.service.IAuthService; import com.zhengqing.common.auth.service.IAuthService;
import com.zhengqing.common.base.enums.AuthSourceEnum;
import com.zhengqing.common.base.model.bo.JwtUserBO;
import com.zhengqing.system.entity.SysUser; import com.zhengqing.system.entity.SysUser;
import com.zhengqing.system.service.ISysUserService; import com.zhengqing.system.service.ISysUserService;
import com.zhengqing.system.util.PasswordUtil; import com.zhengqing.system.util.PasswordUtil;
@ -45,7 +46,8 @@ public class AuthServiceImpl implements IAuthService {
// 登录 // 登录
StpUtil.login(JSONUtil.toJsonStr( StpUtil.login(JSONUtil.toJsonStr(
JwtUserBO.builder() JwtUserBO.builder()
.userId(sysUser.getUserId()) .authSourceEnum(AuthSourceEnum.B)
.userId(String.valueOf(sysUser.getUserId()))
.userName(sysUser.getUsername()) .userName(sysUser.getUsername())
.build() .build()
)); ));

@ -4,13 +4,16 @@
<slot name="header" :res="res"></slot> <slot name="header" :res="res"></slot>
</div> </div>
<slot name="zdy-header" :res="res"></slot> <slot name="zdy-header" :res="res"></slot>
<el-table ref="baseTable" v-loading=" <el-table
loading && ref="baseTable"
(isPage v-loading="loading && (isPage ? res.records == null || res.records.length == 0 : tableDataList == null || tableDataList.length == 0)"
? res.records == null || res.records.length == 0 v-bind="$attrs"
: tableDataList == null || tableDataList.length == 0) :data="isPage ? res.records : tableDataList"
" v-bind="$attrs" :data="isPage ? res.records : tableDataList" :class="{ pointer: pointer }" size="small" fit :class="{ pointer: pointer }"
highlight-current-row> size="small"
fit
highlight-current-row
>
<el-table-column v-if="selection" type="selection" :width="55"></el-table-column> <el-table-column v-if="selection" type="selection" :width="55"></el-table-column>
<template v-if="indexCode"> <template v-if="indexCode">
<el-table-column type="index" label="序号" width="60px"></el-table-column> <el-table-column type="index" label="序号" width="60px"></el-table-column>
@ -27,8 +30,13 @@
</el-table> </el-table>
<div v-if="isPage" class="pagination-container"> <div v-if="isPage" class="pagination-container">
<base-pagination v-if="res && res.total > 0" :total="res.total == null ? 0 : res.total" <base-pagination
v-model:page="pageParams.pageNum" v-model:limit="pageParams.pageSize" @pagination="getListPage" /> v-if="res && res.total > 0"
:total="res.total == null ? 0 : res.total"
v-model:page="pageParams.pageNum"
v-model:limit="pageParams.pageSize"
@pagination="getListPage"
/>
</div> </div>
</div> </div>
</template> </template>

@ -30,7 +30,6 @@ export default {
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.title-card { .title-card {
h2 { h2 {
position: relative; position: relative;
border-bottom: 1px solid #ebeef5; border-bottom: 1px solid #ebeef5;

@ -21,7 +21,7 @@ const { tagsView } = useStore()
const visitedViews = computed(() => tagsView.visitedViews) const visitedViews = computed(() => tagsView.visitedViews)
const scrollWrapper = computed(() => proxy?.$refs.scrollContainer.$refs.wrap$) const scrollWrapper = computed(() => proxy?.$refs.scrollContainer.$refs.wrapRef)
onMounted(() => { onMounted(() => {
scrollWrapper.value.addEventListener('scroll', emitScroll, true) scrollWrapper.value.addEventListener('scroll', emitScroll, true)

@ -1,9 +1,16 @@
<template> <template>
<div class="tags-view__container"> <div class="tags-view__container">
<scroll-pane ref="scrollPaneRef" class="tags-view__wrapper" @scroll="handleScroll"> <scroll-pane ref="scrollPaneRef" class="tags-view__wrapper" @scroll="handleScroll">
<router-link v-for="tag in visitedViews" :key="tag.path" :data-path="tag.path" <router-link
:class="isActive(tag) ? 'active' : ''" :to="{ path: tag.path, query: tag.query }" class="tags-view__item" v-for="tag in visitedViews"
@click.middle="!isAffix(tag) ? closeSelectedTag(tag) : ''" @contextmenu.prevent="openMenu(tag, $event)"> :key="tag.path"
:data-path="tag.path"
:class="isActive(tag) ? 'active' : ''"
:to="{ path: tag.path, query: tag.query }"
class="tags-view__item"
@click.middle="!isAffix(tag) ? closeSelectedTag(tag) : ''"
@contextmenu.prevent="openMenu(tag, $event)"
>
{{ tag.meta.title }} {{ tag.meta.title }}
<span v-if="!isAffix(tag)" class="icon-close" @click.prevent.stop="closeSelectedTag(tag)"> <span v-if="!isAffix(tag)" class="icon-close" @click.prevent.stop="closeSelectedTag(tag)">
<el-icon> <el-icon>
@ -325,7 +332,7 @@ onMounted(() => {
cursor: pointer; cursor: pointer;
&:hover { &:hover {
background: rgb(77, 156, 130); background: #eee;
} }
} }
} }

@ -5,8 +5,8 @@ import { localStorage } from '@/utils/storage'
export const useSettingStore = defineStore({ export const useSettingStore = defineStore({
id: 'setting', id: 'setting',
state: (): SettingState => ({ state: (): SettingState => ({
// tagsView: localStorage.get('tagsView') != null ? localStorage.get('tagsView') : true, // 默认开启
tagsView: false, tagsView: localStorage.get('tagsView') != null ? localStorage.get('tagsView') : true,
}), }),
}) })

@ -7,20 +7,20 @@
<el-form-item label="字典值:" prop="value"> <el-form-item label="字典值:" prop="value">
<el-input v-model="form.value" placeholder="输入字典值" /> <el-input v-model="form.value" placeholder="输入字典值" />
</el-form-item> </el-form-item>
<el-form-item label="展示顺序:"> <el-form-item label="序:">
<el-input-number v-model="form.sort" /> <el-input-number v-model="form.sort" />
</el-form-item> </el-form-item>
</el-form> </el-form>
<span slot="footer" class="dialog-footer"> <template #footer>
<el-button @click="dialogVisible = false"> </el-button> <el-button @click="dialogVisible = false"> </el-button>
<el-button type="primary" @click="handleSave"> </el-button> <el-button type="primary" @click="handleSave"> </el-button>
</span> </template>
</base-dialog> </base-dialog>
</template> </template>
<script> <script>
export default { export default {
name: 'EditDict', name: 'EditDict',
emits: ["saveSucc"], emits: ['saveSucc'],
data() { data() {
return { return {
titleMap: { titleMap: {
@ -79,5 +79,4 @@ export default {
}, },
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped></style>
</style>

@ -1,7 +1,7 @@
<template> <template>
<base-wraper> <base-wraper>
<el-row style="height: 100%" :gutter="15"> <el-row :gutter="15">
<el-col :span="5" style="height: 100%"> <el-col :span="5">
<base-wraper full-height> <base-wraper full-height>
<base-title-card title="字典类型"> <base-title-card title="字典类型">
<el-button type="primary" @click="addDictType">添加</el-button> <el-button type="primary" @click="addDictType">添加</el-button>
@ -27,10 +27,10 @@
<base-title-card style="margin-top: 10px" title="字典列表"> <base-title-card style="margin-top: 10px" title="字典列表">
<el-button v-if="isShowAddDictButton" type="primary" @click="addDict">添加</el-button> <el-button v-if="isShowAddDictButton" type="primary" @click="addDict">添加</el-button>
<el-table v-loading.body="listLoading" :data="dicList" border :height="calcTableHeight"> <el-table v-loading.body="listLoading" :data="dicList" border :height="calcTableHeight">
<el-table-column prop="id" label="ID" /> <el-table-column type="index" label="序号" width="60px" align="center" />
<el-table-column prop="name" label="字典名称" /> <el-table-column prop="name" label="字典名称" align="center" />
<el-table-column prop="value" label="字典值" /> <el-table-column prop="value" label="字典值" align="center" />
<el-table-column prop="sort" label="展示排序" /> <el-table-column prop="sort" label="排序" align="center" />
<el-table-column label="操作" align="center" width="150"> <el-table-column label="操作" align="center" width="150">
<template v-slot="scope"> <template v-slot="scope">
<el-button link @click="updateDict(scope.row)">编辑</el-button> <el-button link @click="updateDict(scope.row)">编辑</el-button>
@ -134,5 +134,4 @@ export default {
}, },
} }
</script> </script>
<style scoped> <style scoped></style>
</style>

Loading…
Cancel
Save