| @@ -1,61 +0,0 @@ | |||||
| .resource-item { | |||||
| position: relative; | |||||
| width: calc(25% - 15px); | |||||
| padding: 20px; | |||||
| background: white; | |||||
| border: 1px solid #eaeaea; | |||||
| border-radius: 4px; | |||||
| cursor: pointer; | |||||
| @media screen and (max-width: 1860px) { | |||||
| & { | |||||
| width: calc(33.33% - 13.33px); | |||||
| } | |||||
| } | |||||
| &__name { | |||||
| position: relative; | |||||
| display: inline-block; | |||||
| height: 24px; | |||||
| margin: 0 10px 0 0 !important; | |||||
| color: @text-color; | |||||
| font-size: 16px; | |||||
| } | |||||
| &__description { | |||||
| height: 44px; | |||||
| margin-bottom: 20px; | |||||
| color: @text-color-secondary; | |||||
| font-size: 14px; | |||||
| .multiLine(2); | |||||
| } | |||||
| &__time { | |||||
| display: flex; | |||||
| flex: 0 1 content; | |||||
| align-items: center; | |||||
| width: 100%; | |||||
| color: #808080; | |||||
| font-size: 13px; | |||||
| } | |||||
| &:hover { | |||||
| border-color: @primary-color; | |||||
| box-shadow: 0px 0px 6px 1px rgba(0, 0, 0, 0.1); | |||||
| .resource-item__name { | |||||
| color: @primary-color; | |||||
| } | |||||
| } | |||||
| } | |||||
| .resource-item__name { | |||||
| &::after { | |||||
| position: absolute; | |||||
| top: 14px; | |||||
| left: 0; | |||||
| width: 100%; | |||||
| height: 6px; | |||||
| background: linear-gradient(to right, rgba(22, 100, 255, 0.3) 0, rgba(22, 100, 255, 0) 100%); | |||||
| content: ''; | |||||
| } | |||||
| } | |||||
| @@ -1,54 +0,0 @@ | |||||
| import clock from '@/assets/img/clock.png'; | |||||
| import creatByImg from '@/assets/img/creatBy.png'; | |||||
| import KFIcon from '@/components/KFIcon'; | |||||
| import { formatDate } from '@/utils/date'; | |||||
| import { Button, Flex, Typography } from 'antd'; | |||||
| import { ResourceData } from '../../config'; | |||||
| import styles from './index.less'; | |||||
| type ResourceItemProps = { | |||||
| item: ResourceData; | |||||
| isPublic: boolean; | |||||
| onRemove: (item: ResourceData) => void; | |||||
| onClick: (item: ResourceData) => void; | |||||
| }; | |||||
| function ResourceItem({ item, isPublic, onClick, onRemove }: ResourceItemProps) { | |||||
| return ( | |||||
| <div className={styles['resource-item']} onClick={() => onClick(item)}> | |||||
| <Flex justify="space-between" align="center" style={{ marginBottom: '20px', height: '32px' }}> | |||||
| <Typography.Paragraph | |||||
| className={styles['resource-item__name']} | |||||
| ellipsis={{ tooltip: item.name }} | |||||
| > | |||||
| {item.name} | |||||
| </Typography.Paragraph> | |||||
| {!isPublic && ( | |||||
| <Button | |||||
| type="text" | |||||
| shape="circle" | |||||
| onClick={(e) => { | |||||
| e.stopPropagation(); | |||||
| onRemove(item); | |||||
| }} | |||||
| > | |||||
| <KFIcon type="icon-shanchu" font={17} /> | |||||
| </Button> | |||||
| )} | |||||
| </Flex> | |||||
| <div className={styles['resource-item__description']}>{item.description}</div> | |||||
| <Flex justify="space-between"> | |||||
| <div className={styles['resource-item__time']}> | |||||
| <img style={{ width: '17px', marginRight: '6px' }} src={creatByImg} alt="" /> | |||||
| <span>{item.create_by}</span> | |||||
| </div> | |||||
| <div className={styles['resource-item__time']}> | |||||
| <img style={{ width: '12px', marginRight: '5px' }} src={clock} alt="" /> | |||||
| <span>最近更新: {formatDate(item.update_time, 'YYYY-MM-DD')}</span> | |||||
| </div> | |||||
| </Flex> | |||||
| </div> | |||||
| ); | |||||
| } | |||||
| export default ResourceItem; | |||||
| @@ -1,323 +1,344 @@ | |||||
| package com.ruoyi.system.api.domain; | package com.ruoyi.system.api.domain; | ||||
| import java.util.Date; | |||||
| import java.util.List; | |||||
| import javax.validation.constraints.*; | |||||
| import org.apache.commons.lang3.builder.ToStringBuilder; | |||||
| import org.apache.commons.lang3.builder.ToStringStyle; | |||||
| import com.ruoyi.common.core.annotation.Excel; | import com.ruoyi.common.core.annotation.Excel; | ||||
| import com.ruoyi.common.core.annotation.Excel.ColumnType; | import com.ruoyi.common.core.annotation.Excel.ColumnType; | ||||
| import com.ruoyi.common.core.annotation.Excel.Type; | import com.ruoyi.common.core.annotation.Excel.Type; | ||||
| import com.ruoyi.common.core.annotation.Excels; | import com.ruoyi.common.core.annotation.Excels; | ||||
| import com.ruoyi.common.core.web.domain.BaseEntity; | import com.ruoyi.common.core.web.domain.BaseEntity; | ||||
| import com.ruoyi.common.core.xss.Xss; | import com.ruoyi.common.core.xss.Xss; | ||||
| import org.apache.commons.lang3.builder.ToStringBuilder; | |||||
| import org.apache.commons.lang3.builder.ToStringStyle; | |||||
| import javax.validation.constraints.Email; | |||||
| import javax.validation.constraints.NotBlank; | |||||
| import javax.validation.constraints.Size; | |||||
| import java.util.Date; | |||||
| import java.util.List; | |||||
| /** | /** | ||||
| * 用户对象 sys_user | * 用户对象 sys_user | ||||
| * | |||||
| * | |||||
| * @author ruoyi | * @author ruoyi | ||||
| */ | */ | ||||
| public class SysUser extends BaseEntity | |||||
| { | |||||
| public class SysUser extends BaseEntity { | |||||
| private static final long serialVersionUID = 1L; | private static final long serialVersionUID = 1L; | ||||
| /** 用户ID */ | |||||
| /** | |||||
| * 用户ID | |||||
| */ | |||||
| @Excel(name = "用户序号", cellType = ColumnType.NUMERIC, prompt = "用户编号") | @Excel(name = "用户序号", cellType = ColumnType.NUMERIC, prompt = "用户编号") | ||||
| private Long userId; | private Long userId; | ||||
| /** 部门ID */ | |||||
| /** | |||||
| * 部门ID | |||||
| */ | |||||
| @Excel(name = "部门编号", type = Type.IMPORT) | @Excel(name = "部门编号", type = Type.IMPORT) | ||||
| private Long deptId; | private Long deptId; | ||||
| /** 用户账号 */ | |||||
| /** | |||||
| * 用户账号 | |||||
| */ | |||||
| @Excel(name = "登录名称") | @Excel(name = "登录名称") | ||||
| private String userName; | private String userName; | ||||
| /** 用户昵称 */ | |||||
| /** | |||||
| * 用户昵称 | |||||
| */ | |||||
| @Excel(name = "用户名称") | @Excel(name = "用户名称") | ||||
| private String nickName; | private String nickName; | ||||
| /** 用户邮箱 */ | |||||
| /** | |||||
| * 用户邮箱 | |||||
| */ | |||||
| @Excel(name = "用户邮箱") | @Excel(name = "用户邮箱") | ||||
| private String email; | private String email; | ||||
| /** 手机号码 */ | |||||
| /** | |||||
| * 手机号码 | |||||
| */ | |||||
| @Excel(name = "手机号码") | @Excel(name = "手机号码") | ||||
| private String phonenumber; | private String phonenumber; | ||||
| /** 用户性别 */ | |||||
| /** | |||||
| * 用户性别 | |||||
| */ | |||||
| @Excel(name = "用户性别", readConverterExp = "0=男,1=女,2=未知") | @Excel(name = "用户性别", readConverterExp = "0=男,1=女,2=未知") | ||||
| private String sex; | private String sex; | ||||
| /** 用户头像 */ | |||||
| /** | |||||
| * 用户头像 | |||||
| */ | |||||
| private String avatar; | private String avatar; | ||||
| /** 密码 */ | |||||
| /** | |||||
| * 密码 | |||||
| */ | |||||
| private String password; | private String password; | ||||
| /** 帐号状态(0正常 1停用) */ | |||||
| /** | |||||
| * 帐号状态(0正常 1停用) | |||||
| */ | |||||
| @Excel(name = "帐号状态", readConverterExp = "0=正常,1=停用") | @Excel(name = "帐号状态", readConverterExp = "0=正常,1=停用") | ||||
| private String status; | private String status; | ||||
| /** 删除标志(0代表存在 2代表删除) */ | |||||
| /** | |||||
| * 删除标志(0代表存在 2代表删除) | |||||
| */ | |||||
| private String delFlag; | private String delFlag; | ||||
| /** 最后登录IP */ | |||||
| /** | |||||
| * 最后登录IP | |||||
| */ | |||||
| @Excel(name = "最后登录IP", type = Type.EXPORT) | @Excel(name = "最后登录IP", type = Type.EXPORT) | ||||
| private String loginIp; | private String loginIp; | ||||
| /** 最后登录时间 */ | |||||
| /** | |||||
| * 最后登录时间 | |||||
| */ | |||||
| @Excel(name = "最后登录时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss", type = Type.EXPORT) | @Excel(name = "最后登录时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss", type = Type.EXPORT) | ||||
| private Date loginDate; | private Date loginDate; | ||||
| /** 部门对象 */ | |||||
| /** | |||||
| * 部门对象 | |||||
| */ | |||||
| @Excels({ | @Excels({ | ||||
| @Excel(name = "部门名称", targetAttr = "deptName", type = Type.EXPORT), | |||||
| @Excel(name = "部门负责人", targetAttr = "leader", type = Type.EXPORT) | |||||
| @Excel(name = "部门名称", targetAttr = "deptName", type = Type.EXPORT), | |||||
| @Excel(name = "部门负责人", targetAttr = "leader", type = Type.EXPORT) | |||||
| }) | }) | ||||
| private SysDept dept; | private SysDept dept; | ||||
| /** 角色对象 */ | |||||
| /** | |||||
| * 角色对象 | |||||
| */ | |||||
| private List<SysRole> roles; | private List<SysRole> roles; | ||||
| /** 角色组 */ | |||||
| /** | |||||
| * 角色组 | |||||
| */ | |||||
| private Long[] roleIds; | private Long[] roleIds; | ||||
| /** 岗位组 */ | |||||
| /** | |||||
| * 岗位组 | |||||
| */ | |||||
| private Long[] postIds; | private Long[] postIds; | ||||
| /** 角色ID */ | |||||
| /** | |||||
| * 角色ID | |||||
| */ | |||||
| private Long roleId; | private Long roleId; | ||||
| public SysUser() | |||||
| { | |||||
| private String gitLinkUsername; | |||||
| private String gitLinkPassword; | |||||
| public SysUser() { | |||||
| } | } | ||||
| public SysUser(Long userId) | |||||
| { | |||||
| public SysUser(Long userId) { | |||||
| this.userId = userId; | this.userId = userId; | ||||
| } | } | ||||
| public Long getUserId() | |||||
| { | |||||
| public Long getUserId() { | |||||
| return userId; | return userId; | ||||
| } | } | ||||
| public void setUserId(Long userId) | |||||
| { | |||||
| public void setUserId(Long userId) { | |||||
| this.userId = userId; | this.userId = userId; | ||||
| } | } | ||||
| public boolean isAdmin() | |||||
| { | |||||
| public boolean isAdmin() { | |||||
| return isAdmin(this.userId); | return isAdmin(this.userId); | ||||
| } | } | ||||
| public static boolean isAdmin(Long userId) | |||||
| { | |||||
| public static boolean isAdmin(Long userId) { | |||||
| return userId != null && 1L == userId; | return userId != null && 1L == userId; | ||||
| } | } | ||||
| public Long getDeptId() | |||||
| { | |||||
| public Long getDeptId() { | |||||
| return deptId; | return deptId; | ||||
| } | } | ||||
| public void setDeptId(Long deptId) | |||||
| { | |||||
| public void setDeptId(Long deptId) { | |||||
| this.deptId = deptId; | this.deptId = deptId; | ||||
| } | } | ||||
| @Xss(message = "用户昵称不能包含脚本字符") | @Xss(message = "用户昵称不能包含脚本字符") | ||||
| @Size(min = 0, max = 30, message = "用户昵称长度不能超过30个字符") | @Size(min = 0, max = 30, message = "用户昵称长度不能超过30个字符") | ||||
| public String getNickName() | |||||
| { | |||||
| public String getNickName() { | |||||
| return nickName; | return nickName; | ||||
| } | } | ||||
| public void setNickName(String nickName) | |||||
| { | |||||
| public void setNickName(String nickName) { | |||||
| this.nickName = nickName; | this.nickName = nickName; | ||||
| } | } | ||||
| @Xss(message = "用户账号不能包含脚本字符") | @Xss(message = "用户账号不能包含脚本字符") | ||||
| @NotBlank(message = "用户账号不能为空") | @NotBlank(message = "用户账号不能为空") | ||||
| @Size(min = 0, max = 30, message = "用户账号长度不能超过30个字符") | @Size(min = 0, max = 30, message = "用户账号长度不能超过30个字符") | ||||
| public String getUserName() | |||||
| { | |||||
| public String getUserName() { | |||||
| return userName; | return userName; | ||||
| } | } | ||||
| public void setUserName(String userName) | |||||
| { | |||||
| public void setUserName(String userName) { | |||||
| this.userName = userName; | this.userName = userName; | ||||
| } | } | ||||
| @Email(message = "邮箱格式不正确") | @Email(message = "邮箱格式不正确") | ||||
| @Size(min = 0, max = 50, message = "邮箱长度不能超过50个字符") | @Size(min = 0, max = 50, message = "邮箱长度不能超过50个字符") | ||||
| public String getEmail() | |||||
| { | |||||
| public String getEmail() { | |||||
| return email; | return email; | ||||
| } | } | ||||
| public void setEmail(String email) | |||||
| { | |||||
| public void setEmail(String email) { | |||||
| this.email = email; | this.email = email; | ||||
| } | } | ||||
| @Size(min = 0, max = 11, message = "手机号码长度不能超过11个字符") | @Size(min = 0, max = 11, message = "手机号码长度不能超过11个字符") | ||||
| public String getPhonenumber() | |||||
| { | |||||
| public String getPhonenumber() { | |||||
| return phonenumber; | return phonenumber; | ||||
| } | } | ||||
| public void setPhonenumber(String phonenumber) | |||||
| { | |||||
| public void setPhonenumber(String phonenumber) { | |||||
| this.phonenumber = phonenumber; | this.phonenumber = phonenumber; | ||||
| } | } | ||||
| public String getSex() | |||||
| { | |||||
| public String getSex() { | |||||
| return sex; | return sex; | ||||
| } | } | ||||
| public void setSex(String sex) | |||||
| { | |||||
| public void setSex(String sex) { | |||||
| this.sex = sex; | this.sex = sex; | ||||
| } | } | ||||
| public String getAvatar() | |||||
| { | |||||
| public String getAvatar() { | |||||
| return avatar; | return avatar; | ||||
| } | } | ||||
| public void setAvatar(String avatar) | |||||
| { | |||||
| public void setAvatar(String avatar) { | |||||
| this.avatar = avatar; | this.avatar = avatar; | ||||
| } | } | ||||
| public String getPassword() | |||||
| { | |||||
| public String getPassword() { | |||||
| return password; | return password; | ||||
| } | } | ||||
| public void setPassword(String password) | |||||
| { | |||||
| public void setPassword(String password) { | |||||
| this.password = password; | this.password = password; | ||||
| } | } | ||||
| public String getStatus() | |||||
| { | |||||
| public String getStatus() { | |||||
| return status; | return status; | ||||
| } | } | ||||
| public void setStatus(String status) | |||||
| { | |||||
| public void setStatus(String status) { | |||||
| this.status = status; | this.status = status; | ||||
| } | } | ||||
| public String getDelFlag() | |||||
| { | |||||
| public String getDelFlag() { | |||||
| return delFlag; | return delFlag; | ||||
| } | } | ||||
| public void setDelFlag(String delFlag) | |||||
| { | |||||
| public void setDelFlag(String delFlag) { | |||||
| this.delFlag = delFlag; | this.delFlag = delFlag; | ||||
| } | } | ||||
| public String getLoginIp() | |||||
| { | |||||
| public String getLoginIp() { | |||||
| return loginIp; | return loginIp; | ||||
| } | } | ||||
| public void setLoginIp(String loginIp) | |||||
| { | |||||
| public void setLoginIp(String loginIp) { | |||||
| this.loginIp = loginIp; | this.loginIp = loginIp; | ||||
| } | } | ||||
| public Date getLoginDate() | |||||
| { | |||||
| public Date getLoginDate() { | |||||
| return loginDate; | return loginDate; | ||||
| } | } | ||||
| public void setLoginDate(Date loginDate) | |||||
| { | |||||
| public void setLoginDate(Date loginDate) { | |||||
| this.loginDate = loginDate; | this.loginDate = loginDate; | ||||
| } | } | ||||
| public SysDept getDept() | |||||
| { | |||||
| public SysDept getDept() { | |||||
| return dept; | return dept; | ||||
| } | } | ||||
| public void setDept(SysDept dept) | |||||
| { | |||||
| public void setDept(SysDept dept) { | |||||
| this.dept = dept; | this.dept = dept; | ||||
| } | } | ||||
| public List<SysRole> getRoles() | |||||
| { | |||||
| public List<SysRole> getRoles() { | |||||
| return roles; | return roles; | ||||
| } | } | ||||
| public void setRoles(List<SysRole> roles) | |||||
| { | |||||
| public void setRoles(List<SysRole> roles) { | |||||
| this.roles = roles; | this.roles = roles; | ||||
| } | } | ||||
| public Long[] getRoleIds() | |||||
| { | |||||
| public Long[] getRoleIds() { | |||||
| return roleIds; | return roleIds; | ||||
| } | } | ||||
| public void setRoleIds(Long[] roleIds) | |||||
| { | |||||
| public void setRoleIds(Long[] roleIds) { | |||||
| this.roleIds = roleIds; | this.roleIds = roleIds; | ||||
| } | } | ||||
| public Long[] getPostIds() | |||||
| { | |||||
| public Long[] getPostIds() { | |||||
| return postIds; | return postIds; | ||||
| } | } | ||||
| public void setPostIds(Long[] postIds) | |||||
| { | |||||
| public void setPostIds(Long[] postIds) { | |||||
| this.postIds = postIds; | this.postIds = postIds; | ||||
| } | } | ||||
| public Long getRoleId() | |||||
| { | |||||
| public Long getRoleId() { | |||||
| return roleId; | return roleId; | ||||
| } | } | ||||
| public void setRoleId(Long roleId) | |||||
| { | |||||
| public void setRoleId(Long roleId) { | |||||
| this.roleId = roleId; | this.roleId = roleId; | ||||
| } | } | ||||
| public void setGitLinkUsername(String gitLinkUsername) { | |||||
| this.gitLinkUsername = gitLinkUsername; | |||||
| } | |||||
| public String getGitLinkUsername() { | |||||
| return gitLinkUsername; | |||||
| } | |||||
| public void setGitLinkPassword(String gitLinkPassword) { | |||||
| this.gitLinkPassword = gitLinkPassword; | |||||
| } | |||||
| public String getGitLinkPassword() { | |||||
| return gitLinkPassword; | |||||
| } | |||||
| @Override | @Override | ||||
| public String toString() { | public String toString() { | ||||
| return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) | |||||
| .append("userId", getUserId()) | |||||
| .append("deptId", getDeptId()) | |||||
| .append("userName", getUserName()) | |||||
| .append("nickName", getNickName()) | |||||
| .append("email", getEmail()) | |||||
| .append("phonenumber", getPhonenumber()) | |||||
| .append("sex", getSex()) | |||||
| .append("avatar", getAvatar()) | |||||
| .append("password", getPassword()) | |||||
| .append("status", getStatus()) | |||||
| .append("delFlag", getDelFlag()) | |||||
| .append("loginIp", getLoginIp()) | |||||
| .append("loginDate", getLoginDate()) | |||||
| .append("createBy", getCreateBy()) | |||||
| .append("createTime", getCreateTime()) | |||||
| .append("updateBy", getUpdateBy()) | |||||
| .append("updateTime", getUpdateTime()) | |||||
| .append("remark", getRemark()) | |||||
| .append("dept", getDept()) | |||||
| .toString(); | |||||
| return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE) | |||||
| .append("userId", getUserId()) | |||||
| .append("deptId", getDeptId()) | |||||
| .append("userName", getUserName()) | |||||
| .append("nickName", getNickName()) | |||||
| .append("email", getEmail()) | |||||
| .append("phonenumber", getPhonenumber()) | |||||
| .append("sex", getSex()) | |||||
| .append("avatar", getAvatar()) | |||||
| .append("password", getPassword()) | |||||
| .append("status", getStatus()) | |||||
| .append("delFlag", getDelFlag()) | |||||
| .append("loginIp", getLoginIp()) | |||||
| .append("loginDate", getLoginDate()) | |||||
| .append("createBy", getCreateBy()) | |||||
| .append("createTime", getCreateTime()) | |||||
| .append("updateBy", getUpdateBy()) | |||||
| .append("updateTime", getUpdateTime()) | |||||
| .append("remark", getRemark()) | |||||
| .append("dept", getDept()) | |||||
| .append("gitLinkUsername", getGitLinkUsername()) | |||||
| .append("gitLinkPassword", getGitLinkPassword()) | |||||
| .toString(); | |||||
| } | } | ||||
| } | } | ||||
| @@ -15,6 +15,10 @@ spring: | |||||
| discovery: | discovery: | ||||
| # 服务注册地址 | # 服务注册地址 | ||||
| server-addr: nacos-ci4s.ci4s-test.svc:8848 | server-addr: nacos-ci4s.ci4s-test.svc:8848 | ||||
| username: nacos | |||||
| password: nacos | |||||
| retry: | |||||
| enabled: true | |||||
| config: | config: | ||||
| # 配置中心地址 | # 配置中心地址 | ||||
| server-addr: nacos-ci4s.ci4s-test.svc:8848 | server-addr: nacos-ci4s.ci4s-test.svc:8848 | ||||
| @@ -22,4 +26,9 @@ spring: | |||||
| file-extension: yml | file-extension: yml | ||||
| # 共享配置 | # 共享配置 | ||||
| shared-configs: | shared-configs: | ||||
| - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} | |||||
| - data-id: application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} | |||||
| group: DEFAULT_GROUP | |||||
| refresh: true | |||||
| - data-id: ${spring.application.name}-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} | |||||
| group: DEFAULT_GROUP | |||||
| refresh: true | |||||
| @@ -15,6 +15,10 @@ spring: | |||||
| discovery: | discovery: | ||||
| # 服务注册地址 | # 服务注册地址 | ||||
| server-addr: nacos-ci4s.ci4s-test.svc:8848 | server-addr: nacos-ci4s.ci4s-test.svc:8848 | ||||
| username: nacos | |||||
| password: nacos | |||||
| retry: | |||||
| enabled: true | |||||
| config: | config: | ||||
| # 配置中心地址 | # 配置中心地址 | ||||
| server-addr: nacos-ci4s.ci4s-test.svc:8848 | server-addr: nacos-ci4s.ci4s-test.svc:8848 | ||||
| @@ -22,7 +26,12 @@ spring: | |||||
| file-extension: yml | file-extension: yml | ||||
| # 共享配置 | # 共享配置 | ||||
| shared-configs: | shared-configs: | ||||
| - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} | |||||
| - data-id: application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} | |||||
| group: DEFAULT_GROUP | |||||
| refresh: true | |||||
| - data-id: ${spring.application.name}-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} | |||||
| group: DEFAULT_GROUP | |||||
| refresh: true | |||||
| sentinel: | sentinel: | ||||
| # 取消控制台懒加载 | # 取消控制台懒加载 | ||||
| eager: true | eager: true | ||||
| @@ -33,7 +42,7 @@ spring: | |||||
| datasource: | datasource: | ||||
| ds1: | ds1: | ||||
| nacos: | nacos: | ||||
| server-addr: nacos-ci4s.ci4s-test.svc:8848 | |||||
| server-addr: nacos-ci4s.ci4s-test.svc:18848 | |||||
| dataId: sentinel-ruoyi-gateway | dataId: sentinel-ruoyi-gateway | ||||
| groupId: DEFAULT_GROUP | groupId: DEFAULT_GROUP | ||||
| data-type: json | data-type: json | ||||
| @@ -140,7 +140,17 @@ | |||||
| <dependency> | <dependency> | ||||
| <groupId>com.github.docker-java</groupId> | <groupId>com.github.docker-java</groupId> | ||||
| <artifactId>docker-java</artifactId> | <artifactId>docker-java</artifactId> | ||||
| <version>3.1.1</version> | |||||
| <version>3.2.13</version> | |||||
| </dependency> | |||||
| <dependency> | |||||
| <groupId>commons-beanutils</groupId> | |||||
| <artifactId>commons-beanutils</artifactId> | |||||
| <version>1.9.4</version> | |||||
| </dependency> | |||||
| <dependency> | |||||
| <groupId>com.github.docker-java</groupId> | |||||
| <artifactId>docker-java-transport-httpclient5</artifactId> | |||||
| <version>3.2.13</version> | |||||
| </dependency> | </dependency> | ||||
| <dependency> | <dependency> | ||||
| <groupId>com.baomidou</groupId> | <groupId>com.baomidou</groupId> | ||||
| @@ -216,7 +226,22 @@ | |||||
| <version>3.0.8</version> | <version>3.0.8</version> | ||||
| <scope>compile</scope> | <scope>compile</scope> | ||||
| </dependency> | </dependency> | ||||
| <dependency> | |||||
| <groupId>commons-lang</groupId> | |||||
| <artifactId>commons-lang</artifactId> | |||||
| <version>2.6</version> | |||||
| <scope>compile</scope> | |||||
| </dependency> | |||||
| <dependency> | |||||
| <groupId>org.eclipse.jgit</groupId> | |||||
| <artifactId>org.eclipse.jgit</artifactId> | |||||
| <version>5.13.0.202109080827-r</version> | |||||
| </dependency> | |||||
| <dependency> | |||||
| <groupId>redis.clients</groupId> | |||||
| <artifactId>jedis</artifactId> | |||||
| <version>3.6.0</version> | |||||
| </dependency> | |||||
| </dependencies> | </dependencies> | ||||
| @@ -0,0 +1,21 @@ | |||||
| package com.ruoyi.platform.constant; | |||||
| public class Constant { | |||||
| public final static int Image_Type_Pub = 1; // 公共镜像 | |||||
| public final static int Image_Type_Pri = 0; // 私有镜像 | |||||
| public final static int Code_Repo_Pub = 1; // 代码仓库可见性-公开 | |||||
| public final static int Code_Repo_Pri = 0; // 代码仓库可见性-私有 | |||||
| public final static int State_valid = 1; // 有效 | |||||
| public final static int State_invalid = 0; // 无效 | |||||
| public final static int Used_State_used = 1; // 已占用 | |||||
| public final static int Used_State_unused = 0; // 未占用 | |||||
| public final static String Computing_Resource_CPU = "CPU"; // 计算资源_CPU | |||||
| public final static String Computing_Resource_GPU = "GPU"; // 计算资源_GPU | |||||
| } | |||||
| @@ -0,0 +1,69 @@ | |||||
| package com.ruoyi.platform.controller.codeConfig; | |||||
| import com.ruoyi.common.core.web.controller.BaseController; | |||||
| import com.ruoyi.common.core.web.domain.GenericsAjaxResult; | |||||
| import com.ruoyi.platform.domain.CodeConfig; | |||||
| import com.ruoyi.platform.service.CodeConfigService; | |||||
| import io.swagger.annotations.Api; | |||||
| import org.springframework.data.domain.Page; | |||||
| import org.springframework.data.domain.PageRequest; | |||||
| import org.springframework.http.ResponseEntity; | |||||
| import org.springframework.web.bind.annotation.*; | |||||
| import javax.annotation.Resource; | |||||
| @RestController | |||||
| @RequestMapping("codeConfig") | |||||
| @Api("代码配置") | |||||
| public class CodeConfigController extends BaseController { | |||||
| @Resource | |||||
| private CodeConfigService codeConfigService; | |||||
| /** | |||||
| * 分页查询 | |||||
| * | |||||
| * @param codeConfig 筛选条件 | |||||
| * @param page 页数 | |||||
| * @param size 每页大小 | |||||
| * @return 查询结果 | |||||
| */ | |||||
| @GetMapping | |||||
| public GenericsAjaxResult<Page<CodeConfig>> queryByPage(@RequestParam("page") int page, | |||||
| @RequestParam("size") int size, | |||||
| @RequestParam(value = "code_repo_name", required = false) String codeRepoName, | |||||
| @RequestParam(value = "code_repo_vis", required = false)Integer codeRepoVis) { | |||||
| PageRequest pageRequest = PageRequest.of(page, size); | |||||
| CodeConfig codeConfig = new CodeConfig(); | |||||
| codeConfig.setCodeRepoName(codeRepoName); | |||||
| codeConfig.setCodeRepoVis(codeRepoVis); | |||||
| return genericsSuccess(this.codeConfigService.queryByPage(codeConfig, pageRequest)); | |||||
| } | |||||
| /** | |||||
| * 通过主键查询单条数据 | |||||
| * | |||||
| * @param id | |||||
| * @return 单条数据 | |||||
| */ | |||||
| @GetMapping("{id}") | |||||
| public GenericsAjaxResult<CodeConfig> queryById(@PathVariable("id") Long id) { | |||||
| return genericsSuccess(this.codeConfigService.queryById(id)); | |||||
| } | |||||
| @PostMapping | |||||
| public GenericsAjaxResult<CodeConfig> add(@RequestBody CodeConfig codeConfig) { | |||||
| return genericsSuccess(this.codeConfigService.insert(codeConfig)); | |||||
| } | |||||
| @PutMapping | |||||
| public GenericsAjaxResult<CodeConfig> update(@RequestBody CodeConfig codeConfig) { | |||||
| return genericsSuccess(this.codeConfigService.update(codeConfig)); | |||||
| } | |||||
| @DeleteMapping("{id}") | |||||
| public GenericsAjaxResult<String> delete(@PathVariable("id") Long id) { | |||||
| return genericsSuccess(this.codeConfigService.removeById(id)); | |||||
| } | |||||
| } | |||||
| @@ -224,5 +224,7 @@ public class DatasetController { | |||||
| public AjaxResult uploadDatasetPipeline(@RequestBody(required =false) DatasetVersion datasetVersion) throws Exception { | public AjaxResult uploadDatasetPipeline(@RequestBody(required =false) DatasetVersion datasetVersion) throws Exception { | ||||
| return AjaxResult.success(this.datasetService.uploadDatasetPipeline(datasetVersion)); | return AjaxResult.success(this.datasetService.uploadDatasetPipeline(datasetVersion)); | ||||
| } | } | ||||
| } | } | ||||
| @@ -0,0 +1,115 @@ | |||||
| package com.ruoyi.platform.controller.dataset; | |||||
| import com.ruoyi.common.core.web.domain.AjaxResult; | |||||
| import com.ruoyi.platform.domain.Dataset; | |||||
| import com.ruoyi.platform.service.DatasetService; | |||||
| import com.ruoyi.platform.vo.DatasetVo; | |||||
| import io.swagger.annotations.Api; | |||||
| import io.swagger.annotations.ApiOperation; | |||||
| import org.springframework.core.io.InputStreamResource; | |||||
| import org.springframework.data.domain.PageRequest; | |||||
| import org.springframework.http.ResponseEntity; | |||||
| import org.springframework.web.bind.annotation.*; | |||||
| import org.springframework.web.multipart.MultipartFile; | |||||
| import javax.annotation.Resource; | |||||
| @RestController | |||||
| @RequestMapping("newdataset") | |||||
| @Api(value = "新数据集管理") | |||||
| public class NewDatasetFromGitController { | |||||
| /** | |||||
| * 服务对象 | |||||
| */ | |||||
| @Resource | |||||
| private DatasetService datasetService; | |||||
| /** | |||||
| * 新增数据集与版本新 | |||||
| * | |||||
| * @param datasetVo 实体 | |||||
| * @return 新增结果 | |||||
| */ | |||||
| @PostMapping("/addDatasetAndVersion") | |||||
| @ApiOperation("添加数据集和版本") | |||||
| public AjaxResult addDatasetAndVersion(@RequestBody DatasetVo datasetVo) throws Exception { | |||||
| return AjaxResult.success(this.datasetService.newCreateDataset(datasetVo)); | |||||
| } | |||||
| /** | |||||
| * 新增数据集与版本新 | |||||
| * | |||||
| * @param datasetVo 实体 | |||||
| * @return 新增结果 | |||||
| */ | |||||
| @PostMapping("/addVersion") | |||||
| @ApiOperation("添加版本") | |||||
| public AjaxResult addVersion(@RequestBody DatasetVo datasetVo) throws Exception { | |||||
| return AjaxResult.success(this.datasetService.newCreateVersion(datasetVo)); | |||||
| } | |||||
| /** | |||||
| * 上传数据集 | |||||
| * | |||||
| * @param files 上传的数据集文件 | |||||
| * @param uuid 上传唯一标识,构建url | |||||
| * @return 上传结果 | |||||
| */ | |||||
| @CrossOrigin(origins = "*", allowedHeaders = "*") | |||||
| @PostMapping("/upload") | |||||
| @ApiOperation(value = "上传数据集") | |||||
| public AjaxResult uploadDataset(@RequestParam("file") MultipartFile[] files, @RequestParam("uuid") String uuid) throws Exception { | |||||
| return AjaxResult.success(this.datasetService.uploadDatasetlocal(files,uuid)); | |||||
| } | |||||
| /** | |||||
| * 数据集打包下载 | |||||
| * | |||||
| * @param version 数据集版本 | |||||
| * @return 单条数据 | |||||
| */ | |||||
| @GetMapping("/downloadAllFiles") | |||||
| @ApiOperation(value = "下载同一版本下所有数据集,并打包") | |||||
| public ResponseEntity<InputStreamResource> downloadAllDatasetFiles(@RequestParam("repository_name") String repositoryName, @RequestParam("version") String version) throws Exception { | |||||
| return datasetService.downloadAllDatasetFilesNew(repositoryName, version); | |||||
| } | |||||
| /** | |||||
| * 下载数据集 | |||||
| * | |||||
| * @param dataset_version_id ps:这里的id是dataset_version表的主键 | |||||
| * @return 单条数据 | |||||
| */ | |||||
| @GetMapping("/download/{dataset_version_id}") | |||||
| @ApiOperation(value = "下载单个数据集文件", notes = "根据数据集版本表id下载单个数据集文件") | |||||
| public ResponseEntity<InputStreamResource> downloadDataset(@PathVariable("dataset_version_id") Integer dataset_version_id) throws Exception { | |||||
| return datasetService.downloadDataset(dataset_version_id); | |||||
| } | |||||
| @GetMapping("/queryDatasets") | |||||
| @ApiOperation("数据集广场公开数据集分页查询,根据data_type,data_tag筛选,true公开false私有") | |||||
| public AjaxResult queryDatasets(Dataset dataset, @RequestParam("page") int page, | |||||
| @RequestParam("size") int size, | |||||
| @RequestParam(value = "is_public") Boolean isPublic, | |||||
| @RequestParam(value = "data_type", required = false) String dataType, | |||||
| @RequestParam(value = "data_tag", required = false) String dataTag) throws Exception { | |||||
| PageRequest pageRequest = PageRequest.of(page, size); | |||||
| if(isPublic){ | |||||
| return AjaxResult.success(this.datasetService.newPubilcQueryByPage(dataset, pageRequest)); | |||||
| }else { | |||||
| return AjaxResult.success(this.datasetService.newPersonalQueryByPage(dataset, pageRequest)); | |||||
| } | |||||
| } | |||||
| @GetMapping("/getdatasetDetail") | |||||
| @ApiOperation(value = "获取数据集详情") | |||||
| public AjaxResult getDatasetVersions(@PathVariable("datasetId") Integer datasetId) throws Exception { | |||||
| return AjaxResult.success(this.datasetService.getDatasetVersions(datasetId)); | |||||
| } | |||||
| } | |||||
| @@ -45,7 +45,7 @@ public class ImageController extends BaseController { | |||||
| @RequestParam("size") int size, | @RequestParam("size") int size, | ||||
| @RequestParam(value = "image_type") int imageType) { | @RequestParam(value = "image_type") int imageType) { | ||||
| image.setImageType(imageType); | image.setImageType(imageType); | ||||
| PageRequest pageRequest = PageRequest.of(page,size); | |||||
| PageRequest pageRequest = PageRequest.of(page, size); | |||||
| return genericsSuccess(this.imageService.queryByPage(image, pageRequest)); | return genericsSuccess(this.imageService.queryByPage(image, pageRequest)); | ||||
| } | } | ||||
| @@ -72,22 +72,21 @@ public class ImageController extends BaseController { | |||||
| public GenericsAjaxResult<Page<Image>> queryByName(@PathVariable("name") String name) { | public GenericsAjaxResult<Page<Image>> queryByName(@PathVariable("name") String name) { | ||||
| return genericsSuccess(this.imageService.queryByName(name)); | return genericsSuccess(this.imageService.queryByName(name)); | ||||
| } | } | ||||
| /** | /** | ||||
| * 新增数据 | * 新增数据 | ||||
| * | * | ||||
| * @param image 实体 | * @param image 实体 | ||||
| * @return 新增结果 | * @return 新增结果 | ||||
| */ | */ | ||||
| @PostMapping | |||||
| @ApiOperation("新增镜像,不包含镜像版本") | @ApiOperation("新增镜像,不包含镜像版本") | ||||
| public GenericsAjaxResult<Image> add(@RequestBody Image image) { | public GenericsAjaxResult<Image> add(@RequestBody Image image) { | ||||
| return genericsSuccess(this.imageService.insert(image)); | return genericsSuccess(this.imageService.insert(image)); | ||||
| } | } | ||||
| /** | /** | ||||
| * 新增镜像和版本 | |||||
| * | |||||
| * @param imageVo 实体 | * @param imageVo 实体 | ||||
| * 新增镜像和版本 @PostMapping | |||||
| * @return 新增结果 | * @return 新增结果 | ||||
| */ | */ | ||||
| @PostMapping("/addImageAndVersion") | @PostMapping("/addImageAndVersion") | ||||
| @@ -123,21 +122,20 @@ public class ImageController extends BaseController { | |||||
| @PostMapping("/net") | @PostMapping("/net") | ||||
| @ApiOperation("从网络上传构建镜像") | @ApiOperation("从网络上传构建镜像") | ||||
| public GenericsAjaxResult<Map<String, String>> createImageFromNet(@RequestParam("name") String imageName, | public GenericsAjaxResult<Map<String, String>> createImageFromNet(@RequestParam("name") String imageName, | ||||
| @RequestParam("tag") String imageTag, | |||||
| @RequestParam("path") String path) throws Exception { | |||||
| return genericsSuccess(this.imageService.createImageFromNet(imageName,imageTag,path)); | |||||
| @RequestParam("tag") String imageTag, | |||||
| @RequestParam("path") String path) throws Exception { | |||||
| return genericsSuccess(this.imageService.createImageFromNet(imageName, imageTag, path)); | |||||
| } | } | ||||
| @PostMapping("/local") | @PostMapping("/local") | ||||
| @ApiOperation("从本地上传构建镜像") | @ApiOperation("从本地上传构建镜像") | ||||
| public GenericsAjaxResult<Map<String, String>> createImageFromLocal(@RequestParam("name") String imageName, | public GenericsAjaxResult<Map<String, String>> createImageFromLocal(@RequestParam("name") String imageName, | ||||
| @RequestParam("tag") String imageTag, | |||||
| @RequestParam("path") String path) throws Exception { | |||||
| return genericsSuccess(this.imageService.createImageFromLocal(imageName,imageTag,path)); | |||||
| @RequestParam("tag") String imageTag, | |||||
| @RequestParam("path") String path) throws Exception { | |||||
| return genericsSuccess(this.imageService.createImageFromLocal(imageName, imageTag, path)); | |||||
| } | } | ||||
| /** | /** | ||||
| * 镜像上传 | * 镜像上传 | ||||
| * | * | ||||
| @@ -146,8 +144,14 @@ public class ImageController extends BaseController { | |||||
| @PostMapping("/upload") | @PostMapping("/upload") | ||||
| @ApiOperation(value = "上传镜像文件", notes = "上传镜像tar包,返回存储路径") | @ApiOperation(value = "上传镜像文件", notes = "上传镜像tar包,返回存储路径") | ||||
| public GenericsAjaxResult<Map<String, String>> uploadImageFiles(@RequestParam("file") MultipartFile file) throws Exception { | public GenericsAjaxResult<Map<String, String>> uploadImageFiles(@RequestParam("file") MultipartFile file) throws Exception { | ||||
| return genericsSuccess(this.imageService.uploadImageFiles(file)); | |||||
| return genericsSuccess(this.imageService.uploadImageFiles(file)); | |||||
| } | } | ||||
| @PostMapping("/saveImage") | |||||
| @ApiOperation(value = "保存环境为镜像", notes = "docker commit方式保存,并推送到horbor") | |||||
| public void saveImage(@RequestBody ImageVo imageVo) { | |||||
| this.imageService.saveImage(imageVo); | |||||
| } | |||||
| } | } | ||||
| @@ -4,9 +4,12 @@ import com.ruoyi.common.core.web.controller.BaseController; | |||||
| import com.ruoyi.common.core.web.domain.AjaxResult; | import com.ruoyi.common.core.web.domain.AjaxResult; | ||||
| import com.ruoyi.common.core.web.domain.GenericsAjaxResult; | import com.ruoyi.common.core.web.domain.GenericsAjaxResult; | ||||
| import com.ruoyi.platform.domain.DevEnvironment; | import com.ruoyi.platform.domain.DevEnvironment; | ||||
| import com.ruoyi.platform.service.DatasetService; | |||||
| import com.ruoyi.platform.service.JupyterService; | import com.ruoyi.platform.service.JupyterService; | ||||
| import com.ruoyi.platform.vo.DatasetVo; | |||||
| import com.ruoyi.platform.vo.FrameLogPathVo; | import com.ruoyi.platform.vo.FrameLogPathVo; | ||||
| import com.ruoyi.platform.vo.PodStatusVo; | import com.ruoyi.platform.vo.PodStatusVo; | ||||
| import com.ruoyi.platform.vo.VersionVo; | |||||
| import io.swagger.annotations.Api; | import io.swagger.annotations.Api; | ||||
| import io.swagger.annotations.ApiOperation; | import io.swagger.annotations.ApiOperation; | ||||
| import io.swagger.v3.oas.annotations.responses.ApiResponse; | import io.swagger.v3.oas.annotations.responses.ApiResponse; | ||||
| @@ -17,6 +20,8 @@ import java.io.File; | |||||
| import java.io.FileInputStream; | import java.io.FileInputStream; | ||||
| import java.io.IOException; | import java.io.IOException; | ||||
| import java.io.InputStream; | import java.io.InputStream; | ||||
| import java.util.ArrayList; | |||||
| import java.util.List; | |||||
| @RestController | @RestController | ||||
| @RequestMapping("/jupyter") | @RequestMapping("/jupyter") | ||||
| @@ -24,6 +29,8 @@ import java.io.InputStream; | |||||
| public class JupyterController extends BaseController { | public class JupyterController extends BaseController { | ||||
| @Resource | @Resource | ||||
| private JupyterService jupyterService; | private JupyterService jupyterService; | ||||
| @Resource | |||||
| private DatasetService datasetService; | |||||
| @GetMapping(value = "/getURL") | @GetMapping(value = "/getURL") | ||||
| @ApiOperation("得到访问地址") | @ApiOperation("得到访问地址") | ||||
| public GenericsAjaxResult<String> getURL() throws IOException { | public GenericsAjaxResult<String> getURL() throws IOException { | ||||
| @@ -79,4 +86,21 @@ public class JupyterController extends BaseController { | |||||
| jupyterService.mlflow(); | jupyterService.mlflow(); | ||||
| return AjaxResult.success(); | return AjaxResult.success(); | ||||
| } | } | ||||
| @GetMapping(value = "/testdvc") | |||||
| public AjaxResult testdvc() throws Exception { | |||||
| DatasetVo datasetVo = new DatasetVo(); | |||||
| datasetVo.setName("testdassad23"); | |||||
| datasetVo.setDescription("sss"); | |||||
| datasetVo.setAvailableRange(0); | |||||
| datasetVo.setDataTag("计算机视觉"); | |||||
| datasetVo.setDataType("机器翻译"); | |||||
| datasetVo.setVersion("dev"); | |||||
| List<VersionVo> datasetVersionVos = new ArrayList<>(); | |||||
| VersionVo versionVo = new VersionVo(); | |||||
| versionVo.setUrl("E:/test/bb/data/xssa.doc"); | |||||
| datasetVersionVos.add(versionVo); | |||||
| datasetVo.setDatasetVersionVos(datasetVersionVos); | |||||
| return AjaxResult.success(datasetService.newCreateDataset(datasetVo)); | |||||
| } | |||||
| } | } | ||||
| @@ -0,0 +1,57 @@ | |||||
| package com.ruoyi.platform.domain; | |||||
| import com.fasterxml.jackson.databind.PropertyNamingStrategy; | |||||
| import com.fasterxml.jackson.databind.annotation.JsonNaming; | |||||
| import io.swagger.annotations.ApiModelProperty; | |||||
| import lombok.Data; | |||||
| import java.io.Serializable; | |||||
| import java.util.Date; | |||||
| @Data | |||||
| @JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class) | |||||
| public class CodeConfig implements Serializable { | |||||
| private Long id; | |||||
| @ApiModelProperty(name = "code_repo_name",value = "代码仓库名称") | |||||
| private String codeRepoName; | |||||
| @ApiModelProperty(name = "code_repo_vis", value = "代码仓库可见性(1-公开,0-私有)") | |||||
| private Integer codeRepoVis; | |||||
| @ApiModelProperty(name = "git_url", value = "Git地址") | |||||
| private String gitUrl; | |||||
| @ApiModelProperty(name = "git_branch", value = "代码分支/Tag") | |||||
| private String gitBranch; | |||||
| @ApiModelProperty(name = "verify_mode", value = "验证方式(0-用户名密码,1-SSH-Key)") | |||||
| private Integer verifyMode; | |||||
| @ApiModelProperty(name = "git_user_name", value = "Git用户名") | |||||
| private String gitUserName; | |||||
| @ApiModelProperty(name = "git_password", value = "Git密码") | |||||
| private String gitPassword; | |||||
| @ApiModelProperty(name = "ssh_key",value = "SSH Key") | |||||
| private String sshKey; | |||||
| @ApiModelProperty(name = "create_by", value = "创建者") | |||||
| private String createBy; | |||||
| @ApiModelProperty(name = "create_time", value = "创建时间") | |||||
| private Date createTime; | |||||
| @ApiModelProperty(name = "update_by", value = "更新者") | |||||
| private String updateBy; | |||||
| @ApiModelProperty(name = "update_time", value = "更新时间") | |||||
| private Date updateTime; | |||||
| @ApiModelProperty(name = "state", value = "状态,0失效1生效") | |||||
| private Integer state; | |||||
| } | |||||
| @@ -46,7 +46,11 @@ private Integer id; | |||||
| @ApiModelProperty(value = "状态标识", notes = "0表示失效,1表示生效") | @ApiModelProperty(value = "状态标识", notes = "0表示失效,1表示生效") | ||||
| private Integer state; | private Integer state; | ||||
| @ApiModelProperty(value = "占用情况(1-占用,0-未占用)") | |||||
| private Integer usedState; | |||||
| @ApiModelProperty(value = "节点") | |||||
| private String node; | |||||
| public Integer getId() { | public Integer getId() { | ||||
| return id; | return id; | ||||
| @@ -122,5 +126,20 @@ private Integer id; | |||||
| this.state = state; | this.state = state; | ||||
| } | } | ||||
| public Integer getUsedState() { | |||||
| return usedState; | |||||
| } | |||||
| public void setUsedState(Integer usedState) { | |||||
| this.usedState = usedState; | |||||
| } | |||||
| public String getNode() { | |||||
| return node; | |||||
| } | |||||
| public void setNode(String node) { | |||||
| this.node = node; | |||||
| } | |||||
| } | } | ||||
| @@ -3,6 +3,7 @@ package com.ruoyi.platform.domain; | |||||
| import com.fasterxml.jackson.databind.PropertyNamingStrategy; | import com.fasterxml.jackson.databind.PropertyNamingStrategy; | ||||
| import com.fasterxml.jackson.databind.annotation.JsonNaming; | import com.fasterxml.jackson.databind.annotation.JsonNaming; | ||||
| import io.swagger.annotations.ApiModelProperty; | import io.swagger.annotations.ApiModelProperty; | ||||
| import lombok.Data; | |||||
| import java.util.Date; | import java.util.Date; | ||||
| import java.io.Serializable; | import java.io.Serializable; | ||||
| @@ -14,6 +15,7 @@ import java.io.Serializable; | |||||
| * @since 2024-03-05 15:00:02 | * @since 2024-03-05 15:00:02 | ||||
| */ | */ | ||||
| @JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class) | @JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class) | ||||
| @Data | |||||
| public class ImageVersion implements Serializable { | public class ImageVersion implements Serializable { | ||||
| private static final long serialVersionUID = 251017725389874890L; | private static final long serialVersionUID = 251017725389874890L; | ||||
| /** | /** | ||||
| @@ -56,102 +58,7 @@ public class ImageVersion implements Serializable { | |||||
| @ApiModelProperty(value = "状态,0失效,1生效") | @ApiModelProperty(value = "状态,0失效,1生效") | ||||
| private Integer state; | private Integer state; | ||||
| public Integer getId() { | |||||
| return id; | |||||
| } | |||||
| public void setId(Integer id) { | |||||
| this.id = id; | |||||
| } | |||||
| public Integer getImageId() { | |||||
| return imageId; | |||||
| } | |||||
| public void setImageId(Integer imageId) { | |||||
| this.imageId = imageId; | |||||
| } | |||||
| public String getVersion() { | |||||
| return version; | |||||
| } | |||||
| public void setVersion(String version) { | |||||
| this.version = version; | |||||
| } | |||||
| public String getUrl() { | |||||
| return url; | |||||
| } | |||||
| public void setUrl(String url) { | |||||
| this.url = url; | |||||
| } | |||||
| public String getTagName() { | |||||
| return tagName; | |||||
| } | |||||
| public void setTagName(String tagName) { | |||||
| this.tagName = tagName; | |||||
| } | |||||
| public String getFileSize() { | |||||
| return fileSize; | |||||
| } | |||||
| public void setFileSize(String fileSize) { | |||||
| this.fileSize = fileSize; | |||||
| } | |||||
| public String getStatus() { | |||||
| return status; | |||||
| } | |||||
| public void setStatus(String status) { | |||||
| this.status = status; | |||||
| } | |||||
| public String getCreateBy() { | |||||
| return createBy; | |||||
| } | |||||
| public void setCreateBy(String createBy) { | |||||
| this.createBy = createBy; | |||||
| } | |||||
| public Date getCreateTime() { | |||||
| return createTime; | |||||
| } | |||||
| public void setCreateTime(Date createTime) { | |||||
| this.createTime = createTime; | |||||
| } | |||||
| public String getUpdateBy() { | |||||
| return updateBy; | |||||
| } | |||||
| public void setUpdateBy(String updateBy) { | |||||
| this.updateBy = updateBy; | |||||
| } | |||||
| public Date getUpdateTime() { | |||||
| return updateTime; | |||||
| } | |||||
| public void setUpdateTime(Date updateTime) { | |||||
| this.updateTime = updateTime; | |||||
| } | |||||
| public Integer getState() { | |||||
| return state; | |||||
| } | |||||
| public void setState(Integer state) { | |||||
| this.state = state; | |||||
| } | |||||
| @ApiModelProperty(value = "镜像所在主机ip") | |||||
| private String hostIp; | |||||
| } | } | ||||
| @@ -0,0 +1,22 @@ | |||||
| package com.ruoyi.platform.mapper; | |||||
| import com.ruoyi.platform.domain.CodeConfig; | |||||
| import org.apache.ibatis.annotations.Param; | |||||
| import org.springframework.data.domain.Pageable; | |||||
| import java.util.List; | |||||
| public interface CodeConfigDao { | |||||
| long count(@Param("codeConfig") CodeConfig codeConfig); | |||||
| List<CodeConfig> queryAllByLimit(@Param("codeConfig") CodeConfig codeConfig, @Param("pageable") Pageable pageable); | |||||
| CodeConfig queryById(Long id); | |||||
| Long queryByCodeRepoName(@Param("codeRepoName") String codeRepoName); | |||||
| int insert(@Param("codeConfig") CodeConfig codeConfig); | |||||
| int update(@Param("codeConfig") CodeConfig codeConfig); | |||||
| } | |||||
| @@ -73,6 +73,8 @@ public interface ComputingResourceDao { | |||||
| */ | */ | ||||
| int update(@Param("computingResource") ComputingResource computingResource); | int update(@Param("computingResource") ComputingResource computingResource); | ||||
| int updateUsedStateByNode(@Param("node")String node, @Param("usedState") Integer usedState); | |||||
| /** | /** | ||||
| * 通过主键删除数据 | * 通过主键删除数据 | ||||
| * | * | ||||
| @@ -0,0 +1,19 @@ | |||||
| package com.ruoyi.platform.service; | |||||
| import com.ruoyi.platform.domain.CodeConfig; | |||||
| import org.springframework.data.domain.Page; | |||||
| import org.springframework.data.domain.PageRequest; | |||||
| public interface CodeConfigService { | |||||
| Page<CodeConfig> queryByPage(CodeConfig codeConfig, PageRequest pageRequest); | |||||
| CodeConfig queryById(Long id); | |||||
| CodeConfig insert(CodeConfig codeConfig); | |||||
| CodeConfig update(CodeConfig codeConfig); | |||||
| String removeById(Long id); | |||||
| } | |||||
| @@ -3,14 +3,17 @@ package com.ruoyi.platform.service; | |||||
| import com.ruoyi.platform.domain.Dataset; | import com.ruoyi.platform.domain.Dataset; | ||||
| import com.ruoyi.platform.domain.DatasetVersion; | import com.ruoyi.platform.domain.DatasetVersion; | ||||
| import com.ruoyi.platform.vo.DatasetVo; | import com.ruoyi.platform.vo.DatasetVo; | ||||
| import com.ruoyi.platform.vo.NewDatasetVo; | |||||
| import org.springframework.core.io.InputStreamResource; | import org.springframework.core.io.InputStreamResource; | ||||
| import org.springframework.data.domain.Page; | import org.springframework.data.domain.Page; | ||||
| import org.springframework.data.domain.PageRequest; | import org.springframework.data.domain.PageRequest; | ||||
| import org.springframework.http.ResponseEntity; | import org.springframework.http.ResponseEntity; | ||||
| import org.springframework.web.multipart.MultipartFile; | import org.springframework.web.multipart.MultipartFile; | ||||
| import java.io.IOException; | |||||
| import java.util.List; | import java.util.List; | ||||
| import java.util.Map; | import java.util.Map; | ||||
| import java.util.concurrent.CompletableFuture; | |||||
| /** | /** | ||||
| * (Dataset)表服务接口 | * (Dataset)表服务接口 | ||||
| @@ -84,4 +87,19 @@ DatasetService { | |||||
| ResponseEntity<InputStreamResource> downloadAllDatasetFiles(Integer datasetId, String version) throws Exception; | ResponseEntity<InputStreamResource> downloadAllDatasetFiles(Integer datasetId, String version) throws Exception; | ||||
| List<Map<String, String>> exportDataset(String path, String uuid) throws Exception; | List<Map<String, String>> exportDataset(String path, String uuid) throws Exception; | ||||
| CompletableFuture<String> newCreateDataset(DatasetVo datasetVo) throws Exception; | |||||
| CompletableFuture<String> newCreateVersion(DatasetVo datasetVo); | |||||
| List<Map<String, String>> uploadDatasetlocal(MultipartFile[] files, String uuid) throws Exception; | |||||
| ResponseEntity<InputStreamResource> downloadAllDatasetFilesNew(String repositoryName, String version) throws IOException, Exception; | |||||
| Page<NewDatasetVo> newPersonalQueryByPage(Dataset dataset, PageRequest pageRequest) throws Exception; | |||||
| Page<NewDatasetVo> newPubilcQueryByPage(Dataset dataset, PageRequest pageRequest) throws Exception; | |||||
| } | } | ||||
| @@ -0,0 +1,8 @@ | |||||
| package com.ruoyi.platform.service; | |||||
| public interface DvcService { | |||||
| //使用dvc初始化,跟踪,push到远程仓库的接口 | |||||
| public void initaddpushDvc(String localPath) throws Exception ; | |||||
| } | |||||
| @@ -31,7 +31,7 @@ public interface ExperimentInsService { | |||||
| /** | /** | ||||
| * 根据实验ID查找所有具有相同ID的实例,并将它们添加到实验列表中 | * 根据实验ID查找所有具有相同ID的实例,并将它们添加到实验列表中 | ||||
| * | * | ||||
| * @param experimentId 实验id,不是实例id | |||||
| * @param experimentId 实验id,不是实验实例id | |||||
| * @return 实例列表 | * @return 实例列表 | ||||
| */ | */ | ||||
| List<ExperimentIns> getByExperimentId(Integer experimentId) throws IOException; | List<ExperimentIns> getByExperimentId(Integer experimentId) throws IOException; | ||||
| @@ -0,0 +1,17 @@ | |||||
| package com.ruoyi.platform.service; | |||||
| import com.ruoyi.platform.vo.GitProjectVo; | |||||
| import java.util.Map; | |||||
| public interface GitService { | |||||
| //登录方法,返回token | |||||
| String login(String username, String password); | |||||
| //输入token,项目名,tag,创建新项目,返回项目地址 | |||||
| Map createProject(String token, GitProjectVo gitProjectVo) throws Exception; | |||||
| void createBranch(String token,String owner, String projectName, String branchName, String oldBranchName) throws Exception; | |||||
| void createTopic(String token, Integer id, String topicName) throws Exception; | |||||
| } | |||||
| @@ -93,6 +93,5 @@ public interface ImageService { | |||||
| Map<String, String> createImageFromNet(String imageName, String imageTag, String NetPath) throws Exception; | Map<String, String> createImageFromNet(String imageName, String imageTag, String NetPath) throws Exception; | ||||
| Map<String, String> uploadImageFiles(MultipartFile file) throws Exception; | Map<String, String> uploadImageFiles(MultipartFile file) throws Exception; | ||||
| void saveImage(ImageVo imageVo); | |||||
| } | } | ||||
| @@ -0,0 +1,89 @@ | |||||
| package com.ruoyi.platform.service.impl; | |||||
| import com.ruoyi.common.security.utils.SecurityUtils; | |||||
| import com.ruoyi.platform.constant.Constant; | |||||
| import com.ruoyi.platform.domain.CodeConfig; | |||||
| import com.ruoyi.platform.mapper.CodeConfigDao; | |||||
| import com.ruoyi.platform.service.CodeConfigService; | |||||
| import com.ruoyi.system.api.model.LoginUser; | |||||
| import org.apache.commons.lang3.StringUtils; | |||||
| import org.springframework.data.domain.Page; | |||||
| import org.springframework.data.domain.PageImpl; | |||||
| import org.springframework.data.domain.PageRequest; | |||||
| import org.springframework.stereotype.Service; | |||||
| import javax.annotation.Resource; | |||||
| import java.util.Date; | |||||
| import java.util.List; | |||||
| @Service("codeConfigService") | |||||
| public class CodeConfigServiceImpl implements CodeConfigService { | |||||
| @Resource | |||||
| private CodeConfigDao codeConfigDao; | |||||
| @Override | |||||
| public Page<CodeConfig> queryByPage(CodeConfig codeConfig, PageRequest pageRequest) { | |||||
| long total = this.codeConfigDao.count(codeConfig); | |||||
| List<CodeConfig> codeConfigList = this.codeConfigDao.queryAllByLimit(codeConfig, pageRequest); | |||||
| return new PageImpl<>(codeConfigList, pageRequest, total); | |||||
| } | |||||
| @Override | |||||
| public CodeConfig queryById(Long id) { | |||||
| return this.codeConfigDao.queryById(id); | |||||
| } | |||||
| @Override | |||||
| public CodeConfig insert(CodeConfig codeConfig) { | |||||
| Long id = this.codeConfigDao.queryByCodeRepoName(codeConfig.getCodeRepoName()); | |||||
| if(id != null){ | |||||
| throw new IllegalStateException("代码仓库名称已存在"); | |||||
| } | |||||
| LoginUser loginUser = SecurityUtils.getLoginUser(); | |||||
| codeConfig.setCreateBy(loginUser.getUsername()); | |||||
| codeConfig.setUpdateBy(loginUser.getUsername()); | |||||
| codeConfig.setCreateTime(new Date()); | |||||
| codeConfig.setUpdateTime(new Date()); | |||||
| this.codeConfigDao.insert(codeConfig); | |||||
| return codeConfig; | |||||
| } | |||||
| @Override | |||||
| public CodeConfig update(CodeConfig codeConfig) { | |||||
| Long id = this.codeConfigDao.queryByCodeRepoName(codeConfig.getCodeRepoName()); | |||||
| if(id != null && !id.equals(codeConfig.getId())){ | |||||
| throw new IllegalStateException("代码仓库名称已存在"); | |||||
| } | |||||
| LoginUser loginUser = SecurityUtils.getLoginUser(); | |||||
| codeConfig.setUpdateBy(loginUser.getUsername()); | |||||
| if (codeConfig.getCodeRepoVis().equals(Constant.Code_Repo_Pub)) { | |||||
| codeConfig.setVerifyMode(null); | |||||
| codeConfig.setGitUserName(null); | |||||
| codeConfig.setGitPassword(null); | |||||
| codeConfig.setSshKey(null); | |||||
| } | |||||
| this.codeConfigDao.update(codeConfig); | |||||
| return this.codeConfigDao.queryById(codeConfig.getId()); | |||||
| } | |||||
| @Override | |||||
| public String removeById(Long id) { | |||||
| CodeConfig codeConfig = this.codeConfigDao.queryById(id); | |||||
| if (codeConfig == null) { | |||||
| return "代码配置不存在"; | |||||
| } | |||||
| LoginUser loginUser = SecurityUtils.getLoginUser(); | |||||
| String username = loginUser.getUsername(); | |||||
| String createBy = codeConfig.getCreateBy(); | |||||
| if (!(StringUtils.equals(username, "admin") || StringUtils.equals(username, createBy))) { | |||||
| return "无权限删除该代码配置"; | |||||
| } | |||||
| codeConfig.setState(Constant.State_invalid); | |||||
| return this.codeConfigDao.update(codeConfig) > 0 ? "删除成功" : "删除失败"; | |||||
| } | |||||
| } | |||||
| @@ -1,6 +1,6 @@ | |||||
| package com.ruoyi.platform.service.impl; | package com.ruoyi.platform.service.impl; | ||||
| import com.ruoyi.common.core.utils.DateUtils; | |||||
| import com.ruoyi.common.security.utils.SecurityUtils; | import com.ruoyi.common.security.utils.SecurityUtils; | ||||
| import com.ruoyi.platform.annotations.CheckDuplicate; | import com.ruoyi.platform.annotations.CheckDuplicate; | ||||
| import com.ruoyi.platform.domain.AssetIcon; | import com.ruoyi.platform.domain.AssetIcon; | ||||
| @@ -8,17 +8,15 @@ import com.ruoyi.platform.domain.Dataset; | |||||
| import com.ruoyi.platform.domain.DatasetVersion; | import com.ruoyi.platform.domain.DatasetVersion; | ||||
| import com.ruoyi.platform.mapper.DatasetDao; | import com.ruoyi.platform.mapper.DatasetDao; | ||||
| import com.ruoyi.platform.mapper.DatasetVersionDao; | import com.ruoyi.platform.mapper.DatasetVersionDao; | ||||
| import com.ruoyi.platform.service.AssetIconService; | |||||
| import com.ruoyi.platform.service.DatasetService; | |||||
| import com.ruoyi.platform.service.DatasetVersionService; | |||||
| import com.ruoyi.platform.service.MinioService; | |||||
| import com.ruoyi.platform.utils.BeansUtils; | |||||
| import com.ruoyi.platform.utils.FileUtil; | |||||
| import com.ruoyi.platform.utils.MinioUtil; | |||||
| import com.ruoyi.platform.vo.VersionVo; | |||||
| import com.ruoyi.platform.service.*; | |||||
| import com.ruoyi.platform.utils.*; | |||||
| import com.ruoyi.platform.vo.DatasetVo; | import com.ruoyi.platform.vo.DatasetVo; | ||||
| import com.ruoyi.platform.vo.GitProjectVo; | |||||
| import com.ruoyi.platform.vo.NewDatasetVo; | |||||
| import com.ruoyi.platform.vo.VersionVo; | |||||
| import com.ruoyi.system.api.model.LoginUser; | import com.ruoyi.system.api.model.LoginUser; | ||||
| import io.minio.messages.Item; | import io.minio.messages.Item; | ||||
| import org.apache.commons.io.FileUtils; | |||||
| import org.apache.commons.lang3.StringUtils; | import org.apache.commons.lang3.StringUtils; | ||||
| import org.springframework.beans.factory.annotation.Value; | import org.springframework.beans.factory.annotation.Value; | ||||
| import org.springframework.core.io.InputStreamResource; | import org.springframework.core.io.InputStreamResource; | ||||
| @@ -32,14 +30,17 @@ import org.springframework.http.ResponseEntity; | |||||
| import org.springframework.stereotype.Service; | import org.springframework.stereotype.Service; | ||||
| import org.springframework.transaction.annotation.Transactional; | import org.springframework.transaction.annotation.Transactional; | ||||
| import org.springframework.web.multipart.MultipartFile; | import org.springframework.web.multipart.MultipartFile; | ||||
| import redis.clients.jedis.Jedis; | |||||
| import javax.annotation.Resource; | import javax.annotation.Resource; | ||||
| import java.io.ByteArrayInputStream; | |||||
| import java.io.ByteArrayOutputStream; | |||||
| import java.io.InputStream; | |||||
| import java.io.*; | |||||
| import java.lang.reflect.Field; | import java.lang.reflect.Field; | ||||
| import java.nio.file.Files; | |||||
| import java.nio.file.Path; | |||||
| import java.nio.file.Paths; | |||||
| import java.text.SimpleDateFormat; | import java.text.SimpleDateFormat; | ||||
| import java.util.*; | import java.util.*; | ||||
| import java.util.concurrent.CompletableFuture; | |||||
| import java.util.stream.Collectors; | import java.util.stream.Collectors; | ||||
| import java.util.zip.ZipEntry; | import java.util.zip.ZipEntry; | ||||
| import java.util.zip.ZipOutputStream; | import java.util.zip.ZipOutputStream; | ||||
| @@ -67,6 +68,12 @@ public class DatasetServiceImpl implements DatasetService { | |||||
| @Resource | @Resource | ||||
| private MinioService minioService; | private MinioService minioService; | ||||
| @Resource | |||||
| private GitService gitService; | |||||
| @Resource | |||||
| private DvcService dvcService; | |||||
| // 固定存储桶名 | // 固定存储桶名 | ||||
| @Value("${minio.dataReleaseBucketName}") | @Value("${minio.dataReleaseBucketName}") | ||||
| private String bucketName; | private String bucketName; | ||||
| @@ -74,7 +81,16 @@ public class DatasetServiceImpl implements DatasetService { | |||||
| @Resource | @Resource | ||||
| private MinioUtil minioUtil; | private MinioUtil minioUtil; | ||||
| @Value("${spring.redis.host}") | |||||
| private String redisHost; | |||||
| @Value("${minio.accessKey}") | |||||
| String accessKeyId; | |||||
| @Value("${minio.secretKey}") | |||||
| String secretAccessKey; | |||||
| @Value("${minio.endpoint}") | |||||
| String endpoint; | |||||
| @Value("${git.endpoint}") | |||||
| String gitendpoint; | |||||
| /** | /** | ||||
| * 通过ID查询单条数据 | * 通过ID查询单条数据 | ||||
| @@ -370,7 +386,7 @@ public class DatasetServiceImpl implements DatasetService { | |||||
| } | } | ||||
| @Override | @Override | ||||
| public ResponseEntity<InputStreamResource> downloadAllDatasetFiles(Integer datasetId, String version) throws Exception { | |||||
| public ResponseEntity<InputStreamResource> downloadAllDatasetFiles(Integer datasetId, String version) throws Exception { | |||||
| // 根据数据集id查数据名 | // 根据数据集id查数据名 | ||||
| Dataset dataset = this.datasetDao.queryById(datasetId); | Dataset dataset = this.datasetDao.queryById(datasetId); | ||||
| String datasetName = dataset.getName(); | String datasetName = dataset.getName(); | ||||
| @@ -440,4 +456,294 @@ public class DatasetServiceImpl implements DatasetService { | |||||
| return results; | return results; | ||||
| } | } | ||||
| @Override | |||||
| public CompletableFuture<String> newCreateDataset(DatasetVo datasetVo) { | |||||
| return CompletableFuture.supplyAsync(() -> { | |||||
| try { | |||||
| String token = gitService.login("fanshuai", "h1n2x3j4y5@"); | |||||
| LoginUser loginUser = SecurityUtils.getLoginUser(); | |||||
| String ci4sUsername = loginUser.getUsername(); | |||||
| Jedis jedis = new Jedis(redisHost); | |||||
| String userReq = jedis.get(ci4sUsername + "_gitUserInfo"); | |||||
| Map<String, Object> userInfo = JsonUtils.jsonToMap(userReq); | |||||
| Integer userId = (Integer) userInfo.get("user_id"); | |||||
| // 拼接project | |||||
| String repositoryName = ci4sUsername + "_dataset_" + DateUtils.dateTimeNow(); | |||||
| GitProjectVo gitProjectVo = new GitProjectVo(); | |||||
| gitProjectVo.setRepositoryName(repositoryName); | |||||
| gitProjectVo.setName(datasetVo.getName()); | |||||
| gitProjectVo.setDescription(datasetVo.getDescription()); | |||||
| gitProjectVo.setPrivate(datasetVo.getAvailableRange() == 0); | |||||
| gitProjectVo.setUserId(userId); | |||||
| // 创建项目 | |||||
| Map project = gitService.createProject(token, gitProjectVo); | |||||
| // 创建分支 | |||||
| String branchName = datasetVo.getVersion(); | |||||
| gitService.createBranch(token, (String) userInfo.get("login"), repositoryName, branchName, "master"); | |||||
| // 定义标签 标签1:ci4s_dataset 标签2:DataTag 标签3:DataType | |||||
| gitService.createTopic(token, (Integer) project.get("id"), "ci4s_dataset"); | |||||
| gitService.createTopic(token, (Integer) project.get("id"), "DataTag_" + datasetVo.getDataTag()); | |||||
| gitService.createTopic(token, (Integer) project.get("id"), "DataType_" + datasetVo.getDataType()); | |||||
| // 得到项目地址 | |||||
| String projectUrl = gitendpoint + "/" +(String) userInfo.get("login") + "/" + repositoryName + ".git"; | |||||
| // 得到用户操作的路径 | |||||
| String url = datasetVo.getDatasetVersionVos().get(0).getUrl(); | |||||
| String localPath = "E:/test/" + datasetVo.getName(); | |||||
| String sourcePath = url.substring(0, url.lastIndexOf("/")); | |||||
| // 命令行操作 git clone 项目地址 | |||||
| DVCUtils.gitClone(localPath, projectUrl, branchName, "fanshuai", "h1n2x3j4y5@"); | |||||
| String s3Path = "management-platform-files/" + ci4sUsername + "/datasets/" + repositoryName + "/" + branchName; | |||||
| //拼接生产的元数据后写入yaml文件 | |||||
| YamlUtils.generateYamlFile(JsonUtils.objectToMap(datasetVo),sourcePath, "dataset"); | |||||
| DVCUtils.moveFiles(sourcePath, localPath); | |||||
| // dvc init 初始化 | |||||
| DVCUtils.dvcInit(localPath); | |||||
| // 配置远程S3地址 | |||||
| DVCUtils.dvcRemoteAdd(localPath, s3Path); | |||||
| DVCUtils.dvcConfigS3Credentials(localPath, endpoint); | |||||
| DVCUtils.dvcConfigS3Credentials2(localPath, accessKeyId); | |||||
| DVCUtils.dvcConfigS3Credentials3(localPath, secretAccessKey); | |||||
| // dvc 跟踪 | |||||
| DVCUtils.dvcAdd(localPath, "data"); | |||||
| // git commit | |||||
| DVCUtils.gitAdd(localPath, "."); | |||||
| DVCUtils.gitCommit(localPath, "commit from ci4s with " + loginUser.getUsername()); | |||||
| DVCUtils.gitPush(localPath, "fanshuai", "h1n2x3j4y5@"); | |||||
| // dvc push 到远程S3 | |||||
| DVCUtils.dvcPush(localPath); | |||||
| return "新增数据集成功"; | |||||
| } catch (Exception e) { | |||||
| throw new RuntimeException(e); | |||||
| } | |||||
| }); | |||||
| } | |||||
| @Override | |||||
| public CompletableFuture<String> newCreateVersion(DatasetVo datasetVo) { | |||||
| return CompletableFuture.supplyAsync(() -> { | |||||
| try { | |||||
| String token = gitService.login("fanshuai", "h1n2x3j4y5@"); | |||||
| LoginUser loginUser = SecurityUtils.getLoginUser(); | |||||
| String ci4sUsername = loginUser.getUsername(); | |||||
| Jedis jedis = new Jedis(redisHost); | |||||
| String userReq = jedis.get(ci4sUsername + "_gitUserInfo"); | |||||
| Map<String, Object> userInfo = JsonUtils.jsonToMap(userReq); | |||||
| // 创建分支 | |||||
| String branchName = StringUtils.isEmpty(datasetVo.getVersion())? "master" : datasetVo.getVersion(); | |||||
| String repositoryName = datasetVo.getRepositoryName(); | |||||
| if (StringUtils.equals(branchName, "master")) { | |||||
| gitService.createBranch(token, (String) userInfo.get("login"), repositoryName, branchName, "master"); | |||||
| } | |||||
| // 得到项目地址 | |||||
| String projectUrl = gitendpoint + "/" +(String) userInfo.get("login") + "/" + repositoryName + ".git"; | |||||
| // 得到用户操作的路径 | |||||
| String url = datasetVo.getDatasetVersionVos().get(0).getUrl(); | |||||
| String localPath = "E:/test/"+ loginUser.getUsername()+"/datasets/"+ datasetVo.getName(); | |||||
| String sourcePath = url.substring(0, url.lastIndexOf("/")); | |||||
| // 命令行操作 git clone 项目地址 | |||||
| DVCUtils.gitClone(localPath, projectUrl, branchName, "fanshuai", "h1n2x3j4y5@"); | |||||
| String s3Path = "management-platform-files/" + ci4sUsername + "/datasets/" + repositoryName + "/" + branchName; | |||||
| //拼接生产的元数据后写入yaml文件 | |||||
| YamlUtils.generateYamlFile(JsonUtils.objectToMap(datasetVo),sourcePath, "dataset"); | |||||
| DVCUtils.moveFiles(sourcePath, localPath); | |||||
| // dvc init 初始化 | |||||
| DVCUtils.dvcInit(localPath); | |||||
| // 配置远程S3地址 | |||||
| DVCUtils.dvcRemoteAdd(localPath, s3Path); | |||||
| DVCUtils.dvcConfigS3Credentials(localPath, endpoint); | |||||
| DVCUtils.dvcConfigS3Credentials2(localPath, accessKeyId); | |||||
| DVCUtils.dvcConfigS3Credentials3(localPath, secretAccessKey); | |||||
| // dvc 跟踪 | |||||
| DVCUtils.dvcAdd(localPath, "data"); | |||||
| // git commit | |||||
| DVCUtils.gitAdd(localPath, "."); | |||||
| DVCUtils.gitCommit(localPath, "commit from ci4s with " + loginUser.getUsername()); | |||||
| DVCUtils.gitPush(localPath, "fanshuai", "h1n2x3j4y5@"); | |||||
| // dvc push 到远程S3 | |||||
| DVCUtils.dvcPush(localPath); | |||||
| return "新增数据集成功"; | |||||
| } catch (Exception e) { | |||||
| throw new RuntimeException(e); | |||||
| } | |||||
| }); | |||||
| } | |||||
| @Override | |||||
| public Page<NewDatasetVo> newPersonalQueryByPage(Dataset dataset, PageRequest pageRequest) throws Exception { | |||||
| LoginUser loginUser = SecurityUtils.getLoginUser(); | |||||
| String token = gitService.login("fanshuai", "h1n2x3j4y5@"); | |||||
| String ci4sUsername = loginUser.getUsername(); | |||||
| Jedis jedis = new Jedis(redisHost); | |||||
| String userReq = jedis.get(ci4sUsername + "_gitUserInfo"); | |||||
| Map<String, Object> userInfo = JsonUtils.jsonToMap(userReq); | |||||
| //拼接查询url | |||||
| String datasetTagName = dataset.getDatasetTagName(); | |||||
| String datasetTypeName = dataset.getDatasetTypeName(); | |||||
| String topic_name = "ci4s_dataset"; | |||||
| topic_name =StringUtils.isEmpty(datasetTagName)?topic_name : topic_name+",datatag_" + datasetTagName; | |||||
| topic_name =StringUtils.isEmpty(datasetTagName)?topic_name : topic_name+",datatype_" + datasetTypeName; | |||||
| String url = gitendpoint + "/api/users/"+(String) userInfo.get("login")+"/projects.json?page="+pageRequest.getPageNumber()+"&limit="+pageRequest.getPageSize()+"&category=manage&topic_name="+topic_name; | |||||
| String req = HttpUtils.sendGetWithToken(url,null,token); | |||||
| Map<String, Object> stringObjectMap = JacksonUtil.parseJSONStr2Map(req); | |||||
| Integer total = (Integer) stringObjectMap.get("count"); | |||||
| List<Map<String, Object>> projects = (List<Map<String, Object>>) stringObjectMap.get("projects"); | |||||
| return new PageImpl<>(convert(projects), pageRequest, total); | |||||
| } | |||||
| @Override | |||||
| public Page<NewDatasetVo> newPubilcQueryByPage(Dataset dataset, PageRequest pageRequest) throws Exception { | |||||
| LoginUser loginUser = SecurityUtils.getLoginUser(); | |||||
| String token = gitService.login("fanshuai", "h1n2x3j4y5@"); | |||||
| String ci4sUsername = loginUser.getUsername(); | |||||
| Jedis jedis = new Jedis(redisHost); | |||||
| String userReq = jedis.get(ci4sUsername + "_gitUserInfo"); | |||||
| Map<String, Object> userInfo = JsonUtils.jsonToMap(userReq); | |||||
| Integer userId = (Integer) userInfo.get("user_id"); | |||||
| //拼接查询url | |||||
| String datasetTagName = dataset.getDatasetTagName(); | |||||
| String datasetTypeName = dataset.getDatasetTypeName(); | |||||
| String topic_name = "ci4s_dataset"; | |||||
| topic_name =StringUtils.isEmpty(datasetTagName)?topic_name : topic_name+",datatag_" + datasetTagName; | |||||
| topic_name =StringUtils.isEmpty(datasetTagName)?topic_name : topic_name+",datatype_" + datasetTypeName; | |||||
| String url = gitendpoint + "/api/projects.json?user_id="+userId+"&page="+pageRequest.getPageNumber()+"&limit="+pageRequest.getPageSize()+"&sort_by=praises_count&topic_name="+topic_name; | |||||
| String req = HttpUtils.sendGetWithToken(url,null,token); | |||||
| Map<String, Object> stringObjectMap = JacksonUtil.parseJSONStr2Map(req); | |||||
| Integer total = (Integer) stringObjectMap.get("total_count"); | |||||
| List<Map<String, Object>> projects = (List<Map<String, Object>>) stringObjectMap.get("projects"); | |||||
| return new PageImpl<>(convert(projects), pageRequest, total); | |||||
| } | |||||
| @Override | |||||
| public List<Map<String, String>> uploadDatasetlocal(MultipartFile[] files, String uuid) throws Exception { | |||||
| List<Map<String, String>> results = new ArrayList<>(); | |||||
| for (MultipartFile file:files){ | |||||
| // 构建objectName | |||||
| String username = SecurityUtils.getLoginUser().getUsername(); | |||||
| String fileName = file.getOriginalFilename(); | |||||
| String path = "/temp/"+ username +"/datasets/"+ uuid + "/"+"/data/" + fileName; | |||||
| long sizeInBytes = file.getSize(); | |||||
| String formattedSize = FileUtil.formatFileSize(sizeInBytes); | |||||
| File targetFile = new File(path, file.getOriginalFilename()); | |||||
| // 确保目录存在 | |||||
| targetFile.getParentFile().mkdirs(); | |||||
| // 保存文件到目标路径 | |||||
| FileUtils.copyInputStreamToFile(file.getInputStream(), targetFile); | |||||
| // 返回上传文件的路径 | |||||
| String absolutePath = targetFile.getAbsolutePath(); | |||||
| Map<String, String> result = new HashMap<>(); | |||||
| result.put("fileName", fileName); | |||||
| result.put("url", absolutePath); // objectName根据实际情况定义 | |||||
| result.put("fileSize", formattedSize); | |||||
| results.add(result); | |||||
| } | |||||
| return results; | |||||
| } | |||||
| @Override | |||||
| public ResponseEntity<InputStreamResource> downloadAllDatasetFilesNew(String repositoryName, String version) throws Exception { | |||||
| // 命令行操作 git clone 项目地址 | |||||
| LoginUser loginUser = SecurityUtils.getLoginUser(); | |||||
| String token = gitService.login("fanshuai", "h1n2x3j4y5@"); | |||||
| String ci4sUsername = loginUser.getUsername(); | |||||
| Jedis jedis = new Jedis(redisHost); | |||||
| String userReq = jedis.get(ci4sUsername + "_gitUserInfo"); | |||||
| Map<String, Object> userInfo = JsonUtils.jsonToMap(userReq); | |||||
| Integer userId = (Integer) userInfo.get("user_id"); | |||||
| String projectUrl = gitendpoint + "/" +(String) userInfo.get("login") + "/" + repositoryName + ".git"; | |||||
| String localPath = "E:/test/"+ loginUser.getUsername()+"/datasets/" +repositoryName; | |||||
| File folder = new File(localPath); | |||||
| if(folder.exists() && folder.isDirectory()){ | |||||
| //切换分支 | |||||
| DVCUtils.gitCheckoutBranch(localPath, version); | |||||
| //pull | |||||
| DVCUtils.gitPull(localPath,"fanshuai", "h1n2x3j4y5@"); | |||||
| //dvc pull | |||||
| DVCUtils.dvcPull(localPath); | |||||
| }else { | |||||
| DVCUtils.gitClone(localPath, projectUrl, version, "fanshuai", "h1n2x3j4y5@"); | |||||
| } | |||||
| // 打包 data 文件夹 | |||||
| String dataFolderPath = localPath + "/data"; | |||||
| String zipFilePath = localPath + "/data.zip"; | |||||
| try (FileOutputStream fos = new FileOutputStream(zipFilePath); | |||||
| ZipOutputStream zos = new ZipOutputStream(fos)) { | |||||
| Path sourcePath = Paths.get(dataFolderPath); | |||||
| Files.walk(sourcePath).forEach(path -> { | |||||
| if (!Files.isDirectory(path)) { | |||||
| ZipEntry zipEntry = new ZipEntry(sourcePath.relativize(path).toString()); | |||||
| try { | |||||
| zos.putNextEntry(zipEntry); | |||||
| Files.copy(path, zos); | |||||
| zos.closeEntry(); | |||||
| } catch (IOException e) { | |||||
| throw new RuntimeException("Error while zipping: " + path, e); | |||||
| } | |||||
| } | |||||
| }); | |||||
| } | |||||
| // 返回压缩文件的输入流 | |||||
| File zipFile = new File(zipFilePath); | |||||
| InputStreamResource resource = new InputStreamResource(new FileInputStream(zipFile)); | |||||
| return ResponseEntity.ok() | |||||
| .header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=data.zip") | |||||
| .contentType(MediaType.APPLICATION_OCTET_STREAM) | |||||
| .contentLength(zipFile.length()) | |||||
| .body(resource); | |||||
| } | |||||
| public List<NewDatasetVo> convert(List<Map<String, Object>> lst) { | |||||
| if (lst != null && lst.size() > 0) { | |||||
| List<NewDatasetVo> newDatasetVos = ConvertUtil.convertListMapToObjectList(lst, NewDatasetVo.class); | |||||
| for (NewDatasetVo newDatasetVo : newDatasetVos) { | |||||
| Map<String, Object> map = lst.stream() | |||||
| .filter(m -> m.get("repo_id").equals(newDatasetVo.getRepoId())) | |||||
| .findFirst() | |||||
| .orElse(null); | |||||
| if (map != null) { | |||||
| List<Map<String, Object>> topics = (List<Map<String, Object>>) map.get("topics"); | |||||
| if (topics != null) { | |||||
| topics.forEach(topic -> { | |||||
| String name = (String) topic.get("name"); | |||||
| if (name != null) { | |||||
| if (name.startsWith("datatag_")) { | |||||
| newDatasetVo.setDataTag(name.substring("datatag_".length())); | |||||
| } else if (name.startsWith("datatype_")) { | |||||
| newDatasetVo.setDataType(name.substring("datatype_".length())); | |||||
| } | |||||
| } | |||||
| }); | |||||
| } | |||||
| Map<String, Object> author = (Map<String, Object>) map.get("author"); | |||||
| newDatasetVo.setCreateBy((String) author.get("name")); | |||||
| } | |||||
| } | |||||
| return newDatasetVos; | |||||
| } | |||||
| return new ArrayList<>(); | |||||
| } | |||||
| } | } | ||||
| @@ -0,0 +1,34 @@ | |||||
| package com.ruoyi.platform.service.impl; | |||||
| import com.ruoyi.common.security.utils.SecurityUtils; | |||||
| import com.ruoyi.platform.service.DvcService; | |||||
| import com.ruoyi.platform.utils.DVCUtils; | |||||
| import com.ruoyi.system.api.model.LoginUser; | |||||
| import org.springframework.beans.factory.annotation.Value; | |||||
| import org.springframework.stereotype.Service; | |||||
| @Service | |||||
| public class DvcServiceImpl implements DvcService { | |||||
| @Value("${minio.accessKey}") | |||||
| String accessKeyId; | |||||
| @Value("${minio.secretKey}") | |||||
| String secretAccessKey; | |||||
| @Value("${minio.endpoint}") | |||||
| String endpoint; | |||||
| @Override | |||||
| public void initaddpushDvc(String localPath) throws Exception { | |||||
| LoginUser loginUser = SecurityUtils.getLoginUser(); | |||||
| // dvc init 初始化 | |||||
| DVCUtils.dvcInit(localPath); | |||||
| // 配置远程S3地址 | |||||
| DVCUtils.dvcRemoteAdd(localPath,""); | |||||
| // DVCUtils.dvcConfigS3Credentials(localPath,endpoint, accessKeyId, secretAccessKey); | |||||
| // dvc 跟踪 | |||||
| DVCUtils.dvcAdd(localPath , "data"); | |||||
| // git commit | |||||
| DVCUtils.gitCommit(localPath, "commit from ci4s with "+loginUser.getUsername()); | |||||
| // dvc push 到远程S3 | |||||
| DVCUtils.dvcPush(localPath); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,98 @@ | |||||
| package com.ruoyi.platform.service.impl; | |||||
| import com.fasterxml.jackson.core.JsonProcessingException; | |||||
| import com.ruoyi.common.security.utils.SecurityUtils; | |||||
| import com.ruoyi.platform.service.GitService; | |||||
| import com.ruoyi.platform.utils.HttpUtils; | |||||
| import com.ruoyi.platform.utils.JsonUtils; | |||||
| import com.ruoyi.platform.vo.GitProjectVo; | |||||
| import com.ruoyi.system.api.model.LoginUser; | |||||
| import org.apache.commons.lang3.StringUtils; | |||||
| import org.slf4j.Logger; | |||||
| import org.slf4j.LoggerFactory; | |||||
| import org.springframework.beans.factory.annotation.Value; | |||||
| import org.springframework.stereotype.Service; | |||||
| import redis.clients.jedis.Jedis; | |||||
| import java.util.HashMap; | |||||
| import java.util.Map; | |||||
| @Service | |||||
| public class GitServiceImpl implements GitService { | |||||
| @Value("${spring.redis.host}") | |||||
| private String redisHost; | |||||
| private static final Logger log = LoggerFactory.getLogger(GitServiceImpl.class); | |||||
| @Override | |||||
| public String login(String username, String password) { | |||||
| // 构建请求参数 | |||||
| Map<String, Object> params = new HashMap<>(); | |||||
| params.put("grant_type", "password"); | |||||
| params.put("username", username); | |||||
| params.put("password", password); | |||||
| params.put("client_id", "jEdGwrIJixCUIJM9vj2MwA6zmoTVhUdXxiSAaaCiXwA"); | |||||
| params.put("client_secret", "L3wBKTNnRo-wPen7bxR3F1myCvtVDgpWa6MnpfyWeJE"); | |||||
| try { | |||||
| // 发送POST请求 | |||||
| String req = HttpUtils.sendPostRequest("https://www.gitlink.org.cn/oauth/token",null, JsonUtils.mapToJson(params)); | |||||
| // 解析响应JSON | |||||
| if (StringUtils.isEmpty(req)) { | |||||
| throw new RuntimeException("终止响应内容为空。"); | |||||
| } | |||||
| // 将响应的JSON字符串转换为Map对象 | |||||
| Map<String, Object> runResMap = JsonUtils.jsonToMap(req); | |||||
| // 提取access_token | |||||
| // 提取access_token | |||||
| String accessToken = (String) runResMap.get("access_token"); | |||||
| //通过access_token获取用户信息 | |||||
| String userReq = HttpUtils.sendGetWithToken("https://www.gitlink.org.cn/api/users/get_user_info.json",null, accessToken); | |||||
| if (StringUtils.isEmpty(userReq)) { | |||||
| throw new RuntimeException("终止响应内容为空。"); | |||||
| } | |||||
| LoginUser loginUser = SecurityUtils.getLoginUser(); | |||||
| String ci4sUsername = loginUser.getUsername(); | |||||
| // 将access_token存入Redis | |||||
| Jedis jedis = new Jedis(redisHost); | |||||
| jedis.set(ci4sUsername+"_gitToken", accessToken); | |||||
| jedis.set(ci4sUsername+"_gitUserInfo", userReq); | |||||
| return accessToken; | |||||
| } catch (Exception e) { | |||||
| log.error("登录GitLink失败。", e); | |||||
| return null; | |||||
| } | |||||
| } | |||||
| @Override | |||||
| public Map createProject(String token, GitProjectVo gitProjectVo) throws Exception { | |||||
| String userReq = HttpUtils.sendPostWithToken("https://www.gitlink.org.cn/api/projects.json",JsonUtils.objectToJson(gitProjectVo),token); | |||||
| return JsonUtils.jsonToMap(userReq); | |||||
| } | |||||
| @Override | |||||
| public void createBranch(String token,String owner, String projectName, String branchName, String oldBranchName) throws Exception { | |||||
| //https://www.gitlink.org.cn/api/v1/fanshuai/testdssa8755/branches.json | |||||
| // { | |||||
| // "new_branch_name": "SsS", | |||||
| // "old_branch_name": "master" | |||||
| // } | |||||
| String createBranchUrl = "https://www.gitlink.org.cn/api/v1/"+ owner + "/" + projectName + "/branches.json"; | |||||
| Map<String, Object> resMap = new HashMap<>(); | |||||
| resMap.put("new_branch_name", branchName); | |||||
| resMap.put("old_branch_name", oldBranchName); | |||||
| String req = HttpUtils.sendPostWithToken(createBranchUrl,JsonUtils.objectToJson(resMap),token); | |||||
| System.out.println(req); | |||||
| } | |||||
| @Override | |||||
| public void createTopic(String token, Integer id, String topicName) throws Exception { | |||||
| // https://www.gitlink.org.cn/api/v1/project_topics.json | |||||
| Map<String, Object> resMap = new HashMap<>(); | |||||
| resMap.put("project_id", id); | |||||
| resMap.put("name", topicName); | |||||
| String req = HttpUtils.sendPostWithToken("https://www.gitlink.org.cn/api/v1/project_topics.json",JsonUtils.objectToJson(resMap),token); | |||||
| System.out.println(req); | |||||
| } | |||||
| } | |||||
| @@ -2,24 +2,29 @@ package com.ruoyi.platform.service.impl; | |||||
| import com.alibaba.fastjson2.util.DateUtils; | import com.alibaba.fastjson2.util.DateUtils; | ||||
| import com.ruoyi.common.security.utils.SecurityUtils; | import com.ruoyi.common.security.utils.SecurityUtils; | ||||
| import com.ruoyi.platform.constant.Constant; | |||||
| import com.ruoyi.platform.domain.DevEnvironment; | |||||
| import com.ruoyi.platform.domain.Image; | import com.ruoyi.platform.domain.Image; | ||||
| import com.ruoyi.platform.domain.ImageVersion; | import com.ruoyi.platform.domain.ImageVersion; | ||||
| import com.ruoyi.platform.mapper.DevEnvironmentDao; | |||||
| import com.ruoyi.platform.mapper.ImageDao; | import com.ruoyi.platform.mapper.ImageDao; | ||||
| import com.ruoyi.platform.mapper.ImageVersionDao; | import com.ruoyi.platform.mapper.ImageVersionDao; | ||||
| import com.ruoyi.platform.service.ImageService; | import com.ruoyi.platform.service.ImageService; | ||||
| import com.ruoyi.platform.service.ImageVersionService; | import com.ruoyi.platform.service.ImageVersionService; | ||||
| import com.ruoyi.platform.service.MinioService; | import com.ruoyi.platform.service.MinioService; | ||||
| import com.ruoyi.platform.utils.DockerClientUtil; | |||||
| import com.ruoyi.platform.utils.FileUtil; | import com.ruoyi.platform.utils.FileUtil; | ||||
| import com.ruoyi.platform.utils.K8sClientUtil; | import com.ruoyi.platform.utils.K8sClientUtil; | ||||
| import com.ruoyi.platform.vo.ImageVo; | import com.ruoyi.platform.vo.ImageVo; | ||||
| import com.ruoyi.system.api.model.LoginUser; | import com.ruoyi.system.api.model.LoginUser; | ||||
| import io.kubernetes.client.openapi.models.V1PersistentVolumeClaim; | |||||
| import io.kubernetes.client.openapi.models.V1Pod; | import io.kubernetes.client.openapi.models.V1Pod; | ||||
| import org.apache.commons.lang3.StringUtils; | import org.apache.commons.lang3.StringUtils; | ||||
| import org.springframework.beans.BeanUtils; | |||||
| import org.springframework.beans.factory.annotation.Value; | import org.springframework.beans.factory.annotation.Value; | ||||
| import org.springframework.data.domain.Page; | import org.springframework.data.domain.Page; | ||||
| import org.springframework.data.domain.PageImpl; | import org.springframework.data.domain.PageImpl; | ||||
| import org.springframework.data.domain.PageRequest; | import org.springframework.data.domain.PageRequest; | ||||
| import org.springframework.scheduling.annotation.Async; | |||||
| import org.springframework.stereotype.Service; | import org.springframework.stereotype.Service; | ||||
| import org.springframework.transaction.annotation.Transactional; | import org.springframework.transaction.annotation.Transactional; | ||||
| import org.springframework.web.multipart.MultipartFile; | import org.springframework.web.multipart.MultipartFile; | ||||
| @@ -27,6 +32,7 @@ import org.springframework.web.multipart.MultipartFile; | |||||
| import javax.annotation.Resource; | import javax.annotation.Resource; | ||||
| import java.util.Date; | import java.util.Date; | ||||
| import java.util.HashMap; | import java.util.HashMap; | ||||
| import java.util.List; | |||||
| import java.util.Map; | import java.util.Map; | ||||
| import java.util.concurrent.CompletableFuture; | import java.util.concurrent.CompletableFuture; | ||||
| @@ -40,16 +46,19 @@ import java.util.concurrent.CompletableFuture; | |||||
| public class ImageServiceImpl implements ImageService { | public class ImageServiceImpl implements ImageService { | ||||
| @Resource | @Resource | ||||
| private ImageDao imageDao; | private ImageDao imageDao; | ||||
| @Resource | |||||
| private ImageVersionDao imageVersionDao; | |||||
| @Resource | |||||
| private DevEnvironmentDao devEnvironmentDao; | |||||
| @Resource | @Resource | ||||
| private ImageVersionService imageVersionService; | private ImageVersionService imageVersionService; | ||||
| @Resource | |||||
| private ImageVersionDao imageVersionDao; | |||||
| @Resource | @Resource | ||||
| private K8sClientUtil k8sClientUtil; | private K8sClientUtil k8sClientUtil; | ||||
| @Resource | |||||
| private DockerClientUtil dockerClientUtil; | |||||
| @Resource | @Resource | ||||
| private MinioService minioService; | private MinioService minioService; | ||||
| @Value("${harbor.bucketName}") | @Value("${harbor.bucketName}") | ||||
| @@ -75,6 +84,9 @@ public class ImageServiceImpl implements ImageService { | |||||
| private String proxyUrl; | private String proxyUrl; | ||||
| @Value("${minio.pvcName}") | @Value("${minio.pvcName}") | ||||
| private String pvcName; | private String pvcName; | ||||
| @Value("${jupyter.namespace}") | |||||
| private String namespace; | |||||
| /** | /** | ||||
| * 通过ID查询单条数据 | * 通过ID查询单条数据 | ||||
| * | * | ||||
| @@ -89,8 +101,8 @@ public class ImageServiceImpl implements ImageService { | |||||
| /** | /** | ||||
| * 分页查询 | * 分页查询 | ||||
| * | * | ||||
| * @param image 筛选条件 | |||||
| * @param pageRequest 分页对象 | |||||
| * @param image 筛选条件 | |||||
| * @param pageRequest 分页对象 | |||||
| * @return 查询结果 | * @return 查询结果 | ||||
| */ | */ | ||||
| @Override | @Override | ||||
| @@ -100,7 +112,6 @@ public class ImageServiceImpl implements ImageService { | |||||
| } | } | ||||
| /** | /** | ||||
| * 新增数据 | * 新增数据 | ||||
| * | * | ||||
| @@ -128,7 +139,7 @@ public class ImageServiceImpl implements ImageService { | |||||
| @Override | @Override | ||||
| public Image update(Image image) { | public Image update(Image image) { | ||||
| int currentState = image.getState(); | int currentState = image.getState(); | ||||
| if(currentState == 0){ | |||||
| if (currentState == 0) { | |||||
| throw new RuntimeException("镜像已被删除,无法更新。"); | throw new RuntimeException("镜像已被删除,无法更新。"); | ||||
| } | } | ||||
| LoginUser loginUser = SecurityUtils.getLoginUser(); | LoginUser loginUser = SecurityUtils.getLoginUser(); | ||||
| @@ -153,7 +164,7 @@ public class ImageServiceImpl implements ImageService { | |||||
| @Override | @Override | ||||
| public String removeById(Integer id) throws Exception { | public String removeById(Integer id) throws Exception { | ||||
| Image image = this.imageDao.queryById(id); | Image image = this.imageDao.queryById(id); | ||||
| if (image == null){ | |||||
| if (image == null) { | |||||
| throw new Exception("镜像不存在"); | throw new Exception("镜像不存在"); | ||||
| } | } | ||||
| @@ -163,14 +174,20 @@ public class ImageServiceImpl implements ImageService { | |||||
| String createdBy = image.getCreateBy(); | String createdBy = image.getCreateBy(); | ||||
| if (!(StringUtils.equals(username,"admin") || !StringUtils.equals(username,createdBy))){ | |||||
| if (!(StringUtils.equals(username, "admin") || !StringUtils.equals(username, createdBy))) { | |||||
| throw new Exception("无权限删除该镜像"); | throw new Exception("无权限删除该镜像"); | ||||
| } | } | ||||
| if (!imageVersionService.queryByImageId(id).isEmpty()){ | |||||
| throw new Exception("请先删除该镜像下的版本文件"); | |||||
| // if (!imageVersionService.queryByImageId(id).isEmpty()){ | |||||
| // throw new Exception("请先删除该镜像下的版本文件"); | |||||
| // } | |||||
| List<ImageVersion> imageVersions = imageVersionService.queryByImageId(id); | |||||
| for (ImageVersion imageVersion :imageVersions) { | |||||
| dockerClientUtil.removeImage(imageVersion.getUrl(), imageVersion.getHostIp()); | |||||
| } | } | ||||
| image.setState(0); | image.setState(0); | ||||
| return this.imageDao.update(image)>0?"删除成功":"删除失败"; | |||||
| return this.imageDao.update(image) > 0 ? "删除成功" : "删除失败"; | |||||
| } | } | ||||
| @@ -197,7 +214,7 @@ public class ImageServiceImpl implements ImageService { | |||||
| public String insertImageAndVersion(ImageVo imageVo) throws Exception { | public String insertImageAndVersion(ImageVo imageVo) throws Exception { | ||||
| Image existingImage = getByName(imageVo.getName()); | Image existingImage = getByName(imageVo.getName()); | ||||
| Image imageToUse; | Image imageToUse; | ||||
| if(existingImage == null) { | |||||
| if (existingImage == null) { | |||||
| // 如果不存在相同名称的镜像,则创建新的镜像记录 | // 如果不存在相同名称的镜像,则创建新的镜像记录 | ||||
| Image newImage = new Image(); | Image newImage = new Image(); | ||||
| newImage.setName(imageVo.getName()); | newImage.setName(imageVo.getName()); | ||||
| @@ -207,7 +224,7 @@ public class ImageServiceImpl implements ImageService { | |||||
| if (imageToUse == null) { | if (imageToUse == null) { | ||||
| throw new Exception("新增镜像失败"); | throw new Exception("新增镜像失败"); | ||||
| } | } | ||||
| }else{ | |||||
| } else { | |||||
| // 如果已存在相同名称的镜像,使用已存在的镜像 | // 如果已存在相同名称的镜像,使用已存在的镜像 | ||||
| imageToUse = existingImage; | imageToUse = existingImage; | ||||
| } | } | ||||
| @@ -225,9 +242,9 @@ public class ImageServiceImpl implements ImageService { | |||||
| CompletableFuture.supplyAsync(() -> { | CompletableFuture.supplyAsync(() -> { | ||||
| Map<String, String> resultMap = new HashMap<>(); | Map<String, String> resultMap = new HashMap<>(); | ||||
| try { | try { | ||||
| if(imageVo.getUploadType()==0){ | |||||
| resultMap = createImageFromNet(imageVo.getName(), imageVo.getTagName(), imageVo.getPath()); | |||||
| }else{ | |||||
| if (imageVo.getUploadType() == 0) { | |||||
| resultMap = createImageFromNet(imageVo.getName(), imageVo.getTagName(), imageVo.getPath()); | |||||
| } else { | |||||
| resultMap = createImageFromLocal(imageVo.getName(), imageVo.getTagName(), imageVo.getPath()); | resultMap = createImageFromLocal(imageVo.getName(), imageVo.getTagName(), imageVo.getPath()); | ||||
| } | } | ||||
| } catch (Exception e) { | } catch (Exception e) { | ||||
| @@ -236,7 +253,7 @@ public class ImageServiceImpl implements ImageService { | |||||
| throw new RuntimeException("镜像构建失败: " + e.getMessage(), e); | throw new RuntimeException("镜像构建失败: " + e.getMessage(), e); | ||||
| } | } | ||||
| return resultMap; | return resultMap; | ||||
| }).thenAccept(resultMap ->{ | |||||
| }).thenAccept(resultMap -> { | |||||
| try { | try { | ||||
| String imageUrl = resultMap.get("url"); | String imageUrl = resultMap.get("url"); | ||||
| String fileSize = resultMap.get("fileSize"); | String fileSize = resultMap.get("fileSize"); | ||||
| @@ -262,27 +279,27 @@ public class ImageServiceImpl implements ImageService { | |||||
| // 得到容器 | // 得到容器 | ||||
| V1Pod pod = k8sClientUtil.getNSPodList(serviceNS, deploymentName); | V1Pod pod = k8sClientUtil.getNSPodList(serviceNS, deploymentName); | ||||
| if (pod == null) { | if (pod == null) { | ||||
| String podName = deploymentName+"-"+ DateUtils.formatYMD10(new Date()); | |||||
| pod = k8sClientUtil.createPodWithEnv(podName,serviceNS,proxyUrl,mountPath,pvcName,image); | |||||
| String podName = deploymentName + "-" + DateUtils.formatYMD10(new Date()); | |||||
| pod = k8sClientUtil.createPodWithEnv(podName, serviceNS, proxyUrl, mountPath, pvcName, image); | |||||
| } | } | ||||
| String loginCmd = "docker login -u " + harborUser +" -p "+harborpassword+" "+harborUrl; | |||||
| String loginCmd = "docker login -u " + harborUser + " -p " + harborpassword + " " + harborUrl; | |||||
| // 执行命令 docker login -u admin -p Harbor12345 172.20.32.187 | // 执行命令 docker login -u admin -p Harbor12345 172.20.32.187 | ||||
| String loginlog = k8sClientUtil.executeCommand(pod,loginCmd); | |||||
| String loginlog = k8sClientUtil.executeCommand(pod, loginCmd); | |||||
| // 在这个容器的/data/admin 目录下执行命令 docker load -i fileName 得到返回的镜像名字name:tag | // 在这个容器的/data/admin 目录下执行命令 docker load -i fileName 得到返回的镜像名字name:tag | ||||
| String username = SecurityUtils.getLoginUser().getUsername(); | String username = SecurityUtils.getLoginUser().getUsername(); | ||||
| // | // | ||||
| String logs2 = k8sClientUtil.executeCommand(pod,"docker pull "+ netPath); | |||||
| String logs2 = k8sClientUtil.executeCommand(pod, "docker pull " + netPath); | |||||
| // 在容器里执行 docker tag name:tag nexus3.kube-system.svc:8083/imageName:imageTag | // 在容器里执行 docker tag name:tag nexus3.kube-system.svc:8083/imageName:imageTag | ||||
| if (StringUtils.isNoneBlank(logs2)){ | |||||
| if (StringUtils.isNoneBlank(logs2)) { | |||||
| String[] lines = logs2.split("\n"); | String[] lines = logs2.split("\n"); | ||||
| String lastLine = lines[lines.length - 1].trim(); | String lastLine = lines[lines.length - 1].trim(); | ||||
| String tagCmd = "docker tag " + lastLine + " " + harborUrl + "/" + repository + "/" + username + "/" + imageName + ":" + imageTag; | String tagCmd = "docker tag " + lastLine + " " + harborUrl + "/" + repository + "/" + username + "/" + imageName + ":" + imageTag; | ||||
| String imageUrl = harborUrl + "/" + repository + "/" + username + "/" + imageName + ":" + imageTag; | String imageUrl = harborUrl + "/" + repository + "/" + username + "/" + imageName + ":" + imageTag; | ||||
| String pushCmd = "docker push " + imageUrl; | |||||
| String pushCmd = "docker push " + imageUrl; | |||||
| String sizeCmd = "docker inspect --format='{{.Size}}' " + imageUrl; | String sizeCmd = "docker inspect --format='{{.Size}}' " + imageUrl; | ||||
| String s = k8sClientUtil.executeCommand(pod, tagCmd); | String s = k8sClientUtil.executeCommand(pod, tagCmd); | ||||
| if (StringUtils.isNotEmpty(k8sClientUtil.executeCommand(pod, pushCmd))){ | |||||
| if (StringUtils.isNotEmpty(k8sClientUtil.executeCommand(pod, pushCmd))) { | |||||
| resultMap.put("url", imageUrl); | resultMap.put("url", imageUrl); | ||||
| //得到镜像文件大小 | //得到镜像文件大小 | ||||
| String imageSizeStr = k8sClientUtil.executeCommand(pod, sizeCmd); | String imageSizeStr = k8sClientUtil.executeCommand(pod, sizeCmd); | ||||
| @@ -291,10 +308,10 @@ public class ImageServiceImpl implements ImageService { | |||||
| resultMap.put("fileSize", formattedImageSize); | resultMap.put("fileSize", formattedImageSize); | ||||
| return resultMap; | return resultMap; | ||||
| }else { | |||||
| } else { | |||||
| throw new Exception("拉取公网镜像失败,请检查网络或者镜像地址"); | throw new Exception("拉取公网镜像失败,请检查网络或者镜像地址"); | ||||
| } | } | ||||
| }else { | |||||
| } else { | |||||
| throw new Exception("拉取公网镜像失败,请检查网络或者镜像地址"); | throw new Exception("拉取公网镜像失败,请检查网络或者镜像地址"); | ||||
| } | } | ||||
| } | } | ||||
| @@ -305,27 +322,27 @@ public class ImageServiceImpl implements ImageService { | |||||
| // 得到容器 | // 得到容器 | ||||
| V1Pod pod = k8sClientUtil.getNSPodList(serviceNS, deploymentName); | V1Pod pod = k8sClientUtil.getNSPodList(serviceNS, deploymentName); | ||||
| if (pod == null) { | if (pod == null) { | ||||
| String podName = deploymentName+"-"+ DateUtils.formatYMD10(new Date()); | |||||
| pod = k8sClientUtil.createPodWithEnv(podName,serviceNS,proxyUrl,mountPath,pvcName,image); | |||||
| String podName = deploymentName + "-" + DateUtils.formatYMD10(new Date()); | |||||
| pod = k8sClientUtil.createPodWithEnv(podName, serviceNS, proxyUrl, mountPath, pvcName, image); | |||||
| } | } | ||||
| String loginCmd = "docker login -u " + harborUser +" -p "+harborpassword+" "+harborUrl; | |||||
| String loginCmd = "docker login -u " + harborUser + " -p " + harborpassword + " " + harborUrl; | |||||
| // 执行命令 docker login -u admin -p Harbor12345 172.20.32.187 | // 执行命令 docker login -u admin -p Harbor12345 172.20.32.187 | ||||
| String loginlog = k8sClientUtil.executeCommand(pod,loginCmd); | |||||
| String loginlog = k8sClientUtil.executeCommand(pod, loginCmd); | |||||
| // 在这个容器的/data/admin 目录下执行命令 docker load -i fileName 得到返回的镜像名字name:tag | // 在这个容器的/data/admin 目录下执行命令 docker load -i fileName 得到返回的镜像名字name:tag | ||||
| String username = SecurityUtils.getLoginUser().getUsername(); | String username = SecurityUtils.getLoginUser().getUsername(); | ||||
| // | // | ||||
| String filePath = "/data/argo-workflow/" + bucketName + "/" +path; | |||||
| String logs2 = k8sClientUtil.executeCommand(pod,"docker load -i "+filePath); | |||||
| String filePath = "/data/argo-workflow/" + bucketName + "/" + path; | |||||
| String logs2 = k8sClientUtil.executeCommand(pod, "docker load -i " + filePath); | |||||
| // 在容器里执行 docker tag name:tag nexus3.kube-system.svc:8083/imageName:imageTag | // 在容器里执行 docker tag name:tag nexus3.kube-system.svc:8083/imageName:imageTag | ||||
| if (StringUtils.isNoneBlank(logs2)){ | |||||
| String substring = logs2.substring(logs2.indexOf(":")+1).trim(); | |||||
| if (StringUtils.isNoneBlank(logs2)) { | |||||
| String substring = logs2.substring(logs2.indexOf(":") + 1).trim(); | |||||
| String tagCmd = "docker tag " + substring + " " + harborUrl + "/" + repository + "/" + username + "/" + imageName + ":" + imageTag; | String tagCmd = "docker tag " + substring + " " + harborUrl + "/" + repository + "/" + username + "/" + imageName + ":" + imageTag; | ||||
| String imageUrl = harborUrl + "/" + repository + "/" + username + "/" + imageName + ":" + imageTag; | String imageUrl = harborUrl + "/" + repository + "/" + username + "/" + imageName + ":" + imageTag; | ||||
| String pushCmd = "docker push " + imageUrl; | |||||
| String pushCmd = "docker push " + imageUrl; | |||||
| String sizeCmd = "docker inspect --format='{{.Size}}' " + imageUrl; | String sizeCmd = "docker inspect --format='{{.Size}}' " + imageUrl; | ||||
| String s = k8sClientUtil.executeCommand(pod, tagCmd); | String s = k8sClientUtil.executeCommand(pod, tagCmd); | ||||
| if (StringUtils.isNotEmpty(k8sClientUtil.executeCommand(pod, pushCmd))){ | |||||
| if (StringUtils.isNotEmpty(k8sClientUtil.executeCommand(pod, pushCmd))) { | |||||
| resultMap.put("url", imageUrl); | resultMap.put("url", imageUrl); | ||||
| //得到镜像文件大小 | //得到镜像文件大小 | ||||
| String imageSizeStr = k8sClientUtil.executeCommand(pod, sizeCmd); | String imageSizeStr = k8sClientUtil.executeCommand(pod, sizeCmd); | ||||
| @@ -333,18 +350,79 @@ public class ImageServiceImpl implements ImageService { | |||||
| String formattedImageSize = FileUtil.formatFileSize(sizeInBytes); // 格式化镜像文件大小 | String formattedImageSize = FileUtil.formatFileSize(sizeInBytes); // 格式化镜像文件大小 | ||||
| resultMap.put("fileSize", formattedImageSize); | resultMap.put("fileSize", formattedImageSize); | ||||
| return resultMap; | return resultMap; | ||||
| }else { | |||||
| } else { | |||||
| throw new Exception("解析镜像压缩包失败,请检查镜像文件"); | throw new Exception("解析镜像压缩包失败,请检查镜像文件"); | ||||
| } | } | ||||
| }else { | |||||
| } else { | |||||
| throw new Exception("解析镜像压缩包失败,请检查镜像文件"); | throw new Exception("解析镜像压缩包失败,请检查镜像文件"); | ||||
| } | } | ||||
| } | } | ||||
| @Override | @Override | ||||
| public Map<String, String> uploadImageFiles(MultipartFile file) throws Exception { | public Map<String, String> uploadImageFiles(MultipartFile file) throws Exception { | ||||
| LoginUser loginUser = SecurityUtils.getLoginUser(); | LoginUser loginUser = SecurityUtils.getLoginUser(); | ||||
| String path = loginUser.getUsername()+"/"+file.getOriginalFilename(); | |||||
| String path = loginUser.getUsername() + "/" + file.getOriginalFilename(); | |||||
| return minioService.uploadFile(bucketName, path, file); | return minioService.uploadFile(bucketName, path, file); | ||||
| } | } | ||||
| @Override | |||||
| @Transactional | |||||
| @Async | |||||
| public void saveImage(ImageVo imageVo) { | |||||
| Image oldImage = imageDao.getByName(imageVo.getName()); | |||||
| if (oldImage != null) { | |||||
| List<ImageVersion> oldImageVersions = imageVersionDao.queryByImageId(oldImage.getId()); | |||||
| for (ImageVersion oldImageVersion : oldImageVersions) { | |||||
| if(oldImageVersion.getTagName().equals(imageVo.getTagName())){ | |||||
| throw new IllegalStateException("镜像tag不能重复"); | |||||
| } | |||||
| } | |||||
| } | |||||
| LoginUser loginUser = SecurityUtils.getLoginUser(); | |||||
| String username = loginUser.getUsername().toLowerCase(); | |||||
| String podName = username + "-editor-pod" + "-" + imageVo.getDevEnvironmentId().toString(); | |||||
| try { | |||||
| String containerId = k8sClientUtil.getPodContainerId(podName, namespace); | |||||
| String hostIp = k8sClientUtil.getHostIp(podName, namespace); | |||||
| dockerClientUtil.commitImage(imageVo, containerId, hostIp, username); | |||||
| HashMap<String, String> resultMap = dockerClientUtil.pushImageToHorbor(imageVo, hostIp); | |||||
| Image image = new Image(); | |||||
| BeanUtils.copyProperties(imageVo, image); | |||||
| image.setImageType(Constant.Image_Type_Pri); | |||||
| image.setCreateBy(username); | |||||
| image.setUpdateBy(username); | |||||
| image.setUpdateTime(new Date()); | |||||
| image.setCreateTime(new Date()); | |||||
| image.setState(1); | |||||
| imageDao.insert(image); | |||||
| ImageVersion imageVersion = new ImageVersion(); | |||||
| imageVersion.setImageId(image.getId()); | |||||
| imageVersion.setVersion(imageVo.getVersion()); | |||||
| imageVersion.setUrl(resultMap.get("imageName")); | |||||
| imageVersion.setTagName(imageVo.getTagName()); | |||||
| imageVersion.setFileSize(resultMap.get("size")); | |||||
| imageVersion.setCreateBy(username); | |||||
| imageVersion.setUpdateBy(username); | |||||
| imageVersion.setHostIp(hostIp); | |||||
| imageVersion.setUpdateTime(new Date()); | |||||
| imageVersion.setCreateTime(new Date()); | |||||
| imageVersion.setState(1); | |||||
| imageVersion.setStatus("available"); | |||||
| imageVersionDao.insert(imageVersion); | |||||
| //更新dev环境的镜像信息 | |||||
| DevEnvironment devEnvironment = new DevEnvironment(); | |||||
| devEnvironment.setId(imageVo.getDevEnvironmentId()); | |||||
| devEnvironment.setImage(resultMap.get("imageName")); | |||||
| devEnvironmentDao.update(devEnvironment); | |||||
| } catch (Exception e) { | |||||
| throw new RuntimeException("保存镜像失败:" + e); | |||||
| } | |||||
| } | |||||
| } | } | ||||
| @@ -2,8 +2,10 @@ package com.ruoyi.platform.service.impl; | |||||
| import com.ruoyi.common.redis.service.RedisService; | import com.ruoyi.common.redis.service.RedisService; | ||||
| import com.ruoyi.common.security.utils.SecurityUtils; | import com.ruoyi.common.security.utils.SecurityUtils; | ||||
| import com.ruoyi.platform.constant.Constant; | |||||
| import com.ruoyi.platform.domain.DevEnvironment; | import com.ruoyi.platform.domain.DevEnvironment; | ||||
| import com.ruoyi.platform.domain.PodStatus; | import com.ruoyi.platform.domain.PodStatus; | ||||
| import com.ruoyi.platform.mapper.ComputingResourceDao; | |||||
| import com.ruoyi.platform.mapper.DevEnvironmentDao; | import com.ruoyi.platform.mapper.DevEnvironmentDao; | ||||
| import com.ruoyi.platform.service.DevEnvironmentService; | import com.ruoyi.platform.service.DevEnvironmentService; | ||||
| import com.ruoyi.platform.service.JupyterService; | import com.ruoyi.platform.service.JupyterService; | ||||
| @@ -54,6 +56,9 @@ public class JupyterServiceImpl implements JupyterService { | |||||
| @Resource | @Resource | ||||
| private DevEnvironmentDao devEnvironmentDao; | private DevEnvironmentDao devEnvironmentDao; | ||||
| @Resource | |||||
| private ComputingResourceDao computingResourceDao; | |||||
| @Resource | @Resource | ||||
| @Lazy | @Lazy | ||||
| private DevEnvironmentService devEnvironmentService; | private DevEnvironmentService devEnvironmentService; | ||||
| @@ -70,27 +75,29 @@ public class JupyterServiceImpl implements JupyterService { | |||||
| LoginUser loginUser = SecurityUtils.getLoginUser(); | LoginUser loginUser = SecurityUtils.getLoginUser(); | ||||
| String podName = loginUser.getUsername().toLowerCase() + "-editor-pod"; | String podName = loginUser.getUsername().toLowerCase() + "-editor-pod"; | ||||
| String pvcName = loginUser.getUsername().toLowerCase() + "-editor-pvc"; | String pvcName = loginUser.getUsername().toLowerCase() + "-editor-pvc"; | ||||
| V1PersistentVolumeClaim pvc = k8sClientUtil.createPvc(namespace, pvcName, storage,storageClassName); | |||||
| V1PersistentVolumeClaim pvc = k8sClientUtil.createPvc(namespace, pvcName, storage, storageClassName); | |||||
| Integer podPort = k8sClientUtil.createPod(podName, namespace, port, mountPath, pvc, image); | Integer podPort = k8sClientUtil.createPod(podName, namespace, port, mountPath, pvc, image); | ||||
| return masterIp + ":" + podPort; | return masterIp + ":" + podPort; | ||||
| } | } | ||||
| @Override | @Override | ||||
| public String runJupyterService(Integer id) throws Exception { | public String runJupyterService(Integer id) throws Exception { | ||||
| DevEnvironment devEnvironment = this.devEnvironmentDao.queryById(id); | DevEnvironment devEnvironment = this.devEnvironmentDao.queryById(id); | ||||
| if(devEnvironment == null){ | |||||
| if (devEnvironment == null) { | |||||
| throw new Exception("开发环境配置不存在"); | throw new Exception("开发环境配置不存在"); | ||||
| } | } | ||||
| // 提取数据集,模型信息,得到数据集模型的path | // 提取数据集,模型信息,得到数据集模型的path | ||||
| Map<String, Object> dataset = JacksonUtil.parseJSONStr2Map(devEnvironment.getDataset()); | Map<String, Object> dataset = JacksonUtil.parseJSONStr2Map(devEnvironment.getDataset()); | ||||
| String datasetPath = (String) dataset.get("path"); | |||||
| String datasetPath = "argo-workflow" + "/" + dataset.get("path"); | |||||
| Map<String, Object> model = JacksonUtil.parseJSONStr2Map(devEnvironment.getModel()); | Map<String, Object> model = JacksonUtil.parseJSONStr2Map(devEnvironment.getModel()); | ||||
| String modelPath = (String) model.get("path"); | |||||
| String modelPath = "argo-workflow" + "/" + model.get("path"); | |||||
| LoginUser loginUser = SecurityUtils.getLoginUser(); | LoginUser loginUser = SecurityUtils.getLoginUser(); | ||||
| //手动构造pod名称 | |||||
| String podName = loginUser.getUsername().toLowerCase() +"-editor-pod" + "-" + id; | |||||
| //构造pod名称 | |||||
| String podName = loginUser.getUsername().toLowerCase() + "-editor-pod" + "-" + id; | |||||
| String pvcName = loginUser.getUsername().toLowerCase() + "-editor-pvc"; | String pvcName = loginUser.getUsername().toLowerCase() + "-editor-pvc"; | ||||
| //新建编辑器的pvc | //新建编辑器的pvc | ||||
| V1PersistentVolumeClaim pvc = k8sClientUtil.createPvc(namespace, pvcName, storage, storageClassName); | V1PersistentVolumeClaim pvc = k8sClientUtil.createPvc(namespace, pvcName, storage, storageClassName); | ||||
| @@ -98,41 +105,46 @@ public class JupyterServiceImpl implements JupyterService { | |||||
| //TODO 设置镜像可配置,这里先用默认镜像启动pod | //TODO 设置镜像可配置,这里先用默认镜像启动pod | ||||
| // 调用修改后的 createPod 方法,传入额外的参数 | // 调用修改后的 createPod 方法,传入额外的参数 | ||||
| Integer podPort = k8sClientUtil.createConfiguredPod(podName, namespace, port, mountPath, pvc, image, minioPvcName, datasetPath, modelPath); | |||||
| // // 简单的延迟,以便 Pod 有时间启动 | |||||
| // Thread.sleep(2500); | |||||
| // //查询pod状态,更新到数据库 | |||||
| // String podStatus = k8sClientUtil.getPodStatus(podName, namespace); | |||||
| Integer podPort = k8sClientUtil.createConfiguredPod(podName, namespace, port, mountPath, pvc, devEnvironment, minioPvcName, datasetPath, modelPath); | |||||
| String url = masterIp + ":" + podPort; | String url = masterIp + ":" + podPort; | ||||
| redisService.setCacheObject(podName,masterIp + ":" + podPort); | |||||
| redisService.setCacheObject(podName, masterIp + ":" + podPort); | |||||
| devEnvironment.setStatus("Pending"); | devEnvironment.setStatus("Pending"); | ||||
| devEnvironment.setUrl(url); | devEnvironment.setUrl(url); | ||||
| this.devEnvironmentService.update(devEnvironment); | this.devEnvironmentService.update(devEnvironment); | ||||
| return url ; | |||||
| return url; | |||||
| } | } | ||||
| @Override | @Override | ||||
| public String stopJupyterService(Integer id) throws Exception { | public String stopJupyterService(Integer id) throws Exception { | ||||
| DevEnvironment devEnvironment = this.devEnvironmentDao.queryById(id); | DevEnvironment devEnvironment = this.devEnvironmentDao.queryById(id); | ||||
| if (devEnvironment==null){ | |||||
| if (devEnvironment == null) { | |||||
| throw new Exception("开发环境配置不存在"); | throw new Exception("开发环境配置不存在"); | ||||
| } | } | ||||
| LoginUser loginUser = SecurityUtils.getLoginUser(); | LoginUser loginUser = SecurityUtils.getLoginUser(); | ||||
| //手动构造pod名称 | |||||
| String podName = loginUser.getUsername().toLowerCase() +"-editor-pod" + "-" + id; | |||||
| //构造pod和svc名称 | |||||
| String podName = loginUser.getUsername().toLowerCase() + "-editor-pod" + "-" + id; | |||||
| String svcName = loginUser.getUsername().toLowerCase() + "-editor-pod" + "-" + id + "-svc"; | |||||
| //得到pod | //得到pod | ||||
| V1Pod pod = k8sClientUtil.getNSPodList(namespace, podName); | V1Pod pod = k8sClientUtil.getNSPodList(namespace, podName); | ||||
| if(pod == null){ | |||||
| if (pod == null) { | |||||
| return "pod不存在!"; | return "pod不存在!"; | ||||
| } | } | ||||
| if (Constant.Computing_Resource_GPU.equals(devEnvironment.getComputingResource())) { | |||||
| computingResourceDao.updateUsedStateByNode(pod.getSpec().getNodeName(), Constant.Used_State_unused); | |||||
| } | |||||
| // 使用 Kubernetes API 删除 Pod | // 使用 Kubernetes API 删除 Pod | ||||
| String deleteResult = k8sClientUtil.deletePod(podName, namespace); | String deleteResult = k8sClientUtil.deletePod(podName, namespace); | ||||
| // 删除service | |||||
| k8sClientUtil.deleteService(svcName, namespace); | |||||
| devEnvironment.setStatus("Terminated"); | devEnvironment.setStatus("Terminated"); | ||||
| this.devEnvironmentService.update(devEnvironment); | this.devEnvironmentService.update(devEnvironment); | ||||
| return deleteResult + ",编辑器已停止"; | return deleteResult + ",编辑器已停止"; | ||||
| } | } | ||||
| @Override | @Override | ||||
| @@ -140,11 +152,11 @@ public class JupyterServiceImpl implements JupyterService { | |||||
| String status = PodStatus.Terminated.getName(); | String status = PodStatus.Terminated.getName(); | ||||
| PodStatusVo JupyterStatusVo = new PodStatusVo(); | PodStatusVo JupyterStatusVo = new PodStatusVo(); | ||||
| JupyterStatusVo.setStatus(status); | JupyterStatusVo.setStatus(status); | ||||
| if (devEnvironment==null){ | |||||
| if (devEnvironment == null) { | |||||
| return JupyterStatusVo; | return JupyterStatusVo; | ||||
| } | } | ||||
| LoginUser loginUser = SecurityUtils.getLoginUser(); | LoginUser loginUser = SecurityUtils.getLoginUser(); | ||||
| String podName = loginUser.getUsername().toLowerCase() +"-editor-pod" + "-" + devEnvironment.getId(); | |||||
| String podName = loginUser.getUsername().toLowerCase() + "-editor-pod" + "-" + devEnvironment.getId(); | |||||
| try { | try { | ||||
| // 查询相应pod状态 | // 查询相应pod状态 | ||||
| @@ -170,7 +182,7 @@ public class JupyterServiceImpl implements JupyterService { | |||||
| @Override | @Override | ||||
| public void upload(InputStream inputStream) { | public void upload(InputStream inputStream) { | ||||
| try { | try { | ||||
| minioUtil.uploadObject("platform-data","/pytorch/testupload4008208820",inputStream); | |||||
| minioUtil.uploadObject("platform-data", "/pytorch/testupload4008208820", inputStream); | |||||
| } catch (Exception e) { | } catch (Exception e) { | ||||
| e.printStackTrace(); | e.printStackTrace(); | ||||
| } | } | ||||
| @@ -185,7 +197,4 @@ public class JupyterServiceImpl implements JupyterService { | |||||
| } | } | ||||
| } | } | ||||
| @@ -19,58 +19,91 @@ public class AIM64EncoderUtil { | |||||
| } | } | ||||
| public static String aim64encode(Map<String, Object> value) { | public static String aim64encode(Map<String, Object> value) { | ||||
| // 将Map对象转换为JSON字符串 | |||||
| String jsonEncoded = JSON.toJSONString(value); | String jsonEncoded = JSON.toJSONString(value); | ||||
| // 将JSON字符串进行Base64编码 | |||||
| String base64Encoded = Base64.getEncoder().encodeToString(jsonEncoded.getBytes()); | String base64Encoded = Base64.getEncoder().encodeToString(jsonEncoded.getBytes()); | ||||
| String aim64Encoded = base64Encoded; | String aim64Encoded = base64Encoded; | ||||
| // 替换Base64编码中的特定字符 | |||||
| for (Map.Entry<String, String> entry : BS64_REPLACE_CHARACTERS_ENCODING.entrySet()) { | for (Map.Entry<String, String> entry : BS64_REPLACE_CHARACTERS_ENCODING.entrySet()) { | ||||
| aim64Encoded = aim64Encoded.replace(entry.getKey(), entry.getValue()); | aim64Encoded = aim64Encoded.replace(entry.getKey(), entry.getValue()); | ||||
| } | } | ||||
| // 返回带有前缀的AIM64编码字符串 | |||||
| return AIM64_ENCODING_PREFIX + aim64Encoded; | return AIM64_ENCODING_PREFIX + aim64Encoded; | ||||
| } | } | ||||
| // 这是一个静态方法,用于将 Map 对象 value 编码为字符串 | |||||
| public static String encode(Map<String, Object> value, boolean oneWayHashing) { | public static String encode(Map<String, Object> value, boolean oneWayHashing) { | ||||
| // 如果 oneWayHashing 参数为 true,表示使用一种不可逆的哈希算法 | |||||
| if (oneWayHashing) { | if (oneWayHashing) { | ||||
| // 使用 MD5 算法将 value 对象转换为字符串 | |||||
| return md5(JSON.toJSONString(value)); | return md5(JSON.toJSONString(value)); | ||||
| } | } | ||||
| // 如果 oneWayHashing 参数为 false,表示使用一种可逆的编码算法 | |||||
| return aim64encode(value); | return aim64encode(value); | ||||
| } | } | ||||
| // MD5 加密函数,用于将输入字符串转换为 MD5 加密后的字符串。 | |||||
| private static String md5(String input) { | private static String md5(String input) { | ||||
| // 尝试获取 MD5 加密对象 | |||||
| try { | try { | ||||
| java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5"); | java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5"); | ||||
| // 使用 MD5 对象对输入字符串进行加密 | |||||
| byte[] array = md.digest(input.getBytes()); | byte[] array = md.digest(input.getBytes()); | ||||
| // 创建一个 StringBuilder 对象,用于将加密后的字节转换为字符串 | |||||
| StringBuilder sb = new StringBuilder(); | StringBuilder sb = new StringBuilder(); | ||||
| // 遍历加密后的字节数组 | |||||
| for (byte b : array) { | for (byte b : array) { | ||||
| // 将每个字节转换为 16 进制字符串 | |||||
| sb.append(Integer.toHexString((b & 0xFF) | 0x100).substring(1, 3)); | sb.append(Integer.toHexString((b & 0xFF) | 0x100).substring(1, 3)); | ||||
| } | } | ||||
| // 返回加密后的字符串 | |||||
| return sb.toString(); | return sb.toString(); | ||||
| } catch (java.security.NoSuchAlgorithmException e) { | } catch (java.security.NoSuchAlgorithmException e) { | ||||
| // 如果在获取 MD5 加密对象时出现了错误,则打印错误信息 | |||||
| e.printStackTrace(); | e.printStackTrace(); | ||||
| } | } | ||||
| // 如果出现了错误,则返回 null | |||||
| return null; | return null; | ||||
| } | } | ||||
| // 这是一个 decode 方法,用于将 runIds 列表转换为查询字符串 | |||||
| public static String decode(List<String> runIds) { | public static String decode(List<String> runIds) { | ||||
| // 确保 runIds 列表的大小为 3 | // 确保 runIds 列表的大小为 3 | ||||
| if (runIds == null || runIds.size() == 0) { | if (runIds == null || runIds.size() == 0) { | ||||
| // 如果 runIds 为空,抛出 IllegalArgumentException 异常 | |||||
| throw new IllegalArgumentException("runIds 不能为空"); | throw new IllegalArgumentException("runIds 不能为空"); | ||||
| } | } | ||||
| // 构建查询字符串 | // 构建查询字符串 | ||||
| StringBuilder queryBuilder = new StringBuilder("run.hash in ["); | StringBuilder queryBuilder = new StringBuilder("run.hash in ["); | ||||
| // 遍历 runIds 列表 | |||||
| for (int i = 0; i < runIds.size(); i++) { | for (int i = 0; i < runIds.size(); i++) { | ||||
| // 如果当前不是第一个元素,添加逗号 | |||||
| if (i > 0) { | if (i > 0) { | ||||
| queryBuilder.append(","); | queryBuilder.append(","); | ||||
| } | } | ||||
| // 将当前元素添加到查询字符串中,使用双引号括起来 | |||||
| queryBuilder.append("\"").append(runIds.get(i)).append("\""); | queryBuilder.append("\"").append(runIds.get(i)).append("\""); | ||||
| } | } | ||||
| // 将查询字符串闭合 | |||||
| queryBuilder.append("]"); | queryBuilder.append("]"); | ||||
| // 将查询字符串转换为字符串 | |||||
| String query = queryBuilder.toString(); | String query = queryBuilder.toString(); | ||||
| // 创建一个 Map 对象,用于存储查询参数 | |||||
| Map<String, Object> map = new HashMap<>(); | Map<String, Object> map = new HashMap<>(); | ||||
| // 将查询字符串添加到 Map 中 | |||||
| map.put("query", query); | map.put("query", query); | ||||
| // 将 advancedMode 设置为 true | |||||
| map.put("advancedMode", true); | map.put("advancedMode", true); | ||||
| // 将 advancedQuery 设置为查询字符串 | |||||
| map.put("advancedQuery", query); | map.put("advancedQuery", query); | ||||
| // 使用 encode 方法将 Map 对象转换为查询字符串 | |||||
| String searchQuery = encode(map, false); | String searchQuery = encode(map, false); | ||||
| // 返回查询字符串 | |||||
| return searchQuery; | return searchQuery; | ||||
| } | } | ||||
| } | } | ||||
| @@ -9,19 +9,30 @@ import java.util.Set; | |||||
| public class BeansUtils { | public class BeansUtils { | ||||
| // 获取一个 Java 对象中所有为空的属性名称。: | |||||
| public static String[] getNullPropertyNames(Object source) { | public static String[] getNullPropertyNames(Object source) { | ||||
| // 创建一个 BeanWrapper 对象,参数为给定的 Java 对象 | |||||
| final BeanWrapper src = new BeanWrapperImpl(source); | final BeanWrapper src = new BeanWrapperImpl(source); | ||||
| // 获取该对象所有属性描述符 | |||||
| java.beans.PropertyDescriptor[] pds = src.getPropertyDescriptors(); | java.beans.PropertyDescriptor[] pds = src.getPropertyDescriptors(); | ||||
| // 创建一个集合,用于存储为空的属性名称 | |||||
| Set<String> emptyNames = new HashSet<String>(); | Set<String> emptyNames = new HashSet<String>(); | ||||
| // 遍历所有属性描述符 | |||||
| for(java.beans.PropertyDescriptor pd : pds) { | for(java.beans.PropertyDescriptor pd : pds) { | ||||
| // 获取属性值 | |||||
| Object srcValue = src.getPropertyValue(pd.getName()); | Object srcValue = src.getPropertyValue(pd.getName()); | ||||
| // 如果属性值为空,则将属性名称添加到集合中 | |||||
| if (srcValue == null) emptyNames.add(pd.getName()); | if (srcValue == null) emptyNames.add(pd.getName()); | ||||
| } | } | ||||
| // 创建一个字符串数组,用于存储为空的属性名称 | |||||
| String[] result = new String[emptyNames.size()]; | String[] result = new String[emptyNames.size()]; | ||||
| // 将为空的属性名称存储到字符串数组中 | |||||
| return emptyNames.toArray(result); | return emptyNames.toArray(result); | ||||
| } | } | ||||
| public static void copyPropertiesIgnoreNull(Object src, Object target){ | public static void copyPropertiesIgnoreNull(Object src, Object target){ | ||||
| // 使用 BeanUtils 工具类将源对象中的非空属性复制到目标对象中 | |||||
| BeanUtils.copyProperties(src, target, getNullPropertyNames(src)); | BeanUtils.copyProperties(src, target, getNullPropertyNames(src)); | ||||
| } | } | ||||
| } | } | ||||
| @@ -4,10 +4,13 @@ package com.ruoyi.platform.utils; | |||||
| import org.slf4j.Logger; | import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||
| import org.springframework.beans.BeanUtils; | import org.springframework.beans.BeanUtils; | ||||
| import org.apache.commons.beanutils.PropertyUtils; | |||||
| import java.lang.reflect.Field; | |||||
| import java.lang.reflect.InvocationTargetException; | |||||
| import java.util.ArrayList; | import java.util.ArrayList; | ||||
| import java.util.Collection; | import java.util.Collection; | ||||
| import java.util.List; | import java.util.List; | ||||
| import java.util.Map; | |||||
| /** | /** | ||||
| @@ -19,6 +22,13 @@ import java.util.List; | |||||
| public class ConvertUtil { | public class ConvertUtil { | ||||
| public static final Logger logger = LoggerFactory.getLogger(ConvertUtil.class); | public static final Logger logger = LoggerFactory.getLogger(ConvertUtil.class); | ||||
| /** | |||||
| * 将实体对象转换为VO对象 | |||||
| * @param source 源实体对象 | |||||
| * @param target 目标VO对象的类 | |||||
| * @return 转换后的VO对象 | |||||
| */ | |||||
| public static <T> T entityToVo(Object source, Class<T> target) { | public static <T> T entityToVo(Object source, Class<T> target) { | ||||
| if (source == null) { | if (source == null) { | ||||
| return null; | return null; | ||||
| @@ -33,6 +43,8 @@ public class ConvertUtil { | |||||
| return targetObject; | return targetObject; | ||||
| } | } | ||||
| // 将实体对象列表转换为目标类型的列表 | |||||
| public static <T> List<T> entityToVoList(Collection<?> sourceList, Class<T> target) { | public static <T> List<T> entityToVoList(Collection<?> sourceList, Class<T> target) { | ||||
| if (sourceList == null) { | if (sourceList == null) { | ||||
| return null; | return null; | ||||
| @@ -50,5 +62,65 @@ public class ConvertUtil { | |||||
| } | } | ||||
| return targetList; | return targetList; | ||||
| } | } | ||||
| public static <T> List<T> convertListMapToObjectList(List<Map<String, Object>> listMap, Class<T> targetClass) { | |||||
| List<T> resultList = new ArrayList<>(); | |||||
| if (listMap != null) { | |||||
| for (Map<String, Object> map : listMap) { | |||||
| T targetObject = convertMapToObject(map, targetClass); | |||||
| if (targetObject != null) { | |||||
| resultList.add(targetObject); | |||||
| } | |||||
| } | |||||
| } | |||||
| return resultList; | |||||
| } | |||||
| private static <T> T convertMapToObject(Map<String, Object> map, Class<T> targetClass) { | |||||
| try { | |||||
| T targetObject = targetClass.newInstance(); | |||||
| for (Map.Entry<String, Object> entry : map.entrySet()) { | |||||
| String key = entry.getKey(); | |||||
| Object value = entry.getValue(); | |||||
| String camelCaseKey = toCamelCase(key); | |||||
| if (hasProperty(targetClass, camelCaseKey)) { | |||||
| PropertyUtils.setProperty(targetObject, camelCaseKey, value); | |||||
| } | |||||
| } | |||||
| return targetObject; | |||||
| } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { | |||||
| e.printStackTrace(); | |||||
| } | |||||
| return null; | |||||
| } | |||||
| private static boolean hasProperty(Class<?> clazz, String propertyName) { | |||||
| try { | |||||
| Field field = clazz.getDeclaredField(propertyName); | |||||
| return field != null; | |||||
| } catch (NoSuchFieldException e) { | |||||
| return false; | |||||
| } | |||||
| } | |||||
| private static String toCamelCase(String key) { | |||||
| StringBuilder sb = new StringBuilder(); | |||||
| boolean nextUpperCase = false; | |||||
| for (char c : key.toCharArray()) { | |||||
| if (c == '_') { | |||||
| nextUpperCase = true; | |||||
| } else { | |||||
| if (nextUpperCase) { | |||||
| sb.append(Character.toUpperCase(c)); | |||||
| nextUpperCase = false; | |||||
| } else { | |||||
| sb.append(c); | |||||
| } | |||||
| } | |||||
| } | |||||
| return sb.toString(); | |||||
| } | |||||
| } | } | ||||
| @@ -0,0 +1,165 @@ | |||||
| package com.ruoyi.platform.utils; | |||||
| import org.eclipse.jgit.api.*; | |||||
| import org.eclipse.jgit.api.errors.GitAPIException; | |||||
| import org.eclipse.jgit.lib.Repository; | |||||
| import org.eclipse.jgit.storage.file.FileRepositoryBuilder; | |||||
| import org.eclipse.jgit.transport.CredentialsProvider; | |||||
| import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider; | |||||
| import java.io.*; | |||||
| import java.nio.file.*; | |||||
| public class DVCUtils { | |||||
| private static void runCommand(String command, String workingDir) throws Exception { | |||||
| ProcessBuilder processBuilder = new ProcessBuilder(command.split(" ")); | |||||
| processBuilder.directory(new File(workingDir)); | |||||
| Process process = processBuilder.start(); | |||||
| BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); | |||||
| String line; | |||||
| while ((line = reader.readLine()) != null) { | |||||
| System.out.println(line); | |||||
| } | |||||
| int exitCode = process.waitFor(); | |||||
| if (exitCode != 0) { | |||||
| throw new Exception("Command failed with exit code " + exitCode); | |||||
| } | |||||
| } | |||||
| public static void moveFiles(String sourcePath, String targetPath) throws Exception { | |||||
| Path sourceDir = Paths.get(sourcePath); | |||||
| Path targetDir = Paths.get(targetPath).resolve(sourceDir.getFileName()); | |||||
| if (!Files.exists(targetDir)) { | |||||
| Files.createDirectories(targetDir); | |||||
| } | |||||
| Files.move(sourceDir, targetDir, StandardCopyOption.REPLACE_EXISTING); | |||||
| } | |||||
| public static void gitClone(String localPath, String repoUrl, String branch, String username, String password) throws GitAPIException { | |||||
| CloneCommand cloneCommand = Git.cloneRepository() | |||||
| .setURI(repoUrl) | |||||
| .setBranch(branch) | |||||
| .setDirectory(new java.io.File(localPath)) | |||||
| .setCredentialsProvider(new UsernamePasswordCredentialsProvider(username, password)); | |||||
| cloneCommand.call(); | |||||
| } | |||||
| public static void gitAdd(String localPath, String filePath) throws IOException, GitAPIException { | |||||
| FileRepositoryBuilder builder = new FileRepositoryBuilder(); | |||||
| Repository repository = builder.setGitDir(new File(localPath, ".git")) | |||||
| .readEnvironment() | |||||
| .findGitDir() | |||||
| .build(); | |||||
| try (Git git = new Git(repository)) { | |||||
| AddCommand addCommand = git.add(); | |||||
| addCommand.addFilepattern(filePath).call(); | |||||
| } | |||||
| } | |||||
| public static void gitCommit(String localPath, String commitMessage) throws IOException, GitAPIException { | |||||
| FileRepositoryBuilder builder = new FileRepositoryBuilder(); | |||||
| Repository repository = builder.setGitDir(new File(localPath, ".git")) | |||||
| .readEnvironment() | |||||
| .findGitDir() | |||||
| .build(); | |||||
| try (Git git = new Git(repository)) { | |||||
| // 添加所有文件 | |||||
| AddCommand addCommand = git.add(); | |||||
| addCommand.addFilepattern(".").call(); | |||||
| // 提交更改 | |||||
| CommitCommand commitCommand = git.commit(); | |||||
| commitCommand.setMessage(commitMessage).call(); | |||||
| } | |||||
| } | |||||
| public static void gitPush(String localPath, String username, String password) throws IOException, GitAPIException { | |||||
| FileRepositoryBuilder builder = new FileRepositoryBuilder(); | |||||
| Repository repository = builder.setGitDir(new File(localPath, ".git")) | |||||
| .readEnvironment() | |||||
| .findGitDir() | |||||
| .build(); | |||||
| try (Git git = new Git(repository)) { | |||||
| CredentialsProvider credentialsProvider = new UsernamePasswordCredentialsProvider(username, password); | |||||
| PushCommand pushCommand = git.push(); | |||||
| pushCommand.setCredentialsProvider(credentialsProvider) | |||||
| .setForce(true) | |||||
| .call(); | |||||
| } | |||||
| } | |||||
| public static void gitCheckoutBranch(String localPath, String branchName) throws IOException, GitAPIException { | |||||
| FileRepositoryBuilder builder = new FileRepositoryBuilder(); | |||||
| Repository repository = builder.setGitDir(new File(localPath, ".git")) | |||||
| .readEnvironment() | |||||
| .findGitDir() | |||||
| .build(); | |||||
| try (Git git = new Git(repository)) { | |||||
| CheckoutCommand checkoutCommand = git.checkout(); | |||||
| checkoutCommand.setName(branchName).call(); | |||||
| } | |||||
| } | |||||
| public static void gitPull(String localPath, String username, String password) throws IOException, GitAPIException { | |||||
| FileRepositoryBuilder builder = new FileRepositoryBuilder(); | |||||
| Repository repository = builder.setGitDir(new File(localPath, ".git")) | |||||
| .readEnvironment() | |||||
| .findGitDir() | |||||
| .build(); | |||||
| try (Git git = new Git(repository)) { | |||||
| CredentialsProvider credentialsProvider = new UsernamePasswordCredentialsProvider(username, password); | |||||
| PullCommand pullCommand = git.pull(); | |||||
| pullCommand.setCredentialsProvider(credentialsProvider).call(); | |||||
| } | |||||
| } | |||||
| public static void dvcInit(String localPath) throws Exception { | |||||
| String command = "dvc init"; | |||||
| runCommand(command, localPath); | |||||
| } | |||||
| public static void dvcAdd(String localPath, String filePath) throws Exception { | |||||
| String command = "dvc add " + filePath; | |||||
| runCommand(command, localPath); | |||||
| } | |||||
| public static void dvcRemoteAdd(String localPath, String s3RemoteUrl) throws Exception { | |||||
| String command = "dvc remote add -d myremote s3://" + s3RemoteUrl; | |||||
| runCommand(command, localPath); | |||||
| } | |||||
| public static void dvcConfigS3Credentials(String localPath, String endpointurl) throws Exception { | |||||
| String command = "dvc remote modify myremote endpointurl " + endpointurl; | |||||
| runCommand(command, localPath); | |||||
| } | |||||
| public static void dvcConfigS3Credentials2(String localPath, String accessKeyId) throws Exception { | |||||
| String command = "dvc remote modify myremote access_key_id " + accessKeyId; | |||||
| runCommand(command, localPath); | |||||
| } | |||||
| public static void dvcConfigS3Credentials3(String localPath, String secretAccessKey) throws Exception { | |||||
| String command = "dvc remote modify myremote secret_access_key " + secretAccessKey; | |||||
| runCommand(command, localPath); | |||||
| } | |||||
| public static void dvcPush(String localPath) throws Exception { | |||||
| String command = "dvc push"; | |||||
| runCommand(command, localPath); | |||||
| } | |||||
| // 更新的 dvcPull 方法 | |||||
| public static void dvcPull(String localPath) throws Exception { | |||||
| String command = "dvc pull"; | |||||
| runCommand(command, localPath); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,114 @@ | |||||
| package com.ruoyi.platform.utils; | |||||
| import com.github.dockerjava.api.DockerClient; | |||||
| import com.github.dockerjava.api.command.CommitCmd; | |||||
| import com.github.dockerjava.api.command.InspectImageResponse; | |||||
| import com.github.dockerjava.api.model.AuthConfig; | |||||
| import com.github.dockerjava.core.DefaultDockerClientConfig; | |||||
| import com.github.dockerjava.core.DockerClientConfig; | |||||
| import com.github.dockerjava.core.DockerClientImpl; | |||||
| import com.github.dockerjava.httpclient5.ApacheDockerHttpClient; | |||||
| import com.github.dockerjava.transport.DockerHttpClient; | |||||
| import com.ruoyi.platform.vo.ImageVo; | |||||
| import lombok.extern.slf4j.Slf4j; | |||||
| import org.springframework.beans.factory.annotation.Value; | |||||
| import org.springframework.stereotype.Component; | |||||
| import java.time.Duration; | |||||
| import java.util.HashMap; | |||||
| @Slf4j | |||||
| @Component | |||||
| public class DockerClientUtil { | |||||
| @Value("${harbor.bucketName}") | |||||
| private String bucketName; | |||||
| @Value("${harbor.repository}") | |||||
| private String repository; | |||||
| @Value("${harbor.harborUrl}") | |||||
| private String harborUrl; | |||||
| @Value("${harbor.harborUser}") | |||||
| private String harborUser; | |||||
| @Value("${harbor.harborpassword}") | |||||
| private String harborpassword; | |||||
| public DockerClient getDockerClient(String dockerServerUrl) { | |||||
| //创建DefaultDockerClientConfig(指定docker服务器的配置) | |||||
| DockerClientConfig config = DefaultDockerClientConfig | |||||
| .createDefaultConfigBuilder() | |||||
| .withDockerHost("tcp://" + dockerServerUrl + ":2375") | |||||
| .withDockerTlsVerify(false) | |||||
| .withApiVersion("1.40") | |||||
| // .withDockerCertPath(dcokerCertPath) | |||||
| // .withRegistryUsername(registryUser) | |||||
| // .withRegistryPassword(registryPass) | |||||
| // .withRegistryEmail(registryMail) | |||||
| // .withRegistryUrl(registryUrl) | |||||
| .build(); | |||||
| //创建DockerHttpClient | |||||
| DockerHttpClient httpClient = new ApacheDockerHttpClient.Builder() | |||||
| .dockerHost(config.getDockerHost()) | |||||
| .sslConfig(config.getSSLConfig()) | |||||
| .maxConnections(1000) | |||||
| .connectionTimeout(Duration.ofSeconds(300)) | |||||
| .responseTimeout(Duration.ofSeconds(450)) | |||||
| .build(); | |||||
| //创建DockerClient | |||||
| return DockerClientImpl.getInstance(config, httpClient); | |||||
| } | |||||
| public String commitImage(ImageVo imageVo, String containerId, String hostIp, String userName) { | |||||
| DockerClient dockerClient = getDockerClient(hostIp); | |||||
| // 提交容器为镜像,这里的"new_image"和"new_tag"是新镜像的名字和标签 | |||||
| CommitCmd commitCmd = dockerClient.commitCmd(containerId) | |||||
| .withRepository(imageVo.getName()) | |||||
| .withTag(imageVo.getTagName()) | |||||
| .withAuthor(userName) | |||||
| .withMessage(imageVo.getDescription()); | |||||
| return commitCmd.exec(); | |||||
| } | |||||
| public HashMap<String, String> pushImageToHorbor(ImageVo imageVo, String hostIp) { | |||||
| DockerClient dockerClient = getDockerClient(hostIp); | |||||
| //Harbor登录信息 | |||||
| AuthConfig autoConfig = new AuthConfig().withRegistryAddress(harborUrl).withUsername(harborUser).withPassword(harborpassword); | |||||
| String localImageName = imageVo.getName() + ":" + imageVo.getTagName(); | |||||
| String imageName = harborUrl + "/" + bucketName + "/" + imageVo.getName(); | |||||
| //给镜像打上tag | |||||
| dockerClient.tagImageCmd(localImageName, imageName, imageVo.getTagName()).exec(); | |||||
| //推送镜像至镜像仓库 | |||||
| try { | |||||
| dockerClient.pushImageCmd(imageName).withAuthConfig(autoConfig).start().awaitCompletion(); | |||||
| //push成功后,删除本地加载的镜像 | |||||
| dockerClient.removeImageCmd(localImageName).exec(); | |||||
| String totalImageName = imageName + ":" + imageVo.getTagName(); | |||||
| InspectImageResponse exec = dockerClient.inspectImageCmd(totalImageName).exec(); | |||||
| String size = String.format("%.1f GB", (float) exec.getSize() / 1073741824.0); | |||||
| HashMap<String, String> resultMap = new HashMap<>(); | |||||
| resultMap.put("imageName",totalImageName); | |||||
| resultMap.put("size",size); | |||||
| return resultMap; | |||||
| } catch (InterruptedException e) { | |||||
| throw new RuntimeException("推送镜像失败:" + e); | |||||
| } | |||||
| } | |||||
| public void removeImage(String imageName, String hostIp){ | |||||
| DockerClient dockerClient = getDockerClient(hostIp); | |||||
| dockerClient.removeImageCmd(imageName).withForce(true).exec(); | |||||
| } | |||||
| } | |||||
| @@ -2,20 +2,29 @@ package com.ruoyi.platform.utils; | |||||
| public class FileUtil { | public class FileUtil { | ||||
| // 格式化文件大小为可读的字符串表示 | |||||
| public static String formatFileSize(long sizeInBytes) { | public static String formatFileSize(long sizeInBytes) { | ||||
| // 检查文件大小是否为负数 | |||||
| if (sizeInBytes < 0) { | if (sizeInBytes < 0) { | ||||
| throw new IllegalArgumentException("File size cannot be negative."); | throw new IllegalArgumentException("File size cannot be negative."); | ||||
| } | } | ||||
| // 如果文件大小小于1KB,直接返回字节数 | |||||
| if (sizeInBytes < 1024) { | if (sizeInBytes < 1024) { | ||||
| return sizeInBytes + " B"; | return sizeInBytes + " B"; | ||||
| } else if (sizeInBytes < 1024 * 1024) { | |||||
| } | |||||
| // 如果文件大小小于1MB,转换为KB并返回 | |||||
| else if (sizeInBytes < 1024 * 1024) { | |||||
| double sizeInKB = sizeInBytes / 1024.0; | double sizeInKB = sizeInBytes / 1024.0; | ||||
| return String.format("%.2f KB", sizeInKB); | return String.format("%.2f KB", sizeInKB); | ||||
| } else if (sizeInBytes < 1024 * 1024 * 1024) { | |||||
| } | |||||
| // 如果文件大小小于1GB,转换为MB并返回 | |||||
| else if (sizeInBytes < 1024 * 1024 * 1024) { | |||||
| double sizeInMB = sizeInBytes / (1024.0 * 1024); | double sizeInMB = sizeInBytes / (1024.0 * 1024); | ||||
| return String.format("%.2f MB", sizeInMB); | return String.format("%.2f MB", sizeInMB); | ||||
| } else { | |||||
| } | |||||
| // 如果文件大小大于或等于1GB,转换为GB并返回 | |||||
| else { | |||||
| double sizeInGB = sizeInBytes / (1024.0 * 1024 * 1024); | double sizeInGB = sizeInBytes / (1024.0 * 1024 * 1024); | ||||
| return String.format("%.2f GB", sizeInGB); | return String.format("%.2f GB", sizeInGB); | ||||
| } | } | ||||
| @@ -11,6 +11,7 @@ import org.apache.http.client.entity.UrlEncodedFormEntity; | |||||
| import org.apache.http.client.methods.CloseableHttpResponse; | import org.apache.http.client.methods.CloseableHttpResponse; | ||||
| import org.apache.http.client.methods.HttpGet; | import org.apache.http.client.methods.HttpGet; | ||||
| import org.apache.http.client.methods.HttpPost; | import org.apache.http.client.methods.HttpPost; | ||||
| import org.apache.http.client.utils.URIBuilder; | |||||
| import org.apache.http.entity.StringEntity; | import org.apache.http.entity.StringEntity; | ||||
| import org.apache.http.impl.client.CloseableHttpClient; | import org.apache.http.impl.client.CloseableHttpClient; | ||||
| import org.apache.http.impl.client.DefaultHttpClient; | import org.apache.http.impl.client.DefaultHttpClient; | ||||
| @@ -89,6 +90,110 @@ public class HttpUtils { | |||||
| public static String sendGet(String url, String param) { | public static String sendGet(String url, String param) { | ||||
| return sendGet(url, param, "UTF-8"); | return sendGet(url, param, "UTF-8"); | ||||
| } | } | ||||
| // /** | |||||
| // * 向指定 URL 发送带token的GET方法的请求 | |||||
| // * | |||||
| // * @param url 发送请求的 URL | |||||
| // * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。 | |||||
| // * @return 所代表远程资源的响应结果 | |||||
| // */ | |||||
| // public static String sendGetWithToken(String url, String param,String token) { | |||||
| // return sendGet(url, param, "UTF-8",token); | |||||
| // } | |||||
| /** | |||||
| * 向指定 URL 发送带 token 的 GET 方法的请求,使用 Apache HttpClient | |||||
| * | |||||
| * @param url 发送请求的 URL | |||||
| * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。 | |||||
| * @param token 认证 token | |||||
| * @return 所代表远程资源的响应结果 | |||||
| */ | |||||
| public static String sendGetWithToken(String url, String param, String token) { | |||||
| String result = ""; | |||||
| try (CloseableHttpClient httpClient = HttpClients.createDefault()) { | |||||
| URIBuilder uriBuilder = new URIBuilder(url); | |||||
| if (param != null && !param.isEmpty()) { | |||||
| String[] pairs = param.split("&"); | |||||
| for (String pair : pairs) { | |||||
| int idx = pair.indexOf("="); | |||||
| if (idx != -1) { | |||||
| uriBuilder.setParameter(pair.substring(0, idx), pair.substring(idx + 1)); | |||||
| } | |||||
| } | |||||
| } | |||||
| URI uri = uriBuilder.build(); | |||||
| HttpGet httpGet = new HttpGet(uri); | |||||
| httpGet.setHeader("Content-Type", "application/json"); | |||||
| httpGet.setHeader("Authorization", "Bearer " + token); | |||||
| log.info("Executing request: " + httpGet.getRequestLine()); | |||||
| try (CloseableHttpResponse response = httpClient.execute(httpGet)) { | |||||
| int statusCode = response.getStatusLine().getStatusCode(); | |||||
| if (statusCode == 200) { | |||||
| result = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8); | |||||
| } else { | |||||
| throw new IOException("HTTP request failed with response code: " + statusCode); | |||||
| } | |||||
| log.info("Response: " + result); | |||||
| } | |||||
| } catch (URISyntaxException e) { | |||||
| log.error("URISyntaxException, url=" + url + ", param=" + param, e); | |||||
| } catch (IOException e) { | |||||
| log.error("IOException, url=" + url + ", param=" + param, e); | |||||
| } | |||||
| return result; | |||||
| } | |||||
| /** | |||||
| * 向指定 URL 发送带token的GET方法的请求 | |||||
| * | |||||
| * @param url 发送请求的 URL | |||||
| * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。 | |||||
| * @param contentType 编码类型 | |||||
| * @return 所代表远程资源的响应结果 | |||||
| */ | |||||
| public static String sendGet(String url, String param, String contentType,String token) { | |||||
| StringBuilder result = new StringBuilder(); | |||||
| BufferedReader in = null; | |||||
| try { | |||||
| String urlNameString = url + "?" + param; | |||||
| log.info("sendGet - {}", urlNameString); | |||||
| URL realUrl = new URL(urlNameString); | |||||
| URLConnection connection = realUrl.openConnection(); | |||||
| connection.setRequestProperty("accept", "*/*"); | |||||
| connection.setRequestProperty("connection", "Keep-Alive"); | |||||
| connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); | |||||
| connection.setRequestProperty("Authorization", "Bearer " + token); | |||||
| connection.connect(); | |||||
| in = new BufferedReader(new InputStreamReader(connection.getInputStream(), contentType)); | |||||
| String line; | |||||
| while ((line = in.readLine()) != null) { | |||||
| result.append(line); | |||||
| } | |||||
| log.info("recv - {}", result); | |||||
| } catch (ConnectException e) { | |||||
| log.error("调用HttpUtils.sendGet ConnectException, url=" + url + ",param=" + param, e); | |||||
| } catch (SocketTimeoutException e) { | |||||
| log.error("调用HttpUtils.sendGet SocketTimeoutException, url=" + url + ",param=" + param, e); | |||||
| } catch (IOException e) { | |||||
| log.error("调用HttpUtils.sendGet IOException, url=" + url + ",param=" + param, e); | |||||
| } catch (Exception e) { | |||||
| log.error("调用HttpsUtil.sendGet Exception, url=" + url + ",param=" + param, e); | |||||
| } finally { | |||||
| try { | |||||
| if (in != null) { | |||||
| in.close(); | |||||
| } | |||||
| } catch (Exception ex) { | |||||
| log.error("调用in.close Exception, url=" + url + ",param=" + param, ex); | |||||
| } | |||||
| } | |||||
| return result.toString(); | |||||
| } | |||||
| /** | /** | ||||
| * 向指定 URL 发送GET方法的请求 | * 向指定 URL 发送GET方法的请求 | ||||
| @@ -108,7 +213,6 @@ public class HttpUtils { | |||||
| URLConnection connection = realUrl.openConnection(); | URLConnection connection = realUrl.openConnection(); | ||||
| connection.setRequestProperty("accept", "*/*"); | connection.setRequestProperty("accept", "*/*"); | ||||
| connection.setRequestProperty("connection", "Keep-Alive"); | connection.setRequestProperty("connection", "Keep-Alive"); | ||||
| connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); | |||||
| connection.connect(); | connection.connect(); | ||||
| in = new BufferedReader(new InputStreamReader(connection.getInputStream(), contentType)); | in = new BufferedReader(new InputStreamReader(connection.getInputStream(), contentType)); | ||||
| String line; | String line; | ||||
| @@ -136,6 +240,42 @@ public class HttpUtils { | |||||
| return result.toString(); | return result.toString(); | ||||
| } | } | ||||
| /** | |||||
| * 向指定 URL 发送带token的POST方法的请求 | |||||
| * | |||||
| * @param url 发送请求的 URL | |||||
| * @param | |||||
| * @return 所代表远程资源的响应结果 | |||||
| */ | |||||
| public static String sendPostWithToken(String url, Object params, String token) throws Exception { | |||||
| String resultStr = null; | |||||
| HttpPost httpPost = new HttpPost(url); | |||||
| if (params != null) { | |||||
| StringEntity entity; | |||||
| if (params instanceof Map) { | |||||
| entity = new StringEntity(dealPostParams((HashMap<String, String>) params, "UTF-8")); | |||||
| } else if (params instanceof String) { | |||||
| entity = new StringEntity((String) params, "UTF-8"); | |||||
| } else if (params instanceof List) { | |||||
| entity = new UrlEncodedFormEntity((List<? extends NameValuePair>) params, "UTF-8"); | |||||
| } else { | |||||
| throw new Exception("参数有误!"); | |||||
| } | |||||
| httpPost.setHeader("Content-Type", "application/json"); | |||||
| httpPost.setHeader("Authorization", "Bearer " + token); | |||||
| httpPost.setEntity(entity); | |||||
| } | |||||
| try { | |||||
| HttpResponse response = httpClient.execute(httpPost); | |||||
| if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { | |||||
| resultStr = EntityUtils.toString(response.getEntity()); | |||||
| } | |||||
| } catch (IOException e) { | |||||
| e.printStackTrace(); | |||||
| } | |||||
| return resultStr; | |||||
| } | |||||
| /** | /** | ||||
| * 向指定 URL 发送POST方法的请求 | * 向指定 URL 发送POST方法的请求 | ||||
| * | * | ||||
| @@ -37,10 +37,8 @@ public class JsonUtils { | |||||
| // 将JSON字符串转换为扁平化的Map | // 将JSON字符串转换为扁平化的Map | ||||
| public static Map<String, Object> flattenJson(String prefix, Map<String, Object> map) { | public static Map<String, Object> flattenJson(String prefix, Map<String, Object> map) { | ||||
| Map<String, Object> flatMap = new HashMap<>(); | Map<String, Object> flatMap = new HashMap<>(); | ||||
| Iterator<Map.Entry<String, Object>> entries = map.entrySet().iterator(); | |||||
| while (entries.hasNext()) { | |||||
| Map.Entry<String, Object> entry = entries.next(); | |||||
| for (Map.Entry<String, Object> entry : map.entrySet()) { | |||||
| String key = entry.getKey(); | String key = entry.getKey(); | ||||
| Object value = entry.getValue(); | Object value = entry.getValue(); | ||||
| @@ -53,4 +51,9 @@ public class JsonUtils { | |||||
| return flatMap; | return flatMap; | ||||
| } | } | ||||
| // 将Object转换为Map | |||||
| public static Map<String, Object> objectToMap(Object object) throws IOException { | |||||
| return objectMapper.convertValue(object, Map.class); | |||||
| } | |||||
| } | } | ||||
| @@ -1,25 +1,25 @@ | |||||
| package com.ruoyi.platform.utils; | package com.ruoyi.platform.utils; | ||||
| import com.alibaba.nacos.shaded.com.google.gson.reflect.TypeToken; | |||||
| import com.ruoyi.platform.constant.Constant; | |||||
| import com.ruoyi.platform.domain.DevEnvironment; | |||||
| import com.ruoyi.platform.mapper.ComputingResourceDao; | |||||
| import io.kubernetes.client.Exec; | import io.kubernetes.client.Exec; | ||||
| import io.kubernetes.client.custom.IntOrString; | import io.kubernetes.client.custom.IntOrString; | ||||
| import io.kubernetes.client.custom.Quantity; | import io.kubernetes.client.custom.Quantity; | ||||
| import io.kubernetes.client.openapi.ApiClient; | import io.kubernetes.client.openapi.ApiClient; | ||||
| import io.kubernetes.client.openapi.ApiException; | import io.kubernetes.client.openapi.ApiException; | ||||
| import io.kubernetes.client.openapi.ApiResponse; | |||||
| import io.kubernetes.client.openapi.apis.CoreV1Api; | import io.kubernetes.client.openapi.apis.CoreV1Api; | ||||
| import io.kubernetes.client.openapi.models.*; | import io.kubernetes.client.openapi.models.*; | ||||
| import io.kubernetes.client.util.ClientBuilder; | import io.kubernetes.client.util.ClientBuilder; | ||||
| import io.kubernetes.client.util.Watch; | |||||
| import io.kubernetes.client.util.credentials.AccessTokenAuthentication; | import io.kubernetes.client.util.credentials.AccessTokenAuthentication; | ||||
| import lombok.extern.slf4j.Slf4j; | import lombok.extern.slf4j.Slf4j; | ||||
| import org.apache.commons.lang.StringUtils; | import org.apache.commons.lang.StringUtils; | ||||
| import org.apache.poi.ss.formula.functions.T; | |||||
| import org.json.JSONObject; | |||||
| import org.springframework.beans.factory.annotation.Autowired; | import org.springframework.beans.factory.annotation.Autowired; | ||||
| import org.springframework.beans.factory.annotation.Value; | import org.springframework.beans.factory.annotation.Value; | ||||
| import org.springframework.stereotype.Component; | import org.springframework.stereotype.Component; | ||||
| import javax.annotation.PostConstruct; | |||||
| import javax.annotation.Resource; | |||||
| import java.io.BufferedReader; | import java.io.BufferedReader; | ||||
| import java.io.InputStreamReader; | import java.io.InputStreamReader; | ||||
| import java.util.*; | import java.util.*; | ||||
| @@ -40,6 +40,9 @@ public class K8sClientUtil { | |||||
| */ | */ | ||||
| private static ApiClient apiClient; | private static ApiClient apiClient; | ||||
| @Resource | |||||
| private ComputingResourceDao computingResourceDao; | |||||
| /** | /** | ||||
| * 构建集群POD内通过SA访问的客户端 | * 构建集群POD内通过SA访问的客户端 | ||||
| * loading the in-cluster config, including: | * loading the in-cluster config, including: | ||||
| @@ -133,11 +136,11 @@ public class K8sClientUtil { | |||||
| } catch (ApiException e) { | } catch (ApiException e) { | ||||
| log.error("获取 SVC 异常:", e); | log.error("获取 SVC 异常:", e); | ||||
| } | } | ||||
| if (v1ServiceList!=null) { | |||||
| if (v1ServiceList != null) { | |||||
| for (V1Service svc : v1ServiceList.getItems()) { | for (V1Service svc : v1ServiceList.getItems()) { | ||||
| if (StringUtils.equals(svc.getMetadata().getName(), serviceName)) { | if (StringUtils.equals(svc.getMetadata().getName(), serviceName)) { | ||||
| // PVC 已存在 | |||||
| return svc; | |||||
| // SVC 已存在 | |||||
| return svc; | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| @@ -177,22 +180,22 @@ public class K8sClientUtil { | |||||
| /** | /** | ||||
| * 创建k8s PVC | * 创建k8s PVC | ||||
| * | * | ||||
| * @param namespace 命名空间 | |||||
| * @param pvcName 服务名称 | |||||
| * @param namespace 命名空间 | |||||
| * @param pvcName 服务名称 | |||||
| * @return 创建成功的service对象 | * @return 创建成功的service对象 | ||||
| */ | */ | ||||
| public V1PersistentVolumeClaim createPvc(String namespace, String pvcName ,String storage, String storageClassName){ | |||||
| public V1PersistentVolumeClaim createPvc(String namespace, String pvcName, String storage, String storageClassName) { | |||||
| CoreV1Api api = new CoreV1Api(apiClient); | CoreV1Api api = new CoreV1Api(apiClient); | ||||
| V1PersistentVolumeClaimList pvcList = null; | V1PersistentVolumeClaimList pvcList = null; | ||||
| try { | try { | ||||
| pvcList = api.listNamespacedPersistentVolumeClaim(namespace, null,null, null, null, null,null,null, null, null, null); | |||||
| pvcList = api.listNamespacedPersistentVolumeClaim(namespace, null, null, null, null, null, null, null, null, null, null); | |||||
| } catch (ApiException e) { | } catch (ApiException e) { | ||||
| log.error("获取 PVC 异常:", e); | log.error("获取 PVC 异常:", e); | ||||
| } | } | ||||
| if (pvcList!=null) { | |||||
| if (pvcList != null) { | |||||
| for (V1PersistentVolumeClaim pvc1 : pvcList.getItems()) { | for (V1PersistentVolumeClaim pvc1 : pvcList.getItems()) { | ||||
| if (StringUtils.equals(pvc1.getMetadata().getName(),pvcName)) { | |||||
| if (StringUtils.equals(pvc1.getMetadata().getName(), pvcName)) { | |||||
| // PVC 已存在 | // PVC 已存在 | ||||
| return pvc1; | return pvc1; | ||||
| } | } | ||||
| @@ -227,16 +230,17 @@ public class K8sClientUtil { | |||||
| /** | /** | ||||
| * 创建k8s 临时POD | * 创建k8s 临时POD | ||||
| * | |||||
| * @param podName pod name | * @param podName pod name | ||||
| * @param namespace 命名空间 | |||||
| * @param port port | |||||
| * @param namespace 命名空间 | |||||
| * @param port port | |||||
| * @param mountPath 映射路径 | * @param mountPath 映射路径 | ||||
| * @param pvc 存储 | |||||
| * @param image 镜像 | |||||
| * @param pvc 存储 | |||||
| * @param image 镜像 | |||||
| * @return 创建成功的pod,的nodePort端口 | * @return 创建成功的pod,的nodePort端口 | ||||
| */ | */ | ||||
| public Integer createPod(String podName, String namespace, Integer port ,String mountPath, V1PersistentVolumeClaim pvc, String image){ | |||||
| public Integer createPod(String podName, String namespace, Integer port, String mountPath, V1PersistentVolumeClaim pvc, String image) { | |||||
| Map<String, String> selector = new LinkedHashMap<String, String>(); | Map<String, String> selector = new LinkedHashMap<String, String>(); | ||||
| selector.put("k8s-jupyter", podName); | selector.put("k8s-jupyter", podName); | ||||
| @@ -248,7 +252,7 @@ public class K8sClientUtil { | |||||
| } catch (ApiException e) { | } catch (ApiException e) { | ||||
| log.error("获取 POD 异常:", e); | log.error("获取 POD 异常:", e); | ||||
| } | } | ||||
| if (v1PodList!=null) { | |||||
| if (v1PodList != null) { | |||||
| for (V1Pod pod1 : v1PodList.getItems()) { | for (V1Pod pod1 : v1PodList.getItems()) { | ||||
| if (StringUtils.equals(pod1.getMetadata().getName(), podName)) { | if (StringUtils.equals(pod1.getMetadata().getName(), podName)) { | ||||
| // PVC 已存在 | // PVC 已存在 | ||||
| @@ -296,17 +300,18 @@ public class K8sClientUtil { | |||||
| /** | /** | ||||
| * 创建k8s 临时POD | * 创建k8s 临时POD | ||||
| * | |||||
| * @param podName pod name | * @param podName pod name | ||||
| * @param namespace 命名空间 | |||||
| * @param port port | |||||
| * @param namespace 命名空间 | |||||
| * @param port port | |||||
| * @param mountPath 映射路径 | * @param mountPath 映射路径 | ||||
| * @param subPath pvc子路径 | |||||
| * @param pvcName 存储名 | |||||
| * @param image 镜像 | |||||
| * @param subPath pvc子路径 | |||||
| * @param pvcName 存储名 | |||||
| * @param image 镜像 | |||||
| * @return 创建成功的pod,的nodePort端口 | * @return 创建成功的pod,的nodePort端口 | ||||
| */ | */ | ||||
| public Integer createPodWithSubPath(String podName, String namespace, Integer port ,String mountPath,String subPath,String pvcName, String image){ | |||||
| public Integer createPodWithSubPath(String podName, String namespace, Integer port, String mountPath, String subPath, String pvcName, String image) { | |||||
| Map<String, String> selector = new LinkedHashMap<String, String>(); | Map<String, String> selector = new LinkedHashMap<String, String>(); | ||||
| selector.put("k8s-jupyter", podName); | selector.put("k8s-jupyter", podName); | ||||
| @@ -318,7 +323,7 @@ public class K8sClientUtil { | |||||
| } catch (ApiException e) { | } catch (ApiException e) { | ||||
| log.error("获取 POD 异常:", e); | log.error("获取 POD 异常:", e); | ||||
| } | } | ||||
| if (v1PodList!=null) { | |||||
| if (v1PodList != null) { | |||||
| for (V1Pod pod1 : v1PodList.getItems()) { | for (V1Pod pod1 : v1PodList.getItems()) { | ||||
| if (StringUtils.equals(pod1.getMetadata().getName(), podName)) { | if (StringUtils.equals(pod1.getMetadata().getName(), podName)) { | ||||
| // PVC 已存在 | // PVC 已存在 | ||||
| @@ -375,11 +380,51 @@ public class K8sClientUtil { | |||||
| return service.getSpec().getPorts().get(0).getNodePort(); | return service.getSpec().getPorts().get(0).getNodePort(); | ||||
| } | } | ||||
| // 创建配置好的Pod | |||||
| public Integer createConfiguredPod(String podName, String namespace, Integer port, String mountPath, V1PersistentVolumeClaim pvc, DevEnvironment devEnvironment, String dataPvcName, String datasetPath, String modelPath) { | |||||
| public Integer createConfiguredPod(String podName, String namespace, Integer port, String mountPath, V1PersistentVolumeClaim pvc, String image, String dataPvcName, String datasetPath, String modelPath) { | |||||
| //设置选择节点,pod反亲和性 | |||||
| Map<String, String> selector = new LinkedHashMap<>(); | Map<String, String> selector = new LinkedHashMap<>(); | ||||
| selector.put("k8s-jupyter", podName); | |||||
| Map<String, String> nodeSelector = new LinkedHashMap<>(); | |||||
| V1Affinity v1Affinity = new V1Affinity(); | |||||
| if (Constant.Computing_Resource_GPU.equals(devEnvironment.getComputingResource())) { | |||||
| selector.put("k8s-jupyter", "CPU-GPU"); | |||||
| nodeSelector.put("resource-type", "CPU-GPU"); | |||||
| V1LabelSelectorRequirement labelSelectorRequirement = new V1LabelSelectorRequirement() | |||||
| .key("k8s-jupyter").operator("NotIn").values(Collections.singletonList("CPU-GPU")); | |||||
| V1LabelSelector labelSelector = new V1LabelSelector() | |||||
| .matchExpressions(Collections.singletonList(labelSelectorRequirement)); | |||||
| V1PodAffinityTerm podAffinityTerm = new V1PodAffinityTerm() | |||||
| .labelSelector(labelSelector) | |||||
| .namespaces(Collections.singletonList(namespace)) | |||||
| .topologyKey("kubernetes.io/hostname"); | |||||
| V1PodAffinity podAffinity = new V1PodAffinity() | |||||
| .requiredDuringSchedulingIgnoredDuringExecution(Collections.singletonList(podAffinityTerm)); | |||||
| V1LabelSelectorRequirement antiLabelSelectorRequirement = new V1LabelSelectorRequirement() | |||||
| .key("k8s-jupyter").operator("In").values(Collections.singletonList("CPU-GPU")); | |||||
| V1LabelSelector antiLabelSelector = new V1LabelSelector() | |||||
| .matchExpressions(Collections.singletonList(antiLabelSelectorRequirement)); | |||||
| V1PodAffinityTerm antiPodAffinityTerm = new V1PodAffinityTerm() | |||||
| .labelSelector(antiLabelSelector) | |||||
| .namespaces(Collections.singletonList(namespace)) | |||||
| .topologyKey("kubernetes.io/hostname"); | |||||
| V1PodAntiAffinity podAntiAffinity = new V1PodAntiAffinity() | |||||
| .requiredDuringSchedulingIgnoredDuringExecution(Collections.singletonList(antiPodAffinityTerm)); | |||||
| v1Affinity.podAffinity(podAffinity).podAntiAffinity(podAntiAffinity); | |||||
| } else { | |||||
| selector.put("k8s-jupyter", "CPU"); | |||||
| } | |||||
| // 创建Pod | |||||
| CoreV1Api api = new CoreV1Api(apiClient); | CoreV1Api api = new CoreV1Api(apiClient); | ||||
| V1PodList v1PodList = null; | V1PodList v1PodList = null; | ||||
| try { | try { | ||||
| @@ -402,14 +447,34 @@ public class K8sClientUtil { | |||||
| // 配置卷和卷挂载 | // 配置卷和卷挂载 | ||||
| List<V1VolumeMount> volumeMounts = new ArrayList<>(); | List<V1VolumeMount> volumeMounts = new ArrayList<>(); | ||||
| volumeMounts.add(new V1VolumeMount().name("workspace").mountPath(mountPath)); | volumeMounts.add(new V1VolumeMount().name("workspace").mountPath(mountPath)); | ||||
| volumeMounts.add(new V1VolumeMount().name("minio-pvc").mountPath("/datasets").subPath(datasetPath).readOnly(true)); | |||||
| volumeMounts.add(new V1VolumeMount().name("minio-pvc").mountPath("/model").subPath(modelPath).readOnly(true)); | |||||
| volumeMounts.add(new V1VolumeMount().name("minio-pvc").mountPath("/opt/data").subPath(datasetPath).readOnly(true)); | |||||
| volumeMounts.add(new V1VolumeMount().name("minio-pvc").mountPath("/opt/model").subPath(modelPath).readOnly(true)); | |||||
| List<V1Volume> volumes = new ArrayList<>(); | List<V1Volume> volumes = new ArrayList<>(); | ||||
| volumes.add(new V1Volume().name("workspace").persistentVolumeClaim(new V1PersistentVolumeClaimVolumeSource().claimName(pvc.getMetadata().getName()))); | volumes.add(new V1Volume().name("workspace").persistentVolumeClaim(new V1PersistentVolumeClaimVolumeSource().claimName(pvc.getMetadata().getName()))); | ||||
| volumes.add(new V1Volume().name("minio-pvc").persistentVolumeClaim(new V1PersistentVolumeClaimVolumeSource().claimName(dataPvcName))); | volumes.add(new V1Volume().name("minio-pvc").persistentVolumeClaim(new V1PersistentVolumeClaimVolumeSource().claimName(dataPvcName))); | ||||
| //配置资源 | |||||
| JSONObject standardJson = new JSONObject(devEnvironment.getStandard()); | |||||
| JSONObject valueJson = (JSONObject) standardJson.get("value"); | |||||
| int cpu = (int) valueJson.get("cpu"); | |||||
| String memory = (String) valueJson.get("memory"); | |||||
| memory = memory.substring(0, memory.length() - 1).concat("i"); | |||||
| int gpu = (int) valueJson.get("gpu"); | |||||
| HashMap<String, Quantity> limitMap = new HashMap<>(); | |||||
| if (Constant.Computing_Resource_GPU.equals(devEnvironment.getComputingResource())) { | |||||
| limitMap.put("nvidia.com/gpu", new Quantity(String.valueOf(gpu))); | |||||
| } | |||||
| limitMap.put("cpu", new Quantity(String.valueOf(cpu))); | |||||
| limitMap.put("memory", new Quantity(memory)); | |||||
| limitMap.put("ephemeral-storage", new Quantity("100Gi")); | |||||
| V1ResourceRequirements v1ResourceRequirements = new V1ResourceRequirements(); | |||||
| v1ResourceRequirements.setRequests(limitMap); | |||||
| v1ResourceRequirements.setLimits(limitMap); | |||||
| V1Pod pod = new V1PodBuilder() | V1Pod pod = new V1PodBuilder() | ||||
| .withNewMetadata() | .withNewMetadata() | ||||
| .withName(podName) | .withName(podName) | ||||
| @@ -418,21 +483,27 @@ public class K8sClientUtil { | |||||
| .withNewSpec() | .withNewSpec() | ||||
| .addNewContainer() | .addNewContainer() | ||||
| .withName(podName) | .withName(podName) | ||||
| .withImage(image) | |||||
| .withImage(devEnvironment.getImage()) | |||||
| .withPorts(new V1ContainerPort().containerPort(port).protocol("TCP")) | .withPorts(new V1ContainerPort().containerPort(port).protocol("TCP")) | ||||
| .withVolumeMounts(volumeMounts) | .withVolumeMounts(volumeMounts) | ||||
| .withResources(v1ResourceRequirements) | |||||
| .endContainer() | .endContainer() | ||||
| .withVolumes(volumes) | .withVolumes(volumes) | ||||
| .withTerminationGracePeriodSeconds(14400L) | |||||
| .withNodeSelector(nodeSelector) | |||||
| .withAffinity(v1Affinity) | |||||
| .endSpec() | .endSpec() | ||||
| .build(); | .build(); | ||||
| try { | try { | ||||
| pod = api.createNamespacedPod(namespace, pod, null, null, null); | pod = api.createNamespacedPod(namespace, pod, null, null, null); | ||||
| String nodeName = getNodeName(podName, namespace); | |||||
| if (Constant.Computing_Resource_GPU.equals(devEnvironment.getComputingResource())) { | |||||
| computingResourceDao.updateUsedStateByNode(nodeName, Constant.Used_State_used); | |||||
| } | |||||
| } catch (ApiException e) { | } catch (ApiException e) { | ||||
| log.error("创建pod异常:" + e.getResponseBody(), e); | |||||
| throw new RuntimeException("创建pod异常:" + e.getResponseBody()); | |||||
| } catch (Exception e) { | } catch (Exception e) { | ||||
| log.error("创建pod系统异常:", e); | |||||
| throw new RuntimeException("创建pod系统异常:", e); | |||||
| } | } | ||||
| V1Service service = createService(namespace, podName + "-svc", port, selector); | V1Service service = createService(namespace, podName + "-svc", port, selector); | ||||
| @@ -440,14 +511,12 @@ public class K8sClientUtil { | |||||
| } | } | ||||
| /** | /** | ||||
| * 根据获取namespace,deploymentName的Pod Name | * 根据获取namespace,deploymentName的Pod Name | ||||
| * | * | ||||
| * @return podList | * @return podList | ||||
| */ | */ | ||||
| public V1Pod getNSPodList(String namespace,String deploymentName) throws Exception { | |||||
| public V1Pod getNSPodList(String namespace, String deploymentName) throws Exception { | |||||
| // new a CoreV1Api | // new a CoreV1Api | ||||
| CoreV1Api api = new CoreV1Api(apiClient); | CoreV1Api api = new CoreV1Api(apiClient); | ||||
| V1PodList v1PodList = null; | V1PodList v1PodList = null; | ||||
| @@ -468,12 +537,12 @@ public class K8sClientUtil { | |||||
| return null; | return null; | ||||
| } | } | ||||
| public String executeCommand(V1Pod item, String command) { | |||||
| public String executeCommand(V1Pod item, String command) { | |||||
| try { | try { | ||||
| // 创建API实例 | // 创建API实例 | ||||
| // 创建Exec实例 | // 创建Exec实例 | ||||
| Exec exec = new Exec(apiClient); | Exec exec = new Exec(apiClient); | ||||
| String[] cmd = { "/bin/sh", "-c", command}; | |||||
| String[] cmd = {"/bin/sh", "-c", command}; | |||||
| Process proc = exec.exec(item, cmd, false); | Process proc = exec.exec(item, cmd, false); | ||||
| // 读取输出 | // 读取输出 | ||||
| BufferedReader reader = new BufferedReader(new InputStreamReader(proc.getInputStream())); | BufferedReader reader = new BufferedReader(new InputStreamReader(proc.getInputStream())); | ||||
| @@ -498,19 +567,49 @@ public class K8sClientUtil { | |||||
| /** | /** | ||||
| * 根据Pod的名称和Namespace查询Pod的状态 | * 根据Pod的名称和Namespace查询Pod的状态 | ||||
| * @param podName Pod的名称 | |||||
| * | |||||
| * @param podName Pod的名称 | |||||
| * @param namespace Pod所在的Namespace | * @param namespace Pod所在的Namespace | ||||
| */ | */ | ||||
| public String getPodStatus(String podName, String namespace) throws Exception { | |||||
| public String getPodStatus(String podName, String namespace) throws Exception { | |||||
| CoreV1Api api = new CoreV1Api(apiClient); | CoreV1Api api = new CoreV1Api(apiClient); | ||||
| V1Pod pod = api.readNamespacedPod(podName, namespace, null, null, null); | V1Pod pod = api.readNamespacedPod(podName, namespace, null, null, null); | ||||
| return pod.getStatus().getPhase(); | return pod.getStatus().getPhase(); | ||||
| } | } | ||||
| public String getPodLogs(String podName,String namespace,String container,int line) { | |||||
| /** | |||||
| * 根据Pod的名称和Namespace查询Pod的容器信息 | |||||
| * | |||||
| * @param podName Pod的名称 | |||||
| * @param namespace Pod所在的Namespace | |||||
| */ | |||||
| public String getPodContainerId(String podName, String namespace) throws Exception { | |||||
| CoreV1Api api = new CoreV1Api(apiClient); | |||||
| V1Pod pod = api.readNamespacedPod(podName, namespace, null, null, null); | |||||
| if (pod.getStatus().getContainerStatuses().size() != 1) { | |||||
| throw new RuntimeException("容器错误"); | |||||
| } | |||||
| String containerId = pod.getStatus().getContainerStatuses().get(0).getContainerID().split("//")[1]; | |||||
| return containerId; | |||||
| } | |||||
| public String getHostIp(String podName, String namespace) throws Exception { | |||||
| CoreV1Api api = new CoreV1Api(apiClient); | |||||
| V1Pod pod = api.readNamespacedPod(podName, namespace, null, null, null); | |||||
| return pod.getStatus().getHostIP(); | |||||
| } | |||||
| public String getNodeName(String podName, String namespace) throws Exception { | |||||
| CoreV1Api api = new CoreV1Api(apiClient); | |||||
| V1Pod pod = api.readNamespacedPod(podName, namespace, null, null, null); | |||||
| return pod.getSpec().getNodeName(); | |||||
| } | |||||
| public String getPodLogs(String podName, String namespace, String container, int line) { | |||||
| CoreV1Api api = new CoreV1Api(apiClient); | CoreV1Api api = new CoreV1Api(apiClient); | ||||
| try { | try { | ||||
| String log = api.readNamespacedPodLog(podName, namespace, StringUtils.isEmpty(container)?null:container, null, null, null, null,null, null, line, null); | |||||
| String log = api.readNamespacedPodLog(podName, namespace, StringUtils.isEmpty(container) ? null : container, null, null, null, null, null, null, line, null); | |||||
| return log; | return log; | ||||
| } catch (ApiException e) { | } catch (ApiException e) { | ||||
| throw new RuntimeException("获取Pod日志异常", e); | throw new RuntimeException("获取Pod日志异常", e); | ||||
| @@ -519,7 +618,7 @@ public class K8sClientUtil { | |||||
| } | } | ||||
| public V1Pod createPodWithEnv(String podName,String namespace,String proxyUrl ,String mountPath,String pvcName, String image){ | |||||
| public V1Pod createPodWithEnv(String podName, String namespace, String proxyUrl, String mountPath, String pvcName, String image) { | |||||
| CoreV1Api api = new CoreV1Api(apiClient); | CoreV1Api api = new CoreV1Api(apiClient); | ||||
| V1PodList v1PodList = null; | V1PodList v1PodList = null; | ||||
| V1Pod pod = new V1PodBuilder() | V1Pod pod = new V1PodBuilder() | ||||
| @@ -563,7 +662,7 @@ public class K8sClientUtil { | |||||
| /** | /** | ||||
| * 删除 Pod | * 删除 Pod | ||||
| * | * | ||||
| * @param podName Pod 名称 | |||||
| * @param podName Pod 名称 | |||||
| * @param namespace 命名空间 | * @param namespace 命名空间 | ||||
| * @throws ApiException 异常 | * @throws ApiException 异常 | ||||
| */ | */ | ||||
| @@ -578,10 +677,30 @@ public class K8sClientUtil { | |||||
| } | } | ||||
| } | } | ||||
| /** | |||||
| * 删除 Service | |||||
| * | |||||
| * @param svcName Service 名称 | |||||
| * @param namespace 命名空间 | |||||
| * @throws ApiException 异常 | |||||
| */ | |||||
| public String deleteService(String svcName, String namespace) throws ApiException { | |||||
| CoreV1Api api = new CoreV1Api(apiClient); | |||||
| try { | |||||
| V1Status result = api.deleteNamespacedService(svcName, namespace, null, null, null, null, null, null); | |||||
| return "Service " + svcName + " 删除请求已发送"; | |||||
| } catch (ApiException e) { | |||||
| log.error("删除service异常:" + e.getResponseBody(), e); | |||||
| throw e; | |||||
| } | |||||
| } | |||||
| /** | /** | ||||
| * 检查 Pod 是否存在 | * 检查 Pod 是否存在 | ||||
| * | * | ||||
| * @param podName Pod 名称 | |||||
| * @param podName Pod 名称 | |||||
| * @param namespace 命名空间 | * @param namespace 命名空间 | ||||
| * @return 是否存在 | * @return 是否存在 | ||||
| * @throws ApiException 异常 | * @throws ApiException 异常 | ||||
| @@ -589,7 +708,7 @@ public class K8sClientUtil { | |||||
| public boolean checkPodExists(String podName, String namespace) throws ApiException { | public boolean checkPodExists(String podName, String namespace) throws ApiException { | ||||
| CoreV1Api api = new CoreV1Api(apiClient); | CoreV1Api api = new CoreV1Api(apiClient); | ||||
| try { | try { | ||||
| api.readNamespacedPod(podName, namespace, null,false,false); | |||||
| api.readNamespacedPod(podName, namespace, null, false, false); | |||||
| return true; | return true; | ||||
| } catch (ApiException e) { | } catch (ApiException e) { | ||||
| if (e.getCode() == 404) { | if (e.getCode() == 404) { | ||||
| @@ -7,7 +7,8 @@ import org.springframework.stereotype.Component; | |||||
| import java.util.List; | import java.util.List; | ||||
| @Component | @Component | ||||
| public class MlflowUtil { | |||||
| public class | |||||
| MlflowUtil { | |||||
| private static String trackingUri = "http://172.20.32.181:32005"; | private static String trackingUri = "http://172.20.32.181:32005"; | ||||
| private MlflowClient client; | private MlflowClient client; | ||||
| @@ -0,0 +1,28 @@ | |||||
| package com.ruoyi.platform.utils; | |||||
| import org.yaml.snakeyaml.Yaml; | |||||
| import java.io.FileWriter; | |||||
| import java.io.IOException; | |||||
| import java.util.Map; | |||||
| public class YamlUtils { | |||||
| /** | |||||
| * 将Map对象转换为YAML格式并写入指定路径的文件中 | |||||
| * | |||||
| * @param data Map对象 | |||||
| * @param path 文件路径 | |||||
| * @param fileName 文件名 | |||||
| */ | |||||
| public static void generateYamlFile(Map<String, Object> data, String path, String fileName) { | |||||
| Yaml yaml = new Yaml(); | |||||
| String fullPath = path + "/" + fileName + ".yaml"; | |||||
| try (FileWriter writer = new FileWriter(fullPath)) { | |||||
| yaml.dump(data, writer); | |||||
| } catch (IOException e) { | |||||
| e.printStackTrace(); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -3,11 +3,13 @@ package com.ruoyi.platform.vo; | |||||
| import com.fasterxml.jackson.databind.PropertyNamingStrategy; | import com.fasterxml.jackson.databind.PropertyNamingStrategy; | ||||
| import com.fasterxml.jackson.databind.annotation.JsonNaming; | import com.fasterxml.jackson.databind.annotation.JsonNaming; | ||||
| import io.swagger.annotations.ApiModelProperty; | import io.swagger.annotations.ApiModelProperty; | ||||
| import lombok.Data; | |||||
| import java.io.Serializable; | import java.io.Serializable; | ||||
| import java.util.List; | import java.util.List; | ||||
| @JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class) | @JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class) | ||||
| @Data | |||||
| public class DatasetVo implements Serializable { | public class DatasetVo implements Serializable { | ||||
| @@ -25,6 +27,7 @@ public class DatasetVo implements Serializable { | |||||
| private String dataType; | private String dataType; | ||||
| @ApiModelProperty(name = "data_tag") | @ApiModelProperty(name = "data_tag") | ||||
| private String dataTag; | private String dataTag; | ||||
| /** | /** | ||||
| * 版本 | * 版本 | ||||
| */ | */ | ||||
| @@ -33,73 +36,17 @@ public class DatasetVo implements Serializable { | |||||
| @ApiModelProperty(name = "dataset_version_vos") | @ApiModelProperty(name = "dataset_version_vos") | ||||
| private List<VersionVo> datasetVersionVos; | private List<VersionVo> datasetVersionVos; | ||||
| /** | /** | ||||
| * 可用集群 | * 可用集群 | ||||
| */ | */ | ||||
| @ApiModelProperty(name = "available_cluster") | @ApiModelProperty(name = "available_cluster") | ||||
| private String availableCluster; | private String availableCluster; | ||||
| public String getName() { | |||||
| return name; | |||||
| } | |||||
| public void setName(String name) { | |||||
| this.name = name; | |||||
| } | |||||
| public String getDescription() { | |||||
| return description; | |||||
| } | |||||
| public void setDescription(String description) { | |||||
| this.description = description; | |||||
| } | |||||
| public int getAvailableRange() { | |||||
| return availableRange; | |||||
| } | |||||
| public void setAvailableRange(int availableRange) { | |||||
| this.availableRange = availableRange; | |||||
| } | |||||
| public String getDataType() { | |||||
| return dataType; | |||||
| } | |||||
| public void setDataType(String dataType) { | |||||
| this.dataType = dataType; | |||||
| } | |||||
| public String getDataTag() { | |||||
| return dataTag; | |||||
| } | |||||
| public void setDataTag(String dataTag) { | |||||
| this.dataTag = dataTag; | |||||
| } | |||||
| public String getVersion() { | |||||
| return version; | |||||
| } | |||||
| public void setVersion(String version) { | |||||
| this.version = version; | |||||
| } | |||||
| public List<VersionVo> getDatasetVersionVos() { | |||||
| return datasetVersionVos; | |||||
| } | |||||
| public void setDatasetVersionVos(List<VersionVo> datasetVersionVos) { | |||||
| this.datasetVersionVos = datasetVersionVos; | |||||
| } | |||||
| public String getAvailableCluster() { | |||||
| return availableCluster; | |||||
| } | |||||
| public void setAvailableCluster(String availableCluster) { | |||||
| this.availableCluster = availableCluster; | |||||
| } | |||||
| /** | |||||
| * 数据集仓库名称 | |||||
| */ | |||||
| @ApiModelProperty(name = "repository_name") | |||||
| private String repositoryName; | |||||
| } | } | ||||
| @@ -0,0 +1,67 @@ | |||||
| package com.ruoyi.platform.vo; | |||||
| import com.fasterxml.jackson.databind.PropertyNamingStrategy; | |||||
| import com.fasterxml.jackson.databind.annotation.JsonNaming; | |||||
| import io.swagger.annotations.ApiModel; | |||||
| import io.swagger.annotations.ApiModelProperty; | |||||
| import lombok.Data; | |||||
| import java.io.Serializable; | |||||
| @ApiModel(description = "Git项目信息") | |||||
| @Data | |||||
| @JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class) | |||||
| public class GitProjectVo implements Serializable { | |||||
| @ApiModelProperty(value = "用户或组织ID", required = true) | |||||
| private int userId; | |||||
| @ApiModelProperty(value = "项目名称", required = true) | |||||
| private String name; | |||||
| @ApiModelProperty(value = "项目描述", required = false) | |||||
| private String description; | |||||
| @ApiModelProperty(value = "项目标识", required = true) | |||||
| private String repositoryName; | |||||
| // @ApiModelProperty(value = "项目分类ID", required = false) | |||||
| // private int projectCategoryId; | |||||
| // | |||||
| // @ApiModelProperty(value = "项目语言ID", required = false) | |||||
| // private int projectLanguageId; | |||||
| // @ApiModelProperty(value = "项目忽略文件ID", required = false) | |||||
| // private int ignoreId; | |||||
| // @ApiModelProperty(value = "项目许可证ID", required = false) | |||||
| // private int licenseId; | |||||
| @ApiModelProperty(value = "项目是否为私有项目", required = false) | |||||
| private boolean isPrivate; | |||||
| // @ApiModelProperty(value = "是否为区块链激励项目", required = false) | |||||
| // private boolean blockchain; | |||||
| // | |||||
| // @ApiModelProperty(value = "区块链激励金额总数", required = false) | |||||
| // private int blockchainTokenAll; | |||||
| // | |||||
| // @Override | |||||
| // public String toString() { | |||||
| // return "GitProjectVo{" + | |||||
| // "userId=" + userId + | |||||
| // ", name='" + name + '\'' + | |||||
| // ", description='" + description + '\'' + | |||||
| // ", repositoryName='" + repositoryName + '\'' + | |||||
| // ", projectCategoryId=" + projectCategoryId + | |||||
| // ", projectLanguageId=" + projectLanguageId + | |||||
| // ", ignoreId=" + ignoreId + | |||||
| // ", licenseId=" + licenseId + | |||||
| // ", isPrivate=" + isPrivate + | |||||
| // ", blockchain=" + blockchain + | |||||
| // ", blockchainTokenAll=" + blockchainTokenAll + | |||||
| // '}'; | |||||
| // } | |||||
| } | |||||
| @@ -57,13 +57,16 @@ public class ImageVo implements Serializable { | |||||
| @ApiModelProperty(name = "status") | @ApiModelProperty(name = "status") | ||||
| private String status; | private String status; | ||||
| @ApiModelProperty(value = "上传方式, 基于公网上传0,基于本地上传1") | |||||
| @ApiModelProperty(name = "upload_type", value = "上传方式, 基于公网上传0,基于本地上传1") | |||||
| private Integer uploadType; | private Integer uploadType; | ||||
| @ApiModelProperty(value = "镜像上传路径") | @ApiModelProperty(value = "镜像上传路径") | ||||
| private String path; | private String path; | ||||
| @ApiModelProperty(name = "dev_environment_id", value = "环境id") | |||||
| private Integer devEnvironmentId; | |||||
| // public Integer getId() { | // public Integer getId() { | ||||
| // return id; | // return id; | ||||
| // } | // } | ||||
| @@ -147,7 +150,17 @@ public class ImageVo implements Serializable { | |||||
| public String getPath() { | public String getPath() { | ||||
| return path; | return path; | ||||
| } | } | ||||
| public void setPath(String path) { | public void setPath(String path) { | ||||
| this.path = path; | this.path = path; | ||||
| } | } | ||||
| public Integer getDevEnvironmentId() { | |||||
| return devEnvironmentId; | |||||
| } | |||||
| public void setDevEnvironmentId(Integer devEnvironmentId) { | |||||
| this.devEnvironmentId = devEnvironmentId; | |||||
| } | |||||
| } | } | ||||
| @@ -0,0 +1,43 @@ | |||||
| package com.ruoyi.platform.vo; | |||||
| import com.fasterxml.jackson.databind.PropertyNamingStrategy; | |||||
| import com.fasterxml.jackson.databind.annotation.JsonNaming; | |||||
| import io.swagger.annotations.ApiModelProperty; | |||||
| import lombok.Data; | |||||
| import org.apache.ibatis.annotations.MapKey; | |||||
| import java.io.Serializable; | |||||
| import java.util.List; | |||||
| @JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class) | |||||
| @Data | |||||
| public class NewDatasetVo implements Serializable { | |||||
| @ApiModelProperty(name = "name") | |||||
| private String name; | |||||
| /** | |||||
| * 数据集仓库名称 | |||||
| */ | |||||
| @ApiModelProperty(name = "identifier") | |||||
| private String identifier; | |||||
| @ApiModelProperty(name = "description") | |||||
| private String description; | |||||
| /** | |||||
| * 是否公开1公开,0私有 | |||||
| */ | |||||
| @ApiModelProperty(name = "is_public") | |||||
| private Boolean isPublic; | |||||
| @ApiModelProperty(name = "data_type") | |||||
| private String dataType; | |||||
| @ApiModelProperty(name = "data_tag") | |||||
| private String dataTag; | |||||
| @ApiModelProperty(name = "time_ago") | |||||
| private String timeAgo; | |||||
| @ApiModelProperty(name = "repo_id") | |||||
| private Integer repoId; | |||||
| @ApiModelProperty(name = "visits") | |||||
| private Integer visits; | |||||
| @ApiModelProperty(name = "create_by") | |||||
| private String createBy; | |||||
| } | |||||
| @@ -15,6 +15,10 @@ spring: | |||||
| discovery: | discovery: | ||||
| # 服务注册地址 | # 服务注册地址 | ||||
| server-addr: nacos-ci4s.ci4s-test.svc:8848 | server-addr: nacos-ci4s.ci4s-test.svc:8848 | ||||
| username: nacos | |||||
| password: nacos | |||||
| retry: | |||||
| enabled: true | |||||
| config: | config: | ||||
| # 配置中心地址 | # 配置中心地址 | ||||
| server-addr: nacos-ci4s.ci4s-test.svc:8848 | server-addr: nacos-ci4s.ci4s-test.svc:8848 | ||||
| @@ -22,4 +26,9 @@ spring: | |||||
| file-extension: yml | file-extension: yml | ||||
| # 共享配置 | # 共享配置 | ||||
| shared-configs: | shared-configs: | ||||
| - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} | |||||
| - data-id: application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} | |||||
| group: DEFAULT_GROUP | |||||
| refresh: true | |||||
| - data-id: management-platform-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} | |||||
| group: DEFAULT_GROUP | |||||
| refresh: true | |||||
| @@ -0,0 +1,115 @@ | |||||
| <?xml version="1.0" encoding="UTF-8"?> | |||||
| <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> | |||||
| <mapper namespace="com.ruoyi.platform.mapper.CodeConfigDao"> | |||||
| <insert id="insert"> | |||||
| insert into code_config(code_repo_name, code_repo_vis, git_url, git_branch, verify_mode, git_user_name, | |||||
| git_password, ssh_key, create_by, create_time, update_by, update_time) | |||||
| values (#{codeConfig.codeRepoName}, #{codeConfig.codeRepoVis}, #{codeConfig.gitUrl}, #{codeConfig.gitBranch}, | |||||
| #{codeConfig.verifyMode}, #{codeConfig.gitUserName}, #{codeConfig.gitPassword}, | |||||
| #{codeConfig.sshKey}, #{codeConfig.createBy}, #{codeConfig.createTime}, #{codeConfig.updateBy}, | |||||
| #{codeConfig.updateTime}) | |||||
| </insert> | |||||
| <update id="update"> | |||||
| update code_config | |||||
| <set> | |||||
| <if test="codeConfig.codeRepoName != null and codeConfig.codeRepoName != ''"> | |||||
| code_repo_name = #{codeConfig.codeRepoName}, | |||||
| </if> | |||||
| <if test="codeConfig.codeRepoVis != null"> | |||||
| code_repo_vis = #{codeConfig.codeRepoVis}, | |||||
| </if> | |||||
| <if test="codeConfig.gitUrl != null"> | |||||
| git_url = #{codeConfig.gitUrl}, | |||||
| </if> | |||||
| <if test="codeConfig.gitBranch != null and codeConfig.gitBranch != ''"> | |||||
| git_branch = #{codeConfig.gitBranch}, | |||||
| </if> | |||||
| verify_mode = #{codeConfig.verifyMode}, | |||||
| git_user_name = #{codeConfig.gitUserName}, | |||||
| git_password = #{codeConfig.gitPassword}, | |||||
| ssh_key = #{codeConfig.sshKey}, | |||||
| <if test="codeConfig.createBy != null and codeConfig.createBy != ''"> | |||||
| create_by = #{codeConfig.createBy}, | |||||
| </if> | |||||
| <if test="codeConfig.createTime != null"> | |||||
| create_time = #{codeConfig.createTime}, | |||||
| </if> | |||||
| <if test="codeConfig.updateBy != null and codeConfig.updateBy != ''"> | |||||
| update_by = #{codeConfig.updateBy}, | |||||
| </if> | |||||
| <if test="codeConfig.state != null"> | |||||
| state = #{codeConfig.state}, | |||||
| </if> | |||||
| update_time = sysdate() | |||||
| </set> | |||||
| where id = #{codeConfig.id} | |||||
| </update> | |||||
| <select id="count" resultType="java.lang.Long"> | |||||
| select count(1) | |||||
| from code_config | |||||
| <include refid="common_condition"></include> | |||||
| </select> | |||||
| <select id="queryAllByLimit" resultType="com.ruoyi.platform.domain.CodeConfig"> | |||||
| select * from code_config | |||||
| <include refid="common_condition"></include> | |||||
| limit #{pageable.offset}, #{pageable.pageSize} | |||||
| </select> | |||||
| <select id="queryById" resultType="com.ruoyi.platform.domain.CodeConfig"> | |||||
| select * | |||||
| from code_config | |||||
| where id = #{id} | |||||
| and state = 1 | |||||
| </select> | |||||
| <select id="queryByCodeRepoName" resultType="java.lang.Long"> | |||||
| select id | |||||
| from code_config | |||||
| where code_repo_name = #{codeRepoName} | |||||
| and state = 1 | |||||
| </select> | |||||
| <sql id="common_condition"> | |||||
| <where> | |||||
| state = 1 | |||||
| <if test="codeConfig.id != null"> | |||||
| and id = #{codeConfig.id} | |||||
| </if> | |||||
| <if test="codeConfig.codeRepoName != null and codeConfig.codeRepoName != ''"> | |||||
| and code_repo_name LIKE CONCAT('%', #{codeConfig.codeRepoName}, '%') | |||||
| </if> | |||||
| <if test="codeConfig.codeRepoVis != null"> | |||||
| and code_repo_vis = #{codeConfig.codeRepoVis} | |||||
| </if> | |||||
| <if test="codeConfig.gitUrl != null"> | |||||
| and git_url = #{codeConfig.gitUrl} | |||||
| </if> | |||||
| <if test="codeConfig.gitBranch != null and codeConfig.gitBranch != ''"> | |||||
| and git_branch = #{codeConfig.gitBranch} | |||||
| </if> | |||||
| <if test="codeConfig.verifyMode != null"> | |||||
| and verify_mode = #{codeConfig.verifyMode} | |||||
| </if> | |||||
| <if test="codeConfig.gitUserName != null and codeConfig.gitUserName != ''"> | |||||
| and git_user_name = #{codeConfig.gitUserName} | |||||
| </if> | |||||
| <if test="codeConfig.createBy != null and codeConfig.createBy != ''"> | |||||
| and create_by = #{codeConfig.createBy} | |||||
| </if> | |||||
| <if test="codeConfig.createTime != null"> | |||||
| and create_time = #{codeConfig.createTime} | |||||
| </if> | |||||
| <if test="codeConfig.updateBy != null and codeConfig.updateBy != ''"> | |||||
| and update_by = #{codeConfig.updateBy} | |||||
| </if> | |||||
| <if test="codeConfig.updateTime != null"> | |||||
| and update_time = #{codeConfig.updateTime} | |||||
| </if> | |||||
| </where> | |||||
| </sql> | |||||
| </mapper> | |||||
| @@ -156,6 +156,10 @@ computing_resource = values(computing_resource)standard = values(standard)descri | |||||
| where id = #{computingResource.id} | where id = #{computingResource.id} | ||||
| </update> | </update> | ||||
| <update id="updateUsedStateByNode"> | |||||
| update computing_resource set used_state = #{usedState} where node = #{node} | |||||
| </update> | |||||
| <!--通过主键删除--> | <!--通过主键删除--> | ||||
| <delete id="deleteById"> | <delete id="deleteById"> | ||||
| delete from computing_resource where id = #{id} | delete from computing_resource where id = #{id} | ||||
| @@ -15,6 +15,7 @@ | |||||
| <result property="updateBy" column="update_by" jdbcType="VARCHAR"/> | <result property="updateBy" column="update_by" jdbcType="VARCHAR"/> | ||||
| <result property="updateTime" column="update_time" jdbcType="TIMESTAMP"/> | <result property="updateTime" column="update_time" jdbcType="TIMESTAMP"/> | ||||
| <result property="state" column="state" jdbcType="INTEGER"/> | <result property="state" column="state" jdbcType="INTEGER"/> | ||||
| <result property="hostIp" column="host_ip" jdbcType="VARCHAR"/> | |||||
| </resultMap> | </resultMap> | ||||
| <!--根据模型id返回版本列表--> | <!--根据模型id返回版本列表--> | ||||
| @@ -15,6 +15,10 @@ spring: | |||||
| discovery: | discovery: | ||||
| # 服务注册地址 | # 服务注册地址 | ||||
| server-addr: nacos-ci4s.ci4s-test.svc:8848 | server-addr: nacos-ci4s.ci4s-test.svc:8848 | ||||
| username: nacos | |||||
| password: nacos | |||||
| retry: | |||||
| enabled: true | |||||
| config: | config: | ||||
| # 配置中心地址 | # 配置中心地址 | ||||
| server-addr: nacos-ci4s.ci4s-test.svc:8848 | server-addr: nacos-ci4s.ci4s-test.svc:8848 | ||||
| @@ -22,4 +26,6 @@ spring: | |||||
| file-extension: yml | file-extension: yml | ||||
| # 共享配置 | # 共享配置 | ||||
| shared-configs: | shared-configs: | ||||
| - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} | |||||
| - data-id: application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} | |||||
| group: DEFAULT_GROUP | |||||
| refresh: true | |||||
| @@ -15,6 +15,10 @@ spring: | |||||
| discovery: | discovery: | ||||
| # 服务注册地址 | # 服务注册地址 | ||||
| server-addr: nacos-ci4s.ci4s-test.svc:8848 | server-addr: nacos-ci4s.ci4s-test.svc:8848 | ||||
| username: nacos | |||||
| password: nacos | |||||
| retry: | |||||
| enabled: true | |||||
| config: | config: | ||||
| # 配置中心地址 | # 配置中心地址 | ||||
| server-addr: nacos-ci4s.ci4s-test.svc:8848 | server-addr: nacos-ci4s.ci4s-test.svc:8848 | ||||
| @@ -22,4 +26,6 @@ spring: | |||||
| file-extension: yml | file-extension: yml | ||||
| # 共享配置 | # 共享配置 | ||||
| shared-configs: | shared-configs: | ||||
| - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} | |||||
| - data-id: application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} | |||||
| group: DEFAULT_GROUP | |||||
| refresh: true | |||||
| @@ -65,7 +65,7 @@ | |||||
| <groupId>com.mysql</groupId> | <groupId>com.mysql</groupId> | ||||
| <artifactId>mysql-connector-j</artifactId> | <artifactId>mysql-connector-j</artifactId> | ||||
| </dependency> | </dependency> | ||||
| <!-- RuoYi Common Log --> | <!-- RuoYi Common Log --> | ||||
| <dependency> | <dependency> | ||||
| <groupId>com.ruoyi</groupId> | <groupId>com.ruoyi</groupId> | ||||
| @@ -77,7 +77,13 @@ | |||||
| <groupId>com.ruoyi</groupId> | <groupId>com.ruoyi</groupId> | ||||
| <artifactId>ruoyi-common-swagger</artifactId> | <artifactId>ruoyi-common-swagger</artifactId> | ||||
| </dependency> | </dependency> | ||||
| <!-- RuoYi Common DataSource --> | |||||
| <dependency> | |||||
| <groupId>com.ruoyi</groupId> | |||||
| <artifactId>ruoyi-common-datasource</artifactId> | |||||
| </dependency> | |||||
| </dependencies> | </dependencies> | ||||
| <build> | <build> | ||||
| @@ -3,7 +3,7 @@ server: | |||||
| port: 9203 | port: 9203 | ||||
| # Spring | # Spring | ||||
| spring: | |||||
| spring: | |||||
| application: | application: | ||||
| # 应用名称 | # 应用名称 | ||||
| name: ruoyi-job | name: ruoyi-job | ||||
| @@ -15,6 +15,10 @@ spring: | |||||
| discovery: | discovery: | ||||
| # 服务注册地址 | # 服务注册地址 | ||||
| server-addr: nacos-ci4s.ci4s-test.svc:8848 | server-addr: nacos-ci4s.ci4s-test.svc:8848 | ||||
| username: nacos | |||||
| password: nacos | |||||
| retry: | |||||
| enabled: true | |||||
| config: | config: | ||||
| # 配置中心地址 | # 配置中心地址 | ||||
| server-addr: nacos-ci4s.ci4s-test.svc:8848 | server-addr: nacos-ci4s.ci4s-test.svc:8848 | ||||
| @@ -22,4 +26,9 @@ spring: | |||||
| file-extension: yml | file-extension: yml | ||||
| # 共享配置 | # 共享配置 | ||||
| shared-configs: | shared-configs: | ||||
| - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} | |||||
| - data-id: application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} | |||||
| group: DEFAULT_GROUP | |||||
| refresh: true | |||||
| - data-id: ${spring.application.name}-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} | |||||
| group: DEFAULT_GROUP | |||||
| refresh: true | |||||
| @@ -1,22 +1,5 @@ | |||||
| package com.ruoyi.system.controller; | package com.ruoyi.system.controller; | ||||
| import java.io.IOException; | |||||
| import java.util.List; | |||||
| import java.util.Set; | |||||
| import java.util.stream.Collectors; | |||||
| import javax.servlet.http.HttpServletResponse; | |||||
| import org.apache.commons.lang3.ArrayUtils; | |||||
| import org.springframework.beans.factory.annotation.Autowired; | |||||
| import org.springframework.validation.annotation.Validated; | |||||
| import org.springframework.web.bind.annotation.DeleteMapping; | |||||
| import org.springframework.web.bind.annotation.GetMapping; | |||||
| import org.springframework.web.bind.annotation.PathVariable; | |||||
| import org.springframework.web.bind.annotation.PostMapping; | |||||
| import org.springframework.web.bind.annotation.PutMapping; | |||||
| import org.springframework.web.bind.annotation.RequestBody; | |||||
| import org.springframework.web.bind.annotation.RequestMapping; | |||||
| import org.springframework.web.bind.annotation.RestController; | |||||
| import org.springframework.web.multipart.MultipartFile; | |||||
| import com.ruoyi.common.core.domain.R; | import com.ruoyi.common.core.domain.R; | ||||
| import com.ruoyi.common.core.utils.StringUtils; | import com.ruoyi.common.core.utils.StringUtils; | ||||
| import com.ruoyi.common.core.utils.poi.ExcelUtil; | import com.ruoyi.common.core.utils.poi.ExcelUtil; | ||||
| @@ -32,22 +15,27 @@ import com.ruoyi.system.api.domain.SysDept; | |||||
| import com.ruoyi.system.api.domain.SysRole; | import com.ruoyi.system.api.domain.SysRole; | ||||
| import com.ruoyi.system.api.domain.SysUser; | import com.ruoyi.system.api.domain.SysUser; | ||||
| import com.ruoyi.system.api.model.LoginUser; | import com.ruoyi.system.api.model.LoginUser; | ||||
| import com.ruoyi.system.service.ISysConfigService; | |||||
| import com.ruoyi.system.service.ISysDeptService; | |||||
| import com.ruoyi.system.service.ISysPermissionService; | |||||
| import com.ruoyi.system.service.ISysPostService; | |||||
| import com.ruoyi.system.service.ISysRoleService; | |||||
| import com.ruoyi.system.service.ISysUserService; | |||||
| import com.ruoyi.system.service.*; | |||||
| import org.apache.commons.lang3.ArrayUtils; | |||||
| import org.springframework.beans.factory.annotation.Autowired; | |||||
| import org.springframework.validation.annotation.Validated; | |||||
| import org.springframework.web.bind.annotation.*; | |||||
| import org.springframework.web.multipart.MultipartFile; | |||||
| import javax.servlet.http.HttpServletResponse; | |||||
| import java.io.IOException; | |||||
| import java.util.List; | |||||
| import java.util.Set; | |||||
| import java.util.stream.Collectors; | |||||
| /** | /** | ||||
| * 用户信息 | * 用户信息 | ||||
| * | |||||
| * | |||||
| * @author ruoyi | * @author ruoyi | ||||
| */ | */ | ||||
| @RestController | @RestController | ||||
| @RequestMapping("/user") | @RequestMapping("/user") | ||||
| public class SysUserController extends BaseController | |||||
| { | |||||
| public class SysUserController extends BaseController { | |||||
| @Autowired | @Autowired | ||||
| private ISysUserService userService; | private ISysUserService userService; | ||||
| @@ -71,8 +59,7 @@ public class SysUserController extends BaseController | |||||
| */ | */ | ||||
| @RequiresPermissions("system:user:list") | @RequiresPermissions("system:user:list") | ||||
| @GetMapping("/list") | @GetMapping("/list") | ||||
| public TableDataInfo list(SysUser user) | |||||
| { | |||||
| public TableDataInfo list(SysUser user) { | |||||
| startPage(); | startPage(); | ||||
| List<SysUser> list = userService.selectUserList(user); | List<SysUser> list = userService.selectUserList(user); | ||||
| return getDataTable(list); | return getDataTable(list); | ||||
| @@ -81,8 +68,7 @@ public class SysUserController extends BaseController | |||||
| @Log(title = "用户管理", businessType = BusinessType.EXPORT) | @Log(title = "用户管理", businessType = BusinessType.EXPORT) | ||||
| @RequiresPermissions("system:user:export") | @RequiresPermissions("system:user:export") | ||||
| @PostMapping("/export") | @PostMapping("/export") | ||||
| public void export(HttpServletResponse response, SysUser user) | |||||
| { | |||||
| public void export(HttpServletResponse response, SysUser user) { | |||||
| List<SysUser> list = userService.selectUserList(user); | List<SysUser> list = userService.selectUserList(user); | ||||
| ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class); | ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class); | ||||
| util.exportExcel(response, list, "用户数据"); | util.exportExcel(response, list, "用户数据"); | ||||
| @@ -91,8 +77,7 @@ public class SysUserController extends BaseController | |||||
| @Log(title = "用户管理", businessType = BusinessType.IMPORT) | @Log(title = "用户管理", businessType = BusinessType.IMPORT) | ||||
| @RequiresPermissions("system:user:import") | @RequiresPermissions("system:user:import") | ||||
| @PostMapping("/importData") | @PostMapping("/importData") | ||||
| public AjaxResult importData(MultipartFile file, boolean updateSupport) throws Exception | |||||
| { | |||||
| public AjaxResult importData(MultipartFile file, boolean updateSupport) throws Exception { | |||||
| ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class); | ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class); | ||||
| List<SysUser> userList = util.importExcel(file.getInputStream()); | List<SysUser> userList = util.importExcel(file.getInputStream()); | ||||
| String operName = SecurityUtils.getUsername(); | String operName = SecurityUtils.getUsername(); | ||||
| @@ -101,8 +86,7 @@ public class SysUserController extends BaseController | |||||
| } | } | ||||
| @PostMapping("/importTemplate") | @PostMapping("/importTemplate") | ||||
| public void importTemplate(HttpServletResponse response) throws IOException | |||||
| { | |||||
| public void importTemplate(HttpServletResponse response) throws IOException { | |||||
| ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class); | ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class); | ||||
| util.importTemplateExcel(response, "用户数据"); | util.importTemplateExcel(response, "用户数据"); | ||||
| } | } | ||||
| @@ -112,11 +96,9 @@ public class SysUserController extends BaseController | |||||
| */ | */ | ||||
| @InnerAuth | @InnerAuth | ||||
| @GetMapping("/info/{username}") | @GetMapping("/info/{username}") | ||||
| public R<LoginUser> info(@PathVariable("username") String username) | |||||
| { | |||||
| public R<LoginUser> info(@PathVariable("username") String username) { | |||||
| SysUser sysUser = userService.selectUserByUserName(username); | SysUser sysUser = userService.selectUserByUserName(username); | ||||
| if (StringUtils.isNull(sysUser)) | |||||
| { | |||||
| if (StringUtils.isNull(sysUser)) { | |||||
| return R.fail("用户名或密码错误"); | return R.fail("用户名或密码错误"); | ||||
| } | } | ||||
| // 角色集合 | // 角色集合 | ||||
| @@ -135,15 +117,12 @@ public class SysUserController extends BaseController | |||||
| */ | */ | ||||
| @InnerAuth | @InnerAuth | ||||
| @PostMapping("/register") | @PostMapping("/register") | ||||
| public R<Boolean> register(@RequestBody SysUser sysUser) | |||||
| { | |||||
| public R<Boolean> register(@RequestBody SysUser sysUser) { | |||||
| String username = sysUser.getUserName(); | String username = sysUser.getUserName(); | ||||
| if (!("true".equals(configService.selectConfigByKey("sys.account.registerUser")))) | |||||
| { | |||||
| if (!("true".equals(configService.selectConfigByKey("sys.account.registerUser")))) { | |||||
| return R.fail("当前系统没有开启注册功能!"); | return R.fail("当前系统没有开启注册功能!"); | ||||
| } | } | ||||
| if (!userService.checkUserNameUnique(sysUser)) | |||||
| { | |||||
| if (!userService.checkUserNameUnique(sysUser)) { | |||||
| return R.fail("保存用户'" + username + "'失败,注册账号已存在"); | return R.fail("保存用户'" + username + "'失败,注册账号已存在"); | ||||
| } | } | ||||
| return R.ok(userService.registerUser(sysUser)); | return R.ok(userService.registerUser(sysUser)); | ||||
| @@ -151,12 +130,11 @@ public class SysUserController extends BaseController | |||||
| /** | /** | ||||
| * 获取用户信息 | * 获取用户信息 | ||||
| * | |||||
| * | |||||
| * @return 用户信息 | * @return 用户信息 | ||||
| */ | */ | ||||
| @GetMapping("getInfo") | @GetMapping("getInfo") | ||||
| public AjaxResult getInfo() | |||||
| { | |||||
| public AjaxResult getInfo() { | |||||
| SysUser user = userService.selectUserById(SecurityUtils.getUserId()); | SysUser user = userService.selectUserById(SecurityUtils.getUserId()); | ||||
| // 角色集合 | // 角色集合 | ||||
| Set<String> roles = permissionService.getRolePermission(user); | Set<String> roles = permissionService.getRolePermission(user); | ||||
| @@ -173,16 +151,15 @@ public class SysUserController extends BaseController | |||||
| * 根据用户编号获取详细信息 | * 根据用户编号获取详细信息 | ||||
| */ | */ | ||||
| @RequiresPermissions("system:user:query") | @RequiresPermissions("system:user:query") | ||||
| @GetMapping(value = { "/", "/{userId}" }) | |||||
| public AjaxResult getInfo(@PathVariable(value = "userId", required = false) Long userId) | |||||
| { | |||||
| @GetMapping(value = {"/", "/{userId}"}) | |||||
| public AjaxResult getInfo(@PathVariable(value = "userId", required = false) Long userId) { | |||||
| userService.checkUserDataScope(userId); | userService.checkUserDataScope(userId); | ||||
| AjaxResult ajax = AjaxResult.success(); | AjaxResult ajax = AjaxResult.success(); | ||||
| List<SysRole> roles = roleService.selectRoleAll(); | List<SysRole> roles = roleService.selectRoleAll(); | ||||
| ajax.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList())); | |||||
| ajax.put("roles", roles); | |||||
| // ajax.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList())); | |||||
| ajax.put("posts", postService.selectPostAll()); | ajax.put("posts", postService.selectPostAll()); | ||||
| if (StringUtils.isNotNull(userId)) | |||||
| { | |||||
| if (StringUtils.isNotNull(userId)) { | |||||
| SysUser sysUser = userService.selectUserById(userId); | SysUser sysUser = userService.selectUserById(userId); | ||||
| ajax.put(AjaxResult.DATA_TAG, sysUser); | ajax.put(AjaxResult.DATA_TAG, sysUser); | ||||
| ajax.put("postIds", postService.selectPostListByUserId(userId)); | ajax.put("postIds", postService.selectPostListByUserId(userId)); | ||||
| @@ -197,22 +174,19 @@ public class SysUserController extends BaseController | |||||
| @RequiresPermissions("system:user:add") | @RequiresPermissions("system:user:add") | ||||
| @Log(title = "用户管理", businessType = BusinessType.INSERT) | @Log(title = "用户管理", businessType = BusinessType.INSERT) | ||||
| @PostMapping | @PostMapping | ||||
| public AjaxResult add(@Validated @RequestBody SysUser user) | |||||
| { | |||||
| if (!userService.checkUserNameUnique(user)) | |||||
| { | |||||
| public AjaxResult add(@Validated @RequestBody SysUser user) { | |||||
| if (!userService.checkUserNameUnique(user)) { | |||||
| return error("新增用户'" + user.getUserName() + "'失败,登录账号已存在"); | return error("新增用户'" + user.getUserName() + "'失败,登录账号已存在"); | ||||
| } | |||||
| else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user)) | |||||
| { | |||||
| } else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user)) { | |||||
| return error("新增用户'" + user.getUserName() + "'失败,手机号码已存在"); | return error("新增用户'" + user.getUserName() + "'失败,手机号码已存在"); | ||||
| } | |||||
| else if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user)) | |||||
| { | |||||
| } else if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user)) { | |||||
| return error("新增用户'" + user.getUserName() + "'失败,邮箱账号已存在"); | return error("新增用户'" + user.getUserName() + "'失败,邮箱账号已存在"); | ||||
| } else if (StringUtils.isNotEmpty(user.getGitLinkUsername()) && !userService.checktGitLinkUsernameUnique(user)) { | |||||
| return error("新增用户'" + user.getUserName() + "'失败,gitLink用户名已存在"); | |||||
| } | } | ||||
| user.setCreateBy(SecurityUtils.getUsername()); | user.setCreateBy(SecurityUtils.getUsername()); | ||||
| user.setPassword(SecurityUtils.encryptPassword(user.getPassword())); | user.setPassword(SecurityUtils.encryptPassword(user.getPassword())); | ||||
| user.setGitLinkPassword(SecurityUtils.encryptPassword(user.getGitLinkPassword())); | |||||
| return toAjax(userService.insertUser(user)); | return toAjax(userService.insertUser(user)); | ||||
| } | } | ||||
| @@ -222,23 +196,25 @@ public class SysUserController extends BaseController | |||||
| @RequiresPermissions("system:user:edit") | @RequiresPermissions("system:user:edit") | ||||
| @Log(title = "用户管理", businessType = BusinessType.UPDATE) | @Log(title = "用户管理", businessType = BusinessType.UPDATE) | ||||
| @PutMapping | @PutMapping | ||||
| public AjaxResult edit(@Validated @RequestBody SysUser user) | |||||
| { | |||||
| public AjaxResult edit(@Validated @RequestBody SysUser user) { | |||||
| userService.checkUserAllowed(user); | userService.checkUserAllowed(user); | ||||
| userService.checkUserDataScope(user.getUserId()); | userService.checkUserDataScope(user.getUserId()); | ||||
| if (!userService.checkUserNameUnique(user)) | |||||
| { | |||||
| if (!userService.checkUserNameUnique(user)) { | |||||
| return error("修改用户'" + user.getUserName() + "'失败,登录账号已存在"); | return error("修改用户'" + user.getUserName() + "'失败,登录账号已存在"); | ||||
| } | |||||
| else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user)) | |||||
| { | |||||
| } else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user)) { | |||||
| return error("修改用户'" + user.getUserName() + "'失败,手机号码已存在"); | return error("修改用户'" + user.getUserName() + "'失败,手机号码已存在"); | ||||
| } | |||||
| else if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user)) | |||||
| { | |||||
| } else if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user)) { | |||||
| return error("修改用户'" + user.getUserName() + "'失败,邮箱账号已存在"); | return error("修改用户'" + user.getUserName() + "'失败,邮箱账号已存在"); | ||||
| } else if (StringUtils.isNotEmpty(user.getGitLinkUsername()) && !userService.checktGitLinkUsernameUnique(user)) { | |||||
| return error("新增用户'" + user.getUserName() + "'失败,gitLink用户名已存在"); | |||||
| } | } | ||||
| user.setUpdateBy(SecurityUtils.getUsername()); | user.setUpdateBy(SecurityUtils.getUsername()); | ||||
| if(StringUtils.isNotEmpty(user.getPassword())){ | |||||
| user.setPassword(SecurityUtils.encryptPassword(user.getPassword())); | |||||
| } | |||||
| if(StringUtils.isNotEmpty(user.getGitLinkPassword())){ | |||||
| user.setGitLinkPassword(SecurityUtils.encryptPassword(user.getGitLinkPassword())); | |||||
| } | |||||
| return toAjax(userService.updateUser(user)); | return toAjax(userService.updateUser(user)); | ||||
| } | } | ||||
| @@ -248,10 +224,8 @@ public class SysUserController extends BaseController | |||||
| @RequiresPermissions("system:user:remove") | @RequiresPermissions("system:user:remove") | ||||
| @Log(title = "用户管理", businessType = BusinessType.DELETE) | @Log(title = "用户管理", businessType = BusinessType.DELETE) | ||||
| @DeleteMapping("/{userIds}") | @DeleteMapping("/{userIds}") | ||||
| public AjaxResult remove(@PathVariable Long[] userIds) | |||||
| { | |||||
| if (ArrayUtils.contains(userIds, SecurityUtils.getUserId())) | |||||
| { | |||||
| public AjaxResult remove(@PathVariable Long[] userIds) { | |||||
| if (ArrayUtils.contains(userIds, SecurityUtils.getUserId())) { | |||||
| return error("当前用户不能删除"); | return error("当前用户不能删除"); | ||||
| } | } | ||||
| return toAjax(userService.deleteUserByIds(userIds)); | return toAjax(userService.deleteUserByIds(userIds)); | ||||
| @@ -263,8 +237,7 @@ public class SysUserController extends BaseController | |||||
| @RequiresPermissions("system:user:edit") | @RequiresPermissions("system:user:edit") | ||||
| @Log(title = "用户管理", businessType = BusinessType.UPDATE) | @Log(title = "用户管理", businessType = BusinessType.UPDATE) | ||||
| @PutMapping("/resetPwd") | @PutMapping("/resetPwd") | ||||
| public AjaxResult resetPwd(@RequestBody SysUser user) | |||||
| { | |||||
| public AjaxResult resetPwd(@RequestBody SysUser user) { | |||||
| userService.checkUserAllowed(user); | userService.checkUserAllowed(user); | ||||
| userService.checkUserDataScope(user.getUserId()); | userService.checkUserDataScope(user.getUserId()); | ||||
| user.setPassword(SecurityUtils.encryptPassword(user.getPassword())); | user.setPassword(SecurityUtils.encryptPassword(user.getPassword())); | ||||
| @@ -278,8 +251,7 @@ public class SysUserController extends BaseController | |||||
| @RequiresPermissions("system:user:edit") | @RequiresPermissions("system:user:edit") | ||||
| @Log(title = "用户管理", businessType = BusinessType.UPDATE) | @Log(title = "用户管理", businessType = BusinessType.UPDATE) | ||||
| @PutMapping("/changeStatus") | @PutMapping("/changeStatus") | ||||
| public AjaxResult changeStatus(@RequestBody SysUser user) | |||||
| { | |||||
| public AjaxResult changeStatus(@RequestBody SysUser user) { | |||||
| userService.checkUserAllowed(user); | userService.checkUserAllowed(user); | ||||
| userService.checkUserDataScope(user.getUserId()); | userService.checkUserDataScope(user.getUserId()); | ||||
| user.setUpdateBy(SecurityUtils.getUsername()); | user.setUpdateBy(SecurityUtils.getUsername()); | ||||
| @@ -291,8 +263,7 @@ public class SysUserController extends BaseController | |||||
| */ | */ | ||||
| @RequiresPermissions("system:user:query") | @RequiresPermissions("system:user:query") | ||||
| @GetMapping("/authRole/{userId}") | @GetMapping("/authRole/{userId}") | ||||
| public AjaxResult authRole(@PathVariable("userId") Long userId) | |||||
| { | |||||
| public AjaxResult authRole(@PathVariable("userId") Long userId) { | |||||
| AjaxResult ajax = AjaxResult.success(); | AjaxResult ajax = AjaxResult.success(); | ||||
| SysUser user = userService.selectUserById(userId); | SysUser user = userService.selectUserById(userId); | ||||
| List<SysRole> roles = roleService.selectRolesByUserId(userId); | List<SysRole> roles = roleService.selectRolesByUserId(userId); | ||||
| @@ -307,8 +278,7 @@ public class SysUserController extends BaseController | |||||
| @RequiresPermissions("system:user:edit") | @RequiresPermissions("system:user:edit") | ||||
| @Log(title = "用户管理", businessType = BusinessType.GRANT) | @Log(title = "用户管理", businessType = BusinessType.GRANT) | ||||
| @PutMapping("/authRole") | @PutMapping("/authRole") | ||||
| public AjaxResult insertAuthRole(Long userId, Long[] roleIds) | |||||
| { | |||||
| public AjaxResult insertAuthRole(Long userId, Long[] roleIds) { | |||||
| userService.checkUserDataScope(userId); | userService.checkUserDataScope(userId); | ||||
| userService.insertUserAuth(userId, roleIds); | userService.insertUserAuth(userId, roleIds); | ||||
| return success(); | return success(); | ||||
| @@ -319,8 +289,7 @@ public class SysUserController extends BaseController | |||||
| */ | */ | ||||
| @RequiresPermissions("system:user:list") | @RequiresPermissions("system:user:list") | ||||
| @GetMapping("/deptTree") | @GetMapping("/deptTree") | ||||
| public AjaxResult deptTree(SysDept dept) | |||||
| { | |||||
| public AjaxResult deptTree(SysDept dept) { | |||||
| return success(deptService.selectDeptTreeList(dept)); | return success(deptService.selectDeptTreeList(dept)); | ||||
| } | } | ||||
| } | } | ||||
| @@ -124,4 +124,6 @@ public interface SysUserMapper | |||||
| * @return 结果 | * @return 结果 | ||||
| */ | */ | ||||
| public SysUser checkEmailUnique(String email); | public SysUser checkEmailUnique(String email); | ||||
| public SysUser checktGitLinkUsernameUnique(String gitLinkUsername); | |||||
| } | } | ||||
| @@ -90,6 +90,8 @@ public interface ISysUserService | |||||
| */ | */ | ||||
| public boolean checkEmailUnique(SysUser user); | public boolean checkEmailUnique(SysUser user); | ||||
| public boolean checktGitLinkUsernameUnique(SysUser user); | |||||
| /** | /** | ||||
| * 校验用户是否允许操作 | * 校验用户是否允许操作 | ||||
| * | * | ||||
| @@ -212,6 +212,17 @@ public class SysUserServiceImpl implements ISysUserService | |||||
| return UserConstants.UNIQUE; | return UserConstants.UNIQUE; | ||||
| } | } | ||||
| @Override | |||||
| public boolean checktGitLinkUsernameUnique(SysUser user) { | |||||
| Long userId = StringUtils.isNull(user.getUserId()) ? -1L : user.getUserId(); | |||||
| SysUser info = userMapper.checktGitLinkUsernameUnique(user.getGitLinkUsername()); | |||||
| if(StringUtils.isNotNull(info) && info.getUserId().longValue() != userId.longValue()) | |||||
| { | |||||
| return UserConstants.NOT_UNIQUE; | |||||
| } | |||||
| return UserConstants.UNIQUE; | |||||
| } | |||||
| /** | /** | ||||
| * 校验用户是否允许操作 | * 校验用户是否允许操作 | ||||
| * | * | ||||
| @@ -15,6 +15,10 @@ spring: | |||||
| discovery: | discovery: | ||||
| # 服务注册地址 | # 服务注册地址 | ||||
| server-addr: nacos-ci4s.ci4s-test.svc:8848 | server-addr: nacos-ci4s.ci4s-test.svc:8848 | ||||
| username: nacos | |||||
| password: nacos | |||||
| retry: | |||||
| enabled: true | |||||
| config: | config: | ||||
| # 配置中心地址 | # 配置中心地址 | ||||
| server-addr: nacos-ci4s.ci4s-test.svc:8848 | server-addr: nacos-ci4s.ci4s-test.svc:8848 | ||||
| @@ -22,4 +26,6 @@ spring: | |||||
| file-extension: yml | file-extension: yml | ||||
| # 共享配置 | # 共享配置 | ||||
| shared-configs: | shared-configs: | ||||
| - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} | |||||
| - data-id: application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} | |||||
| group: DEFAULT_GROUP | |||||
| refresh: true | |||||
| @@ -1,221 +1,286 @@ | |||||
| <?xml version="1.0" encoding="UTF-8" ?> | <?xml version="1.0" encoding="UTF-8" ?> | ||||
| <!DOCTYPE mapper | <!DOCTYPE mapper | ||||
| PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" | |||||
| "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> | |||||
| PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" | |||||
| "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> | |||||
| <mapper namespace="com.ruoyi.system.mapper.SysUserMapper"> | <mapper namespace="com.ruoyi.system.mapper.SysUserMapper"> | ||||
| <resultMap type="SysUser" id="SysUserResult"> | <resultMap type="SysUser" id="SysUserResult"> | ||||
| <id property="userId" column="user_id" /> | |||||
| <result property="deptId" column="dept_id" /> | |||||
| <result property="userName" column="user_name" /> | |||||
| <result property="nickName" column="nick_name" /> | |||||
| <result property="email" column="email" /> | |||||
| <result property="phonenumber" column="phonenumber" /> | |||||
| <result property="sex" column="sex" /> | |||||
| <result property="avatar" column="avatar" /> | |||||
| <result property="password" column="password" /> | |||||
| <result property="status" column="status" /> | |||||
| <result property="delFlag" column="del_flag" /> | |||||
| <result property="loginIp" column="login_ip" /> | |||||
| <result property="loginDate" column="login_date" /> | |||||
| <result property="createBy" column="create_by" /> | |||||
| <result property="createTime" column="create_time" /> | |||||
| <result property="updateBy" column="update_by" /> | |||||
| <result property="updateTime" column="update_time" /> | |||||
| <result property="remark" column="remark" /> | |||||
| <association property="dept" javaType="SysDept" resultMap="deptResult" /> | |||||
| <collection property="roles" javaType="java.util.List" resultMap="RoleResult" /> | |||||
| <id property="userId" column="user_id"/> | |||||
| <result property="deptId" column="dept_id"/> | |||||
| <result property="userName" column="user_name"/> | |||||
| <result property="nickName" column="nick_name"/> | |||||
| <result property="email" column="email"/> | |||||
| <result property="phonenumber" column="phonenumber"/> | |||||
| <result property="sex" column="sex"/> | |||||
| <result property="avatar" column="avatar"/> | |||||
| <result property="password" column="password"/> | |||||
| <result property="status" column="status"/> | |||||
| <result property="delFlag" column="del_flag"/> | |||||
| <result property="loginIp" column="login_ip"/> | |||||
| <result property="loginDate" column="login_date"/> | |||||
| <result property="createBy" column="create_by"/> | |||||
| <result property="createTime" column="create_time"/> | |||||
| <result property="updateBy" column="update_by"/> | |||||
| <result property="updateTime" column="update_time"/> | |||||
| <result property="remark" column="remark"/> | |||||
| <result property="gitLinkUsername" column="git_link_username"/> | |||||
| <result property="gitLinkPassword" column="git_link_password"/> | |||||
| <association property="dept" javaType="SysDept" resultMap="deptResult"/> | |||||
| <collection property="roles" javaType="java.util.List" resultMap="RoleResult"/> | |||||
| </resultMap> | </resultMap> | ||||
| <resultMap id="deptResult" type="SysDept"> | <resultMap id="deptResult" type="SysDept"> | ||||
| <id property="deptId" column="dept_id" /> | |||||
| <result property="parentId" column="parent_id" /> | |||||
| <result property="deptName" column="dept_name" /> | |||||
| <result property="ancestors" column="ancestors" /> | |||||
| <result property="orderNum" column="order_num" /> | |||||
| <result property="leader" column="leader" /> | |||||
| <result property="status" column="dept_status" /> | |||||
| <id property="deptId" column="dept_id"/> | |||||
| <result property="parentId" column="parent_id"/> | |||||
| <result property="deptName" column="dept_name"/> | |||||
| <result property="ancestors" column="ancestors"/> | |||||
| <result property="orderNum" column="order_num"/> | |||||
| <result property="leader" column="leader"/> | |||||
| <result property="status" column="dept_status"/> | |||||
| </resultMap> | </resultMap> | ||||
| <resultMap id="RoleResult" type="SysRole"> | <resultMap id="RoleResult" type="SysRole"> | ||||
| <id property="roleId" column="role_id" /> | |||||
| <result property="roleName" column="role_name" /> | |||||
| <result property="roleKey" column="role_key" /> | |||||
| <result property="roleSort" column="role_sort" /> | |||||
| <result property="dataScope" column="data_scope" /> | |||||
| <result property="status" column="role_status" /> | |||||
| <id property="roleId" column="role_id"/> | |||||
| <result property="roleName" column="role_name"/> | |||||
| <result property="roleKey" column="role_key"/> | |||||
| <result property="roleSort" column="role_sort"/> | |||||
| <result property="dataScope" column="data_scope"/> | |||||
| <result property="status" column="role_status"/> | |||||
| </resultMap> | </resultMap> | ||||
| <sql id="selectUserVo"> | |||||
| select u.user_id, u.dept_id, u.user_name, u.nick_name, u.email, u.avatar, u.phonenumber, u.password, u.sex, u.status, u.del_flag, u.login_ip, u.login_date, u.create_by, u.create_time, u.remark, | |||||
| d.dept_id, d.parent_id, d.ancestors, d.dept_name, d.order_num, d.leader, d.status as dept_status, | |||||
| r.role_id, r.role_name, r.role_key, r.role_sort, r.data_scope, r.status as role_status | |||||
| <sql id="selectUserVo"> | |||||
| select u.user_id, | |||||
| u.dept_id, | |||||
| u.user_name, | |||||
| u.nick_name, | |||||
| u.email, | |||||
| u.avatar, | |||||
| u.phonenumber, | |||||
| u.password, | |||||
| u.git_link_username, | |||||
| u.git_link_password, | |||||
| u.sex, | |||||
| u.status, | |||||
| u.del_flag, | |||||
| u.login_ip, | |||||
| u.login_date, | |||||
| u.create_by, | |||||
| u.create_time, | |||||
| u.remark, | |||||
| d.dept_id, | |||||
| d.parent_id, | |||||
| d.ancestors, | |||||
| d.dept_name, | |||||
| d.order_num, | |||||
| d.leader, | |||||
| d.status as dept_status, | |||||
| r.role_id, | |||||
| r.role_name, | |||||
| r.role_key, | |||||
| r.role_sort, | |||||
| r.data_scope, | |||||
| r.status as role_status | |||||
| from sys_user u | from sys_user u | ||||
| left join sys_dept d on u.dept_id = d.dept_id | |||||
| left join sys_user_role ur on u.user_id = ur.user_id | |||||
| left join sys_role r on r.role_id = ur.role_id | |||||
| left join sys_dept d on u.dept_id = d.dept_id | |||||
| left join sys_user_role ur on u.user_id = ur.user_id | |||||
| left join sys_role r on r.role_id = ur.role_id | |||||
| </sql> | </sql> | ||||
| <select id="selectUserList" parameterType="SysUser" resultMap="SysUserResult"> | <select id="selectUserList" parameterType="SysUser" resultMap="SysUserResult"> | ||||
| select u.user_id, u.dept_id, u.nick_name, u.user_name, u.email, u.avatar, u.phonenumber, u.sex, u.status, u.del_flag, u.login_ip, u.login_date, u.create_by, u.create_time, u.remark, d.dept_name, d.leader from sys_user u | |||||
| left join sys_dept d on u.dept_id = d.dept_id | |||||
| where u.del_flag = '0' | |||||
| <if test="userId != null and userId != 0"> | |||||
| AND u.user_id = #{userId} | |||||
| </if> | |||||
| <if test="userName != null and userName != ''"> | |||||
| AND u.user_name like concat('%', #{userName}, '%') | |||||
| </if> | |||||
| <if test="status != null and status != ''"> | |||||
| AND u.status = #{status} | |||||
| </if> | |||||
| <if test="phonenumber != null and phonenumber != ''"> | |||||
| AND u.phonenumber like concat('%', #{phonenumber}, '%') | |||||
| </if> | |||||
| <if test="params.beginTime != null and params.beginTime != ''"><!-- 开始时间检索 --> | |||||
| AND date_format(u.create_time,'%y%m%d') >= date_format(#{params.beginTime},'%y%m%d') | |||||
| </if> | |||||
| <if test="params.endTime != null and params.endTime != ''"><!-- 结束时间检索 --> | |||||
| AND date_format(u.create_time,'%y%m%d') <= date_format(#{params.endTime},'%y%m%d') | |||||
| </if> | |||||
| <if test="deptId != null and deptId != 0"> | |||||
| AND (u.dept_id = #{deptId} OR u.dept_id IN ( SELECT t.dept_id FROM sys_dept t WHERE find_in_set(#{deptId}, ancestors) )) | |||||
| </if> | |||||
| <!-- 数据范围过滤 --> | |||||
| ${params.dataScope} | |||||
| </select> | |||||
| <select id="selectAllocatedList" parameterType="SysUser" resultMap="SysUserResult"> | |||||
| select distinct u.user_id, u.dept_id, u.user_name, u.nick_name, u.email, u.phonenumber, u.status, u.create_time | |||||
| from sys_user u | |||||
| left join sys_dept d on u.dept_id = d.dept_id | |||||
| left join sys_user_role ur on u.user_id = ur.user_id | |||||
| left join sys_role r on r.role_id = ur.role_id | |||||
| where u.del_flag = '0' and r.role_id = #{roleId} | |||||
| <if test="userName != null and userName != ''"> | |||||
| AND u.user_name like concat('%', #{userName}, '%') | |||||
| </if> | |||||
| <if test="phonenumber != null and phonenumber != ''"> | |||||
| AND u.phonenumber like concat('%', #{phonenumber}, '%') | |||||
| </if> | |||||
| <!-- 数据范围过滤 --> | |||||
| ${params.dataScope} | |||||
| </select> | |||||
| <select id="selectUnallocatedList" parameterType="SysUser" resultMap="SysUserResult"> | |||||
| select distinct u.user_id, u.dept_id, u.user_name, u.nick_name, u.email, u.phonenumber, u.status, u.create_time | |||||
| from sys_user u | |||||
| left join sys_dept d on u.dept_id = d.dept_id | |||||
| left join sys_user_role ur on u.user_id = ur.user_id | |||||
| left join sys_role r on r.role_id = ur.role_id | |||||
| where u.del_flag = '0' and (r.role_id != #{roleId} or r.role_id IS NULL) | |||||
| and u.user_id not in (select u.user_id from sys_user u inner join sys_user_role ur on u.user_id = ur.user_id and ur.role_id = #{roleId}) | |||||
| <if test="userName != null and userName != ''"> | |||||
| AND u.user_name like concat('%', #{userName}, '%') | |||||
| </if> | |||||
| <if test="phonenumber != null and phonenumber != ''"> | |||||
| AND u.phonenumber like concat('%', #{phonenumber}, '%') | |||||
| </if> | |||||
| <!-- 数据范围过滤 --> | |||||
| ${params.dataScope} | |||||
| </select> | |||||
| <select id="selectUserByUserName" parameterType="String" resultMap="SysUserResult"> | |||||
| <include refid="selectUserVo"/> | |||||
| where u.user_name = #{userName} and u.del_flag = '0' | |||||
| </select> | |||||
| <select id="selectUserById" parameterType="Long" resultMap="SysUserResult"> | |||||
| <include refid="selectUserVo"/> | |||||
| where u.user_id = #{userId} | |||||
| </select> | |||||
| <select id="checkUserNameUnique" parameterType="String" resultMap="SysUserResult"> | |||||
| select user_id, user_name from sys_user where user_name = #{userName} and del_flag = '0' limit 1 | |||||
| </select> | |||||
| <select id="checkPhoneUnique" parameterType="String" resultMap="SysUserResult"> | |||||
| select user_id, phonenumber from sys_user where phonenumber = #{phonenumber} and del_flag = '0' limit 1 | |||||
| </select> | |||||
| <select id="checkEmailUnique" parameterType="String" resultMap="SysUserResult"> | |||||
| select user_id, email from sys_user where email = #{email} and del_flag = '0' limit 1 | |||||
| </select> | |||||
| <insert id="insertUser" parameterType="SysUser" useGeneratedKeys="true" keyProperty="userId"> | |||||
| insert into sys_user( | |||||
| <if test="userId != null and userId != 0">user_id,</if> | |||||
| <if test="deptId != null and deptId != 0">dept_id,</if> | |||||
| <if test="userName != null and userName != ''">user_name,</if> | |||||
| <if test="nickName != null and nickName != ''">nick_name,</if> | |||||
| <if test="email != null and email != ''">email,</if> | |||||
| <if test="avatar != null and avatar != ''">avatar,</if> | |||||
| <if test="phonenumber != null and phonenumber != ''">phonenumber,</if> | |||||
| <if test="sex != null and sex != ''">sex,</if> | |||||
| <if test="password != null and password != ''">password,</if> | |||||
| <if test="status != null and status != ''">status,</if> | |||||
| <if test="createBy != null and createBy != ''">create_by,</if> | |||||
| <if test="remark != null and remark != ''">remark,</if> | |||||
| create_time | |||||
| )values( | |||||
| <if test="userId != null and userId != ''">#{userId},</if> | |||||
| <if test="deptId != null and deptId != ''">#{deptId},</if> | |||||
| <if test="userName != null and userName != ''">#{userName},</if> | |||||
| <if test="nickName != null and nickName != ''">#{nickName},</if> | |||||
| <if test="email != null and email != ''">#{email},</if> | |||||
| <if test="avatar != null and avatar != ''">#{avatar},</if> | |||||
| <if test="phonenumber != null and phonenumber != ''">#{phonenumber},</if> | |||||
| <if test="sex != null and sex != ''">#{sex},</if> | |||||
| <if test="password != null and password != ''">#{password},</if> | |||||
| <if test="status != null and status != ''">#{status},</if> | |||||
| <if test="createBy != null and createBy != ''">#{createBy},</if> | |||||
| <if test="remark != null and remark != ''">#{remark},</if> | |||||
| sysdate() | |||||
| ) | |||||
| </insert> | |||||
| <update id="updateUser" parameterType="SysUser"> | |||||
| update sys_user | |||||
| <set> | |||||
| <if test="deptId != null and deptId != 0">dept_id = #{deptId},</if> | |||||
| <if test="userName != null and userName != ''">user_name = #{userName},</if> | |||||
| <if test="nickName != null and nickName != ''">nick_name = #{nickName},</if> | |||||
| <if test="email != null ">email = #{email},</if> | |||||
| <if test="phonenumber != null ">phonenumber = #{phonenumber},</if> | |||||
| <if test="sex != null and sex != ''">sex = #{sex},</if> | |||||
| <if test="avatar != null and avatar != ''">avatar = #{avatar},</if> | |||||
| <if test="password != null and password != ''">password = #{password},</if> | |||||
| <if test="status != null and status != ''">status = #{status},</if> | |||||
| <if test="loginIp != null and loginIp != ''">login_ip = #{loginIp},</if> | |||||
| <if test="loginDate != null">login_date = #{loginDate},</if> | |||||
| <if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if> | |||||
| <if test="remark != null">remark = #{remark},</if> | |||||
| update_time = sysdate() | |||||
| </set> | |||||
| where user_id = #{userId} | |||||
| </update> | |||||
| <update id="updateUserStatus" parameterType="SysUser"> | |||||
| update sys_user set status = #{status} where user_id = #{userId} | |||||
| </update> | |||||
| <update id="updateUserAvatar" parameterType="SysUser"> | |||||
| update sys_user set avatar = #{avatar} where user_name = #{userName} | |||||
| </update> | |||||
| <update id="resetUserPwd" parameterType="SysUser"> | |||||
| update sys_user set password = #{password} where user_name = #{userName} | |||||
| </update> | |||||
| <delete id="deleteUserById" parameterType="Long"> | |||||
| update sys_user set del_flag = '2' where user_id = #{userId} | |||||
| </delete> | |||||
| <delete id="deleteUserByIds" parameterType="Long"> | |||||
| update sys_user set del_flag = '2' where user_id in | |||||
| <foreach collection="array" item="userId" open="(" separator="," close=")"> | |||||
| #{userId} | |||||
| </foreach> | |||||
| </delete> | |||||
| select u.user_id, u.dept_id, u.nick_name, u.user_name, u.email, u.avatar, u.phonenumber, u.sex, u.status, | |||||
| u.git_link_username, | |||||
| u.del_flag, u.login_ip, u.login_date, u.create_by, u.create_time, u.remark, d.dept_name, d.leader | |||||
| from sys_user u | |||||
| left join sys_dept d on u.dept_id = d.dept_id | |||||
| where u.del_flag = '0' | |||||
| <if test="userId != null and userId != 0"> | |||||
| AND u.user_id = #{userId} | |||||
| </if> | |||||
| <if test="userName != null and userName != ''"> | |||||
| AND u.user_name like concat('%', #{userName}, '%') | |||||
| </if> | |||||
| <if test="status != null and status != ''"> | |||||
| AND u.status = #{status} | |||||
| </if> | |||||
| <if test="phonenumber != null and phonenumber != ''"> | |||||
| AND u.phonenumber like concat('%', #{phonenumber}, '%') | |||||
| </if> | |||||
| <if test="params.beginTime != null and params.beginTime != ''"><!-- 开始时间检索 --> | |||||
| AND date_format(u.create_time,'%y%m%d') >= date_format(#{params.beginTime},'%y%m%d') | |||||
| </if> | |||||
| <if test="params.endTime != null and params.endTime != ''"><!-- 结束时间检索 --> | |||||
| AND date_format(u.create_time,'%y%m%d') <= date_format(#{params.endTime},'%y%m%d') | |||||
| </if> | |||||
| <if test="deptId != null and deptId != 0"> | |||||
| AND (u.dept_id = #{deptId} OR u.dept_id IN ( SELECT t.dept_id FROM sys_dept t WHERE find_in_set(#{deptId}, | |||||
| ancestors) )) | |||||
| </if> | |||||
| <!-- 数据范围过滤 --> | |||||
| ${params.dataScope} | |||||
| </select> | |||||
| <select id="selectAllocatedList" parameterType="SysUser" resultMap="SysUserResult"> | |||||
| select distinct u.user_id, u.dept_id, u.user_name, u.nick_name, u.email, u.phonenumber, u.status, u.create_time, u.git_link_username | |||||
| from sys_user u | |||||
| left join sys_dept d on u.dept_id = d.dept_id | |||||
| left join sys_user_role ur on u.user_id = ur.user_id | |||||
| left join sys_role r on r.role_id = ur.role_id | |||||
| where u.del_flag = '0' and r.role_id = #{roleId} | |||||
| <if test="userName != null and userName != ''"> | |||||
| AND u.user_name like concat('%', #{userName}, '%') | |||||
| </if> | |||||
| <if test="phonenumber != null and phonenumber != ''"> | |||||
| AND u.phonenumber like concat('%', #{phonenumber}, '%') | |||||
| </if> | |||||
| <!-- 数据范围过滤 --> | |||||
| ${params.dataScope} | |||||
| </select> | |||||
| <select id="selectUnallocatedList" parameterType="SysUser" resultMap="SysUserResult"> | |||||
| select distinct u.user_id, u.dept_id, u.user_name, u.nick_name, u.email, u.phonenumber, u.status, u.create_time ,u.git_link_username | |||||
| from sys_user u | |||||
| left join sys_dept d on u.dept_id = d.dept_id | |||||
| left join sys_user_role ur on u.user_id = ur.user_id | |||||
| left join sys_role r on r.role_id = ur.role_id | |||||
| where u.del_flag = '0' and (r.role_id != #{roleId} or r.role_id IS NULL) | |||||
| and u.user_id not in (select u.user_id from sys_user u inner join sys_user_role ur on u.user_id = ur.user_id and | |||||
| ur.role_id = #{roleId}) | |||||
| <if test="userName != null and userName != ''"> | |||||
| AND u.user_name like concat('%', #{userName}, '%') | |||||
| </if> | |||||
| <if test="phonenumber != null and phonenumber != ''"> | |||||
| AND u.phonenumber like concat('%', #{phonenumber}, '%') | |||||
| </if> | |||||
| <!-- 数据范围过滤 --> | |||||
| ${params.dataScope} | |||||
| </select> | |||||
| <select id="selectUserByUserName" parameterType="String" resultMap="SysUserResult"> | |||||
| <include refid="selectUserVo"/> | |||||
| where u.user_name = #{userName} and u.del_flag = '0' | |||||
| </select> | |||||
| <select id="selectUserById" parameterType="Long" resultMap="SysUserResult"> | |||||
| <include refid="selectUserVo"/> | |||||
| where u.user_id = #{userId} | |||||
| </select> | |||||
| <select id="checkUserNameUnique" parameterType="String" resultMap="SysUserResult"> | |||||
| select user_id, user_name | |||||
| from sys_user | |||||
| where user_name = #{userName} | |||||
| and del_flag = '0' limit 1 | |||||
| </select> | |||||
| <select id="checkPhoneUnique" parameterType="String" resultMap="SysUserResult"> | |||||
| select user_id, phonenumber | |||||
| from sys_user | |||||
| where phonenumber = #{phonenumber} | |||||
| and del_flag = '0' limit 1 | |||||
| </select> | |||||
| <select id="checkEmailUnique" parameterType="String" resultMap="SysUserResult"> | |||||
| select user_id, email | |||||
| from sys_user | |||||
| where email = #{email} | |||||
| and del_flag = '0' limit 1 | |||||
| </select> | |||||
| <select id="checktGitLinkUsernameUnique" resultType="com.ruoyi.system.api.domain.SysUser"> | |||||
| select user_id, git_link_username | |||||
| from sys_user | |||||
| where git_link_username = #{gitLinkUsername} | |||||
| and del_flag = '0' limit 1 | |||||
| </select> | |||||
| <insert id="insertUser" parameterType="SysUser" useGeneratedKeys="true" keyProperty="userId"> | |||||
| insert into sys_user( | |||||
| <if test="userId != null and userId != 0">user_id,</if> | |||||
| <if test="deptId != null and deptId != 0">dept_id,</if> | |||||
| <if test="userName != null and userName != ''">user_name,</if> | |||||
| <if test="nickName != null and nickName != ''">nick_name,</if> | |||||
| <if test="email != null and email != ''">email,</if> | |||||
| <if test="avatar != null and avatar != ''">avatar,</if> | |||||
| <if test="phonenumber != null and phonenumber != ''">phonenumber,</if> | |||||
| <if test="sex != null and sex != ''">sex,</if> | |||||
| <if test="password != null and password != ''">password,</if> | |||||
| <if test="status != null and status != ''">status,</if> | |||||
| <if test="createBy != null and createBy != ''">create_by,</if> | |||||
| <if test="remark != null and remark != ''">remark,</if> | |||||
| <if test="remark != null and remark != ''">git_link_username,</if> | |||||
| <if test="remark != null and remark != ''">git_link_password,</if> | |||||
| create_time | |||||
| )values( | |||||
| <if test="userId != null and userId != ''">#{userId},</if> | |||||
| <if test="deptId != null and deptId != ''">#{deptId},</if> | |||||
| <if test="userName != null and userName != ''">#{userName},</if> | |||||
| <if test="nickName != null and nickName != ''">#{nickName},</if> | |||||
| <if test="email != null and email != ''">#{email},</if> | |||||
| <if test="avatar != null and avatar != ''">#{avatar},</if> | |||||
| <if test="phonenumber != null and phonenumber != ''">#{phonenumber},</if> | |||||
| <if test="sex != null and sex != ''">#{sex},</if> | |||||
| <if test="password != null and password != ''">#{password},</if> | |||||
| <if test="status != null and status != ''">#{status},</if> | |||||
| <if test="createBy != null and createBy != ''">#{createBy},</if> | |||||
| <if test="remark != null and remark != ''">#{remark},</if> | |||||
| <if test="gitLinkUsername != null and gitLinkUsername != ''">#{gitLinkUsername},</if> | |||||
| <if test="gitLinkPassword != null and gitLinkPassword != ''">#{gitLinkPassword},</if> | |||||
| sysdate() | |||||
| ) | |||||
| </insert> | |||||
| <update id="updateUser" parameterType="SysUser"> | |||||
| update sys_user | |||||
| <set> | |||||
| <if test="deptId != null and deptId != 0">dept_id = #{deptId},</if> | |||||
| <if test="userName != null and userName != ''">user_name = #{userName},</if> | |||||
| <if test="nickName != null and nickName != ''">nick_name = #{nickName},</if> | |||||
| <if test="email != null ">email = #{email},</if> | |||||
| <if test="phonenumber != null ">phonenumber = #{phonenumber},</if> | |||||
| <if test="sex != null and sex != ''">sex = #{sex},</if> | |||||
| <if test="avatar != null and avatar != ''">avatar = #{avatar},</if> | |||||
| <if test="password != null and password != ''">password = #{password},</if> | |||||
| <if test="status != null and status != ''">status = #{status},</if> | |||||
| <if test="loginIp != null and loginIp != ''">login_ip = #{loginIp},</if> | |||||
| <if test="loginDate != null">login_date = #{loginDate},</if> | |||||
| <if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if> | |||||
| <if test="remark != null">remark = #{remark},</if> | |||||
| <if test="gitLinkUsername != null and gitLinkUsername != ''">git_link_username = #{gitLinkUsername},</if> | |||||
| <if test="gitLinkPassword != null and gitLinkPassword != ''">git_link_password = #{gitLinkPassword},</if> | |||||
| update_time = sysdate() | |||||
| </set> | |||||
| where user_id = #{userId} | |||||
| </update> | |||||
| <update id="updateUserStatus" parameterType="SysUser"> | |||||
| update sys_user | |||||
| set status = #{status} | |||||
| where user_id = #{userId} | |||||
| </update> | |||||
| <update id="updateUserAvatar" parameterType="SysUser"> | |||||
| update sys_user | |||||
| set avatar = #{avatar} | |||||
| where user_name = #{userName} | |||||
| </update> | |||||
| <update id="resetUserPwd" parameterType="SysUser"> | |||||
| update sys_user | |||||
| set password = #{password} | |||||
| where user_name = #{userName} | |||||
| </update> | |||||
| <delete id="deleteUserById" parameterType="Long"> | |||||
| update sys_user | |||||
| set del_flag = '2' | |||||
| where user_id = #{userId} | |||||
| </delete> | |||||
| <delete id="deleteUserByIds" parameterType="Long"> | |||||
| update sys_user set del_flag = '2' where user_id in | |||||
| <foreach collection="array" item="userId" open="(" separator="," close=")"> | |||||
| #{userId} | |||||
| </foreach> | |||||
| </delete> | |||||
| </mapper> | </mapper> | ||||
| @@ -15,6 +15,10 @@ spring: | |||||
| discovery: | discovery: | ||||
| # 服务注册地址 | # 服务注册地址 | ||||
| server-addr: nacos-ci4s.ci4s-test.svc:8848 | server-addr: nacos-ci4s.ci4s-test.svc:8848 | ||||
| username: nacos | |||||
| password: nacos | |||||
| retry: | |||||
| enabled: true | |||||
| config: | config: | ||||
| # 配置中心地址 | # 配置中心地址 | ||||
| server-addr: nacos-ci4s.ci4s-test.svc:8848 | server-addr: nacos-ci4s.ci4s-test.svc:8848 | ||||
| @@ -22,4 +26,6 @@ spring: | |||||
| file-extension: yml | file-extension: yml | ||||
| # 共享配置 | # 共享配置 | ||||
| shared-configs: | shared-configs: | ||||
| - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} | |||||
| - data-id: application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} | |||||
| group: DEFAULT_GROUP | |||||
| refresh: true | |||||