From ffe44f4cb1518d61bd0bd58e56852ba1a513a251 Mon Sep 17 00:00:00 2001 From: Chunyu Date: Sat, 29 Aug 2026 13:49:23 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=20EXE=20=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E5=BA=93=20schema=20=E4=B8=8D=E5=8C=B9=E9=85=8D?= =?UTF-8?q?=E5=AF=BC=E8=87=B4=20500=20=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - ISS 移除 onlyifdoesntexist 确保安装目录 db.sqlite3 始终更新 - .gitignore 忽略所有 sqlite3 文件 - 前端翻页组件和样式更新 --- .gitignore | 2 +- build_installer.bat | 16 ++++++++++++++-- frontend/src/App.jsx | 41 ++++++++++++++++++++++++++++++----------- frontend/src/index.css | 32 +++++++++++++++++++++++++++++++- frontend/vite.config.js | 4 +++- school-meal-setup.iss | 30 +++++++++++++++++++++++------- 6 files changed, 102 insertions(+), 23 deletions(-) diff --git a/.gitignore b/.gitignore index d78fad5..f2954c0 100644 --- a/.gitignore +++ b/.gitignore @@ -9,7 +9,7 @@ frontend/node_modules/ frontend/dist/ # Data -backend/db.sqlite3 +*.sqlite3 backend/staticfiles/ # Logs diff --git a/build_installer.bat b/build_installer.bat index e6a9a5b..14ec4a9 100644 --- a/build_installer.bat +++ b/build_installer.bat @@ -1,4 +1,4 @@ -@echo off +@echo off chcp 65001 >nul echo ========================================== echo 学校订餐菜单生成器 - 一键打包安装包 @@ -40,6 +40,8 @@ if exist "C:\Program Files (x86)\Inno Setup 6\ISCC.exe" ( set "ISCC=C:\Program Files\Inno Setup 6\ISCC.exe" ) else if exist "C:\Program Files (x86)\Inno Setup 5\ISCC.exe" ( set "ISCC=C:\Program Files (x86)\Inno Setup 5\ISCC.exe" +) else if exist "C:\Program Files\Inno Setup 5\ISCC.exe" ( + set "ISCC=C:\Program Files\Inno Setup 5\ISCC.exe" ) else ( where iscc >nul 2>&1 if not errorlevel 1 ( @@ -60,6 +62,16 @@ if "%ISCC%"=="" ( ) echo 找到 Inno Setup: %ISCC% +echo. +echo [3.5/4] 验证语言文件... +for %%I in ("%ISCC%") do set "ISDIR=%%~dpI" +if not exist "%ISDIR%Languages\ChineseSimplified.isl" ( + echo. + echo 警告: 未找到中文语言文件 ChineseSimplified.isl + echo 安装向导将使用英文界面。 + echo 如需中文界面,请确保 Inno Setup 完整安装。 +) + echo. echo [4/4] 编译安装包... "%ISCC%" school-meal-setup.iss @@ -78,4 +90,4 @@ echo 输出目录: installer\ echo 安装包: installer\学校订餐菜单生成器-安装包.exe echo ========================================== echo. -pause +pause \ No newline at end of file diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index c2fbadb..09aca01 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -20,7 +20,8 @@ const TYPE_LABELS = { meats: '荤菜', vegs: '素菜', soup: '营养汤', staple const TYPE_TO_TAB = { meats: 'meat', vegs: 'veg', soup: 'soup', staple: 'staple' } const TYPE_ALL_LABELS = { meat: '荤菜', veg: '素菜', soup: '营养汤', staple: '主食' } const DEFAULT_SCHOOL = '学校菜单' -const MODAL_PAGE_SIZE = 20 +const DEFAULT_PAGE_SIZE = 20 +const PAGE_SIZE_OPTIONS = [10, 20, 50, 100] /** Compute ISO week Monday/Friday as Date objects */ const weekDates = (weekNo) => { @@ -63,7 +64,7 @@ const slotKey = (menu, day, slot, idx) => `${menu}|${day}|${slot}|${idx}` /* ============================ Modern Pagination Component ============================ */ -function Pagination({ page, total, pageSize, onChange }) { +function Pagination({ page, total, pageSize, onPageSizeChange, onChange }) { const totalPages = Math.max(1, Math.ceil(total / pageSize)) const currentPage = Math.min(Math.max(1, page), totalPages) if (totalPages <= 1) return null @@ -149,6 +150,21 @@ function Pagination({ page, total, pageSize, onChange }) { /> 页 + {onPageSizeChange && ( + + 每页 + + 条 + + )} ) @@ -158,6 +174,7 @@ function Pagination({ page, total, pageSize, onChange }) { FlatDishList — paginated dish grid for modals ============================ */ function FlatDishList({ items, currentId, hover, setHover, onSelect, renderItem }) { + const [pageSize, setPageSize] = useState(DEFAULT_PAGE_SIZE) const [page, setPage] = useState(1) // Reset page when items change (e.g. search/filter) @@ -167,8 +184,8 @@ function FlatDishList({ items, currentId, hover, setHover, onSelect, renderItem // Use effect-less pattern: we'll reset via key prop } - const startIdx = (page - 1) * MODAL_PAGE_SIZE - const pageItems = items.slice(startIdx, startIdx + MODAL_PAGE_SIZE) + const startIdx = (page - 1) * pageSize + const pageItems = items.slice(startIdx, startIdx + pageSize) return (
@@ -189,13 +206,14 @@ function FlatDishList({ items, currentId, hover, setHover, onSelect, renderItem ))} {pageItems.length === 0 &&

没有匹配的菜品

}
- + ) } function SwapModal({ editing, menus, dishes, pinyinMap, swapKeyword, swapType, setSwapKeyword, setSwapType, onReplace, onClose }) { const [hover, setHover] = useState(null) + const [swapPageSize, setSwapPageSize] = useState(DEFAULT_PAGE_SIZE) const [swapPage, setSwapPage] = useState(1) // Reset page on filter/search change @@ -229,8 +247,8 @@ function SwapModal({ editing, menus, dishes, pinyinMap, swapKeyword, swapType, s return result }, [swapType, kw, dishes]) - const startIdx = (swapPage - 1) * MODAL_PAGE_SIZE - const pageItems = flatList.slice(startIdx, startIdx + MODAL_PAGE_SIZE) + const startIdx = (swapPage - 1) * swapPageSize + const pageItems = flatList.slice(startIdx, startIdx + swapPageSize) return (
没有匹配的菜品

}
- + @@ -295,6 +313,7 @@ function SwapModal({ editing, menus, dishes, pinyinMap, swapKeyword, swapType, s function PickModal({ pick, slots, dishes, pinyinMap, keyword, pickType, setKeyword, setPickType, onChoose, onClose }) { const [hover, setHover] = useState(null) + const [pickPageSize, setPickPageSize] = useState(DEFAULT_PAGE_SIZE) const [pickPage, setPickPage] = useState(1) // Reset page on filter/search change @@ -324,8 +343,8 @@ function PickModal({ pick, slots, dishes, pinyinMap, keyword, pickType, setKeywo return result }, [pickType, kw, dishes]) - const startIdx = (pickPage - 1) * MODAL_PAGE_SIZE - const pageItems = flatList.slice(startIdx, startIdx + MODAL_PAGE_SIZE) + const startIdx = (pickPage - 1) * pickPageSize + const pageItems = flatList.slice(startIdx, startIdx + pickPageSize) return (
没有匹配的菜品

}
- + diff --git a/frontend/src/index.css b/frontend/src/index.css index a9b0c81..5d1cc1e 100644 --- a/frontend/src/index.css +++ b/frontend/src/index.css @@ -1,4 +1,4 @@ -/* ============================================ +/* ============================================ 学校订餐菜单生成器 — Modern Design System Based on 2025-2026 mainstream web trends ============================================ */ @@ -1072,6 +1072,36 @@ table.excel-like.nutri-table td { box-shadow: 0 0 0 3px var(--c-accent-light); } +/* Page size selector */ +.pg-size { + display: inline-flex; + align-items: center; + gap: 6px; + margin-left: 10px; + font-size: 12px; + color: var(--c-text-muted); + white-space: nowrap; +} + +.pg-size-select { + height: 30px; + padding: 0 6px; + border: 1.5px solid var(--c-border); + border-radius: var(--radius-sm); + font-size: 12px; + background: var(--c-surface); + color: var(--c-text); + outline: none; + cursor: pointer; + transition: border-color 0.18s ease, box-shadow 0.18s ease; + font-family: inherit; +} + +.pg-size-select:focus { + border-color: var(--c-accent); + box-shadow: 0 0 0 3px var(--c-accent-light); +} + /* Pagination responsive */ @media (max-width: 600px) { .pagination { diff --git a/frontend/vite.config.js b/frontend/vite.config.js index bac987a..5a3acfe 100644 --- a/frontend/vite.config.js +++ b/frontend/vite.config.js @@ -1,4 +1,4 @@ -import { defineConfig } from 'vite' +import { defineConfig } from 'vite' import react from '@vitejs/plugin-react' export default defineConfig({ @@ -8,6 +8,8 @@ export default defineConfig({ port: 5173, proxy: { '/api': 'http://127.0.0.1:8000', + '/admin': 'http://127.0.0.1:8000', + '/static': 'http://127.0.0.1:8000', }, }, }) diff --git a/school-meal-setup.iss b/school-meal-setup.iss index 578e090..4b64652 100644 --- a/school-meal-setup.iss +++ b/school-meal-setup.iss @@ -1,4 +1,4 @@ -; Inno Setup script for 学校订餐菜单生成器 +; Inno Setup script for 学校订餐菜单生成器 ; Build with: iscc school-meal-setup.iss ; Prerequisites: Inno Setup 6.x (https://jrsoftware.org/isinfo.php) ; @@ -11,7 +11,7 @@ AppName=学校订餐菜单生成器 AppVersion=1.0.0 AppPublisher=学校食堂管理 AppPublisherURL= -DefaultDirName={autopf}\学校订餐菜单生成器 +DefaultDirName={autopf}\SchoolMeal DefaultGroupName=学校订餐菜单生成器 OutputDir=installer OutputBaseFilename=学校订餐菜单生成器-安装包 @@ -25,9 +25,18 @@ ArchitecturesAllowed=x64compatible ArchitecturesInstallIn64BitMode=x64compatible CloseApplications=force RestartApplications=no -DisableProgramGroupPage=yes UninstallDisplayIcon={app}\app.ico -LicenseFile= +VersionInfoVersion=1.0.0.0 +VersionInfoCompany=学校食堂管理 +VersionInfoDescription=学校订餐菜单生成器安装程序 +VersionInfoProductName=学校订餐菜单生成器 +VersionInfoProductVersion=1.0.0 +MinVersion=10.0.17763 +SetupLogging=yes +UninstallLogMode=append +UsePreviousAppDir=no +UsePreviousGroup=no +UsePreviousSetupType=no [Languages] Name: "chinesesimplified"; MessagesFile: "compiler:Languages\ChineseSimplified.isl" @@ -35,6 +44,7 @@ Name: "english"; MessagesFile: "compiler:Default.isl" [Tasks] Name: "desktopicon"; Description: "创建桌面快捷方式"; GroupDescription: "附加选项:"; Flags: checkedonce +Name: "startupicon"; Description: "开机自动启动"; GroupDescription: "附加选项:"; Flags: unchecked [Files] ; Main executable @@ -47,9 +57,10 @@ Source: "dist\school-meal\_internal\*"; DestDir: "{app}\_internal"; Flags: ignor Source: "app.ico"; DestDir: "{app}"; Flags: ignoreversion [Icons] -Name: "{group}\学校订餐菜单生成器"; Filename: "{app}\school-meal.exe"; IconFilename: "{app}\app.ico" -Name: "{group}\卸载 学校订餐菜单生成器"; Filename: "{uninstallexe}"; IconFilename: "{app}\app.ico" -Name: "{autodesktop}\学校订餐菜单生成器"; Filename: "{app}\school-meal.exe"; Tasks: desktopicon; IconFilename: "{app}\app.ico" +Name: "{group}\学校订餐菜单生成器"; Filename: "{app}\school-meal.exe"; WorkingDir: "{app}"; IconFilename: "{app}\app.ico" +Name: "{group}\卸载 学校订餐菜单生成器"; Filename: "{uninstallexe}"; WorkingDir: "{app}"; IconFilename: "{app}\app.ico" +Name: "{autodesktop}\学校订餐菜单生成器"; Filename: "{app}\school-meal.exe"; WorkingDir: "{app}"; Tasks: desktopicon; IconFilename: "{app}\app.ico" +Name: "{userstartup}\学校订餐菜单生成器"; Filename: "{app}\school-meal.exe"; WorkingDir: "{app}"; Tasks: startupicon; IconFilename: "{app}\app.ico" [Run] Filename: "{app}\school-meal.exe"; Description: "启动 菜单生成器"; Flags: nowait postinstall skipifsilent @@ -79,3 +90,8 @@ begin Result := ''; Exec('taskkill', '/F /IM school-meal.exe', '', SW_HIDE, ewWaitUntilTerminated, ResultCode); end; + +function ShouldSkipPage(PageID: Integer): Boolean; +begin + Result := False; +end; \ No newline at end of file