默认日期变更
This commit is contained in:
@@ -11,7 +11,9 @@
|
|||||||
<div class="panel-head">
|
<div class="panel-head">
|
||||||
<div>
|
<div>
|
||||||
<h2>二板早盘次日盈利</h2>
|
<h2>二板早盘次日盈利</h2>
|
||||||
<p>下载符合二板早盘开盘阈值条件的股票明细,并查看后一交易日盈利情况。</p>
|
<p>
|
||||||
|
下载符合二板早盘开盘阈值条件的股票明细,并查看后一交易日盈利情况。
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -70,109 +72,112 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { computed, onMounted, ref } from 'vue'
|
import { computed, onMounted, ref } from "vue";
|
||||||
import dayjs from 'dayjs'
|
import dayjs from "dayjs";
|
||||||
import { ElMessage } from 'element-plus'
|
import { ElMessage } from "element-plus";
|
||||||
import { Download as DownloadIcon } from '@element-plus/icons-vue'
|
import { Download as DownloadIcon } from "@element-plus/icons-vue";
|
||||||
import { fetchTradeCalendar } from '@/composables/useTradeCalendar'
|
import { fetchTradeCalendar } from "@/composables/useTradeCalendar";
|
||||||
import { downloadSecondBoardProfitCsv } from '@/api/stock'
|
import { downloadSecondBoardProfitCsv } from "@/api/stock";
|
||||||
|
|
||||||
const DEFAULT_START_DATE = '2026-01-01'
|
const DEFAULT_START_DATE = "2026-04-01";
|
||||||
|
|
||||||
const startDate = ref(DEFAULT_START_DATE)
|
const startDate = ref(DEFAULT_START_DATE);
|
||||||
const endDate = ref('')
|
const endDate = ref("");
|
||||||
const downloading = ref(false)
|
const downloading = ref(false);
|
||||||
const openDatesSet = ref(new Set())
|
const openDatesSet = ref(new Set());
|
||||||
const maxTradeDate = ref('')
|
const maxTradeDate = ref("");
|
||||||
|
|
||||||
const canDownload = computed(
|
const canDownload = computed(
|
||||||
() => Boolean(startDate.value && endDate.value) && startDate.value <= endDate.value
|
() =>
|
||||||
)
|
Boolean(startDate.value && endDate.value) &&
|
||||||
|
startDate.value <= endDate.value,
|
||||||
|
);
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
try {
|
try {
|
||||||
const res = await fetchTradeCalendar()
|
const res = await fetchTradeCalendar();
|
||||||
const { open_dates: openDates = [], max_date: maxDate = '' } = res || {}
|
const { open_dates: openDates = [], max_date: maxDate = "" } = res || {};
|
||||||
|
|
||||||
openDatesSet.value = new Set(openDates)
|
openDatesSet.value = new Set(openDates);
|
||||||
maxTradeDate.value = maxDate
|
maxTradeDate.value = maxDate;
|
||||||
endDate.value = maxDate
|
endDate.value = maxDate;
|
||||||
startDate.value = getDefaultStartDate(openDates)
|
startDate.value = getDefaultStartDate(openDates);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('初始化下载页失败', err)
|
console.error("初始化下载页失败", err);
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
|
|
||||||
const clampToMaxDate = (date) => {
|
const clampToMaxDate = (date) => {
|
||||||
if (!date || !maxTradeDate.value || date <= maxTradeDate.value) return date
|
if (!date || !maxTradeDate.value || date <= maxTradeDate.value) return date;
|
||||||
return maxTradeDate.value
|
return maxTradeDate.value;
|
||||||
}
|
};
|
||||||
|
|
||||||
const getDefaultStartDate = (openDates) => {
|
const getDefaultStartDate = (openDates) => {
|
||||||
const fallbackDate = clampToMaxDate(DEFAULT_START_DATE)
|
const fallbackDate = clampToMaxDate(DEFAULT_START_DATE);
|
||||||
const sortedOpenDates = [...openDates].sort()
|
const sortedOpenDates = [...openDates].sort();
|
||||||
const validOpenDates = sortedOpenDates.filter(
|
const validOpenDates = sortedOpenDates.filter(
|
||||||
(date) => !maxTradeDate.value || date <= maxTradeDate.value
|
(date) => !maxTradeDate.value || date <= maxTradeDate.value,
|
||||||
)
|
);
|
||||||
|
|
||||||
if (!validOpenDates.length || openDatesSet.value.has(fallbackDate)) return fallbackDate
|
if (!validOpenDates.length || openDatesSet.value.has(fallbackDate))
|
||||||
|
return fallbackDate;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
validOpenDates.find((date) => date >= fallbackDate) ||
|
validOpenDates.find((date) => date >= fallbackDate) ||
|
||||||
validOpenDates[validOpenDates.length - 1] ||
|
validOpenDates[validOpenDates.length - 1] ||
|
||||||
fallbackDate
|
fallbackDate
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
const disableDates = (time) => {
|
const disableDates = (time) => {
|
||||||
const date = dayjs(time).format('YYYY-MM-DD')
|
const date = dayjs(time).format("YYYY-MM-DD");
|
||||||
if (maxTradeDate.value && date > maxTradeDate.value) return true
|
if (maxTradeDate.value && date > maxTradeDate.value) return true;
|
||||||
return openDatesSet.value.size > 0 ? !openDatesSet.value.has(date) : false
|
return openDatesSet.value.size > 0 ? !openDatesSet.value.has(date) : false;
|
||||||
}
|
};
|
||||||
|
|
||||||
const handleDownload = async () => {
|
const handleDownload = async () => {
|
||||||
if (!startDate.value || !endDate.value) {
|
if (!startDate.value || !endDate.value) {
|
||||||
ElMessage.warning('请选择下载日期范围')
|
ElMessage.warning("请选择下载日期范围");
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (endDate.value < startDate.value) {
|
if (endDate.value < startDate.value) {
|
||||||
ElMessage.warning('结束日期不能早于起始日期')
|
ElMessage.warning("结束日期不能早于起始日期");
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
downloading.value = true
|
downloading.value = true;
|
||||||
try {
|
try {
|
||||||
const blob = await downloadSecondBoardProfitCsv({
|
const blob = await downloadSecondBoardProfitCsv({
|
||||||
start_date: startDate.value,
|
start_date: startDate.value,
|
||||||
end_date: endDate.value
|
end_date: endDate.value,
|
||||||
})
|
});
|
||||||
saveBlob(blob, getDownloadFilename())
|
saveBlob(blob, getDownloadFilename());
|
||||||
ElMessage.success('CSV 下载已开始')
|
ElMessage.success("CSV 下载已开始");
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('下载二板早盘次日盈利 CSV 失败', err)
|
console.error("下载二板早盘次日盈利 CSV 失败", err);
|
||||||
} finally {
|
} finally {
|
||||||
downloading.value = false
|
downloading.value = false;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const saveBlob = (blob, filename) => {
|
const saveBlob = (blob, filename) => {
|
||||||
const url = window.URL.createObjectURL(blob)
|
const url = window.URL.createObjectURL(blob);
|
||||||
const link = document.createElement('a')
|
const link = document.createElement("a");
|
||||||
|
|
||||||
link.href = url
|
link.href = url;
|
||||||
link.download = filename
|
link.download = filename;
|
||||||
document.body.appendChild(link)
|
document.body.appendChild(link);
|
||||||
link.click()
|
link.click();
|
||||||
document.body.removeChild(link)
|
document.body.removeChild(link);
|
||||||
window.URL.revokeObjectURL(url)
|
window.URL.revokeObjectURL(url);
|
||||||
}
|
};
|
||||||
|
|
||||||
const getDownloadFilename = () => {
|
const getDownloadFilename = () => {
|
||||||
const start = startDate.value.replaceAll('-', '')
|
const start = startDate.value.replaceAll("-", "");
|
||||||
const end = endDate.value.replaceAll('-', '')
|
const end = endDate.value.replaceAll("-", "");
|
||||||
return `limit_second_board_profit_${start}_${end}_daily_detail.csv`
|
return `limit_second_board_profit_${start}_${end}_daily_detail.csv`;
|
||||||
}
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|||||||
Reference in New Issue
Block a user