#624 合并release4.2.3

Merged
yangxzh1 merged 21 commits from openioctopus/octopus:master into master 1 year ago
  1. +1
    -1
      admin-portal/src/api/userManager.js
  2. +1
    -0
      admin-portal/src/styles/index.scss
  3. +3
    -2
      admin-portal/src/views/resourceManager/components/ResourceSpec.vue
  4. +1
    -1
      admin-portal/src/views/traningManager/components/taskProfile.vue
  5. +81
    -49
      admin-portal/src/views/userManager/components/addDialog.vue
  6. +92
    -36
      admin-portal/src/views/userManager/components/operateDialog.vue
  7. +35
    -16
      admin-portal/src/views/userManager/user.vue
  8. +0
    -3
      openai-portal/src/directives.js
  9. +2
    -1
      openai-portal/src/layout/components/Navbar.vue
  10. +1
    -0
      openai-portal/src/styles/index.scss
  11. +126
    -61
      openai-portal/src/views/Home/register.vue
  12. +10
    -13
      openai-portal/src/views/trainingManager/components/detailDialog/taskProfile.vue
  13. +2
    -2
      openai-portal/vue.config.js
  14. +3
    -0
      server/admin-server/api/v1/user.proto
  15. +1
    -1
      server/admin-server/configs/config.yaml
  16. +6
    -3
      server/admin-server/internal/service/user.go
  17. +4
    -0
      server/base-server/api/v1/user.proto
  18. +5
    -5
      server/base-server/configs/config.yaml
  19. +6
    -0
      server/base-server/internal/data/dao/model/user.go
  20. +5
    -4
      server/base-server/internal/data/dao/user.go
  21. +38
    -15
      server/base-server/internal/service/trainjob/train_job.go
  22. +8
    -5
      server/base-server/internal/service/user/user.go

+ 1
- 1
admin-portal/src/api/userManager.js View File

@@ -28,7 +28,7 @@ export function editUser(data) {
return request({
url: `/v1/usermanage/user/${data.id}`,
method: 'put',
data: { fullname: data.fullname, password: data.password, resourcePools: data.resourcePools }
data
})
}
// 冻结账号


+ 1
- 0
admin-portal/src/styles/index.scss View File

@@ -18,6 +18,7 @@ label {
}

html {
min-width: 1200px;
height: 100%;
box-sizing: border-box;
}


+ 3
- 2
admin-portal/src/views/resourceManager/components/ResourceSpec.vue View File

@@ -38,8 +38,8 @@
<el-input v-model="ruleForm.name" />
</el-form-item>
<el-form-item label="机时价格" prop="price">
<el-input-number v-model="ruleForm.price" :min="0" :max="10" label="描述文字" />
<span>价格1~10,仅支持正整数</span>
<el-input-number v-model="ruleForm.price" :min="0" label="描述文字" :precision="0"/>
<span class="red">仅支持正整数</span>
</el-form-item>
<el-form-item label="资源信息" prop="resourceQuantity">
<div v-for="(item, index) in ruleForm.resourceQuantity" :key="index">
@@ -257,4 +257,5 @@
.line {
text-align: center;
}
.red{color:#409EFF;margin-left: 10px;font-weight: 800;}
</style>

+ 1
- 1
admin-portal/src/views/traningManager/components/taskProfile.vue View File

@@ -19,7 +19,7 @@
</el-row>
<el-row>
<el-col :span="12">
<div>选用数据集:<span>{{ data.dataSetName + ":" + data.dataSetVersion }}</span></div>
<div>选用数据集:<span>{{ (data.dataSetName&&data.dataSetVersion)?data.dataSetName + ":" + data.dataSetVersion:'' }}</span></div>
</el-col>
<el-col :span="12">
<div>是否分布式:<span>{{ data.isDistributed?'是':'否' }}</span></div>


+ 81
- 49
admin-portal/src/views/userManager/components/addDialog.vue View File

@@ -12,10 +12,9 @@
<el-form-item v-if="user" label="密码确认" :label-width="formLabelWidth" prop="confirm">
<el-input v-model="ruleForm.confirm" type="password" />
</el-form-item>
<!-- <el-form-item label="验证码" :label-width="formLabelWidth" placeholder="请输入验证码" prop="code" v-if="user">
<el-input v-model="ruleForm.verifyCode" class="verifyCode"></el-input>
<VerificationCode :changeCode.sync='verifyCode'></VerificationCode>
</el-form-item> -->
<el-form-item v-if="user" label="电话" :label-width="formLabelWidth" prop="phone">
<el-input v-model="ruleForm.phone" />
</el-form-item>
<el-form-item v-if="group" label="群组名称" :label-width="formLabelWidth" prop="name">
<el-input v-model.trim="ruleForm.name" />
</el-form-item>
@@ -33,6 +32,9 @@
<el-form-item v-if="user" label="姓名" :label-width="formLabelWidth" prop="fullname">
<el-input v-model.trim="ruleForm.fullname" />
</el-form-item>
<el-form-item label="备注" prop="desc" v-if="user" :label-width="formLabelWidth">
<el-input type="textarea" v-model="ruleForm.desc" maxlength="100" show-word-limit="true"></el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="cancel">取 消</el-button>
@@ -75,18 +77,50 @@
}
callback(new Error("请输入合法的邮箱地址"));
}

var checkPhone = (rule, value, callback) => {
if (value === '') {
callback();
} else {
let reg = /^(13|14|15|17|18|19)[0-9]{9}$/
if (reg.test(value)) {
callback();
}
else {
callback("请输入正确手机号码");
}
}
};
var validatePass = (rule, value, callback) => {
if (value === '') {
callback(new Error('请输入密码'));
} else {
if (this.ruleForm.confirm !== '') {
this.$refs.ruleForm.validateField('confirm');
}
callback();
}
};
var validatePass2 = (rule, value, callback) => {
if (value === '') {
callback(new Error('请再次输入密码'));
} else if (value !== this.ruleForm.password) {
callback(new Error('两次输入密码不一致!'));
} else {
callback();
}
};
return {
fileList: [],
ruleForm: {
fullname: '',
password: '',
confirm: '',

phone: '',
resourcePoolId: '',
name: '',
userIds: [],
email: undefined
email: undefined,
desc: ''
},
CreateFormVisible: true,
user: false,
@@ -103,12 +137,16 @@
],
password: [
{ required: true, message: '请输入密码', trigger: 'blur' },
{ min: 8, message: '密码长度不得少于8位', trigger: 'blur' }
{ min: 8, message: '密码长度不得少于8位', trigger: 'blur' },
{ validator: validatePass, trigger: 'blur' }

],
confirm: [
{ required: true, message: '请再次输入密码', trigger: 'blur' }

{ validator: validatePass2, trigger: 'blur' }
],
phone: [
{ required: false, message: '请输入电话' },
{ validator: checkPhone, trigger: "blur" }
],
name: [
{ required: true, message: '请输入群组名', trigger: 'blur' }
@@ -214,46 +252,40 @@
confirm() {
this.$refs['ruleForm'].validate((valid) => {
if (valid) {
if (this.ruleForm.confirm === this.ruleForm.password) {
if (this.user) {
const data = { fullname: this.ruleForm.fullname, password: this.ruleForm.password, email: this.ruleForm.email, gender: 1 }
createUser(data).then(response => {
if (response.success === true) {
this.$message({
message: '新增用户成功',
type: 'success'
});
this.$emit('confirm', false)
} else {
this.$message({
message: this.getErrorMsg(response.error.subcode),
type: 'warning'
});
}
})
} else if (this.group) {
const data = { name: this.ruleForm.name, resourcePoolId: this.ruleForm.resourcePoolId, userIds: this.ruleForm.userIds }
createGroup(data).then(response => {
if (response.success === true) {
this.$message({
message: '新增群组成功',
type: 'success'
});
this.$emit('confirm', false)
} else {
this.$message({
message: this.getErrorMsg(response.error.subcode),
type: 'warning'
});
}
})
}
} else {
this.$message({
message: '输入密码不一致!',
type: 'warning'
});
if (this.user) {
const data = { fullname: this.ruleForm.fullname, password: this.ruleForm.password, email: this.ruleForm.email, gender: 1, phone: this.ruleForm.phone.toString(), desc: this.ruleForm.desc }
createUser(data).then(response => {
if (response.success === true) {
this.$message({
message: '新增用户成功',
type: 'success'
});
this.$emit('confirm', false)
} else {
this.$message({
message: this.getErrorMsg(response.error.subcode),
type: 'warning'
});
}
})
} else if (this.group) {
const data = { name: this.ruleForm.name, resourcePoolId: this.ruleForm.resourcePoolId, userIds: this.ruleForm.userIds }
createGroup(data).then(response => {
if (response.success === true) {
this.$message({
message: '新增群组成功',
type: 'success'
});
this.$emit('confirm', false)
} else {
this.$message({
message: this.getErrorMsg(response.error.subcode),
type: 'warning'
});
}
})
}

} else {
console.log('error submit!!');
return false;


+ 92
- 36
admin-portal/src/views/userManager/components/operateDialog.vue View File

@@ -1,21 +1,23 @@
<template>
<div>
<el-dialog :title="userType==='user'?'重置密码':'编辑群组信息'" width="35%" :visible.sync="CreateFormVisible"
<el-dialog :title="userType==='user'?'编辑用户信息':'编辑群组信息'" width="35%" :visible.sync="CreateFormVisible"
:before-close="handleDialogClose" :close-on-click-modal="false">
<el-form ref="ruleForm" :model="ruleForm" :rules="rules" label-width="100px" class="demo-ruleForm">
<el-form-item v-if="user" label="用户名称" :label-width="formLabelWidth">
<el-input v-model="ruleForm.fullName" disabled />
</el-form-item>
<el-form-item v-if="user" label="用户新密码" :label-width="formLabelWidth" prop="password">
<el-input v-model="ruleForm.password" />
<el-form-item v-if="user&&password" label="用户新密码" :label-width="formLabelWidth" prop="password">
<el-input v-model="ruleForm.password" type="password" />
</el-form-item>
<el-form-item v-if="user" label="密码确认" :label-width="formLabelWidth" prop="confirm">
<el-input v-model="ruleForm.confirm" />
<el-form-item v-if="user&&password" label="密码确认" :label-width="formLabelWidth" prop="confirm">
<el-input v-model="ruleForm.confirm" type="password" />
</el-form-item>
<el-form-item v-if="user&&edite" label="电话" :label-width="formLabelWidth" prop="phone">
<el-input v-model="ruleForm.phone" />
</el-form-item>
<el-form-item label="备注" prop="desc" v-if="user&&edite" :label-width="formLabelWidth">
<el-input type="textarea" v-model="ruleForm.desc" maxlength="100" show-word-limit="true"></el-input>
</el-form-item>
<!-- <el-form-item label="验证码" :label-width="formLabelWidth" placeholder="请输入验证码" prop="code" v-if="user">
<el-input v-model="ruleForm.verifyCode" class="verifyCode"></el-input>
<VerificationCode :changeCode.sync='verifyCode'></VerificationCode>
</el-form-item> -->
<el-form-item v-if="group" label="群组名称" :label-width="formLabelWidth" prop="name">
<el-input v-model="ruleForm.name" disabled />
</el-form-item>
@@ -56,9 +58,45 @@
flag: {
type: String,
default: ""
},
type: {
type: String,
default: 'edite'
}
},
data() {
var checkPhone = (rule, value, callback) => {
if (value === '') {
callback();
} else {
let reg = /^(13|14|15|17|18|19)[0-9]{9}$/
if (reg.test(value)) {
callback();
}
else {
callback("请输入正确手机号码");
}
}
};
var validatePass = (rule, value, callback) => {
if (value === '') {
callback(new Error('请输入密码'));
} else {
if (this.ruleForm.confirm !== '') {
this.$refs.ruleForm.validateField('confirm');
}
callback();
}
};
var validatePass2 = (rule, value, callback) => {
if (value === ''||value==undefined) {
callback(new Error('请再次输入密码'));
} else if (value !== this.ruleForm.password) {
callback(new Error('两次输入密码不一致!'));
} else {
callback();
}
};
return {
fileList: [],
ruleForm: {
@@ -67,7 +105,10 @@
fullname: '',
resourcePoolId: '',
name: '',
userIds: []
userIds: [],
email: undefined,
desc: '',
phone: ''
},
verifyCode: "",
CreateFormVisible: true,
@@ -77,12 +118,13 @@
userOptions: [],
rules: {
password: [
{ required: true, message: '请输入密码', trigger: 'blur' }
{ required: true, message: '请输入密码', trigger: 'blur' },
{ min: 8, message: '密码长度不得少于8位', trigger: 'blur' },
{ validator: validatePass, trigger: 'blur' }

],
confirm: [
{ required: true, message: '请再次输入密码', trigger: 'blur' }

{ validator: validatePass2, trigger: 'blur' }
],
name: [
{ required: true, message: '请输入用户名', trigger: 'blur' }
@@ -93,11 +135,17 @@
],
resourcePoolId: [
{ required: true, message: '请选择资源池', trigger: 'change' }
]
],
phone: [
{ required: false, message: '请输入电话' },
{ validator: checkPhone, trigger: "blur" }
],
},
formLabelWidth: '120px',
pageSize: 100,
userCount: 1
userCount: 1,
edite: false,
password: false

}
},
@@ -106,7 +154,16 @@
this.user = true
this.group = false
this.ruleForm.fullName = this.row.fullName
this.ruleForm.phone = this.row.phone
this.ruleForm.desc = this.row.desc
this.id = this.row.id
if (this.type == 'password') {
this.password = true
this.edite = false
} else {
this.password = false
this.edite = true
}
} else {
this.group = true
this.user = false
@@ -197,27 +254,25 @@
this.$refs['ruleForm'].validate((valid) => {
if (valid) {
if (this.userType === 'user') {
if (this.ruleForm.confirm === this.ruleForm.password) {
const data = { fullname: this.ruleForm.fullname, password: this.ruleForm.password, id: this.id }
editUser(data).then(response => {
if (response.success) {
this.$message({
message: '修改成功',
type: 'success'
});
} else {
this.$message({
message: response.error.message,
type: 'error'
});
}
})
} else {
this.$message({
message: '输入密码不一致!',
type: 'warning'
});
let data = {}
if (this.password) { data = { fullname: this.ruleForm.fullname, password: this.ruleForm.password, id: this.id } }
else {
data = { id: this.id, phone: this.ruleForm.phone.toString(), desc: this.ruleForm.desc }
}
editUser(data).then(response => {
if (response.success) {
this.$message({
message: '修改成功',
type: 'success'
});
this.$emit('confirm', false)
} else {
this.$message({
message: response.error.message,
type: 'error'
});
}
})
} else {
const data = { name: this.ruleForm.name, resourcePoolId: this.ruleForm.resourcePoolId, id: this.id, userIds: this.ruleForm.userIds }
editGroup(data).then(response => {
@@ -226,6 +281,7 @@
message: '修改成功',
type: 'success'
});
this.$emit('confirm', false)
} else {
this.$message({
message: this.getErrorMsg(response.error.subcode),
@@ -234,7 +290,7 @@
}
})
}
this.$emit('confirm', false)
} else {
console.log('error submit!!');
return false;


+ 35
- 16
admin-portal/src/views/userManager/user.vue View File

@@ -18,6 +18,11 @@
<span>{{ scope.row.email }}</span>
</template>
</el-table-column>
<el-table-column v-if="user" label="电话" align="center">
<template slot-scope="scope">
<span>{{ scope.row.phone }}</span>
</template>
</el-table-column>
<el-table-column v-if="group" label="群组名称" align="center">
<template slot-scope="scope">
<span>{{ scope.row.name }}</span>
@@ -33,6 +38,11 @@
<span>{{ scope.row.status===1?'已冻结':'已激活' }}</span>
</template>
</el-table-column>
<el-table-column v-if="user" label="备注" align="center">
<template slot-scope="scope">
<span>{{ scope.row.desc }}</span>
</template>
</el-table-column>
<el-table-column label="创建时间" align="center">
<template slot-scope="scope">
<span>{{ scope.row.createdAt | parseTime }}</span>
@@ -43,18 +53,19 @@
<span>{{ scope.row.updatedAt | parseTime }}</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center">
<el-table-column label="操作" align="center" width="300">
<template slot-scope="scope">
<el-button v-if="user" type="text" @click="handleUserEdit(scope.row)">编辑</el-button>
<el-button v-if="user" type="text" @click="handleUserEdit(scope.row)">资源池</el-button>
<el-button v-if="scope.row.status===2 && user" type="text" @click="handleFreeze(scope.row)">冻结
</el-button>
<el-button v-if="scope.row.status===1 && user" type="text" @click="handleThaw( scope.row)">激活
</el-button>
<el-button v-if="user" type="text" @click="handleReset(scope.row)">重置密码</el-button>
<el-button v-if="user" type="text" @click="handleReset(scope.row,'password')">修改密码</el-button>
<el-button v-if="user" type="text" @click="handleReset(scope.row,'edite')">编辑</el-button>
<el-button v-if="group" type="text" @click="handleEdit(scope.row)">编辑</el-button>
<!-- <el-button @click="handleDelete(scope.row)" type="text" v-if="group">删除</el-button> -->
<el-button type="text" @click="handleDetail(scope.row)">{{ user?'用户详情':'群组详情' }}</el-button>
<el-button v-if="user" type="text" @click="handleUserConfig(scope.row)">用户配置</el-button>
<el-button type="text" @click="handleDetail(scope.row)">{{ user?'所属群组':'用户列表' }}</el-button>
<!-- <el-button v-if="user" type="text" @click="handleUserConfig(scope.row)">用户配置</el-button> -->
</template>
</el-table-column>
</el-table>
@@ -67,13 +78,14 @@
<addDialog v-if="CreateVisible" :flag="flag" @cancel="cancel" @confirm="confirm" @close="close" />
<!-- 创修改信息对话框 -->
<operateDialog v-if="operateVisible" :row="row" :user-type="change" @cancel="cancel" @confirm="confirm"
@close="close" />
@close="close" :type='type'/>
<!-- 用户配置对话框 -->
<userConfig v-if="userConfigVisible" :conKey="conKey" :conValue="conValue" :row="row" @cancel="cancel"
@confirm="confirm" @close="close">
</userConfig>
<!-- 资源池绑定对话框 -->
<userEdit v-if="userEdit" :userResourcePoolList="userResourcePoolList" :row="row" @cancel="cancel" @confirm="confirm" @close="close">
<userEdit v-if="userEdit" :userResourcePoolList="userResourcePoolList" :row="row" @cancel="cancel"
@confirm="confirm" @close="close">
</userEdit>
<!-- 详情对话框 -->
<el-dialog :title="user?'用户名' + userName:'群组名' + groupName" :visible.sync="detailVisible" width="30%" center
@@ -141,7 +153,9 @@
pageSize: 10
},
conKey: [],
conValue: {}
conValue: {},
time: null,
type:''
}
},
created() {
@@ -164,12 +178,12 @@
this.searchForm = []
}
this.getList(this.searchData)
// this.timer = setInterval(this.getList, 1000);

},
beforeDestroy() {
clearTimeout(this.timer);
this.timer = null;
},
// beforeDestroy() {
// clearInterval(this.timer);
// this.timer = null;
// },
methods: {
handleUserEdit(row) {
this.row = row
@@ -177,7 +191,7 @@
if (response.success) {
if (response.data !== null && response.data.resourcePools !== null) {
this.userEdit = true
this.userResourcePoolList =response.data.resourcePools
this.userResourcePoolList = response.data.resourcePools
} else {
this.userResourcePoolList = []
}
@@ -241,9 +255,10 @@
}
})
},
handleReset(row) {
handleReset(row,type) {
this.row = row
this.operateVisible = true
this.type=type
},
handleUserConfig(row) {
this.row = row
@@ -298,7 +313,8 @@
this.operateVisible = val
this.userConfigVisible = val
this.userEdit = val
this.getList(this.searchData)
this.timer = setTimeout(this.getList, 500)

},
close(val) {
this.CreateVisible = val
@@ -311,6 +327,9 @@
this.CreateVisible = true
},
getList(data) {
if (!data) {
data = this.searchData
}
if (this.userTabType === 1) {
getUserList(data).then(response => {
if (response.success) {


+ 0
- 3
openai-portal/src/directives.js View File

@@ -5,10 +5,7 @@ export default MyDirective.install = function(vue, options) {
bind(el, binding) {
const selectDom = el.querySelector('.el-select-dropdown .el-select-dropdown__wrap')
selectDom.addEventListener('scroll', function() {
const isEnd = this.scrollHeight - this.scrollTop <= this.clientHeight
if (isEnd) {
binding.value()
}
})
}
})

+ 2
- 1
openai-portal/src/layout/components/Navbar.vue View File

@@ -7,7 +7,7 @@
<breadcrumb class="breadcrumb-container" />
</el-row>
</el-col>
<el-col :span="10">
<el-col :span="24">
<div class="right-menu">
<el-row class="demo-avatar demo-basic">
<el-dropdown>
@@ -171,6 +171,7 @@
height: 100%;
color: #409EFF;
font-size: 20px;
min-width: 400px;

.avatar-container {
margin-right: 30px;


+ 1
- 0
openai-portal/src/styles/index.scss View File

@@ -20,6 +20,7 @@ label {
html {
height: 100%;
box-sizing: border-box;
min-width: 1200px;
}

#app {


+ 126
- 61
openai-portal/src/views/Home/register.vue View File

@@ -7,45 +7,64 @@
</el-col>
</el-row>
<el-row type="flex" justify="center">
<el-col :span="6">
<el-col :span="6" v-show="!show">
<div>
<el-form ref="loginForm" :model="loginForm" :rules="rules" label-width="80px">
<el-form-item prop="fullName" label="姓名" v-if="show" key="fullName">
<el-input v-model="loginForm.fullName" type="text" auto-complete="off"
<el-form ref="loginForm1" :model="loginForm1" :rules="rules1" label-width="80px">
<el-form-item prop="username" label="邮箱" key="username">
<el-input v-model="loginForm1.username" type="text" auto-complete="off"
placeholder="请输入邮箱号" />
</el-form-item>
<el-form-item label="密码" prop="password">
<el-input type="password" v-model="loginForm1.password" autocomplete="off"></el-input>
</el-form-item>
<el-form-item>
<el-row type="flex" :gutter="20">
<el-col :span="18" :offset="9">
<el-button type="primary" @click="login()">绑定并登录</el-button>
</el-col>
</el-row>
</el-form-item>
<el-form-item>
<el-row type="flex" :gutter="20">
<el-col :span="18" :offset="9">
<el-link type="primary" @click="goRegister">未注册?点击注册</el-link>
</el-col>
</el-row>
</el-form-item>
</el-form>
</div>
</el-col>
<el-col :span="6" v-show="show">
<div>
<el-form ref="loginForm2" :model="loginForm2" :rules="rules2" label-width="80px">
<el-form-item prop="fullName" label="姓名" key="fullName">
<el-input v-model="loginForm2.fullName" type="text" auto-complete="off"
placeholder="请输入姓名" />
</el-form-item>
<el-form-item prop="gender" label="性别" v-if="show" key="gender">
<el-radio-group v-model="loginForm.gender">
<el-form-item prop="gender" label="性别" key="gender">
<el-radio-group v-model="loginForm2.gender">
<el-radio :label="1">男</el-radio>
<el-radio :label="2">女</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item prop="username" label="邮箱" key="username">
<el-input v-model="loginForm.username" type="text" auto-complete="off"
<el-input v-model="loginForm2.username" type="text" auto-complete="off"
placeholder="请输入邮箱号" />
</el-form-item>
<el-form-item prop="password" label="密码" key="password">
<el-input v-model="loginForm.password" type="password" auto-complete="off"
placeholder="密码" />
<el-form-item label="密码" prop="password">
<el-input type="password" v-model="loginForm2.password" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="确认密码" prop="checkPass">
<el-input type="password" v-model="loginForm2.checkPass" autocomplete="off"></el-input>
</el-form-item>
<el-form-item>
<el-row type="flex" :gutter="20">
<el-col :span="18" :offset="9" v-if="!show">
<el-button type="primary" @click="login()">绑定并登录</el-button>
</el-col>
<el-col :span="18" :offset="9" v-if="show">
<el-col :span="18" :offset="9">
<el-button type="primary" @click="register()">注册并登录</el-button>
</el-col>
</el-row>
</el-form-item>
<el-form-item>
<el-row type="flex" :gutter="20" v-if="hidden">
<el-col :span="18" :offset="9">
<el-link type="primary" @click="goRegister">未注册?点击注册</el-link>
</el-col>
</el-row>
</el-form-item>
<el-form-item v-if="show">
<el-row type="flex" justify="end">
<el-col :span="4">
<el-link type="primary" @click="goLogin()">返回登录</el-link>
@@ -55,6 +74,7 @@
</el-form>
</div>
</el-col>

</el-row>
</div>
</template>
@@ -72,22 +92,62 @@
}
callback(new Error("请输入合法的邮箱"));
};
var validatePass = (rule, value, callback) => {
if (value === '') {
console.log('value='+value)
callback(new Error('请输入密码'));
} else {
if (this.loginForm2.checkPass !== '') {
this.$refs.loginForm2.validateField('checkPass');
}
callback();
}
};
var validatePass2 = (rule, value, callback) => {
if (value === '') {
callback(new Error('请再次输入密码'));
} else if (value !== this.loginForm2.password) {
callback(new Error('两次输入密码不一致!'));
} else {
callback();
}
};
return {
show: false,
hidden: true,
loginForm: {
loginForm1: {
username: '',
password: '',
bind: { platform: '', userId: '', userName: '' }
},
loginForm2: {
fullName: '',
username: undefined,
password: undefined,
gender: undefined,
username: '',
password: '',
gender: '',
checkPass: '',
bind: { platform: '', userId: '', userName: '' }
},
rules: {
rules1: {
username: [{ required: true, message: "请输入邮箱号", trigger: "blur" },
{ validator: checkEmail, trigger: "blur" }
],
password: [
{ validator: validatePass, trigger: 'blur' },
{ min: 8, message: '密码长度不能小于8位', trigger: 'blur' }
],
},
rules2: {
username: [{ required: true, message: "请输入邮箱号", trigger: "blur" },
{ validator: checkEmail, trigger: "blur" }
],
password: [{ required: true, message: '请输入用户密码', trigger: 'blur' },
{ min: 8, message: '密码长度不能小于8位', trigger: 'blur' }],
password: [
{ validator: validatePass, trigger: 'blur' },
{ min: 8, message: '密码长度不能小于8位', trigger: 'blur' }
],
checkPass: [
{ validator: validatePass2, trigger: 'blur' }
],
fullName: [{ required: true, message: '请输入姓名', trigger: 'blur' }],
gender: [
{ required: true, message: '请选择性别', trigger: 'change' }
@@ -97,9 +157,12 @@
},
created() {
this.getThirdInfo()
this.loginForm.bind.platform = sessionStorage.getItem("platform")
this.loginForm.bind.userName = sessionStorage.getItem("thirdUserName")
this.loginForm.bind.userId = sessionStorage.getItem("thirdUserId")
this.loginForm1.bind.platform = sessionStorage.getItem("platform")
this.loginForm1.bind.userName = sessionStorage.getItem("thirdUserName")
this.loginForm1.bind.userId = sessionStorage.getItem("thirdUserId")
this.loginForm2.bind.platform = sessionStorage.getItem("platform")
this.loginForm2.bind.userName = sessionStorage.getItem("thirdUserName")
this.loginForm2.bind.userId = sessionStorage.getItem("thirdUserId")
},
computed: {
},
@@ -123,11 +186,41 @@
this.show = false
this.hidden = true
},
// 登录并绑定
login() {
// 在点击提交之前校验表单
let loginForm = JSON.parse(JSON.stringify(this.loginForm1));
delete loginForm.fullName
delete loginForm.gender
this.$refs['loginForm1'].validate((valid) => {
if (valid) {
login(loginForm).then((res) => {
if (res.success) {
this.$message({
message: '登录成功',
type: 'success'
});
setToken(res.data.token)
this.$router.push({ path: '/index' })
} else {
this.$message({
message: this.getErrorMsg(res.error.subcode),
type: 'warning'
});
}
}).catch(() => {
})
} else {
return false;
}
});

},
// 注册并绑定
register() {
this.$refs['loginForm'].validate((valid) => {
this.$refs['loginForm2'].validate((valid) => {
if (valid) {
register(this.loginForm).then(
register(this.loginForm2).then(
response => {
if (response.success) {
this.$message({
@@ -159,35 +252,7 @@
}
});
},
// 登录并绑定
login() {
let loginForm = JSON.parse(JSON.stringify(this.loginForm));
delete loginForm.fullName
delete loginForm.gender
this.$refs['loginForm'].validate((valid) => {
if (valid) {
login(loginForm).then((res) => {
if (res.success) {
this.$message({
message: '登录成功',
type: 'success'
});
setToken(res.data.token)
this.$router.push({ path: '/index' })
} else {
this.$message({
message: this.getErrorMsg(res.error.subcode),
type: 'warning'
});
}
}).catch(() => {
})
} else {
return false;
}
});

},
}
}
</script>


+ 10
- 13
openai-portal/src/views/trainingManager/components/detailDialog/taskProfile.vue View File

@@ -19,7 +19,8 @@
</el-row>
<el-row>
<el-col :span="12">
<div>选用数据集:<span>{{ data.dataSetName + ":" + data.dataSetVersion }}</span></div>
<div>选用数据集:<span>{{ (data.dataSetName&&data.dataSetVersion)?data.dataSetName + ":" +
data.dataSetVersion:'' }}</span></div>
</el-col>
<el-col :span="12">
<div>是否分布式:<span>{{ data.isDistributed?'是':'否' }}</span></div>
@@ -27,7 +28,8 @@
</el-row>
<el-row>
<el-col v-if="!show" :span="12">
<div>资源规格:<span>{{ data.config[0].resourceSpecName + '' + data.config[0].resourceSpecPrice + '机时/h' }}</span>
<div>资源规格:<span>{{ data.config[0].resourceSpecName + '' + data.config[0].resourceSpecPrice + '机时/h'
}}</span>
</div>
</el-col>
<el-col v-if="!show" :span="12">
@@ -47,14 +49,9 @@
<el-divider />
<div class="taskList">分布式任务列表</div>
<div>
<el-table
:data="tableData"
style="width: 100%"
row-key="name"
:tree-props="{children: 'replicaStates', hasChildren: 'hasChildren'}"
default-expand-all
height="700"
>
<el-table :data="tableData" style="width: 100%" row-key="name"
:tree-props="{children: 'replicaStates', hasChildren: 'hasChildren'}" default-expand-all
height="700">
<el-table-column prop="name" label="任务名称" width="200px" :show-overflow-tooltip="true" />
<el-table-column label="是否主任务">
<template slot-scope="scope">
@@ -67,7 +64,7 @@
<el-table-column label="资源规格">
<template slot-scope="scope">
<span v-if="!scope.row.isChildren">
{{ scope.row.resourceSpecName + '' + scope.row.resourceSpecPrice + '机时/h' }}
{{ scope.row.resourceSpecName + '' + scope.row.resourceSpecPrice + '机时/h' }}
</span>
</template>
</el-table-column>
@@ -105,7 +102,7 @@
}
},
computed: {
show: function() {
show: function () {
if (this.data.isDistributed === true) {
return true
} else { return false }
@@ -131,7 +128,7 @@
}
},
methods: {
command: function(data) {
command: function (data) {
let command = data.command
if (data.parameters != null && data.parameters.length != 0) {
data.parameters.forEach(


+ 2
- 2
openai-portal/vue.config.js View File

@@ -42,14 +42,14 @@ module.exports = {
},
proxy: {
[process.env.VUE_APP_BASE_API]: {
target: 'http://192.168.204.155/',
target: 'http://192.168.202.71/',
changeOrigin: true,
pathRewrite: {
['^' + process.env.VUE_APP_BASE_API]: '/openaiserver'
}
},
[process.env.VUE_APP_BASE_API2]: {
target: 'http://192.168.204.155/',
target: 'http://192.168.202.71/',
changeOrigin: true,
pathRewrite: {
['^' + process.env.VUE_APP_BASE_API]: ''


+ 3
- 0
server/admin-server/api/v1/user.proto View File

@@ -76,6 +76,7 @@ message UserItem {
int32 gender = 7;
int32 status = 8;
repeated string resourcePools = 9;
string desc=10;
}

message ListUserRequest {
@@ -111,6 +112,7 @@ message AddUserRequest {
string phone = 3 [(validate.rules).string = {pattern: "^(13|14|15|17|18|19)[0-9]{9}$", ignore_empty:true}];
string password = 4 [(validate.rules).string = {min_len: 8, max_len: 30}];
int32 gender = 5 [(validate.rules).int32 = {in: [1,2]}];
string desc = 6 ;
}

message AddUserReply {
@@ -125,6 +127,7 @@ message UpdateUserRequest {
string phone = 3 [(validate.rules).string = {pattern: "^(13|14|15|17|18|19)[0-9]{9}$", ignore_empty:true}];
int32 gender = 4 [(validate.rules).int32 = {in: [1,2],ignore_empty: true}];
repeated string resourcePools = 5;
string desc = 6 ;
}
UpdateItem user = 2 [(validate.rules).message.required = true];
}


+ 1
- 1
server/admin-server/configs/config.yaml View File

@@ -12,7 +12,7 @@ data:
baseServerAddr: dns:///127.0.0.1:9001
baseServerRequestTimeout: 30s
redis:
addr: 192.168.202.73:30635
addr: 192.168.202.73:30207
username:
password: abcde
service:

+ 6
- 3
server/admin-server/internal/service/user.go View File

@@ -2,6 +2,7 @@ package service

import (
"context"
"github.com/jinzhu/copier"
pb "server/admin-server/api/v1"
"server/admin-server/internal/conf"
"server/admin-server/internal/data"
@@ -10,8 +11,6 @@ import (
"server/common/errors"
"server/common/log"
"time"

"github.com/jinzhu/copier"
)

type UserService struct {
@@ -58,6 +57,7 @@ func (s *UserService) ListUser(ctx context.Context, req *pb.ListUserRequest) (*p
Gender: int32(user.Gender),
Status: int32(user.Status),
ResourcePools: user.ResourcePools,
Desc: user.Desc,
}
}

@@ -102,6 +102,7 @@ func (s *UserService) GetUser(ctx context.Context, req *pb.GetUserRequest) (*pb.
Gender: int32(user.Gender),
Status: int32(user.Status),
ResourcePools: user.ResourcePools,
Desc: user.Desc,
},
Workspaces: workspaces,
}, nil
@@ -114,12 +115,12 @@ func (s *UserService) AddUser(ctx context.Context, req *pb.AddUserRequest) (*pb.
Email: req.Email,
Phone: req.Phone,
Gender: innterapi.GenderType(req.Gender),
Desc: req.Desc,
})

if err != nil {
return nil, err
}

user := addUserReply.User

_, err = s.data.BillingClient.CreateBillingOwner(ctx, &innterapi.CreateBillingOwnerRequest{
@@ -151,6 +152,7 @@ func (s *UserService) UpdateUser(ctx context.Context, req *pb.UpdateUserRequest)
Phone: req.User.Phone,
Gender: innterapi.GenderType(req.User.Gender),
ResourcePools: req.User.ResourcePools,
Desc: req.User.Desc,
})

if err != nil {
@@ -167,6 +169,7 @@ func (s *UserService) UpdateUser(ctx context.Context, req *pb.UpdateUserRequest)
Phone: result.User.Phone,
Gender: int32(result.User.Gender),
Status: int32(result.User.Status),
Desc: result.User.Desc,
},
}, nil
}


+ 4
- 0
server/base-server/api/v1/user.proto View File

@@ -49,6 +49,7 @@ message UserItem {
repeated Bind bind = 10;
string ftpUserName = 11;
repeated string resourcePools = 12;
string desc=13;
}

message Bind {
@@ -64,6 +65,7 @@ message AddUserRequest {
string password = 4 [(validate.rules).string = {min_len: 8, max_len: 30}];
GenderType gender = 5 [(validate.rules).enum = {in: [1,2]}];
Bind bind = 6;
string desc=7;
}

message AddUserReply {
@@ -99,6 +101,7 @@ message ListUserRequest {
string phone = 7 [(validate.rules).string = {pattern: "^(13|14|15|17|18|19)[0-9]{9}$", ignore_empty:true}];
string searchKey = 8 [(validate.rules).string = {max_len: 50}];
UserStatus status = 9 [(validate.rules).enum = {defined_only: true}];
string desc = 10;
}

message ListUserReply {
@@ -116,6 +119,7 @@ message UpdateUserRequest {
UserStatus status = 7 [(validate.rules).enum = {defined_only: true}];
repeated Bind bind = 8;
repeated string resourcePools = 9;
string desc=10;
}

message UpdateUserReply {


+ 5
- 5
server/base-server/configs/config.yaml View File

@@ -13,10 +13,10 @@ server:
data:
database:
driver: mysql
source: root:root@tcp(192.168.204.155:30336)/octopus?charset=utf8&parseTime=True&loc=Local
source: root:root@tcp(192.168.202.73:30336)/octopus?charset=utf8&parseTime=True&loc=Local
kubernetes:
masterUrl: https://192.168.204.155:6443/
configPath: /home/hackmong/openi/155config
masterUrl: https://192.168.202.73:6443/
configPath: ./73kubeconfig
minio:
base:
endPoint: 192.168.202.73:31311
@@ -36,11 +36,11 @@ data:
apiVersion: v1.0
useSSL: false
redis:
addr: 192.168.203.154:30635
addr: 192.168.202.73:30635
username:
password: abcde
influxdb:
addr: 192.168.203.154:8086
addr: 192.168.202.73:30086
username: octopus
password: octopus
database: octopus


+ 6
- 0
server/base-server/internal/data/dao/model/user.go View File

@@ -54,6 +54,7 @@ type User struct {
Bind Binds `gorm:"type:json;comment:'第三方账号绑定信息'"`
FtpUserName string `gorm:"type:varchar(100);uniqueIndex:ftpUserName;comment:'ftp用户名'"`
ResourcePools ResourcePools `gorm:"type:json;comment:'资源池'"`
Desc string `gorm:"type:varchar(100);default:'';index;comment:'备注'"`
}

func (User) TableName() string {
@@ -74,6 +75,7 @@ type UserList struct {
SearchKey string
Status int32
Bind Binds
Desc string
}

func (u UserList) Where(db *gorm.DB) *gorm.DB {
@@ -155,6 +157,7 @@ type UserQuery struct {
Phone string
Bind *Bind
FtpUserName string
Desc string
}

type UserAdd struct {
@@ -167,6 +170,7 @@ type UserAdd struct {
Status int32
Bind *Bind
ResourcePools []string
Desc string
}

type UserUpdate struct {
@@ -179,12 +183,14 @@ type UserUpdate struct {
Bind Binds
FtpUserName string
ResourcePools []string
Desc string
}

type UserUpdateCond struct {
Id string
Email string
Phone string
Desc string
}

type UserListIn struct {


+ 5
- 4
server/base-server/internal/data/dao/user.go View File

@@ -10,9 +10,8 @@ import (

"gorm.io/gorm/clause"

commerrors "server/common/errors"

"gorm.io/gorm"
commerrors "server/common/errors"
)

type UserDao interface {
@@ -71,7 +70,7 @@ func (d *userDao) Find(ctx context.Context, condition *model.UserQuery) (*model.
result = db.Where(&model.User{
Id: condition.Id,
Email: condition.Email,
Phone: condition.Phone,
Phone: condition.Phone,
FtpUserName: condition.FtpUserName,
}).First(&user)
} else {
@@ -97,7 +96,6 @@ func (d *userDao) Find(ctx context.Context, condition *model.UserQuery) (*model.
}
result = db.Where(querySql, params...).First(&user)
}

if result.Error != nil {
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
return nil, nil
@@ -123,6 +121,7 @@ func (d *userDao) Add(ctx context.Context, user *model.UserAdd) (*model.User, er
Status: user.Status,
Bind: bindInfo,
ResourcePools: user.ResourcePools,
Desc: user.Desc,
}

result := db.Omit("ftp_user_name").Create(&u)
@@ -142,6 +141,7 @@ func (d *userDao) Update(ctx context.Context, cond *model.UserUpdateCond, user *
Id: cond.Id,
Email: cond.Email,
Phone: cond.Phone,
Desc: cond.Desc,
}

result := d.db.Model(&condition).Updates(model.User{
@@ -154,6 +154,7 @@ func (d *userDao) Update(ctx context.Context, cond *model.UserUpdateCond, user *
Bind: user.Bind,
FtpUserName: user.FtpUserName,
ResourcePools: user.ResourcePools,
Desc: user.Desc,
})
if result.Error != nil {
return nil, result.Error


+ 38
- 15
server/base-server/internal/service/trainjob/train_job.go View File

@@ -37,6 +37,7 @@ const (
k8sTaskNamePrefix = "task"
NoDistributedJobNum = 1
shmResource = "shm"
readonlyCodeDir = "/readonlycode"
)

type trainJobService struct {
@@ -137,8 +138,11 @@ func (s *trainJobService) TrainJob(ctx context.Context, req *api.TrainJobRequest
return &api.TrainJobReply{JobId: trainJobId}, nil
}

func (s *trainJobService) buildCmd(config *model.Config) []string {
cmd := fmt.Sprintf("cd %s;%s ", s.conf.Service.DockerCodePath, config.Command)
func (s *trainJobService) buildCmd(job *model.TrainJob, config *model.Config) []string {
cmd := config.Command
if job.AlgorithmId != "" {
cmd = fmt.Sprintf("cp -r %s/* %s;cd %s;%s ", readonlyCodeDir, s.conf.Service.DockerCodePath, s.conf.Service.DockerCodePath, config.Command)
}
if len(config.Parameters) == 0 {
return []string{"sh", "-c", cmd}
} else {
@@ -474,18 +478,6 @@ func (s *trainJobService) submitJob(ctx context.Context, job *model.TrainJob, st
minAvailable += i.TaskNumber
//挂载卷
volumeMounts := []v1.VolumeMount{
{
Name: "data",
MountPath: s.conf.Service.DockerCodePath,
SubPath: startJobInfo.algorithmPath,
ReadOnly: true,
},
{
Name: "data",
MountPath: s.conf.Service.DockerDatasetPath,
SubPath: startJobInfo.datasetPath,
ReadOnly: true,
},
{
Name: "data",
MountPath: s.conf.Service.DockerModelPath,
@@ -504,6 +496,32 @@ func (s *trainJobService) submitJob(ctx context.Context, job *model.TrainJob, st
},
}

if startJobInfo.algorithmPath != "" {
volumeMounts = append(volumeMounts,
v1.VolumeMount{
Name: "data",
MountPath: readonlyCodeDir,
SubPath: startJobInfo.algorithmPath,
ReadOnly: true,
},
v1.VolumeMount{
Name: "code",
MountPath: s.conf.Service.DockerCodePath,
ReadOnly: false,
})

}

if startJobInfo.datasetPath != "" {
volumeMounts = append(volumeMounts,
v1.VolumeMount{
Name: "data",
MountPath: s.conf.Service.DockerDatasetPath,
SubPath: startJobInfo.datasetPath,
ReadOnly: true,
})
}

volumes := []v1.Volume{
{
Name: "data",
@@ -520,6 +538,11 @@ func (s *trainJobService) submitJob(ctx context.Context, job *model.TrainJob, st
Path: "/etc/localtime",
}},
},
{
Name: "code",
VolumeSource: v1.VolumeSource{
EmptyDir: &v1.EmptyDirVolumeSource{}},
},
}

//add shareMemory for each subTask
@@ -562,7 +585,7 @@ func (s *trainJobService) submitJob(ctx context.Context, job *model.TrainJob, st
Limits: startJobInfo.specs[i.ResourceSpecId].resources,
},
VolumeMounts: volumeMounts,
Command: s.buildCmd(i),
Command: s.buildCmd(job, i),
},
},
NodeSelector: startJobInfo.specs[i.ResourceSpecId].nodeSelectors,


+ 8
- 5
server/base-server/internal/service/user/user.go View File

@@ -2,17 +2,15 @@ package user

import (
"context"
"golang.org/x/crypto/bcrypt"
api "server/base-server/api/v1"
"server/base-server/internal/common"
"server/base-server/internal/conf"
"server/base-server/internal/data"
"server/base-server/internal/data/dao/model"
"server/common/errors"
"server/common/utils"

"server/common/log"

"golang.org/x/crypto/bcrypt"
"server/common/utils"
)

type UserService struct {
@@ -52,6 +50,7 @@ func (s *UserService) ListUser(ctx context.Context, req *api.ListUserRequest) (*
SearchKey: req.SearchKey,
Phone: req.Phone,
Status: int32(req.Status),
Desc: req.Desc,
})
if err != nil {
return nil, err
@@ -91,6 +90,7 @@ func (s *UserService) ListUser(ctx context.Context, req *api.ListUserRequest) (*
UpdatedAt: user.UpdatedAt.Unix(),
Bind: bindInfo,
ResourcePools: user.ResourcePools,
Desc: user.Desc,
}
users[idx] = item
}
@@ -156,6 +156,7 @@ func (s *UserService) FindUser(ctx context.Context, req *api.FindUserRequest) (*
UpdatedAt: user.UpdatedAt.Unix(),
Bind: bindInfo,
ResourcePools: user.ResourcePools,
Desc: user.Desc,
},
}

@@ -238,6 +239,7 @@ func (s *UserService) AddUser(ctx context.Context, req *api.AddUserRequest) (*ap
user.Status = int32(api.UserStatus_ACTIVITY)
user.Bind = cond.Bind
user.ResourcePools = []string{s.conf.Service.Resource.DefaultPoolName}
user.Desc=req.Desc
u, err := s.data.UserDao.Add(ctx, &user)
if err != nil {
return nil, err
@@ -295,6 +297,7 @@ func (s *UserService) UpdateUser(ctx context.Context, req *api.UpdateUserRequest
Gender: int32(req.Gender),
Status: int32(req.Status),
ResourcePools: req.ResourcePools,
Desc: req.Desc,
}
if len(bindInfo) > 0 {
user.Bind = bindInfo
@@ -307,7 +310,6 @@ func (s *UserService) UpdateUser(ctx context.Context, req *api.UpdateUserRequest
}
user.Password = string(password)
}

result, err := s.data.UserDao.Update(ctx, &model.UserUpdateCond{Id: userId}, &user)
if err != nil {
return nil, err
@@ -333,6 +335,7 @@ func (s *UserService) UpdateUser(ctx context.Context, req *api.UpdateUserRequest
Status: api.UserStatus(result.Status),
Password: result.Password,
Bind: bindInfo2,
Desc: result.Desc,
},
}, nil
}


Loading…
Cancel
Save