optimize: api resp size.
Some checks failed
Build and Push Docker Image / buildx (push) Has been cancelled
Some checks failed
Build and Push Docker Image / buildx (push) Has been cancelled
This commit is contained in:
@@ -53,14 +53,22 @@ export async function fetchCurrentUser(server, token) {
|
||||
return request(server, '/api/auth/me', { token });
|
||||
}
|
||||
|
||||
export async function fetchCalendar(server, token) {
|
||||
return request(server, '/api/calendar', { token });
|
||||
export async function fetchCalendar(server, token, year, month) {
|
||||
const params = new URLSearchParams();
|
||||
if (year !== undefined && month !== undefined) {
|
||||
params.append('year', year);
|
||||
params.append('month', month);
|
||||
}
|
||||
const queryString = params.toString();
|
||||
const path = queryString ? `/api/calendar?${queryString}` : '/api/calendar';
|
||||
return request(server, path, { token });
|
||||
}
|
||||
|
||||
export async function saveCalendar(server, token, markedDates) {
|
||||
|
||||
export async function saveCalendar(server, token, markedDates, deletedDates) {
|
||||
return request(server, '/api/calendar', {
|
||||
method: 'POST',
|
||||
token,
|
||||
body: { markedDates }
|
||||
body: { markedDates, deletedDates }
|
||||
});
|
||||
}
|
||||
|
||||
@@ -26,6 +26,8 @@ export default class CalendarView {
|
||||
this.prevBtn.addEventListener('click', () => {
|
||||
state.currentDate.setMonth(state.currentDate.getMonth() - 1);
|
||||
this.renderCalendar();
|
||||
// Load data for the new month
|
||||
this.loadData();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -33,6 +35,8 @@ export default class CalendarView {
|
||||
this.nextBtn.addEventListener('click', () => {
|
||||
state.currentDate.setMonth(state.currentDate.getMonth() + 1);
|
||||
this.renderCalendar();
|
||||
// Load data for the new month
|
||||
this.loadData();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -40,6 +44,8 @@ export default class CalendarView {
|
||||
this.todayBtn.addEventListener('click', () => {
|
||||
state.currentDate = new Date();
|
||||
this.renderCalendar();
|
||||
// Load data for the current month
|
||||
this.loadData();
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -51,21 +57,12 @@ export default class CalendarView {
|
||||
|
||||
try {
|
||||
showToast('正在加载...', 'info');
|
||||
const result = await fetchCalendar(state.currentServer, state.token);
|
||||
// Convert the new data structure to the old one for backward compatibility
|
||||
const markedDates = {};
|
||||
for (const [date, data] of Object.entries(result.markedDates || {})) {
|
||||
if (typeof data === 'string') {
|
||||
// Old format - just status
|
||||
markedDates[date] = data;
|
||||
} else if (data && typeof data === 'object') {
|
||||
// New format - object with status and updatedAt
|
||||
markedDates[date] = data.status;
|
||||
}
|
||||
}
|
||||
state.markedDates = markedDates;
|
||||
// Store the full data including timestamps
|
||||
state.markedDatesWithTimestamps = result.markedDates || {};
|
||||
// Pass current year and month to only fetch data for the displayed month
|
||||
const year = state.currentDate.getFullYear();
|
||||
const month = state.currentDate.getMonth() + 1; // getMonth() returns 0-11, need 1-12
|
||||
const result = await fetchCalendar(state.currentServer, state.token, year, month);
|
||||
// Merge with existing data
|
||||
Object.assign(state.markedDates, result.markedDates || {});
|
||||
this.renderCalendar();
|
||||
showToast('数据加载成功', 'success');
|
||||
} catch (error) {
|
||||
@@ -82,7 +79,7 @@ export default class CalendarView {
|
||||
|
||||
clearData() {
|
||||
state.markedDates = {};
|
||||
state.markedDatesWithTimestamps = {};
|
||||
state.deletedDates = [];
|
||||
this.renderCalendar();
|
||||
}
|
||||
|
||||
@@ -307,7 +304,8 @@ export default class CalendarView {
|
||||
}
|
||||
|
||||
const dateKey = this.formatDate(date);
|
||||
const currentStatus = state.markedDates[dateKey] || 'none';
|
||||
const dateData = state.markedDates[dateKey];
|
||||
const currentStatus = (dateData && dateData.status) || 'none';
|
||||
let nextStatus;
|
||||
|
||||
switch (currentStatus) {
|
||||
@@ -325,11 +323,21 @@ export default class CalendarView {
|
||||
|
||||
if (nextStatus === 'none') {
|
||||
delete state.markedDates[dateKey];
|
||||
// Track this deletion
|
||||
if (!state.deletedDates.includes(dateKey)) {
|
||||
state.deletedDates.push(dateKey);
|
||||
}
|
||||
// Clear pending tooltip for removed marks
|
||||
this.pendingTooltipDate = null;
|
||||
this.hideTooltip();
|
||||
} else {
|
||||
state.markedDates[dateKey] = nextStatus;
|
||||
// Store status, timestamp will be updated by server on save
|
||||
state.markedDates[dateKey] = { status: nextStatus };
|
||||
// Remove from deleted dates if it was there
|
||||
const deleteIndex = state.deletedDates.indexOf(dateKey);
|
||||
if (deleteIndex !== -1) {
|
||||
state.deletedDates.splice(deleteIndex, 1);
|
||||
}
|
||||
// Store the date for tooltip after save completes
|
||||
this.pendingTooltipDate = dateKey;
|
||||
}
|
||||
@@ -353,7 +361,17 @@ export default class CalendarView {
|
||||
async persistMarkedDates() {
|
||||
state.saveTimeoutId = null;
|
||||
try {
|
||||
await saveCalendar(state.currentServer, state.token, state.markedDates);
|
||||
// Convert state format { date: { status, updatedAt } } to API format { date: status }
|
||||
const markedDatesForAPI = {};
|
||||
for (const [date, data] of Object.entries(state.markedDates)) {
|
||||
if (data && typeof data === 'object' && data.status) {
|
||||
markedDatesForAPI[date] = data.status;
|
||||
}
|
||||
}
|
||||
|
||||
await saveCalendar(state.currentServer, state.token, markedDatesForAPI, state.deletedDates);
|
||||
// Clear the deleted dates array after successful save
|
||||
state.deletedDates = [];
|
||||
showToast('数据已保存', 'success');
|
||||
// Reload data to get updated timestamps
|
||||
await this.loadData();
|
||||
@@ -384,12 +402,16 @@ export default class CalendarView {
|
||||
|
||||
getDateStatus(date) {
|
||||
const dateKey = this.formatDate(date);
|
||||
return state.markedDates[dateKey] || 'none';
|
||||
const dateData = state.markedDates[dateKey];
|
||||
if (dateData && typeof dateData === 'object') {
|
||||
return dateData.status || 'none';
|
||||
}
|
||||
return 'none';
|
||||
}
|
||||
|
||||
getDateTimestamp(date) {
|
||||
const dateKey = this.formatDate(date);
|
||||
const dateData = state.markedDatesWithTimestamps[dateKey];
|
||||
const dateData = state.markedDates[dateKey];
|
||||
if (dateData && typeof dateData === 'object' && dateData.updatedAt) {
|
||||
return dateData.updatedAt;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
const state = {
|
||||
currentDate: new Date(),
|
||||
markedDates: {},
|
||||
markedDatesWithTimestamps: {},
|
||||
markedDates: {}, // Now stores objects with { status, updatedAt }
|
||||
deletedDates: [], // Track dates that have been explicitly deleted
|
||||
currentServer: '',
|
||||
token: '',
|
||||
user: null,
|
||||
|
||||
@@ -5,11 +5,39 @@ const router = express.Router();
|
||||
|
||||
router.get('/', (req, res) => {
|
||||
const userId = req.user.userId;
|
||||
const { year, month } = req.query;
|
||||
|
||||
db.all(
|
||||
'SELECT date, status, updated_at FROM calendar_marks WHERE user_id = ?',
|
||||
[userId],
|
||||
(err, rows) => {
|
||||
// Build query based on whether year and month are provided
|
||||
let query = 'SELECT date, status, updated_at FROM calendar_marks WHERE user_id = ?';
|
||||
const params = [userId];
|
||||
|
||||
// If year and month are provided, filter by that month plus adjacent months
|
||||
if (year && month) {
|
||||
const yearNum = parseInt(year, 10);
|
||||
const monthNum = parseInt(month, 10);
|
||||
|
||||
// Validate year and month
|
||||
if (isNaN(yearNum) || isNaN(monthNum) || monthNum < 1 || monthNum > 12) {
|
||||
return res.status(400).json({ success: false, error: '无效的年份或月份' });
|
||||
}
|
||||
|
||||
// Calculate the date range: previous month to next month
|
||||
// This covers all dates that might be visible in the calendar view
|
||||
const prevMonth = monthNum === 1 ? 12 : monthNum - 1;
|
||||
const prevYear = monthNum === 1 ? yearNum - 1 : yearNum;
|
||||
const nextMonth = monthNum === 12 ? 1 : monthNum + 1;
|
||||
const nextYear = monthNum === 12 ? yearNum + 1 : yearNum;
|
||||
|
||||
const startDate = `${prevYear}-${String(prevMonth).padStart(2, '0')}-01`;
|
||||
// Get the last day of next month
|
||||
const lastDayOfNextMonth = new Date(nextYear, nextMonth, 0).getDate();
|
||||
const endDate = `${nextYear}-${String(nextMonth).padStart(2, '0')}-${String(lastDayOfNextMonth).padStart(2, '0')}`;
|
||||
|
||||
query += ' AND date >= ? AND date <= ?';
|
||||
params.push(startDate, endDate);
|
||||
}
|
||||
|
||||
db.all(query, params, (err, rows) => {
|
||||
if (err) {
|
||||
return res.status(500).json({ success: false, error: '获取数据失败' });
|
||||
}
|
||||
@@ -23,13 +51,12 @@ router.get('/', (req, res) => {
|
||||
});
|
||||
|
||||
res.json({ success: true, markedDates });
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
router.post('/', (req, res) => {
|
||||
const userId = req.user.userId;
|
||||
const { markedDates } = req.body || {};
|
||||
const { markedDates, deletedDates } = req.body || {};
|
||||
|
||||
if (!markedDates || typeof markedDates !== 'object') {
|
||||
return res.status(400).json({ success: false, error: '无效的数据格式' });
|
||||
@@ -40,8 +67,12 @@ router.post('/', (req, res) => {
|
||||
return new Date().toISOString();
|
||||
};
|
||||
|
||||
const dbOperations = Object.entries(markedDates).map(([date, status]) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const dbOperations = [];
|
||||
|
||||
// Update or insert marked dates
|
||||
Object.entries(markedDates).forEach(([date, status]) => {
|
||||
dbOperations.push(
|
||||
new Promise((resolve, reject) => {
|
||||
// First check if this date exists and if status has changed
|
||||
db.get(
|
||||
'SELECT status FROM calendar_marks WHERE user_id = ? AND date = ?',
|
||||
@@ -85,30 +116,18 @@ router.post('/', (req, res) => {
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
const dates = Object.keys(markedDates);
|
||||
if (dates.length > 0) {
|
||||
const placeholders = dates.map(() => '?').join(',');
|
||||
dbOperations.push(
|
||||
new Promise((resolve, reject) => {
|
||||
db.run(
|
||||
`DELETE FROM calendar_marks WHERE user_id = ? AND date NOT IN (${placeholders})`,
|
||||
[userId, ...dates],
|
||||
(err) => {
|
||||
if (err) reject(err);
|
||||
else resolve();
|
||||
}
|
||||
);
|
||||
})
|
||||
);
|
||||
} else {
|
||||
});
|
||||
|
||||
// Delete explicitly removed dates
|
||||
if (deletedDates && Array.isArray(deletedDates) && deletedDates.length > 0) {
|
||||
const placeholders = deletedDates.map(() => '?').join(',');
|
||||
dbOperations.push(
|
||||
new Promise((resolve, reject) => {
|
||||
db.run(
|
||||
'DELETE FROM calendar_marks WHERE user_id = ?',
|
||||
[userId],
|
||||
`DELETE FROM calendar_marks WHERE user_id = ? AND date IN (${placeholders})`,
|
||||
[userId, ...deletedDates],
|
||||
(err) => {
|
||||
if (err) reject(err);
|
||||
else resolve();
|
||||
|
||||
Reference in New Issue
Block a user