From f47b6d483ca0d0d0aa02fa6327242b2dc7e6ce59 Mon Sep 17 00:00:00 2001 From: Fox_block Date: Sun, 8 Mar 2026 20:54:44 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E4=BD=A0=E5=A6=88=E7=9A=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .trae/rules/coding-rules.md | 3 - android/app/capacitor.build.gradle | 19 +++ android/capacitor.settings.gradle | 6 + package.json | 1 + pnpm-lock.yaml | 58 ++++++--- src/main/repos/EventRepository.ts | 4 +- src/main/services/AutoScoreService.ts | 8 +- src/mobile/components/Layout.tsx | 12 +- .../src/components/AutoScoreManager.tsx | 123 ++---------------- src/renderer/src/components/ContentArea.tsx | 17 +-- src/renderer/src/components/OOBE/OOBE.tsx | 16 ++- src/renderer/src/components/Sidebar.tsx | 2 +- .../src/components/StudentManager.tsx | 2 +- .../components/autoScore/actionComponent.tsx | 2 +- .../autoScore/ruleBuilderOverride.css | 4 +- .../components/autoScore/ruleBuilderUtils.ts | 18 +-- .../components/autoScore/ruleComponent.tsx | 2 +- src/shared/autoScore/AutoScoreRuleEngine.ts | 17 +-- 18 files changed, 124 insertions(+), 190 deletions(-) delete mode 100644 .trae/rules/coding-rules.md create mode 100644 android/app/capacitor.build.gradle create mode 100644 android/capacitor.settings.gradle diff --git a/.trae/rules/coding-rules.md b/.trae/rules/coding-rules.md deleted file mode 100644 index 51ef9f7..0000000 --- a/.trae/rules/coding-rules.md +++ /dev/null @@ -1,3 +0,0 @@ -该项目使用pnpm作为包管理器 -每次写完代码后请务必跑一遍格式化和lint,typecheck,一个warning都不可以有 -每次完成任务请详细告知用户“你干了什么”和要确认的问题(如有)。 diff --git a/android/app/capacitor.build.gradle b/android/app/capacitor.build.gradle new file mode 100644 index 0000000..adabd97 --- /dev/null +++ b/android/app/capacitor.build.gradle @@ -0,0 +1,19 @@ +// DO NOT EDIT THIS FILE! IT IS GENERATED EACH TIME "capacitor update" IS RUN + +android { + compileOptions { + sourceCompatibility JavaVersion.VERSION_21 + targetCompatibility JavaVersion.VERSION_21 + } +} + +apply from: "../capacitor-cordova-android-plugins/cordova.variables.gradle" +dependencies { + implementation project(':capacitor-preferences') + +} + + +if (hasProperty('postBuildExtras')) { + postBuildExtras() +} diff --git a/android/capacitor.settings.gradle b/android/capacitor.settings.gradle new file mode 100644 index 0000000..04bb42f --- /dev/null +++ b/android/capacitor.settings.gradle @@ -0,0 +1,6 @@ +// DO NOT EDIT THIS FILE! IT IS GENERATED EACH TIME "capacitor update" IS RUN +include ':capacitor-android' +project(':capacitor-android').projectDir = new File('../node_modules/.pnpm/@capacitor+android@8.1.0_@capacitor+core@8.1.0/node_modules/@capacitor/android/capacitor') + +include ':capacitor-preferences' +project(':capacitor-preferences').projectDir = new File('../node_modules/.pnpm/@capacitor+preferences@8.0.1_@capacitor+core@8.1.0/node_modules/@capacitor/preferences/android') diff --git a/package.json b/package.json index 444be81..796aa22 100644 --- a/package.json +++ b/package.json @@ -77,6 +77,7 @@ "prettier": "^3.7.4", "react": "^19.2.1", "react-dom": "^19.2.1", + "terser": "^5.46.0", "typescript": "^5.9.3", "vite": "^7.2.6" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0456593..4d69b4d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -120,7 +120,7 @@ importers: version: 11.0.0 '@vitejs/plugin-react': specifier: ^5.1.1 - version: 5.1.2(vite@7.3.1(@types/node@22.19.5)(jiti@2.6.1)) + version: 5.1.2(vite@7.3.1(@types/node@22.19.5)(jiti@2.6.1)(terser@5.46.0)) electron: specifier: ^39.2.6 version: 39.2.7 @@ -129,7 +129,7 @@ importers: version: 26.4.0(electron-builder-squirrel-windows@26.4.0) electron-vite: specifier: ^5.0.0 - version: 5.0.0(vite@7.3.1(@types/node@22.19.5)(jiti@2.6.1)) + version: 5.0.0(vite@7.3.1(@types/node@22.19.5)(jiti@2.6.1)(terser@5.46.0)) eslint: specifier: ^9.39.1 version: 9.39.2(jiti@2.6.1) @@ -151,12 +151,15 @@ importers: react-dom: specifier: ^19.2.1 version: 19.2.3(react@19.2.3) + terser: + specifier: ^5.46.0 + version: 5.46.0 typescript: specifier: ^5.9.3 version: 5.9.3 vite: specifier: ^7.2.6 - version: 7.3.1(@types/node@22.19.5)(jiti@2.6.1) + version: 7.3.1(@types/node@22.19.5)(jiti@2.6.1)(terser@5.46.0) packages: @@ -825,6 +828,9 @@ packages: resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} engines: {node: '>=6.0.0'} + '@jridgewell/source-map@0.3.11': + resolution: {integrity: sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==} + '@jridgewell/sourcemap-codec@1.5.5': resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} @@ -1243,79 +1249,66 @@ packages: resolution: {integrity: sha512-Rn3n+FUk2J5VWx+ywrG/HGPTD9jXNbicRtTM11e/uorplArnXZYsVifnPPqNNP5BsO3roI4n8332ukpY/zN7rQ==} cpu: [arm] os: [linux] - libc: [glibc] '@rollup/rollup-linux-arm-musleabihf@4.55.1': resolution: {integrity: sha512-grPNWydeKtc1aEdrJDWk4opD7nFtQbMmV7769hiAaYyUKCT1faPRm2av8CX1YJsZ4TLAZcg9gTR1KvEzoLjXkg==} cpu: [arm] os: [linux] - libc: [musl] '@rollup/rollup-linux-arm64-gnu@4.55.1': resolution: {integrity: sha512-a59mwd1k6x8tXKcUxSyISiquLwB5pX+fJW9TkWU46lCqD/GRDe9uDN31jrMmVP3feI3mhAdvcCClhV8V5MhJFQ==} cpu: [arm64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-arm64-musl@4.55.1': resolution: {integrity: sha512-puS1MEgWX5GsHSoiAsF0TYrpomdvkaXm0CofIMG5uVkP6IBV+ZO9xhC5YEN49nsgYo1DuuMquF9+7EDBVYu4uA==} cpu: [arm64] os: [linux] - libc: [musl] '@rollup/rollup-linux-loong64-gnu@4.55.1': resolution: {integrity: sha512-r3Wv40in+lTsULSb6nnoudVbARdOwb2u5fpeoOAZjFLznp6tDU8kd+GTHmJoqZ9lt6/Sys33KdIHUaQihFcu7g==} cpu: [loong64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-loong64-musl@4.55.1': resolution: {integrity: sha512-MR8c0+UxAlB22Fq4R+aQSPBayvYa3+9DrwG/i1TKQXFYEaoW3B5b/rkSRIypcZDdWjWnpcvxbNaAJDcSbJU3Lw==} cpu: [loong64] os: [linux] - libc: [musl] '@rollup/rollup-linux-ppc64-gnu@4.55.1': resolution: {integrity: sha512-3KhoECe1BRlSYpMTeVrD4sh2Pw2xgt4jzNSZIIPLFEsnQn9gAnZagW9+VqDqAHgm1Xc77LzJOo2LdigS5qZ+gw==} cpu: [ppc64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-ppc64-musl@4.55.1': resolution: {integrity: sha512-ziR1OuZx0vdYZZ30vueNZTg73alF59DicYrPViG0NEgDVN8/Jl87zkAPu4u6VjZST2llgEUjaiNl9JM6HH1Vdw==} cpu: [ppc64] os: [linux] - libc: [musl] '@rollup/rollup-linux-riscv64-gnu@4.55.1': resolution: {integrity: sha512-uW0Y12ih2XJRERZ4jAfKamTyIHVMPQnTZcQjme2HMVDAHY4amf5u414OqNYC+x+LzRdRcnIG1YodLrrtA8xsxw==} cpu: [riscv64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-riscv64-musl@4.55.1': resolution: {integrity: sha512-u9yZ0jUkOED1BFrqu3BwMQoixvGHGZ+JhJNkNKY/hyoEgOwlqKb62qu+7UjbPSHYjiVy8kKJHvXKv5coH4wDeg==} cpu: [riscv64] os: [linux] - libc: [musl] '@rollup/rollup-linux-s390x-gnu@4.55.1': resolution: {integrity: sha512-/0PenBCmqM4ZUd0190j7J0UsQ/1nsi735iPRakO8iPciE7BQ495Y6msPzaOmvx0/pn+eJVVlZrNrSh4WSYLxNg==} cpu: [s390x] os: [linux] - libc: [glibc] '@rollup/rollup-linux-x64-gnu@4.55.1': resolution: {integrity: sha512-a8G4wiQxQG2BAvo+gU6XrReRRqj+pLS2NGXKm8io19goR+K8lw269eTrPkSdDTALwMmJp4th2Uh0D8J9bEV1vg==} cpu: [x64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-x64-musl@4.55.1': resolution: {integrity: sha512-bD+zjpFrMpP/hqkfEcnjXWHMw5BIghGisOKPj+2NaNDuVT+8Ds4mPf3XcPHuat1tz89WRL+1wbcxKY3WSbiT7w==} cpu: [x64] os: [linux] - libc: [musl] '@rollup/rollup-openbsd-x64@4.55.1': resolution: {integrity: sha512-eLXw0dOiqE4QmvikfQ6yjgkg/xDM+MdU9YJuP4ySTibXU0oAvnEWXt7UDJmD4UkYialMfOGFPJnIHSe/kdzPxg==} @@ -1905,6 +1898,9 @@ packages: resolution: {integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==} engines: {node: '>=18'} + commander@2.20.3: + resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} + commander@5.1.0: resolution: {integrity: sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==} engines: {node: '>= 6'} @@ -3885,6 +3881,11 @@ packages: resolution: {integrity: sha512-yYrrsWnrXMcdsnu/7YMYAofM1ktpL5By7vZhf15CrXijWWrEYZks5AXBudalfSWJLlnen/QUJUB5aoB0kqZUGA==} engines: {node: '>=6.0.0'} + terser@5.46.0: + resolution: {integrity: sha512-jTwoImyr/QbOWFFso3YoU3ik0jBBDJ6JTOQiy/J2YxVJdZCc+5u7skhNwiOR3FQIygFqVUPHl7qbbxtjW2K3Qg==} + engines: {node: '>=10'} + hasBin: true + text-hex@1.0.0: resolution: {integrity: sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==} @@ -4941,6 +4942,11 @@ snapshots: '@jridgewell/resolve-uri@3.1.2': {} + '@jridgewell/source-map@0.3.11': + dependencies: + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + '@jridgewell/sourcemap-codec@1.5.5': {} '@jridgewell/trace-mapping@0.3.31': @@ -5696,7 +5702,7 @@ snapshots: '@use-gesture/core': 10.3.0 react: 19.2.3 - '@vitejs/plugin-react@5.1.2(vite@7.3.1(@types/node@22.19.5)(jiti@2.6.1))': + '@vitejs/plugin-react@5.1.2(vite@7.3.1(@types/node@22.19.5)(jiti@2.6.1)(terser@5.46.0))': dependencies: '@babel/core': 7.28.5 '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.28.5) @@ -5704,7 +5710,7 @@ snapshots: '@rolldown/pluginutils': 1.0.0-beta.53 '@types/babel__core': 7.20.5 react-refresh: 0.18.0 - vite: 7.3.1(@types/node@22.19.5)(jiti@2.6.1) + vite: 7.3.1(@types/node@22.19.5)(jiti@2.6.1)(terser@5.46.0) transitivePeerDependencies: - supports-color @@ -6220,6 +6226,8 @@ snapshots: commander@12.1.0: {} + commander@2.20.3: {} + commander@5.1.0: {} commander@9.5.0: @@ -6421,7 +6429,7 @@ snapshots: electron-to-chromium@1.5.267: {} - electron-vite@5.0.0(vite@7.3.1(@types/node@22.19.5)(jiti@2.6.1)): + electron-vite@5.0.0(vite@7.3.1(@types/node@22.19.5)(jiti@2.6.1)(terser@5.46.0)): dependencies: '@babel/core': 7.28.5 '@babel/plugin-transform-arrow-functions': 7.27.1(@babel/core@7.28.5) @@ -6429,7 +6437,7 @@ snapshots: esbuild: 0.25.12 magic-string: 0.30.21 picocolors: 1.1.1 - vite: 7.3.1(@types/node@22.19.5)(jiti@2.6.1) + vite: 7.3.1(@types/node@22.19.5)(jiti@2.6.1)(terser@5.46.0) transitivePeerDependencies: - supports-color @@ -8529,6 +8537,13 @@ snapshots: mkdirp: 0.5.6 rimraf: 2.6.3 + terser@5.46.0: + dependencies: + '@jridgewell/source-map': 0.3.11 + acorn: 8.15.0 + commander: 2.20.3 + source-map-support: 0.5.21 + text-hex@1.0.0: {} throttle-debounce@5.0.2: {} @@ -8717,7 +8732,7 @@ snapshots: extsprintf: 1.4.1 optional: true - vite@7.3.1(@types/node@22.19.5)(jiti@2.6.1): + vite@7.3.1(@types/node@22.19.5)(jiti@2.6.1)(terser@5.46.0): dependencies: esbuild: 0.27.2 fdir: 6.5.0(picomatch@4.0.3) @@ -8729,6 +8744,7 @@ snapshots: '@types/node': 22.19.5 fsevents: 2.3.3 jiti: 2.6.1 + terser: 5.46.0 void-elements@3.1.0: {} diff --git a/src/main/repos/EventRepository.ts b/src/main/repos/EventRepository.ts index 324d28d..b94e173 100644 --- a/src/main/repos/EventRepository.ts +++ b/src/main/repos/EventRepository.ts @@ -225,9 +225,7 @@ export class EventRepository extends Service { return { startTime, rows } } - async getLastScoreTimeByStudents( - studentNames: string[] - ): Promise> { + async getLastScoreTimeByStudents(studentNames: string[]): Promise> { if (studentNames.length === 0) return new Map() const repo = this.ctx.db.dataSource.getRepository(ScoreEventEntity) diff --git a/src/main/services/AutoScoreService.ts b/src/main/services/AutoScoreService.ts index 5893702..cb11382 100644 --- a/src/main/services/AutoScoreService.ts +++ b/src/main/services/AutoScoreService.ts @@ -1,6 +1,10 @@ import { Service } from '../../shared/kernel' import { MainContext } from '../context' -import { AutoScoreRuleEngine, type RuleConfig, type AutoScoreContext } from '../../shared/autoScore/AutoScoreRuleEngine' +import { + AutoScoreRuleEngine, + type RuleConfig, + type AutoScoreContext +} from '../../shared/autoScore/AutoScoreRuleEngine' interface AutoScoreRule extends RuleConfig { id: number @@ -385,7 +389,7 @@ export class AutoScoreService extends Service { id: s.id, name: s.name, tags: s.tags || [], - lastScoreTime: lastScoreTimeMap.get(s.name) || new Date(0), + lastScoreTime: lastScoreTimeMap.get(s.name) || new Date(0) })), events: [], rule: { diff --git a/src/mobile/components/Layout.tsx b/src/mobile/components/Layout.tsx index 7e0e13c..81073f3 100644 --- a/src/mobile/components/Layout.tsx +++ b/src/mobile/components/Layout.tsx @@ -1,5 +1,5 @@ import { Outlet, useLocation, useNavigate } from 'react-router-dom' -import { Layout, TabBar } from 'antd-mobile' +import { TabBar } from 'antd-mobile' import { HomeOutlined, PlusCircleOutlined, @@ -8,8 +8,6 @@ import { } from '@ant-design/icons' import { useTheme } from '../App' -const { Content } = Layout - const tabs = [ { key: '/', title: '主页', icon: }, { key: '/score', title: '积分', icon: }, @@ -23,15 +21,15 @@ export function MobileLayout(): React.JSX.Element { const { isDark } = useTheme() return ( - - +
- +
-
+ ) } diff --git a/src/renderer/src/components/AutoScoreManager.tsx b/src/renderer/src/components/AutoScoreManager.tsx index d0bc3c4..99c0ba8 100644 --- a/src/renderer/src/components/AutoScoreManager.tsx +++ b/src/renderer/src/components/AutoScoreManager.tsx @@ -42,10 +42,6 @@ interface ActionItem { value: string reason: string } -interface TagItem { - id: number - name: string -} interface AutoScoreRuleFormValues { name: string @@ -65,7 +61,6 @@ const ACTION_DEFINITIONS = [ export const AutoScoreManager: React.FC = () => { const { t } = useTranslation() const [rules, setRules] = useState([]) - const [allTags, setAllTags] = useState([]) const [students, setStudents] = useState<{ id: number; name: string }[]>([]) const [loading, setLoading] = useState(false) const [currentPage, setCurrentPage] = useState(1) @@ -85,19 +80,6 @@ export const AutoScoreManager: React.FC = () => { return def ? t(def.labelKey) : eventName } - async function fetchAllTags() { - if (!(window as any).api) return - try { - const res = await (window as any).api.tagsGetAll() - if (res.success && res.data) { - setAllTags(res.data) - } - } catch (e) { - console.error('Failed to fetch tags:', e) - messageApi.error(t('tags.fetchFailed')) - } - } - const fetchRules = async () => { if (!(window as any).api) return @@ -333,20 +315,6 @@ export const AutoScoreManager: React.FC = () => { ]) } - const handleRemoveTrigger = (id: number) => { - setTriggerList((prev) => prev.filter((t) => t.id !== id)) - } - - const handleTriggerChange = ( - id: number, - field: keyof TriggerItem, - value: string | number | 'AND' | 'OR' - ) => { - setTriggerList((prev) => - prev.map((t) => (t.id === id ? { ...t, [field]: value } : t)) - ) - } - const handleAddAction = () => { const nextId = actionList.length ? Math.max(...actionList.map((a) => a.id)) + 1 : 1 const defaultAction = ACTION_DEFINITIONS[0] @@ -369,14 +337,8 @@ export const AutoScoreManager: React.FC = () => { setActionList((prev) => prev.filter((a) => a.id !== id)) } - const handleActionChange = ( - id: number, - field: keyof ActionItem, - value: string | number - ) => { - setActionList((prev) => - prev.map((a) => (a.id === id ? { ...a, [field]: value } : a)) - ) + const handleActionChange = (id: number, field: keyof ActionItem, value: string | number) => { + setActionList((prev) => prev.map((a) => (a.id === id ? { ...a, [field]: value } : a))) } const columns: ColumnsType = [ @@ -481,72 +443,6 @@ export const AutoScoreManager: React.FC = () => { } ] - const renderTriggerItem = (trigger: TriggerItem, index: number) => ( -
- - {index > 0 && ( - handleTriggerChange(trigger.id, 'eventName', value)} - style={{ width: 150 }} - options={TRIGGER_DEFINITIONS.map((d) => ({ - label: t(d.labelKey), - value: d.eventName - }))} - /> - {trigger.eventName === 'interval_time_passed' && ( - handleTriggerChange(trigger.id, 'value', String(value || 0))} - placeholder={t('autoScore.minutesPlaceholder')} - min={1} - style={{ width: 120 }} - addonAfter={t('autoScore.minutes')} - /> - )} - {trigger.eventName === 'student_has_tag' && ( -