This commit is contained in:
guochunsi
2026-01-16 18:35:58 +08:00
parent 61b3745807
commit ebc1366b07
10 changed files with 774 additions and 164 deletions

View File

@@ -0,0 +1,168 @@
<template>
<div class="icon-text" :style="containerStyle">
<el-icon
v-if="icon"
class="icon-text-icon"
:style="iconStyle">
<component :is="icon" />
</el-icon>
<span
v-if="text"
class="icon-text-text"
:style="textStyle">
{{ text }}
</span>
<slot />
</div>
</template>
<script setup lang="ts">
import { computed } from 'vue'
import type { Component } from 'vue'
// 尺寸配置映射(参考 el-tag 的尺寸)
const sizeConfig = {
small: {
iconSize: 14,
textSize: 12,
gap: 4
},
medium: {
iconSize: 16,
textSize: 14,
gap: 4
},
large: {
iconSize: 20,
textSize: 16,
gap: 5
}
}
// 类型颜色映射(与 el-tag 保持一致,提高可读性)
const typeColorMap: Record<string, string> = {
success: '#67c23a', // 成功 - 绿色
danger: '#f56c6c', // 危险 - 红色
warning: '#e6a23c', // 警告 - 橙色
info: '#909399', // 信息 - 灰色
primary: '#409eff' // 主要 - 蓝色
}
interface Props {
// 图标组件Element Plus 图标)
icon?: Component | string
// 文字内容
text?: string
// 类型(类似 el-tag 的 typesuccess、danger、warning、info、primary
type?: 'success' | 'danger' | 'warning' | 'info' | 'primary'
// 尺寸(类似 el-tag 的 sizesmall、medium、large
size?: 'small' | 'medium' | 'large'
// 图标颜色(优先级高于 type
iconColor?: string
// 文字颜色(优先级高于 type
textColor?: string
// 图标尺寸单位px优先级高于 size
iconSize?: number | string
// 文字尺寸单位px优先级高于 size
textSize?: number | string
// 图标和文字之间的间距单位px优先级高于 size
gap?: number | string
// 对齐方式
align?: 'left' | 'center' | 'right'
}
const props = withDefaults(defineProps<Props>(), {
icon: undefined,
text: '',
type: undefined,
size: 'medium',
iconColor: '',
textColor: '',
iconSize: undefined,
textSize: undefined,
gap: undefined,
align: 'left'
})
// 获取实际尺寸配置
const actualSizeConfig = computed(() => {
const config = sizeConfig[props.size]
return {
iconSize: props.iconSize ?? config.iconSize,
textSize: props.textSize ?? config.textSize,
gap: props.gap ?? config.gap
}
})
// 获取实际颜色
const actualIconColor = computed(() => {
if (props.iconColor) return props.iconColor
if (props.type && typeColorMap[props.type]) return typeColorMap[props.type]
return ''
})
const actualTextColor = computed(() => {
if (props.textColor) return props.textColor
if (props.type && typeColorMap[props.type]) return typeColorMap[props.type]
return ''
})
// 容器样式
const containerStyle = computed(() => {
const styles: Record<string, string> = {
display: 'inline-flex',
alignItems: 'center',
gap: `${actualSizeConfig.value.gap}px`
}
if (props.align === 'center') {
styles.justifyContent = 'center'
} else if (props.align === 'right') {
styles.justifyContent = 'flex-end'
}
return styles
})
// 图标样式
const iconStyle = computed(() => {
const styles: Record<string, string> = {
fontSize: `${actualSizeConfig.value.iconSize}px`,
verticalAlign: 'middle'
}
if (actualIconColor.value) {
styles.color = actualIconColor.value
}
return styles
})
// 文字样式
const textStyle = computed(() => {
const styles: Record<string, string> = {
fontSize: `${actualSizeConfig.value.textSize}px`,
verticalAlign: 'middle'
}
if (actualTextColor.value) {
styles.color = actualTextColor.value
}
return styles
})
</script>
<style scoped lang="scss">
.icon-text {
line-height: 1;
.icon-text-icon {
flex-shrink: 0;
}
.icon-text-text {
white-space: nowrap;
}
}
</style>

View File

@@ -16,6 +16,7 @@ import Sign from '/@/components/Sign/index.vue';
import ChinaArea from '/@/components/ChinaArea/index.vue'; import ChinaArea from '/@/components/ChinaArea/index.vue';
import OrgSelector from '/@/components/OrgSelector/index.vue'; import OrgSelector from '/@/components/OrgSelector/index.vue';
import AiEditor from '/@/components/AiEditor/index.vue'; import AiEditor from '/@/components/AiEditor/index.vue';
import IconText from '/@/components/IconText/index.vue';
// 第三方组件 // 第三方组件
import ElementPlus from 'element-plus'; import ElementPlus from 'element-plus';
@@ -56,6 +57,7 @@ export default {
app.component('ChinaArea', ChinaArea); app.component('ChinaArea', ChinaArea);
app.component('OrgSelector', OrgSelector); app.component('OrgSelector', OrgSelector);
app.component('Sign', Sign); app.component('Sign', Sign);
app.component('IconText', IconText);
// 导入全部的elmenet-plus的图标 // 导入全部的elmenet-plus的图标
for (const [key, component] of Object.entries(ElementPlusIconsVue)) { for (const [key, component] of Object.entries(ElementPlusIconsVue)) {

View File

@@ -504,3 +504,60 @@ svg {
.fc-form-row .fc-form-col { .fc-form-row .fc-form-col {
margin-bottom: 18px; margin-bottom: 18px;
} }
/* Tag 标签
------------------------------- */
// 全局优化 el-tag 背景色和文字颜色,提高对比度和可读性
.el-tag {
// 成功类型 - 浅绿背景 + 深绿文字
&.el-tag--success {
--el-tag-bg-color: #f0f9eb !important;
--el-tag-text-color: #67c23a !important;
background-color: #f0f9eb !important;
color: #67c23a !important;
border-color: #b3e19d !important;
}
// 危险类型 - 浅红背景 + 深红文字
&.el-tag--danger {
--el-tag-bg-color: #fef0f0 !important;
--el-tag-text-color: #f56c6c !important;
background-color: #fef0f0 !important;
color: #f56c6c !important;
border-color: #fbc4c4 !important;
}
// 警告类型 - 浅黄背景 + 深橙文字
&.el-tag--warning {
--el-tag-bg-color: #fdf6ec !important;
--el-tag-text-color: #e6a23c !important;
background-color: #fdf6ec !important;
color: #e6a23c !important;
border-color: #f5dab1 !important;
}
// 信息类型 - 浅灰背景 + 深灰文字
&.el-tag--info {
--el-tag-bg-color: #f4f4f5 !important;
--el-tag-text-color: #909399 !important;
background-color: #f4f4f5 !important;
color: #909399 !important;
border-color: #d3d4d6 !important;
}
// 主要类型 - 浅蓝背景 + 深蓝文字
&.el-tag--primary {
--el-tag-bg-color: #ecf5ff !important;
--el-tag-text-color: #409eff !important;
background-color: #ecf5ff !important;
color: #409eff !important;
border-color: #b3d8ff !important;
}
// 确保文字颜色应用到所有子元素
.el-tag__content,
.el-icon,
.el-tag__close {
color: inherit !important;
}
}

View File

@@ -6,7 +6,7 @@
<template #footer> <template #footer>
<div class="dialog-footer"> <div class="dialog-footer">
<el-button @click="handleClose"> </el-button> <el-button @click="handleClose"> </el-button>
<el-button @click="handleConfirm" v-if="props.permissions.sureLQTZ && canConfirm" type="primary">确认已发放</el-button> <el-button @click="handleConfirm" v-auth="'recruit_recruitstudentsignup_sureLQTZ'" v-if="canConfirm" type="primary">确认已发放</el-button>
</div> </div>
</template> </template>
</el-dialog> </el-dialog>
@@ -19,12 +19,6 @@ import { toWord, sureLQTZ } from '/@/api/recruit/recruitstudentsignup'
export default { export default {
name: 'AdmissionNoticeDialog', name: 'AdmissionNoticeDialog',
props: {
permissions: {
type: Object,
default: () => ({})
}
},
emits: ['refresh'], emits: ['refresh'],
setup(props, { emit }) { setup(props, { emit }) {
const visible = ref(false) const visible = ref(false)

View File

@@ -271,16 +271,15 @@
<el-row> <el-row>
<div class="mb15" style="width: 100%;"> <div class="mb15" style="width: 100%;">
<el-button <el-button
class="ml10"
type="primary" type="primary"
icon="Plus" icon="FolderAdd"
v-if="permissions.recruit_send_img" v-auth="'recruit_send_img'"
@click="handleAddData">新增 @click="handleAddData">新增
</el-button> </el-button>
<el-button <el-button
type="warning" type="warning"
plain plain
v-if="permissions.zipExport" v-auth="'zipExport'"
icon="Download" icon="Download"
@click="downZip()">招生名单打包导出 @click="downZip()">招生名单打包导出
</el-button> </el-button>
@@ -296,7 +295,7 @@
type="primary" type="primary"
plain plain
icon="UploadFilled" icon="UploadFilled"
v-if="permissions.recruit_send_img" v-auth="'recruit_send_img'"
@click="handleSendImg()">图片同步 @click="handleSendImg()">图片同步
</el-button> </el-button>
</div> </div>
@@ -314,59 +313,18 @@
<el-table-column <el-table-column
header-align="center" header-align="center"
align="center" align="center"
width="140"
label="操作"> label="操作">
<template #default="scope"> <template #default="scope">
<el-button type="text" size="small" icon="el-icon-view" @click="addOrUpdateHandle(scope.row.id,0)">查看 <div style="display: flex; align-items: center;">
<el-button type="primary" link icon="Document" @click="addOrUpdateHandle(scope.row.id,0)">
查看
</el-button> </el-button>
<el-button v-if="permissions.recruit_recruitstudentsignup_edit" type="text" size="small" <ActionDropdown
icon="el-icon-edit" @click="edit(scope.row.id)">补材料 :items="getActionMenuItems(scope.row)"
</el-button> @command="(command) => handleMoreCommand(command, scope.row)"
/>
<el-button </div>
v-if="permissions.recruit_recruitstudentsignup_interview && scope.row.degreeOfEducation == '3'"
type="text" size="small"
icon="el-icon-check" @click="interviewForm(scope.row)">面试
</el-button>
<el-button v-if="permissions.recruit_recruitstudentsignup_edit && scope.row.auditStatus=='0'"
type="text" size="small" icon="iconfont icon-rizhiguanli"
@click="addOrUpdateHandle(scope.row.id,1)">审核
</el-button>
<el-button
v-if="permissions.recruit_recruitstudentsignup_leaveSchool && scope.row.auditStatus=='20' && scope.row.isMajorChange!='1'"
type="text" size="small" icon="el-icon-circle-close"
@click="handleUpdate(scope.row.id,scope.row.groupId,scope.row.feeAgency)">退学
</el-button>
<el-button v-if="permissions.recruit_recruitstudentsignup_change && scope.row.auditStatus=='20' "
type="text" size="small" @click="majorChange(scope.row.id)">
调整专业
</el-button>
<el-button
v-if="permissions.recruit_recruitstudentsignup_show && scope.row.pushed=='1' && scope.row.paiedOffline!='10'"
type="text" icon="el-icon-tickets" size="small" plain @click="showPayCode(scope.row)">支付二维码
</el-button>
<!-- <el-button v-if="permissions.recruit_recruitstudentsignup_show && scope.row.pushed=='1' && scope.row.paiedOffline=='0' && scope.row.auditStatus=='20'" type="text" icon="el-icon-check" size="small" @click="delayPayTimeSet(scope.row)">延迟收费</el-button>-->
<!-- <el-button-->
<!-- v-if="permissions.recruit_recruitstudentsignup_rePush && scope.row.pushed=='0' && scope.row.auditStatus=='20'"-->
<!-- type="text" icon="el-icon-check" size="small" plain @click="handleRePush(scope.row)">重新推送-->
<!-- </el-button>-->
<el-button
v-if="permissions.recruit_recruitstudentsignup_show && ((scope.row.degreeOfEducation=='1'&& scope.row.isOut=='1' && scope.row.auditStatus=='20')
|| (scope.row.degreeOfEducation=='1'&& scope.row.isOut=='0' && scope.row.paiedOffline!='0' && scope.row.auditStatus=='20')
|| (scope.row.degreeOfEducation=='2' && scope.row.isGradePic=='1' && scope.row.paiedOffline!='0' && scope.row.auditStatus=='20')
|| (scope.row.degreeOfEducation=='3' && scope.row.isGradePic=='1' && scope.row.paiedOffline!='0' && scope.row.auditStatus=='20')
) "
type="text" icon="el-icon-check" size="small" plain @click="lqtz(scope.row)">录取通知书
</el-button>
<el-button
v-if="permissions.recruit_recruitstudentsignup_show && scope.row.paiedOffline!='0' && scope.row.auditStatus=='20'"
type="text" icon="el-icon-check" size="small" plain @click="infoTable(scope.row)">信息表
</el-button>
<!-- <el-button v-if="permissions.recruit_recruitstudentsignup_push && scope.row.auditStatus=='20'" type="text"-->
<!-- icon="el-icon-upload" size="small" plain @click="handlePushCity(scope.row.id)">推送市局-->
<!-- </el-button>-->
</template> </template>
</el-table-column> </el-table-column>
@@ -374,7 +332,7 @@
prop="serialNumber" prop="serialNumber"
header-align="center" header-align="center"
align="center" align="center"
width="120" width="110"
label="唯一号"> label="唯一号">
</el-table-column> </el-table-column>
<el-table-column <el-table-column
@@ -389,64 +347,180 @@
prop="name" prop="name"
header-align="center" header-align="center"
align="left" align="left"
width="250" min-width="250"
label="资料检测"> label="资料检测">
<template #default="scope"> <template #default="scope">
<div v-if="scope.row.isOut=='0'"> <div v-if="scope.row.isOut=='0'" class="material-check-cell">
<span >资料审核状态:</span> <!-- 资料审核状态 -->
<span style="color: #b4bccc" v-if="scope.row.zlsh=='0'">未填写</span> <div class="check-item">
<span style="color: green" v-if="scope.row.zlsh=='2' && scope.row.isOut=='0'">通过</span> <span class="check-label">审核状态</span>
<span style="color: #ff9900" v-if="scope.row.zlsh=='1' && scope.row.isOut=='0'">待审核</span> <el-tag v-if="scope.row.zlsh=='0'" type="info" size="small">未填写</el-tag>
<span style="color: red" v-if="scope.row.zlsh=='3' && scope.row.isOut=='0'">驳回</span> <el-tag v-else-if="scope.row.zlsh=='2'" type="success" size="small">
<br/> <el-icon class="tag-icon"><CircleCheck /></el-icon>
<span v-if="scope.row.zlsh !='2'">材料状态:</span> 审核通过
<span style="color: #ff9900" v-if="!scope.row.graPic && scope.row.zlsh !='2'">缺少毕业证</span> </el-tag>
<span style="color: #3c763d" v-if="scope.row.degreeOfEducation == '1' && scope.row.isOut == '1'">无需上传</span> <el-tag v-else-if="scope.row.zlsh=='1'" type="warning" size="small">待审核</el-tag>
<span style="color: #ff9900" v-if="scope.row.degreeOfEducation == '1' && scope.row.zlsh !='2' && !scope.row.yyPic && !scope.row.housePic && !scope.row.sbPic">, 缺新市民材料</span> <el-tag v-else-if="scope.row.zlsh=='3'" type="danger" size="small">
<br /> <el-icon class="tag-icon"><CircleClose /></el-icon>
<span v-if="scope.row.zlsh=='3' && scope.row.zlshRemark !='' && scope.row.zlshRemark !=null">资料审核意见:</span> 审核驳回
<span style="color: red" v-if="scope.row.zlsh=='3' && scope.row.zlshRemark !='' && scope.row.zlshRemark !=null">{{scope.row.zlshRemark}}</span> </el-tag>
</div> </div>
<!-- 材料状态 -->
<div v-if="scope.row.zlsh !='2'" class="check-item">
<span class="check-label">材料状态</span>
<div class="material-status">
<el-tag v-if="!scope.row.graPic" type="warning" size="small" class="material-tag">
<el-icon class="tag-icon"><Warning /></el-icon>
缺少毕业证
</el-tag>
<el-tag v-if="scope.row.degreeOfEducation == '1' && scope.row.zlsh !='2' && !scope.row.yyPic && !scope.row.housePic && !scope.row.sbPic" type="warning" size="small" class="material-tag">
<el-icon class="tag-icon"><Warning /></el-icon>
缺新市民材料
</el-tag>
<span v-if="scope.row.degreeOfEducation == '1' && scope.row.isOut == '1'" class="no-upload-text">无需上传</span>
</div>
</div>
<!-- 审核意见 -->
<div v-if="scope.row.zlsh=='3' && scope.row.zlshRemark" class="check-item check-remark">
<span class="check-label">审核意见</span>
<div class="remark-content">
<el-icon class="remark-icon"><Warning /></el-icon>
<el-tooltip :content="scope.row.zlshRemark" placement="top" :show-after="300">
<span class="remark-text">{{ scope.row.zlshRemark }}</span>
</el-tooltip>
</div>
</div>
</div>
<span v-else class="empty-text">-</span>
</template>
</el-table-column>
<el-table-column
header-align="center"
align="center"
label="录取专业">
<el-table-column
prop="auditStatus"
header-align="center"
align="center"
width="110"
label="录取状态">
<template #default="scope">
<el-tag
v-if="getAuditStatusTagType(scope.row.auditStatus)"
:type="getAuditStatusTagType(scope.row.auditStatus)"
>
{{ getLabelValue(auditStatusList, scope.row.auditStatus) }}
</el-tag>
<span v-else class="empty-text">-</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
prop="confirmedMajor" prop="confirmedMajor"
header-align="center" header-align="center"
align="left" align="left"
label="录取专业"> min-width="180"
label="专业名称">
<template #default="scope"> <template #default="scope">
<span>录取状态:</span> <div v-if="scope.row.auditStatus==20" class="major-name">
<span v-if="scope.row.auditStatus==0" <el-icon class="major-icon"><Document /></el-icon>
style="color: orange">{{ getLabelValue(auditStatusList, scope.row.auditStatus) }}</span> <span class="major-text">{{ getMajorLabelWithYears(planMajorList, scope.row.confirmedMajor, { key: 'majorCode', value: 'majorName' }) }}</span>
<span v-if="scope.row.auditStatus==20"
style="color: green">{{ getLabelValue(auditStatusList, scope.row.auditStatus) }}</span>
<span v-if="scope.row.auditStatus==-20"
style="color: red">{{ getLabelValue(auditStatusList, scope.row.auditStatus) }}</span>
<br/>
<div v-if="scope.row.auditStatus==20">
录取专业:
{{ getMajorLabelWithYears(planMajorList, scope.row.confirmedMajor, { key: 'majorCode', value: 'majorName' }) }}<br/>
</div>
<div v-if="scope.row.auditStatus==20">
录取时间:{{ dateFormat(scope.row.auditTime) }}
</div>
<div v-if="scope.row.degreeOfEducation == '3'">
面试结果:{{ getLabelValue(interviewDicList, scope.row.interview) }}
<span v-if="scope.row.interview == '-1' && scope.row.interviewReason"
style="color: #ff9900">({{ scope.row.interviewReason }})</span>
</div>
<div v-if="scope.row.confirmedMajor">
证书发放:
<span v-if="scope.row.isBackTz=='0'" style="color: red">未发放</span>
<span v-if="scope.row.isBackTz=='1'" style="color: green">已发放</span>
</div>
<div v-if="scope.row.confirmedMajor">
发放人:
<span v-if="scope.row.isBackTz=='0'" style="color: red"></span>
<span v-if="scope.row.isBackTz=='1'" style="color: green">{{ scope.row.sendUserName }}</span>
</div> </div>
<span v-else class="empty-text">-</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column
prop="auditTime"
header-align="center"
align="center"
width="110"
label="录取时间">
<template #default="scope">
<span v-if="scope.row.auditStatus==20" class="time-text">{{ dateFormat(scope.row.auditTime) }}</span>
<span v-else class="empty-text">-</span>
</template>
</el-table-column>
<el-table-column
prop="interview"
header-align="center"
align="center"
width="110"
label="面试结果">
<template #default="scope">
<div v-if="scope.row.degreeOfEducation == '3'" class="interview-cell">
<!-- <IconText
v-if="scope.row.interview == '1'"
:icon="CircleCheck"
:text="getLabelValue(interviewDicList, scope.row.interview)"
type="success"
size="small"
align="center"
/>
<IconText
v-else-if="scope.row.interview == '-1'"
:icon="CircleClose"
:text="getLabelValue(interviewDicList, scope.row.interview)"
type="danger"
size="small"
align="center"
/>
<IconText
v-else
:text="getLabelValue(interviewDicList, scope.row.interview)"
type="info"
size="small"
align="center"
/> -->
<span>{{ getLabelValue(interviewDicList, scope.row.interview) }}</span>
<div v-if="scope.row.interview == '-1' && scope.row.interviewReason" class="interview-reason">
<el-icon class="reason-icon"><Warning /></el-icon>
<el-tooltip :content="scope.row.interviewReason" placement="top" :show-after="300">
<span class="reason-text">{{ scope.row.interviewReason }}</span>
</el-tooltip>
</div>
</div>
<span v-else class="empty-text">-</span>
</template>
</el-table-column>
<el-table-column
prop="isBackTz"
header-align="center"
align="center"
min-width="150"
label="证书发放/发放人">
<template #default="scope">
<div v-if="scope.row.confirmedMajor" class="certificate-sender-cell">
<!-- <div class="certificate-status">
<IconText
v-if="scope.row.isBackTz=='0'"
:icon="CircleClose"
text="未发放"
type="danger"
align="center"
/>
<IconText
v-else-if="scope.row.isBackTz=='1'"
:icon="CircleCheck"
text="已发放"
type="success"
align="center"
/>
</div> -->
<span>{{ scope.row.isBackTz=='0' ? '未发放' : scope.row.isBackTz=='1' ? '已发放' : '-' }}</span>
<div v-if="scope.row.isBackTz=='1' && scope.row.sendUserName" class="sender-info">
<span class="sender-separator">/</span>
<IconText
:icon="User"
:text="scope.row.sendUserName"
align="center"
/>
</div>
</div>
<span v-else class="empty-text">-</span>
</template>
</el-table-column>
</el-table-column>
<el-table-column <el-table-column
prop="deptCode" prop="deptCode"
@@ -460,7 +534,8 @@
{{ getLabelValueByProps(deptList, scope.row.deptCode, { key: 'deptCode', value: 'deptName' }) }} {{ getLabelValueByProps(deptList, scope.row.deptCode, { key: 'deptCode', value: 'deptName' }) }}
</span> <br/> </span> <br/>
<span v-if="scope.row.auditStatus==20"> <span v-if="scope.row.auditStatus==20">
({{scope.row.auditorName}}) <span v-if="scope.row.auditorName">({{scope.row.auditorName}})</span>
<span v-else>-</span>
</span> </span>
</template> </template>
@@ -473,7 +548,13 @@
width="90" width="90"
label="缴费状态"> label="缴费状态">
<template #default="scope"> <template #default="scope">
<el-tag
v-if="getPaymentStatusTagType(scope.row.paiedOffline)"
:type="getPaymentStatusTagType(scope.row.paiedOffline)"
>
{{ getStatus(scope.row.paiedOffline) }} {{ getStatus(scope.row.paiedOffline) }}
</el-tag>
<span v-else class="empty-text">{{ getStatus(scope.row.paiedOffline) || '-' }}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
@@ -483,8 +564,11 @@
width="90" width="90"
label="推送状态"> label="推送状态">
<template #default="scope"> <template #default="scope">
<span v-if="scope.row.pushed==0" style="color: red">{{ getPushed(scope.row.pushed) }}</span> <el-tag
<span v-if="scope.row.pushed==1" style="color: green">{{ getPushed(scope.row.pushed) }}</span> :type="scope.row.pushed == '0' ? 'danger' : 'success'"
>
{{ getPushed(scope.row.pushed) }}
</el-tag>
</template> </template>
</el-table-column> </el-table-column>
@@ -511,7 +595,7 @@
<!-- 录取通知书弹窗 --> <!-- 录取通知书弹窗 -->
<AdmissionNoticeDialog ref="admissionNoticeDialogRef" :permissions="permissions" @refresh="getDataList"></AdmissionNoticeDialog> <AdmissionNoticeDialog ref="admissionNoticeDialogRef" @refresh="getDataList"></AdmissionNoticeDialog>
<DormFW ref="dormFWRef"></DormFW> <DormFW ref="dormFWRef"></DormFW>
<ShowMap ref="baiduMapRef"></ShowMap> <ShowMap ref="baiduMapRef"></ShowMap>
@@ -521,11 +605,11 @@
</template> </template>
<script setup lang="ts" name="recruitstudentsignup"> <script setup lang="ts" name="recruitstudentsignup">
import { ref, reactive, computed, onMounted, nextTick, defineAsyncComponent, watch } from 'vue' import { ref, reactive, onMounted, nextTick, defineAsyncComponent, watch } from 'vue'
import { storeToRefs } from 'pinia' import { Edit, Check, DocumentChecked, Close, Switch, Tickets, Document, Upload, Warning, User, CircleCheck, CircleClose } from '@element-plus/icons-vue'
import { useUserInfo } from '/@/stores/userInfo'
import { useMessage, useMessageBox } from '/@/hooks/message' import { useMessage, useMessageBox } from '/@/hooks/message'
import { BasicTableProps, useTable } from '/@/hooks/table' import { BasicTableProps, useTable } from '/@/hooks/table'
import { auth } from '/@/utils/authFunction'
import axios from 'axios' import axios from 'axios'
import { getList } from '/@/api/recruit/recruitstudentplangroup' import { getList } from '/@/api/recruit/recruitstudentplangroup'
import { import {
@@ -561,19 +645,7 @@ const InterviewForm = defineAsyncComponent(() => import('/@/views/recruit/recrui
const PayQrcodeDialog = defineAsyncComponent(() => import('./PayQrcodeDialog.vue')) const PayQrcodeDialog = defineAsyncComponent(() => import('./PayQrcodeDialog.vue'))
const DelayPayTimeDialog = defineAsyncComponent(() => import('./DelayPayTimeDialog.vue')) const DelayPayTimeDialog = defineAsyncComponent(() => import('./DelayPayTimeDialog.vue'))
const AdmissionNoticeDialog = defineAsyncComponent(() => import('./AdmissionNoticeDialog.vue')) const AdmissionNoticeDialog = defineAsyncComponent(() => import('./AdmissionNoticeDialog.vue'))
const ActionDropdown = defineAsyncComponent(() => import('/@/components/tools/action-dropdown.vue'))
// 使用 Pinia store
const userInfoStore = useUserInfo()
const { userInfos } = storeToRefs(userInfoStore)
// 创建权限对象
const permissions = computed(() => {
const perms: Record<string, boolean> = {}
userInfos.value.authBtnList.forEach((perm: string) => {
perms[perm] = true
})
return perms
})
// 消息提示 hooks // 消息提示 hooks
const message = useMessage() const message = useMessage()
@@ -932,6 +1004,26 @@ const resetForm = (formName: string) => {
} }
} }
// 获取录取状态标签类型
const getAuditStatusTagType = (status: string | number) => {
const statusMap: Record<string, string> = {
'0': 'warning',
'20': 'success',
'-20': 'danger'
}
return statusMap[String(status)] || ''
}
// 获取缴费状态标签类型
const getPaymentStatusTagType = (status: string | number) => {
const statusMap: Record<string, string> = {
'0': 'danger', // 未缴费
'5': 'warning', // 部分缴费
'10': 'success' // 已缴费
}
return statusMap[String(status)] || ''
}
// 缴费状态 // 缴费状态
const getStatus = (type: string) => { const getStatus = (type: string) => {
return getLabelValue(paystatusList.value, type) return getLabelValue(paystatusList.value, type)
@@ -1006,6 +1098,116 @@ const interviewForm = (row: any) => {
}) })
} }
// 获取操作菜单项
const getActionMenuItems = (row: any) => {
return [
{
command: 'edit',
label: '补材料',
icon: Edit,
visible: () => auth('recruit_recruitstudentsignup_edit')
},
{
command: 'interview',
label: '面试',
icon: Check,
visible: () => auth('recruit_recruitstudentsignup_interview') && row.degreeOfEducation == '3'
},
{
command: 'audit',
label: '审核',
icon: DocumentChecked,
visible: () => auth('recruit_recruitstudentsignup_edit') && row.auditStatus == '0'
},
{
command: 'leaveSchool',
label: '退学',
icon: Close,
visible: () => auth('recruit_recruitstudentsignup_leaveSchool') && row.auditStatus == '20' && row.isMajorChange != '1'
},
{
command: 'majorChange',
label: '调整专业',
icon: Switch,
visible: () => auth('recruit_recruitstudentsignup_change') && row.auditStatus == '20'
},
{
command: 'payQrcode',
label: '支付二维码',
icon: Tickets,
visible: () => auth('recruit_recruitstudentsignup_show') && row.pushed == '1' && row.paiedOffline != '10'
},
{
command: 'rePush',
label: '重新推送',
icon: Check,
visible: () => auth('recruit_recruitstudentsignup_rePush') && row.pushed == '0' && row.auditStatus == '20'
},
{
command: 'admissionNotice',
label: '录取通知书',
icon: Document,
visible: () => {
if (!auth('recruit_recruitstudentsignup_show')) return false
return (
(row.degreeOfEducation == '1' && row.isOut == '1' && row.auditStatus == '20') ||
(row.degreeOfEducation == '1' && row.isOut == '0' && row.paiedOffline != '0' && row.auditStatus == '20') ||
(row.degreeOfEducation == '2' && row.isGradePic == '1' && row.paiedOffline != '0' && row.auditStatus == '20') ||
(row.degreeOfEducation == '3' && row.isGradePic == '1' && row.paiedOffline != '0' && row.auditStatus == '20')
)
}
},
{
command: 'infoTable',
label: '信息表',
icon: Document,
visible: () => auth('recruit_recruitstudentsignup_show') && row.paiedOffline != '0' && row.auditStatus == '20'
},
{
command: 'pushCity',
label: '推送市局',
icon: Upload,
visible: () => auth('recruit_recruitstudentsignup_push') && row.auditStatus == '20'
}
]
}
// 处理更多操作命令
const handleMoreCommand = (command: string, row: any) => {
switch (command) {
case 'edit':
edit(row.id)
break
case 'interview':
interviewForm(row)
break
case 'audit':
addOrUpdateHandle(row.id, 1)
break
case 'leaveSchool':
handleUpdate(row.id, row.groupId, row.feeAgency)
break
case 'majorChange':
majorChange(row.id)
break
case 'payQrcode':
showPayCode(row)
break
case 'admissionNotice':
lqtz(row)
break
case 'infoTable':
infoTable(row)
break
case 'rePush':
handleRePush(row)
break
case 'pushCity':
handlePushCity(row.id)
break
}
}
// 初始化 // 初始化
const init = async () => { const init = async () => {
// 查询二级学院信息 // 查询二级学院信息
@@ -1059,5 +1261,188 @@ onMounted(() => {
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
// 样式内容 // 空值文本样式
.empty-text {
color: #909399;
font-size: 13px;
}
// 专业名称样式
.major-name {
display: flex;
align-items: center;
gap: 6px;
.major-icon {
color: var(--el-color-primary);
font-size: 14px;
flex-shrink: 0;
}
.major-text {
color: #303133;
font-weight: 500;
font-size: 13px;
}
}
// 时间样式
.time-text {
font-size: 13px;
}
// 面试结果样式
.interview-cell {
display: flex;
flex-direction: column;
align-items: center;
gap: 6px;
.interview-reason {
display: flex;
align-items: center;
gap: 4px;
margin-top: 4px;
.reason-icon {
color: #ff9900;
font-size: 12px;
flex-shrink: 0;
}
.reason-text {
color: #ff9900;
font-size: 12px;
max-width: 85px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
display: inline-block;
vertical-align: middle;
}
}
}
// 证书发放/发放人样式
.certificate-sender-cell {
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
gap: 6px;
flex-wrap: wrap;
.certificate-status {
display: flex;
align-items: center;
justify-content: center;
}
.sender-info {
display: flex;
align-items: center;
justify-content: center;
gap: 4px;
.sender-separator {
color: #c0c4cc;
font-size: 12px;
margin: 0 2px;
}
.sender-icon {
font-size: 13px;
flex-shrink: 0;
}
.sender-text {
font-size: 12px;
}
}
}
// 资料检测样式
.material-check-cell {
display: flex;
flex-direction: column;
gap: 8px;
padding: 4px 0;
.check-item {
display: flex;
align-items: flex-start;
gap: 6px;
line-height: 1.5;
.check-label {
color: #606266;
font-size: 12px;
font-weight: 500;
white-space: nowrap;
flex-shrink: 0;
}
:deep(.el-tag) {
display: inline-flex;
align-items: center;
vertical-align: middle;
gap: 4px;
line-height: 1;
.tag-icon {
font-size: 12px;
vertical-align: middle;
}
}
}
.material-status {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
gap: 6px;
align-items: center;
.material-tag {
margin: 0;
flex-shrink: 0;
}
.no-upload-text {
color: #67c23a;
font-size: 12px;
white-space: nowrap;
}
}
.check-remark {
margin-top: 4px;
.remark-content {
display: flex;
align-items: flex-start;
gap: 4px;
flex: 1;
.remark-icon {
color: #f56c6c;
font-size: 14px;
flex-shrink: 0;
margin-top: 2px;
}
.remark-text {
color: #f56c6c;
font-size: 12px;
line-height: 1.5;
display: inline-block;
max-width: 200px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
vertical-align: top;
}
}
}
}
</style> </style>

View File

@@ -111,11 +111,11 @@
import { ref, reactive, nextTick } from 'vue' import { ref, reactive, nextTick } from 'vue'
import { ElNotification } from 'element-plus' import { ElNotification } from 'element-plus'
import { useMessageBox } from '/@/hooks/message' import { useMessageBox } from '/@/hooks/message'
import { getObj, changeMajor } from '@/api/recruit/recruitstudentsignup' import { getObj, changeMajor } from '/@/api/recruit/recruitstudentsignup'
import { getList } from "@/api/recruit/recruitstudentplangroup" import { getList } from "/@/api/recruit/recruitstudentplangroup"
import { listByEdu } from "@/api/recruit/recruitstudentplan" import { listByEdu } from "/@/api/recruit/recruitstudentplan"
import { getDictByType } from "@/api/contract/contract" import { getDictsByTypes } from "/@/api/admin/dict"
import { list as scoreList } from "@/api/recruit/recruitstudentplancorrectscoreconfig" import { list as scoreList } from "/@/api/recruit/recruitstudentplancorrectscoreconfig"
// 消息提示 hooks // 消息提示 hooks
const messageBox = useMessageBox() const messageBox = useMessageBox()
@@ -323,10 +323,10 @@ const init = (id: string | null) => {
dataFormRef.value?.resetFields() dataFormRef.value?.resetFields()
if (dataForm.id) { if (dataForm.id) {
// 获取数据字典代办费 // 获取数据字典代办费
getDictByType("agency_fee").then((res: any) => { getDictsByTypes(["agency_fee"]).then((res: any) => {
agencyFeeList.value = res.data agencyFeeList.value = res.data
// 获取数据字典学费 // 获取数据字典学费
getDictByType("tuition_fee").then((res: any) => { getDictsByTypes(["tuition_fee"]).then((res: any) => {
tuitionFeeList.value = res.data tuitionFeeList.value = res.data
getObj(dataForm.id).then((response: any) => { getObj(dataForm.id).then((response: any) => {
Object.assign(dataForm, response.data) Object.assign(dataForm, response.data)

View File

@@ -4,14 +4,14 @@
:close-on-click-modal="false" :close-on-click-modal="false"
v-model="visible" v-model="visible"
append-to-body append-to-body
width="90%"> width="1000px">
<el-form :model="dataForm" :rules="dataRule" ref="dataFormRef" @keyup.enter="dataFormSubmit" <el-form :model="dataForm" :rules="dataRule" ref="dataFormRef" @keyup.enter="dataFormSubmit"
label-width="170px" size="small"> label-width="120px">
<el-row> <el-row>
<el-col :span="24"> <el-col :span="24">
<el-form-item label="招生计划" prop="groupId"> <el-form-item label="招生计划" prop="groupId">
<el-select v-model="dataForm.groupId" filterable :disabled="!!dataForm.id" <el-select v-model="dataForm.groupId" filterable :disabled="!!dataForm.id"
placeholder="请选择招生计划" size="small" style="width: 100%"> placeholder="请选择招生计划">
<el-option <el-option
v-for="item in planList" v-for="item in planList"
:key="item.id" :key="item.id"
@@ -23,16 +23,14 @@
</el-col> </el-col>
</el-row> </el-row>
<el-row> <el-row>
<el-col :span="24"> <el-col :span="12">
<el-form-item label="姓名" prop="name"> <el-form-item label="姓名" prop="name">
<el-input type="text" v-model="dataForm.name" :disabled="type != 1"></el-input> <el-input type="text" v-model="dataForm.name" :disabled="type != 1"></el-input>
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> <el-col :span="12">
<el-row>
<el-col :span="24">
<el-form-item label="联系人" prop="contactName"> <el-form-item label="联系人" prop="contactName">
<el-select v-model="dataForm.contactName" filterable clearable placeholder="" size="small" style="width: 100%" :disabled="!(permissions.recruit_recruitprestudent_dj_sure || dataForm.auditStatus != '20')"> <el-select v-model="dataForm.contactName" filterable clearable placeholder="" :disabled="!(permissions.recruit_recruitprestudent_dj_sure || dataForm.auditStatus != '20')">
<el-option <el-option
v-for="item in contactNameList" v-for="item in contactNameList"
:key="item.teacherNo" :key="item.teacherNo"
@@ -43,6 +41,7 @@
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
<el-row> <el-row>
<el-col :span="8"> <el-col :span="8">
<el-form-item label="成绩单" prop="scorePhoto"> <el-form-item label="成绩单" prop="scorePhoto">
@@ -164,7 +163,7 @@
<el-row> <el-row>
<el-col :span="24"> <el-col :span="24">
<el-form-item label="材料审核意见" prop="zlshRemark"> <el-form-item label="材料审核意见" prop="zlshRemark">
<el-input v-model="dataForm.zlshRemark" placeholder="请输入审核意见" type="textarea" :rows="2" style="width: 80%;text-align:center;margin-top: 10px"></el-input> <el-input v-model="dataForm.zlshRemark" placeholder="请输入审核意见" type="textarea" :rows="2" ></el-input>
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
@@ -173,8 +172,8 @@
<div class="dialog-footer"> <div class="dialog-footer">
<el-button @click="visible = false">取消</el-button> <el-button @click="visible = false">取消</el-button>
<el-button type="primary" @click="dataFormSubmit('1')" v-if="canSubmit">保存</el-button> <el-button type="primary" @click="dataFormSubmit('1')" v-if="canSubmit">保存</el-button>
<el-button type="success" @click="dataFormSubmit('2')" v-if="canSubmit">通过</el-button> <el-button type="success" plain @click="dataFormSubmit('2')" v-if="canSubmit">通过</el-button>
<el-button type="danger" @click="dataFormSubmit('3')" v-if="canSubmit">驳回</el-button> <el-button type="danger" plain @click="dataFormSubmit('3')" v-if="canSubmit">驳回</el-button>
</div> </div>
</template> </template>
@@ -192,9 +191,9 @@ import { storeToRefs } from 'pinia'
import { useUserInfo } from '/@/stores/userInfo' import { useUserInfo } from '/@/stores/userInfo'
import { Session } from '/@/utils/storage' import { Session } from '/@/utils/storage'
import axios from 'axios' import axios from 'axios'
import { getObj, updateInfo } from '@/api/recruit/recruitstudentsignup' import { getObj, updateInfo } from '/@/api/recruit/recruitstudentsignup'
import { getList } from "@/api/recruit/recruitstudentplangroup" import { getList } from '/@/api/recruit/recruitstudentplangroup'
import { queryAllTeacher } from "@/api/professional/teacherbase" import { queryAllTeacher } from '/@/api/professional/professionaluser/teacherbase'
// 使用 Pinia store // 使用 Pinia store
const userInfoStore = useUserInfo() const userInfoStore = useUserInfo()
@@ -631,7 +630,12 @@ defineExpose({
}) })
</script> </script>
<style scoped> <style lang="scss" scoped>
.el-form{
.el-form-item:last-of-type{
margin-bottom:18px!important;
}
}
.avatar-uploader-icon { .avatar-uploader-icon {
font-size: 28px; font-size: 28px;
color: #8c939d; color: #8c939d;