467 lines
16 KiB
Vue
467 lines
16 KiB
Vue
<template>
|
||
<view class="visit-detail-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>
|
||
|
||
<!-- 内容区域 -->
|
||
<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 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 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>
|
||
</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>
|
||
|
||
<script>
|
||
import { getVisit, delVisit } from '@/api/visit.js';
|
||
|
||
export default {
|
||
name: 'VisitDetail',
|
||
data() {
|
||
return {
|
||
// 页面参数
|
||
visitId: '',
|
||
|
||
// 页面状态
|
||
pageLoading: true,
|
||
loading: false,
|
||
|
||
// 走访信息
|
||
visitInfo: {},
|
||
|
||
// 图片数据
|
||
imageList: [],
|
||
};
|
||
},
|
||
|
||
computed: {
|
||
// 是否可以编辑
|
||
canEdit() {
|
||
// 只有计划中或草稿状态的记录可以编辑
|
||
return (
|
||
this.visitInfo.status === 'planned' ||
|
||
this.visitInfo.status === '0' ||
|
||
this.visitInfo.status === 'draft'
|
||
);
|
||
},
|
||
},
|
||
|
||
onLoad(options) {
|
||
if (options.id) {
|
||
this.visitId = options.id;
|
||
this.loadVisitDetail();
|
||
} else {
|
||
uni.showToast({ title: '参数错误', icon: 'none' });
|
||
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 {
|
||
this.imageList = JSON.parse(response.data.visitImages) || [];
|
||
} catch (e) {
|
||
console.warn('解析图片数据失败:', e);
|
||
this.imageList = [];
|
||
}
|
||
}
|
||
} else {
|
||
uni.showToast({ title: response.msg || '获取数据失败', icon: 'none' });
|
||
uni.navigateBack();
|
||
}
|
||
} catch (error) {
|
||
console.error('加载走访记录详情失败:', error);
|
||
uni.showToast({ title: '网络异常,请稍后重试', icon: 'none' });
|
||
uni.navigateBack();
|
||
} finally {
|
||
this.pageLoading = false;
|
||
}
|
||
},
|
||
|
||
// 获取状态文本
|
||
getStatusText(status) {
|
||
switch (status) {
|
||
case 'planned':
|
||
case '0':
|
||
return '计划中';
|
||
case 'completed':
|
||
case '1':
|
||
return '已完成';
|
||
case 'cancelled':
|
||
case '2':
|
||
return '已取消';
|
||
default:
|
||
return status || '未知';
|
||
}
|
||
},
|
||
|
||
// 获取状态类型
|
||
getStatusType(status) {
|
||
switch (status) {
|
||
case 'planned':
|
||
case '0':
|
||
return 'primary';
|
||
case 'completed':
|
||
case '1':
|
||
return 'success';
|
||
case 'cancelled':
|
||
case '2':
|
||
return 'error';
|
||
default:
|
||
return 'default';
|
||
}
|
||
},
|
||
|
||
// 预览图片
|
||
previewImage(index) {
|
||
const urls = this.imageList.map((item) => item.url);
|
||
uni.previewImage({
|
||
urls,
|
||
current: index,
|
||
});
|
||
},
|
||
|
||
// 编辑走访记录
|
||
handleEdit() {
|
||
uni.navigateTo({
|
||
url: `/pages/visit/edit?id=${this.visitId}`,
|
||
});
|
||
},
|
||
|
||
// 删除走访记录
|
||
handleDelete() {
|
||
uni.showModal({
|
||
title: '确认删除',
|
||
content: '确定要删除这条走访记录吗?删除后无法恢复。',
|
||
success: async (res) => {
|
||
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(() => {
|
||
uni.navigateBack();
|
||
}, 1500);
|
||
} else {
|
||
uni.showToast({ title: response.msg || '删除失败', icon: 'none' });
|
||
}
|
||
} catch (error) {
|
||
console.error('删除走访记录失败:', error);
|
||
uni.showToast({ title: '网络异常,请稍后重试', icon: 'none' });
|
||
} finally {
|
||
this.loading = false;
|
||
}
|
||
},
|
||
},
|
||
};
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.visit-detail-container {
|
||
min-height: 100vh;
|
||
background-color: #f8f8f8;
|
||
}
|
||
|
||
.content-wrapper {
|
||
padding: 20rpx;
|
||
padding-bottom: 40rpx;
|
||
}
|
||
|
||
.info-section {
|
||
background: #ffffff;
|
||
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: linear-gradient(135deg, #f8f9fa 0%, #ffffff 100%);
|
||
}
|
||
|
||
.section-content {
|
||
padding: 20rpx;
|
||
}
|
||
}
|
||
|
||
.info-item {
|
||
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;
|
||
width: 160rpx;
|
||
flex-shrink: 0;
|
||
margin-bottom: 8rpx;
|
||
}
|
||
|
||
.info-value {
|
||
font-size: 28rpx;
|
||
color: #303133;
|
||
flex: 1;
|
||
|
||
&.info-value-multiline {
|
||
line-height: 1.8;
|
||
word-break: break-all;
|
||
color: #606266;
|
||
}
|
||
}
|
||
}
|
||
|
||
.image-grid {
|
||
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%;
|
||
}
|
||
}
|
||
}
|
||
|
||
.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>
|