Some checks failed
Uniapp 自动化打包 CI/CD / 打包 Uniapp 项目 (push) Has been cancelled
420 lines
7.7 KiB
Vue
420 lines
7.7 KiB
Vue
<template>
|
||
<view class="page-container">
|
||
|
||
<!-- 表单区域 -->
|
||
<view class="form-section">
|
||
<view class="form-item">
|
||
<text class="form-label">补卡时间</text>
|
||
<picker mode="date" :value="form.date" @change="onDateChange">
|
||
<view class="picker">{{ form.date }} {{ form.time }}</view>
|
||
</picker>
|
||
</view>
|
||
|
||
<view class="tip-text">
|
||
<text>本月已补卡{{ usedTimes }}次,剩余{{ remainTimes }}次。</text>
|
||
</view>
|
||
|
||
<view class="form-item">
|
||
<text class="form-label">补卡说明</text>
|
||
<textarea v-model="form.remark" placeholder="请输入" class="textarea" />
|
||
</view>
|
||
|
||
<view class="form-item">
|
||
<text class="form-label">附件</text>
|
||
<!-- 如果没有图片,显示上传按钮 -->
|
||
<view class="custom-upload-btn" @click="chooseImage" v-if="!selectedImage">
|
||
<image class="image" src="/static/ic_camera.png"></image>
|
||
<text class="text">上传图片</text>
|
||
</view>
|
||
|
||
<!-- 已选图片预览 -->
|
||
<view class="preview-item" v-else>
|
||
<image class="preview-img" :src="selectedImage" mode="aspectFill" @click="previewImage"></image>
|
||
<view class="delete-btn" @click.stop="deletePic">✕</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 审批记录 -->
|
||
<view class="record-section">
|
||
<text class="section-title">审批记录</text>
|
||
<view class="timeline">
|
||
<view v-for="(item, index) in records" :key="index" class="timeline-item">
|
||
<!-- 点 -->
|
||
<view class="timeline-dot"></view>
|
||
|
||
<!-- 节点内容 -->
|
||
<view class="timeline-content">
|
||
<text class="end-text">{{ item.node }}</text>
|
||
|
||
<view class="record-row" v-if="item.status !== '结束'">
|
||
<image class="avatar" :src="item.avatar" mode="aspectFill" />
|
||
<view class="name-node-container">
|
||
<text class="name">{{ item.name }}</text>
|
||
<text class="status" :class="statusClass(item.status)">{{ item.status }}</text>
|
||
</view>
|
||
<text class="time2">{{ item.time }}</text>
|
||
</view>
|
||
<text v-else class="time">{{ item.time }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 提交按钮 -->
|
||
<view class="footer">
|
||
<button class="submit-btn" type="primary" @click="submit">提交</button>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
export default {
|
||
data() {
|
||
return {
|
||
usedTimes: 0,
|
||
remainTimes: 5,
|
||
selectedImage: '',
|
||
form: {
|
||
date: '2025-07-13',
|
||
time: '09:00',
|
||
remark: ''
|
||
},
|
||
records: [{
|
||
node: '提交',
|
||
name: '于永乐',
|
||
status: '已提交',
|
||
time: '07-12 18:28:22',
|
||
avatar: '/static/avatar1.png'
|
||
},
|
||
{
|
||
node: '审批',
|
||
name: '张桂花',
|
||
status: '已同意',
|
||
time: '07-12 18:30:12',
|
||
avatar: '/static/avatar2.png'
|
||
},
|
||
{
|
||
node: '审批',
|
||
name: '张桂花',
|
||
status: '已拒绝',
|
||
time: '07-12 19:12:45',
|
||
avatar: '/static/avatar2.png'
|
||
},
|
||
{
|
||
node: '结束',
|
||
name: '',
|
||
status: '结束',
|
||
time: '07-12 20:00:00',
|
||
avatar: ''
|
||
}
|
||
]
|
||
}
|
||
},
|
||
methods: {
|
||
onDateChange(e) {
|
||
this.form.date = e.detail.value
|
||
},
|
||
chooseImage() {
|
||
uni.chooseImage({
|
||
count: 1,
|
||
success: (res) => {
|
||
this.selectedImage = res.tempFilePaths[0]
|
||
}
|
||
})
|
||
},
|
||
// 预览图片
|
||
previewImage() {
|
||
uni.previewImage({
|
||
current: this.selectedImage,
|
||
urls: [this.selectedImage]
|
||
})
|
||
},
|
||
// 删除图片
|
||
deletePic(event) {
|
||
this.selectedImage = ''
|
||
},
|
||
|
||
submit() {
|
||
uni.showToast({
|
||
title: '提交成功',
|
||
icon: 'success'
|
||
})
|
||
},
|
||
statusClass(status) {
|
||
if (status === '已提交') return 'blue'
|
||
if (status === '已同意') return 'green'
|
||
if (status === '已拒绝') return 'orange'
|
||
if (status === '结束') return 'gray'
|
||
return ''
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style scoped>
|
||
.page-container {
|
||
background: #f5f5f5;
|
||
min-height: 100vh;
|
||
display: flex;
|
||
flex-direction: column;
|
||
}
|
||
|
||
.form-section {
|
||
background: #fff;
|
||
margin: 20rpx;
|
||
padding: 20rpx;
|
||
border-radius: 12rpx;
|
||
}
|
||
|
||
.form-item {
|
||
margin-bottom: 20rpx;
|
||
}
|
||
|
||
.form-label {
|
||
font-size: 24rpx;
|
||
color: #737373;
|
||
margin-bottom: 10rpx;
|
||
display: block;
|
||
}
|
||
|
||
.tip-text {
|
||
height: 73rpx;
|
||
line-height: 73rpx;
|
||
background: #F7F7F7;
|
||
color: #808080;
|
||
font-size: 24rpx;
|
||
border-radius: 10rpx;
|
||
padding-left: 16rpx;
|
||
}
|
||
|
||
.textarea {
|
||
width: 100%;
|
||
height: 160rpx;
|
||
border: 2rpx solid #ddd;
|
||
border-radius: 8rpx;
|
||
padding: 12rpx;
|
||
font-size: 24rpx;
|
||
}
|
||
|
||
.upload-box {
|
||
border: 2rpx dashed #aaa;
|
||
border-radius: 12rpx;
|
||
padding: 40rpx;
|
||
text-align: center;
|
||
color: #888;
|
||
}
|
||
|
||
.upload-icon {
|
||
width: 60rpx;
|
||
height: 60rpx;
|
||
margin-bottom: 12rpx;
|
||
}
|
||
|
||
/* 审批记录 */
|
||
.record-section {
|
||
background: #fff;
|
||
border-radius: 25rpx;
|
||
margin-left: 32rpx;
|
||
margin-right: 32rpx;
|
||
padding: 35rpx 25rpx 35rpx 25rpx;
|
||
}
|
||
|
||
.section-title {
|
||
font-size: 30rpx;
|
||
font-weight: bold;
|
||
margin-bottom: 20rpx;
|
||
color: #333;
|
||
}
|
||
|
||
/* timeline 方法二:每个节点自己画线 */
|
||
.timeline {
|
||
position: relative;
|
||
margin-left: 12rpx;
|
||
margin-top: 45rpx;
|
||
}
|
||
|
||
.timeline-item {
|
||
position: relative;
|
||
padding-left: 40rpx;
|
||
padding-bottom: 50rpx;
|
||
}
|
||
|
||
.timeline-item::before {
|
||
content: "";
|
||
position: absolute;
|
||
top: 0;
|
||
bottom: 0;
|
||
left: -2rpx;
|
||
width: 2rpx;
|
||
background: #ddd;
|
||
}
|
||
|
||
/* 第一个节点:去掉上半段 */
|
||
.timeline-item:first-child::before {
|
||
top: 20rpx;
|
||
}
|
||
|
||
/* 最后一个节点:去掉下半段 */
|
||
.timeline-item:last-child::before {
|
||
bottom: auto;
|
||
height: 20rpx;
|
||
}
|
||
|
||
/* 状态点 */
|
||
.timeline-dot {
|
||
position: absolute;
|
||
left: -12rpx;
|
||
top: 10rpx;
|
||
width: 20rpx;
|
||
height: 20rpx;
|
||
border: 1rpx solid #10AF7F;
|
||
border-radius: 50%;
|
||
background: #fff;
|
||
}
|
||
|
||
.timeline-content {
|
||
margin-left: -20rpx;
|
||
}
|
||
|
||
.record-row {
|
||
display: flex;
|
||
align-items: center;
|
||
margin-bottom: 8rpx;
|
||
}
|
||
|
||
.avatar {
|
||
width: 54rpx;
|
||
height: 54rpx;
|
||
border-radius: 50%;
|
||
margin-right: 15rpx;
|
||
background: #688CFF;
|
||
}
|
||
|
||
.name-node-container {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: flex-start;
|
||
}
|
||
|
||
.name {
|
||
font-size: 28rpx;
|
||
color: #000;
|
||
}
|
||
|
||
.status {
|
||
font-size: 22rpx;
|
||
font-weight: 500;
|
||
}
|
||
|
||
.status.blue {
|
||
color: #007aff;
|
||
}
|
||
|
||
.status.green {
|
||
color: #4caf50;
|
||
}
|
||
|
||
.status.orange {
|
||
color: #ff6b35;
|
||
}
|
||
|
||
.status.gray {
|
||
color: #999;
|
||
}
|
||
|
||
.end-text {
|
||
font-size: 24rpx;
|
||
color: #000;
|
||
font-weight: bold;
|
||
}
|
||
|
||
.time {
|
||
font-size: 24rpx;
|
||
color: #626262;
|
||
float: right;
|
||
margin-right: 40rpx;
|
||
}
|
||
|
||
.time2 {
|
||
font-size: 24rpx;
|
||
color: #626262;
|
||
position: absolute;
|
||
right: 40rpx;
|
||
bottom: 70rpx;
|
||
}
|
||
|
||
.footer {
|
||
padding: 20rpx;
|
||
}
|
||
|
||
.submit-btn {
|
||
width: 100%;
|
||
height: 90rpx;
|
||
line-height: 90rpx;
|
||
border-radius: 50rpx;
|
||
background: #007aff;
|
||
color: #fff;
|
||
font-size: 32rpx;
|
||
}
|
||
|
||
.text {
|
||
color: #000000;
|
||
font-size: 24rpx;
|
||
margin-left: 10rpx;
|
||
font-weight: 400;
|
||
}
|
||
|
||
.image {
|
||
width: 55rpx;
|
||
height: 42rpx;
|
||
}
|
||
|
||
.custom-upload-btn {
|
||
width: auto;
|
||
margin-left: 0rpx;
|
||
margin-right: 0rpx;
|
||
margin-top: 24rpx;
|
||
height: 244rpx;
|
||
background: #f6f6f6;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: center;
|
||
border-radius: 16rpx;
|
||
}
|
||
|
||
.preview-item {
|
||
position: relative;
|
||
width: auto;
|
||
/* 宽度自动 */
|
||
margin-left: 40rpx;
|
||
margin-right: 40rpx;
|
||
height: 244rpx;
|
||
margin-top: 24rpx;
|
||
/* 固定高度 */
|
||
display: flex;
|
||
justify-content: center;
|
||
/* 水平居中 */
|
||
align-items: center;
|
||
/* 垂直居中 */
|
||
overflow: hidden;
|
||
/* 裁剪超出部分 */
|
||
border-radius: 10rpx;
|
||
/* 可选:圆角 */
|
||
}
|
||
|
||
.delete-btn {
|
||
position: absolute;
|
||
top: 0;
|
||
right: 0;
|
||
width: 40rpx;
|
||
height: 40rpx;
|
||
line-height: 40rpx;
|
||
text-align: center;
|
||
border-radius: 50%;
|
||
background: rgba(0, 0, 0, 0.6);
|
||
color: #fff;
|
||
font-size: 24rpx;
|
||
}
|
||
</style> |