This commit is contained in:
wangweidong 2026-01-09 17:21:46 +08:00
commit 87bf3497b9
5 changed files with 418 additions and 76 deletions

View File

@ -3,13 +3,13 @@
<view class="header">
<view class="header-title">
<view class="head-left">
<image class="head-img" src="/static/index/calendar/superleft.png" @click="prevYear" />
<image class="head-img" src="/static/index/calendar/superleft.png" @click="prevYear" />
<image class="head-img" src="/static/index/calendar/left.png" @click="prevMonth" />
</view>
<view class="year-month">{{ year }}{{ month + 1 }}</view>
<view class="head-left">
<image class="head-img" src="/static/index/calendar/right.png" @click="nextMonth" />
<image class="head-img" src="/static/index/calendar/superright.png" @click="nextYear" />
<image class="head-img" src="/static/index/calendar/superright.png" @click="nextYear" />
</view>
</view>
@ -337,11 +337,13 @@
font-size: 10px;
color: #888;
}
.head-left{
.head-left {
width: 100rpx;
display: flex;
justify-content: space-between;
.head-img{
.head-img {
width: 40rpx;
height: 40rpx;
}

View File

@ -0,0 +1,299 @@
<template>
<view class="calendar">
<view class="header">
<view class="header-title">
<view class="head-left">
<image class="head-img" src="/static/index/calendar/superleft.png" @click="prevYear" />
<image class="head-img" src="/static/index/calendar/left.png" @click="prevMonth" />
</view>
<view class="year-month">{{ year }}{{ month + 1 }}</view>
<view class="head-left">
<image class="head-img" src="/static/index/calendar/right.png" @click="nextMonth" />
<image class="head-img" src="/static/index/calendar/superright.png" @click="nextYear" />
</view>
</view>
<view class="weekdays">
<view v-for="(day, idx) in weekdays" :key="idx" class="weekday">{{ day }}</view>
</view>
</view>
<view class="days">
<view v-for="cell in cells" :key="cell.key" class="day-cell" :class="{
'prev-month': cell.prev,
'next-month': cell.next,
'selected': isSelected(cell.key)
}" @click="selectDate(cell)">
<view class="gregorian">{{ cell.dateText }}</view>
<view class="lunar" v-if="cell.lunarText">{{ cell.lunarText }}</view>
</view>
</view>
</view>
</template>
<script setup>
import {
ref,
computed
} from 'vue';
import solarlunar from 'solarlunar'; // npm install solarlunar
//
const now = new Date();
const year = ref(now.getFullYear());
const month = ref(now.getMonth()); // 0-based
// key (: YYYY-MM-DD)
const selectedKey = ref(null);
// 便 YYYYMMDD
function toDateNumber(y, m, d) {
// m 0-base
const mm = m + 1;
return y * 10000 + mm * 100 + d;
}
// keym 0-base =>
function formatKey(y, m, d) {
const mm = String(m + 1).padStart(2, '0');
const dd = String(d).padStart(2, '0');
return `${y}-${mm}-${dd}`;
}
// ..
const weekdays = ['一', '二', '三', '四', '五', '六', '日'];
// Monday = 0
const firstWeekdayOfMonth = (y, m) => {
const d = new Date(y, m, 1).getDay(); // 0 (Sun) - 6 (Sat)
return (d + 6) % 7; // Monday=0 .. Sunday=6
};
// 6*7 (42) cells
function buildCells(y, m) {
const list = [];
//
const prevDate = new Date(y, m, 0); //
const prevYear = prevDate.getFullYear();
const prevMonth = prevDate.getMonth();
const prevTotal = prevDate.getDate();
const startOffset = firstWeekdayOfMonth(y, m);
//
for (let i = 0; i < startOffset; i++) {
const day = prevTotal - startOffset + i + 1;
const lunar = solarlunar.solar2lunar(prevYear, prevMonth + 1, day);
const dateNumber = toDateNumber(prevYear, prevMonth, day);
list.push({
key: `prev-${prevYear}-${prevMonth + 1}-${day}`,
dateText: day,
lunarText: lunar ? lunar.dayCn : '',
prev: true,
next: false,
year: prevYear,
month: prevMonth,
day,
dateNumber,
});
}
//
const totalDays = new Date(y, m + 1, 0).getDate();
for (let d = 1; d <= totalDays; d++) {
const lunar = solarlunar.solar2lunar(y, m + 1, d);
const dateNumber = toDateNumber(y, m, d);
list.push({
key: formatKey(y, m, d),
dateText: d,
lunarText: lunar ? lunar.dayCn : '',
prev: false,
next: false,
year: y,
month: m,
day: d,
dateNumber,
});
}
// 42
const need = 42 - list.length;
for (let i = 1; i <= need; i++) {
const nd = new Date(y, m + 1, i);
const ny = nd.getFullYear();
const nm = nd.getMonth();
const lunar = solarlunar.solar2lunar(ny, nm + 1, i);
const dateNumber = toDateNumber(ny, nm, i);
list.push({
key: `next-${ny}-${nm + 1}-${i}`,
dateText: i,
lunarText: lunar ? lunar.dayCn : '',
prev: false,
next: true,
year: ny,
month: nm,
day: i,
dateNumber,
});
}
return list;
}
// cells
const cells = computed(() => buildCells(year.value, month.value));
const emit = defineEmits(["datachange"]); //
//
function isSelected(key) {
return selectedKey.value === key;
}
//
function selectDate(cell) {
// /
if (cell.prev || cell.next) return;
const key = formatKey(cell.year, cell.month, cell.day);
// ->
if (selectedKey.value === key) {
selectedKey.value = null;
emit("datachange", {
date: null
});
return;
}
//
selectedKey.value = key;
emit("datachange", {
date: key
});
}
// /
function prevMonth() {
if (month.value === 0) {
year.value--;
month.value = 11;
} else {
month.value--;
}
}
function nextMonth() {
if (month.value === 11) {
year.value++;
month.value = 0;
} else {
month.value++;
}
}
function prevYear() {
year.value--;
}
function nextYear() {
year.value++;
}
</script>
<style scoped lang="less">
.calendar {
padding: 16px;
background: #fff;
border-radius: 30rpx;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
margin: 0 auto;
overflow: hidden;
}
.header {
width: 100%;
display: flex;
flex-direction: column;
}
.header-title {
width: 100%;
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 10rpx;
}
.year-month {
font-size: 18px;
font-weight: bold;
}
.weekdays {
display: flex;
background-color: #F8F8FA;
border-radius: 18rpx;
padding: 8rpx;
margin-top: 8rpx;
}
.weekday {
flex: 1;
text-align: center;
font-size: 12px;
}
.days {
display: flex;
flex-wrap: wrap;
padding: 8rpx 0;
}
.day-cell {
width: calc(100% / 7);
height: 78rpx;
text-align: center;
padding-top: 8rpx;
box-sizing: border-box;
position: relative;
}
/* 前后月份灰色显示 */
.day-cell.prev-month .gregorian,
.day-cell.next-month .gregorian {
color: #ccc;
}
/* 选中(单选)样式 */
.day-cell.selected {
background-color: #0B98DC;
border-radius: 8rpx;
}
.day-cell.selected .gregorian,
.day-cell.selected .lunar {
color: #fff;
}
.gregorian {
font-size: 14px;
}
.lunar {
font-size: 10px;
color: #888;
}
.head-left {
width: 100rpx;
display: flex;
justify-content: space-between;
.head-img {
width: 40rpx;
height: 40rpx;
}
}
</style>

View File

@ -61,7 +61,8 @@
white-space: nowrap;
color: black;
}
.title-time-font-tags{
.title-time-font-tags {
font-size: 24rpx;
font-weight: 600;
/* margin-bottom: 5rpx; */
@ -70,6 +71,7 @@
white-space: nowrap;
color: #999;
}
.title-time-items {
display: flex;
justify-content: space-around;
@ -148,29 +150,16 @@
.title-time-blue {
/* 你的定位与尺寸保持不变 */
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 90%;
height: 88%;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 10;
--color: #99C9FD;
--thick: 2px;
--radius: 16px;
border: var(--thick) dashed var(--color);
border-radius: var(--radius);
background:
/* 上边 */
repeating-linear-gradient(90deg, var(--color) 0 var(--dash), transparent 0 calc(var(--dash) + var(--gap))) top left / 100% var(--thick) no-repeat,
/* 下边 */
repeating-linear-gradient(90deg, var(--color) 0 var(--dash), transparent 0 calc(var(--dash) + var(--gap))) bottom left / 100% var(--thick) no-repeat,
/* 左边 */
repeating-linear-gradient(0deg, var(--color) 0 var(--dash), transparent 0 calc(var(--dash) + var(--gap))) top left / var(--thick) 100% no-repeat,
/* 右边 */
repeating-linear-gradient(0deg, var(--color) 0 var(--dash), transparent 0 calc(var(--dash) + var(--gap))) top right / var(--thick) 100% no-repeat;
.blue-img {
width: 100%;
height: 100%;
}
}
@ -221,20 +210,22 @@
height: 100%;
padding: 20rpx;
.card-time{
.card-time {
position: absolute;
bottom: 20rpx;
left: 20rpx;
font-size: 27rpx;
}
.card-time-red{
.card-time-red {
position: absolute;
bottom: 20rpx;
left: 20rpx;
font-size: 27rpx;
color: #E33B3B;
}
.card-time-blue{
.card-time-blue {
position: absolute;
bottom: 20rpx;
left: 20rpx;
@ -309,44 +300,58 @@
}
.title-time-border-yellow {
margin: 10rpx;
border: 2rpx solid #e5e6e6;
width: calc(100% - 40rpx);
height: calc(100% - 40rpx);
width: calc(100% - 20rpx);
height: calc(100% - 20rpx);
border-radius: 20rpx;
display: flex;
align-items: center;
background-color: #F7F8F9;
background-color: #fdfeff;
flex-direction: column;
}
.title-time-border-hisOk{
margin: 10rpx;
/* .title-time-border-target{
border: 2rpx solid #46B2F6;
width: calc(100% - 20rpx);
height: calc(100% - 20rpx);
border-radius: 20rpx;
display: flex;
align-items: center;
background-color: #fdfeff;
flex-direction: column;
} */
.title-time-border-hisOk {
border: 2rpx solid #D4E4FE;
width: calc(100% - 40rpx);
height: calc(100% - 40rpx);
width: calc(100% - 20rpx);
height: calc(100% - 20rpx);
border-radius: 20rpx;
display: flex;
align-items: center;
background-color: #F6F9FF;
flex-direction: column;
}
.title-time-border-current{
margin: 10rpx;
.title-time-border-current {
border: 3rpx dashed #4690FF;
width: calc(100% - 40rpx);
height: calc(100% - 40rpx);
width: calc(100% - 20rpx);
height: calc(100% - 20rpx);
border-radius: 20rpx;
display: flex;
align-items: center;
background-color: #F6F9FF;
flex-direction: column;
}
.title-time-border-hisFaild{
margin: 10rpx;
.title-time-border-hisFaild {
border: 2rpx dashed #FFE2E2;
width: calc(100% - 40rpx);
height: calc(100% - 40rpx);
width: calc(100% - 20rpx);
height: calc(100% - 20rpx);
border-radius: 20rpx;
display: flex;
align-items: center;
@ -355,9 +360,8 @@
}
.title-time-border-yellow-active-transparent {
margin: 10rpx;
width: calc(100% - 40rpx);
height: calc(100% - 40rpx);
width: calc(100% - 20rpx);
height: calc(100% - 20rpx);
border-radius: 20rpx;
display: flex;
align-items: center;
@ -367,10 +371,9 @@
}
.title-time-border-yellow-active {
margin: 10rpx;
border: 1rpx solid #dae8fa;
width: calc(100% - 40rpx);
height: calc(100% - 40rpx);
width: calc(100% - 20rpx);
height: calc(100% - 20rpx);
border-radius: 20rpx;
display: flex;
align-items: center;
@ -498,7 +501,7 @@
font-weight: 600;
}
.right-order{
.right-order {
position: fixed;
right: 20rpx;
top: 62rpx;
@ -506,24 +509,29 @@
width: 430rpx;
background-color: #fff;
border-radius: 30rpx;
.order-title{
.order-title {
width: 100%;
height: 100rpx;
display: flex;
align-items: center;
.order-month{
.order-month {
margin-left: 30rpx;
font-size: 30rpx;
font-weight: 600;
width: 80rpx;
}
.order-day{
.order-day {
width: 300rpx;
height: 100rpx;
.days-father{
.days-father {
display: flex;
align-items: center;
.days{
.days {
height: 100rpx;
min-width: 50rpx;
display: flex;
@ -532,7 +540,8 @@
font-size: 26rpx;
color: #BBBABA;
}
.targetdays{
.targetdays {
height: 50rpx;
min-width: 50rpx;
display: flex;
@ -547,3 +556,22 @@
}
}
}
.calendar-father {
position: fixed;
top: 150rpx;
right: 30rpx;
width: 700rpx;
height: 600rpx;
z-index: 101;
}
.mengban {
width: 100vw;
height: 100vh;
position: fixed;
top: 0;
left: 0;
z-index: 100;
background: RGBA(239, 240, 244, 0.55);
}

View File

@ -49,11 +49,13 @@
<view class="title-time-blue"
v-show="saveEditIndex.index0 == index0 && saveEditIndex.index1 == index1 && isRule">
<image class="blue-img"
src="/static/index/bluetarget.png" />
</view>
<view :class="getClass(item1,index0,index1)"
style="font-size: 30rpx;overflow: hidden;"
:style="{ animationDelay:`-${computeDelay(index0, index1).toFixed(2)}s` }">
:style="{ animationDelay:`-${computeDelay(index0, index1).toFixed(2)}s`,border:saveEditIndex.index0 == index0 && saveEditIndex.index1 == index1? `2rpx solid #46B2F6`:'' }">
<view class="title-time" v-if="item1.startTime"
style="flex-direction: column;">
@ -66,8 +68,9 @@
class="title-time-font-tags">
({{ item1.directiveName?splitString(item1.directiveName)[1]:""}})
</view>
<view v-if="item1.startTime" :class="getFontClass(item1)" >
{{ `${parseHourMinutestring(item1.startTime).hour}:${parseHourMinutestring(item1.startTime).minute}-${parseHourMinutestring(item1.endTime).hour}:${parseHourMinutestring(item1.endTime).minute}` }}
<view v-if="item1.startTime"
:class="getFontClass(item1,index0,index1)">
{{ `${parseHourMinutestring(item1.startTime).hour}:${parseHourMinutestring(item1.startTime).minute} - ${parseHourMinutestring(item1.endTime).hour}:${parseHourMinutestring(item1.endTime).minute}` }}
</view>
</view>
@ -83,7 +86,7 @@
</view>
<view class="right-order">
<view class="order-title">
<view class="order-month">
<view class="order-month" @click="opendata=true">
{{ selectdata.month }}
</view>
<scroll-view class="order-day" scroll-with-animation :scroll-x="true"
@ -96,6 +99,12 @@
</view>
</scroll-view>
</view>
<view class="calendar-father" v-show="opendata">
<calendarsimple @datachange="dateget" />
</view>
<view v-show="opendata" class="mengban"
@click="opendata=false">
</view>
</view>
</view>
</view>
@ -108,6 +117,7 @@
import { onShow, onHide } from '@dcloudio/uni-app';
import { getNclist, addBatch, addDirective, addInstant, deleteDirective, deleteInstant, editDirective, getDirectiveOrders } from "./api.js";
import { myArray } from './yaoshandiao.js';
import calendarsimple from '@/component/public/calendarsimple.vue'
const props = defineProps({
isshow: {
@ -125,6 +135,7 @@
// }
// }
// )
const opendata = ref(false);
const bodystatus = ref(false);
const bodystatustarget = ref(-1);
const facestatus = ref(false);
@ -266,9 +277,8 @@
}
})
const getFontClass = (item:any) => {
const getFontClass = (item : any, index0, index1) => {
switch (item.executeStatus) {
case 'hisFaild':
return 'card-time-red';
@ -277,7 +287,6 @@
default:
return 'card-time';
}
}
//
@ -611,6 +620,10 @@
forthmenuIndex.value = 0;
}
const deletedonghua = ref(false);
const dateget = (time) => {
opendata.value = false
console.log("time",time.date)
}
</script>
<style lang="less" scoped>

BIN
static/index/bluetarget.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB