feat(业务): 子系统相关我负责的页面进行完善

This commit is contained in:
GUjiYN 2024-04-19 21:01:27 +08:00
parent 3f0779cc0b
commit 99a1c01feb
6 changed files with 941 additions and 505 deletions

View File

@ -1,213 +0,0 @@
/* eslint-env node */
module.exports = {
'root': true,
'env': {
'browser': true,
'node': true,
'es6': true
},
'parser': 'vue-eslint-parser',
'parserOptions': {
'parser': '@typescript-eslint/parser',
'ecmaVersion': 2020,
'sourceType': 'module',
'jsxPragma': 'React',
'ecmaFeatures': {
'jsx': true,
'tsx': true
}
},
'plugins': ['@typescript-eslint', 'import'],
'extends': [
'plugin:vue/vue3-essential',
'plugin:@typescript-eslint/recommended',
'eslint:recommended'
],
'globals': {
defineEmits: 'readonly',
defineProps: 'readonly',
defineExpose: 'readonly',
withDefaults: 'readonly',
WeixinJSBridge: 'readonly',
ElLoading: 'readonly',
ElMessage: 'readonly',
ElMessageBox: 'readonly',
ElNotification: 'readonly'
},
'rules': {
'vue/no-multiple-template-root': 'off',
'vue/multi-word-component-names': 'off',
'vue/singleline-html-element-content-newline': 'off',
'vue/multiline-html-element-content-newline': 'off',
'vue/no-v-html': 'off',
'accessor-pairs': 2,
'arrow-spacing': [2, {
'before': true,
'after': true
}],
'block-spacing': [2, 'always'],
'brace-style': [2, '1tbs', {
'allowSingleLine': true
}],
'camelcase': [0, {
'properties': 'always'
}],
'comma-dangle': [2, 'never'],
'comma-spacing': [2, {
'before': false,
'after': true
}],
'comma-style': [2, 'last'],
'constructor-super': 2,
'curly': [2, 'multi-line'],
'dot-location': [2, 'property'],
'eol-last': 2,
'eqeqeq': ['error', 'always', { 'null': 'ignore' }],
'generator-star-spacing': [2, {
'before': true,
'after': true
}],
'handle-callback-err': [2, '^(err|error)$'],
'indent': [2, 2, {
'SwitchCase': 1
}],
'jsx-quotes': [2, 'prefer-single'],
'key-spacing': [2, {
'beforeColon': false,
'afterColon': true
}],
'keyword-spacing': [2, {
'before': true,
'after': true
}],
'new-cap': [2, {
'newIsCap': true,
'capIsNew': false
}],
'new-parens': 2,
'no-array-constructor': 2,
'no-caller': 2,
'no-console': 'off',
'no-class-assign': 2,
'no-cond-assign': 2,
'no-const-assign': 2,
'no-control-regex': 0,
'no-delete-var': 2,
'no-dupe-args': 2,
'no-dupe-class-members': 2,
'no-dupe-keys': 2,
'no-duplicate-case': 2,
'no-empty-character-class': 2,
'no-empty-pattern': 2,
'no-eval': 2,
'no-ex-assign': 2,
'no-extend-native': 2,
'no-extra-bind': 2,
'no-extra-boolean-cast': 2,
'no-extra-parens': [2, 'functions'],
'no-fallthrough': 2,
'no-floating-decimal': 2,
'no-func-assign': 2,
'no-implied-eval': 2,
'no-inner-declarations': [2, 'functions'],
'no-invalid-regexp': 2,
'no-irregular-whitespace': 2,
'no-iterator': 2,
'no-label-var': 2,
'no-labels': [2, {
'allowLoop': false,
'allowSwitch': false
}],
'no-lone-blocks': 2,
'no-mixed-spaces-and-tabs': 2,
'no-multi-spaces': 2,
'no-multi-str': 2,
'no-multiple-empty-lines': [2, {
'max': 1
}],
'no-native-reassign': 2,
'no-negated-in-lhs': 2,
'no-new-object': 2,
'no-new-require': 2,
'no-new-symbol': 2,
'no-new-wrappers': 2,
'no-obj-calls': 2,
'no-octal': 2,
'no-octal-escape': 2,
'no-path-concat': 2,
'no-proto': 2,
'no-redeclare': 2,
'no-regex-spaces': 2,
'no-return-assign': [2, 'except-parens'],
'no-self-assign': 2,
'no-self-compare': 2,
'no-sequences': 2,
'no-shadow-restricted-names': 2,
'no-spaced-func': 2,
'no-sparse-arrays': 2,
'no-this-before-super': 2,
'no-throw-literal': 2,
'no-trailing-spaces': 2,
'no-undef': 2,
'no-undef-init': 2,
'no-unexpected-multiline': 2,
'no-unmodified-loop-condition': 2,
'no-unneeded-ternary': [2, {
'defaultAssignment': false
}],
'no-unreachable': 2,
'no-unsafe-finally': 2,
'no-unused-vars': [2, {
'vars': 'all',
'args': 'none'
}],
'no-useless-call': 2,
'no-useless-computed-key': 2,
'no-useless-constructor': 2,
'no-useless-escape': 0,
'no-whitespace-before-property': 2,
'no-with': 2,
'one-var': [2, {
'initialized': 'never'
}],
'operator-linebreak': [2, 'after', {
'overrides': {
'?': 'before',
':': 'before'
}
}],
'padded-blocks': [2, 'never'],
'quotes': [2, 'single', {
'avoidEscape': true,
'allowTemplateLiterals': true
}],
'semi': [2, 'always'],
'semi-spacing': [2, {
'before': false,
'after': true
}],
'space-before-blocks': [2, 'always'],
'space-before-function-paren': 'off',
'space-in-parens': [2, 'never'],
'space-infix-ops': 2,
'space-unary-ops': [2, {
'words': true,
'nonwords': false
}],
'spaced-comment': [2, 'always', {
'markers': ['global', 'globals', 'eslint', 'eslint-disable', '*package', '!', ',']
}],
'template-curly-spacing': [2, 'never'],
'use-isnan': 2,
'valid-typeof': 2,
'wrap-iife': [2, 'any'],
'yield-star-spacing': [2, 'both'],
'yoda': [2, 'never'],
'prefer-const': 2,
'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0,
'object-curly-spacing': [2, 'always', {
objectsInObjects: false
}],
'array-bracket-spacing': [2, 'never']
}
};

1
components.d.ts vendored
View File

@ -39,6 +39,7 @@ declare module '@vue/runtime-core' {
ElMenuItem: typeof import('element-plus/es')['ElMenuItem']
ElOption: typeof import('element-plus/es')['ElOption']
ElPagination: typeof import('element-plus/es')['ElPagination']
ElPopover: typeof import('element-plus/es')['ElPopover']
ElProgress: typeof import('element-plus/es')['ElProgress']
ElRadio: typeof import('element-plus/es')['ElRadio']
ElRadioButton: typeof import('element-plus/es')['ElRadioButton']

View File

@ -2,10 +2,13 @@ import request from '@/utils/request';
function getCurrentTimestamp() {
return new Date().getTime();
}
export function GetProject(projectId, token) {
//我负责的页面获取项目
export function GetProject(page, pageSize, token) {
return request({
url: '/project/get/' + projectId,
url: '/project/my/get',
method: 'get',
params: { page, pageSize },
headers: {
'Authorization':'Bearer '+ token,
'content-type': 'application/json;charset=utf-8',
@ -14,11 +17,12 @@ export function GetProject(projectId, token) {
});
}
export function GetProjectInfo(token,id) {
//新增项目
export function AddProject(data, token) {
return request({
url: '/project/get/id/',
method: 'get',
params: { id },
url: '/project/add',
method: 'post',
data,
headers: {
'Authorization':'Bearer '+ token,
'content-type': 'application/json;charset=utf-8',
@ -27,26 +31,73 @@ export function GetProjectInfo(token,id) {
});
}
export function fetchPv(pv) {
//删除项目
export function DeleteProject(id, token) {
return request({
url: '/vue-element-admin/article/pv',
url: '/project/delete',
method: 'delete',
params:{ id },
headers: {
'Authorization':'Bearer '+ token,
'content-type': 'application/json;charset=utf-8',
'Timestamp': getCurrentTimestamp()
}
});
}
//编辑项目
export function EditProject(projectId, data, token) {
return request({
url: '/project/edit/' + projectId,
method: 'put',
data,
headers: {
'Authorization': 'Bearer ' + token,
'content-type': 'application/json;charset=utf-8',
'Timestamp': getCurrentTimestamp()
}
});
}
//根据项目名字模糊查询
export function GetProjectByName(name, token) {
return request({
url: '/project/get/name',
method: 'get',
params: { pv }
params: { name },
headers: {
'Authorization':'Bearer '+ token,
'content-type': 'application/json;charset=utf-8',
'Timestamp': getCurrentTimestamp()
}
});
}
export function createArticle(data) {
//根据项目id查询子系统
export function GetChildSysById(projectId, token) {
return request({
url: '/vue-element-admin/article/create',
method: 'post',
data
url: '/module/get',
method: 'get',
params: { projectId },
headers: {
'Authorization':'Bearer '+ token,
'content-type': 'application/json;charset=utf-8',
'Timestamp': getCurrentTimestamp()
}
});
}
export function updateArticle(data) {
//根据项目名和子系统名查询子模块
export function GetChildModuleByName(projectName, childName, token) {
return request({
url: '/vue-element-admin/article/update',
method: 'post',
data
url: '/project/module/get/name',
method: 'get',
params: { projectName, childName },
headers: {
'Authorization':'Bearer '+ token,
'content-type': 'application/json;charset=utf-8',
'Timestamp': getCurrentTimestamp()
}
});
}

View File

@ -31,7 +31,7 @@ export const constantRoutes:RouteRecordRaw[] = [
}
]
},
{
path: '/login',
component: () => import('@/views/login/index.vue'),
@ -167,52 +167,52 @@ export const asyncRoutes:RouteRecordRaw[] = [
roles: ['admin', 'teacher_user']
},
children: [
{
path: 'charge',
component: () => import('@/views/personal/project/charge.vue'),
name: 'charge',
meta: { title: '我负责的', icon: 'user', affix: true }
},
{
path: 'participate',
component: () => import('@/views/personal/project/participate.vue'),
name: 'participate',
meta: { title: '我负责的', icon: 'user', affix: true }
meta: { title: '我参与的', icon: 'user', affix: true }
},
//我管理的以及子页面
{
path: 'manage',
component: () => import('@/views/personal/project/manage.vue'),
name: 'Manage',
meta: { title: '我管理的', icon: 'user', affix: true, },
},
//我负责的子系统和子模块
{
path: 'childSysCharge/:name',
component: () => import('@/views/personal/project/childSystem/charge.vue'),
name: 'ChildSysCharge',
meta: { title: '子系统', breadcrumb: true , affix: true },
props: true
},
{
path: 'childModCharge',
component: () => import('@/views/personal/project/childmodel/charge.vue'),
name: 'ChildModCharge',
meta: { title: '子模块', breadcrumb: true , hidden: true }
},
//我管理的子系统和子模块
{
path: 'childSysManage',
component: () => import('@/views/personal/project/childSystem/manage.vue'),
name: 'ChildSysManage',
meta: { title: '子系统', breadcrumb: true , hidden: true },
meta: { title: '子系统', breadcrumb: true , hidden: true },
},
{
path: 'childModManage',
component: () => import('@/views/personal/project/childModel/manage.vue'),
component: () => import('@/views/personal/project/childmodel/manage.vue'),
name: 'ChildModManage',
meta: { title: '子模块', breadcrumb: true , hidden: true }
},
//我参与的以及子界面
{
path: 'charge',
component: () => import('@/views/personal/project/charge.vue'),
name: 'Charge',
meta: { title: '我参与的', icon: 'user', affix: true }
},
{
path: 'childSysCharge',
component: () => import('@/views/personal/project/childSystem/manage.vue'),
name: 'ChildSysCharge',
meta: { title: '子系统', breadcrumb: true , hidden: true },
},
{
path: 'childModCharge',
component: () => import('@/views/personal/project/childModel/manage.vue'),
name: 'ChildModCharge',
meta: { title: '子模块', breadcrumb: true , hidden: true }
meta: { title: '子模块', breadcrumb: true , hidden: true }
},
]
}

View File

@ -9,6 +9,7 @@
<el-input
style="width: 550px"
placeholder="请输入"
v-model="searchData.name"
>
<template #prepend>名称</template>
</el-input>
@ -20,7 +21,7 @@
</el-input>
<div>
<el-button-group>
<el-button type="primary">
<el-button type="primary" @click="SearchProjectByName()">
<el-icon><Search /></el-icon>
查询
</el-button>
@ -51,63 +52,88 @@
<el-icon><Plus /></el-icon>
新增
</el-button>
<el-button type="danger" @click="toggleDeleteDialog()">
<el-button type="danger">
<el-icon><DeleteFilled /></el-icon>
删除
</el-button>
</div>
</div>
</template>
<div>
<el-table :data="tableData" ref="multipleTableRef" style="width: 100%">
<el-table-column type="selection" width="55" />
<el-table-column prop="id" label="序号">
<template v-slot="{row}">
<span>{{ row.id }}</span>
</template>
</el-table-column>
<el-table-column prop="name" label="项目名称">
<template v-slot="{row}">
<span>{{ row.name }}</span>
</template>
</el-table-column>
<el-table-column prop="workLoad" label="工作量">
<template v-slot="{row}">
<span>{{ row.workLoad}}</span>
</template>
</el-table-column>
<el-table-column prop="cycle" label="周期">
<template v-slot="{row}">
<span>{{ row.cycle }}</span>
</template>
</el-table-column>
<el-table-column prop="principalUser" label="项目负责人">
<template v-slot="{row}">
<span>{{ row.principalUser }}</span>
</template>
</el-table-column>
<el-table-column prop="isFinish" label="状态">
<template v-slot="{row}">
<span>{{ row.isFinish }}</span>
</template>
</el-table-column>
<el-table-column prop="description" label="项目简介">
<template v-slot="{row}">
<span>{{ row.description }}</span>
</template>
</el-table-column>
<el-table-column fixed="right" label="操作" width="120">
<template #default>
<el-button link type="primary" size="small">编辑</el-button>
<el-button link type="primary" size="small">删除</el-button>
<!--表格内容-->
<el-table :data="tableData" ref="multipleTableRef" style="width: 100%">
<el-table-column type="selection" width="55" />
<el-table-column prop="id" label="序号">
<template v-slot="{row}">
<span>{{ row.id }}</span>
</template>
</el-table-column>
<el-table-column prop="name" label="项目名称">
<template v-slot="{row}">
<span>{{ row.name }}</span>
</template>
</el-table-column>
<el-table-column prop="workLoad" label="工作量">
<template v-slot="{row}">
<span>{{ row.workLoad}}</span>
</template>
</el-table-column>
<el-table-column prop="cycle" label="周期">
<template v-slot="{row}">
<span>{{ row.cycle }}</span>
</template>
</el-table-column>
<el-table-column prop="principalUser" label="项目负责人">
<template v-slot="{row}">
<span>{{ row.principalUser }}</span>
</template>
</el-table-column>
<el-table-column label="状态" width="180">
<template #default="scope">
<el-popover effect="light" width="auto">
<template #reference>
<el-tag :type="getStatusTagColor(scope.row.status)">
{{ scope.row.status }}
</el-tag>
</template>
</el-popover>
</template>
</el-table-column>
<el-table-column prop="files" label="文档">
<el-button link type="primary" size="small">点击下载</el-button>
</el-table-column>
<el-table-column prop="description" label="项目简介">
<template v-slot="{row}">
<span>{{ row.description }}</span>
</template>
</el-table-column>
<el-table-column prop="deadLine" label="截止时间">
<template v-slot="{row}">
<span>{{ row.deadLine }}</span>
</template>
</el-table-column>
<el-table-column fixed="right" label="操作" width="120">
<template #default="{ row }">
<div style="display: flex; justify-content: flex-start; margin-bottom: 4px;">
<el-button link type="primary" size="small" @click="toggleEditDialog(row)">编辑</el-button>
<el-button link type="primary" size="small" @click="toggleDeleteDialog(row)">删除</el-button>
</div>
<div style="margin-bottom: 4px">
<el-button link type="primary" size="small">指定项目负责人</el-button>
<el-button link type="primary" size="small">查看详情</el-button>
</template>
</el-table-column>
</el-table>
</div>
</div>
<div style="margin-bottom: 4px">
<el-button link type="primary" size="small" @click="toChildSystem(row.id)">查看详情</el-button>
</div>
</template>
</el-table-column>
</el-table>
<div style="display: flex; justify-content: center;margin-top: 2vh">
<el-pagination background layout="prev, pager, next" :total="1000" />
<el-pagination
background
layout="prev, pager, next"
:total="totalItems"
/>
</div>
</el-card>
@ -123,7 +149,7 @@
trigger: 'blur',
}"
>
<el-input />
<el-input v-model="AddFormData.name" />
</el-form-item>
<el-form-item
label="周期"
@ -133,7 +159,7 @@
trigger: 'blur',
}"
>
<el-input />
<el-input v-model="AddFormData.cycle"/>
</el-form-item>
<el-form-item
label="工作量"
@ -143,18 +169,57 @@
trigger: 'blur',
}"
>
<el-input />
<el-input v-model="AddFormData.workLoad" />
</el-form-item>
<el-form-item
label="项目描述"
label="截止时间"
:rules="{
required: true,
message: 'domain can not be null',
trigger: 'blur',
}"
>
<el-input type="textarea" />
<div class="block">
<el-date-picker
v-model="AddFormData.deadLine"
type="date"
placeholder="Pick a day"
/>
</div>
</el-form-item>
<el-form-item
label="项目简介"
:rules="{
trigger: 'blur',
}"
>
<el-input type="textarea" v-model="AddFormData.description" />
</el-form-item>
<el-row>
<el-col :span="12">
<el-form-item
label="负责人"
:rules="{
required: true,
message: 'domain can not be null',
trigger: 'blur',
}"
>
<el-input v-model="AddFormData.principalId" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item
label="标签"
:rules="{
message: 'domain can not be null',
trigger: 'blur',
}"
>
<el-input v-model="AddFormData.tags" />
</el-form-item>
</el-col>
</el-row>
<el-form-item>
<el-row>
<el-col :span="20">
@ -166,18 +231,26 @@
trigger: 'blur',
}"
>
<el-select placeholder="Please select a zone">
<el-option label="Zone No.1" value="shanghai" />
<el-option label="Zone No.2" value="beijing" />
</el-select>
<el-select v-model="AddFormData.status">
<el-option value="0">未开始</el-option>
<el-option value="2">进行中</el-option>
<el-option value="1">已完成</el-option>
<el-option value="-1">暂停</el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="4">
<el-form-item>
<el-button type="success">
<el-icon><UploadFilled /></el-icon>
<el-upload
v-model="AddFormData.fakeFile"
multiple
style=" margin-right: 13px;"
>
<el-button type="success">
<el-icon><UploadFilled /></el-icon>
上传文档
</el-button>
</el-upload>
</el-form-item>
</el-col>
</el-row>
@ -186,12 +259,14 @@
<template #footer>
<div class="dialog-footer">
<el-button @click="CancelAdd()">取消</el-button>
<el-button type="primary">
<el-button type="primary" @click="addProject()">
确认
</el-button>
</div>
</template>
</el-dialog>
<!--删除项目对话框-->
<el-dialog
title="删除项目"
@ -202,68 +277,336 @@
<span>确认删除该项目吗?</span>
<template #footer>
<div class="dialog-footer">
<el-button type="danger">删除</el-button>
<el-button type="danger" @click="deleteProject()">删除</el-button>
<el-button @click="CancelDelete()">取消</el-button>
</div>
</template>
</el-dialog>
</template>
<script>
import { Plus, UploadFilled, Delete, DeleteFilled, RefreshRight, Search } from '@element-plus/icons-vue';
import { defineComponent } from 'vue';
import {
GetProject,
GetProjectInfo
} from '@/api/project';
import { getToken } from '@/utils/auth';
export default defineComponent({
name:'projectTable',
components: { RefreshRight, DeleteFilled, Delete, UploadFilled, Plus, Search },
data() {
return {
AddDialogVisible:false,
DeleteDialogVisible:false,
tableData:[],
listLoading: false,
token: getToken(),
projId:''
};
},
created() {
this.getList();
},
methods:{
getList() {
console.log("use token:", this.token)
this.listLoading = true;
GetProject(this.projId, this.token).then(response => {
console.log("完整响应内容:", response);
if (response.data) {
this.tableData = response.data;
} else {
console.error("未获取到预期数据,响应内容:", response);
}
this.listLoading = false;
}).catch(error => {
console.error('请求失败:', error);
this.listLoading = false;
});
},
toggleAddDialog() {
this.AddDialogVisible = !this.AddDialogVisible;
},
CancelAdd() {
this.AddDialogVisible = false;
},
toggleDeleteDialog() {
this.DeleteDialogVisible = !this.DeleteDialogVisible;
},
CancelDelete() {
this.DeleteDialogVisible = false;
}
},
<!--编辑项目对话框-->
<el-dialog v-model="EditDialogVisible" title="编辑项目" width="500">
<el-form label-width="auto" style="max-width: 600px">
<el-form-item
label="项目名称"
:rules="{
required: true,
message: 'domain can not be null',
trigger: 'blur',
}"
>
<el-input v-model="EditFormData.name"/>
</el-form-item>
<el-form-item
label="项目简介"
:rules="{
required: true,
message: 'domain can not be null',
trigger: 'blur',
}"
>
<el-input v-model="EditFormData.description"/>
</el-form-item>
<el-form-item
label="详细介绍"
:rules="{
required: true,
message: 'domain can not be null',
trigger: 'blur',
}"
>
<el-input v-model="EditFormData.tags"/>
</el-form-item>
<el-form-item
label="核心代码"
:rules="{
trigger: 'blur',
}"
>
<el-input type="textarea" />
</el-form-item>
<el-row>
<el-col :span="12">
<el-form-item
label="代码仓库"
:rules="{
required: true,
message: 'domain can not be null',
trigger: 'blur',
}"
>
<el-input />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item
label="类型"
:rules="{
message: 'domain can not be null',
trigger: 'blur',
}"
>
<el-input />
</el-form-item>
</el-col>
</el-row>
<el-form-item>
<el-row>
<el-col :span="20">
<el-form-item
label="报酬"
:rules="{
required: true,
message: 'Please select a status',
trigger: 'blur',
}"
>
<el-select >
<el-option value="0">未开始</el-option>
<el-option value="2">进行中</el-option>
<el-option value="1">已完成</el-option>
<el-option value="-1">暂停</el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button @click="CancelEdit()">取消</el-button>
<el-button type="primary" @click="editProject()">
确认
</el-button>
</div>
</template>
</el-dialog>
</template>
<script lang="ts" setup>
import { ref, reactive, onMounted } from 'vue';
import { Plus, UploadFilled, DeleteFilled, RefreshRight, Search } from '@element-plus/icons-vue';
import { AddProject, DeleteProject, EditProject, GetProject, GetProjectByName } from '@/api/project';
import { getToken } from '@/utils/auth';
import { useRouter } from 'vue-router';
import { ElMessage } from 'element-plus'
const router = useRouter();
const AddDialogVisible = ref(false);
const DeleteDialogVisible = ref(false);
const EditDialogVisible = ref(false);
const tableData = ref([]);
const listLoading = ref(false);
const token = getToken();
const page = ref('');
const pageSize = ref('');
const totalItems = ref(0);
const editId = ref('');
const searchData = reactive({
name:'',
});
const deleteData = reactive({
id: '',
})
const AddFormData = reactive({
name: '',
description: '',
tags: '',
deadLine: '',
workLoad: '',
principalId: '',
cycle: '',
status: '',
fakeFile: {
name: "element-plus-logo.svg",
url: 'https://element-plus.org/images/element-plus-logo.svg'
},
});
const EditFormData = reactive({
name:'',
description:'',
tags:'',
coreCode:'',
git:'',
type:'',
reward:'',
})
//
async function getList() {
console.log("use token:", token);
listLoading.value = true;
try {
const response = await GetProject(page.value, pageSize.value, token);
console.log("完整响应内容:", response);
if (response.data.list) {
tableData.value = response.data.list;
totalItems.value = response.data.total;
} else {
console.error("未获取到预期数据,响应内容:", response);
}
} catch (error) {
console.error('请求失败:', error);
} finally {
listLoading.value = false;
}
}
//
async function addProject() {
console.log("add token:", token);
try {
const res = await AddProject(AddFormData, token);
if (res.data) {
getList();
listLoading.value = true;
ElMessage({
message: '新增成功',
type: 'success',
})
} else {
console.error("未获取到预期数据,响应内容:", res);
}
} finally {
listLoading.value = false;
AddDialogVisible.value = false;
}
}
//
async function deleteProject() {
console.log("delete token:", token);
try {
const res = await DeleteProject(deleteData.id, token);
if (res.code === 200) {
ElMessage({
message: '删除成功',
type: 'success',
})
DeleteDialogVisible.value = false;
getList();
} else {
console.error("删除失败:", res);
}
} finally {
listLoading.value = false;
}
}
//
async function editProject() {
console.log("edit token:", token);
try {
const response = await EditProject(editId, EditFormData, token);
if (response.data) {
tableData.value = response.data;
} else {
console.error("未获取到预期数据,响应内容:", response);
}
} finally {
listLoading.value = false;
AddDialogVisible.value = false;
}
}
//
async function SearchProjectByName() {
console.log("search token:", token);
try {
const response = await GetProjectByName(searchData.name, token);
if (response.data) {
tableData.value = response.data;
} else {
console.error("未获取到预期数据,响应内容:", response);
}
} finally {
listLoading.value = false;
}
}
/*
async function toChildSystem(projectName) {
console.log("search token:", token, "project name:", projectName);
listLoading.value = true; //
try {
const response = await GetChildProjectByName(projectName, token);
if (response && response.data && response.data.name) {
console.log("Child project name:", response.data.name);
router.push({ name: 'ChildSysCharge', params: { name: response.data.name } });
} else {
console.error("未获取到预期的子系统名称,响应内容:", response);
}
} catch (error) {
console.error('查询子系统名称失败:', error);
} finally {
listLoading.value = false; //
}
}
*/
function toChildSystem(projectId) {
router.push({ name: 'ChildSysCharge', params: { name: projectId } });
}
function toggleAddDialog() {
AddDialogVisible.value = !AddDialogVisible.value;
}
function CancelAdd() {
AddDialogVisible.value = false;
}
function toggleDeleteDialog(row) {
console.log("Delete row:", row); //
DeleteDialogVisible.value = !DeleteDialogVisible.value;
}
function CancelDelete() {
DeleteDialogVisible.value = false;
}
function toggleEditDialog(row) {
console.log("Editing row:", row); //
// EditFormData
EditFormData.name = row.name;
EditFormData.description = row.description;
EditFormData.tags = row.tags;
EditFormData.coreCode = row.coreCode;
EditFormData.git = row.git;
EditFormData.type = row.type;
EditFormData.reward = row.reward;
EditDialogVisible.value = true; //
}
function CancelEdit() {
EditDialogVisible.value = false;
}
function getStatusTagColor(status) {
switch(status) {
case '进行':
return 'warning';
case '已完成':
return 'success';
case '未开始':
return 'info';
case '暂停':
return 'danger';
default:
return 'primary'; //
}
}
onMounted(() => {
getList();
});
</script>

View File

@ -1,136 +1,390 @@
<template>
<div style=" width:100%">
<el-card style="max-width: 100vw;margin: 1.5vw;">
<template #header><strong >项目1</strong></template>
<div style="display:flex;flex-direction:row;justify-content: space-around ">
<div>
名称
<el-input v-model="input" style="width: 240px;margin-left:0.5vw" placeholder="请输入" />
</div>
<div>
状态
<el-input v-model="input" style="width: 240px;margin-left:0.5vw" placeholder="请输入" />
</div>
<div>
<el-button type="primary" style="width:80px">查询</el-button>
<el-button style="width:80px">重置</el-button>
</div>
</div>
</el-card>
<el-card style="max-width: 100vw;height:60vh;margin:1.3vw">
<div style="display:flex;flex-direction: row;justify-content: space-between">
<el-button
text
type=''
>子系统列表</el-button
>
</div>
<el-table
ref="multipleTableRef"
:data="tableData"
style="max-width: 100vw;"
@selection-change="handleSelectionChange"
>
<!-- <el-table-column type="selection" width="55" />-->
<el-table-column label="序号" width="120">
<template #default="scope">{{ scope.row.date }}</template>
</el-table-column>
<el-table-column property="name" label="子系统名称" width="120" />
<el-table-column property="address" label="工作量" show-overflow-tooltip />
<el-table-column property="address" label="周期" />
<el-table-column property="address" label="负责人" />
<el-table-column property="address" label="状态" />
<el-table-column property="address" label="子系统简介" />
<el-table-column property="address" label="截止时间" />
<el-table-column property="address" label="操作" >
<el-button
link
style="color:deepskyblue"
@click="toChildModel"
>查看详情</el-button
>
</el-table-column>
</el-table>
<el-pagination
larger
background
layout="prev, pager, next"
:total="50"
class="mt-4"
style="display: flex;flex-direction: row;justify-content: center;margin-top:5vh"
/>
</el-card>
<el-card style="max-width: 100vw;margin: 1.5vw;">
<template #header>
<div class="card-header">
<span>项目1</span>
</div>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import { ElTable } from 'element-plus';
import { useRouter } from 'vue-router';
//
const router = useRouter();
</template>
<div style="display: flex; gap: 100px">
<el-input
style="width: 550px"
placeholder="请输入"
>
<template #prepend>名称</template>
</el-input>
<el-input
style="width: 550px"
placeholder="请输入"
>
<template #prepend>状态</template>
</el-input>
<div>
<el-button-group>
<el-button type="primary">
<el-icon><Search /></el-icon>
查询
</el-button>
<el-button>
<el-icon><RefreshRight /></el-icon>
重置
</el-button>
</el-button-group>
</div>
</div>
<template #footer>Footer content</template>
</el-card>
<el-card style="max-width: 100vw;margin: 1.5vw;">
<template #header>
<div class="card-header" style="display: flex; justify-content: space-between; align-items: center;">
<span>子系统列表</span>
<div style="display: flex;">
<el-button type="primary" >
<el-icon><Plus /></el-icon>
新增
</el-button>
<el-button type="danger">
<el-icon><DeleteFilled /></el-icon>
删除
</el-button>
</div>
</div>
</template>
const toChildModel = () => {
router.push({name:'ChildModCharge'})
};
<!--表格内容-->
<el-table :data="tableData" ref="multipleTableRef" style="width: 100%">
<el-table-column type="selection" width="55" />
<el-table-column prop="id" label="序号">
<template v-slot="{row}">
<span>{{ row.id }}</span>
</template>
</el-table-column>
<el-table-column prop="name" label="子系统名称">
<template v-slot="{row}">
<span>{{ row.name }}</span>
</template>
</el-table-column>
<el-table-column prop="workLoad" label="工作量">
<template v-slot="{row}">
<span>{{ row.workLoad}}</span>
</template>
</el-table-column>
<el-table-column prop="cycle" label="周期">
<template v-slot="{row}">
<span>{{ row.cycle }}</span>
</template>
</el-table-column>
<el-table-column prop="principalUser" label="负责人">
<template v-slot="{row}">
<span>{{ row.principalUser }}</span>
</template>
</el-table-column>
<el-table-column label="状态" width="180">
<template #default="scope">
<el-popover effect="light" width="auto">
<template #reference>
<el-tag >
{{ scope.row.status }}
</el-tag>
</template>
</el-popover>
</template>
</el-table-column>
<el-table-column prop="description" label="子系统简介">
<template v-slot="{row}">
<span>{{ row.description }}</span>
</template>
</el-table-column>
<el-table-column prop="deadLine" label="截止时间">
<template v-slot="{row}">
<span>{{ row.deadLine }}</span>
</template>
</el-table-column>
<el-table-column fixed="right" label="操作" width="120">
<template #default="{ row }">
<div style="display: flex; justify-content: flex-start; margin-bottom: 4px;">
<el-button link type="primary" size="small" >编辑</el-button>
<el-button link type="primary" size="small" >删除</el-button>
</div>
<div style="margin-bottom: 4px">
<el-button link type="primary" size="small">指定项目负责人</el-button>
</div>
<div style="margin-bottom: 4px">
<el-button link type="primary" size="small">查看详情</el-button>
</div>
</template>
</el-table-column>
const input = ref('');
</el-table>
<div style="display: flex; justify-content: center;margin-top: 2vh">
<el-pagination
background
layout="prev, pager, next"
/>
</div>
</el-card>
interface User {
date: string
name: string
address: string
}
const multipleTableRef = ref<InstanceType<typeof ElTable>>();
const multipleSelection = ref<User[]>([]);
const handleSelectionChange = (val: User[]) => {
multipleSelection.value = val;
};
const tableData: User[] = [
{
date: '2016-05-03',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles'
},
{
date: '2016-05-02',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles'
},
{
date: '2016-05-04',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles'
},
{
date: '2016-05-01',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles'
<!--新增子系统对话框-->
<el-dialog title="新增子系统" width="500">
<el-form label-width="auto" style="max-width: 600px">
<el-form-item
label="项目名称"
:rules="{
required: true,
message: 'domain can not be null',
trigger: 'blur',
}"
>
<el-input />
</el-form-item>
<el-form-item
label="周期"
:rules="{
required: true,
message: 'domain can not be null',
trigger: 'blur',
}"
>
<el-input />
</el-form-item>
<el-form-item
label="工作量"
:rules="{
required: true,
message: 'domain can not be null',
trigger: 'blur',
}"
>
<el-input />
</el-form-item>
<el-form-item
label="截止时间"
:rules="{
required: true,
message: 'domain can not be null',
trigger: 'blur',
}"
>
<div class="block">
<el-date-picker
type="date"
placeholder="Pick a day"
/>
</div>
</el-form-item>
<el-form-item
label="项目简介"
:rules="{
trigger: 'blur',
}"
>
<el-input type="textarea" />
</el-form-item>
<el-row>
<el-col :span="12">
<el-form-item
label="负责人"
:rules="{
required: true,
message: 'domain can not be null',
trigger: 'blur',
}"
>
<el-input />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item
label="标签"
:rules="{
message: 'domain can not be null',
trigger: 'blur',
}"
>
<el-input />
</el-form-item>
</el-col>
</el-row>
<el-form-item>
<el-row>
<el-col :span="20">
<el-form-item
label="状态"
:rules="{
required: true,
message: 'Please select a status',
trigger: 'blur',
}"
>
<el-select >
<el-option value="0">未开始</el-option>
<el-option value="2">进行中</el-option>
<el-option value="1">已完成</el-option>
<el-option value="-1">暂停</el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="4">
<el-form-item>
<el-upload
multiple
style=" margin-right: 13px;"
>
<el-button type="success">
<el-icon><UploadFilled /></el-icon>
上传文档
</el-button>
</el-upload>
</el-form-item>
</el-col>
</el-row>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button >取消</el-button>
<el-button type="primary">
确认
</el-button>
</div>
</template>
</el-dialog>
<!--删除项目对话框-->
<el-dialog
title="删除项目"
width="450"
align-center
>
<span>确认删除该项目吗?</span>
<template #footer>
<div class="dialog-footer">
<el-button type="danger" >删除</el-button>
<el-button >取消</el-button>
</div>
</template>
</el-dialog>
<!--编辑项目对话框-->
<el-dialog title="编辑项目" width="500">
<el-form label-width="auto" style="max-width: 600px">
<el-form-item
label="项目名称"
:rules="{
required: true,
message: 'domain can not be null',
trigger: 'blur',
}"
>
<el-input />
</el-form-item>
<el-form-item
label="项目简介"
:rules="{
required: true,
message: 'domain can not be null',
trigger: 'blur',
}"
>
<el-input/>
</el-form-item>
<el-form-item
label="详细介绍"
:rules="{
required: true,
message: 'domain can not be null',
trigger: 'blur',
}"
>
<el-input />
</el-form-item>
<el-form-item
label="核心代码"
:rules="{
trigger: 'blur',
}"
>
<el-input type="textarea" />
</el-form-item>
<el-row>
<el-col :span="12">
<el-form-item
label="代码仓库"
:rules="{
required: true,
message: 'domain can not be null',
trigger: 'blur',
}"
>
<el-input />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item
label="类型"
:rules="{
message: 'domain can not be null',
trigger: 'blur',
}"
>
<el-input />
</el-form-item>
</el-col>
</el-row>
<el-form-item>
<el-row>
<el-col :span="20">
<el-form-item
label="报酬"
:rules="{
required: true,
message: 'Please select a status',
trigger: 'blur',
}"
>
<el-select >
<el-option value="0">未开始</el-option>
<el-option value="2">进行中</el-option>
<el-option value="1">已完成</el-option>
<el-option value="-1">暂停</el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button >取消</el-button>
<el-button type="primary" >
确认
</el-button>
</div>
</template>
</el-dialog>
</template>
<script setup>
import { ref, onMounted } from 'vue';
import { useRoute } from 'vue-router';
import { GetChildSysById } from '@/api/project';
import { getToken } from '@/utils/auth'; // API
const route = useRoute();
const projectId = ref(route.params.name);
const tableData = ref([]);
const token = getToken();
onMounted(async () => {
if (projectId.value) {
try {
const response = await GetChildSysById(projectId.value, token);
tableData.value = response.data; //
} catch (error) {
console.error("Error fetching data:", error);
}
];
</script>
<style>
.my-autocomplete li {
line-height: normal;
padding: 7px;
}
.my-autocomplete li .name {
text-overflow: ellipsis;
overflow: hidden;
}
.my-autocomplete li .addr {
font-size: 12px;
color: #b4b4b4;
}
.my-autocomplete li .highlighted .addr {
color: #ddd;
}
</style>
});
</script>