个股中心、涨停分析接口对接
This commit is contained in:
@@ -125,14 +125,45 @@
|
||||
this.getYesterdayDateData()
|
||||
this.generateMonthDateListData()
|
||||
// 新增:初始化时触发一次事件,传递当天数据给父页面
|
||||
this.emitDateChange(currentYear, currentMonth, currentDay, this.getTodayItem(currentYear, currentMonth, currentDay))
|
||||
|
||||
//this.emitDateChange(currentYear, currentMonth, currentDay, this.getTodayItem(currentYear, currentMonth, currentDay))
|
||||
|
||||
this.emitDateChange(
|
||||
currentYear,
|
||||
currentMonth,
|
||||
currentDay,
|
||||
this.getTodayItem(currentYear, currentMonth, currentDay),
|
||||
this.getPrevDayItem(currentYear, currentMonth, currentDay) // 新增上一天数据
|
||||
)
|
||||
},
|
||||
mounted() {
|
||||
this.getCalendarCombinedData()
|
||||
},
|
||||
methods: {
|
||||
methods: {
|
||||
// 3. 在日历组件methods中新增getPrevDayItem方法
|
||||
/**
|
||||
* 获取指定日期的上一天数据
|
||||
*/
|
||||
getPrevDayItem(year, month, day) {
|
||||
// 计算上一天日期
|
||||
const currentDate = new Date(`${year}-${month}-${day}`);
|
||||
const prevDate = new Date(currentDate.getTime() - 24 * 60 * 60 * 1000);
|
||||
const prevYear = prevDate.getFullYear();
|
||||
const prevMonth = prevDate.getMonth() + 1;
|
||||
const prevDay = prevDate.getDate();
|
||||
|
||||
// 获取上一天的完整数据
|
||||
const targetDate = `${prevYear}-${prevMonth > 9 ? prevMonth : '0' + prevMonth}-${prevDay > 9 ? prevDay : '0' + prevDay}`;
|
||||
const currentMonthList = this.monthDateList[this.selectMonthIndex] || [];
|
||||
const localItem = currentMonthList.find(item => item.date === targetDate) || null;
|
||||
const apiData = this.getCalendarItemByDate(targetDate) || {};
|
||||
|
||||
return {
|
||||
...localItem,
|
||||
zt_count: apiData.zt_count || 0,
|
||||
top_sector: apiData.top_sector || '-',
|
||||
zaban_rate: apiData.zaban_rate || '0%'
|
||||
};
|
||||
},
|
||||
/**
|
||||
* 获取当天的item数据(合并接口数据)
|
||||
*/
|
||||
@@ -156,26 +187,52 @@
|
||||
/**
|
||||
* 触发日期变更事件(传递包含接口数据的item)
|
||||
*/
|
||||
emitDateChange(year, month, day, item) {
|
||||
const yearMonth = `${year}-${month > 9 ? month : '0' + month}`;
|
||||
const fullDate = `${year}-${month > 9 ? month : '0' + month}-${day > 9 ? day : '0' + day}`;
|
||||
this.$emit('date-change', {
|
||||
yearMonth,
|
||||
fullDate,
|
||||
item: item || { // 兜底:无item时赋值空对象+默认值
|
||||
date: fullDate,
|
||||
year,
|
||||
month,
|
||||
day,
|
||||
zt_count: 0,
|
||||
top_sector: '-',
|
||||
zaban_rate: '0%'
|
||||
},
|
||||
year,
|
||||
month,
|
||||
day
|
||||
});
|
||||
},
|
||||
// emitDateChange(year, month, day, item) {
|
||||
// const yearMonth = `${year}-${month > 9 ? month : '0' + month}`;
|
||||
// const fullDate = `${year}-${month > 9 ? month : '0' + month}-${day > 9 ? day : '0' + day}`;
|
||||
// this.$emit('date-change', {
|
||||
// yearMonth,
|
||||
// fullDate,
|
||||
// item: item || { // 兜底:无item时赋值空对象+默认值
|
||||
// date: fullDate,
|
||||
// year,
|
||||
// month,
|
||||
// day,
|
||||
// zt_count: 0,
|
||||
// top_sector: '-',
|
||||
// zaban_rate: '0%'
|
||||
// },
|
||||
// year,
|
||||
// month,
|
||||
// day
|
||||
// });
|
||||
// },
|
||||
emitDateChange(year, month, day, item, prevItem = { zt_count: 0 }) { // 新增prevItem参数,设置默认值兜底
|
||||
const yearMonth = `${year}-${month > 9 ? month : '0' + month}`;
|
||||
const fullDate = `${year}-${month > 9 ? month : '0' + month}-${day > 9 ? day : '0' + day}`;
|
||||
this.$emit('date-change', {
|
||||
yearMonth,
|
||||
fullDate,
|
||||
item: item || { // 兜底:无当前item时赋值空对象+默认值
|
||||
date: fullDate,
|
||||
year,
|
||||
month,
|
||||
day,
|
||||
zt_count: 0,
|
||||
top_sector: '-',
|
||||
zaban_rate: '0%'
|
||||
},
|
||||
prevItem: prevItem || { // 新增:传递上一天数据,兜底默认值
|
||||
zt_count: 0,
|
||||
top_sector: '-',
|
||||
zaban_rate: '0%'
|
||||
},
|
||||
year,
|
||||
month,
|
||||
day
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取当前时间前一天的数据
|
||||
*/
|
||||
@@ -259,7 +316,14 @@
|
||||
// 接口数据加载后,重新触发一次当前选中日期的事件,更新数据
|
||||
if (this.selectDateStr) {
|
||||
const [year, month, day] = this.selectDateStr.split('-').map(Number);
|
||||
this.emitDateChange(year, month, day, this.getTodayItem(year, month, day));
|
||||
//this.emitDateChange(year, month, day, this.getTodayItem(year, month, day));
|
||||
this.emitDateChange(
|
||||
year,
|
||||
month,
|
||||
day,
|
||||
this.getTodayItem(year, month, day),
|
||||
this.getPrevDayItem(year, month, day) // 新增上一天数据
|
||||
)
|
||||
}
|
||||
} else {
|
||||
this.calendarApiData = [];
|
||||
@@ -460,28 +524,84 @@
|
||||
/**
|
||||
* 点击选择开始日期和结束日期
|
||||
* @param {Object} item
|
||||
*/
|
||||
clickSelectDate(item, index) { // 新增index参数
|
||||
if (!item.isCurrentMonth) return
|
||||
if (this.selectDateStr != item.date) {
|
||||
this.selectDateStr = item.date
|
||||
// 1. 获取该日期的接口数据
|
||||
const apiData = this.getCalendarItemByDate(item.date) || {};
|
||||
// 2. 合并本地item和接口数据,补充默认值
|
||||
const mergedItem = {
|
||||
...item, // 本地日期基础数据
|
||||
zt_count: apiData.zt_count || 0, // 涨停家数,默认0
|
||||
top_sector: apiData.top_sector || '-', // 热门板块,默认'-'
|
||||
zaban_rate: apiData.zaban_rate || '0%', // 炸板率,示例字段
|
||||
isWeekend: index % 7 === 0 || index % 7 === 6 // 是否周末
|
||||
};
|
||||
this.chgStockData = mergedItem;
|
||||
// 3. 解析日期,触发事件传递合并后的item
|
||||
const [year, month, day] = item.date.split('-').map(Number);
|
||||
this.emitDateChange(year, month, day, mergedItem);
|
||||
console.log('点击某天(含接口数据)', mergedItem);
|
||||
}
|
||||
}
|
||||
*/
|
||||
clickSelectDate(item, index) { // 新增index参数
|
||||
if (!item.isCurrentMonth) return
|
||||
if (this.selectDateStr != item.date) {
|
||||
this.selectDateStr = item.date
|
||||
// 1. 获取该日期的接口数据
|
||||
const apiData = this.getCalendarItemByDate(item.date) || {};
|
||||
// 2. 合并本地item和接口数据,补充默认值
|
||||
const mergedItem = {
|
||||
...item, // 本地日期基础数据
|
||||
zt_count: apiData.zt_count || 0, // 涨停家数,默认0
|
||||
top_sector: apiData.top_sector || '-', // 热门板块,默认'-'
|
||||
zaban_rate: apiData.zaban_rate || '0%', // 炸板率,示例字段
|
||||
isWeekend: index % 7 === 0 || index % 7 === 6 // 是否周末
|
||||
};
|
||||
|
||||
// ===== 新增:获取上一天的日期和数据 =====
|
||||
// 2.1 计算上一天的日期
|
||||
const currentDate = new Date(item.date);
|
||||
const prevDate = new Date(currentDate.getTime() - 24 * 60 * 60 * 1000); // 减一天
|
||||
const prevYear = prevDate.getFullYear();
|
||||
const prevMonth = prevDate.getMonth() + 1;
|
||||
const prevDay = prevDate.getDate();
|
||||
const prevDateStr = `${prevYear}-${prevMonth > 9 ? prevMonth : '0' + prevMonth}-${prevDay > 9 ? prevDay : '0' + prevDay}`;
|
||||
|
||||
// 2.2 获取上一天的接口数据
|
||||
const prevApiData = this.getCalendarItemByDate(prevDateStr) || {};
|
||||
// 2.3 查找上一天的本地item(用于补全基础信息)
|
||||
let prevLocalItem = null;
|
||||
// 先在当前月份列表找
|
||||
const currentMonthList = this.monthDateList[this.selectMonthIndex] || [];
|
||||
prevLocalItem = currentMonthList.find(i => i.date === prevDateStr);
|
||||
// 如果当前月份没有(跨月),找对应月份的列表
|
||||
if (!prevLocalItem) {
|
||||
const prevMonthIndex = this.selectMonthIndex - (prevMonth < item.month ? 1 : 0);
|
||||
const prevMonthList = this.monthDateList[prevMonthIndex] || [];
|
||||
prevLocalItem = prevMonthList.find(i => i.date === prevDateStr);
|
||||
}
|
||||
|
||||
// 2.4 合并上一天的完整数据
|
||||
const prevMergedItem = {
|
||||
...(prevLocalItem || {}),
|
||||
zt_count: prevApiData.zt_count || 0,
|
||||
top_sector: prevApiData.top_sector || '-',
|
||||
zaban_rate: prevApiData.zaban_rate || '0%',
|
||||
isWeekend: false // 兜底默认值
|
||||
};
|
||||
// =======================================
|
||||
|
||||
this.chgStockData = mergedItem;
|
||||
// 3. 解析日期,触发事件传递【当前数据+上一天数据】
|
||||
const [year, month, day] = item.date.split('-').map(Number);
|
||||
this.emitDateChange(year, month, day, mergedItem, prevMergedItem); // 新增传递上一天数据
|
||||
console.log('点击某天(含接口数据)', { current: mergedItem, prev: prevMergedItem });
|
||||
}
|
||||
}
|
||||
|
||||
// clickSelectDate(item, index) {
|
||||
// if (!item.isCurrentMonth) return
|
||||
// if (this.selectDateStr != item.date) {
|
||||
// this.selectDateStr = item.date
|
||||
|
||||
// const apiData = this.getCalendarItemByDate(item.date) || {};
|
||||
|
||||
// const mergedItem = {
|
||||
// ...item,
|
||||
// zt_count: apiData.zt_count || 0,
|
||||
// top_sector: apiData.top_sector || '-',
|
||||
// zaban_rate: apiData.zaban_rate || '0%',
|
||||
// isWeekend: index % 7 === 0 || index % 7 === 6
|
||||
// };
|
||||
// this.chgStockData = mergedItem;
|
||||
|
||||
// const [year, month, day] = item.date.split('-').map(Number);
|
||||
// this.emitDateChange(year, month, day, mergedItem);
|
||||
// console.log('点击某天(含接口数据)', mergedItem);
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -35,6 +35,15 @@ export default {
|
||||
colorList: {
|
||||
type: Array,
|
||||
default: () => ['#60A5FA', '#FEC200', '#EF4444'] // 外圈、中间、中心
|
||||
},
|
||||
// 新增:字号配置,让组件更灵活
|
||||
fontSizeConfig: {
|
||||
type: Object,
|
||||
default: () => ({
|
||||
minSize: 12, // 最小字号
|
||||
maxSize: 40, // 最大字号
|
||||
scaleFactor: 0.1 // 缩放因子,越大字号差异越明显
|
||||
})
|
||||
}
|
||||
},
|
||||
data() {
|
||||
@@ -113,6 +122,11 @@ export default {
|
||||
// 按权重排序(权重越大,文字越大)
|
||||
const sortedWords = [...this.wordData].sort((a, b) => b.value - a.value);
|
||||
|
||||
// 计算value的最大值和最小值,用于归一化
|
||||
const values = sortedWords.map(item => item.value);
|
||||
this.valueMax = Math.max(...values);
|
||||
this.valueMin = Math.min(...values);
|
||||
|
||||
// 逐个绘制文字
|
||||
sortedWords.forEach((word, index) => {
|
||||
this.placeWord(word, index);
|
||||
@@ -124,24 +138,22 @@ export default {
|
||||
const ctx = this.ctx;
|
||||
// 优化1:提高最大尝试次数(从50→150),让更多文字能找到位置
|
||||
const maxAttempts = 150;
|
||||
const baseFontSize = 12; // 基础字体大小
|
||||
const { minSize, maxSize, scaleFactor } = this.fontSizeConfig;
|
||||
|
||||
// 分段计算分母(适配不同value区间)
|
||||
const value = word.value;
|
||||
const baseDenominator = 1000; // 基础分母
|
||||
const interval = 500; // 区间步长
|
||||
const step = 500; // 分母每次增加的步长
|
||||
// ===== 核心优化:重新设计字号计算逻辑 =====
|
||||
// 1. 归一化value(0-1区间)
|
||||
let normalizedValue = 1;
|
||||
if (this.valueMax !== this.valueMin) {
|
||||
normalizedValue = (word.value - this.valueMin) / (this.valueMax - this.valueMin);
|
||||
}
|
||||
|
||||
// 计算当前value所属区间,动态确定分母
|
||||
const intervalNum = Math.floor(value / interval);
|
||||
let denominator = baseDenominator + (intervalNum * step);
|
||||
|
||||
// 兜底:避免分母过小(比如value为0时)
|
||||
denominator = Math.max(denominator, baseDenominator);
|
||||
|
||||
// 根据分段分母计算字体大小,限制最大值
|
||||
const maxFontSize = 28; // 优化2:适当减小最大字体(从32→28),节省空间
|
||||
const fontSize = Math.min(baseFontSize + (value / denominator) * 16, maxFontSize);
|
||||
// 2. 计算字号:基于归一化值,确保最小到最大的平滑过渡
|
||||
// 公式:最小字号 + (最大字号 - 最小字号) * 归一化值 * 缩放因子
|
||||
const fontSize = Math.min(
|
||||
minSize + (maxSize - minSize) * normalizedValue * scaleFactor,
|
||||
maxSize
|
||||
);
|
||||
// ==========================================
|
||||
|
||||
// 旋转角度:-60° 到 60°
|
||||
const rotateAngle = (Math.random() - 0.5) * 120 * Math.PI / 180;
|
||||
@@ -150,7 +162,7 @@ export default {
|
||||
ctx.font = `${fontSize}px sans-serif`;
|
||||
|
||||
// 获取文字宽度和高度(用于碰撞检测)
|
||||
const textWidth = ctx.measureText(word.name).width;
|
||||
const textWidth = ctx.measureText(word.text || word.name).width; // 兼容text/name字段
|
||||
// 优化3:更精准的文字高度估算(从1.2→1.05),减少无效空间
|
||||
const textHeight = fontSize * 1.05;
|
||||
|
||||
@@ -193,7 +205,7 @@ export default {
|
||||
ctx.fillStyle = color;
|
||||
|
||||
// 无重叠,绘制文字
|
||||
this.drawTextAtPosition(word.name, x, y, rotateAngle, fontSize);
|
||||
this.drawTextAtPosition(word.text || word.name, x, y, rotateAngle, fontSize);
|
||||
|
||||
// 记录已放置的文字信息(用于后续碰撞检测)
|
||||
this.placedWords.push({
|
||||
@@ -238,9 +250,9 @@ export default {
|
||||
// 四个顶点坐标(相对于中心)
|
||||
const points = [
|
||||
{ x: -halfW, y: -halfH },
|
||||
{ x: halfW, y: -halfH },
|
||||
{ x: -halfW, y: halfH },
|
||||
{ x: halfW, y: halfH },
|
||||
{ x: -halfW, y: halfH }
|
||||
{ x: halfW, y: -halfH }
|
||||
];
|
||||
|
||||
// 旋转并平移到实际位置
|
||||
|
||||
Reference in New Issue
Block a user