Initial commit
This commit is contained in:
130
app/components/datepicker/Datepicker.vue
Normal file
130
app/components/datepicker/Datepicker.vue
Normal file
@@ -0,0 +1,130 @@
|
||||
<template>
|
||||
<div class="control has-icons-left" :id="docid">
|
||||
<div :class="`dropdown ${pos || ''} ${focused ? 'is-active' : ''}`" style="width: 100%">
|
||||
<div class="dropdown-trigger" style="width: 100%;">
|
||||
<input :disabled="disabled" :class="`input ${error? 'is-danger' : ''} ${disabled? 'has-text-dark' : ''}`" type="text" placeholder="DD/MM/YYYY"
|
||||
maxlength="10" @focus="setFocus" @blur="lostFocus" @keyup.enter="pressEnter" @keyup="checkDate" v-model="show" />
|
||||
</div>
|
||||
<div class="dropdown-menu" role="menu" @click="doClick()">
|
||||
<div class="dropdown-content">
|
||||
<PickDay v-bind="{ date, maxdate }" @date="selectDate"></PickDay>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<span class="icon is-left">
|
||||
<SvgIcon v-bind="{name: 'calendar.svg', type: 'gray', size: 21}"></SvgIcon>
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
props: ['record', 'attr', 'position', 'mindate', 'maxdate', 'disabled'],
|
||||
data() {
|
||||
return {
|
||||
date: undefined,
|
||||
show: undefined,
|
||||
error: false,
|
||||
focused: false,
|
||||
docid: this.$id(),
|
||||
count1: 0,
|
||||
count2: 0,
|
||||
pos: undefined
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getPos()
|
||||
if(this.record) {
|
||||
this.date = this.record[this.attr]? this.$copy(this.record[this.attr]) : undefined
|
||||
if(this.date) this.show = this.$dayjs(this.date).format('DD/MM/YYYY')
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
record: function(newVal) {
|
||||
if(this.record) {
|
||||
this.date = this.record[this.attr]? this.$copy(this.record[this.attr]) : undefined
|
||||
if(this.date) this.show = this.$dayjs(this.date).format('DD/MM/YYYY')
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
pressEnter() {
|
||||
this.checkDate()
|
||||
if(!this.error) this.focused = false
|
||||
},
|
||||
setFocus() {
|
||||
this.focused = true
|
||||
this.count1 = 0
|
||||
this.count2 = 0
|
||||
},
|
||||
lostFocus() {
|
||||
let self = this
|
||||
setTimeout(()=>{
|
||||
if(self.focused && self.count1===0) self.focused = false
|
||||
}, 200)
|
||||
},
|
||||
processEvent(event) {
|
||||
var doc = document.getElementById(this.docid)
|
||||
if(!doc) return
|
||||
this.count2 += 1
|
||||
var isClickInside = false
|
||||
isClickInside = doc.contains(event.target);
|
||||
if(!isClickInside && this.focused) {
|
||||
if(this.count2-1!==this.count1) {
|
||||
this.focused = false
|
||||
this.count1 = 0
|
||||
this.count2 = 0
|
||||
}
|
||||
}
|
||||
},
|
||||
doClick() {
|
||||
this.count1 += 1
|
||||
},
|
||||
selectDate(v) {
|
||||
this.date = v
|
||||
this.show = this.$dayjs(v).format('DD/MM/YYYY')
|
||||
this.$emit('date', this.date)
|
||||
if(this.focused) this.focused = false
|
||||
this.count1 = 0
|
||||
this.count2 = 0
|
||||
},
|
||||
getDate(value) {
|
||||
let v = value.replace(/\D/g,'').slice(0, 10);
|
||||
if (v.length >= 5) {
|
||||
return `${v.slice(0,2)}/${v.slice(2,4)}/${v.slice(4)}`;
|
||||
}
|
||||
else if (v.length >= 3) {
|
||||
return `${v.slice(0,2)}/${v.slice(2)}`;
|
||||
}
|
||||
return v
|
||||
},
|
||||
checkDate() {
|
||||
if(!this.focused) this.setFocus()
|
||||
this.error = false
|
||||
this.date = undefined
|
||||
if(this.$empty(this.show)) return this.$emit('date', null)
|
||||
this.show = this.getDate(this.show)
|
||||
let val = `${this.show.substring(6,10)}-${this.show.substring(3,5)}-${this.show.substring(0,2)}`
|
||||
if(this.$dayjs(val, "YYYY-MM-DD", true).isValid()) {
|
||||
this.date = val
|
||||
this.$emit('date', this.date)
|
||||
} else this.error = true
|
||||
},
|
||||
getPos() {
|
||||
switch(this.position) {
|
||||
case 'is-top-left':
|
||||
this.pos = 'is-up is-left'
|
||||
break;
|
||||
case 'is-top-right':
|
||||
this.pos = 'is-up is-right'
|
||||
break;
|
||||
case 'is-bottom-left':
|
||||
this.pos = 'is-left'
|
||||
break;
|
||||
case 'is-bottom-right':
|
||||
this.pos = 'is-right'
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
185
app/components/datepicker/EventDetail.vue
Normal file
185
app/components/datepicker/EventDetail.vue
Normal file
@@ -0,0 +1,185 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="field is-grouped mb-4 border-bottom" v-if="1<0">
|
||||
<div class="control pl-2" v-if="mode!=='simple'">
|
||||
<a class="mr-1" @click="previousYear()">
|
||||
<SvgIcon v-bind="{name: 'doubleleft.svg', type: 'gray', size: 18}"></SvgIcon>
|
||||
</a>
|
||||
<a @click="previousMonth()" v-if="type==='days'">
|
||||
<SvgIcon v-bind="{name: 'left1.svg', type: 'gray', size: 18}"></SvgIcon>
|
||||
</a>
|
||||
</div>
|
||||
<div class="control is-expanded has-text-centered">
|
||||
<span class="fsb-16 hyperlink mr-3" @click="type='months'" v-if="type==='days'">{{`Tháng ${month}`}}</span>
|
||||
<span class="fsb-16 hyperlink" @click="type='years'">{{ caption || year }}</span>
|
||||
</div>
|
||||
<div class="control pr-2" v-if="mode!=='simple'">
|
||||
<a class="mr-1" @click="nextMonth()" v-if="type==='days'">
|
||||
<SvgIcon v-bind="{name: 'right.svg', type: 'gray', size: 18}"></SvgIcon>
|
||||
</a>
|
||||
<a @click="nextYear()">
|
||||
<SvgIcon v-bind="{name: 'doubleright.svg', type: 'gray', size: 18}"></SvgIcon>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="type==='days'">
|
||||
<div :class="`columns mx-0 ${i===weeks.length-1? 'mb-1' : ''}`" v-for="(v,i) in weeks" :key="i">
|
||||
<div class="column px-3 py-1 has-text-centered" v-for="(m,h) in v.dates" :key="h" style="min-height: 100px;"
|
||||
:style="`border-right: 1px solid #DCDCDC; border-bottom: 1px solid #DCDCDC; ${(viewport>1 && h===0 || viewport===1)? 'border-left: 1px solid #DCDCDC;' : ''}
|
||||
${i===0? 'border-top: 1px solid #DCDCDC;' : ''}`">
|
||||
<p class="mb-1" v-if="i===0"><b>{{ $find(dateOfWeek, {id: h}).text}}</b></p>
|
||||
<span class="has-background-primary has-text-white px-1 py-1" v-if="m.date===today">{{ m.dayPrint }}</span>
|
||||
<span v-else>{{m.dayPrint}}</span>
|
||||
<div class="has-text-left fs-15 mt-1" v-if="m.event && m.currentMonth===m.mothCondition">
|
||||
<p :class="`pt-1 ${j===m.event.length-1? '' : 'border-bottom'}`" v-for="(h,j) in m.event">
|
||||
<SvgIcon v-bind="{name: h.icon, type: h.color, size: 16}"></SvgIcon>
|
||||
<a class="ml-3" @click="openEvent(h)">{{ h.text }}</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Modal @close="showmodal=undefined" v-bind="showmodal" v-if="showmodal"></Modal>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
props: ['date', 'events', 'mode', 'vyear', 'vmonth'],
|
||||
data() {
|
||||
return {
|
||||
dates: [],
|
||||
dateOfWeek: [{id: 0, text: "CN"}, {id: 1, text: "T2"}, {id: 2, text: "T3"}, {id: 3, text: "T4"},
|
||||
{id: 4, text: "T5",}, {id: 5, text: "T6"}, {id: 6, text: "T7"}],
|
||||
weeks: [],
|
||||
today: this.$dayjs().format('YYYY/MM/DD'),
|
||||
year: undefined,
|
||||
month: undefined,
|
||||
type: 'days',
|
||||
caption: undefined,
|
||||
action: undefined,
|
||||
curdate: undefined,
|
||||
showmodal: undefined,
|
||||
viewport: 5
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.showDate()
|
||||
},
|
||||
watch: {
|
||||
date: function(newVal) {
|
||||
if(newVal) this.showDate()
|
||||
},
|
||||
vmonth: function(newVal) {
|
||||
this.showDate()
|
||||
},
|
||||
events: function(newVal) {
|
||||
this.showDate()
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async openEvent(event) {
|
||||
let row = await this.$getdata('sale', {id: event.sale}, undefined, true)
|
||||
this.showmodal = {title: 'Bán hàng', height: '500px', width: '90%', component: 'sale/Sale', vbind: {row: row, highlight: event.id}}
|
||||
},
|
||||
compiledComponent(value) {
|
||||
return {
|
||||
template: `${value}`
|
||||
}
|
||||
},
|
||||
showDate() {
|
||||
this.curdate = this.date? this.date.replaceAll('-', '/') : undefined
|
||||
this.year = this.$dayjs(this.curdate || this.today).year()
|
||||
this.month = this.$dayjs(this.curdate || this.today).month() + 1
|
||||
if(this.vyear) this.year = this.$copy(this.vyear)
|
||||
if(this.vmonth) this.month = this.$copy(this.vmonth)
|
||||
this.getDates()
|
||||
},
|
||||
chooseToday() {
|
||||
this.$emit('date', this.today.replaceAll('/', '-'))
|
||||
this.year = this.$dayjs(this.today).year()
|
||||
this.month = this.$dayjs(this.today).month() + 1
|
||||
this.getDates()
|
||||
},
|
||||
changeCaption(v) {
|
||||
this.caption = v
|
||||
},
|
||||
selectMonth(v) {
|
||||
this.month = v
|
||||
this.getDates()
|
||||
this.type = 'days'
|
||||
},
|
||||
selectYear(v) {
|
||||
this.year = v
|
||||
this.getDates()
|
||||
this.type = 'days'
|
||||
},
|
||||
getDates() {
|
||||
this.caption = undefined
|
||||
this.dates = this.allDaysInMonth(this.year, this.month)
|
||||
this.dates.map(v=>{
|
||||
let event = this.events? this.$filter(this.events, {isodate: v.date}) : undefined
|
||||
if(event.length>0) v.event = event
|
||||
})
|
||||
this.weeks = this.$unique(this.dates, ['week']).map(v=>{return {week: v.week}})
|
||||
this.weeks.map(v=>{
|
||||
v.dates = this.dates.filter(x=>x.week===v.week)
|
||||
})
|
||||
},
|
||||
nextMonth() {
|
||||
let month = this.month + 1
|
||||
if(month>12) {
|
||||
month = 1
|
||||
this.year += 1
|
||||
}
|
||||
this.month = month
|
||||
this.getDates()
|
||||
},
|
||||
previousMonth() {
|
||||
let month = this.month - 1
|
||||
if(month===0) {
|
||||
month = 12
|
||||
this.year -= 1
|
||||
}
|
||||
this.month = month
|
||||
this.getDates()
|
||||
},
|
||||
nextYear() {
|
||||
if(this.type==='years') return this.action = {name: 'next', id: this.$id()}
|
||||
this.year += 1
|
||||
this.getDates()
|
||||
},
|
||||
previousYear() {
|
||||
if(this.type==='years') return this.action = {name: 'previous', id: this.$id()}
|
||||
this.year -= 1
|
||||
this.getDates()
|
||||
},
|
||||
choose(m) {
|
||||
this.$emit('date', m.date.replaceAll('/', '-'))
|
||||
},
|
||||
createDate(v, x, y) {
|
||||
return v + '/' + (x<10? '0' + x.toString() : x.toString()) + '/' + (y<10? '0' + y.toString() : y.toString())
|
||||
},
|
||||
allDaysInMonth(year, month) {
|
||||
let days = Array.from({length: this.$dayjs(this.createDate(year, month, 1)).daysInMonth()}, (_, i) => i + 1)
|
||||
let arr = []
|
||||
days.map(v=>{
|
||||
for (let i = 0; i < 7; i++) {
|
||||
let thedate = this.$dayjs(this.createDate(year, month, v)).weekday(i)
|
||||
let date = this.$dayjs(new Date(thedate.$d)).format("YYYY/MM/DD")
|
||||
let dayPrint = this.$dayjs(new Date(thedate.$d)).format("DD")
|
||||
let mothCondition = this.$dayjs(date).month() +1
|
||||
let currentMonth = month
|
||||
let found = arr.find(x=>x.date===date)
|
||||
if(!found) {
|
||||
let dayOfWeek = this.$dayjs(date).day()
|
||||
let week = this.$dayjs(date).week()
|
||||
let ele = {date: date, week: week, day: v, dayOfWeek: dayOfWeek, dayPrint: dayPrint, mothCondition: mothCondition, currentMonth: currentMonth}
|
||||
arr.push(ele)
|
||||
}
|
||||
}
|
||||
})
|
||||
return arr
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
19
app/components/datepicker/EventMultiMonth.vue
Normal file
19
app/components/datepicker/EventMultiMonth.vue
Normal file
@@ -0,0 +1,19 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="columns is-multiline mx-0">
|
||||
<div class="column is-4" v-for="v in months">
|
||||
<EventSummary v-bind="{events: events, mode: 'simple', vyear: v.year, vmonth: v.month}"></EventSummary>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import EventSummary from '@/components/datepicker/EventSummary'
|
||||
export default {
|
||||
components: {
|
||||
EventSummary
|
||||
//EventSummary: () => import('@/components/datepicker/EventSummary')
|
||||
},
|
||||
props: ['events', 'months']
|
||||
}
|
||||
</script>
|
||||
52
app/components/datepicker/EventOneMonth.vue
Normal file
52
app/components/datepicker/EventOneMonth.vue
Normal file
@@ -0,0 +1,52 @@
|
||||
<template>
|
||||
<div class="columns mx-0">
|
||||
<div class="column is-narrow" v-if="1<0">
|
||||
<EventSummary></EventSummary>
|
||||
</div>
|
||||
<div class="column">
|
||||
<div class="mb-4">
|
||||
<span class="fsb-17 mr-4">{{ `T${vmonth}/${vyear}` }}</span>
|
||||
<a class="mr-2" @click="previous()"><SvgIcon v-bind="{name: 'left1.svg', type: 'dark', size: 18}"></SvgIcon></a>
|
||||
<a class="mr-3" @click="next()"><SvgIcon v-bind="{name: 'right.svg', type: 'dark', size: 18}"></SvgIcon></a>
|
||||
<a @click="refresh()"><SvgIcon v-bind="{name: 'refresh.svg', type: 'dark', size: 18}"></SvgIcon></a>
|
||||
</div>
|
||||
<EventDetail v-bind="{events: events, vyear: vyear, vmonth: vmonth}"></EventDetail>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import EventSummary from '@/components/datepicker/EventSummary'
|
||||
import EventDetail from '@/components/datepicker/EventDetail'
|
||||
</script>
|
||||
<script>
|
||||
export default {
|
||||
props: ['events', 'year', 'month'],
|
||||
data() {
|
||||
return {
|
||||
vyear: this.year? this.$copy(this.year) : undefined,
|
||||
vmonth: this.month? this.$copy(this.month) : undefined
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
next() {
|
||||
let month = this.vmonth + 1
|
||||
if(month>12) {
|
||||
month = 1
|
||||
this.vyear += 1
|
||||
}
|
||||
this.vmonth = month
|
||||
},
|
||||
previous() {
|
||||
let month = this.vmonth - 1
|
||||
if(month===0) {
|
||||
month = 12
|
||||
this.vyear -= 1
|
||||
}
|
||||
this.vmonth = month
|
||||
},
|
||||
refresh() {
|
||||
this.$emit('refresh')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
189
app/components/datepicker/EventSummary.vue
Normal file
189
app/components/datepicker/EventSummary.vue
Normal file
@@ -0,0 +1,189 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="field is-grouped mb-4 border-bottom">
|
||||
<div class="control pl-2" v-if="mode!=='simple'">
|
||||
<a class="mr-1" @click="previousYear()">
|
||||
<SvgIcon v-bind="{name: 'doubleleft.svg', type: 'gray', size: 18}"></SvgIcon>
|
||||
</a>
|
||||
<a @click="previousMonth()" v-if="type==='days'">
|
||||
<SvgIcon v-bind="{name: 'left1.svg', type: 'gray', size: 18}"></SvgIcon>
|
||||
</a>
|
||||
</div>
|
||||
<div class="control is-expanded has-text-centered">
|
||||
<span class="fsb-16 hyperlink mr-3" @click="mode==='simple'? false : type='PickMonth'" v-if="type==='days'">{{`Tháng ${month}`}}</span>
|
||||
<span class="fsb-16 hyperlink" @click="mode==='simple'? false : type='PickYear'">{{ caption || year }}</span>
|
||||
</div>
|
||||
<div class="control pr-2" v-if="mode!=='simple'">
|
||||
<a class="mr-1" @click="nextMonth()" v-if="type==='days'">
|
||||
<SvgIcon v-bind="{name: 'right.svg', type: 'gray', size: 18}"></SvgIcon>
|
||||
</a>
|
||||
<a @click="nextYear()">
|
||||
<SvgIcon v-bind="{name: 'doubleright.svg', type: 'gray', size: 18}"></SvgIcon>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="type==='days'">
|
||||
<div class="columns is-mobile mx-0">
|
||||
<div class="column px-2 py-1 has-text-grey-dark" v-for="(m,h) in dateOfWeek" :key="h">
|
||||
{{ m.text }}
|
||||
</div>
|
||||
</div>
|
||||
<div :class="`columns is-mobile mx-0 ${i===weeks.length-1? 'mb-1' : ''}`" v-for="(v,i) in weeks" :key="i">
|
||||
<div class="column px-3 fs-14" v-for="(m,h) in v.dates" :key="h" style="padding-top: 1px; padding-bottom: 1px;">
|
||||
<a v-if="m.event && m.currentMonth===m.mothCondition">
|
||||
<Tooltip v-bind="{html: m.event.html, tooltip: m.event.tooltip}"></Tooltip>
|
||||
</a>
|
||||
<span class="has-background-findata has-text-white px-1 py-1" v-else-if="m.date===today">{{ m.dayPrint }}</span>
|
||||
<span v-else>{{m.dayPrint}}</span>
|
||||
</div>
|
||||
</div>
|
||||
<template v-if="mode!=='simple'">
|
||||
<div class="border-bottom"></div>
|
||||
<div class="mt-2">
|
||||
<span class="ml-2 mr-2">Hôm nay: </span>
|
||||
<span class="has-text-primary hyperlink" @click="chooseToday()">{{ $dayjs(today).format('DD/MM/YYYY') }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<div v-else-if="type==='PickMonth'">
|
||||
<PickMonth @month="selectMonth"></PickMonth>
|
||||
</div>
|
||||
<div v-else-if="type==='PickYear'">
|
||||
<PickYear v-bind="{year: year, month: month, action: action}" @year="selectYear" @caption="changeCaption"></PickYear>
|
||||
</div>
|
||||
<Modal @close="showmodal=undefined" v-bind="showmodal" v-if="showmodal"></Modal>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
components: {
|
||||
PickMonth: () => import('@/components/datepicker/PickMonth'),
|
||||
PickYear: () => import('@/components/datepicker/PickYear')
|
||||
},
|
||||
props: ['date', 'events', 'mode', 'vyear', 'vmonth'],
|
||||
data() {
|
||||
return {
|
||||
dates: [],
|
||||
dateOfWeek: [{id: 0, text: "CN"}, {id: 1, text: "T2"}, {id: 2, text: "T3"}, {id: 3, text: "T4"},
|
||||
{id: 4, text: "T5",}, {id: 5, text: "T6"}, {id: 6, text: "T7"}],
|
||||
weeks: [],
|
||||
today: this.$dayjs().format('YYYY/MM/DD'),
|
||||
year: undefined,
|
||||
month: undefined,
|
||||
type: 'days',
|
||||
caption: undefined,
|
||||
action: undefined,
|
||||
curdate: undefined,
|
||||
showmodal: undefined
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.showDate()
|
||||
},
|
||||
watch: {
|
||||
date: function(newVal) {
|
||||
if(newVal) this.showDate()
|
||||
},
|
||||
events: function(newVal) {
|
||||
this.showDate()
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
showDate() {
|
||||
this.curdate = this.date? this.date.replaceAll('-', '/') : undefined
|
||||
this.year = this.$dayjs(this.curdate || this.today).year()
|
||||
this.month = this.$dayjs(this.curdate || this.today).month() + 1
|
||||
if(this.vyear) this.year = this.$copy(this.vyear)
|
||||
if(this.vmonth) this.month = this.$copy(this.vmonth)
|
||||
this.getDates()
|
||||
},
|
||||
chooseToday() {
|
||||
this.$emit('date', this.today.replaceAll('/', '-'))
|
||||
this.year = this.$dayjs(this.today).year()
|
||||
this.month = this.$dayjs(this.today).month() + 1
|
||||
this.getDates()
|
||||
},
|
||||
changeCaption(v) {
|
||||
this.caption = v
|
||||
},
|
||||
selectMonth(v) {
|
||||
this.month = v
|
||||
this.getDates()
|
||||
this.type = 'days'
|
||||
},
|
||||
selectYear(v) {
|
||||
this.year = v
|
||||
this.getDates()
|
||||
this.type = 'days'
|
||||
},
|
||||
getDates() {
|
||||
this.caption = undefined
|
||||
this.dates = this.allDaysInMonth(this.year, this.month)
|
||||
this.dates.map(v=>{
|
||||
let event = this.events? this.$find(this.events, {isodate: v.date}) : undefined
|
||||
if(event) v.event = event
|
||||
})
|
||||
this.weeks = this.$unique(this.dates, ['week']).map(v=>{return {week: v.week}})
|
||||
this.weeks.map(v=>{
|
||||
v.dates = this.dates.filter(x=>x.week===v.week)
|
||||
})
|
||||
},
|
||||
nextMonth() {
|
||||
let month = this.month + 1
|
||||
if(month>12) {
|
||||
month = 1
|
||||
this.year += 1
|
||||
}
|
||||
this.month = month
|
||||
this.getDates()
|
||||
},
|
||||
previousMonth() {
|
||||
let month = this.month - 1
|
||||
if(month===0) {
|
||||
month = 12
|
||||
this.year -= 1
|
||||
}
|
||||
this.month = month
|
||||
this.getDates()
|
||||
},
|
||||
nextYear() {
|
||||
if(this.type==='PickYear') return this.action = {name: 'next', id: this.$id()}
|
||||
this.year += 1
|
||||
this.getDates()
|
||||
},
|
||||
previousYear() {
|
||||
if(this.type==='PickYear') return this.action = {name: 'previous', id: this.$id()}
|
||||
this.year -= 1
|
||||
this.getDates()
|
||||
},
|
||||
choose(m) {
|
||||
this.$emit('date', m.date.replaceAll('/', '-'))
|
||||
},
|
||||
createDate(v, x, y) {
|
||||
return v + '/' + (x<10? '0' + x.toString() : x.toString()) + '/' + (y<10? '0' + y.toString() : y.toString())
|
||||
},
|
||||
allDaysInMonth(year, month) {
|
||||
let days = Array.from({length: this.$dayjs(this.createDate(year, month, 1)).daysInMonth()}, (_, i) => i + 1)
|
||||
let arr = []
|
||||
days.map(v=>{
|
||||
for (let i = 0; i < 7; i++) {
|
||||
let thedate = this.$dayjs(this.createDate(year, month, v)).weekday(i)
|
||||
let date = this.$dayjs(new Date(thedate.$d)).format("YYYY/MM/DD")
|
||||
let dayPrint = this.$dayjs(new Date(thedate.$d)).format("DD")
|
||||
let mothCondition = this.$dayjs(date).month() +1
|
||||
let currentMonth = month
|
||||
let found = arr.find(x=>x.date===date)
|
||||
if(!found) {
|
||||
let dayOfWeek = this.$dayjs(date).day()
|
||||
let week = this.$dayjs(date).week()
|
||||
let ele = {date: date, week: week, day: v, dayOfWeek: dayOfWeek, dayPrint: dayPrint,
|
||||
mothCondition: mothCondition, currentMonth: currentMonth}
|
||||
arr.push(ele)
|
||||
}
|
||||
}
|
||||
})
|
||||
return arr
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
181
app/components/datepicker/PickDay.vue
Normal file
181
app/components/datepicker/PickDay.vue
Normal file
@@ -0,0 +1,181 @@
|
||||
<template>
|
||||
<div class="p-2" style="width: 300px">
|
||||
<div class="field is-grouped mb-4 border-bottom">
|
||||
<div class="control pl-2">
|
||||
<a class="mr-1" @click="previousYear()">
|
||||
<SvgIcon v-bind="{name: 'doubleleft.svg', type: 'gray', size: 18}"></SvgIcon>
|
||||
</a>
|
||||
<a @click="previousMonth()" v-if="type==='days'">
|
||||
<SvgIcon v-bind="{name: 'left1.svg', type: 'gray', size: 18}"></SvgIcon>
|
||||
</a>
|
||||
</div>
|
||||
<div class="control is-expanded has-text-centered">
|
||||
<a class="fsb-16 mr-2" @click="type='months'" v-if="type==='days'">{{`T${month}`}}</a>
|
||||
<a class="fsb-16" @click="type='years'">{{ caption || year }}</a>
|
||||
</div>
|
||||
<div class="control pr-2">
|
||||
<a class="mr-1" @click="nextMonth()" v-if="type==='days'">
|
||||
<SvgIcon v-bind="{name: 'right.svg', type: 'gray', size: 18}"></SvgIcon>
|
||||
</a>
|
||||
<a @click="nextYear()">
|
||||
<SvgIcon v-bind="{name: 'doubleright.svg', type: 'gray', size: 18}"></SvgIcon>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="type==='days'">
|
||||
<div class="columns is-mobile mx-0 mb-3">
|
||||
<div class="column p-0 has-text-grey-light-dark is-flex is-justify-content-center is-align-items-center" style="height: 32px;" v-for="(m,h) in dateOfWeek" :key="h">
|
||||
{{ m.text }}
|
||||
</div>
|
||||
</div>
|
||||
<div :class="`columns is-mobile mx-0 mb-1 ${i===weeks.length-1? 'mb-1' : ''}`" v-for="(v,i) in weeks" :key="i">
|
||||
<div class="column p-0 is-flex is-justify-content-center is-align-items-center" style="width: 40px; height: 32px" v-for="(m,h) in v.dates" :key="h">
|
||||
<span class="fs-14 has-text-grey-light" v-if="m.disable">
|
||||
{{m.dayPrint}}
|
||||
</span>
|
||||
<a class="fs-14" @click="choose(m)" v-else>
|
||||
<span
|
||||
style="width: 25px; height: 25px; border-radius: 4px"
|
||||
:class="[
|
||||
'p-1 is-flex is-justify-content-center is-align-items-center',
|
||||
{
|
||||
'has-background-primary has-text-white': m.date === curdate,
|
||||
'has-background-light has-text-white': m.date === today,
|
||||
'has-text-grey-light': m.currentMonth !== m.monthCondition
|
||||
}
|
||||
]"
|
||||
>
|
||||
{{ m.dayPrint }}
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="border-bottom"></div>
|
||||
<div class="mt-2">
|
||||
<span class="ml-2">Hôm nay: </span>
|
||||
<a class="has-text-primary" @click="chooseToday()">{{ $dayjs(today).format('DD/MM/YYYY') }}</a>
|
||||
</div>
|
||||
</div>
|
||||
<PickMonth v-else-if="type==='months'" @month="selectMonth"></PickMonth>
|
||||
<PickYear v-else-if="type==='years'" v-bind="{ year, month, action }" @year="selectYear" @caption="changeCaption"></PickYear>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import PickMonth from '@/components/datepicker/PickMonth'
|
||||
import PickYear from '@/components/datepicker/PickYear'
|
||||
const { $id, $dayjs, $unique} = useNuxtApp()
|
||||
const emit = defineEmits(['date'])
|
||||
var props = defineProps({
|
||||
date: String,
|
||||
maxdate: String
|
||||
})
|
||||
var dates = []
|
||||
var dateOfWeek = [{id: 0, text: "CN"}, {id: 1, text: "T2"}, {id: 2, text: "T3"}, {id: 3, text: "T4"},
|
||||
{id: 4, text: "T5",}, {id: 5, text: "T6"}, {id: 6, text: "T7"}]
|
||||
var weeks = ref([])
|
||||
var year= ref(undefined)
|
||||
var month = undefined
|
||||
var type = ref('days')
|
||||
var caption = ref(undefined)
|
||||
var action = ref(undefined)
|
||||
var curdate = undefined
|
||||
var today = new Date()
|
||||
function showDate() {
|
||||
curdate = props.date? props.date.replaceAll('-', '/') : undefined
|
||||
year.value = $dayjs(curdate || today).year()
|
||||
month = $dayjs(curdate || today).month() + 1
|
||||
getDates()
|
||||
}
|
||||
function chooseToday() {
|
||||
emit('date', $dayjs(today).format('YYYY-MM-DD') )//today.replaceAll('/', '-'))
|
||||
year.value = $dayjs(today).year()
|
||||
month = $dayjs(today).month() + 1
|
||||
getDates()
|
||||
}
|
||||
function changeCaption(v) {
|
||||
caption.value = v
|
||||
}
|
||||
function selectMonth(v) {
|
||||
month = v
|
||||
getDates()
|
||||
type.value = 'days'
|
||||
}
|
||||
function selectYear(v) {
|
||||
year.value = v
|
||||
getDates()
|
||||
type.value = 'days'
|
||||
}
|
||||
function getDates() {
|
||||
caption.value = undefined
|
||||
dates = allDaysInMonth(year.value, month)
|
||||
weeks.value = $unique(dates, ['week']).map(v=>{return {week: v.week}})
|
||||
weeks.value.map(v=>{
|
||||
v.dates = dates.filter(x=>x.week===v.week)
|
||||
})
|
||||
}
|
||||
function nextMonth() {
|
||||
month = month + 1
|
||||
if(month>12) {
|
||||
month = 1
|
||||
year.value += 1
|
||||
}
|
||||
getDates()
|
||||
}
|
||||
function previousMonth() {
|
||||
month = month - 1
|
||||
if(month===0) {
|
||||
month = 12
|
||||
year.value -= 1
|
||||
}
|
||||
getDates()
|
||||
}
|
||||
function nextYear() {
|
||||
if(type.value==='years') return action.value = {name: 'next', id: $id()}
|
||||
year.value += 1
|
||||
getDates()
|
||||
}
|
||||
function previousYear() {
|
||||
if(type.value==='years') return action.value = {name: 'previous', id: $id()}
|
||||
year.value -= 1
|
||||
getDates()
|
||||
}
|
||||
function choose(m) {
|
||||
emit('date', m.date.replaceAll('/', '-'))
|
||||
}
|
||||
function createDate(v, x, y) {
|
||||
return v + '/' + (x<10? '0' + x.toString() : x.toString()) + '/' + (y<10? '0' + y.toString() : y.toString())
|
||||
}
|
||||
function allDaysInMonth(year, month) {
|
||||
let days = Array.from({length: $dayjs(createDate(year, month, 1)).daysInMonth()}, (_, i) => i + 1)
|
||||
let arr = []
|
||||
days.map(v=>{
|
||||
for (let i = 0; i < 7; i++) {
|
||||
let thedate = $dayjs(createDate(year, month, v)).weekday(i)
|
||||
let date = $dayjs(new Date(thedate.$d)).format("YYYY/MM/DD")
|
||||
let dayPrint = $dayjs(new Date(thedate.$d)).format("DD")
|
||||
let monthCondition = $dayjs(date).month() +1
|
||||
let currentMonth = month
|
||||
let found = arr.find(x=>x.date===date)
|
||||
if(!found) {
|
||||
let dayOfWeek = $dayjs(date).day()
|
||||
let week = $dayjs(date).week()
|
||||
let disable = false
|
||||
if(props.maxdate? $dayjs(props.maxdate).diff(props.date, 'day')>=0 : false) {
|
||||
if($dayjs(props.maxdate).startOf('day').diff(date, 'day')<0) disable = true
|
||||
}
|
||||
let ele = {date: date, week: week, day: v, dayOfWeek: dayOfWeek, dayPrint: dayPrint, monthCondition: monthCondition,
|
||||
currentMonth: currentMonth, disable: disable}
|
||||
arr.push(ele)
|
||||
}
|
||||
}
|
||||
})
|
||||
return arr
|
||||
}
|
||||
// display
|
||||
showDate()
|
||||
// change date
|
||||
watch(() => props.date, (newVal, oldVal) => {
|
||||
showDate()
|
||||
})
|
||||
|
||||
</script>
|
||||
14
app/components/datepicker/PickMonth.vue
Normal file
14
app/components/datepicker/PickMonth.vue
Normal file
@@ -0,0 +1,14 @@
|
||||
<template>
|
||||
<div class="columns is-mobile is-multiline mx-0">
|
||||
<span class="column has-text-centered is-4 hyperlink fs-14" v-for="v in months" @click="$emit('month', v)">Tháng {{ v }}</span>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
months: [1,2,3,4,5,6,7,8,9,10,11,12]
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
57
app/components/datepicker/PickYear.vue
Normal file
57
app/components/datepicker/PickYear.vue
Normal file
@@ -0,0 +1,57 @@
|
||||
<template>
|
||||
<div class="columns is-mobile is-multiline mx-0">
|
||||
<span
|
||||
v-for="(v,i) in years"
|
||||
class="column is-4 has-text-centered hyperlink fs-14"
|
||||
:class="i===0 || i===11 ? 'has-text-grey-light' : ''"
|
||||
@click="$emit('year', v)">{{ v }}</span>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
props: ['year', 'month', 'action'],
|
||||
data() {
|
||||
return {
|
||||
years: []
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.years = [this.year]
|
||||
for(let i = 1; i < 7; i++) {
|
||||
this.years.push(this.year+i)
|
||||
this.years.push(this.year-i)
|
||||
}
|
||||
this.years.sort(function(a, b) {return a - b;})
|
||||
this.years = this.years.slice(0,12)
|
||||
this.$emit('caption', `${this.years[1]}-${this.years[10]}`)
|
||||
},
|
||||
watch: {
|
||||
action: function(newVal) {
|
||||
if(newVal.name==='next') this.next()
|
||||
if(newVal.name==='previous') this.previous()
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
next() {
|
||||
let year = this.years[this.years.length-1]
|
||||
this.years = []
|
||||
for(let i = 0; i < 12; i++) {
|
||||
this.years.push(year+i)
|
||||
}
|
||||
this.years.sort(function(a, b) {return a - b;})
|
||||
this.years = this.years.slice(0,12)
|
||||
this.$emit('caption', `${this.years[1]}-${this.years[10]}`)
|
||||
},
|
||||
previous() {
|
||||
let year = this.years[0]
|
||||
this.years = []
|
||||
for(let i = 0; i < 12; i++) {
|
||||
this.years.push(year-i)
|
||||
}
|
||||
this.years.sort(function(a, b) {return a - b;})
|
||||
this.years = this.years.slice(0,12)
|
||||
this.$emit('caption', `${this.years[1]}-${this.years[10]}`)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
16
app/components/datepicker/ViewEvent.vue
Normal file
16
app/components/datepicker/ViewEvent.vue
Normal file
@@ -0,0 +1,16 @@
|
||||
<template>
|
||||
<div>
|
||||
<span v-html="row.event.name"></span>
|
||||
<!--<p v-for="v in data">{{ v.text }}</p>-->
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
props: ["row"],
|
||||
data() {
|
||||
return {
|
||||
data: this.row.event.arr,
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
Reference in New Issue
Block a user