mirror of
https://gitee.com/durcframework/SOP.git
synced 2025-08-11 21:57:56 +08:00
5.0
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
package com.gitee.sop.adminbackend.common;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* @author 六如
|
||||
*/
|
||||
@Data
|
||||
public class IdParam {
|
||||
@NotNull(message = "id不能为空")
|
||||
private Long id;
|
||||
}
|
@@ -0,0 +1,33 @@
|
||||
package com.gitee.sop.adminbackend.common;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* @author 六如
|
||||
*/
|
||||
@Getter
|
||||
public enum StatusEnum {
|
||||
DISABLED((byte)0),
|
||||
ENABLE((byte)1),
|
||||
SET_PWD((byte)2),
|
||||
;
|
||||
|
||||
private final int status;
|
||||
|
||||
public static StatusEnum of(Integer value) {
|
||||
for (StatusEnum statusEnum : StatusEnum.values()) {
|
||||
if (Objects.equals(statusEnum.status, value)) {
|
||||
return statusEnum;
|
||||
}
|
||||
}
|
||||
return DISABLED;
|
||||
}
|
||||
|
||||
StatusEnum(byte style) {
|
||||
this.status = style;
|
||||
}
|
||||
|
||||
|
||||
}
|
@@ -0,0 +1,80 @@
|
||||
package com.gitee.sop.adminbackend.controller.serve;
|
||||
|
||||
import com.gitee.fastmybatis.core.PageInfo;
|
||||
import com.gitee.fastmybatis.core.query.Query;
|
||||
import com.gitee.sop.adminbackend.common.IdParam;
|
||||
import com.gitee.sop.adminbackend.common.Result;
|
||||
import com.gitee.sop.adminbackend.controller.serve.req.ApiInfoParam;
|
||||
import com.gitee.sop.adminbackend.dao.entity.ApiInfo;
|
||||
import com.gitee.sop.adminbackend.service.serve.ApiInfoService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
|
||||
/**
|
||||
* 接口管理
|
||||
*
|
||||
* @author 六如
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("serve/api")
|
||||
public class ApiInfoController {
|
||||
|
||||
@Autowired
|
||||
private ApiInfoService apiInfoService;
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
*
|
||||
* @param param
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/page")
|
||||
public Result<PageInfo<ApiInfo>> page(ApiInfoParam param) {
|
||||
Query query = param.toQuery();
|
||||
query.orderByDesc("id");
|
||||
PageInfo<ApiInfo> pageInfo = apiInfoService.page(query);
|
||||
return Result.ok(pageInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增记录
|
||||
*
|
||||
* @param user
|
||||
* @return 返回添加后的主键值
|
||||
*/
|
||||
@PostMapping("/add")
|
||||
public Result<Long> add(@Validated @RequestBody ApiInfo user) {
|
||||
apiInfoService.save(user);
|
||||
// 返回添加后的主键值
|
||||
return Result.ok(user.getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改记录
|
||||
*
|
||||
* @param user 表单数据
|
||||
* @return 返回影响行数
|
||||
*/
|
||||
@PostMapping("/update")
|
||||
public Result<Integer> update(@Validated @RequestBody ApiInfo user) {
|
||||
return Result.ok(apiInfoService.update(user));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除记录
|
||||
*
|
||||
* @param param 主键id
|
||||
* @return 返回影响行数
|
||||
*/
|
||||
@PostMapping("/delete")
|
||||
public Result<Integer> delete(@Validated @RequestBody IdParam param) {
|
||||
return Result.ok(apiInfoService.deleteById(param.getId()));
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,18 @@
|
||||
package com.gitee.sop.adminbackend.controller.serve.req;
|
||||
|
||||
import com.gitee.fastmybatis.core.query.Operator;
|
||||
import com.gitee.fastmybatis.core.query.annotation.Condition;
|
||||
import com.gitee.fastmybatis.core.query.param.PageParam;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author 六如
|
||||
*/
|
||||
@Data
|
||||
public class ApiInfoParam extends PageParam {
|
||||
|
||||
@Condition(operator = Operator.like)
|
||||
private String apiName;
|
||||
|
||||
|
||||
}
|
@@ -1,11 +1,12 @@
|
||||
package com.gitee.sop.adminbackend.dao.entity;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import com.gitee.fastmybatis.annotation.Pk;
|
||||
import com.gitee.fastmybatis.annotation.PkStrategy;
|
||||
import com.gitee.fastmybatis.annotation.Table;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import lombok.Data;
|
||||
|
||||
|
||||
/**
|
||||
@@ -35,6 +36,16 @@ public class ApiInfo {
|
||||
*/
|
||||
private String apiVersion;
|
||||
|
||||
/**
|
||||
* 接口描述
|
||||
*/
|
||||
private String description;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* 接口class
|
||||
*/
|
||||
@@ -61,7 +72,7 @@ public class ApiInfo {
|
||||
private Integer isNeedToken;
|
||||
|
||||
/**
|
||||
* 状态,1-启用,0-禁用
|
||||
* 1启用,2禁用
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
|
@@ -0,0 +1,15 @@
|
||||
package com.gitee.sop.adminbackend.service.serve;
|
||||
|
||||
import com.gitee.fastmybatis.core.support.LambdaService;
|
||||
import com.gitee.sop.adminbackend.dao.entity.ApiInfo;
|
||||
import com.gitee.sop.adminbackend.dao.mapper.ApiInfoMapper;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
|
||||
/**
|
||||
* @author 六如
|
||||
*/
|
||||
@Service
|
||||
public class ApiInfoService implements LambdaService<ApiInfo, ApiInfoMapper> {
|
||||
|
||||
}
|
@@ -1,7 +1,6 @@
|
||||
package com.gitee.sop.adminbackend.service.sys.login;
|
||||
|
||||
import com.alibaba.nacos.shaded.com.google.common.collect.Sets;
|
||||
import com.gitee.fastmybatis.core.query.Query;
|
||||
import com.gitee.sop.adminbackend.common.ConfigKeyEnum;
|
||||
import com.gitee.sop.adminbackend.common.exception.BizException;
|
||||
import com.gitee.sop.adminbackend.config.Configs;
|
||||
@@ -11,7 +10,7 @@ import com.gitee.sop.adminbackend.service.sys.login.dto.LoginDTO;
|
||||
import com.gitee.sop.adminbackend.service.sys.login.dto.LoginForm;
|
||||
import com.gitee.sop.adminbackend.service.sys.login.dto.LoginResult;
|
||||
import com.gitee.sop.adminbackend.service.sys.login.dto.LoginUser;
|
||||
import com.gitee.sop.adminbackend.service.sys.login.enums.AdminUserStatusEnum;
|
||||
import com.gitee.sop.adminbackend.common.StatusEnum;
|
||||
import com.gitee.sop.adminbackend.service.sys.login.enums.RegTypeEnum;
|
||||
import com.gitee.sop.adminbackend.util.CopyUtil;
|
||||
import com.gitee.sop.adminbackend.util.GenerateUtil;
|
||||
@@ -26,7 +25,6 @@ import org.springframework.util.StringUtils;
|
||||
import javax.annotation.Resource;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
@@ -68,7 +66,7 @@ public class LoginService {
|
||||
}
|
||||
|
||||
private LoginUser buildLoginUser(SysAdminUser userInfo) {
|
||||
if (AdminUserStatusEnum.of(userInfo.getStatus()) == AdminUserStatusEnum.DISABLED) {
|
||||
if (StatusEnum.of(userInfo.getStatus()) == StatusEnum.DISABLED) {
|
||||
throw new BizException("账号已禁用,请联系管理员");
|
||||
}
|
||||
// 登录成功
|
||||
@@ -125,7 +123,7 @@ public class LoginService {
|
||||
userInfo.setPassword(GenerateUtil.getUUID());
|
||||
userInfo.setNickname(loginResult.getNickname());
|
||||
userInfo.setAvatar("");
|
||||
userInfo.setStatus(AdminUserStatusEnum.ENABLE.getStatus());
|
||||
userInfo.setStatus(StatusEnum.ENABLE.getStatus());
|
||||
userInfo.setRegType(loginResult.getRegTypeEnum().getValue());
|
||||
userInfo.setEmail(loginResult.getEmail());
|
||||
sysAdminUserService.save(userInfo);
|
||||
|
@@ -1,34 +0,0 @@
|
||||
package com.gitee.sop.adminbackend.service.sys.login.enums;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* @author 六如
|
||||
*/
|
||||
public enum AdminUserStatusEnum {
|
||||
DISABLED((byte)0),
|
||||
ENABLE((byte)1),
|
||||
SET_PWD((byte)2),
|
||||
;
|
||||
|
||||
private final int status;
|
||||
|
||||
public static AdminUserStatusEnum of(Integer value) {
|
||||
for (AdminUserStatusEnum adminUserStatusEnum : AdminUserStatusEnum.values()) {
|
||||
if (Objects.equals(adminUserStatusEnum.status, value)) {
|
||||
return adminUserStatusEnum;
|
||||
}
|
||||
}
|
||||
return DISABLED;
|
||||
}
|
||||
|
||||
AdminUserStatusEnum(byte style) {
|
||||
this.status = style;
|
||||
}
|
||||
|
||||
public int getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
}
|
@@ -5,7 +5,7 @@ import com.gitee.sop.adminbackend.dao.entity.SysAdminUser;
|
||||
import com.gitee.sop.adminbackend.service.sys.SysAdminUserService;
|
||||
import com.gitee.sop.adminbackend.service.sys.login.UserCacheManager;
|
||||
import com.gitee.sop.adminbackend.service.sys.login.dto.LoginUser;
|
||||
import com.gitee.sop.adminbackend.service.sys.login.enums.AdminUserStatusEnum;
|
||||
import com.gitee.sop.adminbackend.common.StatusEnum;
|
||||
import com.gitee.sop.adminbackend.util.CopyUtil;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.cache.CacheLoader;
|
||||
@@ -75,7 +75,7 @@ public class DefaultUserCacheManager implements UserCacheManager, InitializingBe
|
||||
log.warn("登录用户不存在,userId:{}", id);
|
||||
return null;
|
||||
}
|
||||
if (userInfo.getStatus() == AdminUserStatusEnum.DISABLED.getStatus()) {
|
||||
if (userInfo.getStatus() == StatusEnum.DISABLED.getStatus()) {
|
||||
log.warn("用户被禁用, userId:{}, username:{}, nickname:{}", userInfo.getId(), userInfo.getUsername(), userInfo.getNickname());
|
||||
return null;
|
||||
}
|
||||
|
@@ -6,9 +6,7 @@ import gradientString from "gradient-string";
|
||||
import boxen, { type Options as BoxenOptions } from "boxen";
|
||||
dayjs.extend(duration);
|
||||
|
||||
const welcomeMessage = gradientString("cyan", "magenta").multiline(
|
||||
`您好! 欢迎使用 pure-admin 开源项目\n我们为您精心准备了下面两个贴心的保姆级文档\nhttps://pure-admin.github.io/pure-admin-doc\nhttps://pure-admin-utils.netlify.app`
|
||||
);
|
||||
const welcomeMessage = gradientString("cyan", "magenta").multiline(`SOP Admin`);
|
||||
|
||||
const boxenOptions: BoxenOptions = {
|
||||
padding: 0.5,
|
||||
|
@@ -93,7 +93,7 @@ export default defineFlatConfig([
|
||||
"@typescript-eslint/prefer-as-const": "warn",
|
||||
"@typescript-eslint/no-empty-function": "off",
|
||||
"@typescript-eslint/no-non-null-assertion": "off",
|
||||
"@typescript-eslint/no-import-type-side-effects": "error",
|
||||
"@typescript-eslint/no-import-type-side-effects": "off",
|
||||
"@typescript-eslint/explicit-module-boundary-types": "off",
|
||||
"@typescript-eslint/consistent-type-imports": [
|
||||
"error",
|
||||
|
@@ -8,7 +8,7 @@
|
||||
name="viewport"
|
||||
content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=0"
|
||||
/>
|
||||
<title>pure-admin-thin</title>
|
||||
<title>SOP Admin</title>
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
<script>
|
||||
window.process = {};
|
||||
|
@@ -5,7 +5,7 @@ import { defineFakeRoute } from "vite-plugin-fake-server/client";
|
||||
* 服务管理
|
||||
*/
|
||||
const apiRouter = {
|
||||
path: "/serviceManage",
|
||||
path: "/serve",
|
||||
meta: {
|
||||
title: "服务管理",
|
||||
icon: "ri:server-line",
|
||||
@@ -13,7 +13,7 @@ const apiRouter = {
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: "/serviceManage/apiManage/index",
|
||||
path: "/serve/api/index",
|
||||
name: "ApiManage",
|
||||
meta: {
|
||||
title: "接口管理",
|
||||
|
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "pure-admin-thin",
|
||||
"name": "SOP Admin",
|
||||
"version": "5.8.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
@@ -55,6 +55,7 @@
|
||||
"@vueuse/motion": "2.2.3",
|
||||
"animate.css": "4.1.1",
|
||||
"axios": "1.7.4",
|
||||
"crypto-js": "4.2.0",
|
||||
"dayjs": "1.11.12",
|
||||
"echarts": "5.5.1",
|
||||
"element-plus": "2.8.0",
|
||||
|
8
sop-admin/sop-admin-frontend/pnpm-lock.yaml
generated
8
sop-admin/sop-admin-frontend/pnpm-lock.yaml
generated
@@ -29,6 +29,9 @@ importers:
|
||||
axios:
|
||||
specifier: 1.7.4
|
||||
version: 1.7.4
|
||||
crypto-js:
|
||||
specifier: 4.2.0
|
||||
version: 4.2.0
|
||||
dayjs:
|
||||
specifier: 1.11.12
|
||||
version: 1.11.12
|
||||
@@ -1605,6 +1608,9 @@ packages:
|
||||
resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==}
|
||||
engines: {node: '>= 8'}
|
||||
|
||||
crypto-js@4.2.0:
|
||||
resolution: {integrity: sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==}
|
||||
|
||||
css-declaration-sorter@6.4.1:
|
||||
resolution: {integrity: sha512-rtdthzxKuyq6IzqX6jEcIzQF/YqccluefyCYheovBOLhFT/drQA9zj/UbRAa9J7C0o6EG6u3E6g+vKkay7/k3g==}
|
||||
engines: {node: ^10 || ^12 || >=14}
|
||||
@@ -5390,6 +5396,8 @@ snapshots:
|
||||
shebang-command: 2.0.0
|
||||
which: 2.0.2
|
||||
|
||||
crypto-js@4.2.0: {}
|
||||
|
||||
css-declaration-sorter@6.4.1(postcss@8.4.41):
|
||||
dependencies:
|
||||
postcss: 8.4.41
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"Version": "5.8.0",
|
||||
"Title": "PureAdmin",
|
||||
"Title": "SOP Admin",
|
||||
"FixedHeader": true,
|
||||
"HiddenSideBar": false,
|
||||
"MultiTagsCache": false,
|
||||
@@ -12,8 +12,8 @@
|
||||
"OverallStyle": "light",
|
||||
"Grey": false,
|
||||
"Weak": false,
|
||||
"HideTabs": false,
|
||||
"HideFooter": false,
|
||||
"HideTabs": true,
|
||||
"HideFooter": true,
|
||||
"Stretch": false,
|
||||
"SidebarStatus": true,
|
||||
"EpThemeColor": "#409EFF",
|
||||
|
0
sop-admin/sop-admin-frontend/src/api/service/api.ts
Normal file
0
sop-admin/sop-admin-frontend/src/api/service/api.ts
Normal file
@@ -48,9 +48,10 @@ const { t, locale, translationCh, translationEn } = useTranslationLang();
|
||||
<LayNavMix v-if="layout === 'mix'" />
|
||||
|
||||
<div v-if="layout === 'vertical'" class="vertical-header-right">
|
||||
<!-- 菜单搜索 -->
|
||||
<!-- 菜单搜索
|
||||
<LaySearch id="header-search" />
|
||||
<!-- 国际化 -->
|
||||
-->
|
||||
<!-- 国际化
|
||||
<el-dropdown id="header-translation" trigger="click">
|
||||
<GlobalizationIcon
|
||||
class="navbar-bg-hover w-[40px] h-[48px] p-[11px] cursor-pointer outline-none"
|
||||
@@ -82,14 +83,19 @@ const { t, locale, translationCh, translationEn } = useTranslationLang();
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
<!-- 全屏 -->
|
||||
-->
|
||||
<!-- 全屏
|
||||
<LaySidebarFullScreen id="full-screen" />
|
||||
<!-- 消息通知 -->
|
||||
-->
|
||||
<!-- 消息通知
|
||||
<LayNotice id="header-notice" />
|
||||
-->
|
||||
<!-- 退出登录 -->
|
||||
<el-dropdown trigger="click">
|
||||
<span class="el-dropdown-link navbar-bg-hover select-none">
|
||||
<!-- 头像
|
||||
<img :src="userAvatar" :style="avatarsStyle" />
|
||||
-->
|
||||
<p v-if="username" class="dark:text-white">{{ username }}</p>
|
||||
</span>
|
||||
<template #dropdown>
|
||||
@@ -104,6 +110,7 @@ const { t, locale, translationCh, translationEn } = useTranslationLang();
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
<!-- 设置
|
||||
<span
|
||||
class="set-icon navbar-bg-hover"
|
||||
:title="t('buttons.pureOpenSystemSet')"
|
||||
@@ -111,6 +118,7 @@ const { t, locale, translationCh, translationEn } = useTranslationLang();
|
||||
>
|
||||
<IconifyIconOffline :icon="Setting" />
|
||||
</span>
|
||||
-->
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
14
sop-admin/sop-admin-frontend/src/model/index.ts
Normal file
14
sop-admin/sop-admin-frontend/src/model/index.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
export type Result = {
|
||||
success: boolean;
|
||||
data: object;
|
||||
};
|
||||
|
||||
export type PageResult = {
|
||||
success: boolean;
|
||||
msg: "";
|
||||
code: "";
|
||||
data: {
|
||||
total: 0;
|
||||
list: Array<any>;
|
||||
};
|
||||
};
|
@@ -37,7 +37,7 @@ import {
|
||||
* 如何排除文件请看:https://cn.vitejs.dev/guide/features.html#negative-patterns
|
||||
*/
|
||||
const modules: Record<string, any> = import.meta.glob(
|
||||
["./modules/**/*.ts", "!./modules/**/remaining.ts"],
|
||||
["./modules/**/*.ts", "!./modules/**/remaining.ts", "!./modules/**/error.ts"],
|
||||
{
|
||||
eager: true
|
||||
}
|
||||
|
@@ -22,6 +22,7 @@ import globalization from "@/assets/svg/globalization.svg?component";
|
||||
import Lock from "@iconify-icons/ri/lock-fill";
|
||||
import Check from "@iconify-icons/ep/check";
|
||||
import User from "@iconify-icons/ri/user-3-fill";
|
||||
import CryptoJS from "crypto-js";
|
||||
|
||||
defineOptions({
|
||||
name: "Login"
|
||||
@@ -40,8 +41,8 @@ const { title, getDropdownItemStyle, getDropdownItemClass } = useNav();
|
||||
const { locale, translationCh, translationEn } = useTranslationLang();
|
||||
|
||||
const ruleForm = reactive({
|
||||
username: "admin",
|
||||
password: "admin123"
|
||||
username: "",
|
||||
password: ""
|
||||
});
|
||||
|
||||
const onLogin = async (formEl: FormInstance | undefined) => {
|
||||
@@ -49,8 +50,10 @@ const onLogin = async (formEl: FormInstance | undefined) => {
|
||||
await formEl.validate((valid, fields) => {
|
||||
if (valid) {
|
||||
loading.value = true;
|
||||
const pwd = ruleForm.password;
|
||||
const hash = CryptoJS.SHA256(pwd).toString();
|
||||
useUserStoreHook()
|
||||
.loginByUsername({ username: ruleForm.username, password: "admin123" })
|
||||
.loginByUsername({ username: ruleForm.username, password: hash })
|
||||
.then(res => {
|
||||
if (res.success) {
|
||||
// 获取后端路由
|
||||
|
@@ -3,8 +3,8 @@ import type { FormRules } from "element-plus";
|
||||
import { $t, transformI18n } from "@/plugins/i18n";
|
||||
|
||||
/** 密码正则(密码格式应为8-18位数字、字母、符号的任意两种组合) */
|
||||
export const REGEXP_PWD =
|
||||
/^(?![0-9]+$)(?![a-z]+$)(?![A-Z]+$)(?!([^(0-9a-zA-Z)]|[()])+$)(?!^.*[\u4E00-\u9FA5].*$)([^(0-9a-zA-Z)]|[()]|[a-z]|[A-Z]|[0-9]){8,18}$/;
|
||||
// export const REGEXP_PWD =
|
||||
// /^(?![0-9]+$)(?![a-z]+$)(?![A-Z]+$)(?!([^(0-9a-zA-Z)]|[()])+$)(?!^.*[\u4E00-\u9FA5].*$)([^(0-9a-zA-Z)]|[()]|[a-z]|[A-Z]|[0-9]){8,18}$/;
|
||||
|
||||
/** 登录校验 */
|
||||
const loginRules = reactive(<FormRules>{
|
||||
@@ -13,8 +13,6 @@ const loginRules = reactive(<FormRules>{
|
||||
validator: (rule, value, callback) => {
|
||||
if (value === "") {
|
||||
callback(new Error(transformI18n($t("login.purePassWordReg"))));
|
||||
} else if (!REGEXP_PWD.test(value)) {
|
||||
callback(new Error(transformI18n($t("login.purePassWordRuleReg"))));
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
|
315
sop-admin/sop-admin-frontend/src/views/serve/api/index.ts
Normal file
315
sop-admin/sop-admin-frontend/src/views/serve/api/index.ts
Normal file
@@ -0,0 +1,315 @@
|
||||
import { computed, ref } from "vue";
|
||||
import {
|
||||
type PlusColumn,
|
||||
useTable,
|
||||
type PageInfo,
|
||||
type FieldValues,
|
||||
type ButtonsCallBackParams
|
||||
} from "plus-pro-components";
|
||||
import { type PageResult } from "@/model";
|
||||
import { http } from "@/utils/http";
|
||||
import { ElMessage } from "element-plus";
|
||||
|
||||
// 后端请求接口
|
||||
const apiUrl = {
|
||||
page: "/serve/api/page",
|
||||
add: "/serve/api/add",
|
||||
update: "/serve/api/update",
|
||||
del: "/serve/api/delete"
|
||||
};
|
||||
|
||||
// 查询表单对象
|
||||
export const searchFormData = ref({
|
||||
apiName: "",
|
||||
pageIndex: 1,
|
||||
pageSize: 10
|
||||
});
|
||||
// 表格对象
|
||||
export const {
|
||||
tableData,
|
||||
total,
|
||||
pageInfo,
|
||||
buttons: actionButtons
|
||||
} = useTable<any[]>();
|
||||
// 默认每页条数,默认10
|
||||
pageInfo.value.pageSize = 10;
|
||||
|
||||
// 查询表单字段定义
|
||||
export const searchFormColumns: PlusColumn[] = [
|
||||
{
|
||||
label: "接口名称",
|
||||
prop: "apiName"
|
||||
}
|
||||
];
|
||||
|
||||
// 表格字段定义
|
||||
export const tableColumns: PlusColumn[] = [
|
||||
{
|
||||
label: "应用名称",
|
||||
prop: "application"
|
||||
},
|
||||
{
|
||||
label: "接口名称",
|
||||
prop: "apiName"
|
||||
},
|
||||
{
|
||||
label: "版本号",
|
||||
prop: "apiVersion",
|
||||
width: 80
|
||||
},
|
||||
{
|
||||
label: "接口描述",
|
||||
prop: "description"
|
||||
},
|
||||
{
|
||||
label: "需要授权",
|
||||
prop: "isPermission",
|
||||
width: 100,
|
||||
valueType: "select",
|
||||
options: [
|
||||
{
|
||||
label: "否",
|
||||
value: 0,
|
||||
color: "red"
|
||||
},
|
||||
{
|
||||
label: "是",
|
||||
value: 1,
|
||||
color: "green"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
label: "需要token",
|
||||
prop: "isNeedToken",
|
||||
width: 100,
|
||||
valueType: "select",
|
||||
options: [
|
||||
{
|
||||
label: "否",
|
||||
value: 0,
|
||||
color: "red"
|
||||
},
|
||||
{
|
||||
label: "是",
|
||||
value: 1,
|
||||
color: "green"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
label: "状态",
|
||||
prop: "status",
|
||||
width: 80,
|
||||
valueType: "select",
|
||||
options: [
|
||||
{
|
||||
label: "禁用",
|
||||
value: 0,
|
||||
color: "red"
|
||||
},
|
||||
{
|
||||
label: "启用",
|
||||
value: 1,
|
||||
color: "green"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
label: "添加时间",
|
||||
prop: "addTime"
|
||||
}
|
||||
];
|
||||
|
||||
actionButtons.value = [
|
||||
{
|
||||
// 修改
|
||||
text: "修改",
|
||||
code: "edit",
|
||||
props: {
|
||||
type: "primary"
|
||||
},
|
||||
show: computed(() => true),
|
||||
onClick(params: ButtonsCallBackParams) {
|
||||
if (params?.formRefs) {
|
||||
// isEdit v0.1.8 新增
|
||||
const isEdit = params.formRefs[0].isEdit.value;
|
||||
isEdit
|
||||
? params.formRefs[0]?.stopCellEdit()
|
||||
: params.formRefs[0]?.startCellEdit();
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
// 删除
|
||||
text: "删除",
|
||||
code: "delete",
|
||||
props: {
|
||||
type: "danger"
|
||||
},
|
||||
confirm: {
|
||||
options: { draggable: true }
|
||||
},
|
||||
onClick(params: ButtonsCallBackParams) {
|
||||
console.log(params, "onClick");
|
||||
},
|
||||
onConfirm(params: ButtonsCallBackParams) {
|
||||
console.log(params, "onConfirm");
|
||||
},
|
||||
onCancel(params: ButtonsCallBackParams) {
|
||||
console.log(params, "onCancel");
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
// 弹窗表单
|
||||
export const dlgShow = ref(false);
|
||||
export const editFormData = ref<FieldValues>({
|
||||
application: "",
|
||||
status: 1,
|
||||
isPermission: 0,
|
||||
isNeedToken: 0
|
||||
});
|
||||
export const editFormRules = {
|
||||
application: [{ required: true, message: "请输入应用名称" }],
|
||||
apiName: [{ required: true, message: "请输入接口名称" }],
|
||||
apiVersion: [{ required: true, message: "请输入版本号" }],
|
||||
description: [{ required: true, message: "请输入接口描述" }]
|
||||
};
|
||||
export const handleDlgOpen = () => {
|
||||
dlgShow.value = true;
|
||||
};
|
||||
|
||||
export const handleSave = () => {
|
||||
http
|
||||
.post<PageResult, any>(apiUrl.add, { data: editFormData.value })
|
||||
.then(resp => {
|
||||
if (resp.success) {
|
||||
ElMessage({
|
||||
message: "保存成功",
|
||||
type: "success"
|
||||
});
|
||||
dlgShow.value = false;
|
||||
search();
|
||||
} else {
|
||||
console.log(resp);
|
||||
ElMessage.error(`保存失败:${resp.msg}`);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export const editFormColumns: PlusColumn[] = [
|
||||
{
|
||||
label: "应用名称",
|
||||
prop: "application",
|
||||
valueType: "copy"
|
||||
},
|
||||
{
|
||||
label: "接口名称",
|
||||
prop: "apiName",
|
||||
valueType: "copy"
|
||||
},
|
||||
{
|
||||
label: "版本号",
|
||||
prop: "apiVersion",
|
||||
valueType: "copy"
|
||||
},
|
||||
{
|
||||
label: "接口描述",
|
||||
prop: "description",
|
||||
valueType: "copy"
|
||||
},
|
||||
{
|
||||
label: "备注",
|
||||
prop: "remark",
|
||||
valueType: "textarea",
|
||||
fieldProps: {
|
||||
maxlength: 10,
|
||||
showWordLimit: true,
|
||||
autosize: { minRows: 2, maxRows: 4 }
|
||||
}
|
||||
},
|
||||
{
|
||||
label: "需要授权",
|
||||
prop: "isPermission",
|
||||
valueType: "radio",
|
||||
options: [
|
||||
{
|
||||
label: "否",
|
||||
value: 0,
|
||||
color: "red"
|
||||
},
|
||||
{
|
||||
label: "是",
|
||||
value: 1,
|
||||
color: "green"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
label: "需要token",
|
||||
prop: "isNeedToken",
|
||||
valueType: "radio",
|
||||
options: [
|
||||
{
|
||||
label: "否",
|
||||
value: 0,
|
||||
color: "red"
|
||||
},
|
||||
{
|
||||
label: "是",
|
||||
value: 1,
|
||||
color: "green"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
label: "状态",
|
||||
prop: "status",
|
||||
valueType: "radio",
|
||||
options: [
|
||||
{
|
||||
label: "禁用",
|
||||
value: 0,
|
||||
color: "red"
|
||||
},
|
||||
{
|
||||
label: "启用",
|
||||
value: 1,
|
||||
color: "green"
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
// 点击查询按钮
|
||||
export const handleSearch = () => {
|
||||
pageInfo.value.page = 1;
|
||||
search();
|
||||
};
|
||||
|
||||
// 查询
|
||||
const search = async () => {
|
||||
try {
|
||||
const { data } = await doSearch();
|
||||
tableData.value = data.list;
|
||||
total.value = data.total;
|
||||
} catch (error) {}
|
||||
};
|
||||
// 请求接口
|
||||
const doSearch = async () => {
|
||||
// 查询参数
|
||||
const data = searchFormData.value;
|
||||
// 添加分页参数
|
||||
data.pageIndex = pageInfo.value.page;
|
||||
data.pageSize = pageInfo.value.pageSize;
|
||||
|
||||
return http.get<PageResult, any>(apiUrl.page, { params: data });
|
||||
};
|
||||
// 分页事件
|
||||
export const handlePaginationChange = (_pageInfo: PageInfo): void => {
|
||||
pageInfo.value = _pageInfo;
|
||||
search();
|
||||
};
|
||||
// 页面加载
|
||||
search();
|
61
sop-admin/sop-admin-frontend/src/views/serve/api/index.vue
Normal file
61
sop-admin/sop-admin-frontend/src/views/serve/api/index.vue
Normal file
@@ -0,0 +1,61 @@
|
||||
<script setup lang="ts">
|
||||
import {
|
||||
actionButtons,
|
||||
dlgShow,
|
||||
editFormColumns,
|
||||
editFormData,
|
||||
editFormRules,
|
||||
handleDlgOpen,
|
||||
handlePaginationChange,
|
||||
handleSave,
|
||||
handleSearch,
|
||||
pageInfo,
|
||||
searchFormColumns,
|
||||
searchFormData,
|
||||
tableColumns,
|
||||
tableData,
|
||||
total
|
||||
} from "./index";
|
||||
</script>
|
||||
<template>
|
||||
<el-card shadow="never">
|
||||
<template #header>
|
||||
<PlusSearch
|
||||
v-model="searchFormData"
|
||||
:columns="searchFormColumns"
|
||||
:show-number="2"
|
||||
label-position="right"
|
||||
:has-reset="false"
|
||||
@search="handleSearch"
|
||||
/>
|
||||
</template>
|
||||
<PlusTable
|
||||
:columns="tableColumns"
|
||||
:table-data="tableData"
|
||||
:action-bar="{ buttons: actionButtons, width: 120 }"
|
||||
:pagination="{
|
||||
total,
|
||||
modelValue: pageInfo,
|
||||
pageSizeList: [10, 20, 50, 100],
|
||||
align: 'right'
|
||||
}"
|
||||
@paginationChange="handlePaginationChange"
|
||||
>
|
||||
<template #title>
|
||||
<el-button type="primary" @click="handleDlgOpen">新增接口</el-button>
|
||||
</template>
|
||||
</PlusTable>
|
||||
<PlusDialogForm
|
||||
v-model:visible="dlgShow"
|
||||
v-model="editFormData"
|
||||
label-width="200px"
|
||||
:form="{
|
||||
columns: editFormColumns,
|
||||
rules: editFormRules,
|
||||
labelWidth: '100px',
|
||||
labelPosition: 'right'
|
||||
}"
|
||||
@confirm="handleSave"
|
||||
/>
|
||||
</el-card>
|
||||
</template>
|
@@ -1,151 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from "vue";
|
||||
import { type PlusColumn, useTable, PageInfo } from "plus-pro-components";
|
||||
|
||||
const state = ref({
|
||||
status: "0",
|
||||
time: new Date().toString()
|
||||
});
|
||||
|
||||
const columns: PlusColumn[] = [
|
||||
{
|
||||
label: "接口名称",
|
||||
prop: "name"
|
||||
}
|
||||
];
|
||||
|
||||
const handleChange = (values: any) => {
|
||||
console.log(values, "change");
|
||||
};
|
||||
const handleSearch = (values: any) => {
|
||||
console.log(values, "search");
|
||||
};
|
||||
const handleRest = () => {
|
||||
console.log("handleRest");
|
||||
};
|
||||
|
||||
interface TableRow {
|
||||
id: number;
|
||||
name: string;
|
||||
status: string;
|
||||
tag: string;
|
||||
time: Date;
|
||||
}
|
||||
|
||||
const TestServe = {
|
||||
getList: async () => {
|
||||
const data = Array.from({ length: 3 }).map((item, index) => {
|
||||
return {
|
||||
id: index,
|
||||
name: index + "name",
|
||||
status: String(index % 3),
|
||||
tag: "success",
|
||||
time: new Date()
|
||||
};
|
||||
});
|
||||
return {
|
||||
data: data as TableRow[],
|
||||
total: data.length
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
const { tableData, total, pageInfo } = useTable<TableRow[]>();
|
||||
|
||||
pageInfo.value.pageSize = 10;
|
||||
|
||||
const tableConfig: PlusColumn[] = [
|
||||
{
|
||||
label: "名称",
|
||||
prop: "name",
|
||||
disabledHeaderFilter: true,
|
||||
tooltip: "名称",
|
||||
tableColumnProps: {
|
||||
align: "center",
|
||||
showOverflowTooltip: true
|
||||
}
|
||||
},
|
||||
{
|
||||
label: "状态",
|
||||
prop: "status",
|
||||
valueType: "select",
|
||||
options: [
|
||||
{
|
||||
label: "未解决",
|
||||
value: "0",
|
||||
color: "red"
|
||||
},
|
||||
{
|
||||
label: "已解决",
|
||||
value: "1",
|
||||
color: "blue"
|
||||
},
|
||||
{
|
||||
label: "解决中",
|
||||
value: "2",
|
||||
color: "yellow"
|
||||
},
|
||||
{
|
||||
label: "失败",
|
||||
value: "3",
|
||||
color: "red"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
label: "标签",
|
||||
prop: "tag",
|
||||
valueType: "tag",
|
||||
fieldProps: (value: string) => {
|
||||
return { type: value };
|
||||
}
|
||||
},
|
||||
{
|
||||
label: "时间",
|
||||
prop: "time",
|
||||
valueType: "date-picker"
|
||||
}
|
||||
];
|
||||
|
||||
const getList = async () => {
|
||||
try {
|
||||
const { data, total: dataTotal } = await TestServe.getList();
|
||||
tableData.value = data;
|
||||
total.value = dataTotal;
|
||||
} catch (error) {}
|
||||
};
|
||||
const handlePaginationChange = (_pageInfo: PageInfo): void => {
|
||||
pageInfo.value = _pageInfo;
|
||||
getList();
|
||||
};
|
||||
getList();
|
||||
</script>
|
||||
<template>
|
||||
<el-card>
|
||||
<PlusSearch
|
||||
v-model="state"
|
||||
:columns="columns"
|
||||
:show-number="2"
|
||||
label-position="right"
|
||||
:has-reset="false"
|
||||
@change="handleChange"
|
||||
@search="handleSearch"
|
||||
@reset="handleRest"
|
||||
/>
|
||||
<el-divider />
|
||||
<PlusTable
|
||||
:columns="tableConfig"
|
||||
:table-data="tableData"
|
||||
:pagination="{
|
||||
total,
|
||||
modelValue: pageInfo,
|
||||
pageSizeList: [10, 20, 50, 100],
|
||||
align: 'right'
|
||||
}"
|
||||
>
|
||||
<template #title>
|
||||
<el-button type="primary">新增接口</el-button>
|
||||
</template>
|
||||
</PlusTable>
|
||||
</el-card>
|
||||
</template>
|
@@ -5,5 +5,5 @@ defineOptions({
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<h1>Pure-Admin-Thin(国际化版本)</h1>
|
||||
<h1>欢迎使用SOP Admin</h1>
|
||||
</template>
|
||||
|
@@ -24,7 +24,14 @@ export default ({ mode }: ConfigEnv): UserConfigExport => {
|
||||
port: VITE_PORT,
|
||||
host: "0.0.0.0",
|
||||
// 本地跨域代理 https://cn.vitejs.dev/config/server-options.html#server-proxy
|
||||
proxy: {},
|
||||
proxy: {
|
||||
"/api": {
|
||||
// 这里填写后端地址
|
||||
target: "http://127.0.0.1:8082",
|
||||
changeOrigin: true,
|
||||
rewrite: path => path.replace(/^\/api/, "")
|
||||
}
|
||||
},
|
||||
// 预热文件以提前转换和缓存结果,降低启动期间的初始页面加载时长并防止转换瀑布
|
||||
warmup: {
|
||||
clientFiles: ["./index.html", "./src/{views,components}/*"]
|
||||
|
@@ -11,20 +11,54 @@ import java.io.Serializable;
|
||||
public class ApiInfoDTO implements Serializable {
|
||||
private static final long serialVersionUID = 2183251167679411550L;
|
||||
|
||||
/**
|
||||
* 应用名称
|
||||
*/
|
||||
private String application;
|
||||
|
||||
/**
|
||||
* 接口名称
|
||||
*/
|
||||
private String apiName;
|
||||
|
||||
/**
|
||||
* 版本号
|
||||
*/
|
||||
private String apiVersion;
|
||||
|
||||
/**
|
||||
* 接口描述
|
||||
*/
|
||||
private String description;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* 接口class
|
||||
*/
|
||||
private String interfaceClassName;
|
||||
|
||||
/**
|
||||
* 方法名称
|
||||
*/
|
||||
private String methodName;
|
||||
|
||||
/**
|
||||
* 参数信息
|
||||
*/
|
||||
private String paramInfo;
|
||||
|
||||
/**
|
||||
* 接口是否需要授权访问
|
||||
*/
|
||||
private Integer isPermission;
|
||||
|
||||
/**
|
||||
* 是否需要appAuthToken
|
||||
*/
|
||||
private Integer isNeedToken;
|
||||
|
||||
private Integer status;
|
||||
|
@@ -10,7 +10,7 @@ import lombok.Getter;
|
||||
@Getter
|
||||
public enum StatusEnum {
|
||||
ENABLE(1),
|
||||
DISABLE(2);
|
||||
DISABLE(0);
|
||||
|
||||
private final int value;
|
||||
|
||||
|
@@ -1,7 +1,6 @@
|
||||
package com.gitee.sop.index.dao.entity;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Date;
|
||||
|
||||
import com.gitee.fastmybatis.annotation.Pk;
|
||||
import com.gitee.fastmybatis.annotation.PkStrategy;
|
||||
@@ -37,6 +36,16 @@ public class ApiInfo {
|
||||
*/
|
||||
private String apiVersion;
|
||||
|
||||
/**
|
||||
* 接口描述
|
||||
*/
|
||||
private String description;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* 接口class
|
||||
*/
|
||||
@@ -63,7 +72,7 @@ public class ApiInfo {
|
||||
private Integer isNeedToken;
|
||||
|
||||
/**
|
||||
* 状态,1-启用,0-禁用
|
||||
* 1启用,2禁用
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
|
@@ -11,25 +11,54 @@ import java.io.Serializable;
|
||||
public class RegisterDTO implements Serializable {
|
||||
private static final long serialVersionUID = 2183251167679411550L;
|
||||
|
||||
/**
|
||||
* 应用名称
|
||||
*/
|
||||
private String application;
|
||||
|
||||
/**
|
||||
* 接口名称
|
||||
*/
|
||||
private String apiName;
|
||||
|
||||
/**
|
||||
* 版本号
|
||||
*/
|
||||
private String apiVersion;
|
||||
|
||||
/**
|
||||
* 接口描述
|
||||
*/
|
||||
private String description;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* 接口class
|
||||
*/
|
||||
private String interfaceClassName;
|
||||
|
||||
/**
|
||||
* 方法名称
|
||||
*/
|
||||
private String methodName;
|
||||
|
||||
/**
|
||||
* 字段信息
|
||||
*
|
||||
* [{"name":"id": "type":"java.lang.Integer"}]
|
||||
* 参数信息
|
||||
*/
|
||||
private String paramInfo;
|
||||
|
||||
/**
|
||||
* 接口是否需要授权访问
|
||||
*/
|
||||
private Integer isPermission;
|
||||
|
||||
/**
|
||||
* 是否需要appAuthToken
|
||||
*/
|
||||
private Integer isNeedToken;
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user