Browse Source

管理员功能complete

bfzgs 2 years ago
parent
commit
0a7742a275
20 changed files with 517 additions and 40 deletions
  1. 2 1
      app/build.gradle
  2. 9 1
      app/src/main/AndroidManifest.xml
  3. 19 0
      app/src/main/assets/echarts.html
  4. 0 0
      app/src/main/assets/echarts.min.js
  5. 39 31
      app/src/main/java/org/brynhild/graduation/activity/admin/ClassDetailInfoActivity.kt
  6. 9 0
      app/src/main/java/org/brynhild/graduation/activity/admin/UserDetailInfoActivity.kt
  7. 191 0
      app/src/main/java/org/brynhild/graduation/activity/common/StatisticActivity.kt
  8. 3 0
      app/src/main/java/org/brynhild/graduation/activity/common/TimetableActivity.kt
  9. 9 0
      app/src/main/java/org/brynhild/graduation/common/constant/StatisticConstant.java
  10. 14 0
      app/src/main/java/org/brynhild/graduation/common/transfer/bo/timetable/StatisticInfo.kt
  11. 5 0
      app/src/main/java/org/brynhild/graduation/common/transfer/vo/timetable/AdminQueryClassStatistic.kt
  12. 5 0
      app/src/main/java/org/brynhild/graduation/common/transfer/vo/timetable/AdminQueryStudentStatistic.kt
  13. 53 0
      app/src/main/java/org/brynhild/graduation/common/utils/FileDownloadUtil.java
  14. 28 0
      app/src/main/java/org/brynhild/graduation/common/utils/FileUtils.java
  15. 7 0
      app/src/main/java/org/brynhild/graduation/service/http/AdminService.kt
  16. 30 0
      app/src/main/java/org/brynhild/graduation/service/http/CommonService.kt
  17. 8 7
      app/src/main/res/layout/activity_class_detail_info.xml
  18. 72 0
      app/src/main/res/layout/activity_statistic.xml
  19. 9 0
      app/src/main/res/layout/activity_user_detail_info.xml
  20. 5 0
      app/src/main/res/menu/admin_class_detail_info_options.xml

+ 2 - 1
app/build.gradle

@@ -84,7 +84,8 @@ dependencies {
 
     implementation 'com.github.zfman:TimetableView:v2.0.7'
 
-    testImplementation 'junit:junit:4.13.2'
+
+    testImplementation 'junit:junit:3.0.0.5'
     androidTestImplementation 'androidx.test.ext:junit:1.1.3'
     androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
 

+ 9 - 1
app/src/main/AndroidManifest.xml

@@ -28,13 +28,20 @@
         android:theme="@style/AppTheme.NoActionBar"
         tools:targetApi="31">
         <activity
-            android:name=".activity.common.TimetableActivity"
+            android:name=".activity.common.StatisticActivity"
             android:exported="true">
 
             <meta-data
                 android:name="android.app.lib_name"
                 android:value="" />
         </activity>
+        <activity
+            android:name=".activity.common.TimetableActivity"
+            android:exported="true">
+            <meta-data
+                android:name="android.app.lib_name"
+                android:value="" />
+        </activity>
         <activity
             android:name=".activity.admin.AcademyDetailInfoActivity"
             android:exported="false">
@@ -122,6 +129,7 @@
         <activity
             android:name=".MainActivity"
             android:exported="true">
+
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
 

+ 19 - 0
app/src/main/assets/echarts.html

@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html style="height: 100%">
+<head>
+    <meta name="viewport" content="width=device-width, initial-scale=1"/>
+    <meta charset="utf-8">
+</head>
+<body style="height: 100%; margin: 0">
+<div id="container" style="height: 600px;width: 400px"></div>
+<script type="text/javascript" src="echarts.min.js"></script>
+<script type="text/javascript">
+        var chart = echarts.init(document.getElementById('container'));
+
+function setChartOptions(options) {
+            chart.setOption(options);
+        }
+
+</script>
+</body>
+</html>

File diff suppressed because it is too large
+ 0 - 0
app/src/main/assets/echarts.min.js


+ 39 - 31
app/src/main/java/org/brynhild/graduation/activity/admin/ClassDetailInfoActivity.kt

@@ -13,9 +13,11 @@ import com.example.devicemanager.view.ConfirmPopupWindow
 import com.google.gson.Gson
 import org.brynhild.graduation.R
 import org.brynhild.graduation.activity.common.BaseActivity
+import org.brynhild.graduation.activity.common.StatisticActivity
 import org.brynhild.graduation.activity.common.TimetableActivity
 import org.brynhild.graduation.common.callback.RecyclerViewCallback
 import org.brynhild.graduation.common.config.LoginConfiguration
+import org.brynhild.graduation.common.constant.StatisticConstant
 import org.brynhild.graduation.common.transfer.Result
 import org.brynhild.graduation.common.transfer.handler.ResponseHandler
 import org.brynhild.graduation.common.transfer.utils.ServiceCreator
@@ -169,37 +171,11 @@ class ClassDetailInfoActivity : BaseActivity() {
             finish()
         }
 
-        binding.adminClassDelete.setOnClickListener {
-            ConfirmPopupWindow.ConfirmPopupWindowBuilder.init(this@ClassDetailInfoActivity)
-                .setContent("确定删除班级:${classEntity.name}吗")
-                .setCancelText("取消删除")
-                .setEnsureText("确定删除")
-                .setEnsureListener {
-                    val service = ServiceCreator.create(AdminService::class.java)
-                    val rmList = ArrayList<Long>()
-                    rmList.add(classEntity.id)
-                    val rmData = AdminDeleteClass(rmList)
-                    service.deleteClass(LoginConfiguration.userInfo!!.token, rmData)
-                        .enqueue(object :
-                            Callback<Result> {
-                            override fun onResponse(
-                                call: Call<Result>,
-                                response: Response<Result>
-                            ) {
-                                ResponseHandler.handle(response, {
-                                    finish()
-                                }, {
-                                    ResponseHandler.showMessage(it)
-                                })
-                            }
-
-                            override fun onFailure(call: Call<Result>, t: Throwable) {
-                                t.printStackTrace()
-                            }
-                        })
-                }
-                .build()
-                .show()
+        binding.adminClassStatistic.setOnClickListener {
+            val intent=Intent(this,StatisticActivity::class.java)
+            intent.putExtra(StatisticConstant.ACTION,StatisticConstant.CLASS_ACTION)
+            intent.putExtra(StatisticConstant.ID_ENUM,classEntity.id)
+            startActivity(intent)
         }
 
         binding.adminClassBatchEnroll.setOnClickListener {
@@ -448,6 +424,38 @@ class ClassDetailInfoActivity : BaseActivity() {
                     }
                     .show()
             }
+            R.id.admin_class_delete->{
+                ConfirmPopupWindow.ConfirmPopupWindowBuilder.init(this@ClassDetailInfoActivity)
+                    .setContent("确定删除班级:${classEntity.name}吗")
+                    .setCancelText("取消删除")
+                    .setEnsureText("确定删除")
+                    .setEnsureListener {
+                        val service = ServiceCreator.create(AdminService::class.java)
+                        val rmList = ArrayList<Long>()
+                        rmList.add(classEntity.id)
+                        val rmData = AdminDeleteClass(rmList)
+                        service.deleteClass(LoginConfiguration.userInfo!!.token, rmData)
+                            .enqueue(object :
+                                Callback<Result> {
+                                override fun onResponse(
+                                    call: Call<Result>,
+                                    response: Response<Result>
+                                ) {
+                                    ResponseHandler.handle(response, {
+                                        finish()
+                                    }, {
+                                        ResponseHandler.showMessage(it)
+                                    })
+                                }
+
+                                override fun onFailure(call: Call<Result>, t: Throwable) {
+                                    t.printStackTrace()
+                                }
+                            })
+                    }
+                    .build()
+                    .show()
+            }
         }
         return true
     }

+ 9 - 0
app/src/main/java/org/brynhild/graduation/activity/admin/UserDetailInfoActivity.kt

@@ -17,10 +17,12 @@ import com.example.devicemanager.view.ConfirmPopupWindow
 import com.google.gson.Gson
 import org.brynhild.graduation.R
 import org.brynhild.graduation.activity.common.BaseActivity
+import org.brynhild.graduation.activity.common.StatisticActivity
 import org.brynhild.graduation.common.config.LoginConfiguration
 import org.brynhild.graduation.common.config.MyApplication
 import org.brynhild.graduation.common.constant.AccountConstant
 import org.brynhild.graduation.common.constant.BroadcastConstant
+import org.brynhild.graduation.common.constant.StatisticConstant
 import org.brynhild.graduation.common.constant.UserStateConstant
 import org.brynhild.graduation.common.transfer.Result
 import org.brynhild.graduation.common.transfer.dto.FileInfo
@@ -251,6 +253,13 @@ class UserDetailInfoActivity : BaseActivity() {
             intent.type = "image/*"
             startActivityForResult(intent, updateAccountAvatar)
         }
+
+        binding.statisticBtn.setOnClickListener {
+            val intent=Intent(this, StatisticActivity::class.java)
+            intent.putExtra(StatisticConstant.ACTION, StatisticConstant.STUDENT_ACTION)
+            intent.putExtra(StatisticConstant.ID_ENUM,user.id)
+            startActivity(intent)
+        }
     }
 
     override fun onCreateOptionsMenu(menu: Menu?): Boolean {

+ 191 - 0
app/src/main/java/org/brynhild/graduation/activity/common/StatisticActivity.kt

@@ -0,0 +1,191 @@
+package org.brynhild.graduation.activity.common
+
+import android.annotation.SuppressLint
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.webkit.WebSettings
+import android.webkit.WebView
+import android.webkit.WebViewClient
+import android.widget.Toast
+import androidx.core.content.ContextCompat
+import com.google.gson.Gson
+import org.brynhild.graduation.common.config.LoginConfiguration
+import org.brynhild.graduation.common.constant.StatisticConstant
+import org.brynhild.graduation.common.transfer.Result
+import org.brynhild.graduation.common.transfer.bo.timetable.StatisticInfo
+import org.brynhild.graduation.common.transfer.dto.FileInfo
+import org.brynhild.graduation.common.transfer.handler.ResponseHandler
+import org.brynhild.graduation.common.transfer.utils.ServiceCreator
+import org.brynhild.graduation.common.transfer.vo.timetable.AdminQueryClassStatistic
+import org.brynhild.graduation.common.transfer.vo.timetable.AdminQueryStudentStatistic
+import org.brynhild.graduation.common.utils.FileDownloadUtil
+import org.brynhild.graduation.common.utils.JsonUtils
+import org.brynhild.graduation.databinding.ActivityStatisticBinding
+import org.brynhild.graduation.service.http.CommonService
+import retrofit2.Call
+import retrofit2.Callback
+import retrofit2.Response
+import kotlin.properties.Delegates
+
+class StatisticActivity : BaseActivity() {
+    private lateinit var binding: ActivityStatisticBinding
+    private var type by Delegates.notNull<Int>()
+    private var id by Delegates.notNull<Long>()
+
+    @SuppressLint("SetJavaScriptEnabled")
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+
+
+        binding=ActivityStatisticBinding.inflate(LayoutInflater.from(this))
+        setContentView(binding.root)
+
+        type=intent.getIntExtra(StatisticConstant.ACTION,1)
+        id=intent.getLongExtra(StatisticConstant.ID_ENUM,0L)
+
+
+        val webSettings: WebSettings = binding.backupChart.settings
+        webSettings.domStorageEnabled = true
+        webSettings.javaScriptEnabled = true
+        webSettings.javaScriptCanOpenWindowsAutomatically = true
+        webSettings.setSupportZoom(false)
+        webSettings.displayZoomControls = false
+        binding.backupChart.setBackgroundColor(ContextCompat.getColor(this, android.R.color.transparent))
+        binding.backupChart.loadUrl("file:///android_asset/echarts.html")
+        binding.backupChart.webViewClient = object : WebViewClient() {
+            override fun onPageFinished(view: WebView?, url: String?) {
+                super.onPageFinished(view, url)
+                loadStatisticInfo()
+            }
+        }
+
+        bindOnClick()
+    }
+
+    private fun bindOnClick(){
+        binding.downloadStatistic.setOnClickListener {
+            val service=ServiceCreator.create(CommonService::class.java)
+            val handler=object:Callback<Result>{
+                override fun onResponse(call: Call<Result>, response: Response<Result>) {
+                    ResponseHandler.handle(response,{
+                        val gson=Gson()
+                        val list=ArrayList<FileInfo>()
+                        for(item in it.data as List<*>){
+                            val json=gson.toJson(item)
+                            val info=JsonUtils.fromJson<FileInfo>(json)
+                            if(info!=null){
+                                list.add(info)
+                            }
+                        }
+                        if(list.size==1){
+                            val info=list[0]
+                            val downLoadName=if(type==StatisticConstant.STUDENT_ACTION){
+                                "student-${id}.docx"
+                            }else{
+                                "class-${id}.docx"
+                            }
+                            println("download:${info.path}")
+                            FileDownloadUtil.downLoad(info.path,downLoadName){
+                                Toast.makeText(this@StatisticActivity,"文件下载完成",Toast.LENGTH_SHORT).show()
+                            }
+                        }
+                    },{
+                        ResponseHandler.showMessage(it)
+                    })
+                }
+
+                override fun onFailure(call: Call<Result>, t: Throwable) {
+                    t.printStackTrace()
+                }
+            }
+
+            when(type){
+                StatisticConstant.CLASS_ACTION->{
+                    val data=AdminQueryClassStatistic(id)
+                    service.generateClassStatistic(LoginConfiguration.userInfo!!.token,data).enqueue(handler)
+                }
+                StatisticConstant.STUDENT_ACTION->{
+                    val data=AdminQueryStudentStatistic(id)
+                    service.generateStudentStatistic(LoginConfiguration.userInfo!!.token,data).enqueue(handler)
+                }
+            }
+        }
+
+        binding.title.text="考勤数据"
+        binding.backButton.setOnClickListener {
+            finish()
+        }
+    }
+
+
+    private fun loadStatisticInfo() {
+        val service=ServiceCreator.create(CommonService::class.java)
+        val handler=object:Callback<Result>{
+            override fun onResponse(call: Call<Result>, response: Response<Result>) {
+                ResponseHandler.handle(response,{
+                    val gson=Gson()
+                    val list=ArrayList<StatisticInfo>()
+                    println(gson.toJson(it))
+                    for(item in it.data as List<*>){
+                        val json=gson.toJson(item)
+                        val info=JsonUtils.fromJson<StatisticInfo>(json)
+                        if(info!=null){
+                            list.add(info)
+                        }
+                    }
+                    renderStatisticInfoList(list)
+                },{
+                    ResponseHandler.showMessage(it)
+                })
+            }
+
+            override fun onFailure(call: Call<Result>, t: Throwable) {
+                t.printStackTrace()
+            }
+        }
+
+        when(type){
+            StatisticConstant.CLASS_ACTION->{
+                val data=AdminQueryClassStatistic(id)
+                service.queryClassStatistic(LoginConfiguration.userInfo!!.token,data).enqueue(handler)
+            }
+            StatisticConstant.STUDENT_ACTION->{
+                val data=AdminQueryStudentStatistic(id)
+                service.queryStudentStatistic(LoginConfiguration.userInfo!!.token,data).enqueue(handler)
+            }
+        }
+
+    }
+
+    private fun renderStatisticInfoList(list:List<StatisticInfo>){
+        var first=true
+        val nameBuilder=StringBuilder()
+        val rateBuilder=StringBuilder()
+
+        for(item in list){
+            if(!first){
+                nameBuilder.append(",")
+                rateBuilder.append(",")
+            }
+            nameBuilder.append(item.course.name)
+            rateBuilder.append(item.rate*100)
+            first=false
+        }
+        val chartOptions = """
+            setChartOptions(
+                {
+                    xAxis: {type: 'value'}, 
+                    yAxis: {type: 'category', data: [${nameBuilder}]},
+                    series: [{
+                        type: 'bar',
+                        data: [${rateBuilder}],
+                        label: {show: true, position: 'inside'}
+                    }]
+                }
+                );
+                """
+        println(chartOptions)
+        binding.backupChart.evaluateJavascript(chartOptions, null)
+    }
+
+}

+ 3 - 0
app/src/main/java/org/brynhild/graduation/activity/common/TimetableActivity.kt

@@ -19,6 +19,8 @@ import org.brynhild.graduation.common.transfer.handler.ResponseHandler
 import org.brynhild.graduation.common.transfer.utils.ServiceCreator
 import org.brynhild.graduation.common.transfer.vo.timetable.AdminAddTimeTable
 import org.brynhild.graduation.common.transfer.vo.timetable.QueryTimeTableRequest
+import org.brynhild.graduation.common.utils.FileDownloadUtil
+import org.brynhild.graduation.common.utils.FileUtils
 import org.brynhild.graduation.common.utils.JsonUtils
 import org.brynhild.graduation.databinding.ActivityTimetableBinding
 import org.brynhild.graduation.databinding.AdminAddTimetableDialogBinding
@@ -125,6 +127,7 @@ class TimetableActivity : BaseActivity() {
             classEntity = JsonUtils.fromJson<ClassEntity>(json)!!
             loadTimeTableData()
         }
+
     }
 
     private fun initTimetableView() {

+ 9 - 0
app/src/main/java/org/brynhild/graduation/common/constant/StatisticConstant.java

@@ -0,0 +1,9 @@
+package org.brynhild.graduation.common.constant;
+
+public class StatisticConstant {
+    public static final Integer CLASS_ACTION=1;
+    public static final Integer STUDENT_ACTION=2;
+
+    public static final String ACTION="action";
+    public static final String ID_ENUM="id";
+}

+ 14 - 0
app/src/main/java/org/brynhild/graduation/common/transfer/bo/timetable/StatisticInfo.kt

@@ -0,0 +1,14 @@
+package org.brynhild.graduation.common.transfer.bo.timetable
+
+import org.brynhild.graduation.network.entiity.Course
+
+data class StatisticInfo(
+    val course: Course,
+    val count:Long,
+    val actualCount:Long,
+    val rate:Double
+):Comparable<StatisticInfo>{
+    override fun compareTo(other: StatisticInfo): Int {
+        return other.rate.compareTo(rate)
+    }
+}

+ 5 - 0
app/src/main/java/org/brynhild/graduation/common/transfer/vo/timetable/AdminQueryClassStatistic.kt

@@ -0,0 +1,5 @@
+package org.brynhild.graduation.common.transfer.vo.timetable
+
+data class AdminQueryClassStatistic(
+	val id:Long?,
+)

+ 5 - 0
app/src/main/java/org/brynhild/graduation/common/transfer/vo/timetable/AdminQueryStudentStatistic.kt

@@ -0,0 +1,5 @@
+package org.brynhild.graduation.common.transfer.vo.timetable
+
+data class AdminQueryStudentStatistic(
+	val id:Long?,
+)

+ 53 - 0
app/src/main/java/org/brynhild/graduation/common/utils/FileDownloadUtil.java

@@ -0,0 +1,53 @@
+package org.brynhild.graduation.common.utils;
+
+
+import android.os.Looper;
+
+import org.brynhild.graduation.common.callback.DefaultCallback;
+
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.net.URL;
+
+public class FileDownloadUtil {
+    /**
+     * 从服务器下载文件
+     * @param path 下载文件的地址
+     * @param FileName 文件名字
+     */
+    public static void downLoad(final String path, final String FileName, DefaultCallback callback) {
+        new Thread(() -> {
+            try {
+                URL url = new URL(path);
+                HttpURLConnection con = (HttpURLConnection) url.openConnection();
+                con.setReadTimeout(5000);
+                con.setConnectTimeout(5000);
+                con.setRequestProperty("Charset", "UTF-8");
+                con.setRequestMethod("GET");
+                if (con.getResponseCode() == 200) {
+                    InputStream is = con.getInputStream();//获取输入流
+                    FileOutputStream fileOutputStream = null;//文件输出流
+                    if (is != null) {
+                        FileUtils fileUtils = new FileUtils();
+                        fileOutputStream = new FileOutputStream(fileUtils.createFile(FileName));//指定文件保存路径,代码看下一步
+                        byte[] buf = new byte[1024];
+                        int ch;
+                        while ((ch = is.read(buf)) != -1) {
+                            fileOutputStream.write(buf, 0, ch);//将获取到的流写入文件中
+                        }
+                    }
+                    if (fileOutputStream != null) {
+                        fileOutputStream.flush();
+                        fileOutputStream.close();
+                    }
+                    Looper.prepare();
+                    callback.execute();
+                    Looper.loop();
+                }
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }).start();
+    }
+}

+ 28 - 0
app/src/main/java/org/brynhild/graduation/common/utils/FileUtils.java

@@ -0,0 +1,28 @@
+package org.brynhild.graduation.common.utils;
+
+import android.os.Environment;
+
+import java.io.File;
+
+public class FileUtils {
+    private String path = Environment.getExternalStorageDirectory().toString() + "/brynhild";
+ 
+    public FileUtils() {
+        File file = new File(path);
+        /**
+         *如果文件夹不存在就创建
+         */
+        if (!file.exists()) {
+            file.mkdirs();
+        }
+    }
+ 
+    /**
+     * 创建一个文件
+     * @param FileName 文件名
+     * @return
+     */
+    public File createFile(String FileName) {
+        return new File(path, FileName);
+    }
+}

+ 7 - 0
app/src/main/java/org/brynhild/graduation/service/http/AdminService.kt

@@ -232,4 +232,11 @@ interface AdminService {
         @Body info: AdminAddTimeTable
     ): Call<Result>
 
+
+
+
+
+
+
+
 }

+ 30 - 0
app/src/main/java/org/brynhild/graduation/service/http/CommonService.kt

@@ -1,11 +1,41 @@
 package org.brynhild.graduation.service.http
 
+import org.brynhild.graduation.common.constant.AccountConstant
 import org.brynhild.graduation.common.transfer.Result
+import org.brynhild.graduation.common.transfer.vo.timetable.AdminQueryClassStatistic
+import org.brynhild.graduation.common.transfer.vo.timetable.AdminQueryStudentStatistic
 import retrofit2.Call
+import retrofit2.http.Body
 import retrofit2.http.GET
+import retrofit2.http.Header
+import retrofit2.http.POST
 
 interface CommonService {
 
     @GET("timetable/public/config")
     fun loadTimeTableConfig(): Call<Result>
+
+    @POST("timetable/public/statistic/class")
+    fun queryClassStatistic(
+        @Header(AccountConstant.ACCOUNT_HEADER) token: String,
+        @Body info: AdminQueryClassStatistic
+    ): Call<Result>
+
+    @POST("timetable/public/statistic/student")
+    fun queryStudentStatistic(
+        @Header(AccountConstant.ACCOUNT_HEADER) token: String,
+        @Body info: AdminQueryStudentStatistic
+    ): Call<Result>
+
+    @POST("timetable/public/statistic/class/generate")
+    fun generateClassStatistic(
+        @Header(AccountConstant.ACCOUNT_HEADER) token: String,
+        @Body info: AdminQueryClassStatistic
+    ): Call<Result>
+
+    @POST("timetable/public/statistic/student/generate")
+    fun generateStudentStatistic(
+        @Header(AccountConstant.ACCOUNT_HEADER) token: String,
+        @Body info: AdminQueryStudentStatistic
+    ): Call<Result>
 }

+ 8 - 7
app/src/main/res/layout/activity_class_detail_info.xml

@@ -104,13 +104,6 @@
         android:gravity="center"
         android:orientation="horizontal">
 
-        <Button
-            android:id="@+id/admin_class_delete"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_marginRight="10dp"
-            android:text="删除班级" />
-
         <Button
             android:id="@+id/admin_class_batch_enroll"
             android:layout_width="wrap_content"
@@ -129,8 +122,16 @@
             android:id="@+id/queryTimeTable"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
+            android:layout_marginRight="10dp"
             android:text="查看课表" />
 
+        <Button
+            android:id="@+id/admin_class_statistic"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginRight="10dp"
+            android:text="考勤数据" />
+
 
     </LinearLayout>
 

+ 72 - 0
app/src/main/res/layout/activity_statistic.xml

@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical"
+    tools:context=".activity.common.StatisticActivity">
+
+    <com.google.android.material.appbar.AppBarLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content">
+
+        <com.google.android.material.appbar.CollapsingToolbarLayout
+            android:id="@+id/collapsingToolbar"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:fitsSystemWindows="true"
+            android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
+            app:contentScrim="@color/majorBlue"
+            app:layout_scrollFlags="scroll|exitUntilCollapsed"
+            app:popupTheme="@style/ThemeOverlay.AppCompat.Light">
+
+            <androidx.appcompat.widget.Toolbar
+                android:id="@+id/toolBar"
+                android:layout_width="match_parent"
+                android:layout_height="?attr/actionBarSize"
+                app:layout_collapseMode="pin">
+
+                <ImageView
+                    android:id="@+id/backButton"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_gravity="center_vertical"
+                    android:src="@drawable/node_modules_reactnavigationstack_dist_views_assets_backicon" />
+            </androidx.appcompat.widget.Toolbar>
+
+            <TextView
+                android:id="@+id/title"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_centerInParent="true"
+                android:layout_gravity="center"
+                android:text="标题栏"
+                android:textColor="@android:color/white"
+                android:textSize="20sp" />
+        </com.google.android.material.appbar.CollapsingToolbarLayout>
+
+
+    </com.google.android.material.appbar.AppBarLayout>
+
+    <WebView
+        android:id="@+id/backupChart"
+        android:layout_width="match_parent"
+        android:layout_height="600dp" />
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:gravity="center"
+        android:orientation="horizontal">
+
+        <Button
+            android:id="@+id/download_statistic"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginRight="10dp"
+            android:text="下载结果" />
+
+    </LinearLayout>
+
+
+</LinearLayout>

+ 9 - 0
app/src/main/res/layout/activity_user_detail_info.xml

@@ -78,7 +78,16 @@
             android:id="@+id/recordBtn"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
+            android:layout_marginRight="20dp"
             android:text="签到记录" />
+
+        <Button
+            android:id="@+id/statisticBtn"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginRight="20dp"
+            android:text="考勤数据" />
+
     </LinearLayout>
 
     <LinearLayout

+ 5 - 0
app/src/main/res/menu/admin_class_detail_info_options.xml

@@ -11,4 +11,9 @@
         android:icon="@drawable/ic_modify"
         android:title="Modify"
         app:showAsAction="always" />
+    <item
+        android:id="@+id/admin_class_delete"
+        android:icon="@drawable/ic_delete"
+        android:title="Delete"
+        app:showAsAction="always" />
 </menu>

Some files were not shown because too many files changed in this diff