This commit is contained in:
19
App.vue
19
App.vue
@@ -7,12 +7,27 @@ export default {
|
|||||||
// 国际化,设置当前语言
|
// 国际化,设置当前语言
|
||||||
if (this.vuex_locale) {
|
if (this.vuex_locale) {
|
||||||
this.$i18n.locale = this.vuex_locale;
|
this.$i18n.locale = this.vuex_locale;
|
||||||
this.$u.api.lang({lang: this.vuex_locale});
|
this.$u.api.lang({
|
||||||
|
lang: this.vuex_locale
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
//只有在基座运行的情况下才能打印看到
|
//只有在基座运行的情况下才能打印看到
|
||||||
const clientInfo = plus.push.getClientInfo()
|
const clientInfo = plus.push.getClientInfo()
|
||||||
console.log(clientInfo)
|
|
||||||
|
this.$store.commit('$uStore', {
|
||||||
|
name: 'vuex_push_clientId',
|
||||||
|
value: clientInfo.clientid
|
||||||
|
});
|
||||||
|
|
||||||
|
// 监听系统通知栏点击事件
|
||||||
|
plus.push.addEventListener("click", function(msg) {
|
||||||
|
console.log("用户点击了推送消息:", msg);
|
||||||
|
// msg.payload 就是推送时传的自定义数据
|
||||||
|
uni.navigateTo({
|
||||||
|
url: "/pages/sys/workbench/earlyWarning/warnDetail",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
// 设置底部导航栏角标
|
// 设置底部导航栏角标
|
||||||
// uni.setTabBarBadge({
|
// uni.setTabBarBadge({
|
||||||
|
@@ -30,5 +30,5 @@ const config = {
|
|||||||
config.baseUrl = 'http://183.230.235.66:11010/api';
|
config.baseUrl = 'http://183.230.235.66:11010/api';
|
||||||
|
|
||||||
|
|
||||||
// config.baseUrl = 'http://5b35f15d.r28.cpolar.top';
|
// config.baseUrl = 'http://3efb1a71.r28.cpolar.top';
|
||||||
export default config;
|
export default config;
|
||||||
|
@@ -26,6 +26,7 @@ const install = (Vue, vm) => {
|
|||||||
}
|
}
|
||||||
req.header["source"] = "uniapp";
|
req.header["source"] = "uniapp";
|
||||||
req.header["clientId"] = "dab457a1ea14411787c240db05bb0832"
|
req.header["clientId"] = "dab457a1ea14411787c240db05bb0832"
|
||||||
|
req.header["pushClientId"] = vm.vuex_push_clientId
|
||||||
// 默认指定返回 JSON 数据
|
// 默认指定返回 JSON 数据
|
||||||
if (!req.header[ajaxHeader]){
|
if (!req.header[ajaxHeader]){
|
||||||
req.header[ajaxHeader] = 'json';
|
req.header[ajaxHeader] = 'json';
|
||||||
|
@@ -1,12 +1,12 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="calendar-container">
|
<view class="calendar-container">
|
||||||
<!-- 展开/收起按钮,可以外部隐藏 -->
|
<!-- 展开/收起按钮,可以外部隐藏 -->
|
||||||
<view class="calendar-header">
|
<!-- <view class="calendar-header">
|
||||||
<button size="mini" @click="toggleMode">
|
<button size="mini" @click="toggleMode">
|
||||||
{{ mode === 'month' ? '收起为周' : '展开为月' }}
|
{{ mode === 'month' ? '收起为周' : '展开为月' }}
|
||||||
</button>
|
</button>
|
||||||
<text>{{ displayTitle }}</text>
|
<text>{{ displayTitle }}</text>
|
||||||
</view>
|
</view> -->
|
||||||
|
|
||||||
<view
|
<view
|
||||||
class="calendar-content"
|
class="calendar-content"
|
||||||
@@ -46,7 +46,7 @@ export default {
|
|||||||
props: {
|
props: {
|
||||||
initialMode: { type: String, default: 'month' }, // 'month' or 'week'
|
initialMode: { type: String, default: 'month' }, // 'month' or 'week'
|
||||||
initialDate: { type: String, default: '' },
|
initialDate: { type: String, default: '' },
|
||||||
allowWeekSwitch: { type: Boolean, default: true } // 控制是否允许上下滑切换
|
allowWeekSwitch: { type: Boolean, default: false } // 控制是否允许上下滑切换
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
const today = new Date()
|
const today = new Date()
|
||||||
@@ -68,8 +68,10 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
mode() {
|
mode(newMode, oldMode) {
|
||||||
this.generateRenderDays()
|
this.generateRenderDays()
|
||||||
|
// 通知父组件mode已改变
|
||||||
|
this.$emit('modeChange', newMode);
|
||||||
},
|
},
|
||||||
selected() {
|
selected() {
|
||||||
this.generateRenderDays()
|
this.generateRenderDays()
|
||||||
@@ -231,15 +233,27 @@ export default {
|
|||||||
let year = y
|
let year = y
|
||||||
if (m > 12) { m = 1; year++ }
|
if (m > 12) { m = 1; year++ }
|
||||||
if (m < 1) { m = 12; year-- }
|
if (m < 1) { m = 12; year-- }
|
||||||
|
|
||||||
|
// 切换后的基准日期设为该月1号
|
||||||
this.anchorDate = new Date(year, m - 1, 1)
|
this.anchorDate = new Date(year, m - 1, 1)
|
||||||
|
this.selected = this.formatDate(this.anchorDate) // ✅ 选中当月1号
|
||||||
|
this.$emit('dateChange', this.selected)
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
const d = this.safeDate(this.selected)
|
// 以当前 anchorDate 为基准移动周
|
||||||
|
const d = this.safeDate(this.anchorDate)
|
||||||
d.setDate(d.getDate() + direction * 7)
|
d.setDate(d.getDate() + direction * 7)
|
||||||
this.selected = this.formatDate(d)
|
|
||||||
|
// 更新基准周
|
||||||
this.anchorDate = this.startOfWeek(d)
|
this.anchorDate = this.startOfWeek(d)
|
||||||
|
|
||||||
|
// ✅ 选中该周周日(startOfWeek返回的就是周日)
|
||||||
|
this.selected = this.formatDate(this.anchorDate)
|
||||||
|
this.$emit('dateChange', this.selected)
|
||||||
}
|
}
|
||||||
this.generateRenderDays()
|
this.generateRenderDays()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@@ -249,7 +263,7 @@ export default {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
border-radius: 12rpx;
|
border-radius: 12rpx;
|
||||||
box-shadow: 0 2rpx 16rpx #eee;
|
/* box-shadow: 0 2rpx 16rpx #eee; */
|
||||||
padding: 12rpx;
|
padding: 12rpx;
|
||||||
}
|
}
|
||||||
.calendar-header {
|
.calendar-header {
|
||||||
|
140
components/SelectCalendarDialog.vue
Normal file
140
components/SelectCalendarDialog.vue
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
<template>
|
||||||
|
<view>
|
||||||
|
<view v-if="visible" class="mask" @click="close"></view>
|
||||||
|
<!-- 底部弹窗 -->
|
||||||
|
<view class="popup" v-if="visible">
|
||||||
|
<!-- 弹窗标题 -->
|
||||||
|
<view class="dialog-title">选择时间</view>
|
||||||
|
|
||||||
|
<!-- 日期显示区域 -->
|
||||||
|
<view class="date-display">
|
||||||
|
{{ selectedDate }}
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 日历组件 -->
|
||||||
|
<view class="calendar-wrapper">
|
||||||
|
<CommonCalendar :initial-date="selectedDate" @dateChange="handleDateSelected" />
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 确认按钮 -->
|
||||||
|
<view class="confirm-btn" @click="confirmSelection">
|
||||||
|
确认
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import CommonCalendar from '@/components/CommonCalendar.vue'
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
CommonCalendar
|
||||||
|
},
|
||||||
|
name: "SelectCalendarDialog",
|
||||||
|
props: {
|
||||||
|
visible: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
selectedDate: this.getCurrentDate(), // 默认选中的日期
|
||||||
|
showCalendar: true // 控制日历是否显示
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
close() {
|
||||||
|
this.$emit('update:visible', false);
|
||||||
|
},
|
||||||
|
// 获取当前日期
|
||||||
|
getCurrentDate() {
|
||||||
|
const today = new Date();
|
||||||
|
const year = today.getFullYear();
|
||||||
|
const month = String(today.getMonth() + 1).padStart(2, '0');
|
||||||
|
const day = String(today.getDate()).padStart(2, '0');
|
||||||
|
return `${year}-${month}-${day}`;
|
||||||
|
},
|
||||||
|
|
||||||
|
// 处理日期选择
|
||||||
|
handleDateSelected(date) {
|
||||||
|
this.selectedDate = date;
|
||||||
|
// 不再需要手动关闭日历,因为日历会一直显示在弹窗中
|
||||||
|
},
|
||||||
|
|
||||||
|
// 确认选择
|
||||||
|
confirmSelection() {
|
||||||
|
this.$emit('confirm', this.selectedDate);
|
||||||
|
this.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.mask {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: rgba(0, 0, 0, 0.3);
|
||||||
|
z-index: 998;
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
max-height: 80%;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 24rpx 24rpx 0 0;
|
||||||
|
overflow: hidden;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
z-index: 999;
|
||||||
|
animation: slideUp 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-title {
|
||||||
|
font-size: 36rpx;
|
||||||
|
color: #333;
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
margin-top: 45rpx;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.date-display {
|
||||||
|
width: 100%;
|
||||||
|
height: 73rpx;
|
||||||
|
line-height: 73rpx;
|
||||||
|
text-align: start;
|
||||||
|
background: #EBF5FF;
|
||||||
|
border-radius: 10rpx;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #0B0B0B;
|
||||||
|
margin-bottom: 6rpx;
|
||||||
|
margin-left: 35rpx;
|
||||||
|
margin-right: 35rpx;
|
||||||
|
padding-left: 35rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-wrapper {
|
||||||
|
width: 100%;
|
||||||
|
margin-bottom: 89rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.confirm-btn {
|
||||||
|
height: 88rpx;
|
||||||
|
line-height: 88rpx;
|
||||||
|
text-align: center;
|
||||||
|
background-color: #0090FF;
|
||||||
|
color: white;
|
||||||
|
border-radius: 44rpx;
|
||||||
|
font-size: 36rpx;
|
||||||
|
margin-left: 65rpx;
|
||||||
|
margin-right: 65rpx;
|
||||||
|
margin-bottom: 40rpx;
|
||||||
|
}
|
||||||
|
</style>
|
115
components/punchInfo.vue
Normal file
115
components/punchInfo.vue
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
<template>
|
||||||
|
<!-- 上班 -->
|
||||||
|
<view class="timeline-item">
|
||||||
|
<view class="timeline-dot"></view>
|
||||||
|
<view class="timeline-content">
|
||||||
|
<text class="timeline-label">应上班 09:00</text>
|
||||||
|
<view class="clock-card late">
|
||||||
|
<text class="clock-text">已打卡 08:48:32</text>
|
||||||
|
<text class="status orange">迟到</text>
|
||||||
|
<text class="buka" @click="goBuka">申请补卡</text>
|
||||||
|
<view class="location">
|
||||||
|
<text class="icon">📍</text>
|
||||||
|
<text class="loc-text">某综合服务中心1栋</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default{
|
||||||
|
props:{
|
||||||
|
info:{}
|
||||||
|
},
|
||||||
|
methods:{
|
||||||
|
goBuka(){
|
||||||
|
uni.navigateTo({
|
||||||
|
url: '/pages/sys/user/myRecord/cardReplacement'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.timeline-item {
|
||||||
|
position: relative;
|
||||||
|
padding-left: 20rpx;
|
||||||
|
margin-left: 60rpx;
|
||||||
|
margin-right: 90rpx;
|
||||||
|
margin-bottom: 40rpx;
|
||||||
|
border-left: 2rpx solid #e0e0e0; /* 竖线 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeline-item:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeline-dot {
|
||||||
|
position: absolute;
|
||||||
|
left: -10rpx;
|
||||||
|
top: -10rpx;
|
||||||
|
width: 16rpx;
|
||||||
|
height: 16rpx;
|
||||||
|
background-color: #666;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeline-content {
|
||||||
|
margin-left: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeline-label {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #737373;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 打卡卡片 */
|
||||||
|
.clock-card {
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
padding: 24rpx;
|
||||||
|
margin-top: 23rpx;
|
||||||
|
box-shadow: 0 4rpx 12rpx rgba(0,0,0,0.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
.clock-text {
|
||||||
|
font-size: 34rpx;
|
||||||
|
color: #000000;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.status {
|
||||||
|
margin-left: 20rpx;
|
||||||
|
font-size: 28rpx;
|
||||||
|
}
|
||||||
|
.status.orange {
|
||||||
|
color: #ff6b35;
|
||||||
|
}
|
||||||
|
|
||||||
|
.buka {
|
||||||
|
margin-left: 20rpx;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #3370FF;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 地点 */
|
||||||
|
.location {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-top: 12rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
margin-right: 6rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loc-text {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #1C9BFF;
|
||||||
|
}
|
||||||
|
</style>
|
@@ -388,6 +388,12 @@
|
|||||||
"navigationBarTitleText": "我的考勤"
|
"navigationBarTitleText": "我的考勤"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/sys/user/myRecord/cardReplacement",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "补卡申请"
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "pages/sys/workbench/oa/oa",
|
"path": "pages/sys/workbench/oa/oa",
|
||||||
"style": {
|
"style": {
|
||||||
|
420
pages/sys/user/myRecord/cardReplacement.vue
Normal file
420
pages/sys/user/myRecord/cardReplacement.vue
Normal file
@@ -0,0 +1,420 @@
|
|||||||
|
<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>
|
@@ -1,18 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="my-record-container">
|
<view class="my-record-container">
|
||||||
|
<text class="month-title">{{ selectedDate.substring(0,4) }}年{{ selectedDate.substring(5,7) }}月</text>
|
||||||
<!-- 月份标题和切换 -->
|
|
||||||
<view class="month-header">
|
|
||||||
<view class="month-nav">
|
|
||||||
<view class="month-arrow" @click="prevMonth">
|
|
||||||
<image class="arrow-icon" src="/static/ic_arrow_gray.webp" mode="aspectFit" style="transform: rotate(180deg)" />
|
|
||||||
</view>
|
|
||||||
<text class="month-title">{{ currentYear }}年{{ currentMonth }}月</text>
|
|
||||||
<view class="month-arrow" @click="nextMonth">
|
|
||||||
<image class="arrow-icon" src="/static/ic_arrow_gray.webp" mode="aspectFit" />
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<!-- 考勤统计 -->
|
<!-- 考勤统计 -->
|
||||||
<view class="attendance-stats">
|
<view class="attendance-stats">
|
||||||
@@ -36,35 +24,11 @@
|
|||||||
|
|
||||||
<!-- 日历 -->
|
<!-- 日历 -->
|
||||||
<view class="calendar">
|
<view class="calendar">
|
||||||
<view class="weekdays">
|
|
||||||
<text v-for="day in weekdays" :key="day" class="weekday">{{ day }}</text>
|
|
||||||
</view>
|
|
||||||
<view class="dates" v-if="calendarExpanded">
|
|
||||||
<view
|
|
||||||
v-for="(date, index) in allDates"
|
|
||||||
:key="index"
|
|
||||||
:class="getDateClass(date)"
|
|
||||||
@click="selectDate(date)"
|
|
||||||
>
|
|
||||||
<text v-if="date.value" class="date-text">{{ date.value }}</text>
|
|
||||||
<view v-if="date.hasRecord" class="record-dot"></view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="dates" v-else>
|
|
||||||
<view
|
|
||||||
v-for="(date, index) in currentWeekDates"
|
|
||||||
:key="index"
|
|
||||||
:class="getDateClass(date)"
|
|
||||||
@click="selectDate(date)"
|
|
||||||
>
|
|
||||||
<text v-if="date.value" class="date-text">{{ date.value }}</text>
|
|
||||||
<view v-if="date.hasRecord" class="record-dot"></view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
|
<CommonCalendar ref="calendarComponent" :initial-date="selectedDate" :allowWeekSwitch='true' :initialMode='mode' @dateChange="handleDateSelected" @modeChange="handleModeChange" />
|
||||||
<!-- 展开/收缩按钮 -->
|
<!-- 展开/收缩按钮 -->
|
||||||
<view class="calendar-toggle" @click="toggleCalendar">
|
<view class="calendar-toggle" @click="toggleCalendarMode">
|
||||||
<image v-if="calendarExpanded" class='image_zk' src="/static/ic_exp.png"></image>
|
<image v-if="mode == 'month'" class='image_zk' src="/static/ic_exp.png"></image>
|
||||||
<image v-else class='image_sq' src="/static/ic_sq.png"></image>
|
<image v-else class='image_sq' src="/static/ic_sq.png"></image>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@@ -72,146 +36,54 @@
|
|||||||
<!-- 固定班次 -->
|
<!-- 固定班次 -->
|
||||||
<view class="fixed-shifts">
|
<view class="fixed-shifts">
|
||||||
<text class="shifts-title">固定班次</text>
|
<text class="shifts-title">固定班次</text>
|
||||||
|
<PunchInfo/>
|
||||||
<view class="shift-item">
|
<PunchInfo/>
|
||||||
<view class="shift-time">
|
|
||||||
<view class="time-dot"></view>
|
|
||||||
<text class="time-text">应上班 09:00</text>
|
|
||||||
</view>
|
|
||||||
<view class="record leave-record">
|
|
||||||
<text class="record-text">已请假 09:00—12:00</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<view class="shift-item">
|
|
||||||
<view class="shift-time">
|
|
||||||
<view class="time-dot"></view>
|
|
||||||
<text class="time-text">应下班 18:00</text>
|
|
||||||
</view>
|
|
||||||
<view class="record clock-record">
|
|
||||||
<text class="record-text">已打卡 18:02:18</text>
|
|
||||||
<text class="location">@某综合服务中心1栋</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import CommonCalendar from '@/components/CommonCalendar.vue'
|
||||||
|
import PunchInfo from '@/components/punchInfo.vue'
|
||||||
export default {
|
export default {
|
||||||
|
components: {
|
||||||
|
CommonCalendar,
|
||||||
|
PunchInfo
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
weekdays: ['日', '一', '二', '三', '四', '五', '六'],
|
selectedDate: this.getCurrentDate(), // 默认选中的日期
|
||||||
calendarExpanded: true,
|
mode: 'month'
|
||||||
selectedDate: 8,
|
|
||||||
currentYear: 2025,
|
|
||||||
currentMonth: 7,
|
|
||||||
allDates: [],
|
|
||||||
prevMonthDates: [],
|
|
||||||
nextMonthDates: [],
|
|
||||||
swiperCurrent: 1,
|
|
||||||
touchStartX: 0,
|
|
||||||
touchStartY: 0
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
created() {
|
|
||||||
this.generateCalendarDates();
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
currentWeekDates() {
|
|
||||||
const selectedIndex = this.allDates.findIndex(date => date.selected);
|
|
||||||
if (selectedIndex === -1) return this.allDates.slice(0, 7);
|
|
||||||
const startOfWeek = Math.floor(selectedIndex / 7) * 7;
|
|
||||||
return this.allDates.slice(startOfWeek, startOfWeek + 7);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
methods: {
|
||||||
toggleCalendar() {
|
// 获取当前日期
|
||||||
this.calendarExpanded = !this.calendarExpanded;
|
getCurrentDate() {
|
||||||
|
const today = new Date();
|
||||||
|
const year = today.getFullYear();
|
||||||
|
const month = String(today.getMonth() + 1).padStart(2, '0');
|
||||||
|
const day = String(today.getDate()).padStart(2, '0');
|
||||||
|
return `${year}-${month}-${day}`;
|
||||||
},
|
},
|
||||||
selectDate(date) {
|
|
||||||
if (!date.value) return;
|
|
||||||
this.allDates.forEach(d => d.selected = false);
|
|
||||||
date.selected = true;
|
|
||||||
this.selectedDate = date.value;
|
|
||||||
},
|
|
||||||
getDateClass(date) {
|
|
||||||
return {
|
|
||||||
'date-item': true,
|
|
||||||
'selected': date.selected,
|
|
||||||
'has-record': date.hasRecord,
|
|
||||||
'empty': !date.value
|
|
||||||
};
|
|
||||||
},
|
|
||||||
prevMonth() {
|
|
||||||
if (this.currentMonth === 1) {
|
|
||||||
this.currentYear--;
|
|
||||||
this.currentMonth = 12;
|
|
||||||
} else {
|
|
||||||
this.currentMonth--;
|
|
||||||
}
|
|
||||||
this.generateCalendarDates();
|
|
||||||
},
|
|
||||||
nextMonth() {
|
|
||||||
if (this.currentMonth === 12) {
|
|
||||||
this.currentYear++;
|
|
||||||
this.currentMonth = 1;
|
|
||||||
} else {
|
|
||||||
this.currentMonth++;
|
|
||||||
}
|
|
||||||
this.generateCalendarDates();
|
|
||||||
},
|
|
||||||
generateCalendarDates() {
|
|
||||||
this.allDates = this.buildMonthDates(this.currentYear, this.currentMonth);
|
|
||||||
|
|
||||||
let prevY = this.currentYear, prevM = this.currentMonth - 1;
|
// 处理日期选择
|
||||||
if (prevM === 0) { prevM = 12; prevY--; }
|
handleDateSelected(date) {
|
||||||
this.prevMonthDates = this.buildMonthDates(prevY, prevM);
|
this.selectedDate = date;
|
||||||
|
},
|
||||||
|
|
||||||
let nextY = this.currentYear, nextM = this.currentMonth + 1;
|
// 处理日历模式变化
|
||||||
if (nextM === 13) { nextM = 1; nextY++; }
|
handleModeChange(mode) {
|
||||||
this.nextMonthDates = this.buildMonthDates(nextY, nextM);
|
this.mode = mode;
|
||||||
},
|
},
|
||||||
buildMonthDates(year, month) {
|
|
||||||
const firstDay = new Date(year, month - 1, 1).getDay();
|
|
||||||
const daysInMonth = new Date(year, month, 0).getDate();
|
|
||||||
let dates = [];
|
|
||||||
for (let i = 0; i < firstDay; i++) dates.push({ value: null });
|
|
||||||
for (let i = 1; i <= daysInMonth; i++) {
|
|
||||||
dates.push({ value: i, hasRecord: i <= 20, selected: i === this.selectedDate });
|
|
||||||
}
|
|
||||||
const remaining = 7 - (dates.length % 7);
|
|
||||||
if (remaining < 7) for (let i = 0; i < remaining; i++) dates.push({ value: null });
|
|
||||||
return dates;
|
|
||||||
},
|
|
||||||
isInCurrentWeek(date) {
|
|
||||||
if (!date.value) return false;
|
|
||||||
const index = this.allDates.findIndex(d => d.value === this.selectedDate);
|
|
||||||
if (index === -1) return false;
|
|
||||||
const start = Math.floor(index / 7) * 7;
|
|
||||||
const week = this.allDates.slice(start, start + 7);
|
|
||||||
return week.includes(date);
|
|
||||||
},
|
|
||||||
onTouchStart(e) {
|
|
||||||
this.touchStartX = e.changedTouches[0].clientX;
|
|
||||||
this.touchStartY = e.changedTouches[0].clientY;
|
|
||||||
},
|
|
||||||
onTouchEnd(e) {
|
|
||||||
const endX = e.changedTouches[0].clientX;
|
|
||||||
const endY = e.changedTouches[0].clientY;
|
|
||||||
const deltaX = endX - this.touchStartX;
|
|
||||||
const deltaY = endY - this.touchStartY;
|
|
||||||
|
|
||||||
// 上下滑切换月/周视图
|
// 切换日历模式
|
||||||
if (Math.abs(deltaY) > Math.abs(deltaX)) {
|
toggleCalendarMode() {
|
||||||
if (deltaY < -50 && this.calendarExpanded) this.calendarExpanded = false;
|
// 调用日历组件的toggleMode方法
|
||||||
else if (deltaY > 50 && !this.calendarExpanded) this.calendarExpanded = true;
|
if (this.$refs.calendarComponent) {
|
||||||
|
this.$refs.calendarComponent.toggleMode();
|
||||||
}
|
}
|
||||||
},
|
|
||||||
onSwiperChange(e) {
|
|
||||||
const current = e.detail.current;
|
|
||||||
if (current === 0) { this.prevMonth(); this.swiperCurrent = 1; }
|
|
||||||
else if (current === 2) { this.nextMonth(); this.swiperCurrent = 1; }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -219,65 +91,16 @@ export default {
|
|||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.my-record-container {
|
.my-record-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 顶部导航栏 */
|
|
||||||
.header {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
padding: 20rpx 30rpx;
|
|
||||||
background-color: #fff;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.back-btn {
|
|
||||||
width: 40rpx;
|
|
||||||
height: 40rpx;
|
|
||||||
margin-right: 20rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-title {
|
|
||||||
font-size: 36rpx;
|
|
||||||
font-weight: bold;
|
|
||||||
color: #333;
|
|
||||||
position: absolute;
|
|
||||||
left: 50%;
|
|
||||||
transform: translateX(-50%);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 月份标题和导航 */
|
|
||||||
.month-header {
|
|
||||||
padding: 20rpx 30rpx;
|
|
||||||
margin-left: 180rpx;
|
|
||||||
margin-right: 180rpx;
|
|
||||||
background-color: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.month-nav {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
}
|
|
||||||
|
|
||||||
.month-arrow {
|
|
||||||
width: 40rpx;
|
|
||||||
height: 40rpx;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.arrow-icon {
|
|
||||||
width: 32rpx;
|
|
||||||
height: 32rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.month-title {
|
.month-title {
|
||||||
font-size: 32rpx;
|
font-size: 28rpx;
|
||||||
font-weight: bold;
|
font-weight: 600;
|
||||||
|
margin-left: 35rpx;
|
||||||
color: #333;
|
color: #333;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -286,7 +109,7 @@ export default {
|
|||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-around;
|
justify-content: space-around;
|
||||||
padding: 40rpx 30rpx;
|
padding: 40rpx 30rpx;
|
||||||
margin: 20rpx 30rpx;
|
margin: 28rpx 30rpx 15rpx 30rpx;
|
||||||
background-color: #f7f7f7;
|
background-color: #f7f7f7;
|
||||||
border-radius: 10rpx;
|
border-radius: 10rpx;
|
||||||
|
|
||||||
@@ -315,90 +138,28 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* 日历样式 */
|
/* 日历样式 */
|
||||||
.calendar { overflow: hidden; margin-left: 20rpx; margin-right: 20rpx}
|
.calendar { overflow: hidden; margin-left: 10rpx; margin-right: 10rpx}
|
||||||
.weekdays { display: flex; padding: 20rpx 0; }
|
|
||||||
.weekday { flex: 1; text-align: center; font-size: 28rpx; color: #666; }
|
|
||||||
.dates { display: flex; flex-wrap: wrap; padding: 20rpx 0; }
|
|
||||||
.date-item { width: 14.28%; height: 70rpx; display: flex; align-items: center; justify-content: center; position: relative; margin-bottom: 20rpx; }
|
|
||||||
.date-item.empty { color: #ccc; }
|
|
||||||
.date-item.selected { background-color: #007aff; border-radius: 50%; width: 60rpx; height: 60rpx; margin: 10rpx auto; }
|
|
||||||
.date-item.selected .date-text { color: #fff; }
|
|
||||||
.date-text { font-size: 28rpx; color: #333; }
|
|
||||||
.record-dot { position: absolute; bottom: 8rpx; left: 50%; transform: translateX(-50%); width: 8rpx; height: 8rpx; background-color: #007aff; border-radius: 50%; }
|
|
||||||
.date-item.selected .record-dot { background-color: #fff; }
|
|
||||||
|
|
||||||
.calendar-toggle { text-align: center; background-color: #fff; margin-top: -30rpx;}
|
.calendar-toggle { text-align: center; background-color: #fff;}
|
||||||
.image_sq { width: 37rpx; height: 6rpx; }
|
.image_sq { width: 37rpx; height: 6rpx; }
|
||||||
.image_zk { width: 52rpx; height: 19rpx; }
|
.image_zk { width: 52rpx; height: 19rpx; }
|
||||||
|
|
||||||
/* 固定班次 */
|
/* 固定班次 */
|
||||||
.fixed-shifts {
|
.fixed-shifts {
|
||||||
margin: 20rpx 30rpx;
|
flex: 1;
|
||||||
background-color: #f5f5f5;
|
background-color: #f5f5f5;
|
||||||
border-radius: 16rpx;
|
|
||||||
padding: 30rpx;
|
padding: 30rpx;
|
||||||
|
overflow: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.shifts-title {
|
.shifts-title {
|
||||||
font-size: 32rpx;
|
font-size: 28rpx;
|
||||||
font-weight: bold;
|
color: #737373;
|
||||||
color: #333;
|
|
||||||
margin-bottom: 30rpx;
|
margin-bottom: 30rpx;
|
||||||
}
|
margin-top: 7rpx;
|
||||||
|
|
||||||
.shift-item {
|
|
||||||
margin-bottom: 40rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.shift-item:last-child {
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.shift-time {
|
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
justify-content: center;
|
||||||
margin-bottom: 20rpx;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.time-dot {
|
|
||||||
width: 12rpx;
|
|
||||||
height: 12rpx;
|
|
||||||
background-color: #ff6b35;
|
|
||||||
border-radius: 50%;
|
|
||||||
margin-right: 16rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.time-text {
|
|
||||||
font-size: 28rpx;
|
|
||||||
color: #333;
|
|
||||||
}
|
|
||||||
|
|
||||||
.record {
|
|
||||||
border: 2rpx dashed #e0e0e0;
|
|
||||||
border-radius: 12rpx;
|
|
||||||
padding: 24rpx;
|
|
||||||
margin-left: 28rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.leave-record {
|
|
||||||
background-color: #fff7f0;
|
|
||||||
border-color: #ffb366;
|
|
||||||
}
|
|
||||||
|
|
||||||
.clock-record {
|
|
||||||
background-color: #f0f9ff;
|
|
||||||
border-color: #66b3ff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.record-text {
|
|
||||||
font-size: 28rpx;
|
|
||||||
color: #333;
|
|
||||||
margin-bottom: 8rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.location {
|
|
||||||
font-size: 24rpx;
|
|
||||||
color: #007aff;
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
@@ -34,7 +34,7 @@
|
|||||||
<image class="ins-line-image" src="/static/ic_my_repair_03.png" />
|
<image class="ins-line-image" src="/static/ic_my_repair_03.png" />
|
||||||
<view class="ins-info">巡检人:{{ item.actUserName || '' }}</view>
|
<view class="ins-info">巡检人:{{ item.actUserName || '' }}</view>
|
||||||
<view class="ins-info">计划完成时间:{{ item.planInsTime || '' }}</view>
|
<view class="ins-info">计划完成时间:{{ item.planInsTime || '' }}</view>
|
||||||
<view class="ins-info">实际完成时间:{{ item.location || '' }}</view>
|
<view class="ins-info">实际完成时间:{{ item.compleTime || '' }}</view>
|
||||||
<view class="ins-info">巡检进度:{{ item.inspectionProgress || '' }}</view>
|
<view class="ins-info">巡检进度:{{ item.inspectionProgress || '' }}</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
|
@@ -60,7 +60,7 @@
|
|||||||
<view class="btn-outline" @click="startTask(item)">立即巡检</view>
|
<view class="btn-outline" @click="startTask(item)">立即巡检</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view class="status" v-else v-if="item.inspectionResults == 1" @click="goDetail(item)">
|
<view class="status" v-else-if="item.inspectionResults == 1" @click="goDetail(item)">
|
||||||
<view>完成巡检</view>
|
<view>完成巡检</view>
|
||||||
<view class="badge" :class="item.inspectionResults == 1 ? 'badge-success' : 'badge-warn'">
|
<view class="badge" :class="item.inspectionResults == 1 ? 'badge-success' : 'badge-warn'">
|
||||||
{{ item.inspectionResults == 1 ? '正常' : '异常' }}
|
{{ item.inspectionResults == 1 ? '正常' : '异常' }}
|
||||||
|
@@ -31,12 +31,12 @@
|
|||||||
<!-- 开始时间 -->
|
<!-- 开始时间 -->
|
||||||
<view class="form-row">
|
<view class="form-row">
|
||||||
<text class="label required">开始时间</text>
|
<text class="label required">开始时间</text>
|
||||||
<picker mode="date" @change="startDateChange">
|
<!-- <picker mode="date" @change="startDateChange"> -->
|
||||||
<view class="picker">
|
<view class="picker" @click="startDateSelect">
|
||||||
<text :class="!startDate ? 'placeholder' : ''">{{ startDate || '请选择' }}</text>
|
<text :class="!startDate ? 'placeholder' : ''">{{ startDate || '请选择' }}</text>
|
||||||
<image class="right-arrow" src="/static/ic_right_arrow_g.png" />
|
<image class="right-arrow" src="/static/ic_right_arrow_g.png" />
|
||||||
</view>
|
</view>
|
||||||
</picker>
|
<!-- </picker> -->
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 结束时间 -->
|
<!-- 结束时间 -->
|
||||||
@@ -63,8 +63,8 @@
|
|||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 上传图片 -->
|
<!-- 上传图片 -->
|
||||||
<u-upload class="upload-style" :fileList="selectedImages" @on-list-change="onListChange" @delete="deletePic" name="upload"
|
<u-upload class="upload-style" :fileList="selectedImages" @on-list-change="onListChange" @delete="deletePic"
|
||||||
multiple maxCount="3" width="180" height="180" :autoUpload="false"></u-upload>
|
name="upload" multiple maxCount="3" width="180" height="180" :autoUpload="false"></u-upload>
|
||||||
|
|
||||||
<!-- 提交按钮 -->
|
<!-- 提交按钮 -->
|
||||||
<button class="submit-btn" @click="submitLeave">提交</button>
|
<button class="submit-btn" @click="submitLeave">提交</button>
|
||||||
@@ -113,13 +113,8 @@
|
|||||||
<view class="popup-content">
|
<view class="popup-content">
|
||||||
<view class="popup-title">请假类型</view>
|
<view class="popup-title">请假类型</view>
|
||||||
<view class="popup-options">
|
<view class="popup-options">
|
||||||
<view
|
<view v-for="(type, index) in leaveTypes" :key="index" class="popup-option"
|
||||||
v-for="(type, index) in leaveTypes"
|
:class="{ selected: leaveTypeIndex === index }" @click="selectLeaveType(index)">
|
||||||
:key="index"
|
|
||||||
class="popup-option"
|
|
||||||
:class="{ 'selected': leaveTypeIndex === index }"
|
|
||||||
@click="selectLeaveType(index)"
|
|
||||||
>
|
|
||||||
{{ type }}
|
{{ type }}
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@@ -127,11 +122,14 @@
|
|||||||
</view>
|
</view>
|
||||||
</u-popup>
|
</u-popup>
|
||||||
|
|
||||||
|
<SelectCalendarDialog :visible.sync="showCalendarDialog" @confirm="onConfirm" />
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import SelectCalendarDialog from '@/components/SelectCalendarDialog.vue'
|
||||||
export default {
|
export default {
|
||||||
|
components: { SelectCalendarDialog },
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
tabs: ['发起申请', '请假记录', '已完成'],
|
tabs: ['发起申请', '请假记录', '已完成'],
|
||||||
@@ -150,6 +148,7 @@ export default {
|
|||||||
pageNum: 1,
|
pageNum: 1,
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
showLeaveTypePopup: false,
|
showLeaveTypePopup: false,
|
||||||
|
showCalendarDialog: false,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@@ -159,8 +158,11 @@ export default {
|
|||||||
bindPickerChange(e) {
|
bindPickerChange(e) {
|
||||||
this.leaveTypeIndex = e.detail.value;
|
this.leaveTypeIndex = e.detail.value;
|
||||||
},
|
},
|
||||||
startDateChange(e) {
|
startDateSelect() {
|
||||||
this.startDate = e.detail.value;
|
this.showCalendarDialog = true
|
||||||
|
},
|
||||||
|
onConfirm(selectedDate){
|
||||||
|
this.startDate = selectedDate
|
||||||
},
|
},
|
||||||
endDateChange(e) {
|
endDateChange(e) {
|
||||||
this.endDate = e.detail.value;
|
this.endDate = e.detail.value;
|
||||||
@@ -190,8 +192,7 @@ export default {
|
|||||||
},
|
},
|
||||||
async loadLeaveRecords() {
|
async loadLeaveRecords() {
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
let data = [
|
let data = [{
|
||||||
{
|
|
||||||
type: '请假',
|
type: '请假',
|
||||||
leaveType: '病假',
|
leaveType: '病假',
|
||||||
status: '已通过',
|
status: '已通过',
|
||||||
@@ -513,6 +514,7 @@ export default {
|
|||||||
font-size: 28rpx;
|
font-size: 28rpx;
|
||||||
color: #999;
|
color: #999;
|
||||||
}
|
}
|
||||||
|
|
||||||
.upload-style {
|
.upload-style {
|
||||||
margin-left: 15rpx;
|
margin-left: 15rpx;
|
||||||
margin-right: 15rpx;
|
margin-right: 15rpx;
|
||||||
@@ -548,22 +550,21 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.popup-options {
|
.popup-options {
|
||||||
display: flex;
|
display: grid;
|
||||||
flex-wrap: wrap;
|
grid-template-columns: repeat(3, 1fr);
|
||||||
justify-content: space-between;
|
/* 三列,可改成2/4列 */
|
||||||
|
gap: 20rpx;
|
||||||
|
/* 行列间距 */
|
||||||
|
padding: 20rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
.popup-option {
|
.popup-option {
|
||||||
width: 30%;
|
text-align: center;
|
||||||
height: 80rpx;
|
padding: 20rpx 0;
|
||||||
background-color: #f7f7f7;
|
|
||||||
border-radius: 12rpx;
|
border-radius: 12rpx;
|
||||||
display: flex;
|
background-color: #f5f5f5;
|
||||||
align-items: center;
|
font-size: 28rpx;
|
||||||
justify-content: center;
|
|
||||||
font-size: 32rpx;
|
|
||||||
color: #333;
|
color: #333;
|
||||||
margin-bottom: 20rpx;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.popup-option.selected {
|
.popup-option.selected {
|
||||||
|
@@ -74,11 +74,11 @@
|
|||||||
text: '报事报修',
|
text: '报事报修',
|
||||||
url:'/pages/sys/user/myRepair/myRepair'
|
url:'/pages/sys/user/myRepair/myRepair'
|
||||||
},
|
},
|
||||||
// {
|
{
|
||||||
// icon: 'https://picsum.photos/80/80?random=3',
|
icon: 'https://picsum.photos/80/80?random=3',
|
||||||
// text: '工作巡检',
|
text: '工作巡检',
|
||||||
// url:'/pages/sys/workbench/inspection/inspection'
|
url:'/pages/sys/workbench/inspection/inspection'
|
||||||
// },
|
},
|
||||||
// {
|
// {
|
||||||
// icon: 'https://picsum.photos/80/80?random=3',
|
// icon: 'https://picsum.photos/80/80?random=3',
|
||||||
// text: '通讯录',
|
// text: '通讯录',
|
||||||
|
@@ -16,7 +16,7 @@ try{
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 需要永久存储,且下次APP启动需要取出的,在state中的变量名
|
// 需要永久存储,且下次APP启动需要取出的,在state中的变量名
|
||||||
let saveStateKeys = ['vuex_user', 'vuex_token', 'vuex_remember', 'vuex_locale','vuex_isAgent'];
|
let saveStateKeys = ['vuex_user', 'vuex_token', 'vuex_remember', 'vuex_locale','vuex_isAgent','vuex_push_clientId'];
|
||||||
|
|
||||||
// 保存变量到本地存储中
|
// 保存变量到本地存储中
|
||||||
const saveLifeData = function(key, value){
|
const saveLifeData = function(key, value){
|
||||||
@@ -41,6 +41,7 @@ const store = new Vuex.Store({
|
|||||||
vuex_remember: lifeData.vuex_remember ? lifeData.vuex_remember : '',
|
vuex_remember: lifeData.vuex_remember ? lifeData.vuex_remember : '',
|
||||||
vuex_locale: lifeData.vuex_locale ? lifeData.vuex_locale : '',
|
vuex_locale: lifeData.vuex_locale ? lifeData.vuex_locale : '',
|
||||||
vuex_isAgent: lifeData.vuex_isAgent ? lifeData.vuex_isAgent : '',
|
vuex_isAgent: lifeData.vuex_isAgent ? lifeData.vuex_isAgent : '',
|
||||||
|
vuex_push_clientId: lifeData.vuex_push_clientId ? lifeData.vuex_push_clientId : '',
|
||||||
|
|
||||||
// 如果vuex_version无需保存到本地永久存储,无需lifeData.vuex_version方式
|
// 如果vuex_version无需保存到本地永久存储,无需lifeData.vuex_version方式
|
||||||
vuex_config: config,
|
vuex_config: config,
|
||||||
|
Reference in New Issue
Block a user