mirror of
https://gitee.com/goploy/goploy.git
synced 2024-12-04 13:11:28 +08:00
A optimize project
This commit is contained in:
parent
616715bebd
commit
8384690979
@ -213,7 +213,7 @@ func (Crontab) Edit(gp *core.Goploy) *core.Response {
|
||||
return &core.Response{}
|
||||
}
|
||||
|
||||
// import many crontab
|
||||
// Import many crontab
|
||||
func (Crontab) Import(gp *core.Goploy) *core.Response {
|
||||
type ReqData struct {
|
||||
ServerID int64 `json:"serverId" validate:"gt=0"`
|
||||
@ -272,7 +272,7 @@ func (Crontab) Import(gp *core.Goploy) *core.Response {
|
||||
return &core.Response{}
|
||||
}
|
||||
|
||||
// DeleteRow one Crontab
|
||||
// Remove one Crontab
|
||||
func (Crontab) Remove(gp *core.Goploy) *core.Response {
|
||||
type ReqData struct {
|
||||
ID int64 `json:"id" validate:"gt=0"`
|
||||
|
@ -470,6 +470,13 @@ func (Project) AddFile(gp *core.Goploy) *core.Response {
|
||||
return &core.Response{Code: core.Error, Message: err.Error()}
|
||||
}
|
||||
|
||||
_, err := os.Stat(core.GetProjectFilePath(reqData.ProjectID))
|
||||
if err != nil {
|
||||
err := os.MkdirAll(core.GetProjectFilePath(reqData.ProjectID), os.ModePerm)
|
||||
if err != nil {
|
||||
return &core.Response{Code: core.Error, Message: err.Error()}
|
||||
}
|
||||
}
|
||||
file, err := os.Create(path.Join(core.GetProjectFilePath(reqData.ProjectID), reqData.Filename))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
@ -508,6 +515,14 @@ func (Project) EditFile(gp *core.Goploy) *core.Response {
|
||||
return &core.Response{Code: core.Error, Message: err.Error()}
|
||||
}
|
||||
|
||||
_, err = os.Stat(core.GetProjectFilePath(projectFileData.ProjectID))
|
||||
if err != nil {
|
||||
err := os.MkdirAll(core.GetProjectFilePath(projectFileData.ProjectID), os.ModePerm)
|
||||
if err != nil {
|
||||
return &core.Response{Code: core.Error, Message: err.Error()}
|
||||
}
|
||||
}
|
||||
|
||||
file, err := os.Create(path.Join(core.GetProjectFilePath(projectFileData.ProjectID), projectFileData.Filename))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
|
@ -34,7 +34,7 @@ var (
|
||||
Gwg sync.WaitGroup
|
||||
)
|
||||
|
||||
// GetCurrentPath if env = 'production' return absolute else return relative
|
||||
// GetAssetDir if env = 'production' return absolute else return relative
|
||||
func GetAssetDir() string {
|
||||
if AssetDir != "" {
|
||||
return AssetDir
|
||||
|
@ -1,4 +1,191 @@
|
||||
import Axios from './axios'
|
||||
import { Request, Pagination, ID, Total } from './types'
|
||||
|
||||
export class ProjectServerData {
|
||||
public datagram!: {
|
||||
detail: {
|
||||
id: number
|
||||
projectId: number
|
||||
serverId: number
|
||||
serverName: string
|
||||
serverIP: string
|
||||
serverPort: number
|
||||
serverOwner: string
|
||||
serverPassword: string
|
||||
serverPath: string
|
||||
serverDescription: string
|
||||
insertTime: string
|
||||
updateTime: string
|
||||
}
|
||||
}
|
||||
}
|
||||
export class ProjectServerList extends Request {
|
||||
readonly url = '/project/getBindServerList'
|
||||
readonly method = 'get'
|
||||
public param: ID
|
||||
public datagram!: {
|
||||
list: ProjectServerData['datagram']['detail'][]
|
||||
}
|
||||
constructor(param: ProjectServerList['param']) {
|
||||
super()
|
||||
this.param = param
|
||||
}
|
||||
}
|
||||
|
||||
export class ProjectServerAdd extends Request {
|
||||
readonly url = '/project/addServer'
|
||||
readonly method = 'post'
|
||||
public param: {
|
||||
projectId: number
|
||||
serverIds: number[]
|
||||
}
|
||||
constructor(param: ProjectServerAdd['param']) {
|
||||
super()
|
||||
this.param = param
|
||||
}
|
||||
}
|
||||
|
||||
export class ProjectServerRemove extends Request {
|
||||
readonly url = '/project/removeServer'
|
||||
readonly method = 'delete'
|
||||
public param: {
|
||||
projectServerId: number
|
||||
}
|
||||
constructor(param: ProjectServerRemove['param']) {
|
||||
super()
|
||||
this.param = param
|
||||
}
|
||||
}
|
||||
|
||||
export class ProjectUserData {
|
||||
public datagram!: {
|
||||
detail: {
|
||||
id: number
|
||||
namespaceId: number
|
||||
projectId: number
|
||||
projectName: string
|
||||
userId: number
|
||||
userName: string
|
||||
role: string
|
||||
insertTime: string
|
||||
updateTime: string
|
||||
}
|
||||
}
|
||||
}
|
||||
export class ProjectUserList extends Request {
|
||||
readonly url = '/project/getBindUserList'
|
||||
readonly method = 'get'
|
||||
public param: ID
|
||||
public datagram!: {
|
||||
list: ProjectUserData['datagram']['detail'][]
|
||||
}
|
||||
constructor(param: ProjectUserList['param']) {
|
||||
super()
|
||||
this.param = param
|
||||
}
|
||||
}
|
||||
|
||||
export class ProjectUserAdd extends Request {
|
||||
readonly url = '/project/addUser'
|
||||
readonly method = 'post'
|
||||
public param: {
|
||||
projectId: number
|
||||
userIds: number[]
|
||||
}
|
||||
constructor(param: ProjectUserAdd['param']) {
|
||||
super()
|
||||
this.param = param
|
||||
}
|
||||
}
|
||||
|
||||
export class ProjectUserRemove extends Request {
|
||||
readonly url = '/project/removeUser'
|
||||
readonly method = 'delete'
|
||||
public param: {
|
||||
projectUserId: number
|
||||
}
|
||||
constructor(param: ProjectUserRemove['param']) {
|
||||
super()
|
||||
this.param = param
|
||||
}
|
||||
}
|
||||
|
||||
export class ProjectFileData {
|
||||
public datagram!: {
|
||||
detail: {
|
||||
id: number
|
||||
projectId: number
|
||||
filename: string
|
||||
insertTime: string
|
||||
updateTime: string
|
||||
}
|
||||
}
|
||||
}
|
||||
export class ProjectFileList extends Request {
|
||||
readonly url = '/project/getProjectFileList'
|
||||
readonly method = 'get'
|
||||
public param: ID
|
||||
public datagram!: {
|
||||
list: ProjectFileData['datagram']['detail'][]
|
||||
}
|
||||
constructor(param: ProjectUserList['param']) {
|
||||
super()
|
||||
this.param = param
|
||||
}
|
||||
}
|
||||
|
||||
export class ProjectFileContent extends Request {
|
||||
readonly url = '/project/getProjectFileContent'
|
||||
readonly method = 'get'
|
||||
public param: ID
|
||||
public datagram!: {
|
||||
content: string
|
||||
}
|
||||
constructor(param: ProjectUserList['param']) {
|
||||
super()
|
||||
this.param = param
|
||||
}
|
||||
}
|
||||
|
||||
export class ProjectFileAdd extends Request {
|
||||
readonly url = '/project/addFile'
|
||||
readonly method = 'post'
|
||||
public param: {
|
||||
projectId: number
|
||||
content: string
|
||||
filename: string
|
||||
}
|
||||
public datagram!: ID
|
||||
constructor(param: ProjectFileAdd['param']) {
|
||||
super()
|
||||
this.param = param
|
||||
}
|
||||
}
|
||||
|
||||
export class ProjectFileEdit extends Request {
|
||||
readonly url = '/project/editFile'
|
||||
readonly method = 'put'
|
||||
public param: {
|
||||
id: number
|
||||
content: string
|
||||
}
|
||||
constructor(param: ProjectFileEdit['param']) {
|
||||
super()
|
||||
this.param = param
|
||||
}
|
||||
}
|
||||
|
||||
export class ProjectFileRemove extends Request {
|
||||
readonly url = '/project/removeFile'
|
||||
readonly method = 'delete'
|
||||
public param: {
|
||||
projectFileId: number
|
||||
}
|
||||
constructor(param: ProjectFileRemove['param']) {
|
||||
super()
|
||||
this.param = param
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {Promise}
|
||||
@ -34,54 +221,6 @@ export function getRemoteBranchList(url) {
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {id} id
|
||||
* @return {Promise}
|
||||
*/
|
||||
export function getBindServerList(id) {
|
||||
return Axios.request({
|
||||
url: '/project/getBindServerList',
|
||||
method: 'get',
|
||||
params: { id },
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {id} id
|
||||
* @return {Promise}
|
||||
*/
|
||||
export function getBindUserList(id) {
|
||||
return Axios.request({
|
||||
url: '/project/getBindUserList',
|
||||
method: 'get',
|
||||
params: { id },
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {id} id
|
||||
* @return {Promise}
|
||||
*/
|
||||
export function getProjectFileList(id) {
|
||||
return Axios.request({
|
||||
url: '/project/getProjectFileList',
|
||||
method: 'get',
|
||||
params: { id },
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {id} id
|
||||
* @return {Promise}
|
||||
*/
|
||||
export function getProjectFileContent(id) {
|
||||
return Axios.request({
|
||||
url: '/project/getProjectFileContent',
|
||||
method: 'get',
|
||||
params: { id },
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} project
|
||||
* @param {string} owner
|
||||
@ -128,68 +267,6 @@ export function remove(id) {
|
||||
})
|
||||
}
|
||||
|
||||
export function addUser(data) {
|
||||
return Axios.request({
|
||||
url: '/project/addUser',
|
||||
method: 'post',
|
||||
data,
|
||||
})
|
||||
}
|
||||
|
||||
export function removeUser(projectUserId) {
|
||||
return Axios.request({
|
||||
url: '/project/removeUser',
|
||||
method: 'delete',
|
||||
data: {
|
||||
projectUserId,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
export function addServer(data) {
|
||||
return Axios.request({
|
||||
url: '/project/addServer',
|
||||
method: 'post',
|
||||
data,
|
||||
})
|
||||
}
|
||||
|
||||
export function removeServer(projectServerId) {
|
||||
return Axios.request({
|
||||
url: '/project/removeServer',
|
||||
method: 'delete',
|
||||
data: {
|
||||
projectServerId,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
export function addFile(data) {
|
||||
return Axios.request({
|
||||
url: '/project/addFile',
|
||||
method: 'post',
|
||||
data,
|
||||
})
|
||||
}
|
||||
|
||||
export function editFile(data) {
|
||||
return Axios.request({
|
||||
url: '/project/editFile',
|
||||
method: 'put',
|
||||
data,
|
||||
})
|
||||
}
|
||||
|
||||
export function removeFile(projectFileId) {
|
||||
return Axios.request({
|
||||
url: '/project/removeFile',
|
||||
method: 'delete',
|
||||
data: {
|
||||
projectFileId,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
export function addTask(data) {
|
||||
return Axios.request({
|
||||
url: '/project/addTask',
|
||||
|
@ -136,7 +136,7 @@ export const asyncRoutes: RouteRecordRaw[] = [
|
||||
{
|
||||
path: 'index',
|
||||
name: 'ProjectIndex',
|
||||
component: () => import('@/views/project/index.vue'),
|
||||
component: () => import('@/views/project/manage/index.vue'),
|
||||
meta: {
|
||||
title: 'project',
|
||||
icon: 'project',
|
||||
|
@ -1,5 +1,9 @@
|
||||
<template>
|
||||
<el-dialog v-model="dialogVisible" :title="$t('manage')">
|
||||
<el-dialog
|
||||
v-model="dialogVisible"
|
||||
:title="$t('manage')"
|
||||
:close-on-click-modal="false"
|
||||
>
|
||||
<el-row class="app-bar" type="flex" justify="end">
|
||||
<el-button type="primary" icon="el-icon-plus" @click="handleAdd" />
|
||||
<el-row
|
||||
|
343
web+/src/views/project/manage/TheFileDialog.vue
Normal file
343
web+/src/views/project/manage/TheFileDialog.vue
Normal file
@ -0,0 +1,343 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
v-model="dialogVisible"
|
||||
:title="$t('manage')"
|
||||
custom-class="file-dialog"
|
||||
:close-on-click-modal="false"
|
||||
>
|
||||
<el-row
|
||||
v-if="formProps.show === 'file-list'"
|
||||
type="flex"
|
||||
justify="space-between"
|
||||
align="middle"
|
||||
style="margin: 10px 0"
|
||||
>
|
||||
<span>{{ $t('projectPage.projectFileTips') }}</span>
|
||||
<el-button type="primary" icon="el-icon-plus" @click="handleAppendFile" />
|
||||
</el-row>
|
||||
<el-form ref="fileForm" :model="formData" class="file-form" @submit.prevent>
|
||||
<template v-if="formProps.show === 'file-list'">
|
||||
<el-form-item
|
||||
v-for="(file, index) in formData.files"
|
||||
:key="index"
|
||||
label-width="0"
|
||||
prop="directory"
|
||||
>
|
||||
<el-row type="flex">
|
||||
<el-input
|
||||
v-model.trim="file.filename"
|
||||
autocomplete="off"
|
||||
placeholder="path/to/example/.env"
|
||||
:disabled="file.state === 'success'"
|
||||
:readonly="file.state === 'success'"
|
||||
style="flex: 1"
|
||||
>
|
||||
<template #prepend>{{ formProps.projectPath }}</template>
|
||||
<template v-if="file.state === 'success'" #suffix>
|
||||
<i
|
||||
class="el-input__icon el-icon-check"
|
||||
style="color: #67c23a; font-size: 16px; font-weight: 900"
|
||||
/>
|
||||
</template>
|
||||
<template v-else-if="file.state === 'loading'" #suffix>
|
||||
<i
|
||||
class="el-input__icon el-icon-loading"
|
||||
style="font-size: 14px; font-weight: 900"
|
||||
/>
|
||||
</template>
|
||||
<template v-else #suffix>
|
||||
<i
|
||||
class="el-input__icon el-icon-close"
|
||||
style="color: #f56c6c; font-size: 16px; font-weight: 900"
|
||||
/>
|
||||
</template>
|
||||
</el-input>
|
||||
<el-upload
|
||||
ref="upload"
|
||||
style="margin: 0 12px"
|
||||
:action="`${formProps.action}?projectFileId=${file.id}&projectId=${file.projectId}&filename=${file.filename}`"
|
||||
:before-upload="(uploadFile) => beforeUpload(uploadFile, index)"
|
||||
:on-success="
|
||||
(response, uploadFile, uploadFileList) =>
|
||||
handleUploadSuccess(
|
||||
response,
|
||||
uploadFile,
|
||||
uploadFileList,
|
||||
index
|
||||
)
|
||||
"
|
||||
:show-file-list="false"
|
||||
:disabled="!validateFilename(file, index)"
|
||||
multiple
|
||||
>
|
||||
<el-button
|
||||
:disabled="!validateFilename(file, index)"
|
||||
type="text"
|
||||
icon="el-icon-upload"
|
||||
/>
|
||||
</el-upload>
|
||||
<el-button
|
||||
:disabled="!validateFilename(file, index)"
|
||||
type="text"
|
||||
icon="el-icon-edit"
|
||||
@click="getProjectFileContent(file, index)"
|
||||
/>
|
||||
<el-button
|
||||
type="text"
|
||||
icon="el-icon-delete"
|
||||
@click="removeFile(index)"
|
||||
/>
|
||||
</el-row>
|
||||
</el-form-item>
|
||||
</template>
|
||||
<el-form-item
|
||||
v-else
|
||||
v-loading="formProps.editContentLoading"
|
||||
prop="projectFileEdit"
|
||||
label-width="0px"
|
||||
>
|
||||
<v-ace-editor
|
||||
v-model:value="formData.content"
|
||||
lang="sh"
|
||||
theme="github"
|
||||
style="height: 500px"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template v-if="formProps.show !== 'file-list'" #footer>
|
||||
<el-button @click="formProps.show = 'file-list'">
|
||||
{{ $t('cancel') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
:disabled="formProps.disabled"
|
||||
type="primary"
|
||||
@click="fileSubmit"
|
||||
>
|
||||
{{ $t('confirm') }}
|
||||
</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import {
|
||||
ProjectFileList,
|
||||
ProjectFileContent,
|
||||
ProjectFileAdd,
|
||||
ProjectFileEdit,
|
||||
ProjectFileRemove,
|
||||
} from '@/api/project'
|
||||
import { VAceEditor } from 'vue3-ace-editor'
|
||||
import { role } from '@/utils/namespace'
|
||||
import { ElMessageBox, ElMessage } from 'element-plus'
|
||||
import { computed, watch, defineComponent, reactive } from 'vue'
|
||||
import { HttpResponse, ID } from '@/api/types'
|
||||
|
||||
interface FormFileInfo {
|
||||
id: number
|
||||
projectId: number
|
||||
filename: string
|
||||
content: string
|
||||
state: string
|
||||
}
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
VAceEditor,
|
||||
},
|
||||
props: {
|
||||
modelValue: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
projectId: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
},
|
||||
emits: ['update:modelValue'],
|
||||
setup(props, { emit }) {
|
||||
const dialogVisible = computed({
|
||||
get: () => props.modelValue,
|
||||
set: (val) => {
|
||||
emit('update:modelValue', val)
|
||||
},
|
||||
})
|
||||
const formData = reactive({
|
||||
files: [] as FormFileInfo[],
|
||||
content: '',
|
||||
projectId: 0,
|
||||
})
|
||||
const getProjectFileList = (projectId: number) => {
|
||||
new ProjectFileList({ id: projectId }).request().then((response) => {
|
||||
formData.files = response.data.list.map((item) => {
|
||||
return { ...item, state: 'success', content: '' }
|
||||
})
|
||||
})
|
||||
}
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
(val: typeof props['modelValue']) => {
|
||||
if (val === true) {
|
||||
getProjectFileList(props.projectId)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
return {
|
||||
role,
|
||||
dialogVisible,
|
||||
getProjectFileList,
|
||||
formData,
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
formProps: {
|
||||
projectPath: '/data/www/goploy/',
|
||||
action: import.meta.env.VITE_APP_BASE_API + '/project/uploadFile',
|
||||
show: 'file-list',
|
||||
editContentLoading: false,
|
||||
disabled: false,
|
||||
selectedIndex: -1,
|
||||
},
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
projectId: function (newVal) {
|
||||
this.formData.projectId = newVal
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
getProjectFileContent(file: FormFileInfo, index: number) {
|
||||
this.formProps.selectedIndex = index
|
||||
this.formProps.show = 'edit-content'
|
||||
if (file.id === 0) {
|
||||
this.formData.content = this.formData.files[index]['content']
|
||||
return
|
||||
}
|
||||
this.formData.content = ''
|
||||
this.formProps.editContentLoading = true
|
||||
new ProjectFileContent({ id: file.id })
|
||||
.request()
|
||||
.then((response) => {
|
||||
this.formData.content = this.formData.files[index]['content'] =
|
||||
response.data.content
|
||||
})
|
||||
.finally(() => {
|
||||
this.formProps.editContentLoading = false
|
||||
})
|
||||
},
|
||||
handleAppendFile() {
|
||||
this.formData.files.push({
|
||||
filename: '',
|
||||
projectId: this.projectId,
|
||||
state: 'loading',
|
||||
content: '',
|
||||
id: 0,
|
||||
})
|
||||
},
|
||||
beforeUpload(file: File, index: number) {
|
||||
this.formData.files[index].state = 'loading'
|
||||
ElMessage.info(this.$t('uploading'))
|
||||
},
|
||||
|
||||
handleUploadSuccess(
|
||||
response: HttpResponse<ID>,
|
||||
file: File,
|
||||
fileList: File[],
|
||||
index: number
|
||||
) {
|
||||
if (response.code !== 0) {
|
||||
this.formData.files[index].state = 'fail'
|
||||
ElMessage.error(response.message)
|
||||
} else {
|
||||
this.formData.files[index].id = response.data.id
|
||||
this.formData.files[index].state = 'success'
|
||||
ElMessage.success('Success')
|
||||
}
|
||||
},
|
||||
validateFilename(file: FormFileInfo, index: number) {
|
||||
const filename = file.filename
|
||||
if (file.state === 'success') {
|
||||
return true
|
||||
} else if (filename === '') {
|
||||
return false
|
||||
} else if (filename.substr(filename.length - 1, 1) === '/') {
|
||||
return false
|
||||
}
|
||||
const filenames = this.formData.files.map((item) => item.filename)
|
||||
filenames.splice(index, 1)
|
||||
return filenames.indexOf(filename) === -1
|
||||
},
|
||||
|
||||
fileSubmit() {
|
||||
const file = this.formData.files[this.formProps.selectedIndex]
|
||||
this.formProps.disabled = true
|
||||
if (file.id === 0) {
|
||||
new ProjectFileAdd({
|
||||
projectId: file.projectId,
|
||||
filename: file.filename,
|
||||
content: this.formData.content,
|
||||
})
|
||||
.request()
|
||||
.then((response) => {
|
||||
this.formData.files[this.formProps.selectedIndex].id =
|
||||
response.data.id
|
||||
this.formData.files[this.formProps.selectedIndex].state = 'success'
|
||||
this.formProps.show = 'file-list'
|
||||
ElMessage.success('Success')
|
||||
})
|
||||
.finally(() => {
|
||||
this.formProps.disabled = false
|
||||
})
|
||||
} else {
|
||||
new ProjectFileEdit({
|
||||
id: file.id,
|
||||
content: this.formData.content,
|
||||
})
|
||||
.request()
|
||||
.then(() => {
|
||||
this.formData.files[this.formProps.selectedIndex].state = 'success'
|
||||
this.formProps.show = 'file-list'
|
||||
ElMessage.success('Success')
|
||||
})
|
||||
.finally(() => {
|
||||
this.formProps.disabled = false
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
removeFile(index: number) {
|
||||
if (this.formData.files[index].id === 0) {
|
||||
this.formData.files.splice(index, 1)
|
||||
} else {
|
||||
ElMessageBox.confirm(
|
||||
this.$t('projectPage.removeFileTips', {
|
||||
filename: this.formData.files[index].filename,
|
||||
}),
|
||||
this.$t('tips'),
|
||||
{
|
||||
confirmButtonText: this.$t('confirm'),
|
||||
cancelButtonText: this.$t('cancel'),
|
||||
type: 'warning',
|
||||
}
|
||||
)
|
||||
.then(() => {
|
||||
new ProjectFileRemove({
|
||||
projectFileId: this.formData.files[index].id,
|
||||
})
|
||||
.request()
|
||||
.then(() => {
|
||||
ElMessage.success('Success')
|
||||
this.formData.files.splice(index, 1)
|
||||
})
|
||||
})
|
||||
.catch(() => {
|
||||
ElMessage.info('Cancel')
|
||||
})
|
||||
}
|
||||
},
|
||||
},
|
||||
})
|
||||
</script>
|
249
web+/src/views/project/manage/TheServerDialog.vue
Normal file
249
web+/src/views/project/manage/TheServerDialog.vue
Normal file
@ -0,0 +1,249 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
v-model="dialogVisible"
|
||||
:title="$t('manage')"
|
||||
:close-on-click-modal="false"
|
||||
>
|
||||
<el-row class="app-bar" type="flex" justify="end">
|
||||
<el-button type="primary" icon="el-icon-plus" @click="handleAdd" />
|
||||
<el-row
|
||||
v-if="showAddView"
|
||||
type="flex"
|
||||
justify="center"
|
||||
style="margin-top: 10px; width: 100%"
|
||||
>
|
||||
<el-form ref="form" :inline="true" :rules="formRules" :model="formData">
|
||||
<el-form-item
|
||||
:label="$t('server')"
|
||||
label-width="120px"
|
||||
prop="serverIds"
|
||||
>
|
||||
<el-select v-model="formData.serverIds" multiple>
|
||||
<el-option
|
||||
v-for="(item, index) in serverOption"
|
||||
:key="index"
|
||||
:label="item.label"
|
||||
:value="item.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item style="margin-right: 0px; margin-bottom: 5px">
|
||||
<el-button
|
||||
type="primary"
|
||||
:disabled="formProps.disabled"
|
||||
@click="add"
|
||||
>
|
||||
{{ $t('confirm') }}
|
||||
</el-button>
|
||||
<el-button @click="showAddView = false">
|
||||
{{ $t('cancel') }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-row>
|
||||
</el-row>
|
||||
<el-table
|
||||
v-loading="tableLoading"
|
||||
border
|
||||
stripe
|
||||
highlight-current-row
|
||||
:data="tableData"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-table-column prop="serverId" :label="$t('serverId')" width="100" />
|
||||
<el-table-column
|
||||
prop="serverName"
|
||||
:label="$t('serverName')"
|
||||
width="120"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="serverDescription"
|
||||
:label="$t('serverDescription')"
|
||||
min-width="200"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
prop="insertTime"
|
||||
:label="$t('insertTime')"
|
||||
width="160"
|
||||
align="center"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="updateTime"
|
||||
:label="$t('updateTime')"
|
||||
width="160"
|
||||
align="center"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="operation"
|
||||
:label="$t('op')"
|
||||
width="80"
|
||||
align="center"
|
||||
>
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
type="danger"
|
||||
icon="el-icon-delete"
|
||||
@click="remove(scope.row)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<template #footer>
|
||||
<el-button @click="dialogVisible = false">
|
||||
{{ $t('cancel') }}
|
||||
</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import {
|
||||
ProjectServerData,
|
||||
ProjectServerList,
|
||||
ProjectServerAdd,
|
||||
ProjectServerRemove,
|
||||
} from '@/api/project'
|
||||
import { ServerOption } from '@/api/server'
|
||||
import Validator from 'async-validator'
|
||||
import { ElMessageBox, ElMessage } from 'element-plus'
|
||||
import { computed, watch, defineComponent, ref, Ref } from 'vue'
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
modelValue: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
projectId: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
},
|
||||
emits: ['update:modelValue'],
|
||||
setup(props, { emit }) {
|
||||
const tableData: Ref<ProjectServerList['datagram']['list']> = ref([])
|
||||
const dialogVisible = computed({
|
||||
get: () => props.modelValue,
|
||||
set: (val) => {
|
||||
emit('update:modelValue', val)
|
||||
},
|
||||
})
|
||||
const tableLoading = ref(false)
|
||||
const getBindServerList = (projectId: number) => {
|
||||
tableLoading.value = true
|
||||
new ProjectServerList({ id: projectId })
|
||||
.request()
|
||||
.then((response) => {
|
||||
tableData.value = response.data.list
|
||||
})
|
||||
.finally(() => {
|
||||
tableLoading.value = false
|
||||
})
|
||||
}
|
||||
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
(val: typeof props['modelValue']) => {
|
||||
if (val === true) {
|
||||
getBindServerList(props.projectId)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
const showAddView = ref(false)
|
||||
const handleAdd = () => {
|
||||
showAddView.value = true
|
||||
}
|
||||
const serverOption: Ref<ServerOption['datagram']['list']> = ref([])
|
||||
watch(showAddView, (val: boolean) => {
|
||||
if (val === true) {
|
||||
new ServerOption().request().then((response) => {
|
||||
serverOption.value = response.data.list
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
return {
|
||||
dialogVisible,
|
||||
getBindServerList,
|
||||
tableLoading,
|
||||
tableData,
|
||||
showAddView,
|
||||
handleAdd,
|
||||
serverOption,
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
formProps: {
|
||||
disabled: false,
|
||||
},
|
||||
formData: {
|
||||
projectId: 0,
|
||||
serverIds: [],
|
||||
},
|
||||
formRules: {
|
||||
serverIds: [
|
||||
{
|
||||
type: 'array',
|
||||
required: true,
|
||||
message: 'Server required',
|
||||
trigger: 'change',
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
projectId: function (newVal) {
|
||||
this.formData.projectId = newVal
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
add() {
|
||||
;(this.$refs.form as Validator).validate((valid: boolean) => {
|
||||
if (valid) {
|
||||
this.formProps.disabled = true
|
||||
new ProjectServerAdd(this.formData)
|
||||
.request()
|
||||
.then(() => {
|
||||
ElMessage.success('Success')
|
||||
this.getBindServerList(this.formData.projectId)
|
||||
})
|
||||
.finally(() => {
|
||||
this.formProps.disabled = false
|
||||
})
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
remove(data: ProjectServerData['datagram']['detail']) {
|
||||
ElMessageBox.confirm(
|
||||
this.$t('crontabPage.removeCrontabServerTips'),
|
||||
this.$t('tips'),
|
||||
{
|
||||
confirmButtonText: this.$t('confirm'),
|
||||
cancelButtonText: this.$t('cancel'),
|
||||
type: 'warning',
|
||||
}
|
||||
)
|
||||
.then(() => {
|
||||
new ProjectServerRemove({
|
||||
projectServerId: data.id,
|
||||
})
|
||||
.request()
|
||||
.then(() => {
|
||||
ElMessage.success('Success')
|
||||
this.getBindServerList(data.projectId)
|
||||
})
|
||||
})
|
||||
.catch(() => {
|
||||
ElMessage.info('Cancel')
|
||||
})
|
||||
},
|
||||
},
|
||||
})
|
||||
</script>
|
259
web+/src/views/project/manage/TheUserDialog.vue
Normal file
259
web+/src/views/project/manage/TheUserDialog.vue
Normal file
@ -0,0 +1,259 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
v-model="dialogVisible"
|
||||
:title="$t('manage')"
|
||||
:close-on-click-modal="false"
|
||||
>
|
||||
<el-row class="app-bar" type="flex" justify="end">
|
||||
<el-button type="primary" icon="el-icon-plus" @click="handleAdd" />
|
||||
<el-row
|
||||
v-if="showAddView"
|
||||
type="flex"
|
||||
justify="center"
|
||||
style="margin-top: 10px; width: 100%"
|
||||
>
|
||||
<el-form ref="form" :inline="true" :rules="formRules" :model="formData">
|
||||
<el-form-item
|
||||
:label="$t('user')"
|
||||
label-width="60px"
|
||||
prop="userIds"
|
||||
style="margin-bottom: 5px"
|
||||
>
|
||||
<el-select
|
||||
v-model="formData.userIds"
|
||||
:loading="userLoading"
|
||||
multiple
|
||||
clearable
|
||||
filterable
|
||||
>
|
||||
<el-option
|
||||
v-for="(item, index) in userOption.filter(
|
||||
(item) => [role.Admin, role.Manager].indexOf(item.role) === -1
|
||||
)"
|
||||
:key="index"
|
||||
:label="item.userName"
|
||||
:value="item.userId"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item style="margin-right: 0px; margin-bottom: 5px">
|
||||
<el-button
|
||||
type="primary"
|
||||
:disabled="formProps.disabled"
|
||||
@click="add"
|
||||
>
|
||||
{{ $t('confirm') }}
|
||||
</el-button>
|
||||
<el-button @click="showAddView = false">
|
||||
{{ $t('cancel') }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-row>
|
||||
</el-row>
|
||||
<el-table
|
||||
v-loading="tableLoading"
|
||||
border
|
||||
stripe
|
||||
highlight-current-row
|
||||
:data="tableData"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-table-column prop="userId" :label="$t('userId')" width="100" />
|
||||
<el-table-column prop="userName" :label="$t('userName')" />
|
||||
<el-table-column
|
||||
prop="insertTime"
|
||||
:label="$t('insertTime')"
|
||||
width="135"
|
||||
align="center"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="updateTime"
|
||||
:label="$t('updateTime')"
|
||||
width="135"
|
||||
align="center"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="operation"
|
||||
:label="$t('op')"
|
||||
width="80"
|
||||
align="center"
|
||||
fixed="right"
|
||||
>
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
v-show="role.hasManagerPermission()"
|
||||
type="danger"
|
||||
icon="el-icon-delete"
|
||||
@click="remove(scope.row)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<template #footer>
|
||||
<el-button @click="dialogVisible = false">
|
||||
{{ $t('cancel') }}
|
||||
</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import {
|
||||
ProjectUserData,
|
||||
ProjectUserList,
|
||||
ProjectUserAdd,
|
||||
ProjectUserRemove,
|
||||
} from '@/api/project'
|
||||
import { NamespaceUserOption } from '@/api/namespace'
|
||||
import { role } from '@/utils/namespace'
|
||||
import Validator from 'async-validator'
|
||||
import { ElMessageBox, ElMessage } from 'element-plus'
|
||||
import { computed, watch, defineComponent, ref, Ref } from 'vue'
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
modelValue: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
projectId: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
},
|
||||
emits: ['update:modelValue'],
|
||||
setup(props, { emit }) {
|
||||
let tableData: Ref<ProjectUserList['datagram']['list']> = ref([])
|
||||
const dialogVisible = computed({
|
||||
get: () => props.modelValue,
|
||||
set: (val) => {
|
||||
emit('update:modelValue', val)
|
||||
},
|
||||
})
|
||||
let tableLoading = ref(false)
|
||||
const getBindUserList = (projectId: number) => {
|
||||
tableLoading.value = true
|
||||
new ProjectUserList({ id: projectId })
|
||||
.request()
|
||||
.then((response) => {
|
||||
tableData.value = response.data.list
|
||||
})
|
||||
.finally(() => {
|
||||
tableLoading.value = false
|
||||
})
|
||||
}
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
(val: typeof props['modelValue']) => {
|
||||
if (val === true) {
|
||||
getBindUserList(props.projectId)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
let showAddView = ref(false)
|
||||
const handleAdd = () => {
|
||||
showAddView.value = true
|
||||
}
|
||||
const userLoading = ref(false)
|
||||
let userOption: Ref<NamespaceUserOption['datagram']['list']> = ref([])
|
||||
watch(showAddView, (val: boolean) => {
|
||||
if (val === true) {
|
||||
userLoading.value = true
|
||||
new NamespaceUserOption()
|
||||
.request()
|
||||
.then((response) => {
|
||||
userOption.value = response.data.list
|
||||
})
|
||||
.finally(() => {
|
||||
userLoading.value = false
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
return {
|
||||
role,
|
||||
dialogVisible,
|
||||
getBindUserList,
|
||||
tableLoading,
|
||||
tableData,
|
||||
showAddView,
|
||||
handleAdd,
|
||||
userLoading,
|
||||
userOption,
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
formProps: {
|
||||
disabled: false,
|
||||
},
|
||||
formData: {
|
||||
projectId: 0,
|
||||
userIds: [],
|
||||
},
|
||||
formRules: {
|
||||
userIds: [
|
||||
{
|
||||
type: 'array',
|
||||
required: true,
|
||||
message: 'User required',
|
||||
trigger: 'change',
|
||||
},
|
||||
],
|
||||
role: [{ required: true, message: 'Role required', trigger: 'change' }],
|
||||
},
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
projectId: function (newVal) {
|
||||
this.formData.projectId = newVal
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
add() {
|
||||
;(this.$refs.form as Validator).validate((valid: boolean) => {
|
||||
if (valid) {
|
||||
this.formProps.disabled = true
|
||||
new ProjectUserAdd(this.formData)
|
||||
.request()
|
||||
.then(() => {
|
||||
this.showAddView = false
|
||||
ElMessage.success('Success')
|
||||
this.getBindUserList(this.formData.projectId)
|
||||
})
|
||||
.finally(() => {
|
||||
this.formProps.disabled = false
|
||||
})
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
remove(data: ProjectUserData['datagram']['detail']) {
|
||||
ElMessageBox.confirm(
|
||||
this.$t('namespacePage.removeUserTips'),
|
||||
this.$t('tips'),
|
||||
{
|
||||
confirmButtonText: this.$t('confirm'),
|
||||
cancelButtonText: this.$t('cancel'),
|
||||
type: 'warning',
|
||||
}
|
||||
)
|
||||
.then(() => {
|
||||
new ProjectUserRemove({ projectUserId: data.id })
|
||||
.request()
|
||||
.then(() => {
|
||||
ElMessage.success('Success')
|
||||
this.getBindUserList(data.projectId)
|
||||
})
|
||||
})
|
||||
.catch(() => {
|
||||
ElMessage.info('Cancel')
|
||||
})
|
||||
},
|
||||
},
|
||||
})
|
||||
</script>
|
@ -568,332 +568,30 @@
|
||||
</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
<el-dialog v-model="dialogServerVisible" :title="$t('manage')">
|
||||
<el-row class="app-bar" type="flex" justify="end">
|
||||
<el-button
|
||||
type="primary"
|
||||
icon="el-icon-plus"
|
||||
@click="handleAddServer"
|
||||
<TheServerDialog
|
||||
v-model="dialogServerVisible"
|
||||
:project-id="selectedItem.id"
|
||||
/>
|
||||
</el-row>
|
||||
<el-table
|
||||
border
|
||||
stripe
|
||||
highlight-current-row
|
||||
:data="tableServerData"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-table-column prop="serverId" :label="$t('serverId')" width="100" />
|
||||
<el-table-column
|
||||
prop="serverName"
|
||||
:label="$t('serverName')"
|
||||
min-width="120"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="serverDescription"
|
||||
:label="$t('serverDescription')"
|
||||
min-width="200"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
prop="insertTime"
|
||||
:label="$t('insertTime')"
|
||||
width="135"
|
||||
align="center"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="updateTime"
|
||||
:label="$t('updateTime')"
|
||||
width="135"
|
||||
align="center"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="operation"
|
||||
:label="$t('op')"
|
||||
width="80"
|
||||
align="center"
|
||||
fixed="right"
|
||||
>
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
type="danger"
|
||||
icon="el-icon-delete"
|
||||
@click="removeServer(scope.row)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<template #footer class="dialog-footer">
|
||||
<el-button @click="dialogServerVisible = false">
|
||||
{{ $t('cancel') }}
|
||||
</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
<el-dialog v-model="dialogUserVisible" :title="$t('manage')">
|
||||
<el-row class="app-bar" type="flex" justify="end">
|
||||
<el-button type="primary" icon="el-icon-plus" @click="handleAddUser" />
|
||||
</el-row>
|
||||
<el-table
|
||||
border
|
||||
stripe
|
||||
highlight-current-row
|
||||
:data="tableUserData"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-table-column prop="userId" :label="$t('userId')" width="100" />
|
||||
<el-table-column prop="userName" :label="$t('userName')" />
|
||||
<el-table-column
|
||||
prop="insertTime"
|
||||
:label="$t('insertTime')"
|
||||
width="135"
|
||||
align="center"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="updateTime"
|
||||
:label="$t('updateTime')"
|
||||
width="135"
|
||||
align="center"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="operation"
|
||||
:label="$t('op')"
|
||||
width="80"
|
||||
align="center"
|
||||
fixed="right"
|
||||
>
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
v-show="role.hasManagerPermission()"
|
||||
type="danger"
|
||||
icon="el-icon-delete"
|
||||
@click="removeUser(scope.row)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<template #footer class="dialog-footer">
|
||||
<el-button @click="dialogUserVisible = false">
|
||||
{{ $t('cancel') }}
|
||||
</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
<el-dialog
|
||||
<TheUserDialog v-model="dialogUserVisible" :project-id="selectedItem.id" />
|
||||
<TheFileDialog
|
||||
v-model="dialogFileManagerVisible"
|
||||
:title="$t('manage')"
|
||||
custom-class="file-dialog"
|
||||
>
|
||||
<el-row
|
||||
v-if="fileFormProps.show === 'file-list'"
|
||||
type="flex"
|
||||
justify="space-between"
|
||||
align="middle"
|
||||
style="margin: 10px 0"
|
||||
>
|
||||
<span>{{ $t('projectPage.projectFileTips') }}</span>
|
||||
<el-button
|
||||
type="primary"
|
||||
icon="el-icon-plus"
|
||||
@click="handleAppendFile"
|
||||
:project-id="selectedItem.id"
|
||||
/>
|
||||
</el-row>
|
||||
<el-form
|
||||
ref="fileForm"
|
||||
:rules="fileFormRules"
|
||||
:model="fileFormData"
|
||||
class="file-form"
|
||||
>
|
||||
<template v-if="fileFormProps.show === 'file-list'">
|
||||
<el-form-item
|
||||
v-for="(file, index) in fileFormData.files"
|
||||
:key="index"
|
||||
label-width="0"
|
||||
prop="directory"
|
||||
>
|
||||
<el-row type="flex">
|
||||
<el-input
|
||||
v-model.trim="file.filename"
|
||||
autocomplete="off"
|
||||
placeholder="path/to/example/.env"
|
||||
:disabled="file.state === 'success'"
|
||||
:readonly="file.state === 'success'"
|
||||
>
|
||||
<template #prepend>{{ fileFormProps.projectPath }}</template>
|
||||
<template v-if="file.state === 'success'" #suffix>
|
||||
<i
|
||||
class="el-input__icon el-icon-check"
|
||||
style="color: #67c23a; font-size: 16px; font-weight: 900"
|
||||
/>
|
||||
</template>
|
||||
<template v-else-if="file.state === 'loading'" #suffix>
|
||||
<i
|
||||
class="el-input__icon el-icon-loading"
|
||||
style="font-size: 14px; font-weight: 900"
|
||||
/>
|
||||
</template>
|
||||
<template v-else #suffix>
|
||||
<i
|
||||
class="el-input__icon el-icon-close"
|
||||
style="color: #f56c6c; font-size: 16px; font-weight: 900"
|
||||
/>
|
||||
</template>
|
||||
</el-input>
|
||||
<el-upload
|
||||
ref="upload"
|
||||
style="margin: 0 12px"
|
||||
:action="`${fileFormProps.action}?projectFileId=${file.id}&projectId=${file.projectId}&filename=${file.filename}`"
|
||||
:before-upload="(uploadFile) => beforeUpload(uploadFile, index)"
|
||||
:on-success="
|
||||
(response, uploadFile, uploadFileList) =>
|
||||
handleUploadSuccess(
|
||||
response,
|
||||
uploadFile,
|
||||
uploadFileList,
|
||||
index
|
||||
)
|
||||
"
|
||||
:show-file-list="false"
|
||||
:disabled="!validateFilename(file, index)"
|
||||
multiple
|
||||
>
|
||||
<el-button
|
||||
:disabled="!validateFilename(file, index)"
|
||||
type="text"
|
||||
icon="el-icon-upload"
|
||||
/>
|
||||
</el-upload>
|
||||
<el-button
|
||||
:disabled="!validateFilename(file, index)"
|
||||
type="text"
|
||||
icon="el-icon-edit"
|
||||
@click="getProjectFileContent(file, index)"
|
||||
/>
|
||||
<el-button
|
||||
type="text"
|
||||
icon="el-icon-delete"
|
||||
@click="removeFile(index)"
|
||||
/>
|
||||
</el-row>
|
||||
</el-form-item>
|
||||
</template>
|
||||
<el-form-item v-else prop="projectFileEdit" label-width="0px">
|
||||
<v-ace-editor
|
||||
v-model:value="fileFormData.content"
|
||||
v-loading="fileFormProps.editContentLoading"
|
||||
:lang="getScriptLang()"
|
||||
theme="github"
|
||||
style="height: 500px"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template v-if="fileFormProps.show !== 'file-list'" #footer>
|
||||
<el-button @click="fileFormProps.show = 'file-list'">
|
||||
{{ $t('cancel') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
:disabled="fileFormProps.disabled"
|
||||
type="primary"
|
||||
@click="fileSubmit"
|
||||
>
|
||||
{{ $t('confirm') }}
|
||||
</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
<el-dialog v-model="dialogAddServerVisible" :title="$t('add')">
|
||||
<el-form
|
||||
ref="addServerForm"
|
||||
:rules="addServerFormRules"
|
||||
:model="addServerFormData"
|
||||
>
|
||||
<el-form-item :label="$t('server')" label-width="80px" prop="serverIds">
|
||||
<el-select
|
||||
v-model="addServerFormData.serverIds"
|
||||
multiple
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option
|
||||
v-for="(item, index) in serverOption"
|
||||
:key="index"
|
||||
:label="item.label"
|
||||
:value="item.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="dialogAddServerVisible = false">
|
||||
{{ $t('cancel') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
:disabled="addServerFormProps.disabled"
|
||||
type="primary"
|
||||
@click="addServer"
|
||||
>
|
||||
{{ $t('confirm') }}
|
||||
</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
<el-dialog v-model="dialogAddUserVisible" :title="$t('add')">
|
||||
<el-form
|
||||
ref="addUserForm"
|
||||
:rules="addUserFormRules"
|
||||
:model="addUserFormData"
|
||||
>
|
||||
<el-form-item :label="$t('member')" label-width="80px" prop="userIds">
|
||||
<el-select
|
||||
v-model="addUserFormData.userIds"
|
||||
multiple
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option
|
||||
v-for="(item, index) in userOption.filter(
|
||||
(item) => [role.Admin, role.Manager].indexOf(item.role) === -1
|
||||
)"
|
||||
:key="index"
|
||||
:label="item.userName"
|
||||
:value="item.userId"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="dialogAddUserVisible = false">
|
||||
{{ $t('cancel') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
:disabled="addUserFormProps.disabled"
|
||||
type="primary"
|
||||
@click="addUser"
|
||||
>
|
||||
{{ $t('confirm') }}
|
||||
</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</el-row>
|
||||
</template>
|
||||
<script>
|
||||
import tableHeight from '@/mixin/tableHeight'
|
||||
import { parseGitURL } from '@/utils'
|
||||
import { NamespaceUserOption } from '@/api/namespace'
|
||||
import { getOption as getServerOption } from '@/api/server'
|
||||
import { ServerOption } from '@/api/server'
|
||||
import {
|
||||
getList,
|
||||
getTotal,
|
||||
getBindServerList,
|
||||
getBindUserList,
|
||||
getProjectFileList,
|
||||
getRemoteBranchList,
|
||||
getProjectFileContent,
|
||||
add,
|
||||
edit,
|
||||
remove,
|
||||
addServer,
|
||||
addUser,
|
||||
addFile,
|
||||
editFile,
|
||||
removeFile,
|
||||
setAutoDeploy,
|
||||
removeServer,
|
||||
removeUser,
|
||||
} from '@/api/project'
|
||||
import { role } from '@/utils/namespace'
|
||||
import { VAceEditor } from 'vue3-ace-editor'
|
||||
@ -901,12 +599,17 @@ import 'ace-builds/src-noconflict/mode-sh'
|
||||
import 'ace-builds/src-noconflict/mode-python'
|
||||
import 'ace-builds/src-noconflict/mode-php'
|
||||
import 'ace-builds/src-noconflict/theme-github'
|
||||
|
||||
import TheServerDialog from './TheServerDialog.vue'
|
||||
import TheUserDialog from './TheUserDialog.vue'
|
||||
import TheFileDialog from './TheFileDialog.vue'
|
||||
import { defineComponent } from 'vue'
|
||||
export default defineComponent({
|
||||
name: 'ProjectIndex',
|
||||
components: {
|
||||
VAceEditor,
|
||||
TheServerDialog,
|
||||
TheUserDialog,
|
||||
TheFileDialog,
|
||||
},
|
||||
mixins: [tableHeight],
|
||||
data() {
|
||||
@ -933,8 +636,6 @@ export default defineComponent({
|
||||
dialogAutoDeployVisible: false,
|
||||
dialogServerVisible: false,
|
||||
dialogUserVisible: false,
|
||||
dialogAddServerVisible: false,
|
||||
dialogAddUserVisible: false,
|
||||
dialogFileManagerVisible: false,
|
||||
serverOption: [],
|
||||
userOption: [],
|
||||
@ -946,8 +647,6 @@ export default defineComponent({
|
||||
rows: 16,
|
||||
total: 0,
|
||||
},
|
||||
tableServerData: [],
|
||||
tableUserData: [],
|
||||
formProps: {
|
||||
reviewURLParamOption: [
|
||||
{
|
||||
@ -1048,53 +747,6 @@ export default defineComponent({
|
||||
id: 0,
|
||||
autoDeploy: 0,
|
||||
},
|
||||
fileFormProps: {
|
||||
projectPath: '/data/www/goploy/',
|
||||
action: import.meta.env.VITE_APP_BASE_API + '/project/uploadFile',
|
||||
show: 'file-list',
|
||||
editContentLoading: false,
|
||||
disabled: false,
|
||||
selectedIndex: -1,
|
||||
},
|
||||
fileFormData: {
|
||||
files: [],
|
||||
content: '',
|
||||
},
|
||||
fileFormRules: {},
|
||||
addServerFormProps: {
|
||||
disabled: false,
|
||||
},
|
||||
addServerFormData: {
|
||||
projectId: 0,
|
||||
serverIds: [],
|
||||
},
|
||||
addServerFormRules: {
|
||||
serverIds: [
|
||||
{
|
||||
type: 'array',
|
||||
required: true,
|
||||
message: 'Server required',
|
||||
trigger: 'change',
|
||||
},
|
||||
],
|
||||
},
|
||||
addUserFormProps: {
|
||||
disabled: false,
|
||||
},
|
||||
addUserFormData: {
|
||||
projectId: 0,
|
||||
userIds: [],
|
||||
},
|
||||
addUserFormRules: {
|
||||
userIds: [
|
||||
{
|
||||
type: 'array',
|
||||
required: true,
|
||||
message: 'User required',
|
||||
trigger: 'change',
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
},
|
||||
created() {
|
||||
@ -1182,71 +834,20 @@ export default defineComponent({
|
||||
},
|
||||
|
||||
handleServer(data) {
|
||||
this.getBindServerList(data.id)
|
||||
// 先把projectID写入添加服务器的表单
|
||||
this.addServerFormData.projectId = data.id
|
||||
this.selectedItem = data
|
||||
this.dialogServerVisible = true
|
||||
},
|
||||
|
||||
handleUser(data) {
|
||||
this.getBindUserList(data.id)
|
||||
// 先把projectID写入添加用户的表单
|
||||
this.addUserFormData.projectId = data.id
|
||||
this.selectedItem = data
|
||||
this.dialogUserVisible = true
|
||||
},
|
||||
|
||||
handleAddServer() {
|
||||
this.dialogAddServerVisible = true
|
||||
},
|
||||
|
||||
handleAddUser() {
|
||||
this.dialogAddUserVisible = true
|
||||
},
|
||||
|
||||
handleFile(data) {
|
||||
this.getProjectFileList(data.id)
|
||||
this.selectedItem = data
|
||||
this.dialogFileManagerVisible = true
|
||||
},
|
||||
|
||||
handleAppendFile() {
|
||||
this.fileFormData.files.push({
|
||||
filename: '',
|
||||
projectId: this.selectedItem.id,
|
||||
state: 'loading',
|
||||
id: 0,
|
||||
})
|
||||
},
|
||||
|
||||
validateFilename(file, index) {
|
||||
const filename = file.filename
|
||||
if (file.state === 'success') {
|
||||
return true
|
||||
} else if (filename === '') {
|
||||
return false
|
||||
} else if (filename.substr(filename.length - 1, 1) === '/') {
|
||||
return false
|
||||
}
|
||||
const filenames = this.fileFormData.files.map((item) => item.filename)
|
||||
filenames.splice(index, 1)
|
||||
return filenames.indexOf(filename) === -1
|
||||
},
|
||||
|
||||
beforeUpload(file, index) {
|
||||
this.fileFormData.files[index].state = 'loading'
|
||||
this.$message.info(this.$i18n.t('uploading'))
|
||||
},
|
||||
|
||||
handleUploadSuccess(response, file, fileList, index) {
|
||||
if (response.code !== 0) {
|
||||
this.fileFormData.files[index].state = 'fail'
|
||||
this.$message.error(response.message)
|
||||
} else {
|
||||
this.fileFormData.files[index].id = response.data.id
|
||||
this.fileFormData.files[index].state = 'success'
|
||||
this.$message.success('Success')
|
||||
}
|
||||
},
|
||||
submit() {
|
||||
this.$refs.form.validate((valid) => {
|
||||
if (valid) {
|
||||
@ -1322,154 +923,8 @@ export default defineComponent({
|
||||
})
|
||||
},
|
||||
|
||||
addServer() {
|
||||
this.$refs.addServerForm.validate((valid) => {
|
||||
if (valid) {
|
||||
this.addServerFormProps.disabled = true
|
||||
addServer(this.addServerFormData)
|
||||
.then(() => {
|
||||
this.dialogAddServerVisible = false
|
||||
this.$message.success('Success')
|
||||
this.getBindServerList(this.addServerFormData.projectId)
|
||||
})
|
||||
.finally(() => {
|
||||
this.addServerFormProps.disabled = false
|
||||
})
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
addUser() {
|
||||
this.$refs.addUserForm.validate((valid) => {
|
||||
if (valid) {
|
||||
this.addUserFormProps.disabled = true
|
||||
addUser(this.addUserFormData)
|
||||
.then(() => {
|
||||
this.dialogAddUserVisible = false
|
||||
this.$message.success('Success')
|
||||
this.getBindUserList(this.addUserFormData.projectId)
|
||||
})
|
||||
.finally(() => {
|
||||
this.addUserFormProps.disabled = false
|
||||
})
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
removeServer(data) {
|
||||
this.$confirm(
|
||||
this.$i18n.t('projectPage.removeServerTips', {
|
||||
serverName: data.serverName,
|
||||
}),
|
||||
this.$i18n.t('tips'),
|
||||
{
|
||||
confirmButtonText: this.$i18n.t('confirm'),
|
||||
cancelButtonText: this.$i18n.t('cancel'),
|
||||
type: 'warning',
|
||||
}
|
||||
)
|
||||
.then(() => {
|
||||
removeServer(data.id).then(() => {
|
||||
this.$message.success('Success')
|
||||
this.getBindServerList(data.projectId)
|
||||
})
|
||||
})
|
||||
.catch(() => {
|
||||
this.$message.info('Cancel')
|
||||
})
|
||||
},
|
||||
|
||||
removeUser(data) {
|
||||
this.$confirm(
|
||||
this.$i18n.t('projectPage.removeUserTips', { userName: data.userName }),
|
||||
this.$i18n.t('tips'),
|
||||
{
|
||||
confirmButtonText: this.$i18n.t('confirm'),
|
||||
cancelButtonText: this.$i18n.t('cancel'),
|
||||
type: 'warning',
|
||||
}
|
||||
)
|
||||
.then(() => {
|
||||
removeUser(data.id).then(() => {
|
||||
this.$message.success('Success')
|
||||
this.getBindUserList(data.projectId)
|
||||
})
|
||||
})
|
||||
.catch(() => {
|
||||
this.$message.info('Cancel')
|
||||
})
|
||||
},
|
||||
|
||||
removeFile(index) {
|
||||
if (this.fileFormData.files[index].id === 0) {
|
||||
this.fileFormData.files.splice(index, 1)
|
||||
} else {
|
||||
this.$confirm(
|
||||
this.$i18n.t('projectPage.removeFileTips', {
|
||||
filename: this.fileFormData.files[index].filename,
|
||||
}),
|
||||
this.$i18n.t('tips'),
|
||||
{
|
||||
confirmButtonText: this.$i18n.t('confirm'),
|
||||
cancelButtonText: this.$i18n.t('cancel'),
|
||||
type: 'warning',
|
||||
}
|
||||
)
|
||||
.then(() => {
|
||||
removeFile(this.fileFormData.files[index].id).then(() => {
|
||||
this.$message.success('Success')
|
||||
this.fileFormData.files.splice(index, 1)
|
||||
})
|
||||
})
|
||||
.catch(() => {
|
||||
this.$message.info('Cancel')
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
fileSubmit() {
|
||||
const file = this.fileFormData.files[this.fileFormProps.selectedIndex]
|
||||
this.fileFormProps.disabled = true
|
||||
if (file.id === 0) {
|
||||
addFile({
|
||||
projectId: file.projectId,
|
||||
filename: file.filename,
|
||||
content: this.fileFormData.content,
|
||||
})
|
||||
.then((response) => {
|
||||
this.fileFormData.files[this.fileFormProps.selectedIndex].id =
|
||||
response.data.id
|
||||
this.fileFormData.files[this.fileFormProps.selectedIndex].state =
|
||||
'success'
|
||||
this.fileFormProps.show = 'file-list'
|
||||
this.$message.success('Success')
|
||||
})
|
||||
.finally(() => {
|
||||
this.fileFormProps.disabled = false
|
||||
})
|
||||
} else {
|
||||
editFile({
|
||||
id: file.id,
|
||||
content: this.fileFormData.content,
|
||||
})
|
||||
.then(() => {
|
||||
this.fileFormData.files[this.fileFormProps.selectedIndex].state =
|
||||
'success'
|
||||
this.fileFormProps.show = 'file-list'
|
||||
this.$message.success('Success')
|
||||
})
|
||||
.finally(() => {
|
||||
this.fileFormProps.disabled = false
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
getOptions() {
|
||||
getServerOption().then((response) => {
|
||||
new ServerOption().request().then((response) => {
|
||||
this.serverOption = response.data.list
|
||||
this.serverOption.map((element) => {
|
||||
element.label =
|
||||
@ -1480,7 +935,7 @@ export default defineComponent({
|
||||
return element
|
||||
})
|
||||
})
|
||||
getUserOption().then((response) => {
|
||||
new NamespaceUserOption().request().then((response) => {
|
||||
this.userOption = response.data.list
|
||||
})
|
||||
},
|
||||
@ -1502,48 +957,6 @@ export default defineComponent({
|
||||
})
|
||||
},
|
||||
|
||||
getProjectFileList(projectID) {
|
||||
getProjectFileList(projectID).then((response) => {
|
||||
this.fileFormData.files = response.data.list.map((item) => {
|
||||
item.state = 'success'
|
||||
return item
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
getProjectFileContent(file, index) {
|
||||
this.fileFormProps.selectedIndex = index
|
||||
this.fileFormProps.show = 'edit-content'
|
||||
this.fileFormData.content = this.fileFormData.files[index]['content']
|
||||
? this.fileFormData.files[index]['content']
|
||||
: ''
|
||||
if (file.id === 0) {
|
||||
return
|
||||
}
|
||||
this.fileFormProps.editContentLoading = true
|
||||
getProjectFileContent(file.id)
|
||||
.then((response) => {
|
||||
this.fileFormData.content = this.fileFormData.files[index][
|
||||
'content'
|
||||
] = response.data.content
|
||||
})
|
||||
.finally(() => {
|
||||
this.fileFormProps.editContentLoading = false
|
||||
})
|
||||
},
|
||||
|
||||
getBindServerList(projectID) {
|
||||
getBindServerList(projectID).then((response) => {
|
||||
this.tableServerData = response.data.list
|
||||
})
|
||||
},
|
||||
|
||||
getBindUserList(projectID) {
|
||||
getBindUserList(projectID).then((response) => {
|
||||
this.tableUserData = response.data.list
|
||||
})
|
||||
},
|
||||
|
||||
getRemoteBranchList() {
|
||||
if (this.formProps.branch.length > 0) {
|
||||
return
|
@ -1,5 +1,9 @@
|
||||
<template>
|
||||
<el-dialog v-model="dialogVisible" :title="$t('import')">
|
||||
<el-dialog
|
||||
v-model="dialogVisible"
|
||||
:title="$t('import')"
|
||||
:close-on-click-modal="false"
|
||||
>
|
||||
<el-row>
|
||||
<el-row type="flex" style="width: 100%">
|
||||
<el-select
|
||||
|
@ -1,5 +1,9 @@
|
||||
<template>
|
||||
<el-dialog v-model="dialogVisible" :title="$t('manage')">
|
||||
<el-dialog
|
||||
v-model="dialogVisible"
|
||||
:title="$t('manage')"
|
||||
:close-on-click-modal="false"
|
||||
>
|
||||
<el-row class="app-bar" type="flex" justify="end">
|
||||
<el-button type="primary" icon="el-icon-plus" @click="handleAdd" />
|
||||
<el-row
|
||||
@ -204,7 +208,6 @@ export default defineComponent({
|
||||
new CrontabServerAdd(this.formData)
|
||||
.request()
|
||||
.then(() => {
|
||||
this.dialogVisible = false
|
||||
ElMessage.success('Success')
|
||||
this.getBindServerList(this.formData.crontabId)
|
||||
})
|
||||
|
Loading…
Reference in New Issue
Block a user