增加日历组件
This commit is contained in:
@@ -173,6 +173,8 @@ export default {
|
||||
return this.piechartFn(params.chartProperties, data);
|
||||
} else if (chartType == "widget-text") {
|
||||
return this.widgettext(params.chartProperties, data)
|
||||
} else if (chartType == "widget-calendar") {
|
||||
return this.widgetcalendar(params.chartProperties, data)
|
||||
} else if (chartType == "widget-stackchart") {
|
||||
return this.stackChartFn(params.chartProperties, data)
|
||||
} else if (chartType == "widget-coord") {
|
||||
@@ -285,6 +287,9 @@ export default {
|
||||
}
|
||||
return analysisData;
|
||||
},
|
||||
widgetcalendar (chartProperties, data) {
|
||||
return data
|
||||
},
|
||||
// 坐标系数据解析
|
||||
coordChartFn(chartProperties, data) {
|
||||
const analysisData = {};
|
||||
|
||||
@@ -0,0 +1,223 @@
|
||||
/*
|
||||
* @Descripttion: 日历组件json
|
||||
* @version:
|
||||
* @Author: lishuaiwu
|
||||
* @Date: 2025-06-05 13:44:32
|
||||
*/
|
||||
export const widgetCalendar = {
|
||||
code: 'widget-calendar',
|
||||
type: 'text',
|
||||
tabName: '文本栏',
|
||||
label: '日历',
|
||||
icon: 'iconbiaoge',
|
||||
options: {
|
||||
// 配置
|
||||
setup: [
|
||||
{
|
||||
type: 'el-input-text',
|
||||
label: '图层名称',
|
||||
name: 'layerName',
|
||||
required: false,
|
||||
placeholder: '',
|
||||
value: '日历',
|
||||
},
|
||||
[
|
||||
{
|
||||
name: '日历样式',
|
||||
list: [
|
||||
{
|
||||
type: 'vue-color',
|
||||
label: '边框线颜色',
|
||||
name: 'borderColor',
|
||||
required: false,
|
||||
placeholder: '',
|
||||
value: 'rgb(221, 221, 221)'
|
||||
},
|
||||
{
|
||||
type: 'vue-color',
|
||||
label: '头部背景颜色',
|
||||
name: 'headerBackground',
|
||||
required: false,
|
||||
placeholder: '',
|
||||
value: 'rgb(10, 115, 255)'
|
||||
},
|
||||
{
|
||||
type: 'vue-color',
|
||||
label: '头部文字颜色',
|
||||
name: 'headerTextColor',
|
||||
required: false,
|
||||
placeholder: '',
|
||||
value: 'rgb(255, 255, 255)'
|
||||
},
|
||||
{
|
||||
type: 'vue-color',
|
||||
label: '头部按钮颜色',
|
||||
name: 'headerBtnBackground',
|
||||
required: false,
|
||||
placeholder: '',
|
||||
value: 'rgb(10, 115, 255)'
|
||||
},
|
||||
{
|
||||
type: 'vue-color',
|
||||
label: '头部按钮文字',
|
||||
name: 'headerBtnTextColor',
|
||||
required: false,
|
||||
placeholder: '',
|
||||
value: 'rgb(255, 255, 255)'
|
||||
},
|
||||
{
|
||||
type: 'vue-color',
|
||||
label: '星期背景色',
|
||||
name: 'weekBackground',
|
||||
required: false,
|
||||
placeholder: '',
|
||||
value: 'rgb(10, 39, 50)'
|
||||
},
|
||||
{
|
||||
type: 'vue-color',
|
||||
label: '星期文字颜色',
|
||||
name: 'weekTextColor',
|
||||
required: false,
|
||||
placeholder: '',
|
||||
value: 'rgb(255, 255, 255)'
|
||||
},
|
||||
{
|
||||
type: 'vue-color',
|
||||
label: '日期背景色',
|
||||
name: 'dayBackground',
|
||||
required: false,
|
||||
placeholder: '',
|
||||
value: 'rgb(0, 59, 81)'
|
||||
},
|
||||
{
|
||||
type: 'vue-color',
|
||||
label: '日期文字颜色',
|
||||
name: 'dayTextColor',
|
||||
required: false,
|
||||
placeholder: '',
|
||||
value: 'rgb(255, 255, 255)'
|
||||
},
|
||||
{
|
||||
type: 'vue-color',
|
||||
label: '当日背景色',
|
||||
name: 'todayBackground',
|
||||
required: false,
|
||||
placeholder: '',
|
||||
value: 'rgba(0, 59, 81, .5)'
|
||||
},
|
||||
{
|
||||
type: 'vue-color',
|
||||
label: '当日文字颜色',
|
||||
name: 'todayTextColor',
|
||||
required: false,
|
||||
placeholder: '',
|
||||
value: 'rgb(0, 0, 0)'
|
||||
},
|
||||
{
|
||||
type: 'el-switch',
|
||||
label: '按钮显隐',
|
||||
name: 'isButton',
|
||||
required: false,
|
||||
placeholder: '',
|
||||
value: true,
|
||||
},
|
||||
]
|
||||
}
|
||||
]
|
||||
],
|
||||
data: [
|
||||
{
|
||||
type: 'el-radio-group',
|
||||
label: '数据类型',
|
||||
name: 'dataType',
|
||||
require: false,
|
||||
placeholder: '',
|
||||
selectValue: true,
|
||||
selectOptions: [
|
||||
{
|
||||
code: 'staticData',
|
||||
name: '静态数据',
|
||||
},
|
||||
{
|
||||
code: 'dynamicData',
|
||||
name: '动态数据',
|
||||
},
|
||||
],
|
||||
value: 'staticData',
|
||||
},
|
||||
{
|
||||
type: 'el-input-number',
|
||||
label: '刷新时间(毫秒)',
|
||||
name: 'refreshTime',
|
||||
relactiveDom: 'dataType',
|
||||
relactiveDomValue: 'dynamicData',
|
||||
value: 600000
|
||||
},
|
||||
{
|
||||
type: 'el-button',
|
||||
label: '静态数据',
|
||||
name: 'staticData',
|
||||
required: false,
|
||||
placeholder: '',
|
||||
relactiveDom: 'dataType',
|
||||
relactiveDomValue: 'staticData',
|
||||
value: [
|
||||
{
|
||||
"date": "2025-06-01",
|
||||
"data": '2单'
|
||||
},
|
||||
{
|
||||
"date": "2025-06-02",
|
||||
"data": '10单'
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'dycustComponents',
|
||||
label: '',
|
||||
name: 'dynamicData',
|
||||
required: false,
|
||||
placeholder: '',
|
||||
relactiveDom: 'dataType',
|
||||
relactiveDomValue: 'dynamicData',
|
||||
chartType: 'widget-calendar',
|
||||
dictKey: 'TEXT_PROPERTIES',
|
||||
value: '',
|
||||
}
|
||||
],
|
||||
position: [
|
||||
{
|
||||
type: 'el-input-number',
|
||||
label: '左边距',
|
||||
name: 'left',
|
||||
required: false,
|
||||
placeholder: '',
|
||||
value: 0,
|
||||
},
|
||||
{
|
||||
type: 'el-input-number',
|
||||
label: '上边距',
|
||||
name: 'top',
|
||||
required: false,
|
||||
placeholder: '',
|
||||
value: 0,
|
||||
},
|
||||
{
|
||||
type: 'el-input-number',
|
||||
label: '宽度',
|
||||
name: 'width',
|
||||
required: false,
|
||||
placeholder: '该容器在1920px大屏中的宽度',
|
||||
value: 600,
|
||||
},
|
||||
{
|
||||
type: 'el-input-number',
|
||||
label: '高度',
|
||||
name: 'height',
|
||||
required: false,
|
||||
placeholder: '该容器在1080px大屏中的高度',
|
||||
value: 400,
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,7 @@ import {widgetSliders} from "./configure/texts/widget-slider"
|
||||
import {widgetVideo} from "./configure/texts/widget-video"
|
||||
import {widgetTable} from "./configure/texts/widget-table"
|
||||
import {widgetIframe} from "./configure/texts/widget-iframe"
|
||||
import {widgetCalendar} from "./configure/texts/widget-calendar"
|
||||
import {widgetUniversal} from "./configure/widget-universal"
|
||||
import {widgetBarchart} from "./configure/barCharts/widget-barchart"
|
||||
import {widgetGradientBarchart} from "./configure/barCharts/widget-gradient-barchart"
|
||||
@@ -70,6 +71,7 @@ export const widgetTool = [
|
||||
widgetVideo,
|
||||
widgetTable,
|
||||
widgetIframe,
|
||||
widgetCalendar,
|
||||
// widgetUniversal,
|
||||
widgetBarchart,
|
||||
widgetGradientBarchart,
|
||||
|
||||
@@ -19,6 +19,7 @@ import widgetImage from "./texts/widgetImage.vue";
|
||||
import widgetSlider from "./texts/widgetSlider.vue";
|
||||
import widgetVideo from "./texts/widgetVideo.vue";
|
||||
import WidgetIframe from "./texts/widgetIframe.vue";
|
||||
import widgetCalendar from "./texts/widgetCalendar.vue";
|
||||
import widgetBarchart from "./bar/widgetBarchart.vue";
|
||||
import widgetLinechart from "./line/widgetLinechart.vue";
|
||||
import widgetBarlinechart from "./barline/widgetBarlinechart";
|
||||
@@ -72,6 +73,7 @@ export default {
|
||||
widgetSlider,
|
||||
widgetVideo,
|
||||
WidgetIframe,
|
||||
widgetCalendar,
|
||||
widgetBarchart,
|
||||
widgetGradientColorBarchart,
|
||||
widgetLinechart,
|
||||
|
||||
@@ -0,0 +1,371 @@
|
||||
<template>
|
||||
<div class="calendar-container full-box" :style="styleObj">
|
||||
<div class="calendar-header" :style="headerStyle">
|
||||
<button class="nav-button" :style="headerBtnStyle" @click="prevMonth" v-if="showButton"><</button>
|
||||
<div class="current-month-title">{{ currentMonthTitle }}</div>
|
||||
<button class="nav-button" :style="headerBtnStyle" @click="nextMonth" v-if="showButton">></button>
|
||||
</div>
|
||||
|
||||
<div class="calendar-month">
|
||||
<div class="weekdays" :style="weekStyle">
|
||||
<div class="weekday" v-for="day in weekdays" :key="day">{{ day }}</div>
|
||||
</div>
|
||||
<div class="days-grid" :style="dayStyle">
|
||||
<div
|
||||
class="day-cell"
|
||||
v-for="day in currentMonthDays"
|
||||
:key="day.date"
|
||||
:class="{
|
||||
'out-of-range': day.isOutOfRange,
|
||||
'current-month': day.isCurrentMonth,
|
||||
'today': day.isToday
|
||||
}"
|
||||
:style="cellStyle(day.isToday)"
|
||||
>
|
||||
<slot name="day" :day="day">
|
||||
<div class="day-number">{{ day.day }}</div>
|
||||
<div class="day-content" v-html="text[day.date] || ''"></div>
|
||||
</slot>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import moment from 'moment'
|
||||
import { targetWidgetLinkageLogic } from "@/views/bigscreenDesigner/designer/linkageLogic";
|
||||
|
||||
export default {
|
||||
name: 'widgetCalendar',
|
||||
props: {
|
||||
value: Object,
|
||||
ispreview: Boolean,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
weekdays: ['日', '一', '二', '三', '四', '五', '六'],
|
||||
currentMonth: moment().startOf('month'),
|
||||
startDate: moment().format('YYYY-MM-DD'),
|
||||
endDate: moment().format('YYYY-MM-DD'),
|
||||
options: {},
|
||||
optionsSetUp: {},
|
||||
optionsPosition: {},
|
||||
optionsData: {},
|
||||
|
||||
text: ''
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
momentStartDate() {
|
||||
return moment(this.startDate, 'YYYY-MM-DD').startOf('day')
|
||||
},
|
||||
momentEndDate() {
|
||||
return moment(this.endDate, 'YYYY-MM-DD').endOf('day')
|
||||
},
|
||||
showButton () {
|
||||
return this.optionsSetUp.isButton;
|
||||
},
|
||||
styleObj() {
|
||||
const allStyle = this.optionsPosition;
|
||||
return {
|
||||
position: this.ispreview ? "absolute" : "static",
|
||||
width: allStyle.width + "px",
|
||||
height: allStyle.height + "px",
|
||||
left: allStyle.left + "px",
|
||||
top: allStyle.top + "px",
|
||||
background: this.optionsSetUp.tableBgColor,
|
||||
borderColor: this.optionsSetUp.borderColor
|
||||
};
|
||||
},
|
||||
headerStyle () {
|
||||
return {
|
||||
background: this.optionsSetUp.headerBackground,
|
||||
color: this.optionsSetUp.headerTextColor,
|
||||
justifyContent: this.optionsSetUp.isButton ? 'space-between' : 'center'
|
||||
|
||||
};
|
||||
},
|
||||
headerBtnStyle () {
|
||||
return {
|
||||
background: this.optionsSetUp.headerBtnBackground,
|
||||
color: this.optionsSetUp.headerBtnTextColor
|
||||
};
|
||||
},
|
||||
weekStyle () {
|
||||
return {
|
||||
background: this.optionsSetUp.weekBackground,
|
||||
color: this.optionsSetUp.weekTextColor
|
||||
};
|
||||
},
|
||||
dayStyle () {
|
||||
return {
|
||||
backgroundColor: this.optionsSetUp.borderColor
|
||||
}
|
||||
},
|
||||
currentMonthTitle() {
|
||||
return `${this.currentMonth.year()}年${this.currentMonth.month() + 1}月`
|
||||
},
|
||||
currentMonthDays() {
|
||||
const daysInMonth = this.currentMonth.daysInMonth()
|
||||
const firstDayOfMonth = moment(this.currentMonth).startOf('month')
|
||||
const startingDayOfWeek = firstDayOfMonth.day()
|
||||
|
||||
const days = []
|
||||
|
||||
// 添加上个月的日期
|
||||
const daysFromPrevMonth = startingDayOfWeek
|
||||
const prevMonth = moment(this.currentMonth).subtract(1, 'month')
|
||||
for (let i = 0; i < daysFromPrevMonth; i++) {
|
||||
const day = prevMonth.daysInMonth() - daysFromPrevMonth + i + 1
|
||||
const date = moment(prevMonth).date(day)
|
||||
days.push(this.createDayObject(date, false))
|
||||
}
|
||||
|
||||
// 添加当前月的日期
|
||||
for (let day = 1; day <= daysInMonth; day++) {
|
||||
const date = moment(this.currentMonth).date(day)
|
||||
days.push(this.createDayObject(date, true))
|
||||
}
|
||||
|
||||
// 添加下个月的日期
|
||||
const totalCells = daysFromPrevMonth + daysInMonth
|
||||
const remainingCells = totalCells % 7 === 0 ? 0 : 7 - (totalCells % 7)
|
||||
const nextMonth = moment(this.currentMonth).add(1, 'month')
|
||||
for (let i = 1; i <= remainingCells; i++) {
|
||||
const date = moment(nextMonth).date(i)
|
||||
days.push(this.createDayObject(date, false))
|
||||
}
|
||||
|
||||
return days
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
value: {
|
||||
handler(val) {
|
||||
this.options = val;
|
||||
this.optionsSetUp = val.setup;
|
||||
this.optionsPosition = val.position;
|
||||
this.optionsData = val.data;
|
||||
this.setOptionsData();
|
||||
},
|
||||
deep: true
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.options = this.value;
|
||||
this.optionsSetUp = this.value.setup;
|
||||
this.optionsPosition = this.value.position;
|
||||
this.optionsData = this.value.data;
|
||||
targetWidgetLinkageLogic(this);
|
||||
this.setOptionsData();
|
||||
},
|
||||
methods: {
|
||||
// 数据解析
|
||||
setOptionsData(e, paramsConfig) {
|
||||
const optionsData = this.optionsData; // 数据类型 静态 or 动态
|
||||
// 联动接收者逻辑开始
|
||||
optionsData.dynamicData = optionsData.dynamicData || {}; // 兼容 dynamicData undefined
|
||||
const myDynamicData = optionsData.dynamicData;
|
||||
clearInterval(this.flagInter); // 不管咋,先干掉上一次的定时任务,避免多跑
|
||||
if (
|
||||
e &&
|
||||
optionsData.dataType !== "staticData" &&
|
||||
Object.keys(myDynamicData.contextData).length
|
||||
) {
|
||||
const keyArr = Object.keys(myDynamicData.contextData);
|
||||
paramsConfig.forEach((conf) => {
|
||||
if (keyArr.includes(conf.targetKey)) {
|
||||
myDynamicData.contextData[conf.targetKey] = e[conf.originKey];
|
||||
}
|
||||
});
|
||||
}
|
||||
// 联动接收者逻辑结束
|
||||
if (optionsData.dataType === "dynamicData") {
|
||||
this.dynamicDataFn(optionsData.dynamicData, optionsData.refreshTime);
|
||||
} else {
|
||||
const data = this.objToOne(this.options).staticData
|
||||
let obj = {}
|
||||
data.forEach(e => {
|
||||
obj[e.date] = e.data
|
||||
});
|
||||
this.text = obj
|
||||
};
|
||||
},
|
||||
dynamicDataFn(val, refreshTime) {
|
||||
if (!val) return;
|
||||
if (this.ispreview) {
|
||||
this.getEchartData(val);
|
||||
this.flagInter = setInterval(() => {
|
||||
this.getEchartData(val);
|
||||
}, refreshTime);
|
||||
} else {
|
||||
this.getEchartData(val);
|
||||
}
|
||||
},
|
||||
getEchartData(val) {
|
||||
const data = this.queryEchartsData(val);
|
||||
data.then(res => {
|
||||
let obj = {}
|
||||
res.forEach(e => {
|
||||
obj[e.date] = e.data
|
||||
});
|
||||
this.text = obj
|
||||
this.$forceUpdate();
|
||||
});
|
||||
},
|
||||
cellStyle (isToday) {
|
||||
return {
|
||||
backgroundColor: isToday ? this.optionsSetUp.todayBackground : this.optionsSetUp.dayBackground,
|
||||
color: isToday ? this.optionsSetUp.todayTextColor : this.optionsSetUp.dayTextColor,
|
||||
}
|
||||
},
|
||||
prevMonth() {
|
||||
this.currentMonth = moment(this.currentMonth).subtract(1, 'month')
|
||||
},
|
||||
nextMonth() {
|
||||
this.currentMonth = moment(this.currentMonth).add(1, 'month')
|
||||
},
|
||||
createDayObject(date, isCurrentMonth) {
|
||||
const isToday = date.isSame(moment(), 'day')
|
||||
const isBeforeRange = date.isBefore(this.momentStartDate, 'day')
|
||||
const isAfterRange = date.isAfter(this.momentEndDate, 'day')
|
||||
const isDisabled = isBeforeRange || isAfterRange
|
||||
|
||||
return {
|
||||
date: date.format('YYYY-MM-DD'),
|
||||
year: date.year(),
|
||||
month: date.month(), // 0-11
|
||||
day: date.date(), // 1-31
|
||||
weekday: date.day(), // 0-6 (0是周日)
|
||||
isCurrentMonth,
|
||||
isOutOfRange: !isCurrentMonth,
|
||||
isToday,
|
||||
isBeforeRange,
|
||||
isAfterRange,
|
||||
isDisabled,
|
||||
fullDate: date.toDate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.calendar-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border: 1px solid #ddd;
|
||||
}
|
||||
|
||||
.full-box {
|
||||
height: 100%;
|
||||
.calendar-month {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
.days-grid {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.calendar-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 10px;
|
||||
background-color: rgb(10, 115, 255);
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.current-month-title {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.nav-button {
|
||||
background: none;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 4px;
|
||||
padding: 5px 10px;
|
||||
cursor: pointer;
|
||||
font-size: 16px;
|
||||
color: #ffffff;
|
||||
|
||||
&:hover {
|
||||
opacity: .5;
|
||||
}
|
||||
}
|
||||
|
||||
.weekdays {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(7, 1fr);
|
||||
background-color: rgb(10, 39, 50);
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.weekday {
|
||||
text-align: center;
|
||||
padding: 8px 0;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.days-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(7, 1fr);
|
||||
grid-gap: 1px;
|
||||
background-color: rgb(221, 221, 221);
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.day-cell {
|
||||
min-height: 60px;
|
||||
background-color: rgb(0, 59, 81);
|
||||
padding: 5px;
|
||||
position: relative;
|
||||
width: calc(100% - 0px);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
/* 当前月份的日期 */
|
||||
.day-cell.current-month {
|
||||
background-color: rgb(0, 59, 81);
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
/* 非当前月份的日期 */
|
||||
.day-cell:not(.current-month) {
|
||||
background-color: rgba(0, 59, 81, .5);
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
/* 今天日期 */
|
||||
.day-cell.today {
|
||||
background-color: #e6f7ff;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
/* 日期范围外的单元格 */
|
||||
.day-cell.disabled-day {
|
||||
background-color: #e0e0e0;
|
||||
color: #999;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.day-number {
|
||||
font-weight: bold;
|
||||
width: 30px;
|
||||
}
|
||||
.day-content {
|
||||
text-align: left;
|
||||
padding: 0 10px;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
@@ -26,6 +26,7 @@ import widgetImage from "./texts/widgetImage.vue";
|
||||
import widgetSlider from "./texts/widgetSlider.vue";
|
||||
import widgetVideo from "./texts/widgetVideo.vue";
|
||||
import WidgetIframe from "./texts/widgetIframe.vue";
|
||||
import widgetCalendar from "./texts/widgetCalendar.vue";
|
||||
import widgetBarchart from "./bar/widgetBarchart.vue";
|
||||
import widgetScatter from "./scatter/widgetScatter.vue";
|
||||
import widgetGradientColorBarchart from "./bar/widgetGradientColorBarchart.vue";
|
||||
@@ -79,6 +80,7 @@ export default {
|
||||
widgetSlider,
|
||||
widgetVideo,
|
||||
WidgetIframe,
|
||||
widgetCalendar,
|
||||
widgetBarchart,
|
||||
widgetGradientColorBarchart,
|
||||
widgetLinechart,
|
||||
|
||||
Reference in New Issue
Block a user