提交
This commit is contained in:
1 parent
9310a7323f
commit
384373a2c1
11 files changed
+2053
-1810
No files matched your search
@@ -159,6 +159,32 @@ page {
|
||||
background: #0051d9 !important;
|
||||
}
|
||||
|
||||
/* Navbar导航栏主题色覆盖 - 勤工俭学模块统一背景色 */
|
||||
.u-navbar {
|
||||
background-color: #0051d9 !important;
|
||||
}
|
||||
|
||||
.u-navbar__content {
|
||||
background-color: #0051d9 !important;
|
||||
}
|
||||
|
||||
.u-navbar__content__title {
|
||||
color: #fff !important;
|
||||
}
|
||||
|
||||
/* uni-app 原生导航栏样式覆盖 */
|
||||
uni-page-head {
|
||||
background-color: #0051d9 !important;
|
||||
}
|
||||
|
||||
.uni-page-head {
|
||||
background-color: #0051d9 !important;
|
||||
}
|
||||
|
||||
.uni-page-head__title {
|
||||
color: #fff !important;
|
||||
}
|
||||
|
||||
/* ========== 全局温暖商务风格样式 ========== */
|
||||
|
||||
/* 全局页面背景 */
|
||||
|
||||
@@ -274,7 +274,7 @@
|
||||
"path": "pages/workStudy/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "勤工俭学",
|
||||
"navigationBarBackgroundColor": "#1890ff",
|
||||
"navigationBarBackgroundColor": "#0051d9",
|
||||
"navigationBarTextStyle": "white"
|
||||
}
|
||||
},
|
||||
@@ -282,7 +282,7 @@
|
||||
"path": "pages/workStudy/detail",
|
||||
"style": {
|
||||
"navigationBarTitleText": "岗位详情",
|
||||
"navigationBarBackgroundColor": "#1890ff",
|
||||
"navigationBarBackgroundColor": "#0051d9",
|
||||
"navigationBarTextStyle": "white"
|
||||
}
|
||||
},
|
||||
@@ -290,7 +290,7 @@
|
||||
"path": "pages/workStudy/apply",
|
||||
"style": {
|
||||
"navigationBarTitleText": "申请岗位",
|
||||
"navigationBarBackgroundColor": "#1890ff",
|
||||
"navigationBarBackgroundColor": "#0051d9",
|
||||
"navigationBarTextStyle": "white"
|
||||
}
|
||||
},
|
||||
@@ -298,7 +298,7 @@
|
||||
"path": "pages/workStudy/applicationDetail",
|
||||
"style": {
|
||||
"navigationBarTitleText": "申请详情",
|
||||
"navigationBarBackgroundColor": "#1890ff",
|
||||
"navigationBarBackgroundColor": "#0051d9",
|
||||
"navigationBarTextStyle": "white"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
<template>
|
||||
<view class="internship-page">
|
||||
<!-- 顶部导航 -->
|
||||
<u-navbar title="实习打卡" :border-bottom="false" bg-color="#3c9cff" title-color="#fff">
|
||||
<view slot="left" @click="goBack">
|
||||
<u-icon name="arrow-left" color="#fff" size="22"></u-icon>
|
||||
</view>
|
||||
</u-navbar>
|
||||
|
||||
<!-- 顶部用户信息卡片 -->
|
||||
<view class="user-card">
|
||||
<view class="user-info">
|
||||
@@ -23,8 +30,10 @@
|
||||
<!-- 实习信息卡片 -->
|
||||
<view class="internship-card" v-if="internshipInfo">
|
||||
<view class="card-header">
|
||||
<u-icon name="bookmark" size="18" color="#409eff"></u-icon>
|
||||
<text class="card-title">实习信息</text>
|
||||
<view class="header-left">
|
||||
<u-icon name="file-text" size="18" color="#409eff"></u-icon>
|
||||
<text class="card-title">实习信息</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="internship-info">
|
||||
<view class="info-row">
|
||||
@@ -59,9 +68,11 @@
|
||||
|
||||
<!-- 今日签到卡片 -->
|
||||
<view class="checkin-card">
|
||||
<view class="card-header">
|
||||
<u-icon name="clock" size="18" color="#67c23a"></u-icon>
|
||||
<text class="card-title">今日签到</text>
|
||||
<view class="card-header card-header-between">
|
||||
<view class="header-left">
|
||||
<u-icon name="checkmark-circle" size="18" color="#67c23a"></u-icon>
|
||||
<text class="card-title">今日签到</text>
|
||||
</view>
|
||||
<text class="date-text">{{ currentDate }}</text>
|
||||
</view>
|
||||
|
||||
@@ -85,14 +96,20 @@
|
||||
<view class="checkin-actions" v-else>
|
||||
<u-button
|
||||
type="primary"
|
||||
size="large"
|
||||
shape="round"
|
||||
:loading="checkinLoading"
|
||||
:disabled="checkinLoading || !canCheckin"
|
||||
@click="handleCheckin"
|
||||
:custom-style="checkinButtonStyle"
|
||||
class="checkin-btn"
|
||||
:custom-style="{ height: '88rpx' }"
|
||||
>
|
||||
<u-icon name="map" size="20" color="#fff" style="margin-right: 8px"></u-icon>
|
||||
{{ checkinLoading ? '签到中...' : '立即签到' }}
|
||||
<u-icon
|
||||
name="checkmark-circle"
|
||||
size="20"
|
||||
color="#fff"
|
||||
style="margin-right: 8rpx"
|
||||
></u-icon>
|
||||
<text style="color: #fff">{{ checkinLoading ? '签到中...' : '立即签到' }}</text>
|
||||
</u-button>
|
||||
|
||||
<view class="checkin-tips" v-if="!canCheckin">
|
||||
@@ -106,6 +123,7 @@
|
||||
<view class="location-card">
|
||||
<view class="card-header">
|
||||
<view class="header-left">
|
||||
<u-icon name="map" size="18" color="#f56c6c"></u-icon>
|
||||
<text class="card-title">签到位置</text>
|
||||
</view>
|
||||
</view>
|
||||
@@ -114,14 +132,14 @@
|
||||
<view class="location-row">
|
||||
<u-button
|
||||
type="primary"
|
||||
size="default"
|
||||
plain
|
||||
shape="round"
|
||||
@click="handleGetLocation"
|
||||
:loading="locationLoading"
|
||||
class="location-btn"
|
||||
:custom-style="{ height: '88rpx' }"
|
||||
>
|
||||
<u-icon name="map-fill" size="20" color="#2979ff" />
|
||||
<text style="margin-left: 8rpx">
|
||||
<u-icon name="map-fill" size="20" color="#fff" />
|
||||
<text style="margin-left: 8rpx; color: #fff">
|
||||
{{ checkIsWechatBrowser() ? '微信定位' : '定位' }}
|
||||
</text>
|
||||
</u-button>
|
||||
@@ -129,13 +147,23 @@
|
||||
|
||||
<!-- 位置信息显示 -->
|
||||
<view v-if="currentLocation" class="location-info-section">
|
||||
<!-- 坐标信息 -->
|
||||
<view class="location-coords-container">
|
||||
<!-- 坐标信息和查看位置按钮 -->
|
||||
<view class="location-coords-row">
|
||||
<text class="location-coords">
|
||||
经纬度:{{ currentLocation.latitude.toFixed(6) }},{{
|
||||
currentLocation.longitude.toFixed(6)
|
||||
}}
|
||||
</text>
|
||||
<u-button
|
||||
size="small"
|
||||
type="primary"
|
||||
shape="round"
|
||||
@click="openLocationInMap"
|
||||
class="view-map-btn"
|
||||
>
|
||||
<u-icon name="eye" size="14" color="#fff" />
|
||||
<text style="margin-left: 4rpx; color: #fff">查看位置</text>
|
||||
</u-button>
|
||||
</view>
|
||||
|
||||
<!-- 精度信息 -->
|
||||
@@ -158,20 +186,6 @@
|
||||
></u-tag>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 查看位置按钮 -->
|
||||
<view class="location-action-container">
|
||||
<u-button
|
||||
size="default"
|
||||
type="primary"
|
||||
plain
|
||||
@click="openLocationInMap"
|
||||
class="view-map-btn"
|
||||
>
|
||||
<u-icon name="eye" size="16" color="#2979ff" />
|
||||
<text>查看位置</text>
|
||||
</u-button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -179,7 +193,7 @@
|
||||
<view class="location-error-card" v-if="locationError && !currentLocation">
|
||||
<view class="card-header">
|
||||
<view class="header-left">
|
||||
<u-icon name="map-pin" size="18" color="#f56c6c"></u-icon>
|
||||
<u-icon name="map" size="18" color="#f56c6c"></u-icon>
|
||||
<text class="card-title">位置信息</text>
|
||||
</view>
|
||||
<u-button
|
||||
@@ -243,8 +257,10 @@
|
||||
<!-- 考勤统计 -->
|
||||
<view class="statistics-card">
|
||||
<view class="card-header">
|
||||
<u-icon size="18" color="#e6a23c"></u-icon>
|
||||
<text class="card-title">本月考勤</text>
|
||||
<view class="header-left">
|
||||
<u-icon name="calendar" size="18" color="#e6a23c"></u-icon>
|
||||
<text class="card-title">本月考勤</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="stats-grid">
|
||||
<view class="stat-item">
|
||||
@@ -354,21 +370,15 @@ export default {
|
||||
|
||||
// 当前日期
|
||||
currentDate: '',
|
||||
|
||||
// 样式
|
||||
checkinButtonStyle: {
|
||||
width: '100%',
|
||||
height: '50px',
|
||||
borderRadius: '25px',
|
||||
background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
|
||||
border: 'none',
|
||||
fontSize: '16px',
|
||||
fontWeight: 'bold',
|
||||
},
|
||||
};
|
||||
},
|
||||
|
||||
methods: {
|
||||
// 返回上一页
|
||||
goBack() {
|
||||
uni.navigateBack();
|
||||
},
|
||||
|
||||
// === 微信SDK相关方法 ===
|
||||
|
||||
// 检查微信环境并自动初始化SDK
|
||||
@@ -1435,18 +1445,17 @@ export default {
|
||||
<style scoped>
|
||||
.internship-page {
|
||||
min-height: 100vh;
|
||||
background: #f5f7fa;
|
||||
padding: 16px;
|
||||
background-color: #f5f6fa;
|
||||
padding-bottom: 40rpx;
|
||||
}
|
||||
|
||||
/* 用户信息卡片 */
|
||||
.user-card {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
border-radius: 16px;
|
||||
padding: 20px;
|
||||
margin-bottom: 16px;
|
||||
color: white;
|
||||
box-shadow: 0 8px 32px rgba(102, 126, 234, 0.3);
|
||||
background-color: #ffffff;
|
||||
border-radius: 16rpx;
|
||||
padding: 30rpx;
|
||||
margin: 20rpx;
|
||||
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.user-info {
|
||||
@@ -1455,7 +1464,7 @@ export default {
|
||||
}
|
||||
|
||||
.avatar-section {
|
||||
margin-right: 16px;
|
||||
margin-right: 24rpx;
|
||||
}
|
||||
|
||||
.info-section {
|
||||
@@ -1463,15 +1472,16 @@ export default {
|
||||
}
|
||||
|
||||
.user-name {
|
||||
font-size: 18px;
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
margin-bottom: 4px;
|
||||
color: #303133;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
.user-detail {
|
||||
font-size: 14px;
|
||||
opacity: 0.9;
|
||||
margin-bottom: 2px;
|
||||
font-size: 26rpx;
|
||||
color: #606266;
|
||||
margin-bottom: 4rpx;
|
||||
}
|
||||
|
||||
/* 通用卡片样式 */
|
||||
@@ -1480,216 +1490,222 @@ export default {
|
||||
.location-card,
|
||||
.statistics-card,
|
||||
.records-card {
|
||||
background: white;
|
||||
border-radius: 12px;
|
||||
padding: 16px;
|
||||
margin-bottom: 16px;
|
||||
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
|
||||
background-color: #ffffff;
|
||||
border-radius: 16rpx;
|
||||
padding: 24rpx;
|
||||
margin: 0 20rpx 20rpx 20rpx;
|
||||
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.card-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 16px;
|
||||
padding-bottom: 12px;
|
||||
margin-bottom: 24rpx;
|
||||
padding-bottom: 20rpx;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
min-height: 32px; /* 确保最小高度 */
|
||||
gap: 8px; /* 确保元素之间有间距 */
|
||||
min-height: 48rpx;
|
||||
}
|
||||
|
||||
.card-header-between {
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.header-left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex: 1;
|
||||
min-width: 0; /* 允许flex子项收缩 */
|
||||
margin-right: 12px; /* 与右侧按钮保持距离 */
|
||||
gap: 8rpx;
|
||||
}
|
||||
|
||||
.card-title {
|
||||
font-size: 16px;
|
||||
font-size: 30rpx;
|
||||
font-weight: bold;
|
||||
margin-left: 8px;
|
||||
margin-left: 0;
|
||||
color: #303133;
|
||||
white-space: nowrap; /* 防止文字换行 */
|
||||
overflow: hidden; /* 隐藏溢出文字 */
|
||||
text-overflow: ellipsis; /* 显示省略号 */
|
||||
flex-shrink: 1; /* 允许收缩 */
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.refresh-btn {
|
||||
flex-shrink: 0;
|
||||
min-width: 70px; /* 确保按钮最小宽度 */
|
||||
min-width: 100rpx;
|
||||
}
|
||||
|
||||
.date-text {
|
||||
font-size: 12px;
|
||||
font-size: 24rpx;
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
/* 实习信息 */
|
||||
.internship-info {
|
||||
padding-top: 8px;
|
||||
padding-top: 12rpx;
|
||||
}
|
||||
|
||||
.info-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 8px;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.label {
|
||||
font-size: 14px;
|
||||
font-size: 26rpx;
|
||||
color: #606266;
|
||||
width: 80px;
|
||||
min-width: 140rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.value {
|
||||
font-size: 14px;
|
||||
font-size: 26rpx;
|
||||
color: #303133;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
/* 签到状态 */
|
||||
.checkin-status {
|
||||
padding: 16px;
|
||||
padding: 24rpx;
|
||||
background: #f0f9ff;
|
||||
border-radius: 8px;
|
||||
border-left: 4px solid #67c23a;
|
||||
border-radius: 12rpx;
|
||||
border-left: 6rpx solid #67c23a;
|
||||
}
|
||||
|
||||
.status-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 8px;
|
||||
margin-bottom: 12rpx;
|
||||
}
|
||||
|
||||
.status-text {
|
||||
font-size: 16px;
|
||||
font-size: 30rpx;
|
||||
font-weight: bold;
|
||||
color: #67c23a;
|
||||
margin-left: 8px;
|
||||
margin-left: 12rpx;
|
||||
}
|
||||
|
||||
.time-info,
|
||||
.location-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 4px;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
.time-label,
|
||||
.location-label {
|
||||
font-size: 14px;
|
||||
font-size: 26rpx;
|
||||
color: #606266;
|
||||
margin-right: 8px;
|
||||
margin-right: 12rpx;
|
||||
}
|
||||
|
||||
.time-value,
|
||||
.location-value {
|
||||
font-size: 14px;
|
||||
font-size: 26rpx;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
/* 签到操作 */
|
||||
.checkin-actions {
|
||||
padding: 16px 0;
|
||||
padding: 24rpx 0;
|
||||
}
|
||||
|
||||
.checkin-btn {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.checkin-tips {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-top: 12px;
|
||||
margin-top: 16rpx;
|
||||
}
|
||||
|
||||
.tips-text {
|
||||
font-size: 12px;
|
||||
font-size: 24rpx;
|
||||
color: #909399;
|
||||
margin-left: 4px;
|
||||
margin-left: 8rpx;
|
||||
}
|
||||
|
||||
/* 位置信息(参考请假页面样式) */
|
||||
/* 位置信息 */
|
||||
.location-row {
|
||||
margin-bottom: 16px;
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
|
||||
.location-btn {
|
||||
width: 100%;
|
||||
height: 44px;
|
||||
height: 72rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 8px;
|
||||
border: 1px solid #2979ff;
|
||||
background: #fff;
|
||||
color: #2979ff;
|
||||
border-radius: 12rpx;
|
||||
}
|
||||
|
||||
.location-info-section {
|
||||
margin-top: 16px;
|
||||
padding: 16px;
|
||||
margin-top: 24rpx;
|
||||
padding: 24rpx;
|
||||
background: #f8f9fa;
|
||||
border-radius: 8px;
|
||||
border-radius: 12rpx;
|
||||
border: 1px solid #e4e7ed;
|
||||
}
|
||||
|
||||
.location-coords-container {
|
||||
margin-bottom: 12px;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.location-coords-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 20rpx;
|
||||
gap: 16rpx;
|
||||
}
|
||||
|
||||
.location-coords {
|
||||
font-size: 14px;
|
||||
font-size: 26rpx;
|
||||
color: #303133;
|
||||
font-family: monospace;
|
||||
line-height: 1.5;
|
||||
word-break: break-all;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.location-action-container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-top: 12px;
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
|
||||
.view-map-btn {
|
||||
min-width: 120px;
|
||||
height: 36px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 6px;
|
||||
height: 56rpx !important;
|
||||
min-width: auto !important;
|
||||
width: auto !important;
|
||||
flex-shrink: 0;
|
||||
padding: 0 20rpx !important;
|
||||
}
|
||||
|
||||
/* 精度信息 */
|
||||
.accuracy-section {
|
||||
margin-bottom: 16px;
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
|
||||
.accuracy-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 10px 12px;
|
||||
padding: 16rpx 20rpx;
|
||||
background: #f0f9ff;
|
||||
border-radius: 8px;
|
||||
border-radius: 12rpx;
|
||||
border: 1px solid #b3e5fc;
|
||||
}
|
||||
|
||||
.accuracy-icon {
|
||||
margin-right: 8px;
|
||||
margin-right: 12rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.accuracy-text {
|
||||
font-size: 13px;
|
||||
font-size: 26rpx;
|
||||
color: #67c23a;
|
||||
font-weight: 500;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.accuracy-tag {
|
||||
margin-left: 8px;
|
||||
margin-left: 12rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
@@ -1697,41 +1713,37 @@ export default {
|
||||
.location-actions {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-top: 4px; /* 与上方内容保持间距 */
|
||||
margin-top: 12rpx;
|
||||
}
|
||||
|
||||
.map-btn {
|
||||
min-width: 140px;
|
||||
width: 100%; /* 在小屏幕上占满宽度 */
|
||||
max-width: 200px; /* 最大宽度限制 */
|
||||
min-width: 200rpx;
|
||||
width: 100%;
|
||||
max-width: 300rpx;
|
||||
}
|
||||
|
||||
.btn-text {
|
||||
margin-left: 6px;
|
||||
margin-left: 8rpx;
|
||||
}
|
||||
|
||||
/* 小屏幕适配 */
|
||||
@media screen and (max-width: 375px) {
|
||||
.card-header {
|
||||
flex-wrap: nowrap; /* 保持单行,避免换行 */
|
||||
gap: 4px;
|
||||
min-height: 36px; /* 稍微增加高度 */
|
||||
flex-wrap: nowrap;
|
||||
min-height: 36px;
|
||||
}
|
||||
|
||||
.header-left {
|
||||
min-width: 0; /* 允许完全收缩 */
|
||||
flex: 1;
|
||||
margin-right: 6px;
|
||||
gap: 6rpx;
|
||||
}
|
||||
|
||||
.card-title {
|
||||
font-size: 15px; /* 稍微减小字体 */
|
||||
max-width: 100px; /* 限制最大宽度 */
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.refresh-btn {
|
||||
min-width: 58px; /* 小屏幕下减小按钮宽度 */
|
||||
font-size: 12px; /* 减小按钮字体 */
|
||||
min-width: 58px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.map-btn {
|
||||
@@ -1742,17 +1754,12 @@ export default {
|
||||
|
||||
/* 极小屏幕适配(iPhone SE等) */
|
||||
@media screen and (max-width: 320px) {
|
||||
.card-header {
|
||||
gap: 2px;
|
||||
}
|
||||
|
||||
.header-left {
|
||||
margin-right: 4px;
|
||||
gap: 4rpx;
|
||||
}
|
||||
|
||||
.card-title {
|
||||
font-size: 14px;
|
||||
max-width: 80px;
|
||||
font-size: 26rpx;
|
||||
}
|
||||
|
||||
.refresh-btn {
|
||||
@@ -1783,55 +1790,55 @@ export default {
|
||||
.location-error-card {
|
||||
background: #fffbe6;
|
||||
border: 1px solid #ffe58f;
|
||||
border-radius: 12px;
|
||||
padding: 16px;
|
||||
margin-bottom: 16px;
|
||||
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
|
||||
border-radius: 16rpx;
|
||||
padding: 24rpx;
|
||||
margin: 0 20rpx 20rpx 20rpx;
|
||||
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.error-content {
|
||||
padding-top: 8px;
|
||||
padding-top: 12rpx;
|
||||
}
|
||||
|
||||
.error-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-bottom: 16px;
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
|
||||
.error-icon {
|
||||
margin-right: 8px;
|
||||
margin-right: 12rpx;
|
||||
}
|
||||
|
||||
.error-title {
|
||||
font-size: 16px;
|
||||
font-size: 30rpx;
|
||||
font-weight: bold;
|
||||
color: #e6a23c;
|
||||
}
|
||||
|
||||
.error-message {
|
||||
display: block;
|
||||
font-size: 14px;
|
||||
font-size: 26rpx;
|
||||
color: #faad14;
|
||||
text-align: center;
|
||||
margin-bottom: 20px;
|
||||
margin-bottom: 30rpx;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.error-tips-section {
|
||||
background: #fff7e6;
|
||||
border-radius: 8px;
|
||||
padding: 16px;
|
||||
border-radius: 12rpx;
|
||||
padding: 24rpx;
|
||||
border: 1px solid #ffd591;
|
||||
}
|
||||
|
||||
.tips-title {
|
||||
display: block;
|
||||
font-size: 14px;
|
||||
font-size: 26rpx;
|
||||
font-weight: bold;
|
||||
color: #d48806;
|
||||
margin-bottom: 12px;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.tips-list {
|
||||
@@ -1841,7 +1848,7 @@ export default {
|
||||
.tip-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 8px;
|
||||
margin-bottom: 12rpx;
|
||||
}
|
||||
|
||||
.tip-item:last-child {
|
||||
@@ -1849,12 +1856,12 @@ export default {
|
||||
}
|
||||
|
||||
.tip-icon {
|
||||
margin-right: 8px;
|
||||
margin-right: 12rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.tip-text {
|
||||
font-size: 13px;
|
||||
font-size: 24rpx;
|
||||
color: #d48806;
|
||||
line-height: 1.4;
|
||||
}
|
||||
@@ -1863,40 +1870,40 @@ export default {
|
||||
.stats-grid {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding-top: 8px;
|
||||
padding-top: 12rpx;
|
||||
}
|
||||
|
||||
.stat-item {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
padding: 12px 8px;
|
||||
padding: 20rpx 12rpx;
|
||||
background: #f8f9fa;
|
||||
border-radius: 8px;
|
||||
margin: 0 4px;
|
||||
border-radius: 12rpx;
|
||||
margin: 0 8rpx;
|
||||
}
|
||||
|
||||
.stat-number {
|
||||
display: block;
|
||||
font-size: 20px;
|
||||
font-size: 36rpx;
|
||||
font-weight: bold;
|
||||
color: #409eff;
|
||||
margin-bottom: 4px;
|
||||
color: #2979ff;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
font-size: 12px;
|
||||
font-size: 24rpx;
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
/* 签到记录 */
|
||||
.records-list {
|
||||
padding-top: 8px;
|
||||
padding-top: 12rpx;
|
||||
}
|
||||
|
||||
.record-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 12px 0;
|
||||
padding: 20rpx 0;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
@@ -1905,17 +1912,17 @@ export default {
|
||||
}
|
||||
|
||||
.record-date {
|
||||
font-size: 14px;
|
||||
font-size: 26rpx;
|
||||
color: #303133;
|
||||
width: 100px;
|
||||
width: 160rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.record-time {
|
||||
font-size: 14px;
|
||||
font-size: 26rpx;
|
||||
color: #606266;
|
||||
flex: 1;
|
||||
margin-left: 12px;
|
||||
margin-left: 20rpx;
|
||||
}
|
||||
|
||||
.record-status {
|
||||
@@ -1927,72 +1934,21 @@ export default {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 32px 0;
|
||||
padding: 60rpx 0;
|
||||
}
|
||||
|
||||
.empty-text {
|
||||
font-size: 14px;
|
||||
font-size: 26rpx;
|
||||
color: #909399;
|
||||
margin-top: 8px;
|
||||
margin-top: 12rpx;
|
||||
}
|
||||
|
||||
/* 响应式设计 */
|
||||
@media screen and (max-width: 375px) {
|
||||
.coord-row {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.coord-divider {
|
||||
margin: 0 12px;
|
||||
}
|
||||
|
||||
.coord-value {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.map-btn {
|
||||
min-width: 120px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.error-tips-section {
|
||||
padding: 12px;
|
||||
}
|
||||
/* uview组件样式调整 */
|
||||
::v-deep .u-tag {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 414px) {
|
||||
.location-address {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.coord-row {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.accuracy-info {
|
||||
padding: 12px 16px;
|
||||
}
|
||||
|
||||
.coord-value {
|
||||
font-size: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
/* 深色模式适配 */
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.location-address,
|
||||
.coord-row {
|
||||
background: rgba(255, 255, 255, 0.05);
|
||||
}
|
||||
|
||||
.accuracy-info {
|
||||
background: rgba(103, 194, 58, 0.1);
|
||||
border-color: rgba(103, 194, 58, 0.3);
|
||||
}
|
||||
|
||||
.error-tips-section {
|
||||
background: rgba(255, 247, 230, 0.1);
|
||||
border-color: rgba(255, 213, 145, 0.3);
|
||||
}
|
||||
::v-deep .u-button {
|
||||
border-radius: 12rpx;
|
||||
}
|
||||
</style>
|
||||
+332
-314
File diff suppressed because it is too large.
Load diff
+235
-193
@@ -1,173 +1,196 @@
|
||||
<template>
|
||||
<view class="visit-detail-container">
|
||||
<!-- 学生信息 -->
|
||||
<view class="info-section">
|
||||
<view class="section-title">学生信息</view>
|
||||
<view class="section-content">
|
||||
<view class="info-item">
|
||||
<text class="info-label">学生姓名:</text>
|
||||
<text class="info-value">{{ visitInfo.studentName || '-' }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="info-label">学号:</text>
|
||||
<text class="info-value">{{ visitInfo.studentNo || '-' }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="info-label">班级:</text>
|
||||
<text class="info-value">{{ visitInfo.className || '-' }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="info-label">专业:</text>
|
||||
<text class="info-value">{{ visitInfo.majorName || '-' }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="info-label">学院:</text>
|
||||
<text class="info-value">{{ visitInfo.collegeName || '-' }}</text>
|
||||
</view>
|
||||
<!-- 顶部导航 -->
|
||||
<u-navbar title="走访详情" :border-bottom="false" bg-color="#3c9cff" title-color="#fff">
|
||||
<view slot="left" @click="goBack">
|
||||
<u-icon name="arrow-left" color="#fff" size="22"></u-icon>
|
||||
</view>
|
||||
</view>
|
||||
</u-navbar>
|
||||
|
||||
<!-- 企业信息 -->
|
||||
<view class="info-section">
|
||||
<view class="section-title">企业信息</view>
|
||||
<view class="section-content">
|
||||
<view class="info-item">
|
||||
<text class="info-label">企业名称:</text>
|
||||
<text class="info-value">{{ visitInfo.companyName || '-' }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="info-label">企业地址:</text>
|
||||
<text class="info-value">{{ visitInfo.companyAddress || '-' }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 加载状态 -->
|
||||
<u-loading-page :loading="pageLoading" loading-text="加载中..."></u-loading-page>
|
||||
|
||||
<!-- 走访基本信息 -->
|
||||
<view class="info-section">
|
||||
<view class="section-title">走访基本信息</view>
|
||||
<view class="section-content">
|
||||
<view class="info-item">
|
||||
<text class="info-label">走访日期:</text>
|
||||
<text class="info-value">{{ visitInfo.visitDate || '-' }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="info-label">走访人员:</text>
|
||||
<text class="info-value">{{ visitInfo.visitorName || '-' }}</text>
|
||||
</view>
|
||||
<view class="info-item" v-if="visitInfo.visitorPosition">
|
||||
<text class="info-label">走访人职务:</text>
|
||||
<text class="info-value">{{ visitInfo.visitorPosition }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="info-label">走访状态:</text>
|
||||
<u-tag
|
||||
:text="getStatusText(visitInfo.status)"
|
||||
:type="getStatusType(visitInfo.status)"
|
||||
size="mini"
|
||||
/>
|
||||
</view>
|
||||
<view class="info-item info-item-full" v-if="visitInfo.visitPurpose">
|
||||
<text class="info-label">走访目的:</text>
|
||||
<text class="info-value info-value-multiline">{{ visitInfo.visitPurpose }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 走访内容 -->
|
||||
<view class="info-section">
|
||||
<view class="section-title">走访内容</view>
|
||||
<view class="section-content">
|
||||
<view class="info-item info-item-full" v-if="visitInfo.companySituation">
|
||||
<text class="info-label">企业情况:</text>
|
||||
<text class="info-value info-value-multiline">{{ visitInfo.companySituation }}</text>
|
||||
</view>
|
||||
<view class="info-item info-item-full" v-if="visitInfo.studentPerformance">
|
||||
<text class="info-label">学生表现:</text>
|
||||
<text class="info-value info-value-multiline">{{ visitInfo.studentPerformance }}</text>
|
||||
</view>
|
||||
<view class="info-item info-item-full" v-if="visitInfo.problemsFound">
|
||||
<text class="info-label">发现问题:</text>
|
||||
<text class="info-value info-value-multiline">{{ visitInfo.problemsFound }}</text>
|
||||
</view>
|
||||
<view class="info-item info-item-full" v-if="visitInfo.suggestions">
|
||||
<text class="info-label">改进建议:</text>
|
||||
<text class="info-value info-value-multiline">{{ visitInfo.suggestions }}</text>
|
||||
</view>
|
||||
<view class="info-item info-item-full" v-if="visitInfo.visitSummary">
|
||||
<text class="info-label">走访总结:</text>
|
||||
<text class="info-value info-value-multiline">{{ visitInfo.visitSummary }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 现场照片 -->
|
||||
<view class="info-section" v-if="imageList.length > 0">
|
||||
<view class="section-title">现场照片</view>
|
||||
<view class="section-content">
|
||||
<view class="image-grid">
|
||||
<view
|
||||
class="image-item"
|
||||
v-for="(image, index) in imageList"
|
||||
:key="index"
|
||||
@click="previewImage(index)"
|
||||
>
|
||||
<image :src="image.url" mode="aspectFill" />
|
||||
<!-- 内容区域 -->
|
||||
<view v-if="!pageLoading" class="content-wrapper">
|
||||
<!-- 学生信息 -->
|
||||
<view class="info-section">
|
||||
<view class="section-title">学生信息</view>
|
||||
<view class="section-content">
|
||||
<view class="info-item">
|
||||
<text class="info-label">学生姓名:</text>
|
||||
<text class="info-value">{{ visitInfo.studentName || '-' }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="info-label">学号:</text>
|
||||
<text class="info-value">{{ visitInfo.studentNo || '-' }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="info-label">班级:</text>
|
||||
<text class="info-value">{{ visitInfo.className || '-' }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="info-label">专业:</text>
|
||||
<text class="info-value">{{ visitInfo.majorName || '-' }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="info-label">学院:</text>
|
||||
<text class="info-value">{{ visitInfo.collegeName || '-' }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 备注信息 -->
|
||||
<view class="info-section" v-if="visitInfo.remark">
|
||||
<view class="section-title">备注信息</view>
|
||||
<view class="section-content">
|
||||
<view class="info-item info-item-full">
|
||||
<text class="info-value info-value-multiline">{{ visitInfo.remark }}</text>
|
||||
<!-- 企业信息 -->
|
||||
<view class="info-section">
|
||||
<view class="section-title">企业信息</view>
|
||||
<view class="section-content">
|
||||
<view class="info-item">
|
||||
<text class="info-label">企业名称:</text>
|
||||
<text class="info-value">{{ visitInfo.companyName || '-' }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="info-label">企业地址:</text>
|
||||
<text class="info-value">{{ visitInfo.companyAddress || '-' }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 系统信息 -->
|
||||
<view class="info-section">
|
||||
<view class="section-title">系统信息</view>
|
||||
<view class="section-content">
|
||||
<view class="info-item">
|
||||
<text class="info-label">创建时间:</text>
|
||||
<text class="info-value">{{ visitInfo.createTime || '-' }}</text>
|
||||
</view>
|
||||
<view class="info-item" v-if="visitInfo.updateTime">
|
||||
<text class="info-label">更新时间:</text>
|
||||
<text class="info-value">{{ visitInfo.updateTime }}</text>
|
||||
<!-- 走访基本信息 -->
|
||||
<view class="info-section">
|
||||
<view class="section-title">走访基本信息</view>
|
||||
<view class="section-content">
|
||||
<view class="info-item">
|
||||
<text class="info-label">走访日期:</text>
|
||||
<text class="info-value">{{ visitInfo.visitDate || '-' }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="info-label">走访人员:</text>
|
||||
<text class="info-value">{{ visitInfo.visitorName || '-' }}</text>
|
||||
</view>
|
||||
<view class="info-item" v-if="visitInfo.visitorPosition">
|
||||
<text class="info-label">走访人职务:</text>
|
||||
<text class="info-value">{{ visitInfo.visitorPosition }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="info-label">走访状态:</text>
|
||||
<u-tag
|
||||
:text="getStatusText(visitInfo.status)"
|
||||
:type="getStatusType(visitInfo.status)"
|
||||
size="mini"
|
||||
/>
|
||||
</view>
|
||||
<view class="info-item info-item-full" v-if="visitInfo.visitPurpose">
|
||||
<text class="info-label">走访目的:</text>
|
||||
<text class="info-value info-value-multiline">
|
||||
{{ visitInfo.visitPurpose }}
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 操作按钮 -->
|
||||
<view class="action-section" v-if="canEdit">
|
||||
<u-button
|
||||
type="primary"
|
||||
@click="handleEdit"
|
||||
:loading="loading"
|
||||
style="margin-right: 20rpx;"
|
||||
>
|
||||
编辑走访记录
|
||||
</u-button>
|
||||
<u-button
|
||||
type="error"
|
||||
@click="handleDelete"
|
||||
:loading="loading"
|
||||
plain
|
||||
>
|
||||
删除记录
|
||||
</u-button>
|
||||
</view>
|
||||
<!-- 走访内容 -->
|
||||
<view class="info-section">
|
||||
<view class="section-title">走访内容</view>
|
||||
<view class="section-content">
|
||||
<view class="info-item info-item-full" v-if="visitInfo.companySituation">
|
||||
<text class="info-label">企业情况:</text>
|
||||
<text class="info-value info-value-multiline">
|
||||
{{ visitInfo.companySituation }}
|
||||
</text>
|
||||
</view>
|
||||
<view class="info-item info-item-full" v-if="visitInfo.studentPerformance">
|
||||
<text class="info-label">学生表现:</text>
|
||||
<text class="info-value info-value-multiline">
|
||||
{{ visitInfo.studentPerformance }}
|
||||
</text>
|
||||
</view>
|
||||
<view class="info-item info-item-full" v-if="visitInfo.problemsFound">
|
||||
<text class="info-label">发现问题:</text>
|
||||
<text class="info-value info-value-multiline">
|
||||
{{ visitInfo.problemsFound }}
|
||||
</text>
|
||||
</view>
|
||||
<view class="info-item info-item-full" v-if="visitInfo.suggestions">
|
||||
<text class="info-label">改进建议:</text>
|
||||
<text class="info-value info-value-multiline">
|
||||
{{ visitInfo.suggestions }}
|
||||
</text>
|
||||
</view>
|
||||
<view class="info-item info-item-full" v-if="visitInfo.visitSummary">
|
||||
<text class="info-label">走访总结:</text>
|
||||
<text class="info-value info-value-multiline">
|
||||
{{ visitInfo.visitSummary }}
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 加载遮罩 -->
|
||||
<u-loading-page
|
||||
:loading="pageLoading"
|
||||
loading-text="加载中..."
|
||||
loading-mode="circle"
|
||||
/>
|
||||
<!-- 现场照片 -->
|
||||
<view class="info-section" v-if="imageList.length > 0">
|
||||
<view class="section-title">现场照片</view>
|
||||
<view class="section-content">
|
||||
<view class="image-grid">
|
||||
<view
|
||||
class="image-item"
|
||||
v-for="(image, index) in imageList"
|
||||
:key="index"
|
||||
@click="previewImage(index)"
|
||||
>
|
||||
<image :src="image.url" mode="aspectFill" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 备注信息 -->
|
||||
<view class="info-section" v-if="visitInfo.remark">
|
||||
<view class="section-title">备注信息</view>
|
||||
<view class="section-content">
|
||||
<view class="info-item info-item-full">
|
||||
<text class="info-value info-value-multiline">{{ visitInfo.remark }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 系统信息 -->
|
||||
<view class="info-section">
|
||||
<view class="section-title">系统信息</view>
|
||||
<view class="section-content">
|
||||
<view class="info-item">
|
||||
<text class="info-label">创建时间:</text>
|
||||
<text class="info-value">{{ visitInfo.createTime || '-' }}</text>
|
||||
</view>
|
||||
<view class="info-item" v-if="visitInfo.updateTime">
|
||||
<text class="info-label">更新时间:</text>
|
||||
<text class="info-value">{{ visitInfo.updateTime }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 操作按钮 -->
|
||||
<view class="action-section" v-if="canEdit">
|
||||
<u-button
|
||||
type="primary"
|
||||
shape="round"
|
||||
@click="handleEdit"
|
||||
:loading="loading"
|
||||
style="flex: 1; margin-right: 20rpx"
|
||||
>
|
||||
<u-icon name="edit-pen" size="16" style="margin-right: 4rpx"></u-icon>
|
||||
编辑走访记录
|
||||
</u-button>
|
||||
<u-button
|
||||
type="error"
|
||||
shape="round"
|
||||
@click="handleDelete"
|
||||
:loading="loading"
|
||||
plain
|
||||
style="flex: 1"
|
||||
>
|
||||
<u-icon name="trash" size="16" style="margin-right: 4rpx"></u-icon>
|
||||
删除记录
|
||||
</u-button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
@@ -180,29 +203,31 @@ export default {
|
||||
return {
|
||||
// 页面参数
|
||||
visitId: '',
|
||||
|
||||
|
||||
// 页面状态
|
||||
pageLoading: true,
|
||||
loading: false,
|
||||
|
||||
|
||||
// 走访信息
|
||||
visitInfo: {},
|
||||
|
||||
|
||||
// 图片数据
|
||||
imageList: []
|
||||
imageList: [],
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
computed: {
|
||||
// 是否可以编辑
|
||||
canEdit() {
|
||||
// 只有计划中或草稿状态的记录可以编辑
|
||||
return this.visitInfo.status === 'planned' ||
|
||||
this.visitInfo.status === '0' ||
|
||||
this.visitInfo.status === 'draft';
|
||||
}
|
||||
return (
|
||||
this.visitInfo.status === 'planned' ||
|
||||
this.visitInfo.status === '0' ||
|
||||
this.visitInfo.status === 'draft'
|
||||
);
|
||||
},
|
||||
},
|
||||
|
||||
|
||||
onLoad(options) {
|
||||
if (options.id) {
|
||||
this.visitId = options.id;
|
||||
@@ -212,17 +237,22 @@ export default {
|
||||
uni.navigateBack();
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
methods: {
|
||||
// 返回上一页
|
||||
goBack() {
|
||||
uni.navigateBack();
|
||||
},
|
||||
|
||||
// 加载走访记录详情
|
||||
async loadVisitDetail() {
|
||||
this.pageLoading = true;
|
||||
try {
|
||||
const response = await getVisit(this.visitId);
|
||||
|
||||
|
||||
if (response.code === 200 && response.data) {
|
||||
this.visitInfo = response.data;
|
||||
|
||||
|
||||
// 处理图片数据
|
||||
if (response.data.visitImages) {
|
||||
try {
|
||||
@@ -232,7 +262,6 @@ export default {
|
||||
this.imageList = [];
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
uni.showToast({ title: response.msg || '获取数据失败', icon: 'none' });
|
||||
uni.navigateBack();
|
||||
@@ -245,7 +274,7 @@ export default {
|
||||
this.pageLoading = false;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
// 获取状态文本
|
||||
getStatusText(status) {
|
||||
switch (status) {
|
||||
@@ -262,7 +291,7 @@ export default {
|
||||
return status || '未知';
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
// 获取状态类型
|
||||
getStatusType(status) {
|
||||
switch (status) {
|
||||
@@ -279,23 +308,23 @@ export default {
|
||||
return 'default';
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
// 预览图片
|
||||
previewImage(index) {
|
||||
const urls = this.imageList.map(item => item.url);
|
||||
const urls = this.imageList.map((item) => item.url);
|
||||
uni.previewImage({
|
||||
urls,
|
||||
current: index
|
||||
current: index,
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
// 编辑走访记录
|
||||
handleEdit() {
|
||||
uni.navigateTo({
|
||||
url: `/pages/visit/edit?id=${this.visitId}`
|
||||
url: `/pages/visit/edit?id=${this.visitId}`,
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
// 删除走访记录
|
||||
handleDelete() {
|
||||
uni.showModal({
|
||||
@@ -305,16 +334,16 @@ export default {
|
||||
if (res.confirm) {
|
||||
await this.deleteVisit();
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
// 执行删除
|
||||
async deleteVisit() {
|
||||
this.loading = true;
|
||||
try {
|
||||
const response = await delVisit(this.visitId);
|
||||
|
||||
|
||||
if (response.code === 200) {
|
||||
uni.showToast({ title: '删除成功', icon: 'success' });
|
||||
setTimeout(() => {
|
||||
@@ -329,8 +358,8 @@ export default {
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -338,6 +367,9 @@ export default {
|
||||
.visit-detail-container {
|
||||
min-height: 100vh;
|
||||
background-color: #f8f8f8;
|
||||
}
|
||||
|
||||
.content-wrapper {
|
||||
padding: 20rpx;
|
||||
padding-bottom: 40rpx;
|
||||
}
|
||||
@@ -347,16 +379,17 @@ export default {
|
||||
border-radius: 12rpx;
|
||||
margin-bottom: 20rpx;
|
||||
overflow: hidden;
|
||||
|
||||
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.08);
|
||||
|
||||
.section-title {
|
||||
padding: 24rpx 20rpx 16rpx;
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
border-bottom: 1rpx solid #ebeef5;
|
||||
background: #f8f9fa;
|
||||
background: linear-gradient(135deg, #f8f9fa 0%, #ffffff 100%);
|
||||
}
|
||||
|
||||
|
||||
.section-content {
|
||||
padding: 20rpx;
|
||||
}
|
||||
@@ -366,16 +399,16 @@ export default {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
margin-bottom: 16rpx;
|
||||
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
|
||||
&.info-item-full {
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
|
||||
.info-label {
|
||||
font-size: 28rpx;
|
||||
color: #606266;
|
||||
@@ -383,15 +416,16 @@ export default {
|
||||
flex-shrink: 0;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
|
||||
.info-value {
|
||||
font-size: 28rpx;
|
||||
color: #303133;
|
||||
flex: 1;
|
||||
|
||||
|
||||
&.info-value-multiline {
|
||||
line-height: 1.6;
|
||||
line-height: 1.8;
|
||||
word-break: break-all;
|
||||
color: #606266;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -400,13 +434,19 @@ export default {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 16rpx;
|
||||
|
||||
|
||||
.image-item {
|
||||
width: 200rpx;
|
||||
height: 200rpx;
|
||||
border-radius: 8rpx;
|
||||
overflow: hidden;
|
||||
|
||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
|
||||
transition: all 0.3s ease;
|
||||
|
||||
&:active {
|
||||
transform: scale(0.95);
|
||||
}
|
||||
|
||||
image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
@@ -416,9 +456,11 @@ export default {
|
||||
|
||||
.action-section {
|
||||
display: flex;
|
||||
gap: 20rpx;
|
||||
padding: 20rpx;
|
||||
background: #ffffff;
|
||||
border-radius: 12rpx;
|
||||
margin-bottom: 20rpx;
|
||||
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
+276
-251
@@ -1,216 +1,232 @@
|
||||
<template>
|
||||
<view class="visit-edit-container">
|
||||
<!-- 顶部导航 -->
|
||||
<u-navbar title="编辑走访" :border-bottom="false" bg-color="#3c9cff" title-color="#fff">
|
||||
<view slot="left" @click="goBack">
|
||||
<u-icon name="arrow-left" color="#fff" size="22"></u-icon>
|
||||
</view>
|
||||
</u-navbar>
|
||||
|
||||
<!-- 加载状态 -->
|
||||
<u-loading-page :loading="pageLoading" loading-text="加载中..."></u-loading-page>
|
||||
|
||||
<!-- 表单内容 -->
|
||||
<u-form
|
||||
ref="formRef"
|
||||
:model="form"
|
||||
:rules="rules"
|
||||
label-width="180rpx"
|
||||
label-position="left"
|
||||
>
|
||||
<!-- 学生信息展示 -->
|
||||
<view class="form-section">
|
||||
<view class="section-title">学生信息</view>
|
||||
|
||||
<view class="student-info-section">
|
||||
<view class="info-row">
|
||||
<text class="info-label">学生姓名:</text>
|
||||
<text class="info-value">{{ visitInfo.studentName || '-' }}</text>
|
||||
</view>
|
||||
<view class="info-row">
|
||||
<text class="info-label">学号:</text>
|
||||
<text class="info-value">{{ visitInfo.studentNo || '-' }}</text>
|
||||
</view>
|
||||
<view class="info-row">
|
||||
<text class="info-label">班级:</text>
|
||||
<text class="info-value">{{ visitInfo.className || '-' }}</text>
|
||||
</view>
|
||||
<view class="info-row">
|
||||
<text class="info-label">专业:</text>
|
||||
<text class="info-value">{{ visitInfo.majorName || '-' }}</text>
|
||||
</view>
|
||||
<view class="info-row">
|
||||
<text class="info-label">实习单位:</text>
|
||||
<text class="info-value">{{ visitInfo.companyName || '-' }}</text>
|
||||
<view v-if="!pageLoading" class="content-wrapper">
|
||||
<u-form
|
||||
ref="formRef"
|
||||
:model="form"
|
||||
:rules="rules"
|
||||
label-width="180rpx"
|
||||
label-position="left"
|
||||
>
|
||||
<!-- 学生信息展示 -->
|
||||
<view class="form-section">
|
||||
<view class="section-title">学生信息</view>
|
||||
|
||||
<view class="student-info-section">
|
||||
<view class="info-row">
|
||||
<text class="info-label">学生姓名:</text>
|
||||
<text class="info-value">{{ visitInfo.studentName || '-' }}</text>
|
||||
</view>
|
||||
<view class="info-row">
|
||||
<text class="info-label">学号:</text>
|
||||
<text class="info-value">{{ visitInfo.studentNo || '-' }}</text>
|
||||
</view>
|
||||
<view class="info-row">
|
||||
<text class="info-label">班级:</text>
|
||||
<text class="info-value">{{ visitInfo.className || '-' }}</text>
|
||||
</view>
|
||||
<view class="info-row">
|
||||
<text class="info-label">专业:</text>
|
||||
<text class="info-value">{{ visitInfo.majorName || '-' }}</text>
|
||||
</view>
|
||||
<view class="info-row">
|
||||
<text class="info-label">实习单位:</text>
|
||||
<text class="info-value">{{ visitInfo.companyName || '-' }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 走访基本信息 -->
|
||||
<view class="form-section">
|
||||
<view class="section-title">走访信息</view>
|
||||
|
||||
<u-form-item label="走访日期" prop="visitDate" required>
|
||||
<view @click="showVisitDatePicker = true" style="width: 100%">
|
||||
<u-input
|
||||
v-model="form.visitDate"
|
||||
placeholder="请选择走访日期"
|
||||
readonly
|
||||
border="none"
|
||||
suffix-icon="calendar"
|
||||
suffix-icon-style="color: #c8c9cc;"
|
||||
style="pointer-events: none"
|
||||
/>
|
||||
</view>
|
||||
</u-form-item>
|
||||
|
||||
<u-form-item label="走访人员" prop="visitorName" required>
|
||||
<u-input
|
||||
v-model="form.visitorName"
|
||||
placeholder="请输入走访人员姓名"
|
||||
border="none"
|
||||
clearable
|
||||
/>
|
||||
</u-form-item>
|
||||
|
||||
<u-form-item label="走访人职务" prop="visitorPosition">
|
||||
<u-input
|
||||
v-model="form.visitorPosition"
|
||||
placeholder="请输入走访人员职务"
|
||||
border="none"
|
||||
clearable
|
||||
/>
|
||||
</u-form-item>
|
||||
|
||||
<u-form-item label="走访目的" prop="visitPurpose" required>
|
||||
<u-textarea
|
||||
v-model="form.visitPurpose"
|
||||
placeholder="请输入走访目的"
|
||||
:maxlength="500"
|
||||
show-confirm-bar
|
||||
height="120"
|
||||
auto-height
|
||||
/>
|
||||
</u-form-item>
|
||||
</view>
|
||||
<!-- 走访基本信息 -->
|
||||
<view class="form-section">
|
||||
<view class="section-title">走访信息</view>
|
||||
|
||||
<!-- 走访内容 -->
|
||||
<view class="form-section">
|
||||
<view class="section-title">走访内容</view>
|
||||
|
||||
<u-form-item label="企业情况" prop="companySituation">
|
||||
<u-textarea
|
||||
v-model="form.companySituation"
|
||||
placeholder="请描述企业基本情况"
|
||||
:maxlength="1000"
|
||||
show-confirm-bar
|
||||
height="120"
|
||||
auto-height
|
||||
/>
|
||||
</u-form-item>
|
||||
|
||||
<u-form-item label="学生表现" prop="studentPerformance">
|
||||
<u-textarea
|
||||
v-model="form.studentPerformance"
|
||||
placeholder="请描述学生实习表现"
|
||||
:maxlength="1000"
|
||||
show-confirm-bar
|
||||
height="120"
|
||||
auto-height
|
||||
/>
|
||||
</u-form-item>
|
||||
|
||||
<u-form-item label="发现问题" prop="problemsFound">
|
||||
<u-textarea
|
||||
v-model="form.problemsFound"
|
||||
placeholder="请描述发现的问题"
|
||||
:maxlength="1000"
|
||||
show-confirm-bar
|
||||
height="120"
|
||||
auto-height
|
||||
/>
|
||||
</u-form-item>
|
||||
|
||||
<u-form-item label="改进建议" prop="suggestions">
|
||||
<u-textarea
|
||||
v-model="form.suggestions"
|
||||
placeholder="请提出改进建议"
|
||||
:maxlength="1000"
|
||||
show-confirm-bar
|
||||
height="120"
|
||||
auto-height
|
||||
/>
|
||||
</u-form-item>
|
||||
|
||||
<u-form-item label="走访总结" prop="visitSummary">
|
||||
<u-textarea
|
||||
v-model="form.visitSummary"
|
||||
placeholder="请输入走访总结"
|
||||
:maxlength="1000"
|
||||
show-confirm-bar
|
||||
height="120"
|
||||
auto-height
|
||||
/>
|
||||
</u-form-item>
|
||||
</view>
|
||||
|
||||
<!-- 现场照片 -->
|
||||
<view class="form-section">
|
||||
<view class="section-title">现场照片</view>
|
||||
|
||||
<view class="upload-section">
|
||||
<view class="image-list">
|
||||
<view
|
||||
class="image-item"
|
||||
v-for="(image, index) in imageList"
|
||||
:key="index"
|
||||
>
|
||||
<image
|
||||
:src="image.url"
|
||||
mode="aspectFill"
|
||||
@click="previewImage(index)"
|
||||
<u-form-item label="走访日期" prop="visitDate" required>
|
||||
<view @click="showVisitDatePicker = true" style="width: 100%">
|
||||
<u-input
|
||||
v-model="form.visitDate"
|
||||
placeholder="请选择走访日期"
|
||||
readonly
|
||||
border="none"
|
||||
suffix-icon="calendar"
|
||||
suffix-icon-style="color: #c8c9cc;"
|
||||
style="pointer-events: none"
|
||||
/>
|
||||
<view class="delete-btn" @click="removeImage(index)">
|
||||
<u-icon name="close" size="12" color="#ffffff" />
|
||||
</view>
|
||||
</u-form-item>
|
||||
|
||||
<u-form-item label="走访人员" prop="visitorName" required>
|
||||
<u-input
|
||||
v-model="form.visitorName"
|
||||
placeholder="请输入走访人员姓名"
|
||||
border="none"
|
||||
clearable
|
||||
/>
|
||||
</u-form-item>
|
||||
|
||||
<u-form-item label="走访人职务" prop="visitorPosition">
|
||||
<u-input
|
||||
v-model="form.visitorPosition"
|
||||
placeholder="请输入走访人员职务"
|
||||
border="none"
|
||||
clearable
|
||||
/>
|
||||
</u-form-item>
|
||||
|
||||
<u-form-item label="走访目的" prop="visitPurpose" required>
|
||||
<u-textarea
|
||||
v-model="form.visitPurpose"
|
||||
placeholder="请输入走访目的"
|
||||
:maxlength="500"
|
||||
show-confirm-bar
|
||||
height="120"
|
||||
auto-height
|
||||
/>
|
||||
</u-form-item>
|
||||
</view>
|
||||
|
||||
<!-- 走访内容 -->
|
||||
<view class="form-section">
|
||||
<view class="section-title">走访内容</view>
|
||||
|
||||
<u-form-item label="企业情况" prop="companySituation">
|
||||
<u-textarea
|
||||
v-model="form.companySituation"
|
||||
placeholder="请描述企业基本情况"
|
||||
:maxlength="1000"
|
||||
show-confirm-bar
|
||||
height="120"
|
||||
auto-height
|
||||
/>
|
||||
</u-form-item>
|
||||
|
||||
<u-form-item label="学生表现" prop="studentPerformance">
|
||||
<u-textarea
|
||||
v-model="form.studentPerformance"
|
||||
placeholder="请描述学生实习表现"
|
||||
:maxlength="1000"
|
||||
show-confirm-bar
|
||||
height="120"
|
||||
auto-height
|
||||
/>
|
||||
</u-form-item>
|
||||
|
||||
<u-form-item label="发现问题" prop="problemsFound">
|
||||
<u-textarea
|
||||
v-model="form.problemsFound"
|
||||
placeholder="请描述发现的问题"
|
||||
:maxlength="1000"
|
||||
show-confirm-bar
|
||||
height="120"
|
||||
auto-height
|
||||
/>
|
||||
</u-form-item>
|
||||
|
||||
<u-form-item label="改进建议" prop="suggestions">
|
||||
<u-textarea
|
||||
v-model="form.suggestions"
|
||||
placeholder="请提出改进建议"
|
||||
:maxlength="1000"
|
||||
show-confirm-bar
|
||||
height="120"
|
||||
auto-height
|
||||
/>
|
||||
</u-form-item>
|
||||
|
||||
<u-form-item label="走访总结" prop="visitSummary">
|
||||
<u-textarea
|
||||
v-model="form.visitSummary"
|
||||
placeholder="请输入走访总结"
|
||||
:maxlength="1000"
|
||||
show-confirm-bar
|
||||
height="120"
|
||||
auto-height
|
||||
/>
|
||||
</u-form-item>
|
||||
</view>
|
||||
|
||||
<!-- 现场照片 -->
|
||||
<view class="form-section">
|
||||
<view class="section-title">现场照片</view>
|
||||
|
||||
<view class="upload-section">
|
||||
<view class="image-list">
|
||||
<view
|
||||
class="image-item"
|
||||
v-for="(image, index) in imageList"
|
||||
:key="index"
|
||||
>
|
||||
<image
|
||||
:src="image.url"
|
||||
mode="aspectFill"
|
||||
@click="previewImage(index)"
|
||||
/>
|
||||
<view class="delete-btn" @click="removeImage(index)">
|
||||
<u-icon name="close" size="12" color="#ffffff" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view
|
||||
class="upload-btn"
|
||||
@click="chooseImage"
|
||||
v-if="imageList.length < maxImageCount"
|
||||
>
|
||||
<u-icon name="camera" size="24" color="#c8c9cc" />
|
||||
<text class="upload-text">添加照片</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view
|
||||
class="upload-btn"
|
||||
@click="chooseImage"
|
||||
v-if="imageList.length < maxImageCount"
|
||||
>
|
||||
<u-icon name="camera" size="24" color="#c8c9cc" />
|
||||
<text class="upload-text">添加照片</text>
|
||||
</view>
|
||||
<text class="upload-tip">最多上传{{ maxImageCount }}张照片</text>
|
||||
</view>
|
||||
<text class="upload-tip">最多上传{{ maxImageCount }}张照片</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 备注信息 -->
|
||||
<view class="form-section">
|
||||
<view class="section-title">备注信息</view>
|
||||
|
||||
<u-form-item label="备注" prop="remark">
|
||||
<u-textarea
|
||||
v-model="form.remark"
|
||||
placeholder="请输入备注信息(可选)"
|
||||
:maxlength="500"
|
||||
show-confirm-bar
|
||||
height="120"
|
||||
auto-height
|
||||
/>
|
||||
</u-form-item>
|
||||
</view>
|
||||
</u-form>
|
||||
<!-- 备注信息 -->
|
||||
<view class="form-section">
|
||||
<view class="section-title">备注信息</view>
|
||||
|
||||
<u-form-item label="备注" prop="remark">
|
||||
<u-textarea
|
||||
v-model="form.remark"
|
||||
placeholder="请输入备注信息(可选)"
|
||||
:maxlength="500"
|
||||
show-confirm-bar
|
||||
height="120"
|
||||
auto-height
|
||||
/>
|
||||
</u-form-item>
|
||||
</view>
|
||||
</u-form>
|
||||
</view>
|
||||
|
||||
<!-- 底部操作按钮 -->
|
||||
<view class="bottom-actions">
|
||||
<u-button
|
||||
type="default"
|
||||
<view v-if="!pageLoading" class="bottom-actions">
|
||||
<u-button
|
||||
type="info"
|
||||
shape="round"
|
||||
@click="saveDraft"
|
||||
:loading="draftLoading"
|
||||
style="margin-right: 20rpx;"
|
||||
style="margin-right: 20rpx"
|
||||
>
|
||||
<u-icon name="folder" size="16" style="margin-right: 4rpx"></u-icon>
|
||||
保存草稿
|
||||
</u-button>
|
||||
<u-button
|
||||
type="primary"
|
||||
<u-button
|
||||
type="primary"
|
||||
shape="round"
|
||||
@click="submitForm"
|
||||
:loading="submitLoading"
|
||||
style="flex: 1;"
|
||||
style="flex: 1"
|
||||
>
|
||||
<u-icon name="checkmark-circle" size="16" style="margin-right: 4rpx"></u-icon>
|
||||
更新走访记录
|
||||
</u-button>
|
||||
</view>
|
||||
@@ -226,11 +242,7 @@
|
||||
/>
|
||||
|
||||
<!-- 加载遮罩 -->
|
||||
<u-loading-page
|
||||
:loading="pageLoading"
|
||||
loading-text="加载中..."
|
||||
loading-mode="circle"
|
||||
/>
|
||||
<u-loading-page :loading="pageLoading" loading-text="加载中..." loading-mode="circle" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
@@ -243,13 +255,13 @@ export default {
|
||||
return {
|
||||
// 页面参数
|
||||
visitId: '',
|
||||
|
||||
|
||||
// 页面状态
|
||||
pageLoading: true,
|
||||
|
||||
|
||||
// 走访信息
|
||||
visitInfo: {},
|
||||
|
||||
|
||||
// 表单数据
|
||||
form: {
|
||||
visitId: '',
|
||||
@@ -268,37 +280,37 @@ export default {
|
||||
visitSummary: '',
|
||||
visitImages: '',
|
||||
remark: '',
|
||||
status: ''
|
||||
status: '',
|
||||
},
|
||||
|
||||
|
||||
// 表单验证规则
|
||||
rules: {
|
||||
visitDate: [
|
||||
{ required: true, message: '请选择走访日期', trigger: ['blur', 'change'] }
|
||||
{ required: true, message: '请选择走访日期', trigger: ['blur', 'change'] },
|
||||
],
|
||||
visitorName: [
|
||||
{ required: true, message: '请输入走访人员姓名', trigger: ['blur', 'change'] }
|
||||
{ required: true, message: '请输入走访人员姓名', trigger: ['blur', 'change'] },
|
||||
],
|
||||
visitPurpose: [
|
||||
{ required: true, message: '请输入走访目的', trigger: ['blur', 'change'] }
|
||||
]
|
||||
{ required: true, message: '请输入走访目的', trigger: ['blur', 'change'] },
|
||||
],
|
||||
},
|
||||
|
||||
|
||||
// 日期选择
|
||||
showVisitDatePicker: false,
|
||||
visitDateValue: Date.now(),
|
||||
maxDate: Date.now() + 30 * 24 * 60 * 60 * 1000, // 30天后
|
||||
|
||||
|
||||
// 图片上传
|
||||
imageList: [],
|
||||
maxImageCount: 10,
|
||||
|
||||
|
||||
// 加载状态
|
||||
submitLoading: false,
|
||||
draftLoading: false
|
||||
draftLoading: false,
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
onLoad(options) {
|
||||
if (options.id) {
|
||||
this.visitId = options.id;
|
||||
@@ -308,17 +320,22 @@ export default {
|
||||
uni.navigateBack();
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
methods: {
|
||||
// 返回上一页
|
||||
goBack() {
|
||||
uni.navigateBack();
|
||||
},
|
||||
|
||||
// 加载走访记录详情
|
||||
async loadVisitDetail() {
|
||||
this.pageLoading = true;
|
||||
try {
|
||||
const response = await getVisit(this.visitId);
|
||||
|
||||
|
||||
if (response.code === 200 && response.data) {
|
||||
this.visitInfo = response.data;
|
||||
|
||||
|
||||
// 填充表单数据
|
||||
this.form = {
|
||||
visitId: response.data.visitId,
|
||||
@@ -337,9 +354,9 @@ export default {
|
||||
visitSummary: response.data.visitSummary,
|
||||
visitImages: response.data.visitImages,
|
||||
remark: response.data.remark,
|
||||
status: response.data.status
|
||||
status: response.data.status,
|
||||
};
|
||||
|
||||
|
||||
// 处理图片数据
|
||||
if (response.data.visitImages) {
|
||||
try {
|
||||
@@ -349,12 +366,11 @@ export default {
|
||||
this.imageList = [];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 设置日期选择器的值
|
||||
if (response.data.visitDate) {
|
||||
this.visitDateValue = new Date(response.data.visitDate).getTime();
|
||||
}
|
||||
|
||||
} else {
|
||||
uni.showToast({ title: response.msg || '获取数据失败', icon: 'none' });
|
||||
uni.navigateBack();
|
||||
@@ -367,14 +383,14 @@ export default {
|
||||
this.pageLoading = false;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
// 走访日期确认
|
||||
handleVisitDateConfirm(value) {
|
||||
const date = new Date(value);
|
||||
this.form.visitDate = this.formatDate(date);
|
||||
this.showVisitDatePicker = false;
|
||||
},
|
||||
|
||||
|
||||
// 格式化日期
|
||||
formatDate(date) {
|
||||
const year = date.getFullYear();
|
||||
@@ -382,7 +398,7 @@ export default {
|
||||
const day = String(date.getDate()).padStart(2, '0');
|
||||
return `${year}-${month}-${day}`;
|
||||
},
|
||||
|
||||
|
||||
// 选择图片
|
||||
chooseImage() {
|
||||
const remainCount = this.maxImageCount - this.imageList.length;
|
||||
@@ -392,24 +408,24 @@ export default {
|
||||
sourceType: ['album', 'camera'],
|
||||
success: (res) => {
|
||||
this.handleImageUpload(res.tempFilePaths);
|
||||
}
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
// 处理图片上传
|
||||
async handleImageUpload(filePaths) {
|
||||
uni.showLoading({ title: '上传中...' });
|
||||
|
||||
|
||||
try {
|
||||
for (const filePath of filePaths) {
|
||||
// 这里应该调用具体的文件上传接口
|
||||
// 暂时使用本地路径作为示例
|
||||
this.imageList.push({
|
||||
url: filePath,
|
||||
path: filePath
|
||||
path: filePath,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// 更新表单中的图片数据
|
||||
this.form.visitImages = JSON.stringify(this.imageList);
|
||||
} catch (error) {
|
||||
@@ -419,33 +435,33 @@ export default {
|
||||
uni.hideLoading();
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
// 预览图片
|
||||
previewImage(index) {
|
||||
const urls = this.imageList.map(item => item.url);
|
||||
const urls = this.imageList.map((item) => item.url);
|
||||
uni.previewImage({
|
||||
urls,
|
||||
current: index
|
||||
current: index,
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
// 删除图片
|
||||
removeImage(index) {
|
||||
this.imageList.splice(index, 1);
|
||||
this.form.visitImages = JSON.stringify(this.imageList);
|
||||
},
|
||||
|
||||
|
||||
// 保存草稿
|
||||
async saveDraft() {
|
||||
this.draftLoading = true;
|
||||
try {
|
||||
const formData = {
|
||||
...this.form,
|
||||
status: 'planned' // 草稿状态
|
||||
status: 'planned', // 草稿状态
|
||||
};
|
||||
|
||||
|
||||
const response = await updateVisit(formData);
|
||||
|
||||
|
||||
if (response.code === 200) {
|
||||
uni.showToast({ title: '草稿保存成功', icon: 'success' });
|
||||
setTimeout(() => {
|
||||
@@ -461,7 +477,7 @@ export default {
|
||||
this.draftLoading = false;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
// 提交表单
|
||||
async submitForm() {
|
||||
// 表单验证
|
||||
@@ -471,16 +487,16 @@ export default {
|
||||
console.log('表单验证失败:', error);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
this.submitLoading = true;
|
||||
try {
|
||||
const formData = {
|
||||
...this.form,
|
||||
status: 'completed' // 已完成状态
|
||||
status: 'completed', // 已完成状态
|
||||
};
|
||||
|
||||
|
||||
const response = await updateVisit(formData);
|
||||
|
||||
|
||||
if (response.code === 200) {
|
||||
uni.showToast({ title: '更新成功', icon: 'success' });
|
||||
setTimeout(() => {
|
||||
@@ -495,8 +511,8 @@ export default {
|
||||
} finally {
|
||||
this.submitLoading = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -504,6 +520,9 @@ export default {
|
||||
.visit-edit-container {
|
||||
min-height: 100vh;
|
||||
background-color: #f8f8f8;
|
||||
}
|
||||
|
||||
.content-wrapper {
|
||||
padding-bottom: 120rpx; // 为底部按钮留出空间
|
||||
}
|
||||
|
||||
@@ -511,7 +530,13 @@ export default {
|
||||
background: #ffffff;
|
||||
margin-bottom: 20rpx;
|
||||
padding: 0 20rpx;
|
||||
|
||||
border-radius: 12rpx;
|
||||
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.08);
|
||||
|
||||
&:first-child {
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
padding: 24rpx 0 16rpx;
|
||||
font-size: 32rpx;
|
||||
@@ -527,21 +552,21 @@ export default {
|
||||
border-radius: 8rpx;
|
||||
padding: 20rpx;
|
||||
margin-top: 16rpx;
|
||||
|
||||
|
||||
.info-row {
|
||||
display: flex;
|
||||
margin-bottom: 12rpx;
|
||||
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
|
||||
.info-label {
|
||||
font-size: 28rpx;
|
||||
color: #606266;
|
||||
width: 140rpx;
|
||||
}
|
||||
|
||||
|
||||
.info-value {
|
||||
font-size: 28rpx;
|
||||
color: #303133;
|
||||
@@ -556,19 +581,19 @@ export default {
|
||||
flex-wrap: wrap;
|
||||
gap: 16rpx;
|
||||
margin-bottom: 16rpx;
|
||||
|
||||
|
||||
.image-item {
|
||||
position: relative;
|
||||
width: 160rpx;
|
||||
height: 160rpx;
|
||||
border-radius: 8rpx;
|
||||
overflow: hidden;
|
||||
|
||||
|
||||
image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
|
||||
.delete-btn {
|
||||
position: absolute;
|
||||
top: 8rpx;
|
||||
@@ -582,7 +607,7 @@ export default {
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.upload-btn {
|
||||
width: 160rpx;
|
||||
height: 160rpx;
|
||||
@@ -592,7 +617,7 @@ export default {
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
|
||||
.upload-text {
|
||||
font-size: 24rpx;
|
||||
color: #c8c9cc;
|
||||
@@ -600,7 +625,7 @@ export default {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.upload-tip {
|
||||
font-size: 24rpx;
|
||||
color: #909399;
|
||||
@@ -619,4 +644,4 @@ export default {
|
||||
align-items: center;
|
||||
z-index: 100;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
+247
-177
@@ -1,15 +1,21 @@
|
||||
<template>
|
||||
<view class="visit-container">
|
||||
<!-- 顶部导航 -->
|
||||
<u-navbar title="班主任走访" :border-bottom="false" bg-color="#3c9cff" title-color="#fff">
|
||||
<view slot="left" @click="goBack">
|
||||
<u-icon name="arrow-left" color="#fff" size="22"></u-icon>
|
||||
</view>
|
||||
</u-navbar>
|
||||
|
||||
<!-- 搜索栏 -->
|
||||
<view class="search-bar">
|
||||
<u-search
|
||||
v-model="searchKeyword"
|
||||
<u-search
|
||||
v-model="searchKeyword"
|
||||
placeholder="搜索学生姓名、学号或企业"
|
||||
:show-action="false"
|
||||
@search="handleSearch"
|
||||
@custom="handleSearch"
|
||||
bg-color="#f6f6f6"
|
||||
height="72"
|
||||
shape="round"
|
||||
/>
|
||||
</view>
|
||||
@@ -47,19 +53,21 @@
|
||||
</view>
|
||||
</view>
|
||||
<view class="filter-actions">
|
||||
<u-button
|
||||
type="primary"
|
||||
size="small"
|
||||
<u-button
|
||||
type="primary"
|
||||
shape="round"
|
||||
size="small"
|
||||
@click="handleFilter"
|
||||
:loading="loading"
|
||||
>
|
||||
筛选
|
||||
</u-button>
|
||||
<u-button
|
||||
type="default"
|
||||
size="small"
|
||||
<u-button
|
||||
type="info"
|
||||
shape="round"
|
||||
size="small"
|
||||
@click="resetFilter"
|
||||
style="margin-left: 10rpx;"
|
||||
style="margin-left: 10rpx"
|
||||
>
|
||||
重置
|
||||
</u-button>
|
||||
@@ -68,30 +76,36 @@
|
||||
|
||||
<!-- 筛选按钮 -->
|
||||
<view class="action-bar">
|
||||
<u-button
|
||||
type="default"
|
||||
size="small"
|
||||
<u-button
|
||||
type="info"
|
||||
shape="round"
|
||||
size="small"
|
||||
:icon="showFilter ? 'arrow-up' : 'arrow-down'"
|
||||
@click="showFilter = !showFilter"
|
||||
>
|
||||
{{ showFilter ? '收起筛选' : '展开筛选' }}
|
||||
</u-button>
|
||||
<u-button
|
||||
type="primary"
|
||||
size="small"
|
||||
icon="plus"
|
||||
@click="handleAdd"
|
||||
>
|
||||
<u-button type="primary" shape="round" size="small" icon="plus" @click="handleAdd">
|
||||
新增走访
|
||||
</u-button>
|
||||
</view>
|
||||
|
||||
<!-- 加载状态 -->
|
||||
<u-loading-page
|
||||
:loading="loading && visitList.length === 0"
|
||||
loading-text="加载中..."
|
||||
></u-loading-page>
|
||||
|
||||
<!-- 走访记录列表 -->
|
||||
<view class="list-container">
|
||||
<view class="list-content" v-if="visitList.length > 0">
|
||||
<view
|
||||
class="visit-card"
|
||||
v-for="item in visitList"
|
||||
<view v-if="!loading || visitList.length > 0" class="content-wrapper">
|
||||
<view v-if="visitList.length === 0" class="empty-container">
|
||||
<u-empty text="暂无走访记录" mode="data"></u-empty>
|
||||
</view>
|
||||
|
||||
<view class="list-content" v-else>
|
||||
<view
|
||||
class="visit-card"
|
||||
v-for="item in visitList"
|
||||
:key="item.visitId"
|
||||
@click="handleView(item)"
|
||||
>
|
||||
@@ -102,83 +116,99 @@
|
||||
<text class="student-no">{{ item.studentNo }}</text>
|
||||
</view>
|
||||
<view class="status-badge">
|
||||
<u-tag
|
||||
:text="item.statusName || item.status"
|
||||
<u-tag
|
||||
:text="getStatusLabel(item.status)"
|
||||
:type="getStatusType(item.status)"
|
||||
size="mini"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
|
||||
<!-- 企业信息 -->
|
||||
<view class="card-row">
|
||||
<u-icon name="home" size="16" color="#909399" />
|
||||
<text class="info-text">{{ item.companyName || '-' }}</text>
|
||||
</view>
|
||||
|
||||
|
||||
<!-- 走访信息 -->
|
||||
<view class="card-row">
|
||||
<u-icon name="calendar" size="16" color="#909399" />
|
||||
<text class="info-text">{{ item.visitDate || '-' }}</text>
|
||||
<u-icon name="account" size="16" color="#909399" style="margin-left: 20rpx;" />
|
||||
<u-icon
|
||||
name="account"
|
||||
size="16"
|
||||
color="#909399"
|
||||
style="margin-left: 20rpx"
|
||||
/>
|
||||
<text class="info-text">{{ item.visitorName || '-' }}</text>
|
||||
</view>
|
||||
|
||||
|
||||
<!-- 班级专业信息 -->
|
||||
<view class="card-row">
|
||||
<u-icon name="bookmark" size="16" color="#909399" />
|
||||
<text class="info-text">{{ item.className || '-' }} / {{ item.majorName || '-' }}</text>
|
||||
<text class="info-text">
|
||||
{{ item.className || '-' }} / {{ item.majorName || '-' }}
|
||||
</text>
|
||||
</view>
|
||||
|
||||
|
||||
<!-- 操作按钮 -->
|
||||
<view class="card-actions">
|
||||
<u-button
|
||||
type="default"
|
||||
size="mini"
|
||||
<u-button
|
||||
type="primary"
|
||||
shape="round"
|
||||
size="small"
|
||||
@click.stop="handleEdit(item)"
|
||||
v-if="item.status === 'planned' || item.status === '0'"
|
||||
>
|
||||
<u-icon
|
||||
name="edit-pen"
|
||||
size="14"
|
||||
color="#fff"
|
||||
style="margin-right: 4rpx"
|
||||
></u-icon>
|
||||
编辑
|
||||
</u-button>
|
||||
<u-button
|
||||
type="error"
|
||||
size="mini"
|
||||
<u-button
|
||||
type="error"
|
||||
shape="round"
|
||||
size="small"
|
||||
@click.stop="handleDelete(item)"
|
||||
style="margin-left: 10rpx;"
|
||||
style="margin-left: 10rpx"
|
||||
v-if="item.status === 'planned' || item.status === '0'"
|
||||
>
|
||||
<u-icon
|
||||
name="trash"
|
||||
size="14"
|
||||
color="#fff"
|
||||
style="margin-right: 4rpx"
|
||||
></u-icon>
|
||||
删除
|
||||
</u-button>
|
||||
<u-button
|
||||
type="info"
|
||||
shape="round"
|
||||
size="small"
|
||||
plain
|
||||
@click.stop="handleView(item)"
|
||||
v-else
|
||||
>
|
||||
<u-icon name="eye" size="14" style="margin-right: 4rpx"></u-icon>
|
||||
查看
|
||||
</u-button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 空状态 -->
|
||||
<view class="empty-state" v-else-if="!loading">
|
||||
<u-empty
|
||||
mode="data"
|
||||
text="暂无走访记录"
|
||||
textColor="#c8c9cc"
|
||||
iconColor="#c8c9cc"
|
||||
|
||||
<!-- 上拉加载更多 -->
|
||||
<view class="load-more" v-if="hasMore">
|
||||
<u-loadmore
|
||||
:status="loadMoreStatus"
|
||||
@loadmore="loadMore"
|
||||
load-text="加载更多"
|
||||
loading-text="正在加载..."
|
||||
no-more-text="没有更多了"
|
||||
/>
|
||||
</view>
|
||||
|
||||
<!-- 加载状态 -->
|
||||
<view class="loading-state" v-if="loading">
|
||||
<u-loading-icon mode="circle" />
|
||||
<text style="margin-left: 10rpx; color: #909399;">加载中...</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 上拉加载更多 -->
|
||||
<view class="load-more" v-if="hasMore && visitList.length > 0">
|
||||
<u-loadmore
|
||||
:status="loadMoreStatus"
|
||||
@loadmore="loadMore"
|
||||
load-text="加载更多"
|
||||
loading-text="正在加载..."
|
||||
no-more-text="没有更多了"
|
||||
/>
|
||||
</view>
|
||||
|
||||
<!-- 状态选择器 -->
|
||||
@@ -218,51 +248,56 @@ export default {
|
||||
visitorName: '',
|
||||
status: '',
|
||||
beginVisitDate: '',
|
||||
endVisitDate: ''
|
||||
endVisitDate: '',
|
||||
},
|
||||
|
||||
|
||||
// 列表数据
|
||||
visitList: [],
|
||||
total: 0,
|
||||
loading: false,
|
||||
hasMore: true,
|
||||
loadMoreStatus: 'loadmore',
|
||||
|
||||
|
||||
// 状态选择
|
||||
showStatusPicker: false,
|
||||
statusOptions: [],
|
||||
currentStatusIndex: -1,
|
||||
statusText: '',
|
||||
statusDict: [],
|
||||
|
||||
|
||||
// 日期选择
|
||||
showDatePicker: false,
|
||||
dateRangeText: '',
|
||||
selectedDateRange: []
|
||||
selectedDateRange: [],
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
onLoad() {
|
||||
this.initPage();
|
||||
},
|
||||
|
||||
|
||||
onPullDownRefresh() {
|
||||
this.refreshList();
|
||||
},
|
||||
|
||||
|
||||
onReachBottom() {
|
||||
if (this.hasMore && this.loadMoreStatus === 'loadmore') {
|
||||
this.loadMore();
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
methods: {
|
||||
// 返回上一页
|
||||
goBack() {
|
||||
uni.navigateBack();
|
||||
},
|
||||
|
||||
// 初始化页面
|
||||
async initPage() {
|
||||
await this.loadStatusDict();
|
||||
this.getList();
|
||||
},
|
||||
|
||||
|
||||
// 加载状态字典
|
||||
async loadStatusDict() {
|
||||
try {
|
||||
@@ -272,55 +307,57 @@ export default {
|
||||
this.statusOptions = [
|
||||
[
|
||||
{ text: '全部状态', value: '' },
|
||||
...response.data.map(item => ({
|
||||
...response.data.map((item) => ({
|
||||
text: item.dictLabel,
|
||||
value: item.dictValue
|
||||
}))
|
||||
]
|
||||
value: item.dictValue,
|
||||
})),
|
||||
],
|
||||
];
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('加载状态字典失败:', error);
|
||||
// 设置默认状态选项
|
||||
this.statusOptions = [[
|
||||
{ text: '全部状态', value: '' },
|
||||
{ text: '计划中', value: 'planned' },
|
||||
{ text: '已完成', value: 'completed' },
|
||||
{ text: '已取消', value: 'cancelled' }
|
||||
]];
|
||||
this.statusOptions = [
|
||||
[
|
||||
{ text: '全部状态', value: '' },
|
||||
{ text: '计划中', value: 'planned' },
|
||||
{ text: '已完成', value: 'completed' },
|
||||
{ text: '已取消', value: 'cancelled' },
|
||||
],
|
||||
];
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
// 获取列表数据
|
||||
async getList(isLoadMore = false) {
|
||||
if (this.loading) return;
|
||||
|
||||
|
||||
this.loading = true;
|
||||
if (!isLoadMore) {
|
||||
this.loadMoreStatus = 'loadmore';
|
||||
} else {
|
||||
this.loadMoreStatus = 'loading';
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
const response = await listVisit(this.queryParams);
|
||||
|
||||
|
||||
if (response.code === 200) {
|
||||
// 后端返回的是TableDataInfo格式,直接包含rows和total字段
|
||||
const { rows, total } = response;
|
||||
|
||||
|
||||
if (isLoadMore) {
|
||||
this.visitList = [...this.visitList, ...rows || []];
|
||||
this.visitList = [...this.visitList, ...(rows || [])];
|
||||
} else {
|
||||
this.visitList = rows || [];
|
||||
}
|
||||
|
||||
|
||||
this.total = total || 0;
|
||||
|
||||
|
||||
// 判断是否还有更多数据
|
||||
const currentTotal = this.visitList.length;
|
||||
this.hasMore = currentTotal < this.total;
|
||||
|
||||
|
||||
if (!this.hasMore) {
|
||||
this.loadMoreStatus = 'nomore';
|
||||
}
|
||||
@@ -337,13 +374,13 @@ export default {
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
// 刷新列表
|
||||
refreshList() {
|
||||
this.queryParams.pageNum = 1;
|
||||
this.getList();
|
||||
},
|
||||
|
||||
|
||||
// 加载更多
|
||||
loadMore() {
|
||||
if (this.hasMore && !this.loading) {
|
||||
@@ -351,18 +388,18 @@ export default {
|
||||
this.getList(true);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
// 搜索
|
||||
handleSearch() {
|
||||
this.queryParams.studentKeyword = this.searchKeyword;
|
||||
this.refreshList();
|
||||
},
|
||||
|
||||
|
||||
// 筛选
|
||||
handleFilter() {
|
||||
this.refreshList();
|
||||
},
|
||||
|
||||
|
||||
// 重置筛选
|
||||
resetFilter() {
|
||||
this.queryParams = {
|
||||
@@ -372,7 +409,7 @@ export default {
|
||||
visitorName: '',
|
||||
status: '',
|
||||
beginVisitDate: '',
|
||||
endVisitDate: ''
|
||||
endVisitDate: '',
|
||||
};
|
||||
this.statusText = '';
|
||||
this.dateRangeText = '';
|
||||
@@ -380,7 +417,7 @@ export default {
|
||||
this.currentStatusIndex = -1;
|
||||
this.refreshList();
|
||||
},
|
||||
|
||||
|
||||
// 状态选择确认
|
||||
handleStatusConfirm(value) {
|
||||
const selected = value.value[0];
|
||||
@@ -389,7 +426,7 @@ export default {
|
||||
this.currentStatusIndex = value.index[0];
|
||||
this.showStatusPicker = false;
|
||||
},
|
||||
|
||||
|
||||
// 日期选择确认
|
||||
handleDateConfirm(value) {
|
||||
this.selectedDateRange = value;
|
||||
@@ -404,7 +441,33 @@ export default {
|
||||
}
|
||||
this.showDatePicker = false;
|
||||
},
|
||||
|
||||
|
||||
// 获取状态标签文本
|
||||
getStatusLabel(status) {
|
||||
// 如果statusDict字典已加载,从字典中查找
|
||||
if (this.statusDict && this.statusDict.length > 0) {
|
||||
const dictItem = this.statusDict.find((item) => item.dictValue === String(status));
|
||||
if (dictItem) {
|
||||
return dictItem.dictLabel;
|
||||
}
|
||||
}
|
||||
|
||||
// 如果字典未加载或找不到,使用默认映射
|
||||
switch (String(status)) {
|
||||
case 'planned':
|
||||
case '0':
|
||||
return '计划中';
|
||||
case 'completed':
|
||||
case '1':
|
||||
return '已完成';
|
||||
case 'cancelled':
|
||||
case '2':
|
||||
return '已取消';
|
||||
default:
|
||||
return status || '未知';
|
||||
}
|
||||
},
|
||||
|
||||
// 获取状态类型
|
||||
getStatusType(status) {
|
||||
switch (status) {
|
||||
@@ -421,28 +484,28 @@ export default {
|
||||
return 'default';
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
// 查看详情
|
||||
handleView(item) {
|
||||
uni.navigateTo({
|
||||
url: `/pages/visit/detail?id=${item.visitId}`
|
||||
url: `/pages/visit/detail?id=${item.visitId}`,
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
// 新增走访
|
||||
handleAdd() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/visit/add'
|
||||
url: '/pages/visit/add',
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
// 编辑走访
|
||||
handleEdit(item) {
|
||||
uni.navigateTo({
|
||||
url: `/pages/visit/edit?id=${item.visitId}`
|
||||
url: `/pages/visit/edit?id=${item.visitId}`,
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
// 删除走访
|
||||
handleDelete(item) {
|
||||
uni.showModal({
|
||||
@@ -452,16 +515,16 @@ export default {
|
||||
if (res.confirm) {
|
||||
await this.deleteVisit(item.visitId);
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
// 执行删除
|
||||
async deleteVisit(id) {
|
||||
try {
|
||||
uni.showLoading({ title: '删除中...' });
|
||||
const response = await delVisit(id);
|
||||
|
||||
|
||||
if (response.code === 200) {
|
||||
uni.showToast({ title: '删除成功', icon: 'success' });
|
||||
this.refreshList();
|
||||
@@ -474,8 +537,8 @@ export default {
|
||||
} finally {
|
||||
uni.hideLoading();
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -494,11 +557,11 @@ export default {
|
||||
background: #ffffff;
|
||||
padding: 0 20rpx 20rpx;
|
||||
border-bottom: 1rpx solid #ebeef5;
|
||||
|
||||
|
||||
.filter-item {
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
|
||||
.filter-actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
@@ -515,76 +578,83 @@ export default {
|
||||
border-bottom: 1rpx solid #ebeef5;
|
||||
}
|
||||
|
||||
.list-container {
|
||||
.content-wrapper {
|
||||
padding: 20rpx;
|
||||
}
|
||||
|
||||
.visit-card {
|
||||
background: #ffffff;
|
||||
border-radius: 12rpx;
|
||||
padding: 24rpx;
|
||||
margin-bottom: 20rpx;
|
||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.06);
|
||||
|
||||
.card-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 16rpx;
|
||||
|
||||
.student-info {
|
||||
.student-name {
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
margin-right: 16rpx;
|
||||
}
|
||||
|
||||
.student-no {
|
||||
font-size: 26rpx;
|
||||
color: #909399;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.card-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 12rpx;
|
||||
|
||||
.info-text {
|
||||
font-size: 28rpx;
|
||||
color: #606266;
|
||||
margin-left: 8rpx;
|
||||
}
|
||||
|
||||
&:last-of-type {
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.card-actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 10rpx;
|
||||
padding-top: 16rpx;
|
||||
border-top: 1rpx solid #ebeef5;
|
||||
}
|
||||
}
|
||||
|
||||
.empty-state {
|
||||
.empty-container {
|
||||
padding: 80rpx 20rpx;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.loading-state {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 40rpx;
|
||||
.list-content {
|
||||
.visit-card {
|
||||
background: #ffffff;
|
||||
border-radius: 12rpx;
|
||||
padding: 24rpx;
|
||||
margin-bottom: 20rpx;
|
||||
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.08);
|
||||
transition: all 0.3s ease;
|
||||
|
||||
&:active {
|
||||
transform: scale(0.99);
|
||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.06);
|
||||
}
|
||||
|
||||
.card-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
margin-bottom: 16rpx;
|
||||
|
||||
.student-info {
|
||||
flex: 1;
|
||||
|
||||
.student-name {
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
margin-right: 16rpx;
|
||||
}
|
||||
|
||||
.student-no {
|
||||
font-size: 26rpx;
|
||||
color: #909399;
|
||||
}
|
||||
}
|
||||
|
||||
.status-badge {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.card-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 12rpx;
|
||||
|
||||
.info-text {
|
||||
font-size: 28rpx;
|
||||
color: #606266;
|
||||
margin-left: 8rpx;
|
||||
}
|
||||
|
||||
&:last-of-type {
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.card-actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 10rpx;
|
||||
padding-top: 16rpx;
|
||||
border-top: 1rpx solid #ebeef5;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.load-more {
|
||||
padding: 20rpx;
|
||||
padding: 20rpx 0;
|
||||
}
|
||||
</style>
|
||||
@@ -1,11 +1,18 @@
|
||||
<template>
|
||||
<view class="detail-container">
|
||||
<!-- 顶部导航 -->
|
||||
<u-navbar title="申请详情" :border-bottom="false" bg-color="#0051d9" title-color="#fff">
|
||||
<view slot="left" @click="goBack">
|
||||
<u-icon name="arrow-left" color="#fff" size="22"></u-icon>
|
||||
</view>
|
||||
</u-navbar>
|
||||
|
||||
<!-- 申请状态卡片 -->
|
||||
<view class="status-card" v-if="applicationData">
|
||||
<view class="card-title">申请状态</view>
|
||||
<view class="status-info">
|
||||
<view class="main-status">
|
||||
<u-tag
|
||||
<u-tag
|
||||
:text="getApplicationStatusText(applicationData.status)"
|
||||
:type="getApplicationStatusType(applicationData.status)"
|
||||
size="large"
|
||||
@@ -17,7 +24,10 @@
|
||||
<text class="status-label">申请时间:</text>
|
||||
<text class="status-value">{{ applicationData.createTime }}</text>
|
||||
</view>
|
||||
<view class="status-item" v-if="applicationData.updateTime !== applicationData.createTime">
|
||||
<view
|
||||
class="status-item"
|
||||
v-if="applicationData.updateTime !== applicationData.createTime"
|
||||
>
|
||||
<text class="status-label">更新时间:</text>
|
||||
<text class="status-value">{{ applicationData.updateTime }}</text>
|
||||
</view>
|
||||
@@ -32,11 +42,11 @@
|
||||
<view class="position-name">{{ applicationData.positionName }}</view>
|
||||
<view class="position-detail">
|
||||
<view class="detail-item">
|
||||
<u-icon name="list" size="28" color="#666" />
|
||||
<u-icon name="list" size="18" color="#666" />
|
||||
<text>岗位类型:{{ applicationData.positionType }}</text>
|
||||
</view>
|
||||
<view class="detail-item">
|
||||
<u-icon name="map" size="28" color="#666" />
|
||||
<u-icon name="map" size="18" color="#666" />
|
||||
<text>工作地点:{{ applicationData.workLocation }}</text>
|
||||
</view>
|
||||
</view>
|
||||
@@ -61,7 +71,9 @@
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="info-label">联系电话:</text>
|
||||
<text class="info-value contact-phone" @click="callPhone">{{ applicationData.contactPhone }}</text>
|
||||
<text class="info-value contact-phone" @click="callPhone">
|
||||
{{ applicationData.contactPhone }}
|
||||
</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="info-label">学院:</text>
|
||||
@@ -124,12 +136,12 @@
|
||||
<!-- 审核记录 -->
|
||||
<view class="review-card" v-if="hasReviewRecord">
|
||||
<view class="card-title">审核记录</view>
|
||||
|
||||
|
||||
<!-- 学院审核 -->
|
||||
<view class="review-item" v-if="applicationData.collegeReviewStatus">
|
||||
<view class="review-header">
|
||||
<view class="review-title">学院审核</view>
|
||||
<u-tag
|
||||
<u-tag
|
||||
:text="getReviewStatusText(applicationData.collegeReviewStatus)"
|
||||
:type="getReviewStatusType(applicationData.collegeReviewStatus)"
|
||||
size="mini"
|
||||
@@ -156,7 +168,7 @@
|
||||
<view class="review-item" v-if="applicationData.finalReviewStatus">
|
||||
<view class="review-header">
|
||||
<view class="review-title">学生处审核</view>
|
||||
<u-tag
|
||||
<u-tag
|
||||
:text="getReviewStatusText(applicationData.finalReviewStatus)"
|
||||
:type="getReviewStatusType(applicationData.finalReviewStatus)"
|
||||
size="mini"
|
||||
@@ -182,18 +194,18 @@
|
||||
|
||||
<!-- 底部操作按钮 -->
|
||||
<view class="bottom-actions" v-if="showActions">
|
||||
<u-button
|
||||
type="warning"
|
||||
size="large"
|
||||
<u-button
|
||||
type="warning"
|
||||
size="large"
|
||||
@click="editApplication"
|
||||
v-if="canEdit"
|
||||
style="margin-right: 20rpx;"
|
||||
style="margin-right: 20rpx"
|
||||
>
|
||||
编辑申请
|
||||
</u-button>
|
||||
<u-button
|
||||
type="error"
|
||||
size="large"
|
||||
<u-button
|
||||
type="error"
|
||||
size="large"
|
||||
@click="cancelApplication"
|
||||
v-if="canCancel"
|
||||
:loading="canceling"
|
||||
@@ -208,10 +220,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
getApplicationDetail,
|
||||
cancelApplication
|
||||
} from '@/api/workStudy.js';
|
||||
import { getApplicationDetail, cancelApplication } from '@/api/workStudy.js';
|
||||
|
||||
export default {
|
||||
name: 'ApplicationDetail',
|
||||
@@ -220,35 +229,41 @@ export default {
|
||||
applicationId: '',
|
||||
applicationData: null,
|
||||
loading: false,
|
||||
canceling: false
|
||||
canceling: false,
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
computed: {
|
||||
// 是否有审核记录
|
||||
hasReviewRecord() {
|
||||
return this.applicationData &&
|
||||
(this.applicationData.collegeReviewStatus || this.applicationData.finalReviewStatus);
|
||||
return (
|
||||
this.applicationData &&
|
||||
(this.applicationData.collegeReviewStatus || this.applicationData.finalReviewStatus)
|
||||
);
|
||||
},
|
||||
|
||||
|
||||
// 是否显示操作按钮
|
||||
showActions() {
|
||||
return this.canEdit || this.canCancel;
|
||||
},
|
||||
|
||||
|
||||
// 是否可以编辑
|
||||
canEdit() {
|
||||
return this.applicationData &&
|
||||
['DRAFT', 'COLLEGE_REJECTED'].includes(this.applicationData.status);
|
||||
return (
|
||||
this.applicationData &&
|
||||
['DRAFT', 'COLLEGE_REJECTED'].includes(this.applicationData.status)
|
||||
);
|
||||
},
|
||||
|
||||
|
||||
// 是否可以撤销
|
||||
canCancel() {
|
||||
return this.applicationData &&
|
||||
['DRAFT', 'SUBMITTED', 'COLLEGE_REVIEWING'].includes(this.applicationData.status);
|
||||
}
|
||||
return (
|
||||
this.applicationData &&
|
||||
['DRAFT', 'SUBMITTED', 'COLLEGE_REVIEWING'].includes(this.applicationData.status)
|
||||
);
|
||||
},
|
||||
},
|
||||
|
||||
|
||||
onLoad(options) {
|
||||
if (options.id) {
|
||||
this.applicationId = options.id;
|
||||
@@ -256,22 +271,27 @@ export default {
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: '申请ID不能为空',
|
||||
icon: 'none'
|
||||
icon: 'none',
|
||||
});
|
||||
setTimeout(() => {
|
||||
uni.navigateBack();
|
||||
}, 1500);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
methods: {
|
||||
// 返回上一页
|
||||
goBack() {
|
||||
uni.navigateBack();
|
||||
},
|
||||
|
||||
// 加载申请详情
|
||||
async loadApplicationDetail() {
|
||||
this.loading = true;
|
||||
|
||||
|
||||
try {
|
||||
const response = await getApplicationDetail(this.applicationId);
|
||||
|
||||
|
||||
if (response.code === 200) {
|
||||
this.applicationData = response.data;
|
||||
} else {
|
||||
@@ -281,9 +301,9 @@ export default {
|
||||
console.error('加载申请详情失败:', error);
|
||||
uni.showToast({
|
||||
title: error.message || '加载失败',
|
||||
icon: 'none'
|
||||
icon: 'none',
|
||||
});
|
||||
|
||||
|
||||
setTimeout(() => {
|
||||
uni.navigateBack();
|
||||
}, 1500);
|
||||
@@ -291,36 +311,36 @@ export default {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
// 编辑申请
|
||||
editApplication() {
|
||||
if (!this.applicationData) return;
|
||||
|
||||
|
||||
uni.navigateTo({
|
||||
url: `/pages/workStudy/apply?positionId=${this.applicationData.positionId}&applicationId=${this.applicationData.id}&mode=edit`
|
||||
url: `/pages/workStudy/apply?positionId=${this.applicationData.positionId}&applicationId=${this.applicationData.id}&mode=edit`,
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
// 撤销申请
|
||||
async cancelApplication() {
|
||||
try {
|
||||
const { confirm } = await uni.showModal({
|
||||
title: '确认撤销',
|
||||
content: '确定要撤销此申请吗?',
|
||||
showCancel: true
|
||||
showCancel: true,
|
||||
});
|
||||
|
||||
|
||||
if (!confirm) return; // 用户取消
|
||||
|
||||
|
||||
this.canceling = true;
|
||||
const response = await cancelApplication(this.applicationData.id);
|
||||
|
||||
|
||||
if (response.code === 200) {
|
||||
uni.showToast({
|
||||
title: '撤销成功',
|
||||
icon: 'success'
|
||||
icon: 'success',
|
||||
});
|
||||
|
||||
|
||||
// 重新加载数据
|
||||
setTimeout(() => {
|
||||
this.loadApplicationDetail();
|
||||
@@ -332,13 +352,13 @@ export default {
|
||||
console.error('撤销申请失败:', error);
|
||||
uni.showToast({
|
||||
title: error.message || '撤销失败',
|
||||
icon: 'none'
|
||||
icon: 'none',
|
||||
});
|
||||
} finally {
|
||||
this.canceling = false;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
// 拨打电话
|
||||
callPhone() {
|
||||
if (this.applicationData && this.applicationData.contactPhone) {
|
||||
@@ -348,96 +368,99 @@ export default {
|
||||
console.error('拨打电话失败:', error);
|
||||
uni.showToast({
|
||||
title: '拨打电话失败',
|
||||
icon: 'none'
|
||||
icon: 'none',
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
// 格式化身份证号(中间位隐藏)
|
||||
formatIdCard(idCard) {
|
||||
if (!idCard || idCard.length < 10) return idCard;
|
||||
return idCard.substring(0, 6) + '********' + idCard.substring(idCard.length - 4);
|
||||
},
|
||||
|
||||
|
||||
// 获取申请状态文字
|
||||
getApplicationStatusText(status) {
|
||||
const statusMap = {
|
||||
'DRAFT': '草稿',
|
||||
'SUBMITTED': '已提交',
|
||||
'COLLEGE_REVIEWING': '学院审核中',
|
||||
'COLLEGE_APPROVED': '学院审核通过',
|
||||
'COLLEGE_REJECTED': '学院审核未通过',
|
||||
'FINAL_REVIEWING': '学生处审核中',
|
||||
'FINAL_APPROVED': '审核通过',
|
||||
'FINAL_REJECTED': '审核未通过',
|
||||
'CANCELLED': '已撤销'
|
||||
DRAFT: '草稿',
|
||||
SUBMITTED: '已提交',
|
||||
COLLEGE_REVIEWING: '学院审核中',
|
||||
COLLEGE_APPROVED: '学院审核通过',
|
||||
COLLEGE_REJECTED: '学院审核未通过',
|
||||
FINAL_REVIEWING: '学生处审核中',
|
||||
FINAL_APPROVED: '审核通过',
|
||||
FINAL_REJECTED: '审核未通过',
|
||||
CANCELLED: '已撤销',
|
||||
};
|
||||
return statusMap[status] || '未知状态';
|
||||
},
|
||||
|
||||
|
||||
// 获取申请状态类型
|
||||
getApplicationStatusType(status) {
|
||||
const typeMap = {
|
||||
'DRAFT': 'info',
|
||||
'SUBMITTED': 'warning',
|
||||
'COLLEGE_REVIEWING': 'warning',
|
||||
'COLLEGE_APPROVED': 'success',
|
||||
'COLLEGE_REJECTED': 'error',
|
||||
'FINAL_REVIEWING': 'warning',
|
||||
'FINAL_APPROVED': 'success',
|
||||
'FINAL_REJECTED': 'error',
|
||||
'CANCELLED': 'info'
|
||||
DRAFT: 'info',
|
||||
SUBMITTED: 'warning',
|
||||
COLLEGE_REVIEWING: 'warning',
|
||||
COLLEGE_APPROVED: 'success',
|
||||
COLLEGE_REJECTED: 'error',
|
||||
FINAL_REVIEWING: 'warning',
|
||||
FINAL_APPROVED: 'success',
|
||||
FINAL_REJECTED: 'error',
|
||||
CANCELLED: 'info',
|
||||
};
|
||||
return typeMap[status] || 'default';
|
||||
},
|
||||
|
||||
|
||||
// 获取审核状态文字
|
||||
getReviewStatusText(status) {
|
||||
const statusMap = {
|
||||
'PENDING': '待审核',
|
||||
'APPROVED': '通过',
|
||||
'REJECTED': '未通过'
|
||||
PENDING: '待审核',
|
||||
APPROVED: '通过',
|
||||
REJECTED: '未通过',
|
||||
};
|
||||
return statusMap[status] || '未知';
|
||||
},
|
||||
|
||||
|
||||
// 获取审核状态类型
|
||||
getReviewStatusType(status) {
|
||||
const typeMap = {
|
||||
'PENDING': 'warning',
|
||||
'APPROVED': 'success',
|
||||
'REJECTED': 'error'
|
||||
PENDING: 'warning',
|
||||
APPROVED: 'success',
|
||||
REJECTED: 'error',
|
||||
};
|
||||
return typeMap[status] || 'default';
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.detail-container {
|
||||
min-height: 100vh;
|
||||
background-color: #f5f5f5;
|
||||
background-color: #f5f6fa;
|
||||
padding-bottom: 120rpx; /* 为底部按钮留空间 */
|
||||
}
|
||||
|
||||
.status-card, .info-card, .content-card, .review-card {
|
||||
.status-card,
|
||||
.info-card,
|
||||
.content-card,
|
||||
.review-card {
|
||||
background-color: #fff;
|
||||
margin: 20rpx;
|
||||
border-radius: 12rpx;
|
||||
border-radius: 16rpx;
|
||||
padding: 30rpx;
|
||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
|
||||
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.card-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
color: #303133;
|
||||
margin-bottom: 24rpx;
|
||||
padding-bottom: 16rpx;
|
||||
border-bottom: 1rpx solid #f0f0f0;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
/* 状态卡片 */
|
||||
@@ -463,12 +486,12 @@ export default {
|
||||
|
||||
.status-label {
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
.status-value {
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
/* 岗位信息 */
|
||||
@@ -516,14 +539,14 @@ export default {
|
||||
|
||||
.info-label {
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
color: #606266;
|
||||
min-width: 160rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.info-value {
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
color: #303133;
|
||||
flex: 1;
|
||||
line-height: 1.5;
|
||||
}
|
||||
@@ -536,7 +559,7 @@ export default {
|
||||
/* 内容卡片 */
|
||||
.content-text {
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
color: #606266;
|
||||
line-height: 1.8;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
@@ -563,7 +586,7 @@ export default {
|
||||
.review-title {
|
||||
font-size: 30rpx;
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.review-info {
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
<template>
|
||||
<view class="apply-container">
|
||||
<!-- 顶部导航 -->
|
||||
<u-navbar title="申请岗位" :border-bottom="false" bg-color="#0051d9" title-color="#fff">
|
||||
<view slot="left" @click="goBack">
|
||||
<u-icon name="arrow-left" color="#fff" size="22"></u-icon>
|
||||
</view>
|
||||
</u-navbar>
|
||||
|
||||
<!-- 岗位信息卡片 -->
|
||||
<view class="position-card" v-if="positionData">
|
||||
<view class="card-title">申请岗位</view>
|
||||
@@ -14,59 +21,38 @@
|
||||
|
||||
<!-- 申请表单 -->
|
||||
<view class="form-container">
|
||||
<u-form
|
||||
:model="formData"
|
||||
ref="form"
|
||||
label-width="140"
|
||||
label-position="left"
|
||||
>
|
||||
<u-form :model="formData" ref="form" label-width="140" label-position="left">
|
||||
<!-- 基本信息 -->
|
||||
<view class="form-section">
|
||||
<view class="section-title">基本信息</view>
|
||||
|
||||
<u-form-item
|
||||
label="学生姓名"
|
||||
prop="studentName"
|
||||
:required="true"
|
||||
>
|
||||
<u-input
|
||||
v-model="formData.studentName"
|
||||
|
||||
<u-form-item label="学生姓名" prop="studentName" :required="true">
|
||||
<u-input
|
||||
v-model="formData.studentName"
|
||||
placeholder="请输入学生姓名"
|
||||
:disabled="true"
|
||||
/>
|
||||
</u-form-item>
|
||||
|
||||
<u-form-item
|
||||
label="学号"
|
||||
prop="studentNumber"
|
||||
:required="true"
|
||||
>
|
||||
<u-input
|
||||
v-model="formData.studentNumber"
|
||||
|
||||
<u-form-item label="学号" prop="studentNumber" :required="true">
|
||||
<u-input
|
||||
v-model="formData.studentNumber"
|
||||
placeholder="请输入学号"
|
||||
:disabled="true"
|
||||
/>
|
||||
</u-form-item>
|
||||
|
||||
<u-form-item
|
||||
label="身份证号"
|
||||
prop="idCard"
|
||||
:required="true"
|
||||
>
|
||||
<u-input
|
||||
v-model="formData.idCard"
|
||||
|
||||
<u-form-item label="身份证号" prop="idCard" :required="true">
|
||||
<u-input
|
||||
v-model="formData.idCard"
|
||||
placeholder="请输入身份证号"
|
||||
maxlength="18"
|
||||
/>
|
||||
</u-form-item>
|
||||
|
||||
<u-form-item
|
||||
label="联系电话"
|
||||
prop="contactPhone"
|
||||
:required="true"
|
||||
>
|
||||
<u-input
|
||||
v-model="formData.contactPhone"
|
||||
|
||||
<u-form-item label="联系电话" prop="contactPhone" :required="true">
|
||||
<u-input
|
||||
v-model="formData.contactPhone"
|
||||
placeholder="请输入联系电话"
|
||||
maxlength="11"
|
||||
/>
|
||||
@@ -76,133 +62,109 @@
|
||||
<!-- 学籍信息 -->
|
||||
<view class="form-section">
|
||||
<view class="section-title">学籍信息</view>
|
||||
|
||||
<u-form-item
|
||||
label="学院名称"
|
||||
prop="collegeName"
|
||||
:required="true"
|
||||
>
|
||||
<u-input
|
||||
v-model="formData.collegeName"
|
||||
|
||||
<u-form-item label="学院名称" prop="collegeName" :required="true">
|
||||
<u-input
|
||||
v-model="formData.collegeName"
|
||||
placeholder="学院名称"
|
||||
:disabled="true"
|
||||
/>
|
||||
</u-form-item>
|
||||
|
||||
<u-form-item
|
||||
label="专业名称"
|
||||
prop="majorName"
|
||||
:required="true"
|
||||
>
|
||||
<u-input
|
||||
v-model="formData.majorName"
|
||||
|
||||
<u-form-item label="专业名称" prop="majorName" :required="true">
|
||||
<u-input
|
||||
v-model="formData.majorName"
|
||||
placeholder="专业名称"
|
||||
:disabled="true"
|
||||
/>
|
||||
</u-form-item>
|
||||
|
||||
<u-form-item
|
||||
label="班级名称"
|
||||
prop="className"
|
||||
:required="true"
|
||||
>
|
||||
<u-input
|
||||
v-model="formData.className"
|
||||
|
||||
<u-form-item label="班级名称" prop="className" :required="true">
|
||||
<u-input
|
||||
v-model="formData.className"
|
||||
placeholder="班级名称"
|
||||
:disabled="true"
|
||||
/>
|
||||
</u-form-item>
|
||||
|
||||
|
||||
</view>
|
||||
|
||||
<!-- 申请信息 -->
|
||||
<view class="form-section">
|
||||
<view class="section-title">申请信息</view>
|
||||
|
||||
<u-form-item
|
||||
label="家庭经济情况"
|
||||
prop="familyFinancialStatus"
|
||||
:required="true"
|
||||
>
|
||||
<u-radio-group v-model="formData.familyFinancialStatus">
|
||||
<u-radio
|
||||
v-for="option in familyStatusOptions"
|
||||
:key="option.value"
|
||||
:name="option.value"
|
||||
:label="option.label"
|
||||
style="margin-right: 20rpx; margin-bottom: 15rpx; font-size: 28rpx;"
|
||||
/>
|
||||
</u-radio-group>
|
||||
|
||||
<u-form-item label="家庭经济情况" prop="familyFinancialStatus" :required="true">
|
||||
<u-picker
|
||||
:columns="familyStatusColumns"
|
||||
v-model="familyStatusIndex"
|
||||
:show="showFamilyStatusPicker"
|
||||
@confirm="onFamilyStatusConfirm"
|
||||
@close="showFamilyStatusPicker = false"
|
||||
></u-picker>
|
||||
<view class="picker-input" @click="showFamilyStatusPicker = true">
|
||||
<text
|
||||
class="picker-text"
|
||||
:class="{ placeholder: !formData.familyFinancialStatus }"
|
||||
>
|
||||
{{ formData.familyFinancialStatus || '请选择家庭经济情况' }}
|
||||
</text>
|
||||
<u-icon name="arrow-right" size="14" color="#c8c9cc"></u-icon>
|
||||
</view>
|
||||
</u-form-item>
|
||||
|
||||
<u-form-item
|
||||
label="计划工作时长"
|
||||
prop="plannedWorkHours"
|
||||
>
|
||||
<u-input
|
||||
v-model="formData.plannedWorkHours"
|
||||
|
||||
<u-form-item label="计划工作时长" prop="plannedWorkHours">
|
||||
<u-input
|
||||
v-model="formData.plannedWorkHours"
|
||||
placeholder="请输入计划工作时长(小时/周)"
|
||||
type="number"
|
||||
placeholder-style="font-size: 24rpx"
|
||||
/>
|
||||
</u-form-item>
|
||||
|
||||
<u-form-item
|
||||
label="申请理由"
|
||||
prop="applicationReason"
|
||||
:required="true"
|
||||
>
|
||||
<u-textarea
|
||||
v-model="formData.applicationReason"
|
||||
|
||||
<u-form-item label="申请理由" prop="applicationReason" :required="true">
|
||||
<u-textarea
|
||||
v-model="formData.applicationReason"
|
||||
placeholder="请详细说明申请此岗位的理由"
|
||||
:maxlength="500"
|
||||
:show-word-limit="true"
|
||||
height="200"
|
||||
count
|
||||
placeholder-style="font-size: 24rpx"
|
||||
/>
|
||||
</u-form-item>
|
||||
|
||||
<u-form-item
|
||||
label="个人能力及经验"
|
||||
prop="personalAbility"
|
||||
:required="true"
|
||||
>
|
||||
<u-textarea
|
||||
v-model="formData.personalAbility"
|
||||
|
||||
<u-form-item label="个人能力及经验" prop="personalAbility" :required="true">
|
||||
<u-textarea
|
||||
v-model="formData.personalAbility"
|
||||
placeholder="请描述与岗位相关的个人能力和经验"
|
||||
:maxlength="500"
|
||||
:show-word-limit="true"
|
||||
height="200"
|
||||
count
|
||||
placeholder-style="font-size: 24rpx"
|
||||
/>
|
||||
</u-form-item>
|
||||
|
||||
<u-form-item
|
||||
label="时间安排"
|
||||
prop="timeArrangement"
|
||||
:required="true"
|
||||
>
|
||||
<u-textarea
|
||||
v-model="formData.timeArrangement"
|
||||
|
||||
<u-form-item label="时间安排" prop="timeArrangement" :required="true">
|
||||
<u-textarea
|
||||
v-model="formData.timeArrangement"
|
||||
placeholder="请说明您的时间安排,确保能够胜任此岗位工作"
|
||||
:maxlength="300"
|
||||
:show-word-limit="true"
|
||||
height="150"
|
||||
count
|
||||
placeholder-style="font-size: 24rpx"
|
||||
/>
|
||||
</u-form-item>
|
||||
|
||||
<u-form-item
|
||||
label="备注"
|
||||
prop="remark"
|
||||
>
|
||||
<u-textarea
|
||||
v-model="formData.remark"
|
||||
|
||||
<u-form-item label="备注" prop="remark">
|
||||
<u-textarea
|
||||
v-model="formData.remark"
|
||||
placeholder="其他需要说明的情况(选填)"
|
||||
:maxlength="200"
|
||||
:show-word-limit="true"
|
||||
height="120"
|
||||
count
|
||||
placeholder-style="font-size: 24rpx"
|
||||
/>
|
||||
</u-form-item>
|
||||
</view>
|
||||
@@ -211,42 +173,34 @@
|
||||
|
||||
<!-- 底部操作按钮 -->
|
||||
<view class="bottom-actions">
|
||||
<u-button
|
||||
type="default"
|
||||
size="large"
|
||||
<u-button
|
||||
plain
|
||||
type="info"
|
||||
size="large"
|
||||
@click="saveDraft"
|
||||
:loading="saving"
|
||||
style="margin-right: 20rpx;"
|
||||
:custom-style="draftButtonStyle"
|
||||
>
|
||||
保存草稿
|
||||
</u-button>
|
||||
<u-button
|
||||
type="primary"
|
||||
size="large"
|
||||
@click="submitApplication"
|
||||
:loading="submitting"
|
||||
>
|
||||
<u-button type="primary" size="large" @click="submitApplication" :loading="submitting">
|
||||
提交申请
|
||||
</u-button>
|
||||
</view>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<!-- 加载状态 -->
|
||||
<u-loading-page :loading="loading" loading-text="加载中..." />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
import {
|
||||
getPositionWithApplicationStatus,
|
||||
getCurrentStudentInfo,
|
||||
getApplicationOptions,
|
||||
addApplication,
|
||||
updateApplication,
|
||||
getApplicationDetail
|
||||
getApplicationDetail,
|
||||
} from '@/api/workStudy.js';
|
||||
|
||||
export default {
|
||||
@@ -258,7 +212,7 @@ export default {
|
||||
mode: 'create', // create 或 edit
|
||||
positionData: null,
|
||||
studentInfo: null,
|
||||
|
||||
|
||||
// 表单数据
|
||||
formData: {
|
||||
studentName: '',
|
||||
@@ -274,69 +228,118 @@ export default {
|
||||
applicationReason: '',
|
||||
personalAbility: '',
|
||||
timeArrangement: '',
|
||||
remark: ''
|
||||
remark: '',
|
||||
},
|
||||
|
||||
|
||||
// 家庭经济情况选项(与web端保持一致)
|
||||
familyStatusOptions: [
|
||||
{ value: '特困', label: '特困' },
|
||||
{ value: '贫困', label: '贫困' },
|
||||
{ value: '一般', label: '一般' },
|
||||
{ value: '良好', label: '良好' }
|
||||
{ value: '良好', label: '良好' },
|
||||
],
|
||||
|
||||
|
||||
// 家庭经济情况选择器相关
|
||||
showFamilyStatusPicker: false,
|
||||
familyStatusIndex: [0],
|
||||
// uview-ui 2.x 单列选择器:使用纯字符串数组(二维)最稳定
|
||||
// 格式:[[字符串1, 字符串2, ...]] - 外层数组表示列,内层数组表示选项
|
||||
familyStatusColumns: [['特困', '贫困', '一般', '良好']],
|
||||
|
||||
// 加载状态
|
||||
loading: false,
|
||||
saving: false,
|
||||
submitting: false
|
||||
submitting: false,
|
||||
|
||||
// 按钮样式
|
||||
draftButtonStyle: {
|
||||
marginRight: '20rpx',
|
||||
},
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
onLoad(options) {
|
||||
if (options.positionId) {
|
||||
this.positionId = options.positionId;
|
||||
this.applicationId = options.applicationId || '';
|
||||
this.mode = options.mode || 'create';
|
||||
|
||||
|
||||
this.initData();
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: '岗位ID不能为空',
|
||||
icon: 'none'
|
||||
icon: 'none',
|
||||
});
|
||||
setTimeout(() => {
|
||||
uni.navigateBack();
|
||||
}, 1500);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
methods: {
|
||||
// 返回上一页
|
||||
goBack() {
|
||||
uni.navigateBack();
|
||||
},
|
||||
|
||||
// 家庭经济情况选择器确认
|
||||
// uview-ui 2.x Picker 组件 - 纯字符串数组模式
|
||||
// confirm 事件返回:{ value: [选中值1, 选中值2, ...], indexs: [索引1, 索引2, ...] }
|
||||
// 单列选择器:value 是 ['贫困'],indexs 是 [1]
|
||||
onFamilyStatusConfirm(e) {
|
||||
console.log('=== 家庭经济情况选择器确认 ===');
|
||||
console.log('完整事件参数:', e);
|
||||
console.log('e.value:', e.value); // 例如:['贫困']
|
||||
console.log('e.indexs:', e.indexs); // 例如:[1]
|
||||
|
||||
// 单列选择器,取第一列的值
|
||||
if (e && e.value && Array.isArray(e.value) && e.value.length > 0) {
|
||||
const selectedValue = e.value[0]; // 直接获取字符串,如 "贫困"
|
||||
console.log('选中的值:', selectedValue);
|
||||
|
||||
// 直接赋值
|
||||
this.formData.familyFinancialStatus = selectedValue;
|
||||
|
||||
// 更新索引用于回显
|
||||
if (e.indexs && Array.isArray(e.indexs)) {
|
||||
this.familyStatusIndex = e.indexs;
|
||||
console.log('更新索引为:', this.familyStatusIndex);
|
||||
}
|
||||
|
||||
console.log(
|
||||
'✅ 更新成功,familyFinancialStatus =',
|
||||
this.formData.familyFinancialStatus,
|
||||
);
|
||||
} else {
|
||||
console.error('❌ 无效的选择器返回值:', e);
|
||||
}
|
||||
|
||||
this.showFamilyStatusPicker = false;
|
||||
console.log('=== 选择器关闭 ===\n');
|
||||
},
|
||||
|
||||
// 初始化数据
|
||||
async initData() {
|
||||
this.loading = true;
|
||||
|
||||
|
||||
try {
|
||||
// 并行加载数据
|
||||
const promises = [
|
||||
this.loadPositionData(),
|
||||
this.loadStudentInfo()
|
||||
];
|
||||
|
||||
const promises = [this.loadPositionData(), this.loadStudentInfo()];
|
||||
|
||||
await Promise.all(promises);
|
||||
|
||||
|
||||
// 如果是编辑模式,加载申请详情
|
||||
if (this.mode === 'edit' && this.applicationId) {
|
||||
await this.loadApplicationDetail();
|
||||
}
|
||||
|
||||
|
||||
// 填充学生基本信息
|
||||
this.fillStudentInfo();
|
||||
|
||||
} catch (error) {
|
||||
console.error('初始化数据失败:', error);
|
||||
uni.showToast({
|
||||
title: '加载数据失败',
|
||||
icon: 'none'
|
||||
icon: 'none',
|
||||
});
|
||||
setTimeout(() => {
|
||||
uni.navigateBack();
|
||||
@@ -345,7 +348,7 @@ export default {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
// 加载岗位数据
|
||||
async loadPositionData() {
|
||||
const response = await getPositionWithApplicationStatus(this.positionId);
|
||||
@@ -355,7 +358,7 @@ export default {
|
||||
throw new Error(response.msg || '获取岗位信息失败');
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
// 加载学生信息
|
||||
async loadStudentInfo() {
|
||||
const response = await getCurrentStudentInfo();
|
||||
@@ -365,43 +368,40 @@ export default {
|
||||
throw new Error(response.msg || '获取学生信息失败');
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
// 加载申请详情(编辑模式)
|
||||
async loadApplicationDetail() {
|
||||
const response = await getApplicationDetail(this.applicationId);
|
||||
if (response.code === 200) {
|
||||
const data = response.data;
|
||||
|
||||
|
||||
// 填充表单数据
|
||||
Object.keys(this.formData).forEach(key => {
|
||||
Object.keys(this.formData).forEach((key) => {
|
||||
if (data[key] !== undefined) {
|
||||
this.formData[key] = data[key];
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
// 填充学生基本信息
|
||||
fillStudentInfo() {
|
||||
if (this.studentInfo) {
|
||||
// 修改字段映射以匹配后端返回的字段名
|
||||
this.formData.studentName = this.studentInfo.name || ''; // 修正:name
|
||||
this.formData.studentNumber = this.studentInfo.studentNo || ''; // 修正:studentNo
|
||||
this.formData.studentName = this.studentInfo.name || ''; // 修正:name
|
||||
this.formData.studentNumber = this.studentInfo.studentNo || ''; // 修正:studentNo
|
||||
this.formData.collegeName = this.studentInfo.collegeName || '';
|
||||
this.formData.majorName = this.studentInfo.majorName || '';
|
||||
this.formData.className = this.studentInfo.className || '';
|
||||
|
||||
|
||||
// 如果是创建模式,填充其他基本信息
|
||||
if (this.mode === 'create') {
|
||||
this.formData.idCard = this.studentInfo.idCard || '';
|
||||
this.formData.contactPhone = this.studentInfo.phone || ''; // 修正:phone
|
||||
|
||||
this.formData.contactPhone = this.studentInfo.phone || ''; // 修正:phone
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
// 表单验证
|
||||
validateForm() {
|
||||
const requiredFields = [
|
||||
@@ -415,54 +415,59 @@ export default {
|
||||
{ field: 'familyFinancialStatus', name: '家庭经济情况' },
|
||||
{ field: 'applicationReason', name: '申请理由' },
|
||||
{ field: 'personalAbility', name: '个人能力及经验' },
|
||||
{ field: 'timeArrangement', name: '时间安排' }
|
||||
{ field: 'timeArrangement', name: '时间安排' },
|
||||
];
|
||||
|
||||
|
||||
for (const item of requiredFields) {
|
||||
if (!this.formData[item.field] || this.formData[item.field].trim() === '') {
|
||||
uni.showToast({
|
||||
title: `请填写${item.name}`,
|
||||
icon: 'none'
|
||||
icon: 'none',
|
||||
});
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 验证身份证号格式
|
||||
if (this.formData.idCard && !/^[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/.test(this.formData.idCard)) {
|
||||
if (
|
||||
this.formData.idCard &&
|
||||
!/^[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/.test(
|
||||
this.formData.idCard,
|
||||
)
|
||||
) {
|
||||
uni.showToast({
|
||||
title: '身份证号格式不正确',
|
||||
icon: 'none'
|
||||
icon: 'none',
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// 验证手机号格式
|
||||
if (this.formData.contactPhone && !/^1[3-9]\d{9}$/.test(this.formData.contactPhone)) {
|
||||
uni.showToast({
|
||||
title: '手机号格式不正确',
|
||||
icon: 'none'
|
||||
icon: 'none',
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
|
||||
// 保存草稿
|
||||
async saveDraft(autoNavigate = true) {
|
||||
if (!this.validateForm()) return false;
|
||||
|
||||
|
||||
this.saving = true;
|
||||
|
||||
|
||||
try {
|
||||
const requestData = {
|
||||
...this.formData,
|
||||
positionId: this.positionId,
|
||||
positionName: this.positionData.positionName,
|
||||
positionType: this.positionData.positionType || ''
|
||||
positionType: this.positionData.positionType || '',
|
||||
};
|
||||
|
||||
|
||||
let response;
|
||||
if (this.mode === 'edit' && this.applicationId) {
|
||||
requestData.id = this.applicationId;
|
||||
@@ -470,13 +475,13 @@ export default {
|
||||
} else {
|
||||
response = await addApplication(requestData);
|
||||
}
|
||||
|
||||
|
||||
if (response.code === 200) {
|
||||
uni.showToast({
|
||||
title: '保存成功',
|
||||
icon: 'success'
|
||||
icon: 'success',
|
||||
});
|
||||
|
||||
|
||||
if (autoNavigate) {
|
||||
setTimeout(() => {
|
||||
uni.navigateBack();
|
||||
@@ -490,82 +495,81 @@ export default {
|
||||
console.error('保存草稿失败:', error);
|
||||
uni.showToast({
|
||||
title: error.message || '保存失败',
|
||||
icon: 'none'
|
||||
icon: 'none',
|
||||
});
|
||||
return false;
|
||||
} finally {
|
||||
this.saving = false;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
// 提交申请
|
||||
async submitApplication() {
|
||||
if (!this.validateForm()) return;
|
||||
|
||||
|
||||
try {
|
||||
const { confirm } = await uni.showModal({
|
||||
title: '确认提交',
|
||||
content: '确定要提交申请吗?提交后将无法修改。',
|
||||
showCancel: true
|
||||
showCancel: true,
|
||||
});
|
||||
|
||||
|
||||
if (!confirm) return; // 用户取消
|
||||
|
||||
|
||||
this.submitting = true;
|
||||
|
||||
|
||||
// 先保存申请(不自动跳转)
|
||||
const saveSuccess = await this.saveDraft(false);
|
||||
|
||||
|
||||
if (saveSuccess) {
|
||||
// 这里可以添加提交申请的逻辑
|
||||
// 如果后端有单独的提交接口,可以调用
|
||||
|
||||
|
||||
uni.showToast({
|
||||
title: '提交成功',
|
||||
icon: 'success'
|
||||
icon: 'success',
|
||||
});
|
||||
|
||||
|
||||
setTimeout(() => {
|
||||
uni.navigateBack();
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('提交申请失败:', error);
|
||||
uni.showToast({
|
||||
title: error.message || '提交失败',
|
||||
icon: 'none'
|
||||
icon: 'none',
|
||||
});
|
||||
} finally {
|
||||
this.submitting = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.apply-container {
|
||||
min-height: 100vh;
|
||||
background-color: #f5f5f5;
|
||||
background-color: #f5f6fa;
|
||||
padding-bottom: 120rpx; /* 为底部按钮留空间 */
|
||||
}
|
||||
|
||||
.position-card {
|
||||
background-color: #fff;
|
||||
margin: 20rpx;
|
||||
border-radius: 12rpx;
|
||||
border-radius: 16rpx;
|
||||
padding: 30rpx;
|
||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
|
||||
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.card-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
color: #303133;
|
||||
margin-bottom: 20rpx;
|
||||
padding-bottom: 16rpx;
|
||||
border-bottom: 1rpx solid #f0f0f0;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
.position-info {
|
||||
@@ -593,9 +597,9 @@ export default {
|
||||
.form-container {
|
||||
background-color: #fff;
|
||||
margin: 20rpx;
|
||||
border-radius: 12rpx;
|
||||
border-radius: 16rpx;
|
||||
padding: 30rpx;
|
||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
|
||||
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.form-section {
|
||||
@@ -609,10 +613,10 @@ export default {
|
||||
.section-title {
|
||||
font-size: 30rpx;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
color: #303133;
|
||||
margin-bottom: 30rpx;
|
||||
padding-bottom: 12rpx;
|
||||
border-bottom: 2rpx solid #1890ff;
|
||||
border-bottom: 2rpx solid #3c9cff;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
@@ -623,7 +627,7 @@ export default {
|
||||
left: 0;
|
||||
width: 60rpx;
|
||||
height: 2rpx;
|
||||
background-color: #1890ff;
|
||||
background-color: #3c9cff;
|
||||
}
|
||||
|
||||
.bottom-actions {
|
||||
@@ -661,4 +665,27 @@ export default {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
/* picker输入框样式 */
|
||||
.picker-input {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
padding: 16rpx 24rpx;
|
||||
background-color: #f8f9fa;
|
||||
border-radius: 12rpx;
|
||||
border: 1px solid #eee;
|
||||
}
|
||||
|
||||
.picker-text {
|
||||
font-size: 28rpx;
|
||||
color: #303133;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.picker-text.placeholder {
|
||||
font-size: 24rpx; /* placeholder 字体更小 */
|
||||
color: #c8c9cc;
|
||||
}
|
||||
</style>
|
||||
@@ -1,12 +1,19 @@
|
||||
<template>
|
||||
<view class="detail-container">
|
||||
<!-- 顶部导航 -->
|
||||
<u-navbar title="岗位详情" :border-bottom="false" bg-color="#0051d9" title-color="#fff">
|
||||
<view slot="left" @click="goBack">
|
||||
<u-icon name="arrow-left" color="#fff" size="22"></u-icon>
|
||||
</view>
|
||||
</u-navbar>
|
||||
|
||||
<!-- 岗位基本信息 -->
|
||||
<view class="info-card" v-if="positionData">
|
||||
<view class="card-header">
|
||||
<view class="position-title">
|
||||
<view class="position-name">{{ positionData.positionName }}</view>
|
||||
<view class="position-status">
|
||||
<u-tag
|
||||
<u-tag
|
||||
:text="getStatusText(positionData.status)"
|
||||
:type="getStatusType(positionData.status)"
|
||||
size="mini"
|
||||
@@ -24,15 +31,19 @@
|
||||
<view class="core-info">
|
||||
<view class="info-item">
|
||||
<view class="info-label">
|
||||
<u-icon name="account" size="32" color="#1890ff" />
|
||||
<u-icon name="account" size="18" color="#303133" />
|
||||
<text>招录情况</text>
|
||||
</view>
|
||||
<view class="info-content">
|
||||
<view class="recruitment-info">
|
||||
<text class="recruitment-text">需求 {{ positionData.requiredCount }} 人</text>
|
||||
<text class="recruitment-text current">已招录 {{ positionData.currentCount || 0 }} 人</text>
|
||||
<text class="recruitment-text">
|
||||
需求 {{ positionData.requiredCount }} 人
|
||||
</text>
|
||||
<text class="recruitment-text current">
|
||||
已招录 {{ positionData.currentCount || 0 }} 人
|
||||
</text>
|
||||
</view>
|
||||
<u-line-progress
|
||||
<u-line-progress
|
||||
:percent="getRecruitmentProgress()"
|
||||
:active-color="getProgressColor()"
|
||||
height="12"
|
||||
@@ -43,7 +54,7 @@
|
||||
|
||||
<view class="info-item">
|
||||
<view class="info-label">
|
||||
<u-icon name="clock" size="32" color="#1890ff" />
|
||||
<u-icon name="clock" size="18" color="#303133" />
|
||||
<text>工作时间</text>
|
||||
</view>
|
||||
<view class="info-content">
|
||||
@@ -53,17 +64,19 @@
|
||||
|
||||
<view class="info-item">
|
||||
<view class="info-label">
|
||||
<u-icon name="calendar" size="32" color="#1890ff" />
|
||||
<u-icon name="calendar" size="18" color="#303133" />
|
||||
<text>有效期限</text>
|
||||
</view>
|
||||
<view class="info-content">
|
||||
<text class="info-value">{{ positionData.startDate }} 至 {{ positionData.endDate }}</text>
|
||||
<text class="info-value">
|
||||
{{ positionData.startDate }} 至 {{ positionData.endDate }}
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="info-item">
|
||||
<view class="info-label">
|
||||
<u-icon name="account" size="32" color="#1890ff" />
|
||||
<u-icon name="account" size="18" color="#303133" />
|
||||
<text>联系老师</text>
|
||||
</view>
|
||||
<view class="info-content">
|
||||
@@ -73,17 +86,19 @@
|
||||
|
||||
<view class="info-item">
|
||||
<view class="info-label">
|
||||
<u-icon name="phone" size="32" color="#1890ff" />
|
||||
<u-icon name="phone" size="18" color="#303133" />
|
||||
<text>联系电话</text>
|
||||
</view>
|
||||
<view class="info-content">
|
||||
<text class="info-value contact-phone" @click="callPhone">{{ positionData.contactPhone }}</text>
|
||||
<text class="info-value contact-phone" @click="callPhone">
|
||||
{{ positionData.contactPhone }}
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="info-item" v-if="positionData.salaryInfo">
|
||||
<view class="info-label">
|
||||
<u-icon name="rmb-circle" size="32" color="#1890ff" />
|
||||
<u-icon name="rmb-circle" size="18" color="#303133" />
|
||||
<text>薪资情况</text>
|
||||
</view>
|
||||
<view class="info-content">
|
||||
@@ -96,7 +111,7 @@
|
||||
<!-- 岗位要求 -->
|
||||
<view class="content-card" v-if="positionData && positionData.positionRequirements">
|
||||
<view class="card-title">
|
||||
<u-icon name="file-text" size="32" color="#1890ff" />
|
||||
<u-icon name="file-text" size="18" color="#303133" />
|
||||
<text>岗位要求</text>
|
||||
</view>
|
||||
<view class="content-text">{{ positionData.positionRequirements }}</view>
|
||||
@@ -105,7 +120,7 @@
|
||||
<!-- 工作内容 -->
|
||||
<view class="content-card" v-if="positionData && positionData.workContent">
|
||||
<view class="card-title">
|
||||
<u-icon name="list" size="32" color="#1890ff" />
|
||||
<u-icon name="list" size="18" color="#303133" />
|
||||
<text>工作内容</text>
|
||||
</view>
|
||||
<view class="content-text">{{ positionData.workContent }}</view>
|
||||
@@ -114,13 +129,13 @@
|
||||
<!-- 申请状态 -->
|
||||
<view class="status-card" v-if="applicationStatus">
|
||||
<view class="card-title">
|
||||
<u-icon name="info-circle" size="32" color="#1890ff" />
|
||||
<u-icon name="info-circle" size="18" color="#303133" />
|
||||
<text>我的申请状态</text>
|
||||
</view>
|
||||
<view class="status-content">
|
||||
<view class="status-item">
|
||||
<text class="status-label">申请状态:</text>
|
||||
<u-tag
|
||||
<u-tag
|
||||
:text="applicationStatus.applicationStatusText"
|
||||
:type="getApplicationStatusType(applicationStatus.applicationStatus)"
|
||||
size="mini"
|
||||
@@ -131,21 +146,24 @@
|
||||
<text class="status-label">申请时间:</text>
|
||||
<text class="status-value">{{ applicationStatus.lastApplicationTime }}</text>
|
||||
</view>
|
||||
<view class="status-actions" v-if="applicationStatus.canEdit || applicationStatus.canCancel">
|
||||
<u-button
|
||||
type="warning"
|
||||
size="small"
|
||||
<view
|
||||
class="status-actions"
|
||||
v-if="applicationStatus.canEdit || applicationStatus.canCancel"
|
||||
>
|
||||
<u-button
|
||||
type="warning"
|
||||
size="small"
|
||||
@click="editApplication"
|
||||
v-if="applicationStatus.canEdit"
|
||||
>
|
||||
编辑申请
|
||||
</u-button>
|
||||
<u-button
|
||||
type="error"
|
||||
size="small"
|
||||
<u-button
|
||||
type="error"
|
||||
size="small"
|
||||
@click="cancelApplication"
|
||||
v-if="applicationStatus.canCancel"
|
||||
style="margin-left: 20rpx;"
|
||||
style="margin-left: 20rpx"
|
||||
>
|
||||
撤销申请
|
||||
</u-button>
|
||||
@@ -156,7 +174,7 @@
|
||||
<!-- 备注信息 -->
|
||||
<view class="content-card" v-if="positionData && positionData.remark">
|
||||
<view class="card-title">
|
||||
<u-icon name="chat" size="32" color="#1890ff" />
|
||||
<u-icon name="chat" size="18" color="#303133" />
|
||||
<text>备注信息</text>
|
||||
</view>
|
||||
<view class="content-text">{{ positionData.remark }}</view>
|
||||
@@ -164,9 +182,9 @@
|
||||
|
||||
<!-- 底部操作按钮 -->
|
||||
<view class="bottom-actions">
|
||||
<u-button
|
||||
type="primary"
|
||||
size="large"
|
||||
<u-button
|
||||
type="primary"
|
||||
size="large"
|
||||
@click="handleApply"
|
||||
:disabled="!canApply()"
|
||||
:loading="submitting"
|
||||
@@ -181,10 +199,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
getPositionWithApplicationStatus,
|
||||
cancelApplication
|
||||
} from '@/api/workStudy.js';
|
||||
import { getPositionWithApplicationStatus, cancelApplication } from '@/api/workStudy.js';
|
||||
|
||||
export default {
|
||||
name: 'WorkStudyDetail',
|
||||
@@ -194,10 +209,10 @@ export default {
|
||||
positionData: null,
|
||||
applicationStatus: null,
|
||||
loading: false,
|
||||
submitting: false
|
||||
submitting: false,
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
onLoad(options) {
|
||||
if (options.id) {
|
||||
this.positionId = options.id;
|
||||
@@ -205,22 +220,27 @@ export default {
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: '岗位ID不能为空',
|
||||
icon: 'none'
|
||||
icon: 'none',
|
||||
});
|
||||
setTimeout(() => {
|
||||
uni.navigateBack();
|
||||
}, 1500);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
methods: {
|
||||
// 返回上一页
|
||||
goBack() {
|
||||
uni.navigateBack();
|
||||
},
|
||||
|
||||
// 加载岗位详情
|
||||
async loadPositionDetail() {
|
||||
this.loading = true;
|
||||
|
||||
|
||||
try {
|
||||
const response = await getPositionWithApplicationStatus(this.positionId);
|
||||
|
||||
|
||||
if (response.code === 200) {
|
||||
this.positionData = response.data.position;
|
||||
this.applicationStatus = response.data.applicationStatus;
|
||||
@@ -231,9 +251,9 @@ export default {
|
||||
console.error('加载岗位详情失败:', error);
|
||||
uni.showToast({
|
||||
title: error.message || '加载失败',
|
||||
icon: 'none'
|
||||
icon: 'none',
|
||||
});
|
||||
|
||||
|
||||
setTimeout(() => {
|
||||
uni.navigateBack();
|
||||
}, 1500);
|
||||
@@ -241,62 +261,66 @@ export default {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
// 申请岗位
|
||||
handleApply() {
|
||||
if (!this.canApply()) {
|
||||
uni.showToast({
|
||||
title: this.getApplyButtonText(),
|
||||
icon: 'none'
|
||||
icon: 'none',
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// 如果已有申请且可以编辑,则编辑申请
|
||||
if (this.applicationStatus && this.applicationStatus.hasApplication && this.applicationStatus.canEdit) {
|
||||
if (
|
||||
this.applicationStatus &&
|
||||
this.applicationStatus.hasApplication &&
|
||||
this.applicationStatus.canEdit
|
||||
) {
|
||||
this.editApplication();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// 否则新建申请
|
||||
uni.navigateTo({
|
||||
url: `/pages/workStudy/apply?positionId=${this.positionId}`
|
||||
url: `/pages/workStudy/apply?positionId=${this.positionId}`,
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
// 编辑申请
|
||||
editApplication() {
|
||||
if (this.applicationStatus && this.applicationStatus.applicationId) {
|
||||
uni.navigateTo({
|
||||
url: `/pages/workStudy/apply?positionId=${this.positionId}&applicationId=${this.applicationStatus.applicationId}&mode=edit`
|
||||
url: `/pages/workStudy/apply?positionId=${this.positionId}&applicationId=${this.applicationStatus.applicationId}&mode=edit`,
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
// 撤销申请
|
||||
async cancelApplication() {
|
||||
if (!this.applicationStatus || !this.applicationStatus.applicationId) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
const { confirm } = await uni.showModal({
|
||||
title: '确认撤销',
|
||||
content: '确定要撤销此申请吗?',
|
||||
showCancel: true
|
||||
showCancel: true,
|
||||
});
|
||||
|
||||
|
||||
if (!confirm) return; // 用户取消
|
||||
|
||||
|
||||
this.submitting = true;
|
||||
const response = await cancelApplication(this.applicationStatus.applicationId);
|
||||
|
||||
|
||||
if (response.code === 200) {
|
||||
uni.showToast({
|
||||
title: '撤销成功',
|
||||
icon: 'success'
|
||||
icon: 'success',
|
||||
});
|
||||
|
||||
|
||||
// 重新加载数据
|
||||
setTimeout(() => {
|
||||
this.loadPositionDetail();
|
||||
@@ -308,13 +332,13 @@ export default {
|
||||
console.error('撤销申请失败:', error);
|
||||
uni.showToast({
|
||||
title: error.message || '撤销失败',
|
||||
icon: 'none'
|
||||
icon: 'none',
|
||||
});
|
||||
} finally {
|
||||
this.submitting = false;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
// 拨打电话
|
||||
callPhone() {
|
||||
if (this.positionData && this.positionData.contactPhone) {
|
||||
@@ -324,41 +348,41 @@ export default {
|
||||
console.error('拨打电话失败:', error);
|
||||
uni.showToast({
|
||||
title: '拨打电话失败',
|
||||
icon: 'none'
|
||||
icon: 'none',
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
// 获取状态文字
|
||||
getStatusText(status) {
|
||||
const statusMap = {
|
||||
'DRAFT': '草稿',
|
||||
'PUBLISHED': '已发布',
|
||||
'RECRUITING': '招录中',
|
||||
'FULL': '已满员',
|
||||
'EXPIRED': '已过期',
|
||||
'SUSPENDED': '已暂停',
|
||||
'CANCELLED': '已取消'
|
||||
DRAFT: '草稿',
|
||||
PUBLISHED: '已发布',
|
||||
RECRUITING: '招录中',
|
||||
FULL: '已满员',
|
||||
EXPIRED: '已过期',
|
||||
SUSPENDED: '已暂停',
|
||||
CANCELLED: '已取消',
|
||||
};
|
||||
return statusMap[status] || '未知状态';
|
||||
},
|
||||
|
||||
|
||||
// 获取状态类型
|
||||
getStatusType(status) {
|
||||
const typeMap = {
|
||||
'DRAFT': 'info',
|
||||
'PUBLISHED': 'warning',
|
||||
'RECRUITING': 'success',
|
||||
'FULL': 'primary',
|
||||
'EXPIRED': 'error',
|
||||
'SUSPENDED': 'warning',
|
||||
'CANCELLED': 'error'
|
||||
DRAFT: 'info',
|
||||
PUBLISHED: 'warning',
|
||||
RECRUITING: 'success',
|
||||
FULL: 'primary',
|
||||
EXPIRED: 'error',
|
||||
SUSPENDED: 'warning',
|
||||
CANCELLED: 'error',
|
||||
};
|
||||
return typeMap[status] || 'default';
|
||||
},
|
||||
|
||||
|
||||
// 获取招录进度
|
||||
getRecruitmentProgress() {
|
||||
if (!this.positionData || !this.positionData.requiredCount) return 0;
|
||||
@@ -366,7 +390,7 @@ export default {
|
||||
const required = this.positionData.requiredCount;
|
||||
return Math.min(Math.round((current / required) * 100), 100);
|
||||
},
|
||||
|
||||
|
||||
// 获取进度条颜色
|
||||
getProgressColor() {
|
||||
const progress = this.getRecruitmentProgress();
|
||||
@@ -375,49 +399,55 @@ export default {
|
||||
if (progress >= 50) return '#1890ff';
|
||||
return '#52c41a';
|
||||
},
|
||||
|
||||
|
||||
// 判断是否可以申请
|
||||
canApply() {
|
||||
if (!this.positionData) return false;
|
||||
|
||||
|
||||
// 岗位状态必须是招录中
|
||||
if (this.positionData.status !== 'RECRUITING') return false;
|
||||
|
||||
|
||||
// 如果已有申请,判断是否可以重新申请
|
||||
if (this.applicationStatus && this.applicationStatus.hasApplication) {
|
||||
// 如果申请被拒绝,可以重新申请
|
||||
return this.applicationStatus.applicationStatus === 'FINAL_REJECTED' ||
|
||||
this.applicationStatus.applicationStatus === 'COLLEGE_REJECTED';
|
||||
return (
|
||||
this.applicationStatus.applicationStatus === 'FINAL_REJECTED' ||
|
||||
this.applicationStatus.applicationStatus === 'COLLEGE_REJECTED'
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// 检查是否已满员
|
||||
const current = this.positionData.currentCount || 0;
|
||||
const required = this.positionData.requiredCount || 0;
|
||||
return current < required;
|
||||
},
|
||||
|
||||
|
||||
// 获取申请按钮文字
|
||||
getApplyButtonText() {
|
||||
if (!this.positionData) return '加载中...';
|
||||
|
||||
|
||||
if (this.positionData.status !== 'RECRUITING') {
|
||||
return '岗位暂不可申请';
|
||||
}
|
||||
|
||||
|
||||
// 检查是否已满员
|
||||
const current = this.positionData.currentCount || 0;
|
||||
const required = this.positionData.requiredCount || 0;
|
||||
if (current >= required) {
|
||||
return '岗位已满员';
|
||||
}
|
||||
|
||||
|
||||
// 如果有申请记录
|
||||
if (this.applicationStatus && this.applicationStatus.hasApplication) {
|
||||
const status = this.applicationStatus.applicationStatus;
|
||||
|
||||
|
||||
if (status === 'DRAFT') {
|
||||
return '完善申请信息';
|
||||
} else if (status === 'SUBMITTED' || status === 'COLLEGE_REVIEWING' || status === 'FINAL_REVIEWING') {
|
||||
} else if (
|
||||
status === 'SUBMITTED' ||
|
||||
status === 'COLLEGE_REVIEWING' ||
|
||||
status === 'FINAL_REVIEWING'
|
||||
) {
|
||||
return '申请审核中';
|
||||
} else if (status === 'FINAL_APPROVED') {
|
||||
return '申请已通过';
|
||||
@@ -426,45 +456,47 @@ export default {
|
||||
} else if (status === 'CANCELLED') {
|
||||
return '重新申请';
|
||||
}
|
||||
|
||||
|
||||
return '查看申请状态';
|
||||
}
|
||||
|
||||
|
||||
return '申请此岗位';
|
||||
},
|
||||
|
||||
|
||||
// 获取申请状态类型
|
||||
getApplicationStatusType(status) {
|
||||
const typeMap = {
|
||||
'DRAFT': 'info',
|
||||
'SUBMITTED': 'warning',
|
||||
'COLLEGE_REVIEWING': 'warning',
|
||||
'COLLEGE_APPROVED': 'success',
|
||||
'COLLEGE_REJECTED': 'error',
|
||||
'FINAL_REVIEWING': 'warning',
|
||||
'FINAL_APPROVED': 'success',
|
||||
'FINAL_REJECTED': 'error',
|
||||
'CANCELLED': 'info'
|
||||
DRAFT: 'info',
|
||||
SUBMITTED: 'warning',
|
||||
COLLEGE_REVIEWING: 'warning',
|
||||
COLLEGE_APPROVED: 'success',
|
||||
COLLEGE_REJECTED: 'error',
|
||||
FINAL_REVIEWING: 'warning',
|
||||
FINAL_APPROVED: 'success',
|
||||
FINAL_REJECTED: 'error',
|
||||
CANCELLED: 'info',
|
||||
};
|
||||
return typeMap[status] || 'default';
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.detail-container {
|
||||
min-height: 100vh;
|
||||
background-color: #f5f5f5;
|
||||
background-color: #f5f6fa;
|
||||
padding-bottom: 120rpx; /* 为底部按钮留空间 */
|
||||
}
|
||||
|
||||
.info-card, .content-card, .status-card {
|
||||
.info-card,
|
||||
.content-card,
|
||||
.status-card {
|
||||
background-color: #fff;
|
||||
margin: 20rpx;
|
||||
border-radius: 12rpx;
|
||||
border-radius: 16rpx;
|
||||
padding: 30rpx;
|
||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
|
||||
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.card-header {
|
||||
@@ -481,7 +513,7 @@ export default {
|
||||
.position-name {
|
||||
font-size: 36rpx;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
color: #303133;
|
||||
flex: 1;
|
||||
line-height: 1.3;
|
||||
}
|
||||
@@ -530,7 +562,7 @@ export default {
|
||||
.info-label text {
|
||||
font-size: 28rpx;
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
color: #303133;
|
||||
margin-left: 12rpx;
|
||||
}
|
||||
|
||||
@@ -540,7 +572,7 @@ export default {
|
||||
|
||||
.info-value {
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
color: #606266;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
@@ -566,7 +598,7 @@ export default {
|
||||
}
|
||||
|
||||
.recruitment-text.current {
|
||||
color: #1890ff;
|
||||
color: #0051d9;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
@@ -579,15 +611,15 @@ export default {
|
||||
}
|
||||
|
||||
.card-title text {
|
||||
font-size: 32rpx;
|
||||
font-size: 30rpx;
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
color: #303133;
|
||||
margin-left: 12rpx;
|
||||
}
|
||||
|
||||
.content-text {
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
color: #606266;
|
||||
line-height: 1.8;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
Reference in new issue
Block a user