|
|
|
@ -0,0 +1,361 @@
|
|
|
|
|
package com.example.doitnow;
|
|
|
|
|
|
|
|
|
|
import android.content.DialogInterface;
|
|
|
|
|
import android.content.Intent;
|
|
|
|
|
import android.os.Bundle;
|
|
|
|
|
import android.os.Handler;
|
|
|
|
|
import android.os.Looper;
|
|
|
|
|
import android.view.MenuItem;
|
|
|
|
|
import android.view.View;
|
|
|
|
|
import android.webkit.CookieManager;
|
|
|
|
|
import android.webkit.WebResourceRequest;
|
|
|
|
|
import android.webkit.WebSettings;
|
|
|
|
|
import android.webkit.WebView;
|
|
|
|
|
import android.webkit.WebViewClient;
|
|
|
|
|
import android.widget.Toast;
|
|
|
|
|
|
|
|
|
|
import androidx.annotation.NonNull;
|
|
|
|
|
import androidx.appcompat.app.AppCompatActivity;
|
|
|
|
|
import androidx.core.view.ViewCompat;
|
|
|
|
|
import androidx.core.view.WindowInsetsCompat;
|
|
|
|
|
import androidx.fragment.app.Fragment;
|
|
|
|
|
import androidx.fragment.app.FragmentTransaction;
|
|
|
|
|
|
|
|
|
|
import com.google.android.material.bottomnavigation.BottomNavigationView;
|
|
|
|
|
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
|
|
|
|
|
|
|
|
|
import org.json.JSONArray;
|
|
|
|
|
import org.json.JSONException;
|
|
|
|
|
import org.json.JSONObject;
|
|
|
|
|
|
|
|
|
|
import java.io.IOException;
|
|
|
|
|
import java.text.ParseException;
|
|
|
|
|
import java.text.SimpleDateFormat;
|
|
|
|
|
import java.util.ArrayList;
|
|
|
|
|
import java.util.Arrays;
|
|
|
|
|
import java.util.Calendar;
|
|
|
|
|
import java.util.Date;
|
|
|
|
|
import java.util.HashMap;
|
|
|
|
|
import java.util.LinkedHashMap;
|
|
|
|
|
import java.util.List;
|
|
|
|
|
import java.util.Map;
|
|
|
|
|
|
|
|
|
|
import okhttp3.Call;
|
|
|
|
|
import okhttp3.Callback;
|
|
|
|
|
import okhttp3.OkHttpClient;
|
|
|
|
|
import okhttp3.Request;
|
|
|
|
|
import okhttp3.Response;
|
|
|
|
|
import com.example.doitnow.Adapter.kebiaoManager;
|
|
|
|
|
|
|
|
|
|
public class MainActivity extends AppCompatActivity implements DialogCloseListener {
|
|
|
|
|
|
|
|
|
|
private FloatingActionButton fab,fab4;
|
|
|
|
|
private BottomNavigationView bottomNavigationView;
|
|
|
|
|
private Fragment currentFragment;
|
|
|
|
|
public static List<Lesson> kebiaodata=new ArrayList<>();
|
|
|
|
|
private kebiaoManager km;
|
|
|
|
|
private boolean FinishGetting;
|
|
|
|
|
public static String getWeekdayFromSunday(String sundayStr, int weekdayNumber) throws ParseException {
|
|
|
|
|
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-M-d");
|
|
|
|
|
|
|
|
|
|
// 將字串轉成 Date
|
|
|
|
|
Date sundayDate = sdf.parse(sundayStr);
|
|
|
|
|
|
|
|
|
|
// 設定 Calendar 為這個週日
|
|
|
|
|
Calendar calendar = Calendar.getInstance();
|
|
|
|
|
calendar.setTime(sundayDate);
|
|
|
|
|
|
|
|
|
|
// 計算需要加幾天(1 = 星期一, ..., 7 = 星期日)
|
|
|
|
|
int daysToAdd = weekdayNumber % 7; // 若是 7 (星期日),則加 0 天
|
|
|
|
|
calendar.add(Calendar.DATE, daysToAdd);
|
|
|
|
|
|
|
|
|
|
// 回傳結果
|
|
|
|
|
return sdf.format(calendar.getTime());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public List<String> getSundaysInRange(String startDate) {
|
|
|
|
|
List<String> sundays = new ArrayList<>();
|
|
|
|
|
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-M-d"); // 修改为无前导零的格式
|
|
|
|
|
try {
|
|
|
|
|
// 将日期字符串转换为 Date 对象
|
|
|
|
|
Date start = dateFormat.parse(startDate);
|
|
|
|
|
|
|
|
|
|
Calendar calendar = Calendar.getInstance();
|
|
|
|
|
calendar.setTime(start);
|
|
|
|
|
|
|
|
|
|
// 如果开始日期不是周日,找到下一个周日
|
|
|
|
|
if (calendar.get(Calendar.DAY_OF_WEEK) != Calendar.SUNDAY) {
|
|
|
|
|
calendar.add(Calendar.DAY_OF_MONTH, Calendar.SUNDAY - calendar.get(Calendar.DAY_OF_WEEK));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 逐个添加每个周日到列表中
|
|
|
|
|
for (int i=0;i<16;i++){
|
|
|
|
|
sundays.add(dateFormat.format(calendar.getTime()));
|
|
|
|
|
km.insertweek(i+1,dateFormat.format(calendar.getTime()));
|
|
|
|
|
calendar.add(Calendar.WEEK_OF_YEAR, 1); // 每次递增一周
|
|
|
|
|
}
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return sundays;
|
|
|
|
|
}
|
|
|
|
|
private void getCookies(String url) throws IOException, ParseException {
|
|
|
|
|
CookieManager cookieManager = CookieManager.getInstance();
|
|
|
|
|
String cookies = cookieManager.getCookie(url);
|
|
|
|
|
Map<String, String> cookiesMap = new HashMap<>();
|
|
|
|
|
for (String cookie : cookies.split(";")) {
|
|
|
|
|
String[] parts = cookie.trim().split("=", 2);
|
|
|
|
|
if (parts.length == 2) {
|
|
|
|
|
cookiesMap.put(parts[0], parts[1]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
List<String> order = Arrays.asList(
|
|
|
|
|
"JSESSIONID", "iPlanetDirectoryPro", "SF_cookie_2",
|
|
|
|
|
"RouTe_WAF_E1268C", "PORTAL-TOKEN", "SF_cookie_1",
|
|
|
|
|
"web_m_site", "route"
|
|
|
|
|
);
|
|
|
|
|
Map<String, String> sortedCookies = new LinkedHashMap<>();
|
|
|
|
|
for (String key : order) {
|
|
|
|
|
if (cookiesMap.containsKey(key)) {
|
|
|
|
|
sortedCookies.put(key, cookiesMap.get(key));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
StringBuilder sortedCookieHeader = new StringBuilder();
|
|
|
|
|
for (Map.Entry<String, String> entry : sortedCookies.entrySet()) {
|
|
|
|
|
sortedCookieHeader.append(entry.getKey()).append("=").append(entry.getValue()).append("; ");
|
|
|
|
|
}
|
|
|
|
|
List<String> sundays=getSundaysInRange("2025-2-16");
|
|
|
|
|
km.deleteLesson();
|
|
|
|
|
String nodateUrl = "https://zhlj.whu.edu.cn/mobile/homepageapi/getCurriculumData?date=";
|
|
|
|
|
for(String sunday : sundays) {
|
|
|
|
|
OkHttpClient client = new OkHttpClient();
|
|
|
|
|
String apiUrl=nodateUrl+sunday;
|
|
|
|
|
Request request = new Request.Builder()
|
|
|
|
|
.url(apiUrl)
|
|
|
|
|
.addHeader("Cookie", sortedCookieHeader.toString()) // 设置 Cookie
|
|
|
|
|
.build();
|
|
|
|
|
client.newCall(request).enqueue(new Callback() {
|
|
|
|
|
@Override
|
|
|
|
|
public void onFailure(Call call, IOException e) {
|
|
|
|
|
runOnUiThread(() ->
|
|
|
|
|
Toast.makeText(MainActivity.this, "請求失敗: " + e.getMessage(), Toast.LENGTH_SHORT).show()
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void onResponse(Call call, Response response) throws IOException {
|
|
|
|
|
if (response.isSuccessful() && response.body() != null) {
|
|
|
|
|
String responseData = response.body().string();
|
|
|
|
|
displayCurriculumData(responseData,sunday);
|
|
|
|
|
} else {
|
|
|
|
|
runOnUiThread(() ->
|
|
|
|
|
Toast.makeText(MainActivity.this, "請求失敗,狀態碼: " + response.code(), Toast.LENGTH_SHORT).show()
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
public void displayCurriculumData(String responseData,String date) {
|
|
|
|
|
try {
|
|
|
|
|
JSONObject response = new JSONObject(responseData);
|
|
|
|
|
if (response.getInt("code") == 200) {
|
|
|
|
|
JSONArray data = response.getJSONArray("data");
|
|
|
|
|
for (int i = 0; i < data.length(); i++) {
|
|
|
|
|
JSONObject dayData = data.getJSONObject(i);
|
|
|
|
|
int day = dayData.getInt("day");
|
|
|
|
|
JSONArray curriculumList = dayData.getJSONArray("curriculumList");
|
|
|
|
|
for (int j = 0; j < curriculumList.length(); j++) {
|
|
|
|
|
JSONObject curriculum = curriculumList.getJSONObject(j);
|
|
|
|
|
// 只有當有有效數據時才顯示
|
|
|
|
|
if (curriculum.has("name") && curriculum.getString("name")!="null") {
|
|
|
|
|
Lesson temp = new Lesson();
|
|
|
|
|
String today = getWeekdayFromSunday(date, day);
|
|
|
|
|
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-M-d");
|
|
|
|
|
Date d = sdf.parse(today);
|
|
|
|
|
temp.name = curriculum.getString("name");
|
|
|
|
|
temp.teacher = curriculum.getString("teacher");
|
|
|
|
|
temp.classroom = curriculum.getString("classroom");
|
|
|
|
|
temp.fromClass = curriculum.getInt("fromClass");
|
|
|
|
|
temp.endClass = curriculum.getInt("endClass");
|
|
|
|
|
temp.day = day;
|
|
|
|
|
temp.date = d;
|
|
|
|
|
km.insertLesson(temp);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} catch (JSONException e) {
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
} catch (ParseException e) {
|
|
|
|
|
throw new RuntimeException(e);
|
|
|
|
|
}
|
|
|
|
|
FinishGetting=true;
|
|
|
|
|
}
|
|
|
|
|
public void takekebiaoClick(View view)
|
|
|
|
|
{
|
|
|
|
|
FinishGetting=false;
|
|
|
|
|
WebView webView = findViewById(R.id.webview);
|
|
|
|
|
webView.setVisibility(View.VISIBLE); // 確保 WebView 是可見的
|
|
|
|
|
webView.bringToFront();
|
|
|
|
|
webView.clearCache(true); // 🔥 關鍵
|
|
|
|
|
webView.clearHistory(); // 🔥 關鍵
|
|
|
|
|
webView.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE); // 🔥 關鍵
|
|
|
|
|
webView.getSettings().setJavaScriptEnabled(true);
|
|
|
|
|
webView.getSettings().setDomStorageEnabled(true); // ⬅️ 確保能開 modern JS 服務
|
|
|
|
|
webView.setWebViewClient(new WebViewClient() {
|
|
|
|
|
@Override
|
|
|
|
|
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
|
|
|
|
|
return false; // 让 WebView 继续加载
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void onPageFinished(WebView view, String url) {
|
|
|
|
|
super.onPageFinished(view, url);
|
|
|
|
|
|
|
|
|
|
if (url.equals("https://zhlj.whu.edu.cn/mobile/apppage/h5page")) { // 登录成功后访问的页面
|
|
|
|
|
try {
|
|
|
|
|
// 等待 Cookie 更新完成
|
|
|
|
|
new Handler(Looper.getMainLooper()).postDelayed(() -> {
|
|
|
|
|
try {
|
|
|
|
|
getCookies(url);// 获取 cookies
|
|
|
|
|
} catch (IOException e) {
|
|
|
|
|
throw new RuntimeException(e);
|
|
|
|
|
} catch (ParseException e) {
|
|
|
|
|
throw new RuntimeException(e);
|
|
|
|
|
}
|
|
|
|
|
webView.setVisibility(View.INVISIBLE);
|
|
|
|
|
}, 1000); // 延迟 1 秒获取 cookie,确保 Cookie 已经更新
|
|
|
|
|
} catch (Exception ex) {
|
|
|
|
|
ex.printStackTrace();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
String loginUrl = "https://cas.whu.edu.cn/authserver/login?service=https%3A%2F%2Fzhlj.whu.edu.cn%2FcasLogin";
|
|
|
|
|
webView.loadUrl(loginUrl);
|
|
|
|
|
}
|
|
|
|
|
@Override
|
|
|
|
|
protected void onCreate(Bundle savedInstanceState) {
|
|
|
|
|
super.onCreate(savedInstanceState);
|
|
|
|
|
setContentView(R.layout.activity_main);
|
|
|
|
|
fab = findViewById(R.id.fab);
|
|
|
|
|
bottomNavigationView = findViewById(R.id.bottom_navigation);
|
|
|
|
|
fab4=findViewById(R.id.fab4);
|
|
|
|
|
km=new kebiaoManager(this);
|
|
|
|
|
ViewCompat.setOnApplyWindowInsetsListener(findViewById(android.R.id.content), (v, insets) -> {
|
|
|
|
|
WindowInsetsCompat systemBars = insets;
|
|
|
|
|
v.setPadding(systemBars.getInsets(WindowInsetsCompat.Type.systemBars()).left,
|
|
|
|
|
systemBars.getInsets(WindowInsetsCompat.Type.systemBars()).top,
|
|
|
|
|
systemBars.getInsets(WindowInsetsCompat.Type.systemBars()).right,
|
|
|
|
|
systemBars.getInsets(WindowInsetsCompat.Type.systemBars()).bottom);
|
|
|
|
|
return insets;
|
|
|
|
|
});
|
|
|
|
|
fab.setOnClickListener(v ->
|
|
|
|
|
AddNewTask.newInstance().show(getSupportFragmentManager(), AddNewTask.TAG)
|
|
|
|
|
);
|
|
|
|
|
fab4.setOnClickListener(this::takekebiaoClick);
|
|
|
|
|
bottomNavigationView.setOnItemSelectedListener(new BottomNavigationView.OnItemSelectedListener() {
|
|
|
|
|
@Override
|
|
|
|
|
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
|
|
|
|
|
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
|
|
|
|
|
|
|
|
|
|
Fragment newFragment = null;
|
|
|
|
|
String tag = "";
|
|
|
|
|
|
|
|
|
|
int id = item.getItemId();
|
|
|
|
|
if (id == R.id.nav_calendar) {
|
|
|
|
|
tag = "calendar";
|
|
|
|
|
} else if (id == R.id.nav_alltodo) {
|
|
|
|
|
tag = "alltodo";
|
|
|
|
|
} else if (id == R.id.nav_schedule) {
|
|
|
|
|
tag = "schedule";
|
|
|
|
|
} else if (id == R.id.nav_plant) {
|
|
|
|
|
tag = "plant";
|
|
|
|
|
} else if (id==R.id.nav_ai) {
|
|
|
|
|
tag="ai";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
newFragment = getSupportFragmentManager().findFragmentByTag(tag);
|
|
|
|
|
if (newFragment == null) {
|
|
|
|
|
switch (tag) {
|
|
|
|
|
case "calendar":
|
|
|
|
|
newFragment = new CalendarFragment();
|
|
|
|
|
break;
|
|
|
|
|
case "alltodo":
|
|
|
|
|
newFragment = new AllTodoFragment();
|
|
|
|
|
break;
|
|
|
|
|
case "schedule":
|
|
|
|
|
newFragment = new ScheduleFragment();
|
|
|
|
|
break;
|
|
|
|
|
case "plant":
|
|
|
|
|
newFragment = new PlantFragment();
|
|
|
|
|
break;
|
|
|
|
|
case "ai":
|
|
|
|
|
newFragment = new AIFragment();
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
transaction.add(R.id.fragment_container, newFragment, tag);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (currentFragment != null && currentFragment != newFragment) {
|
|
|
|
|
transaction.hide(currentFragment);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
transaction.show(newFragment);
|
|
|
|
|
transaction.commit();
|
|
|
|
|
currentFragment = newFragment;
|
|
|
|
|
|
|
|
|
|
if ("schedule".equals(tag)){
|
|
|
|
|
fab.setVisibility(View.GONE);
|
|
|
|
|
fab4.setVisibility(View.VISIBLE);
|
|
|
|
|
} else if ("alltodo".equals(tag)||("calendar".equals(tag))) {
|
|
|
|
|
fab4.setVisibility(View.GONE);
|
|
|
|
|
fab.setVisibility(View.VISIBLE);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
fab.setVisibility(View.GONE);
|
|
|
|
|
fab4.setVisibility(View.GONE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 預設打開 AllTodoFragment
|
|
|
|
|
if (savedInstanceState == null) {
|
|
|
|
|
currentFragment = new AllTodoFragment();
|
|
|
|
|
getSupportFragmentManager()
|
|
|
|
|
.beginTransaction()
|
|
|
|
|
.add(R.id.fragment_container, currentFragment, "alltodo")
|
|
|
|
|
.commit();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bottomNavigationView.setSelectedItemId(R.id.nav_alltodo);
|
|
|
|
|
|
|
|
|
|
getSupportFragmentManager().setFragmentResultListener(
|
|
|
|
|
"taskAdded", this, (key, bundle) -> {
|
|
|
|
|
boolean added = bundle.getBoolean("taskAdded", false);
|
|
|
|
|
if (added) {
|
|
|
|
|
updateTaskList(); // 下面我會幫你補這個方法
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void handleDialogClose(DialogInterface dialog) {
|
|
|
|
|
if (currentFragment instanceof AllTodoFragment) {
|
|
|
|
|
((AllTodoFragment) currentFragment).refreshData();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void updateTaskList() {
|
|
|
|
|
Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.fragment_container);
|
|
|
|
|
if (fragment instanceof AllTodoFragment) {
|
|
|
|
|
((AllTodoFragment) fragment).refreshTaskList();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|