智能开屏:显示“姓名+早上/中午/下午/晚上问候”,支持春节、端午、中秋、国庆等节日文案,可点击跳过:[SmartLaunchScreen.vue](E:/jiaowu/web/src/components/SmartLaunchScreen.vue)

长按 App 图标:提供“我的课表、考试安排、课堂签到、消息中心”四个入口。签到会按学生/教师角色自动分流:[shortcuts.xml](E:/jiaowu/web/native/android/app/src/main/res/xml/shortcuts.xml)
桌面小组件:新增“今日课表”和“近期考试”,展示最近同步的数据,点击可进入对应页面:[WidgetRenderer.java](E:/jiaowu/web/native/android/app/src/main/java/edu/mingxu/jiaowu/WidgetRenderer.java)
安全处理:组件只缓存课程和考试摘要,不保存登录令牌;退出账号会清空组件,隔天未刷新时不会继续展示旧的“今日课表”。
原生模板已纳入版本管理,每次 npm run cap:sync 会自动恢复到被忽略的 Android 工程:[configure-capacitor.mjs](E:/jiaowu/web/scripts/configure-capacitor.mjs)
This commit is contained in:
2026-07-29 11:11:37 +08:00 Unverified
parent 93997ea8b1
commit 66622ca207
27 changed files with 1304 additions and 5 deletions
@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#173B72"
android:pathData="M3,3h7v2H5v5H3zM14,3h7v7h-2V5h-5zM3,14h2v5h5v2H3zM19,14h2v7h-7v-2h5zM7,7h10v10H7zM9,9v6h6V9z" />
</vector>
@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#173B72"
android:pathData="M14,2H6c-1.1,0 -2,0.9 -2,2v16c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2V8zM13,9V3.5L18.5,9zM8,13h8v2H8zM8,17h8v2H8z" />
</vector>
@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#173B72"
android:pathData="M12,22c1.1,0 1.99,-0.9 1.99,-2h-4c0,1.1 0.9,2 2.01,2zM18,16v-5c0,-3.07 -1.63,-5.64 -4.5,-6.32V4c0,-0.83 -0.67,-1.5 -1.5,-1.5S10.5,3.17 10.5,4v0.68C7.64,5.36 6,7.92 6,11v5l-2,2v1h16v-1z" />
</vector>
@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#173B72"
android:pathData="M19,4h-1V2h-2v2H8V2H6v2H5c-1.11,0 -1.99,0.9 -1.99,2L3,20c0,1.1 0.89,2 2,2h14c1.1,0 2,-0.9 2,-2V6c0,-1.1 -0.9,-2 -2,-2zM19,20H5V9h14v11zM7,11h5v5H7z" />
</vector>
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="3dp" />
<solid android:color="#2F8F89" />
</shape>
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="24dp" />
<gradient
android:angle="315"
android:startColor="#F8FBFF"
android:endColor="#EAF2FF" />
<stroke
android:width="1dp"
android:color="#DCE7F8" />
</shape>
@@ -0,0 +1,102 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/widget_root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/widget_background"
android:clickable="true"
android:focusable="true"
android:orientation="vertical"
android:padding="16dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
<View
android:layout_width="5dp"
android:layout_height="22dp"
android:layout_marginEnd="9dp"
android:background="@drawable/widget_accent" />
<TextView
android:id="@+id/widget_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:ellipsize="end"
android:maxLines="1"
android:text="今日课表"
android:textColor="#102652"
android:textSize="16sp"
android:textStyle="bold" />
<TextView
android:id="@+id/widget_updated"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="等待同步"
android:textColor="#74839E"
android:textSize="10sp" />
</LinearLayout>
<TextView
android:id="@+id/widget_empty"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:gravity="center"
android:text="登录 App 后同步教务数据"
android:textColor="#61718D"
android:textSize="13sp" />
<LinearLayout
android:id="@+id/widget_row_one"
style="@style/WidgetAcademicRow">
<TextView
android:id="@+id/widget_time_one"
style="@style/WidgetAcademicTime" />
<LinearLayout style="@style/WidgetAcademicCopy">
<TextView
android:id="@+id/widget_item_title_one"
style="@style/WidgetAcademicTitle" />
<TextView
android:id="@+id/widget_item_subtitle_one"
style="@style/WidgetAcademicSubtitle" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:id="@+id/widget_row_two"
style="@style/WidgetAcademicRow">
<TextView
android:id="@+id/widget_time_two"
style="@style/WidgetAcademicTime" />
<LinearLayout style="@style/WidgetAcademicCopy">
<TextView
android:id="@+id/widget_item_title_two"
style="@style/WidgetAcademicTitle" />
<TextView
android:id="@+id/widget_item_subtitle_two"
style="@style/WidgetAcademicSubtitle" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:id="@+id/widget_row_three"
style="@style/WidgetAcademicRow">
<TextView
android:id="@+id/widget_time_three"
style="@style/WidgetAcademicTime" />
<LinearLayout style="@style/WidgetAcademicCopy">
<TextView
android:id="@+id/widget_item_title_three"
style="@style/WidgetAcademicTitle" />
<TextView
android:id="@+id/widget_item_subtitle_three"
style="@style/WidgetAcademicSubtitle" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
@@ -0,0 +1,17 @@
<?xml version='1.0' encoding='utf-8'?>
<resources>
<string name="app_name">明序教务</string>
<string name="title_activity_main">明序教务</string>
<string name="package_name">edu.mingxu.jiaowu</string>
<string name="custom_url_scheme">edu.mingxu.jiaowu</string>
<string name="shortcut_timetable_short">我的课表</string>
<string name="shortcut_timetable_long">查看我的今日课表</string>
<string name="shortcut_exams_short">考试安排</string>
<string name="shortcut_exams_long">查看近期考试安排</string>
<string name="shortcut_attendance_short">课堂签到</string>
<string name="shortcut_attendance_long">扫码、定位或发起签到</string>
<string name="shortcut_notifications_short">消息中心</string>
<string name="shortcut_notifications_long">查看教务通知和待办</string>
<string name="widget_schedule_name">明序今日课表</string>
<string name="widget_exam_name">明序近期考试</string>
</resources>
@@ -0,0 +1,67 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
<style name="AppTheme.NoActionBar" parent="Theme.AppCompat.DayNight.NoActionBar">
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
<item name="android:background">@null</item>
</style>
<style name="AppTheme.NoActionBarLaunch" parent="Theme.SplashScreen">
<item name="android:background">@drawable/splash</item>
</style>
<style name="WidgetAcademicRow">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">0dp</item>
<item name="android:layout_weight">1</item>
<item name="android:gravity">center_vertical</item>
<item name="android:minHeight">42dp</item>
<item name="android:orientation">horizontal</item>
</style>
<style name="WidgetAcademicTime">
<item name="android:layout_width">76dp</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:ellipsize">end</item>
<item name="android:maxLines">1</item>
<item name="android:textColor">#2F8F89</item>
<item name="android:textSize">11sp</item>
<item name="android:textStyle">bold</item>
</style>
<style name="WidgetAcademicCopy">
<item name="android:layout_width">0dp</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_weight">1</item>
<item name="android:orientation">vertical</item>
</style>
<style name="WidgetAcademicTitle">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:ellipsize">end</item>
<item name="android:maxLines">1</item>
<item name="android:textColor">#152848</item>
<item name="android:textSize">13sp</item>
<item name="android:textStyle">bold</item>
</style>
<style name="WidgetAcademicSubtitle">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:ellipsize">end</item>
<item name="android:maxLines">1</item>
<item name="android:textColor">#74839E</item>
<item name="android:textSize">10sp</item>
</style>
</resources>
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:description="@string/widget_exam_name"
android:initialLayout="@layout/widget_academic"
android:minWidth="250dp"
android:minHeight="120dp"
android:previewLayout="@layout/widget_academic"
android:resizeMode="horizontal|vertical"
android:updatePeriodMillis="1800000"
android:widgetCategory="home_screen" />
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:description="@string/widget_schedule_name"
android:initialLayout="@layout/widget_academic"
android:minWidth="250dp"
android:minHeight="120dp"
android:previewLayout="@layout/widget_academic"
android:resizeMode="horizontal|vertical"
android:updatePeriodMillis="1800000"
android:widgetCategory="home_screen" />
@@ -0,0 +1,51 @@
<?xml version="1.0" encoding="utf-8"?>
<shortcuts xmlns:android="http://schemas.android.com/apk/res/android">
<shortcut
android:shortcutId="timetable"
android:enabled="true"
android:icon="@drawable/ic_shortcut_timetable"
android:shortcutShortLabel="@string/shortcut_timetable_short"
android:shortcutLongLabel="@string/shortcut_timetable_long">
<intent
android:action="android.intent.action.VIEW"
android:targetPackage="edu.mingxu.jiaowu"
android:targetClass="edu.mingxu.jiaowu.MainActivity"
android:data="mingxu://open/timetable" />
</shortcut>
<shortcut
android:shortcutId="exams"
android:enabled="true"
android:icon="@drawable/ic_shortcut_exam"
android:shortcutShortLabel="@string/shortcut_exams_short"
android:shortcutLongLabel="@string/shortcut_exams_long">
<intent
android:action="android.intent.action.VIEW"
android:targetPackage="edu.mingxu.jiaowu"
android:targetClass="edu.mingxu.jiaowu.MainActivity"
android:data="mingxu://open/exams" />
</shortcut>
<shortcut
android:shortcutId="attendance"
android:enabled="true"
android:icon="@drawable/ic_shortcut_attendance"
android:shortcutShortLabel="@string/shortcut_attendance_short"
android:shortcutLongLabel="@string/shortcut_attendance_long">
<intent
android:action="android.intent.action.VIEW"
android:targetPackage="edu.mingxu.jiaowu"
android:targetClass="edu.mingxu.jiaowu.MainActivity"
android:data="mingxu://open/attendance" />
</shortcut>
<shortcut
android:shortcutId="notifications"
android:enabled="true"
android:icon="@drawable/ic_shortcut_notifications"
android:shortcutShortLabel="@string/shortcut_notifications_short"
android:shortcutLongLabel="@string/shortcut_notifications_long">
<intent
android:action="android.intent.action.VIEW"
android:targetPackage="edu.mingxu.jiaowu"
android:targetClass="edu.mingxu.jiaowu.MainActivity"
android:data="mingxu://open/notifications" />
</shortcut>
</shortcuts>