确认报名(团队)对接

main
significative 8 months ago
parent fe73766095
commit dd278c0c50
  1. 1
      package.json
  2. 23
      pnpm-lock.yaml
  3. 102
      src/api/person.ts
  4. 1
      src/views/projectName/index.vue
  5. 76
      src/views/registrationGroup copy/components/dalog.vue
  6. 78
      src/views/registrationGroup copy/components/edit.vue
  7. 153
      src/views/registrationGroup copy/components/infoList.vue
  8. 585
      src/views/registrationGroup copy/index.vue
  9. 119
      src/views/registrationGroup/components/stuDialog.vue
  10. 163
      src/views/registrationGroup/components/stuList.vue
  11. 122
      src/views/registrationGroup/components/teaDialog.vue
  12. 217
      src/views/registrationGroup/components/teaList.vue
  13. 218
      src/views/registrationGroup/index.vue

@ -16,6 +16,7 @@
"preinstall": "node ./scripts/preinstall.js"
},
"dependencies": {
"@ant-design/icons-vue": "^7.0.1",
"@element-plus/icons-vue": "^2.3.1",
"axios": "^1.6.8",
"echarts": "5.3.2",

@ -1,6 +1,9 @@
lockfileVersion: '6.0'
dependencies:
'@ant-design/icons-vue':
specifier: ^7.0.1
version: 7.0.1(vue@3.4.21)
'@element-plus/icons-vue':
specifier: ^2.3.1
version: 2.3.1(vue@3.4.21)
@ -131,6 +134,26 @@ packages:
'@jridgewell/trace-mapping': 0.3.25
dev: true
/@ant-design/colors@6.0.0:
resolution: {integrity: sha512-qAZRvPzfdWHtfameEGP2Qvuf838NhergR35o+EuVyB5XvSA98xod5r4utvi4TJ3ywmevm290g9nsCG5MryrdWQ==}
dependencies:
'@ctrl/tinycolor': 3.6.1
dev: false
/@ant-design/icons-svg@4.4.2:
resolution: {integrity: sha512-vHbT+zJEVzllwP+CM+ul7reTEfBR0vgxFe7+lREAsAA7YGsYpboiq2sQNeQeRvh09GfQgs/GyFEvZpJ9cLXpXA==}
dev: false
/@ant-design/icons-vue@7.0.1(vue@3.4.21):
resolution: {integrity: sha512-eCqY2unfZK6Fe02AwFlDHLfoyEFreP6rBwAZMIJ1LugmfMiVgwWDYlp1YsRugaPtICYOabV1iWxXdP12u9U43Q==}
peerDependencies:
vue: '>=3.0.3'
dependencies:
'@ant-design/colors': 6.0.0
'@ant-design/icons-svg': 4.4.2
vue: 3.4.21(typescript@5.2.2)
dev: false
/@babel/code-frame@7.24.7:
resolution: {integrity: sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==}
engines: {node: '>=6.9.0'}

@ -1,37 +1,58 @@
import request from '@/utils/requset'
function f(callback: Function) {
return (...arg: any[]) => {
return new Promise((resolve, reject) => {
callback(...arg).then((res: any) => {
if (res.code >= 200 && res.code < 300) resolve(res)
else reject(res)
}).catch(reject);
})
import req1 from '@/utils/requset';
import { AxiosInstance } from 'axios';
function copyRequest(req1: AxiosInstance, instanceConfig = {}) {
let request: AxiosInstance, copyStatus: boolean;
try {
// @ts-ignore
const req2 = req1.create(instanceConfig);
function acopyInterceptors(target: any, interceptorManager: any) {
const handlers = interceptorManager.handlers;
for (let index = 0; index < handlers?.length; index++) {
const { fulfilled, rejected, runWhen, synchronous } = handlers[index];
let options;
if (synchronous !== false || runWhen !== null) options = { synchronous, runWhen };
target.use(fulfilled, rejected, options)
}
}
acopyInterceptors(req2.interceptors.request, req1.interceptors.request);
acopyInterceptors(req2.interceptors.response, req1.interceptors.response);
request = req2;
copyStatus = true;
} catch (error) {
console.warn('拷贝失败,私有拦截器可能失效:\n', error);
request = req1;
copyStatus = false;
}
return { request, copyStatus };
}
const { request, copyStatus } = copyRequest(req1);
// 若拷贝成功,添加自己独有的拦截器
if (copyStatus) {
request.interceptors.response.use((response: any) => {
if (response.code >= 200 && response.code < 300) return response;
else return Promise.reject(response);
})
}
// =============================================================================
enum api {
liststu = '/abilityEvaluation/personalAbilityEvaluationCollect/liststu', // 个人能力评价列表
integral = '/annualScore/personalCompTotalScore/liststu', // 个人积分列表
liststu = '/abilityEvaluation/personalAbilityEvaluationCollect/liststu', // 个人能力评价列表
integral = '/annualScore/personalCompTotalScore/liststu', // 个人积分列表
PAGE_XSFXBG = '/annualcompetitionprojectregistration/annualCompetitionProjectRegistration/xsfxbg', // 个人能力报告
competition = '/AnnualCompPoint/annualCompPoint/findcompp', // 比赛项目列表
competitionOne = '/AnnualCompPoint/annualCompPoint/findcomppxq', // 比赛项目单个
signUp = '/annualcompetitionprojectregistration/annualCompetitionProjectRegistration/edit', // 年度比赛项目报名 POST
competition = '/AnnualCompPoint/annualCompPoint/findcompp', // 比赛项目列表
competitionOne = '/AnnualCompPoint/annualCompPoint/findcomppxq', // 比赛项目单个
signUp = '/annualcompetitionprojectregistration/annualCompetitionProjectRegistration/edit', // 年度比赛项目报名 POST
membersList = '/online/cgreport/api/getData/1696139786651197442', // 团队成员列表
adviserList = '/online/cgreport/api/getData/1828357196360998913', // 指导老师列表
listStudent = '/AnnualCompPoint/annualCompPoint/listStudent', // 比赛项目报名表
}
export const getlEvaluateApi = f((params: Record<'pageNo' | 'pageSize', number>) => request.get(api.liststu, { params }));
export const getlIntegralApi = f((params: Record<'pageNo' | 'pageSize', number>) => request.get(api.integral, { params }));
export const getXsfxbgApi = f(
(params = {}) => {
const par = { recreateFlag: false, annualid: '' };
Object.assign(par, params);
return request.get(api.PAGE_XSFXBG, { params: par });
}
);
export const getCompetitionApi = f((id: string) => request.get(api.competition, { params: { id } }));
export const getCompetitionOneApi = f((id: string) => request.get(api.competitionOne, { params: { id } }));
// http://10.115.2.247:3300/jeecgboot/AnnualCompPoint/annualCompPoint/listStudent?column=createTime&order=desc&pageNo=1&pageSize=10&_t=1727422864387
interface SignUpData {
annualCompid: string,
entryFormat: '团队' | '个人',
@ -39,4 +60,31 @@ interface SignUpData {
instructorSheetList?: any[],
teamManagementList?: any[],
}
export const getSignUpApi = f((data: SignUpData) => request.post(api.signUp, data));
interface MembersOrAdviser {
pageNo: number,
pageSize: number,
onlRepUrlParamStr: `annualCompid=${string}`,
entryFormat: '团队' | '个人',
id: string,
column?: string,
order?: 'asc' | 'desc'
}
export const getlEvaluateApi = (params: Record<'pageNo' | 'pageSize', number>) => request.get(api.liststu, { params });
export const getlIntegralApi = (params: Record<'pageNo' | 'pageSize', number>) => request.get(api.integral, { params });
export const getXsfxbgApi = (params = {}) => {
const par = { recreateFlag: false, annualid: '' };
Object.assign(par, params);
return request.get(api.PAGE_XSFXBG, { params: par });
}
export const getCompetitionApi = (id: string) => request.get(api.competition, { params: { id } });
export const getCompetitionOneApi = (id: string) => request.get(api.competitionOne, { params: { id } });
export const getSignUpApi = (data: SignUpData) => request.post(api.signUp, data);
export const getMembersList = (params: MembersOrAdviser) => request.get(api.membersList, { params });
export const getAdviserList = (params: MembersOrAdviser) => request.get(api.adviserList, { params });

@ -84,7 +84,6 @@ function handleSub() {
let path;
if (data.value.entryForm === 'Y') path = '/registrationGroup';
else path = '/registrationPersonage';
router.push({ path, query: { id: route.query.id,objName:data.value.objName } })
}

@ -0,0 +1,76 @@
<template>
<el-dialog :modelValue="modelValue" @update:modelValue="(newValue: boolean) => $emit('update:modelValue', newValue)"
title="用户信息" width="800" draggable overflow>
<div class="table-box">
<el-table ref="multipleTableRef" border :data="tableData" class="table">
<el-table-column label="选择" width="55">
<template #default="scope">
<el-radio v-model="selectedRow" :value="scope.row" />
</template>
</el-table-column>
<el-table-column label="序号">
<template #default="scope">
{{ scope.$index + 1 }}
</template>
</el-table-column>
<el-table-column property="realname" label="真实姓名" sortable />
<el-table-column property="work_no" label="学号" sortable />
</el-table>
<div class="pagin-box">
<el-pagination class="pagination" style="width: 100%;" v-model:current-page="params.pageNo"
v-model:page-size="params.pageSize" :page-sizes="[10, 20, 30, 40]"
layout="slo, total,slot, sizes, prev, pager, next, jumper" :total="total" @change="getList" />
</div>
</div>
<template #footer>
<div class="dialog-footer">
<el-button @click="$emit('update:modelValue', false)">关闭</el-button>
<el-button type="primary"
@click="() => { $emit('update:modelValue', false); $emit('selected', selectedRow); }">确认</el-button>
</div>
</template>
</el-dialog>
</template>
<script lang="ts" setup>
import { computed, reactive, ref, watch } from 'vue';
import { getMembersList } from '@/api/person';
import { useRoute } from 'vue-router';
const props = defineProps(['modelValue']);
const $emit = defineEmits(['update:modelValue', 'selected']);
const route = useRoute();
watch(() => props.modelValue, () => getList());
//
const tableData = reactive<any[]>([]);
const selectedRow = ref();
//
const total = ref(0);
const params = reactive<any>({
pageNo: 1,
pageSize: 10,
onlRepUrlParamStr: `annualCompid=${route.query.objName}`,
entryFormat: '团队',
id: route.query.id,
})
const getList = async () => {
if (!props.modelValue) return
const res: any = await getMembersList(params);
tableData.length = 0;
tableData.push(...res.result.records);
total.value = res.result.total;
}
</script>
<style lang="scss" scoped>
.form-box {
padding: 0 60px;
}
</style>

@ -0,0 +1,78 @@
<template>
<el-dialog title="编辑" width="800" draggable>
<div class="form-box">
<el-form ref="ruleFormRef" style="max-width: 600px" :model="ruleForm" status-icon :rules="rules"
label-width="auto" class="demo-ruleForm">
<el-form-item label="年度比赛项目" prop="pass">
<el-input v-model="ruleForm.pass" type="text" autocomplete="off" />
</el-form-item>
<el-form-item label="参赛形式" prop="checkPass">
<el-input v-model="ruleForm.checkPass" type="text" autocomplete="off" />
</el-form-item>
<el-form-item label="队伍名称" prop="age">
<el-input v-model.number="ruleForm.age" />
</el-form-item>
</el-form>
</div>
<el-tabs v-model="activeName" class="demo-tabs" @tab-click="onCutTab">
<el-tab-pane label="团队成员表" name="members">
<info-list ref="memRef"></info-list>
</el-tab-pane>
<el-tab-pane label="指导老师表" name="adviser">
<info-list></info-list>
</el-tab-pane>
</el-tabs>
<div>
<el-button>关闭</el-button>
<el-button type="primary" @click="submit">确认</el-button>
</div>
</el-dialog>
</template>
<script lang="ts" setup>
import { reactive, ref } from 'vue';
import type { TabsPaneContext, FormInstance, FormRules } from 'element-plus';
import { useRoute } from 'vue-router';
import infoList from './infoList.vue';
const route = useRoute();
defineProps(['data']);
const activeName = ref('members');
const onCutTab = (tab: TabsPaneContext) => {
console.log(tab.props.name,)
}
// form
const ruleFormRef = ref<FormInstance>();
const ruleForm = reactive({
pass: route.query.objName,
checkPass: '团队赛',
age: '',
})
const rules = reactive<FormRules<typeof ruleForm>>({});
const memRef = ref<any>(null);
const submit = () => {
memRef.value.submit()
}
</script>
<style lang="scss" scoped>
.el-tabs--top {
flex-direction: column;
}
.form-box {
padding: 0 60px;
}
</style>

@ -0,0 +1,153 @@
<template>
<el-button type="primary" icon="Plus" @click="add">新增</el-button>
<div class="table-box">
<el-table ref="multipleTableRef" border :data="tableData" class="table" height="276px">
<el-table-column type="selection" width="55" />
<el-table-column property="#" label="#" />
<el-table-column>
<template #header>
<el-icon>
<Edit />
</el-icon>
<span style="margin-left: 10px;">用户</span>
</template>
<template #default="scope">
<el-input @click="openDialog(scope.row)" v-model="scope.row['用户']" placeholder="请选择"
:prefix-icon="ClusterOutlined" />
</template>
</el-table-column>
<el-table-column>
<template #header>
<el-icon>
<Edit />
</el-icon>
<span style="margin-left: 10px;">是否队长</span>
</template>
<template #default="scope">
<el-cascader v-model="scope.row['是否队长']" :options="options" />
</template>
</el-table-column>
<el-table-column>
<template #header>
<el-icon>
<Edit />
</el-icon>
<span style="margin-left: 10px;">队员序号</span>
</template>
<template #default="scope">
<el-input v-model="scope.row['队员序号']" />
</template>
</el-table-column>
</el-table>
</div>
<!-- <div>
<el-button>关闭</el-button>
<el-button type="primary" @click="submit">确认</el-button>
</div> -->
<dalog v-model="visible" @selected="handleSelected" />
</template>
<script lang="ts" setup>
import { reactive, ref } from 'vue';
import dalog from './dalog.vue';
import { ClusterOutlined } from '@ant-design/icons-vue';
import { ElMessage } from 'element-plus';
const options = [
{
value: true,
label: '是',
},
{
value: false,
label: '否',
},
]
//
const tableData = reactive<any[]>([])
const add = () => {
const length = tableData.push({
'#': tableData.length + 1,
'用户': '',
'是否队长': '',
'队员序号': '',
row: undefined,
});
openDialog(tableData[length - 1]);
}
// dialogdialog
const target = ref<any>();
const openDialog = (row: any) => {
visible.value = true;
target.value = row;
}
const visible = ref(false);
//
const handleSelected = (row: any) => {
if (tableData.some(o => o?.row?.id === row.id)) {
ElMessage({
message: '用户不能多选!',
type: 'error'
})
return
}
target.value['用户'] = row.realname;
target.value.row = row;
}
//
const submit = () => {
console.log(tableData);
}
defineExpose({submit})
</script>
<style lang="scss" scoped>
.form-box {
padding: 0 60px;
}
.table-box {
.table {
width: 100%;
}
.pagin-box {
width: 100%;
height: 64px;
display: flex;
align-items: center;
.pagination {
padding: 0 24px;
:deep() {
.el-pagination__total {
margin-right: auto;
}
li.number.is-active {
background-color: #42D9AC;
color: rgba(255, 255, 255, 0.9);
font-family: Microsoft YaHei UI, Microsoft YaHei UI;
}
span.el-pagination__jump {
background-color: #F3F3F3;
padding: 2px 8px;
}
}
}
}
}
</style>

@ -0,0 +1,585 @@
<template>
<!-- 报名信息确认页面 团队 -->
<div class="fill"></div>
<div class="banner">
<div class="box">
<div class="title-box">
<div class="title">报名信息确认</div>
<div class="text">
请仔细核对报名信息报名成功后无法修改请仔细核对报名信息报名成功后无法修改
请仔细核对报名信息报名成功后无法修改请仔细核对报名信息报名成功后无法修改
请仔细核对报名信息报名成功后无法修改请仔细核对报名信息报名成功后无法修改
</div>
</div>
<div class="img-box">
<img src="../../assets/images/applyImg.png" alt="">
</div>
</div>
</div>
<div class="registration-layout">
<div class="top">
<!-- 比赛信息 -->
<el-card class="com">
<div class="title">比赛信息</div>
<div class="content">
<div class="card-annual">
<div class="annual">2023年度</div>
<div class="title-box">
<div class="text">河南省大学生创新创业大赛</div>
<img src="../../assets/images/编组.png" alt="">
</div>
</div>
<div class="right">
<div class="info-box">
<div class="name">比赛年度</div>
<div class="title">2024年度</div>
<div class="name">比赛名称</div>
<div class="title">河南省大学生创新创业大赛</div>
<div class="date-box">
<div class="label">开始报名时间</div>
<div class="date">2323.6.1 18:00</div>
</div>
<div class="date-box">
<div class="label">开始截至时间</div>
<div class="date">2323.6.1 18:00</div>
</div>
</div>
</div>
</div>
</el-card>
<!-- 项目信息 -->
<el-card class="com">
<div class="title">项目信息</div>
<div class="content track">
<div class="card-annual">
<p>红色之旅赛道</p>
</div>
<div class="right">
<div class="info-box">
<div class="name">项目名称</div>
<div class="title">红色之旅赛道</div>
<div class="name">要求人数</div>
<div class="title">1</div>
<div class="date-box">
<div class="label">开始报名时间</div>
<div class="date">2323.6.1 18:00</div>
</div>
<div class="date-box">
<div class="label">开始截至时间</div>
<div class="date">2323.6.1 18:00</div>
</div>
</div>
</div>
</div>
</el-card>
</div>
<el-card class="center">
<div class="personage-info">
<div class="head">
<div class="title">个人信息</div>
<div class="icon">
<img src="../../assets/images/ellipsis.png" alt="">
</div>
</div>
<div class="info-box">
<div class="label">姓名</div>
<div class="text">{{ info.realname }}</div>
</div>
<div class="info-box">
<div class="label">姓别</div>
<div class="text">{{ pasSex(info.sex) }}</div>
</div>
<div class="info-box">
<div class="label">学号</div>
<div class="text">{{ info.workNo }}</div>
</div>
<div class="info-box">
<div class="label">手机号</div>
<div class="text">{{ info.phone }}</div>
</div>
<div class="info-box">
<div class="label">邮箱</div>
<div class="text">{{ info.email }}</div>
</div>
<!-- <div class="info-box">
<div class="label">院系</div>
<div class="text">国际教育学院</div>
</div>
<div class="info-box">
<div class="label">专业</div>
<div class="text">软件工程</div>
</div>
<div class="info-box">
<div class="label">指导老师</div>
<div class="text">令狐冲</div>
</div>
<div class="info-box">
<div class="label">所属团队</div>
<div class="text">王不留行的团队</div>
</div>
<div class="info-box remark">
<div class="label">其它备注</div>
<div class="text"></div>
</div> -->
</div>
</el-card>
<el-card class="list" :body-style="{ padding: 0 }">
<div class="head">
<div class="left">
<el-button class="btn" type="primary" @click="cliAddBtn">添加队员</el-button>
<div class="text">已选2位</div>
</div>
<div class="right">
<el-input v-model="input" style="width: 280px" placeholder="请输入学号进行搜索" suffix-icon="Search" />
</div>
</div>
<div class="table-box">
<el-table ref="multipleTableRef" border :data="tableData" class="table" height="276px">
<el-table-column type="selection" width="55" />
<el-table-column property="stuNum" label="学号" sortable />
<el-table-column property="name" label="姓名" sortable />
<el-table-column property="department" label="院系" sortable />
<el-table-column property="phone" label="手机号" sortable />
</el-table>
<div class="pagin-box">
<el-pagination class="pagination" style="width: 100%;" v-model:current-page="pagInfo.currentPage"
v-model:page-size="pagInfo.pageSize" :page-sizes="[10, 20, 30, 40]"
layout="slo, total,slot, sizes, prev, pager, next, jumper" :total="pagInfo.total"
@change="handleChange" />
</div>
</div>
</el-card>
<div class="bottom">
<el-button class="btn">取消报名</el-button>
<el-button class="btn cyan">确认报名</el-button>
</div>
</div>
<edit v-model="isOpen" />
</template>
<script lang="ts" setup>
import { reactive, ref, toRefs } from 'vue';
import { useRoute } from 'vue-router';
import userStore from '@/store/module/user';
import edit from './components/edit.vue';
const user = userStore();
const route = useRoute();
//
const { userInfo: info } = toRefs(user);
//
function pasSex(num: number) {
if (num == 1) return '男'
else if (num == 2) return '女'
else return '保密'
}
//
const input = ref('');
const tableData = reactive([])
//
const pagInfo = reactive({
currentPage: 1,
pageSize: 10,
total: 400
})
function handleChange(currentPage: number, pageSize: number) {
console.log(currentPage, pageSize);
}
//
const isOpen = ref(true);
function cliAddBtn() {
isOpen.value = true
}
</script>
<style lang="scss" scoped>
.fill {
padding-top: 80px;
}
.banner {
width: 100%;
height: 289;
background: linear-gradient(90deg, #FFFFFF 0%, #F0F8FF 100%);
padding: 21px 0 37px 225px;
.box {
width: 1515px;
height: 231px;
display: flex;
gap: 104px;
justify-content: space-between;
align-items: center;
.title-box {
width: 1151px;
.title {
height: 59px;
font-family: Open Sans, Open Sans;
font-weight: bold;
font-size: 42px;
color: #333333;
line-height: 59px;
}
.text {
margin-top: 20px;
font-family: Open Sans, Open Sans;
font-weight: 400;
font-size: 20px;
color: #666666;
line-height: 23px;
}
}
.img-box {
img {
object-fit: cover;
}
}
}
img {
width: 100%;
height: 100%;
object-fit: cover;
}
}
.registration-layout {
margin-top: 20px;
margin: 0 auto;
width: 1397px;
&>* {
background: #FFFFFF;
}
.top {
display: flex;
justify-content: space-between;
margin: 25px 0;
height: 300px;
.com {
width: 685px;
height: 300px;
border-radius: 6px 6px 6px 6px;
padding-top: 22px;
padding-left: 32px;
.title {
height: 28px;
font-family: Microsoft YaHei UI, Microsoft YaHei UI;
font-weight: bold;
font-size: 20px;
color: rgba(0, 0, 0, 0.9);
line-height: 28px;
margin-bottom: 18px;
}
margin-right: 22px;
.content {
display: flex;
gap: 22px;
.card-annual {
padding: 28px 0 0 28px;
width: 340px;
height: 182px;
background: linear-gradient(90deg, #21ACA5 0%, #42D9AC99 100%);
border-radius: 8px;
overflow: hidden;
.annual {
height: 19px;
font-family: Inter, Inter;
font-weight: bold;
font-size: 16px;
color: rgba(255, 255, 255, 0.8);
line-height: 19px;
}
.title-box {
margin-top: 13px;
display: flex;
align-items: center;
gap: 28px;
.text {
width: 202px;
font-family: Inter, Inter;
font-weight: normal;
font-size: 32px;
color: #FFFFFF;
line-height: 39px;
}
}
}
.right {
.info-box {
.name {
height: 20px;
font-family: Microsoft YaHei UI, Microsoft YaHei UI;
font-weight: 400;
font-size: 14px;
color: #ACACAC;
line-height: 20px;
margin-bottom: 8px;
}
.title {
height: 20px;
font-family: Microsoft YaHei UI, Microsoft YaHei UI;
font-weight: bold;
font-size: 20px;
color: #333333;
line-height: 20px;
margin-bottom: 12px;
}
.date-box {
margin-bottom: 12px;
display: flex;
align-items: center;
.label {
height: 20px;
font-family: Microsoft YaHei UI, Microsoft YaHei UI;
font-weight: 400;
font-size: 14px;
color: #ACACAC;
line-height: 20px;
}
.date {
font-family: Microsoft YaHei UI, Microsoft YaHei UI;
font-weight: bold;
font-size: 18px;
color: #333333;
}
}
}
}
}
.track {
.card-annual {
background: url(../../assets/images/item.png) no-repeat;
background-size: cover;
display: flex;
justify-content: center;
align-items: center;
padding: 0;
p {
font-family: Microsoft YaHei UI, Microsoft YaHei UI;
font-weight: bold;
font-size: 40px;
color: #76DAE5;
}
}
}
}
}
.center {
// height: 388px;
border-radius: 6px 6px 6px 6px;
margin-bottom: 25px;
.personage-info {
margin: 30px;
// width: 780px;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
row-gap: 32px;
.head {
width: 100%;
display: flex;
justify-content: space-between;
align-items: center;
.title {
height: 28px;
font-family: Microsoft YaHei UI, Microsoft YaHei UI;
font-weight: bold;
font-size: 20px;
color: rgba(0, 0, 0, 0.9);
line-height: 28px;
}
.icon {
padding: 5px;
cursor: pointer;
}
}
.info-box {
&.remark {
width: 377.333px;
}
width: 176px;
height: 60px;
display: flex;
flex-direction: column;
justify-content: space-between;
.label {
height: 22px;
font-family: Microsoft YaHei UI, Microsoft YaHei UI;
font-weight: 400;
font-size: 14px;
color: rgba(0, 0, 0, 0.4);
line-height: 22px;
}
.text {
height: 22px;
font-family: Microsoft YaHei UI, Microsoft YaHei UI;
font-weight: 400;
font-size: 14px;
color: rgba(0, 0, 0, 0.9);
line-height: 22px;
}
}
}
}
.list {
.head {
padding: 32px;
height: 96px;
background: #FFFFFF;
box-shadow: 0px 2px 3px 0px rgba(0, 0, 0, 0.1);
border-radius: 6px 6px 0px 0px;
display: flex;
justify-content: space-between;
align-items: center;
&>* {
height: 32px;
}
.left {
display: flex;
gap: 12px;
align-items: center;
.btn {
height: 32px;
width: 88px;
background: #42D9AC;
border-radius: 3px 3px 3px 3px;
border: none;
}
.text {
font-family: Microsoft YaHei UI, Microsoft YaHei UI;
font-weight: 400;
font-size: 14px;
color: rgba(0, 0, 0, 0.4);
}
}
}
.table-box {
.table {
width: 100%;
}
.pagin-box {
width: 100%;
height: 64px;
display: flex;
align-items: center;
.pagination {
padding: 0 24px;
:deep() {
.el-pagination__total {
margin-right: auto;
}
li.number.is-active {
background-color: #42D9AC;
color: rgba(255, 255, 255, 0.9);
font-family: Microsoft YaHei UI, Microsoft YaHei UI;
}
span.el-pagination__jump {
background-color: #F3F3F3;
padding: 2px 8px;
}
}
}
}
}
}
.bottom {
margin: 46px 0;
height: 70px;
display: flex;
gap: 106px;
justify-content: center;
align-items: center;
.btn {
--color1: #FFF4CE;
--color2: #FF6B6B;
width: 387px;
height: 69px;
border-radius: 69px;
border: none;
font-family: Microsoft YaHei UI, Microsoft YaHei UI;
font-weight: bold;
font-size: 24px;
color: #FFFFFF;
background: linear-gradient(to right, var(--color1), var(--color2));
box-shadow: 7px 7px 22px -10px rgba(0, 0, 0, 0.22);
transition: all 0.2s;
&:hover {
transform: scale(1.1);
}
&.cyan {
--color1: #00D0D0;
--color2: #42D9AC;
}
}
}
}
</style>

@ -0,0 +1,119 @@
<template>
<el-dialog :modelValue="modelValue" @update:modelValue="(newValue: boolean) => $emit('update:modelValue', newValue)"
title="用户信息" width="800" draggable overflow>
<div class="table-box">
<el-table ref="multipleTableRef" border :data="tableData" @row-click="(row: any) => selectedRow = row"
append-to-body
class="table" v-loading="loading">
<el-table-column label="选择" width="55">
<template #default="scope">
<el-radio v-model="selectedRow" :value="scope.row" />
</template>
</el-table-column>
<el-table-column label="序号">
<template #default="scope">
{{ scope.$index + 1 }}
</template>
</el-table-column>
<el-table-column property="realname" label="真实姓名" sortable />
<el-table-column property="work_no" label="学号" sortable />
</el-table>
</div>
<template #footer>
<div class="pagin-box">
<el-pagination class="pagination" style="width: 100%;" v-model:current-page="params.pageNo"
v-model:page-size="params.pageSize" :page-sizes="[10, 20, 30, 40]"
layout="slo, total,slot, sizes, prev, pager, next, jumper" :total="total" @change="getList" />
</div>
<div class="dialog-footer">
<el-button @click="$emit('update:modelValue', false)">关闭</el-button>
<el-button type="primary"
@click="() => { $emit('update:modelValue', false); $emit('selected', selectedRow); }">确认</el-button>
</div>
</template>
</el-dialog>
</template>
<script lang="ts" setup>
import { reactive, ref, watch } from 'vue';
import { getMembersList } from '@/api/person';
import { useRoute } from 'vue-router';
import { ElMessage } from 'element-plus';
const props = defineProps(['modelValue', 'type']);
const $emit = defineEmits(['update:modelValue', 'selected']);
const route = useRoute();
watch(() => props.modelValue, () => getList());
//
const tableData = reactive<any[]>([]);
const selectedRow = ref();
//
const total = ref(0);
const params = reactive<any>({
pageNo: 1,
pageSize: 10,
onlRepUrlParamStr: `annualCompid=${route.query.objName}`,
entryFormat: '团队',
id: route.query.id,
})
const loading = ref(false);
const getList = async () => {
if (!props.modelValue) return
loading.value = true;
try {
const res: any = await getMembersList(params);
tableData.length = 0;
tableData.push(...res.result.records);
total.value = res.result.total;
} catch (error: any) {
ElMessage({
message: error.message,
type: 'error'
})
} finally {
loading.value = false;
}
}
</script>
<style lang="scss" scoped>
.form-box {
padding: 0 60px;
}
.pagin-box {
width: 100%;
height: 64px;
display: flex;
align-items: center;
.pagination {
padding: 0 24px;
:deep() {
.el-pagination__total {
margin-right: auto;
}
li.number.is-active {
background-color: #42D9AC;
color: rgba(255, 255, 255, 0.9);
font-family: Microsoft YaHei UI, Microsoft YaHei UI;
}
span.el-pagination__jump {
background-color: #F3F3F3;
padding: 2px 8px;
}
}
}
}
</style>

@ -0,0 +1,163 @@
<template>
<div>
<el-button type="primary" icon="Plus" @click="add" class="btn">新增</el-button>
<el-button type="primary" icon="Plus" @click="del" class="btn" v-show="isSele">删除</el-button>
<div class="table-box">
<el-table ref="multipleTableRef" @select="(selection: any[]) => isSele = !!selection.length" border
:data="tableData" class="table" height="276px">
<el-table-column type="selection" width="55" />
<el-table-column label="#" width="55">
<template #default="{ $index }">
{{ $index + 1 }}
</template>
</el-table-column>
<el-table-column>
<template #header>
<el-icon>
<Edit />
</el-icon>
<span style="margin-left: 10px;">用户</span>
</template>
<template #default="{ row }">
<el-input @click="openDialog(row)" v-model="row.realname" placeholder="请选择"
:prefix-icon="ClusterOutlined" />
</template>
</el-table-column>
<el-table-column>
<template #header>
<el-icon>
<Edit />
</el-icon>
<span style="margin-left: 10px;">是否队长</span>
</template>
<template #default="{ row }">
<el-cascader :modelValue="row.captain" @update:modelValue="(arr: any[]) => row.captain = arr[0]"
:options="options" />
</template>
</el-table-column>
<el-table-column>
<template #header>
<el-icon>
<Edit />
</el-icon>
<span style="margin-left: 10px;">队员序号</span>
</template>
<template #default="{ row }">
<el-input v-model="row.teamSeq" />
</template>
</el-table-column>
</el-table>
</div>
<stu-dialog v-model="visible" @selected="handleSelected" />
</div>
</template>
<script lang="ts" setup>
import { reactive, ref } from 'vue';
import stuDialog from './stuDialog.vue';
import { ClusterOutlined } from '@ant-design/icons-vue';
import { ElMessage } from 'element-plus';
const options = [
{
value: '1',
label: '是',
},
{
value: '0',
label: '否',
},
]
//
const tableData = reactive<any[]>([])
const add = () => {
const length = tableData.push({
realname: '', //
captain: '', //
teamSeq: '', //
userId: '', // id
});
openDialog(tableData[length - 1]);
}
// dialogdialog
const target = ref<any>();
const openDialog = (row: any) => {
visible.value = true;
target.value = row;
}
const visible = ref(false);
//
const handleSelected = (row: any = {}) => {
if (tableData.some(o => o.userId === row.id)) {
ElMessage({
message: '用户不能多选!',
type: 'error'
})
return
}
target.value.realname = row.realname;
target.value.userId = row.id;
}
//
defineExpose({ submit: () => tableData })
//
const multipleTableRef = ref<any>(null);
const isSele = ref(false);
const del = () => {
const rows = multipleTableRef.value.getSelectionRows()
rows.forEach((row: any) => {
const index = tableData.indexOf(row);
if (index === -1) return;
tableData.splice(index, 1);
})
}
</script>
<style lang="scss" scoped>
.btn {
margin-bottom: 20px;
}
.table-box {
.table {
width: 100%;
}
.pagin-box {
width: 100%;
height: 64px;
display: flex;
align-items: center;
.pagination {
padding: 0 24px;
:deep() {
.el-pagination__total {
margin-right: auto;
}
li.number.is-active {
background-color: #42D9AC;
color: rgba(255, 255, 255, 0.9);
font-family: Microsoft YaHei UI, Microsoft YaHei UI;
}
span.el-pagination__jump {
background-color: #F3F3F3;
padding: 2px 8px;
}
}
}
}
}
</style>

@ -0,0 +1,122 @@
<template>
<el-dialog :modelValue="modelValue" @update:modelValue="(newValue: boolean) => $emit('update:modelValue', newValue)"
append-to-body
title="用户信息" width="1000" draggable overflow>
<div class="table-box">
<el-table ref="multipleTableRef" border :data="tableData" @row-click="(row: any) => selectedRow = row"
class="table" v-loading="loading">
<el-table-column label="选择" width="55">
<template #default="scope">
<el-radio v-model="selectedRow" :value="scope.row" />
</template>
</el-table-column>
<el-table-column label="序号">
<template #default="scope">
{{ scope.$index + 1 }}
</template>
</el-table-column>
<el-table-column property="realname" label="名字" sortable />
<el-table-column property="exp_title" label="学历" sortable />
<el-table-column property="exp_zc" label="职称" sortable />
<el-table-column property="teamajor" label="专业" sortable />
<el-table-column property="exp_yjfx" label="研究方向" sortable />
<el-table-column property="phone" label="电话" sortable />
</el-table>
<div class="pagin-box">
<el-pagination class="pagination" style="width: 100%;" v-model:current-page="params.pageNo"
v-model:page-size="params.pageSize" :page-sizes="[10, 20, 30, 40]"
layout="slo, total,slot, sizes, prev, pager, next, jumper" :total="total" @change="getList" />
</div>
</div>
<template #footer>
<div class="dialog-footer">
<el-button @click="$emit('update:modelValue', false)">关闭</el-button>
<el-button type="primary"
@click="() => { $emit('update:modelValue', false); $emit('selected', selectedRow); }">确认</el-button>
</div>
</template>
</el-dialog>
</template>
<script lang="ts" setup>
import { reactive, ref, watch } from 'vue';
import { getAdviserList } from '@/api/person';
import { useRoute } from 'vue-router';
import { ElMessage } from 'element-plus';
const props = defineProps(['modelValue', 'type']);
const $emit = defineEmits(['update:modelValue', 'selected']);
const route = useRoute();
watch(() => props.modelValue, () => getList());
//
const tableData = reactive<any[]>([]);
const selectedRow = ref();
//
const total = ref(0);
const params = reactive<any>({
pageNo: 1,
pageSize: 10,
onlRepUrlParamStr: `annualCompid=${route.query.objName}`,
entryFormat: '团队',
id: route.query.id,
})
const loading = ref(false);
const getList = async () => {
if (!props.modelValue) return
loading.value = true;
try {
const res: any = await getAdviserList(params);
tableData.length = 0;
tableData.push(...res.result.records);
total.value = res.result.total;
} catch (error: any) {
ElMessage({
message: error.message,
type: 'error'
})
} finally {
loading.value = false;
}
}
</script>
<style lang="scss" scoped>
.form-box {
padding: 0 60px;
}
.pagin-box {
width: 100%;
height: 64px;
display: flex;
align-items: center;
.pagination {
padding: 0 24px;
:deep() {
.el-pagination__total {
margin-right: auto;
}
li.number.is-active {
background-color: #42D9AC;
color: rgba(255, 255, 255, 0.9);
font-family: Microsoft YaHei UI, Microsoft YaHei UI;
}
span.el-pagination__jump {
background-color: #F3F3F3;
padding: 2px 8px;
}
}
}
}
</style>

@ -0,0 +1,217 @@
<template>
<div>
<el-button type="primary" icon="Plus" @click="add" class="btn">新增</el-button>
<el-button type="primary" icon="Plus" @click="del" class="btn" v-show="isSele">删除</el-button>
<div class="table-box">
<el-table ref="multipleTableRef" border :data="tableData"
@select="(selection: any[]) => isSele = !!selection.length" height="276px">
<el-table-column type="selection" width="55" />
<el-table-column label="#" width="55">
<template #default="{ $index }">
{{ $index + 1 }}
</template>
</el-table-column>
<el-table-column>
<template #header>
<el-icon>
<Edit />
</el-icon>
<span style="margin-left: 10px;">指导老师类型</span>
</template>
<template #default="{ row }">
<el-cascader :modelValue="row.teacherType"
@update:modelValue="(arr: any[]) => row.teacherType = arr[0]" :options="options" />
</template>
</el-table-column>
<el-table-column>
<template #header>
<el-icon>
<Edit />
</el-icon>
<span style="margin-left: 10px;">指导老师姓名</span>
</template>
<template #default="{ row }">
<el-input @click="openDialog(row)" v-model="row.teacherName" placeholder="请选择"
:prefix-icon="ClusterOutlined" />
</template>
</el-table-column>
<el-table-column>
<template #header>
<el-icon>
<Edit />
</el-icon>
<span style="margin-left: 10px;">学历</span>
</template>
<template #default="{ row }">
<el-input v-model="row.teacherXl" placeholder="请输入学历" />
</template>
</el-table-column>
<el-table-column>
<template #header>
<el-icon>
<Edit />
</el-icon>
<span style="margin-left: 10px;">职称</span>
</template>
<template #default="{ row }">
<el-input v-model="row.teacherZc" placeholder="请输入职称" />
</template>
</el-table-column>
<el-table-column>
<template #header>
<el-icon>
<Edit />
</el-icon>
<span style="margin-left: 10px;">专业</span>
</template>
<template #default="{ row }">
<el-input v-model="row.teacherZy" placeholder="请输入专业" />
</template>
</el-table-column>
<el-table-column>
<template #header>
<el-icon>
<Edit />
</el-icon>
<span style="margin-left: 10px;">研究方向</span>
</template>
<template #default="{ row }">
<el-input v-model="row.teacherYjfx" placeholder="请输入研究方向" />
</template>
</el-table-column>
<el-table-column>
<template #header>
<el-icon>
<Edit />
</el-icon>
<span style="margin-left: 10px;">手机号</span>
</template>
<template #default="{ row }">
<el-input v-model="row.teacherPhone" placeholder="请输入手机号" />
</template>
</el-table-column>
</el-table>
</div>
<tea-dialog v-model="visible" @selected="handleSelected" />
</div>
</template>
<script lang="ts" setup>
import { reactive, ref } from 'vue';
import teaDialog from './teaDialog.vue';
import { ClusterOutlined } from '@ant-design/icons-vue';
import { ElMessage } from 'element-plus';
const options = [
{
value: '1',
label: '指导老师',
},
{
value: '2',
label: '领队老师',
},
]
//
const tableData = reactive<any[]>([])
const add = () => {
const length = tableData.push({
teacherName: '',
teacherPhone: '',
teacherType: '',
teacherXl: '',
teacherYjfx: '',
teacherZc: '',
teacherZy: '',
teacherid: '',
});
openDialog(tableData[length - 1]);
}
// dialogdialog
const target = ref<any>();
const openDialog = (row: any) => {
visible.value = true;
target.value = row;
}
const visible = ref(false);
//
const handleSelected = (row: any = {}) => {
if (tableData.some(o => o.id === row.id)) {
ElMessage({
message: '用户不能多选!',
type: 'error'
})
return
}
target.value.teacherName = row.realname;
target.value.teacherXl = row.exp_title;
target.value.teacherZc = row.exp_zc;
target.value.teacherZy = row.teamajor;
target.value.teacherYjfx = row.exp_yjfx;
target.value.teacherPhone = row.phone;
target.value.teacherid = row.user_id;
}
//
const submit = () => tableData;
defineExpose({ submit })
//
const multipleTableRef = ref<any>(null);
const isSele = ref(false);
const del = () => {
const rows = multipleTableRef.value.getSelectionRows()
rows.forEach((row: any) => {
const index = tableData.indexOf(row);
if (index === -1) return;
tableData.splice(index, 1);
})
}
</script>
<style lang="scss" scoped>
.btn {
margin-bottom: 20px;
}
.table-box {
.table {
width: 100%;
}
.pagin-box {
width: 100%;
height: 64px;
display: flex;
align-items: center;
.pagination {
padding: 0 24px;
:deep() {
.el-pagination__total {
margin-right: auto;
}
li.number.is-active {
background-color: #42D9AC;
color: rgba(255, 255, 255, 0.9);
font-family: Microsoft YaHei UI, Microsoft YaHei UI;
}
span.el-pagination__jump {
background-color: #F3F3F3;
padding: 2px 8px;
}
}
}
}
}
</style>

@ -78,9 +78,6 @@
<div class="personage-info">
<div class="head">
<div class="title">个人信息</div>
<div class="icon">
<img src="../../assets/images/ellipsis.png" alt="">
</div>
</div>
<div class="info-box">
<div class="label">姓名</div>
@ -106,71 +103,55 @@
<div class="label">邮箱</div>
<div class="text">{{ info.email }}</div>
</div>
<!-- <div class="info-box">
<div class="label">院系</div>
<div class="text">国际教育学院</div>
</div>
<div class="info-box">
<div class="label">专业</div>
<div class="text">软件工程</div>
</div>
<div class="info-box">
<div class="label">指导老师</div>
<div class="text">令狐冲</div>
</div>
<div class="info-box">
<div class="label">所属团队</div>
<div class="text">王不留行的团队</div>
</div>
<div class="info-box remark">
<div class="label">其它备注</div>
<div class="text"></div>
</div> -->
</div>
</el-card>
<el-card class="list" :body-style="{ padding: 0 }">
<div class="head">
<div class="left">
<el-button class="btn" type="primary">添加队员</el-button>
<div class="text">已选2位</div>
</div>
<div class="right">
<el-input v-model="input" style="width: 280px" placeholder="请输入学号进行搜索" suffix-icon="Search" />
<el-card class="list">
<div class="table-box">
<div>
<el-form ref="ruleFormRef" style="max-width: 600px" :model="ruleForm" status-icon :rules="rules"
label-width="auto" class="demo-ruleForm">
<el-form-item label="年度比赛项目">
<el-input v-model="ruleForm.annualCompid" type="text" disabled />
</el-form-item>
<el-form-item label="参赛形式">
<el-input v-model="ruleForm.entryFormat" type="text" disabled />
</el-form-item>
<el-form-item label="队伍名称" prop="teamName">
<el-input v-model.number="ruleForm.teamName" />
</el-form-item>
</el-form>
</div>
</div>
<div class="table-box">
<el-table ref="multipleTableRef" border :data="tableData" class="table">
<el-table-column type="selection" width="55" />
<el-table-column property="stuNum" label="学号" sortable />
<el-table-column property="name" label="姓名" sortable />
<el-table-column property="department" label="院系" sortable />
<el-table-column property="phone" label="手机号" sortable />
</el-table>
<div class="pagin-box">
<el-pagination class="pagination" style="width: 100%;" v-model:current-page="pagInfo.currentPage"
v-model:page-size="pagInfo.pageSize" :page-sizes="[10, 20, 30, 40]"
layout="slo, total,slot, sizes, prev, pager, next, jumper" :total="pagInfo.total"
@change="handleChange" />
<el-tabs v-model="activeName">
<el-tab-pane label="团队成员表" name="members" />
<el-tab-pane label="指导老师表" name="adviser" />
</el-tabs>
<!-- 动画区域 -->
<div class="animation-box" :class="{ translate: activeName === 'adviser' }">
<stu-list ref="stuRef"/>
<tea-list ref="teaRef"/>
</div>
</div>
</el-card>
<div class="bottom">
<el-button class="btn">取消报名</el-button>
<el-button class="btn cyan">确认报名</el-button>
<el-button class="btn" @click="$router.push('/')">取消报名</el-button>
<el-button class="btn cyan" @click="submit" :loading="loading">确认报名</el-button>
</div>
</div>
</template>
<script lang="ts" setup>
import { reactive, ref, toRefs } from 'vue';
import { useRoute } from 'vue-router';
import userStore from '@/store/module/user';
import type { FormInstance, FormRules } from 'element-plus';
import { ElMessage } from 'element-plus';
import { getSignUpApi } from '@/api/person';
import stuList from './components/stuList.vue';
import teaList from './components/teaList.vue';
const user = userStore();
const route = useRoute();
//
const { userInfo: info } = toRefs(user);
@ -182,85 +163,69 @@ function pasSex(num: number) {
else return '保密'
}
const input = ref('');
const tableData = [
{
id: 1,
stuNum: '20230101',
name: '张三',
department: '软件工程',
phone: '13598664456',
},
{
id: 2,
stuNum: '20230101',
name: '张三',
department: '软件工程',
phone: '13598664456',
},
{
id: 3,
stuNum: '20230101',
name: '张三',
department: '软件工程',
phone: '13598664456',
},
{
id: 4,
stuNum: '20230101',
name: '张三',
department: '软件工程',
phone: '13598664456',
},
{
id: 4,
stuNum: '20230101',
name: '张三',
department: '软件工程',
phone: '13598664456',
},
{
id: 4,
stuNum: '20230101',
name: '张三',
department: '软件工程',
phone: '13598664456',
},
{
id: 4,
stuNum: '20230101',
name: '张三',
department: '软件工程',
phone: '13598664456',
},
{
id: 4,
stuNum: '20230101',
name: '张三',
department: '软件工程',
phone: '13598664456',
},
{
id: 4,
stuNum: '20230101',
name: '张三',
department: '软件工程',
phone: '13598664456',
},
]
//
const pagInfo = reactive({
currentPage: 1,
pageSize: 10,
total: 400
// members: adviser:
const activeName = ref('members');
// form
const ruleFormRef = ref<FormInstance>();
const ruleForm = reactive<any>({
annualCompid: route.query.objName,
entryFormat: '团队',
id: route.query.id,
teamName: '', //
instructorSheetList: [], //
teamManagementList: [] //
})
function handleChange(currentPage: number, pageSize: number) {
console.log(currentPage, pageSize);
const rules = reactive<FormRules<typeof ruleForm>>({});
const stuRef = ref<any>(null);
const teaRef = ref<any>(null);
const loading = ref(false);
const submit = () => {
ruleForm.instructorSheetList = [...teaRef.value.submit()]
ruleForm.teamManagementList = [...stuRef.value.submit()]
loading.value = true;
getSignUpApi(ruleForm).then((res: any) => {
ElMessage({
message: res?.message || '报名成功',
type: 'success'
})
}).catch(err => {
ElMessage({
message: err.message,
type: 'error'
})
}).finally(() => loading.value = false)
}
</script>
<style lang="scss" scoped>
.animation-box {
display: flex;
transition: all 0.3s;
gap: 20px;
&.translate {
translate: calc(-100% - 20px);
}
&>* {
width: 100%;
flex-shrink: 0;
}
}
.el-tabs--top {
flex-direction: column;
}
.fill {
padding-top: 80px;
}
@ -561,7 +526,6 @@ function handleChange(currentPage: number, pageSize: number) {
.table-box {
.table {
width: 100%;
height: 276px;
}
.pagin-box {

Loading…
Cancel
Save