效果图和数据结构如上两图所示,简单总结一下需求
1.后台会将本年度的节假日数据提前录入,在页面初始化时,请求回的列表就是上图图2所示,并渲染到页面,holidayName为1,工作日,0为节假日
2.点击某天,可以设置节假日或工作日
3.设置节假日或工作日时,备注为非必填输入项,展现在日期下面的文字就是holidayName
父组件
view/holiday/index.vue
<template>
<div class="container">
<div class="buttons">
<el-button class="holidayButton" type="primary" @click="submitHoliday"
>设置节假日</el-button
>
<el-button class="holidayButton" type="primary" @click="submitWorkDay"
>设置工作日</el-button
>
</div>
<full-calendar
firstDay="1"
lang="zh"
:events="holidayList"
@eventClick="eventClick"
@changeMonth="changeDate"
>
</full-calendar>
</div>
</template>
<script>
import FullCalendar from "@/components/vue-fullcalendar/fullCalendar";
import {
mapState, mapGetters } from "vuex";
import {
listHoliday, getHoliday, updateHoliday } from "@/api/upms/holiday";
export default {
components: {
FullCalendar,
},
data() {
let self = this;
return {
holidayList: [],
events: [],
selectedDay: "",
holidayStatus: "",
selectedYear: new Date().getFullYear(),
};
},
created() {
this.getList(this.selectedYear);
},
watch: {
selectedYear: function (newVal, oldVal) {
if (newVal != oldVal) {
this.getList(newVal);
}
},
},
computed: {
...mapState({
useFuncList: (state) => state.useFunction.useFuncList,
}),
...mapGetters(["emplId"]),
},
methods: {
getList(year) {
listHoliday(year).then((response) => {
console.log(response);
this.holidayList = response.data;
});
},
eventClick(date, event, jsEvent, pos) {
this.selectedDay = this.parseTime(date, "{y}-{m}-{d}");
},
changeDate(start, end, currentStart, currentDate) {
this.selectedYear = this.parseTime(currentDate, "{y}");
},
submitHoliday() {
let param = {
};
param.holidayDate = this.selectedDay;
param.holidayFlag = "0";
param.changeEmplId = this.emplId;
console.log(param);
if (this.selectedDay != "") {
this.$prompt(
"请输入备注",
"确定设置" + this.selectedDay + "为节假日吗?",
{
confirmButtonText: "确定",
cancelButtonText: "取消",
}
)
.then(({
value }) => {
param.holidayName = value;
updateHoliday(param).then((res) => {
this.$message({
message: "设置成功", type: "success" });
this.getList(this.selectedYear);
});
})
.catch(() => {
this.$message({
type: "info",
message: "取消设置",
});
});
} else {
this.$message({
message: "请选择日期", type: "error" });
}
},
submitWorkDay() {
let param = {
};
param.holidayDate = this.selectedDay;
param.holidayFlag = "1";
param.changeEmplId = this.emplId;
if (this.selectedDay != "") {
this.$prompt(
"请输入备注",
"确定设置" + this.selectedDay + "为工作日吗?",
{
confirmButtonText: "确定",
cancelButtonText: "取消",
}
)
.then(({
value }) => {
param.holidayName = value;
updateHoliday(param).then((res) => {
this.$message({
message: "设置成功", type: "success" });
this.getList(this.selectedYear);
});
})
.catch(() => {
this.$message({
type: "info",
message: "取消设置",
});
});
} else {
this.$message({
message: "请选择日期", type: "error" });
}
},
},
};
</script>
<style lang="scss" scoped>
.container {
padding-top: 30px;
margin: 0 auto;
background: #fff;
.buttons {
margin-left: 50px;
}
}
</style>
子组件(日历组件)目录结构
components/vue-fullcalendar/fullCalendar.vue
//components/vue-fullcalendar/fullCalendar.vue
<template>
<div class="comp-full-calendar">
<!-- header pick month -->
<fc-header :current-date="currentDate"
:title-format="titleFormat"
:first-day="firstDay"
:month-names="monthNames"
@change="emitChangeMonth">
<div slot="header-left">
<slot name="fc-header-left">
</slot>
</div>
<div slot="header-right">
<slot name="fc-header-right">
</slot>
</div>
</fc-header>
<fc-body :current-date="currentDate" :events="events" :month-names="monthNames"
:week-names="weekNames" :first-day="firstDay"
@eventclick="emitEventClick" @dayclick="emitDayClick"
@moreclick="emitMoreClick">
<div slot="body-card">
<slot name="fc-body-card">
</slot>
</div>
</fc-body>
</div>
</template>
<script type="text/babel">
import langSets from './dataMap/langSets'
import header from './components/header.vue'
import body from './components/body.vue'
export default {
props : {
events : {
// events will be displayed on calendar
type : Array,
default :()=> []
},
lang : {
type : String,
default : 'en'
},
firstDay : {
type : Number | String,
validator (val) {
let res = parseInt(val)
return res >= 0 && res <= 6
},
default : 0
},
titleFormat : {
type : String,
default () {
return langSets[this.lang].titleFormat
}
},
monthNames : {
type : Array,
default () {
return langSets[this.lang].monthNames
}
},
weekNames : {
type : Array,
default () {
let arr = langSets[this.lang].weekNames
return arr.slice(this.firstDay).concat(arr.slice(0, this.firstDay))
}
}
},
data () {
return {
currentDate : new Date()
}
},
methods : {
emitChangeMonth (start, end, currentStart, current) {
this.currentDate = current
this.$emit('changeMonth', start, end, currentStart, current)
},
emitEventClick (date, event, jsEvent, pos) {
// console.log(date,event)
this.$emit('eventClick', date, event, jsEvent, pos)
},
emitDayClick (day, jsEvent) {
this.$emit('dayClick', day, jsEvent)
},
emitMoreClick (day, events, jsEvent) {
this.$emit('moreClick', day, events, jsEvent)
}
},
components : {
'fc-body' : body,
'fc-header' : header
}
}
</script>
<style lang="scss">
.comp-full-calendar{
background: #fff;
width: 100%;
padding-left: 50px;
padding-right: 50px;
ul,p{
margin:0;
padding:0;
font-size: 14px;
}
}
</style>
components/vue-fullcalendar/index.js
//components/vue-fullcalendar/index.js
import vueFullcalendar from './fullCalendar'
const fc = vueFullcalendar
module.exports = fc
components/vue-fullcalendar/dataMap/langSets.js
//components/vue-fullcalendar/dataMap/langSets.js
export default {
en : {
weekNames : ['Sun', 'Mon','Tue','Wed','Thu','Fri','Sat'],
monthNames : ['January','February','March','April','May','June','July','August','September','October','November','December'],
titleFormat : 'MMMM yyyy'
},
zh : {
weekNames : ['周日', '周一','周二','周三','周四','周五','周六'],
monthNames : ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
titleFormat : 'yyyy年MM月'
},
fr : {
weekNames : ['Dim','Lun','Mar','Mer','Jeu','Ven','Sam'],
monthNames : ['Janvier','Février','Mars','Avril','Mai','Juin','Juillet','Août','Septembre','Octobre','Novembre','Décembre'],
titleFormat : 'MMMM yyyy'
}
}
components/vue-fullcalendar/components/body.vue
样式的修改,数据的传递处理, 主要集中在这个组件中
//components/vue-fullcalendar/components/body.vue
<template>
<div class="full-calendar-body">
<div class="weeks">
<strong class="week" v-for="(week, index) in weekNames" :key="index">{
{
week
}}</strong>
</div>
<div class="dates" ref="dates">
<!-- absolute so we can make dynamic td -->
<div class="dates-events">
<div
class="events-week"
v-for="(week, index) in currentDates"
:key="index"
>
<div
class="events-day"
v-for="(day, index) in week"
:key="index"
track-by="$index"
:class="{
today: day.isToday,
'not-cur-month': !day.isCurMonth,
eventBg: day.events.length > 0,
clickDay: day.date === selectedDay,
}"
@click.stop="eventClick(day.date, day.events, $event)"
>
<div class="event-box">
<p
class="event-item"
v-for="(event, index) in day.events"
:key="index"
v-show="event.cellIndex <= eventLimit"
:class="[
classNames(event.cssClass),
{
'is-start': isStart(event.start, day.date),
'is-end': isEnd(event.end, day.date),
'is-opacity': !event.isShow,
'is-work':event.holidayFlag/1==1
},
]"
>
{
{
isBegin(event, day.date, day.weekDay) }}
<span v-if="event.holidayName">{
{
event.holidayName?event.holidayName:''}}</span>
</p>
<p
v-if="day.events.length > eventLimit"
class="more-link"
@click.stop="selectThisDay(day, $event)"
>
+
{
{
day.events[day.events.length - 1].cellIndex - eventLimit
}}
more
</p>
</div>
<p class="day-number" :class="{ eventDay: day.events.length > 0,'iswork':day.events.length > 0&&day.events[0].holidayFlag/1==1 }" >
{
{
day.monthDay }}
</p>
</div>
</div>
</div>
<!-- <div class="dates-bg">
<div class="week-row" v-for="week in currentDates">
<div class="day-cell" v-for="day in week"
:class="{
'today' : day.isToday,
'not-cur-month' : !day.isCurMonth}">
<p v-if="day.events.length == 0" class="day-number">{
{
day.monthDay}}</p>
</div>
</div>
</div> -->
<!-- full events when click show more -->
<div
class="more-events"
v-show="showMore"
:style="{ left: morePos.left + 'px', top: morePos.top + 'px' }"
>
<div class="more-header">
<span class="title">{
{
moreTitle(selectDay.date) }}</span>
<span class="close" @click.stop="showMore = false">x</span>
</div>
<div class="more-body">
<ul class="body-list">
<li
v-for="(event, index) in selectDay.events"
:key="index"
:id='index'
v-show="event.isShow"
class="body-item"
@click="eventClick(event, $event)"
>
{
{
eventTitle}}
</li>
</ul>
</div>
</div>
<slot name="body-card"> </slot>
</div>
</div>
</template>
<script type="text/babel">
import dateFunc from "./dateFunc";
export default {
props: {
currentDate: {
},
events: {
type: Array,
},
weekNames: {
type: Array,
default: [],
},
monthNames: {
},
firstDay: {
},
},
watch: {
},
created() {
// setTimeout(() => {
// }, 1000)
this.handleEvents()
// this.events = events
},
data() {
return {
// weekNames : DAY_NAMES,
weekMask: [1, 2, 3, 4, 5, 6, 7],
// events : [],
isLismit: true,
eventLimit: 1,
showMore: false,
morePos: {
top: 0,
left: 0,
},
selectDay: {
},
eventTitle: "休",
selectedDay: "",
};
},
watch: {
weekNames(val) {
console.log("watch weekNames", val);
},
events(newVal, oldVal) {
if (newVal.length > 0) {
this.handleEvents()
}
},
},
computed: {
currentDates() {
return this.getCalendar();
},
},
methods: {
handleEvents() {
this.events.forEach((item, index) => {
item._id = item.id || index;
(item.start = item.holidayDate),
(item.end = item.start || item.holidayDate);
});
// console.log(this.events)
},
isBegin(event, date, index) {
// console.log(event)
let st = new Date(event.start);
if (index == 0 || st.toDateString() == date.toDateString()) {
if(event.holidayFlag/1==0){
return this.eventTitle;
}else if(event.holidayFlag/1==1){
return "班"
}
}
return " ";
},
moreTitle(date) {
let dt = new Date(date);
return (
this.weekNames[dt.getDay()] +
", " +
this.monthNames[dt.getMonth()] +
dt.getDate()
);
},
classNames(cssClass) {
// console.log(cssClass)
if (!cssClass) return "";
// string
if (typeof cssClass == "string") return cssClass;
// Array
if (Array.isArray(cssClass)) return cssClass.join(" ");
// else
return "";
},
getCalendar() {
// calculate 2d-array of each month
// first day of this month
let now = new Date(); // today
let current = new Date(this.currentDate);
let startDate = dateFunc.getStartDate(current); // 1st day of this month
let curWeekDay = startDate.getDay();
// begin date of this table may be some day of last month
let diff = parseInt(this.firstDay) - curWeekDay;
diff = diff > 0 ? diff - 7 : diff;
startDate.setDate(startDate.getDate() + diff);
let calendar = [];
for (let perWeek = 0; perWeek < 6; perWeek++) {
let week = [];
for (let perDay = 0; perDay < 7; perDay++) {
week.push({
monthDay: startDate.getDate(),
isToday: now.toDateString() == startDate.toDateString(),
isCurMonth: startDate.getMonth() == current.getMonth(),
weekDay: perDay,
date: new Date(startDate),
events: this.slotEvents(startDate),
});
startDate.setDate(startDate.getDate() + 1);
// if (startDate.toDateString() == endDate.toDateString()) {
// isFinal = true
// break
// }
}
calendar.push(week);
}
return calendar;
},
slotEvents(date) {
// find all events start from this date
let cellIndexArr = [];
let thisDayEvents = this.events.filter((day) => {
let dt = new Date(day.start);
let st = new Date(dt.getFullYear(), dt.getMonth(), dt.getDate());
let ed = day.end ? new Date(day.end) : st;
// console.log('slotEvt', st, ed, date)
return date >= st && date <= ed;
});
// sort by duration
thisDayEvents.sort((a, b) => {
if (!a.cellIndex) return 1;
if (!b.cellIndex) return -1;
return a.cellIndex - b.cellIndex;
});
// mark cellIndex and place holder
for (let i = 0; i < thisDayEvents.length; i++) {
thisDayEvents[i].cellIndex = thisDayEvents[i].cellIndex || i + 1;
thisDayEvents[i].isShow = true;
if (thisDayEvents[i].cellIndex == i + 1 || i > 2) continue;
thisDayEvents.splice(i, 0, {
title: "holder",
cellIndex: i + 1,
start: dateFunc.format(date, "yyyy-MM-dd"),
end: dateFunc.format(date, "yyyy-MM-dd"),
isShow: false,
});
}
return thisDayEvents;
},
isStart(eventDate, date) {
let st = new Date(eventDate);
return st.toDateString() == date.toDateString();
},
isEnd(eventDate, date) {
let ed = new Date(eventDate);
return ed.toDateString() == date.toDateString();
},
selectThisDay(day, jsEvent) {
this.selectDay = day;
this.showMore = true;
this.morePos = this.computePos(event.target);
this.morePos.top -= 100;
let events = day.events.filter((item) => {
return item.isShow == true;
});
this.$emit("moreclick", day.date, events, jsEvent);
},
computePos(target) {
let eventRect = target.getBoundingClientRect();
let pageRect = this.$refs.dates.getBoundingClientRect();
return {
left: eventRect.left - pageRect.left,
top: eventRect.top + eventRect.height - pageRect.top,
};
},
dayClick(day, event) {
this.$emit("dayclick", day, event);
},
eventClick(date, event, jsEvent) {
// console.log(date,event)
// if (!event.isShow) {
// return
// }
// jsEvent.target.classList.add("clickDay");
this.selectedDay = date;
jsEvent.stopPropagation();
let pos = this.computePos(jsEvent.target);
this.$emit("eventclick", date, event, jsEvent, pos);
},
},
};
</script>
<style lang="scss">
.full-calendar-body {
margin-top: 20px;
.weeks {
height: 30px;
line-height: 30px;
display: flex;
border-top: 1px solid #dfe6ec;
border-bottom: 1px solid #dfe6ec;
border-left: 1px solid #dfe6ec;
.week {
flex: 1;
text-align: center;
border-right: 1px solid #dfe6ec;
}
}
.dates {
position: relative;
.week-row {
// width: 100%;
// position:absolute;
border-left: 1px solid #dfe6ec;
display: flex;
.day-cell {
flex: 1;
min-height: 90px;
padding: 4px;
border-right: 1px solid #dfe6ec;
border-bottom: 1px solid #dfe6ec;
.day-number {
text-align: center;
font-size: 20px;
font-weight: bold;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
&.today {
background-color: #fcf8e3;
}
&.not-cur-month {
.day-number {
color: rgba(0, 0, 0, 0.24);
}
}
}
}
.dates-events {
// position:absolute;
position: relative;
top: 0;
left: 0;
z-index: 1;
width: 100%;
border-left: 1px solid #dfe6ec;
.events-week {
display: flex;
border-bottom: 1px solid #dfe6ec;
.events-day:hover {
background-color: rgba(102, 153, 255, 0.1);
}
.events-day {
cursor: pointer;
flex: 1;
min-height: 90px;
overflow: hidden;
text-overflow: ellipsis;
border-right: 1px solid #dfe6ec;
position: relative;
&.eventBg {
background-color: #f5f5f5;
}
&.clickDay {
background-color: rgba(102, 153, 255, 0.2);
}
.day-number {
text-align: center;
font-size: 20px;
font-weight: bold;
height: 100%;
margin-top: -30px;
display: flex;
justify-content: center;
align-items: center;
&.eventDay {
color:#e02d2d;
}
&.iswork{
color:#000;
}
}
&.today {
background-color: #fcf8e3;
}
&.not-cur-month {
pointer-events: none;
.day-number {
color: rgba(0, 0, 0, 0.24);
}
}
.event-box {
height: 30px;
.event-item {
cursor: pointer;
text-align: center;
font-size: 18px;
font-weight: bold;
background-color: #f43;
margin-bottom: 2px;
color: #fff;
// padding: 2px 5px;
height: 100%;
line-height: 30px;
width:30px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
&.is-start {
margin-left: 4px;
// border-top-left-radius:4px;
// border-bottom-left-radius:4px;
}
&.is-end {
margin-right: 4px;
// border-top-right-radius:4px;
// border-bottom-right-radius:4px;
}
&.is-opacity {
opacity: 0;
}
&.is-work{
background-color: #969799;
span{
color:#999;
}
}
span{
position: absolute;
bottom: 5px;
left: 0;
right: 0;
margin: auto;
color:#e02d2d;
font-size: 14px;
}
}
.more-link {
cursor: pointer;
// text-align: right;
padding-left: 8px;
padding-right: 2px;
color: rgba(0, 0, 0, 0.38);
font-size: 14px;
}
}
}
}
}
.more-events {
// position:absolute;
position: relative;
width: 150px;
z-index: 2;
border: 1px solid #eee;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15);
.more-header {
background-color: #eee;
padding: 5px;
display: flex;
align-items: center;
font-size: 14px;
.title {
flex: 1;
}
.close {
margin-right: 2px;
cursor: pointer;
font-size: 16px;
}
}
.more-body {
height: 140px;
overflow: hidden;
.body-list {
height: 120px;
padding: 5px;
overflow: auto;
background-color: #fff;
.body-item {
cursor: pointer;
font-size: 12px;
background-color: #c7e6fd;
margin-bottom: 2px;
color: rgba(0, 0, 0, 0.87);
padding: 0 0 0 4px;
height: 18px;
line-height: 18px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}
}
}
}
}
</style>
components/vue-fullcalendar/components/header.vue
//components/vue-fullcalendar/components/header.vue
<template>
<div class="full-calendar-header">
<div class="header-left">
<slot name="header-left">
</slot>
</div>
<div class="header-center">
<!-- <span class="prev-month" @click.stop="goPrev">{
{
leftArrow}}</span>
<span class="title">{
{
title}}</span>
<span class="next-month" @click.stop="goNext">{
{
rightArrow}}</span> -->
<el-date-picker
v-model="nowMonth"
type="month"
placeholder="选择月"
value-format="yyyy-MM"
:clearable = "false"
@change="changeMonthDay"
style="font-size: 16px;font-weight: bold;">
</el-date-picker>
<el-button class="to-today" type="primary" plain @click="toDate">本月</el-button>
</div>
<div class="header-right">
<slot name="header-right">
</slot>
</div>
</div>
</template>
<script type="text/babel">
import dateFunc from './dateFunc'
export default {
created () {
this.dispatchEvent()
},
props : {
currentDate : {
},
titleFormat : {
},
firstDay : {
},
monthNames : {
}
},
data () {
return {
title : '',
leftArrow : '<',
rightArrow : '>',
headDate : new Date(),
nowMonth : dateFunc.format(new Date(), 'yyyy-MM')
}
},
watch : {
currentDate (val) {
if (!val) return
this.headDate = val
// this.headDate = JSON.parse(JSON.stringify(val))
}
},
methods : {
toDate() {
this.headDate = new Date()
this.nowMonth = new Date()
this.dispatchEvent()
},
goPrev () {
this.headDate = this.changeMonth(this.headDate, -1)
this.dispatchEvent()
},
goNext () {
this.headDate = this.changeMonth(this.headDate, 1)
this.dispatchEvent()
},
changeMonth (date, num) {
let dt = new Date(date)
return new Date(dt.setMonth(dt.getMonth() + num))
},
dispatchEvent() {
this.title = dateFunc.format(this.headDate, this.titleFormat, this.monthNames)
let startDate = dateFunc.getStartDate(this.headDate)
let curWeekDay = startDate.getDay()
// 1st day of this monthView
let diff = parseInt(this.firstDay) - curWeekDay
if (diff) diff -= 7
startDate.setDate(startDate.getDate() + diff)
// the month view is 6*7
let endDate = dateFunc.changeDay(startDate, 41)
// 1st day of current month
let currentDate = dateFunc.getStartDate(this.headDate)
this.$emit('change',
dateFunc.format(startDate, 'yyyy-MM-dd'),
dateFunc.format(endDate, 'yyyy-MM-dd'),
dateFunc.format(currentDate,'yyyy-MM-dd'),
this.headDate
)
},
changeMonthDay(value) {
this.headDate = new Date(value);
this.dispatchEvent()
}
}
}
</script>
<style lang="scss">
.full-calendar-header{
display: flex;
align-items: center;
.header-left,.header-right{
flex:1;
}
.header-center{
flex:3;
text-align:center;
font-size:18px;
.to-today{
margin-left: 30px;
}
.title{
margin: 0 10px;
}
.prev-month,.next-month{
cursor: pointer;
}
}
}
</style>
components/vue-fullcalendar/components/dateFunc.js
//components/vue-fullcalendar/components/dateFunc.js
var shortMonth = [
'Jan',
'Feb',
'Mar',
'Apr',
'May',
'Jun',
'Jul',
'Aug',
'Sep',
'Oct',
'Nov',
'Dec'
]
var defMonthNames = [
'January',
'February',
'March',
'April',
'May',
'June',
'July',
'August',
'September',
'October',
'November',
'December'
]
let dateFunc = {
getDuration (date) {
// how many days of this month
let dt = new Date(date)
var month = dt.getMonth()
dt.setMonth(dt.getMonth() + 1)
dt.setDate(0);
return dt.getDate()
},
changeDay (date, num) {
let dt = new Date(date)
return new Date(dt.setDate(dt.getDate()+num))
},
getStartDate(date) {
// return first day of this month
return new Date(date.getFullYear(), date.getMonth(), 1)
},
getEndDate (date) {
// get last day of this month
let dt = new Date(date.getFullYear(),date.getMonth()+1,1) // 1st day of next month
return new Date(dt.setDate(dt.getDate()-1)) // last day of this month
},
format (date, format, monthNames) {
monthNames = monthNames || defMonthNames
if (typeof date === 'string') {
date = new Date(date.replace(/-/g, '/'))
} else {
date = new Date(date)
}
var map = {
'M' : date.getMonth() + 1,
'd' : date.getDate(),
'h' : date.getHours(),
'm' : date.getMinutes(),
's' : date.getSeconds(),
'q' : Math.floor((date.getMonth() + 3) / 3),
'S' : date.getMilliseconds()
}
format = format.replace(/([yMdhmsqS])+/g, (all, t) => {
var v = map[t]
if (v !== undefined) {
if (all === 'MMMM') {
return monthNames[v - 1]
}
if (all === 'MMM') {
return shortMonth[v - 1]
}
if (all.length > 1) {
v = '0' + v
v = v.substr(v.length - 2)
}
return v
} else if (t === 'y') {
return String(date.getFullYear()).substr(4 - all.length)
}
return all
})
return format
}
}
export default dateFunc
components/vue-fullcalendar/components/eventCard.vue
其实这里面没东西啦
<template>
</template>
<script type="text/javascript"></script>
补充:有人说没有parseTime的方法,现在补充一下,可以挂在到全局,也可单独写个moudle,随你心意
export function parseTime (time, pattern) {
if (arguments.length === 0 || !time) {
return null
}
const format = pattern || '{y}-{m}-{d} {h}:{i}:{s}'
let date
if (typeof time === 'object') {
date = time
} else {
if ((typeof time === 'string') && (/^[0-9]+$/.test(time))) {
time = parseInt(time)
} else if (typeof time === 'string') {
time = time.replace(new RegExp(/-/gm), '/')
}
if ((typeof time === 'number') && (time.toString().length === 10)) {
time = time * 1000
}
date = new Date(time)
}
const formatObj = {
y: date.getFullYear(),
m: date.getMonth() + 1,
d: date.getDate(),
h: date.getHours(),
i: date.getMinutes(),
s: date.getSeconds(),
a: date.getDay()
}
const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
let value = formatObj[key]
// Note: getDay() returns 0 on Sunday
if (key === 'a') {
return ['日', '一', '二', '三', '四', '五', '六'][value] }
if (result.length > 0 && value < 10) {
value = '0' + value
}
return value || 0
})
return time_str
}