【uniapp3】分享一个自己写的h5日历组件

简言

分享一下自己基于uniapp写的日历组件。如果不太满足你的需求,可以自己改造。
在这里插入图片描述

日历

实现分析:

  • 页面显示 - 分为顶部显示和日历显示,我这里做了多行和单行显示两种情况,主要是当时看着手机的日历做的,手机上的日历单行和多行显示切换特别丝滑,但是我没实现出来。(我觉得限制原因是当时水平不够,再加上滚动用的uniapp的swipper组件,不能定制化实现)。
  • 分屏滚动 - 使用 uniapp的swipper组件,我这里,单行使用这个月周+上个月最后一周+下个月最后一周数据,多行使用这个月+上个月+下个月数据;这样处理的原因是在进行月份切换的时候可以先显示数据然后进行数据更新,实现无感无限切换滚动。
  • 各种事件 - 点击日期发送选中日期的数据。
  • 数据逻辑 - 主要是先确定你想要的数据结构,然后以这个为单位组装成行(周)数组或多行(月)数组。

没有自己实现滚动,也算是取了巧。感觉难点就是日期的数据处理 和 滚动,已经单多行切换了。

代码: uniapp写的 vue2和vue3应该都能用,样式注意使用了sass。

<template>
  <view class="calendar">
    <view class="wrapper">
      <slot
        name="top"
        :nowMonthText="nowMonthText"
        :pickerMonth="pickerMonth"
        :prevMonth="prevMonth"
        :nextMonth="nextMonth"
      >
        <view class="top">
          <view class="month-box">
            <view class="month-text">
              <view class="uni-input" @tap="pickerMonth">{{
                nowMonthText
              }}</view>
            </view>
            <view class="back-today" @tap="goToday">回到今天</view>
          </view>
          <view class="top-left">
            <view class="icon-arrow arrow-left" @tap="previousFn"></view>
            <view class="icon-arrow arrow-right" @tap="nextFn"></view>
          </view>
        </view>
      </slot>
      <view class="calender-box">
        <view class="head-title">
          <view
            class="head-title-item"
            v-for="v in calenderTitleList"
            :key="v"
            >{{ v }}</view
          >
        </view>
        <!-- 一行显示 -->

        <swiper
          v-if="showType === 1"
          class="row-swiper"
          circular
          :disable-programmatic-animation="true"
          :duration="duration"
          :current="swiperCurrent"
          @change="swipereChangFn"
        >
          <swiper-item
            v-for="(v, index) in calenderRowDaysList"
            :key="index"
            :item-id="v.label"
          >
            <view class="row-days-list">
              <view
                class="days-list-item"
                v-for="(item, i) in v.value"
                :key="`${index}-${i}`"
                :class="{
                  used: item.used,
                }"
              >
                <view
                  class="label"
                  v-if="(isNowMonth && item.isNowMonth) || !isNowMonth"
                  :class="{
                    disabled: item.disabled,
                  }"
                  @tap="clickDay(item)"
                >
                  <view
                    class="text"
                    :class="{
                      'active-item':
                        nowSelectDay && nowSelectDay['time'] === item.time,
                      'active-item--disabled':
                        nowSelectDay &&
                        nowSelectDay['time'] === item.time &&
                        item.disabled,
                      'today-text':
                        item.label === '' &&
                        nowSelectDay &&
                        nowSelectDay['time'] !== item.time &&
                        !item.disabled,
                    }"
                  >
                    {{ item.label }}
                  </view>
                  <view
                    v-show="!item.disabled && item.state"
                    class="state-item text-state-item"
                  >
                  </view>
                  <view
                    class="item-adjust"
                    v-if="!item.disabled && item.adjust && item.adjust.value"
                    :class="{ 'text-state-leave': item.adjust.value == '1' }"
                  >
                    {{ item.adjust.value == "1" ? "休" : "课" }}
                  </view>
                </view>
              </view>
            </view>
          </swiper-item>
        </swiper>
        <!-- 全行显示 -->
        <swiper
          v-else
          class="all-swiper"
          circular
          :disable-programmatic-animation="true"
          :duration="duration"
          @change="swipereChangFn"
          :current="swiperCurrent"
          :class="{
            'six-height':
              swiperDaysList[0] && swiperDaysList[0].value.length / 7 === 6,
          }"
        >
          <swiper-item
            v-for="(v, index) in swiperDaysList"
            :key="index"
            :item-id="v.label"
          >
            <view class="days-list">
              <view
                class="days-list-item"
                v-for="(item, i) in v.value"
                :key="`${index}-${i}`"
                :class="{
                  used: item.used,
                }"
              >
                <view
                  class="label"
                  v-if="(isNowMonth && item.isNowMonth) || !isNowMonth"
                  :class="{
                    disabled: item.disabled,
                  }"
                  @tap="clickDay(item)"
                >
                  <view
                    class="text"
                    :class="{
                      'active-item':
                        nowSelectDay && nowSelectDay['time'] === item.time,
                      'active-item--disabled':
                        nowSelectDay &&
                        nowSelectDay['time'] === item.time &&
                        item.disabled,
                      'today-text':
                        item.label === '' &&
                        nowSelectDay &&
                        nowSelectDay['time'] !== item.time &&
                        !item.disabled,
                    }"
                  >
                    {{ item.label }}
                  </view>
                  <view
                    v-show="!item.disabled && item.state"
                    class="state-item"
                  ></view>
                  <view
                    class="item-adjust"
                    v-if="!item.disabled && item.adjust && item.adjust.value"
                    :class="{ 'text-state-leave': item.adjust.value == '1' }"
                  >
                    {{ item.adjust.value == "1" ? "休" : "课" }}
                  </view>
                </view>
              </view>
            </view>
          </swiper-item>
        </swiper>
        <view v-if="!hideArrow" class="arrow-wrapper" @click="showTypeChange">
          <view
            class="arrow-left"
            :class="{ 'arrow-left--up': showType === 0 }"
          ></view>
          <view
            class="arrow-right"
            :class="{ 'arrow-right--up': showType === 0 }"
          ></view>
        </view>
      </view>
      <view class="content">
        <slot :value="nowSelectDay"></slot>
      </view>
    </view>
    <!-- 选择月份 -->
    <uni-popup ref="monthPopup" :type="'bottom'">
      <view class="month-popup-box">
        <view class="month-top">
          <view class="cancel-text" @tap="cancelDateFn">取消</view>
          <view class="ok-text" @tap="sucessDate">完成</view>
        </view>
        <picker-view
          :value="selectValue"
          @change="bindChange"
          class="picker-view"
        >
          <picker-view-column>
            <view class="item" v-for="(item, index) in years" :key="index"
              >{{ item }}年</view
            >
          </picker-view-column>
          <picker-view-column>
            <view class="item" v-for="(item, index) in months" :key="index"
              >{{ item }}月</view
            >
          </picker-view-column>
        </picker-view>
      </view>
    </uni-popup>
  </view>
</template>

<script>
export default {
  props: {
    isNowMonth: {
      //  是否只显示当前月日历值
      type: Boolean,
      default: false,
    },
    limitNowMoth: {
      //  限制只有当月
      type: Boolean,
      default: false,
    },
    showRowType: {
      type: Boolean,
      default: true,
    },
    dateStateList: {
      //  日历中的状态 [{date:'2023/12/1',value:1}]
      type: Array,
      default: () => [],
    },
    dateAdjustList: {
      //  日历中的调课状态 [{date:'2023/12/1',value:1}] 1为休,2为调课
      type: Array,
      default: () => [],
    },
    defaultValue: {
      type: String,
      default: "",
    },
    hideArrow: {
      type: Boolean,
      default: false,
    },
  },
  emits: ["ok", "cancel", "changeMonth"],
  data() {
    const date = new Date();
    const years = [];
    const year = date.getFullYear();
    const months = [];
    const month = date.getMonth() + 1;
    const day = date.getDate();
    for (let i = 1990; i <= date.getFullYear() + 30; i++) {
      years.push(i);
    }
    for (let i = 1; i <= 12; i++) {
      months.push(i);
    }

    return {
      monthValue: [years.findIndex((item) => item === year), month - 1], //  选择月份值
      years,
      year, //当前年
      months,
      month, //  当前月
      day, //  当前日
      selectValue: [], //  月份选择器选中的值
      //  日历
      calenderTitleList: ["一", "二", "三", "四", "五", "六", "日"],
      swiperDaysList: [], //  swiper全行显示列表 0-当月 1-下月 2-上月
      swiperCurrent: 0, //  swiper当前显示索引
      duration: 500, //  动画时长
      calenderRowDaysList: [], //  rowSwiper行显示列表
      nowSelectDay: null, //  当前选中值
      showType: 0, //  0 全部行显示 1,1行显示
      isJust: false, //  是否是校准
    };
  },
  computed: {
    nowMonthText() {
      const [yearIndex, monthIndex] = this.monthValue;
      let str = `${
        this.years[yearIndex]
          ? this.years[yearIndex]
          : this.years[this.years.length - 1]
      }${this.months[monthIndex]}`;
      this.$emit("changeMonth", [
        this.years[yearIndex],
        this.months[monthIndex].toString().padStart(2, "0"),
      ]);
      return str;
    },
  },
  watch: {
    showRowType: {
      handler(val) {
        if (val) {
          this.showType = 1;
        } else {
          this.showType = 0;
        }
      },
      immediate: true,
    },
    defaultValue(val) {
      if (val && val !== "") {
        this.nowSelectDay = {
          time: Date.parse(val),
        };
      }
    },
  },

  mounted() {
    this.updateCalender();
  },

  methods: {
    showTypeChange() {
      this.showType = 1 - this.showType;
      // this.goToday();
      this.updateCalender(false);
      this.initCurrent();
    },
    //  点击天数
    clickDay(item) {
      if (item.disabled) return;
      this.nowSelectDay = item;
      this.$emit("ok", this.nowSelectDay);
    },
    pickerMonth() {
      if (this.limitNowMoth) return;
      //  同步当前月份值
      this.selectValue = this.monthValue.map((item) => item);
      this.$refs.monthPopup.open();
    },
    //  选择月份赋值
    bindChange({ target }) {
      this.selectValue = target.value;
    },
    //  选择月份完成
    sucessDate() {
      this.monthValue = this.selectValue.map((item) => item);
      this.updateCalender(false);
      if (this.showType === 1) {
        //  一行显示
        //  默认回到第一项

        this.initCurrent();
      }
      this.$refs.monthPopup.close();
    },
    //  取消选择月份
    cancelDateFn() {
      this.$refs.monthPopup.close();
    },
    swipereChangFn(event) {
      if (this.isJust) return;
      const { currentItemId, current } = event.detail;
      this.swiperCurrent = current;
      switch (currentItemId) {
        case "next":
          this.nextMonth();
          break;
        case "pre":
          this.prevMonth();
          break;
      }
      //  月份改变后定位
      if (this.showType === 0) {
        setTimeout(() => this.initCurrent(), 50);
      } else {
        if (currentItemId === "next") {
          setTimeout(() => this.initCurrent(), 50);
        } else if (currentItemId === "pre") {
          const CalenderDaysList = this.getDayList(
            this.years[this.monthValue[0]],
            this.months[this.monthValue[1]]
          );
          let preArr = this.group(CalenderDaysList, 7);
          setTimeout(() => this.initCurrent(preArr.length - 1), 50);
        }
      }
    },
    //  默认回到第一项
    initCurrent(index = 0) {
      if (index === 0) this.isJust = true;
      this.duration = 0;
      this.swiperCurrent = index;
      setTimeout(() => {
        this.isJust = false;
        this.duration = 500;
      }, 0);
    },
    //  回到今天
    goToday() {
      const { years, year, month, day } = this;
      const nowDayDate = `${year}/${month}/${day}`;

      this.monthValue = [years.findIndex((item) => item === year), month - 1];
      this.updateCalender();
      //  默认点击今天
      this.nowSelectDay = {
        value: day, //  值
        label: "今", //  描述
        disabled: false, //  禁用
        isNowMonth: true,
        date: nowDayDate,
        time: new Date(year, month - 1, day).valueOf(),
        state: this.dateStateList.find((data) => data.date === nowDayDate),
        adjust: this.dateAdjustList.find((data) => data.date === nowDayDate),
      };
      //  生成日历碰到今日会触发,这里注释掉
      // this.$emit("ok", this.nowSelectDay);
    },
    //
    previousFn() {
      if (this.swiperCurrent !== 0) {
        this.swiperCurrent--;
      } else {
        this.swipereChangFn({
          detail: {
            currentItemId: "pre",
            current: 0,
          },
        });
      }
    },
    nextFn() {
      this.swiperCurrent++;
    },
    //  上一月
    prevMonth() {
      this.monthValue = this.monthValue.map((item, index) => {
        if (this.monthValue[1] <= 0 && index == 0) {
          return --item;
        } else if (this.monthValue[1] <= 0 && index == 1) {
          return 11;
        } else if (index === 1) {
          return --item;
        }
        return item;
      });
      this.updateCalender(false);
    },
    //  下一月
    nextMonth() {
      this.monthValue = this.monthValue.map((item, index) => {
        if (this.monthValue[1] >= 11 && index == 0) {
          return item + 1;
        } else if (this.monthValue[1] >= 11 && index == 1) {
          return 0;
        } else if (index === 1) {
          return ++item;
        }
        return item;
      });
      this.updateCalender(false);
    },
    //  更新日历
    updateCalender(updateNowDay = true) {
      const year = this.years[this.monthValue[0]];
      const month = this.months[this.monthValue[1]];
      const preYMArr = this.getMonthV(this.monthValue, 2);
      const nextYMArr = this.getMonthV(this.monthValue);
      const nowCalenderDaysList = this.getDayList(year, month);
      const preCalenderDaysList = this.getDayList(preYMArr[0], preYMArr[1]);
      const nextCalenderDaysList = this.getDayList(nextYMArr[0], nextYMArr[1]);
      if (this.year === year && this.month === month) {
        // 含有(今)年月
        for (let i in nowCalenderDaysList) {
          if (nowCalenderDaysList[i].label === "今" && updateNowDay) {
            this.nowSelectDay = nowCalenderDaysList[i];
            this.$emit("ok", this.nowSelectDay);
            if (this.showType !== 0) {
              this.swiperCurrent = Math.ceil((i * 1 + 1) / 7) - 1;
            }
          }
        }
      }
      if (this.showType === 0) {
        //  全行显示
        this.swiperDaysList = this.limitNowMoth
          ? [
              {
                label: "now",
                value: nowCalenderDaysList,
              }, //  当月
            ]
          : [
              {
                label: "now",
                value: nowCalenderDaysList,
              }, //  当月
              {
                label: "next",
                value: nextCalenderDaysList,
              }, //  下一月
              {
                label: "pre",
                value: preCalenderDaysList,
              },
              //  上一月
            ];
      } else {
        //1 一行
        let nowArr = this.group(nowCalenderDaysList, 7);
        let preArr = this.group(preCalenderDaysList, 7);
        let nextArr = this.group(nextCalenderDaysList, 7);
        this.calenderRowDaysList = this.limitNowMoth
          ? [
              ...nowArr.map((arr) => {
                return { label: "now", value: arr };
              }), //  当月
            ]
          : [
              ...nowArr.map((arr) => {
                return { label: "now", value: arr };
              }), //  当月
              {
                label: "next",
                value: nextArr[0],
              }, //  下月第一行
              {
                label: "pre",
                value: preArr[preArr.length - 1],
              }, //  上月最后一行
            ];
      }
    },
    //  根据当前月份值获取上下年月值
    getMonthV(value, type = 1) {
      let arr = []; //  当前月份
      if (type === 1) {
        //  默认获取下一月
        arr = value.map((item, index) => {
          if (value[1] >= 11 && index == 0) {
            return item + 1;
          } else if (value[1] >= 11 && index == 1) {
            return 0;
          } else if (index === 1) {
            return ++item;
          }
          return item;
        });
      } else {
        //  获取上一月
        arr = value.map((item, index) => {
          if (value[1] <= 1 && index == 0) {
            return --item;
          } else if (value <= 1 && index == 1) {
            return 11;
          } else if (index === 1) {
            return --item;
          }
          return item;
        });
      }
      return [this.years[arr[0]], this.months[arr[1]]];
    },
    //  根据年月获取天数列表
    getDayList(year, month) {
      let list = [];

      const startDate = new Date(year, month - 1, 1);
      const endDate = new Date(year, month, 1);
      const days = (endDate - startDate) / (1000 * 60 * 60 * 24);
      for (let i = 1; i <= days; i++) {
        const dateStr = `${year}/${month}/${i}`;
        let week = new Date(dateStr).getDay();

        if (i === 1) {
          let startIndex = week === 0 ? 6 : week - 1;
          //  上月天数列表
          let prevDays =
            (startDate - new Date(year, month - 2, 1)) / (1000 * 60 * 60 * 24);
          let preList = [];
          let piL = 7 + (startIndex - 7);
          for (let pi = 0; pi < piL; pi++) {
            const preDay = prevDays - piL + pi + 1;
            const date = `${year}/${month - 1}/${preDay}`;
            preList.push({
              value: preDay, //  值
              label: preDay, //  描述
              disabled: true, //  禁用
              isNowMonth: false,
              date,
              time: new Date(date).valueOf(),
              state: this.dateStateList.find((data) => data.date === date),
              adjust: this.dateAdjustList.find((data) => data.date === date),
            });
          }
          list.splice(0, startIndex, ...preList);
        }
        list.push({
          value: i, //  值
          label:
            new Date(year, month - 1, i).valueOf() ===
            new Date(this.year, this.month - 1, this.day).valueOf()
              ? "今"
              : i, //  描述
          disabled: false, //  禁用
          isNowMonth: true,
          date: dateStr,
          time: new Date(year, month - 1, i).valueOf(),
          state: this.dateStateList.find((data) => data.date === dateStr),
          adjust: this.dateAdjustList.find((data) => data.date === dateStr),
        });
      }
      //  补齐
      if (list.length % 7 !== 0) {
        let endIndex = 7 - (list.length % 7);
        //  下月天数列表
        let nextList = [];
        for (let ni = 0; ni < endIndex; ni++) {
          nextList.push({
            value: ni + 1, //  值
            label: ni + 1,
            disabled: true, //  禁用
            isNowMonth: false,
            date: `${year}/${month + 1}/${ni + 1}`,
            time: new Date(year, month, ni + 1).valueOf(),
          });
        }
        list.push(...nextList);
      }
      return list;
    },
    //  单数组分割成等长二维数组
    group(list, len) {
      let index = 0;
      const arr = [];
      while (index < list.length) {
        arr.push(list.slice(index, (index += len)));
      }
      return arr;
    },
  },
};
</script>

<style lang="scss" scoped>
.calendar {
  position: relative;
  background: #fff;
}

.wrapper {
  font-family: PingFangSC-Regular, PingFang SC;
  color: #222;
}
// 顶部
.top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 32rpx 48rpx 16rpx;

  .title {
    height: 48rpx;
    font-size: 34rpx;
    font-weight: 600;
    color: #222222;
    line-height: 48rpx;
  }
  .parting-line {
    width: 1rpx;
    height: 28rpx;
    background: #666;
    margin: 0 16rpx;
  }
  .month-box {
    display: flex;
    align-items: center;
    line-height: 37rpx;
    font-size: 32rpx;
    color: #333333;
    font-weight: 600;
    .back-today {
      font-size: 24rpx;
      font-weight: 400;
      line-height: 24rpx;
      color: $c-primary;
      margin-left: 12rpx;
    }
  }
  .top-left {
    display: flex;
    align-items: center;
    .icon-arrow {
      width: 28rpx;
      height: 28rpx;
    }
    .arrow-left {
      background: center/100%
        url(#{$img-url}/static/img/free/b-icon-arrow-left.png);
    }
    .arrow-right {
      margin-left: 24rpx;
      background: center/100%
        url(#{$img-url}/static/img/free/b-icon-arrow-right.png);
    }
  }
}
.row-swiper {
  height: 110rpx;
}
.all-swiper {
  height: 450rpx;
  transition: height ease 0.5s;
}
.six-height {
  height: 53 0rpx;
}
.calender-box {
  position: relative;
  padding: 24rpx 24rpx 0;
  // box-shadow: 30vw 5rpx 10rpx rgba($color: #eee, $alpha: 0.4),
  //   -30vw 5rpx 10rpx rgba($color: #eee, $alpha: 0.4);
  z-index: 10;
  .head-title {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    grid-gap: 10rpx;
    margin-bottom: 16rpx;
    &-item {
      width: 90rpx;
      height: 33rpx;
      font-size: 24rpx;
      font-weight: 400;
      color: #888888;
      line-height: 33rpx;
      text-align: center;
    }
  }
  .days-list {
    display: grid;
    height: 100%;
    grid-template-columns: repeat(7, 1fr);
    grid-gap: 10rpx;
    padding-top: 14rpx;
    align-content: stretch;
  }
  .row-days-list {
    display: grid;
    height: 100%;
    grid-template-columns: repeat(7, 1fr);
    grid-gap: 10rpx;
    margin-bottom: 10rpx;
    // align-content: space-around;
    align-content: stretch;
    padding-top: 14rpx;
  }
  .days-list-item {
    display: flex;
    align-items: flex-start;
    justify-content: center;
    width: 100%;
    height: 74rpx;
    font-size: 34rpx;
    font-family: Helvetica;
    color: #222222;
    line-height: 41rpx;
    .label {
      position: relative;
      display: flex;
      flex-direction: column;
      justify-content: flex-start;
      align-items: center;
      .text {
        flex-shrink: 0;
        position: relative;
        width: 62rpx;
        height: 62rpx;
        line-height: 62rpx;
        text-align: center;
      }
    }
    .active-item {
      background-color: #006eff;
      color: #fff;
      border-radius: 50%;
    }
    .today-text {
      color: #006eff;
    }
    .active-item--disabled {
      opacity: 0.5;
    }
    .state-item {
      flex-shrink: 0;
      margin-top: 4rpx;
      width: 10rpx;
      height: 10rpx;
      background: #006eff;
      border-radius: 50%;
    }
    .text-state-item {
      width: 8rpx;
      height: 8rpx;

      background-color: #ff7400;
    }

    .item-adjust {
      position: absolute;
      top: -24rpx;
      right: -6rpx;
      width: 20rpx;
      height: 20rpx;
      font-family: PingFangSC, PingFang SC;
      font-weight: 400;
      font-size: 20rpx;
      color: #666666;
      text-align: right;
      font-style: normal;
    }
    .text-state-leave {
      color: #ff7400;
    }

    .disabled {
      color: #eaeaea;
    }
  }

  .arrow-wrapper {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 50rpx;
    height: 40rpx;
    margin: 10rpx auto;
    .arrow-left {
      width: 20rpx;
      height: 4rpx;
      background-color: #ddd;
      border-radius: 2rpx 0 0 2rpx;
      transform: rotate(30deg);
      transform-origin: center right;
      transition: transform ease-in 0.3s;
    }
    .arrow-right {
      width: 20rpx;
      height: 4rpx;
      background-color: #ddd;
      border-radius: 0rpx 2rpx 2rpx 0;
      transform: rotate(-30deg);
      transform-origin: center left;
      transition: transform ease-in 0.3s;
    }
    .arrow-left--up {
      transform: rotate(-30deg);
    }
    .arrow-right--up {
      transform: rotate(30deg);
    }
  }
}

.month-popup-box {
  font-size: 30rpx;
  .month-top {
    display: flex;
    align-items: center;
    justify-content: space-between;
    border-bottom: 1rpx solid #ccc;
    padding: 28rpx 32rpx;
    .ok-text {
      font-size: 30rpx;
      color: #006eff;
      line-height: 42rpx;
    }
    .cancel-text {
      color: #999;
      font-size: 30rpx;
      line-height: 42rpx;
    }
  }
  .picker-view {
    width: 100%;
    height: 400rpx;
    text-align: center;
  }
}

:deep(.popup .uni-popup__wrapper.uni-custom.bottom .uni-popup__wrapper-box) {
  max-height: 100vh;
}
</style>

使用,记得引用先。
在这里插入图片描述

结语

结束了。本来想写更多呢,结果代码字数太多,太卡了,有兴趣自己看吧。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/906377.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Nginx安装配置详解

Nginx Nginx官网 Tengine翻译的Nginx中文文档 轻量级的Web服务器&#xff0c;主要有反向代理、负载均衡的功能。 能够支撑5万的并发量&#xff0c;运行时内存和CPU占用低&#xff0c;配置简单&#xff0c;运行稳定。 写在前 uWSGI与Nginx的关系 1. 安装 Windows 官网 Stabl…

Java版企电子招标采购系统源业码Spring Cloud + Spring Boot +二次开发+ MybatisPlus + Redis

功能描述 1、门户管理&#xff1a;所有用户可在门户页面查看所有的公告信息及相关的通知信息。主要板块包含&#xff1a;招标公告、非招标公告、系统通知、政策法规。 2、立项管理&#xff1a;企业用户可对需要采购的项目进行立项申请&#xff0c;并提交审批&#xff0c;查看所…

MS01SF1 精准测距UWB模组助力露天采矿中的人车定位安全和作业效率提升

在当今矿业行业&#xff0c;随着全球对资源需求的不断增加和开采难度的逐步提升&#xff0c;传统的作业方式面临着越来越多的挑战。露天矿山开采&#xff0c;因其大规模的作业环境和复杂的地形特点&#xff0c;面临着作业人员的安全风险、设备调度的高难度以及资源利用率低下等…

【Web.路由】——路由模板

路由模板负责根据规则生成URL&#xff0c;从而使得请求可以正常访问到资源。 总之就是——》》》 规范如何写一个url&#xff0c;并且命名以方便进行管理。 在Asp.net core中的Http管道机制&#xff0c;UseRouting()和 UseEndpoints()这两个中间件来实现整个路由系统。关于asp…

c加加11第二弹~

1lambda 1.1.lambda表达式书写格式 [capture-list] (parameters) mutable -> return-type { statement} 1.2lambda表达式各部分说明 [capture-list] : 捕捉列表&#xff0c;该列表总是出现在lambda函数的开始位置&#xff0c;编译器根据[]来判断接下来的代码是否为lamb…

记录|多线程和异步简单理解

目录 前言一、单线程二、多线程-Thread多线程是都多少个的时候会导致性能变差 三、多线程-Task类Task的优势 四、异步- awaitawait注意&#xff1a;多个Task Run()天剑await后&#xff0c;变成了同步执行解决方法 更新时间 前言 参考视频&#xff1a;C#基础教程 多线程编程入门…

凸极式发电机的相量图分析和计算,内功率因数角和外功率因数角和功角的定义。

图1&#xff1a;同步发电机稳态相量图 若发电机为凸极式&#xff0c;由于凸极机正、交轴同步电抗不等&#xff0c;即xd≠xq&#xff0c;因此必须先借助虚构电动势 E ˙ Q E ˙ q − ( x d − x q ) I ˙ d \dot{E}_Q\dot{E}_q-(x_d-x_q)\dot{I}_d E˙Q​E˙q​−(xd​−xq​)…

C语言原码、反码和补码的详解

C语言原码、反码和补码的详解 放在最前面的1、前言正数的原码、反码和补码负数的原码、反码和补码 2、整数的原码&#xff08;2.1&#xff09;原码的定义&#xff08;2.2&#xff09;计算原码 3、整数的反码&#xff08;3.1&#xff09;反码的定义&#xff08;3.2&#xff09;计…

idea 导入Spring源码遇到的坑并解决

1.下载相关文件 通过百度网盘分享的文件&#xff1a;Spring 链接&#xff1a;https://pan.baidu.com/s/1r9rkGOCaY9SFn9ecng5cIg?pwd8888 提取码&#xff1a;8888 2.配置gradle环境 gradle下载地址 需要翻墙下 https://services.gradle.org/distributions/ 我选择的是 grad…

Redis-“自动分片、一定程度的高可用性”(sharding水平拆分、failover故障转移)特性(Sentinel、Cluster)

文章目录 零、写在前面一、水平拆分(sharding/分片)、故障转移(failover)机制介绍水平拆分&#xff08;Sharding&#xff09;故障转移机制 二、Redis的水平拆分的机制有关的配置1. 环境准备2. 配置文件配置3. 启动所有Redis实例4. 创建集群5. 测试集群读/写6. 集群管理 三、Red…

C++STL详解(九)map和set的使用

一.关联式容器的介绍 CSTL包含了序列式容器和关联式容器&#xff1a; 序列式容器里面存储的是元素本身&#xff0c;其底层是线性的数据结构&#xff0c;就譬如我们之前学习的vector&#xff0c;list&#xff0c;deque等等。关联式容器里面存储的是<key,value>的键值对&…

goframe开发一个企业网站 模版界面4

###goframe已有了模板的功能 {{"string"}} // 一般 string {{raw string}} // 原始 string {{c}} // byte {{print nil}} // nil 也被支持 {{. | FuncA | FuncB | FuncC}}{{if .condition}}... {{else}}{{if .condition2}}...{{end}} {{end}}{{rang…

一、k8s快速入门之学习Kubernetes组件基础

一、三个容器管理器平台 Apache MESOS 开源的分布式资源管理框架&#xff0c;被推特选为基础平台&#xff0c;2019年推特换位k8s&#xff0c;MESOS最新版可以在MESOS上管理k8sDOCKER SWARM docker总部发行的&#xff0c;实现docker的集群方案&#xff0c;和docker捆版一起&…

初始JavaEE篇——多线程(7):定时器、CAS

找往期文章包括但不限于本期文章中不懂的知识点&#xff1a; 个人主页&#xff1a;我要学编程程(ಥ_ಥ)-CSDN博客 所属专栏&#xff1a;JavaEE 目录 定时器的使用 定时器的原理 模拟实现定时器 CAS 介绍 CAS的应用场景 解析 AtomicInteger 类 实现自旋锁 CAS的缺陷…

【UGUI】为射击游戏添加动态显示的分数和血量到UI界面

项目背景 在这个项目中&#xff0c;我们希望实现一个简单的游戏系统&#xff0c;其中玩家可以通过击中目标来获得分数&#xff0c;同时通过与怪物碰撞来减少血量。分数和血量需要在游戏界面上实时显示&#xff0c;以便玩家能够随时了解自己的状态。 技术实现 1. 静态变量的使…

stm32引脚PB3、PB4、PA15作为普通IO口用时,需要先解除调试端口复用

当项目调试的时候&#xff0c;发现PA15引脚无论配置输出高还是低或者输入&#xff0c;均只能输出3.3V的高电平。 目前STM的硬件调试有两种方法&#xff0c;JTAG和SW的方式&#xff0c;目前个人认为最好的方式就是SW&#xff0c;因为它只占用PA13和PA14两个IO。而JTAG还要多占用…

MATLAB与STK互联:仿真并获取低轨卫星与指定区域地面站的可见性数据

MATLAB控制STK实现&#xff1a;仿真并获取低轨卫星与指定区域地面站的可见性数据 本次仿真主要参考了多篇文献和网站&#xff0c;包括但不限于&#xff1a;《Using MATLAB for STK Automation》、CSDN博文&#xff1a; 拜火先知的博客_CSDN博客-笔记、AGI官网有关MATLAB的内容…

用Python设置、更新和获取Excel单元格的值

Excel工作簿作为一款广泛使用的数据管理工具&#xff0c;与Python相结合&#xff0c;可以使得自动化处理大量数据成为可能。通过Python来设置、更新以及读取Excel单元格的值&#xff0c;不仅可以极大地提高工作效率&#xff0c;减少重复劳动&#xff0c;还能增强数据处理流程的…

Golang | Leetcode Golang题解之第525题连续数组

题目&#xff1a; 题解&#xff1a; func findMaxLength(nums []int) (maxLength int) {mp : map[int]int{0: -1}counter : 0for i, num : range nums {if num 1 {counter} else {counter--}if prevIndex, has : mp[counter]; has {maxLength max(maxLength, i-prevIndex)} …

提升网站安全性 HTTPS的重要性与应用指南

内容概要 在如今数字化快速发展的时代&#xff0c;网站安全显得尤为重要。许多用户在访问网站时&#xff0c;尤其是涉及个人信息或金融交易时&#xff0c;对数据传输的安全性有着高度的关注。HTTPS&#xff08;超文本传输安全协议&#xff09;正是为了满足这种需求而诞生的。通…