AndroidStudio-Design and development of multi-level directory function for study notes

Demonstration effect

Insert image description here

Description of Requirement

根据需求,为用户展示多级目录(目前设计的为4级目录),并在选择了指定目录后显示详情页面,供用户点赞,查看,上传,标记等操作

Development estimate

front end

  1. Each page displays the contents of a hierarchy/directory, including title, img, and possible description of the directory.
  2. After entering the final directory, click to view the details page. The details page includes the title content of all previous levels/directories to which the final directory belongs, as well as the detailed contents of the final directory.
  3. In addition to the 2 descriptions, the detailed content also needs to show partial functions like comments (like and unlike operations can be performed), the marking function of the details page, whether the directory has helpful functions, and the ability to add your own thoughts on this details page. Function
  4. For each operation on the details page, try to prompt the user with the result of the operation.
  5. UI has not yet made a request

rear end

  1. Multi-level table design
  2. Try to use the least number of interfaces to communicate with the server

Front-end development

UI small framework for multi-level directories

Just to interrupt, my implementation process is to dynamically add a new view to the view of the existing activity in the application, that is, a new view is added to each level of directory.
I hesitated between activity and view, and finally decided on the form of activity It's a bit fussy, after all, it only displays a view, which displays some basic information. At most, the final details page may be worth one activity, but after creating 5 activities and using one view to make 4 copies, a separate processing details page is added. Among the views, I chose the latter. After all, the transmission of data between different activities was enough to shut down my brain for several days. Back to the

topic, I used the information about Dynamically create a directory page view code, and then perform magic modification. I wrote a manager to dynamically create the view and
upload the source code directly.

public class CustomViewMgr {
    
    



    //创建一个容器用于存放view,进行管理
//    List<View> views;
//    ViewGroup curView;
    protected LayoutInflater inflater;
    public CustomViewMgr(Context context) {
    
    
        //初始化

        inflater = (LayoutInflater) context.getSystemService(LAYOUT_INFLATER_SERVICE);
    }

    public LayoutInflater getInflater(){
    
    
        return this.inflater;
    }

    /**
     * 根据layout和对应的view找到需要新生成的view,为了方便拓展接收和返回都设置为了object
     *
     * @param oldView   原来在显示的view
     * @param layoutId  你新的xml的id
     * @param newViewId 你新的xml对应的viewId
     * @return Object
     */
    public Object getNewView(View oldView, int layoutId, int newViewId) {
    
    
        if (oldView != null) {
    
    
            oldView.setVisibility(View.GONE);
        }
        //获得需要新显示的layout
        ConstraintLayout constraintLayout2 = (ConstraintLayout) inflater.inflate(layoutId, null);
        //根据layout获得需要的view
        //添加到view容器中
        return constraintLayout2.findViewById(newViewId);
    }

    public void refreshRecycleView(RecyclerView recyclerView, NewsItemAdapter temAdapter,ViewGroup curView) {
    
    

        //这一步是把绑定好数据的适配器添加到视图上
        recyclerView.setAdapter(temAdapter);
        //这一步是清除要展示的view的父级,否则会闪退报错
        ViewGroup parent_tem = (ViewGroup) recyclerView.getParent();
        parent_tem.removeView(recyclerView);
        //最后再把视图和配套的数据添加到现有的view中
        curView.addView(recyclerView);
    }
}

This CustomViewMgrclass is actually very simple. It is mainly used to find views located in other xml. For example, I want to add a component (button, list, etc.) from other views to a certain view. Through this class, getNewViewfirst Parameters can be filled in null by default. I am here mainly to save trouble. I hope that every time I create a new view, I can automatically hide the previous view. I wrote it here, mainly the last two, the first one is layoutid, and the second one is The first is the ID of the view you need to create, and you can return the view you need. Why is it so troublesome? Because if you don't find your view under the corresponding layout, the system will find your view under the current view by default. If the view you just created is under the current view, it will be fine, but if it is not, it will directly report an error and crash, prompting you that the current view does not have the view you want. As for the second refreshRecycleView method of this
class CustomViewMgrIt is mainly for RecyclerView this view. If you do not remove its parent directory before creating it and then add it to the current view, it will report an error saying that you need to remove the RecyclerView parent directory before you can add other views. I don’t know if this problem exists, I’ll talk about it if I encounter it later.

front-end xml

Create animation-related xml under res/anim

<?xml version="1.0" encoding="utf-8"?>
<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
    android:animation="@anim/slide_in_left"
    android:animationOrder="normal"
    android:delay="15%">

</layoutAnimation>

Create xml that splits horizontal components under res/drawable

<?xml version="1.0" encoding="utf-8"?>
<shape android:shape="rectangle"
    xmlns:android="http://schemas.android.com/apk/res/android" >
    <size android:height="1dp" android:width="100dp"/>
</shape>

Create the xml of the details page under res/layout

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:background="#ececed"
    tools:context=".TestActivity">

	//这个LineraLayout是详情页的view
    <LinearLayout
        android:id="@+id/showNewView"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="#fff"
        android:gravity="center_horizontal"
        android:orientation="vertical"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="@dimen/common_15dp"
            android:divider="@drawable/divider"
            android:gravity="center"
            android:orientation="horizontal"
            android:showDividers="middle">

            <LinearLayout
                android:id="@+id/solve_btn"
                android:gravity="center"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="vertical">

                <ImageView
                    android:layout_width="50sp"
                    android:layout_height="50sp"
                    android:src="@drawable/pic" />
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="已解决"/>
            </LinearLayout>

            <LinearLayout
                android:id="@+id/mark_btn"
                android:gravity="center"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="vertical">

                <ImageView
                    android:layout_width="50sp"
                    android:layout_height="50sp"
                    android:src="@drawable/pic" />
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="标记"/>
            </LinearLayout>
            <LinearLayout
                android:id="@+id/add_btn"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:gravity="center"
                android:orientation="vertical">

                <ImageView
                    android:layout_width="50sp"
                    android:layout_height="50sp"
                    android:src="@drawable/pic" />
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:textSize="12sp"
                    android:text="我的想法"/>
            </LinearLayout>
        </LinearLayout>

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:orientation="vertical">

            <TextView
                android:id="@+id/menu1_text"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="15dp"
                android:text="测试"
                android:textColor="#000"
                android:textSize="30dp" />

            <TextView
                android:id="@+id/menu2_text"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="测试"
                android:textColor="#000"
                android:textSize="20dp" />

            <TextView
                android:id="@+id/menu3_text"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="15dp"
                android:text="测试"
                android:textColor="#000"
                android:textSize="20dp" />

            <TextView
                android:id="@+id/menu4_text"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="测试"
                android:textColor="#000"
                android:textSize="20dp" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="center_horizontal|center_vertical"
            android:orientation="vertical">

            <TextView
                android:id="@+id/new_view_text"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="15dp"
                android:text="测试"
                android:textAlignment="center"
                android:textColor="#000"
                android:textSize="20dp"
                android:textStyle="bold" />
        </LinearLayout>


        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/showCommentView"

            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginTop="20dp"
            android:orientation="vertical"
            app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager">

        </androidx.recyclerview.widget.RecyclerView>


    </LinearLayout>

	//------------这个RecyclerView就是显示每级目录的view
    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/menuRecycleView"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:clipToPadding="false"
        android:layoutAnimation="@anim/layout_slide_in_left"
        android:orientation="vertical"
        app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

    </androidx.recyclerview.widget.RecyclerView>
</androidx.constraintlayout.widget.ConstraintLayout>

If you report an exception here and say that the RecyclerView component cannot be found, you need to write it under
the corresponding link and then sync (the dolphin in the upper right corner of Android Studio). The above xml includes both the view of the details page and the view showing each level of directory. , of course you can create another xml to store the views of each level of directory separately, I am just lazy here...build.gradle
implementation 'androidx.recyclerview:recyclerview:1.0.0'

Create xml about the items in each directory under res/layout

<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_marginStart="10dp"
    android:layout_marginTop="10dp"
    app:cardCornerRadius="4dp"
    app:cardElevation="4dp">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:padding="10dp">

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal">

        <ImageView
            android:layout_width="20sp"
            android:layout_height="20sp"
            android:src="@mipmap/ic_launcher"
            />

            <TextView
                android:id="@+id/textTitle"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="test "
                android:paddingLeft="10sp"
                android:textColor="#212121"
                android:textSize="18sp"
                android:textStyle="bold" />


        </LinearLayout>


        <TextView
            android:id="@+id/textDescription"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textColor="#757575"
            android:textIsSelectable="true"
            android:textSize="16sp"/>
        <TextView
            android:id="@+id/textZan"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textColor="#757575"
            android:text=""
            android:textAlignment="textEnd"
            android:textSize="16sp"/>

    </LinearLayout>

</androidx.cardview.widget.CardView>

If you are not prompted here CardView, it is the same as above , add the RecyclerViewfollowing to the corresponding one and then sync itbuild.grale
implementation 'androidx.cardview:cardview:1.0.0'

Front-end code—local demo version

Then it is finally the activity's turn to
create a new activity class. Inherit Activity
because it is in the demo stage, so the server is not involved. The following data part is fake data added manually.

package com.yeyupiaoling.testvad;

import android.app.Activity;
import android.app.AlertDialog;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.recyclerview.widget.RecyclerView;
import com.yeyupiaoling.testvad.CustomView.CustomViewMgr;
import java.util.ArrayList;
import java.util.List;

public class TestActivity extends Activity {
    
    

    int menu1 = 0;
    int menu2 = 0;
    int menu3 = 0;
    int menu4 = 0;
    LayoutInflater inflater;
    ConstraintLayout parent;

    //创建一个容器用于存放view,进行管理
    List<View> views;
    ViewGroup curView;
    CustomViewMgr customViewMgr;

    //    编辑界面
    LinearLayout edit_view;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        // 初始化
        views = new ArrayList<>();
        edit_view = null;
        setContentView(R.layout.activity_test);
        curView = findViewById(R.id.activity_main);

        customViewMgr = new CustomViewMgr(getApplicationContext());

        RecyclerView newRecyclerView = (RecyclerView) customViewMgr.getNewView(null, R.layout.activity_menu1, R.id.menuRecycleView);


        List<NewsItem> newsItems = new ArrayList<>();

        for (int i = 0; i < 15; i++) {
    
    
            newsItems.add(new NewsItem("一级目录" + i, "this is a news about pure doing a new function in android studio"));
        }
        NewsItemAdapter adapter = new NewsItemAdapter(newsItems);


        adapter.setOnItemClickListener(new NewsItemAdapter.OnItemClickListener() {
    
    
            @Override
            public void onItemClick(int postion, View view) {
    
    
                menu1 = postion;
                //这一步是找到需要展示的view
                RecyclerView recycleView_tem = (RecyclerView) customViewMgr.getNewView(newRecyclerView, R.layout.activity_menu1, R.id.menuRecycleView);
                List<NewsItem> newsItems = new ArrayList<>();
                for (int i = 0; i < 15; i++) {
    
    
                    newsItems.add(new NewsItem("二级目录" + i, "this is a news about pure doing a new function in android studio"));
                }
                NewsItemAdapter adapter_tem = new NewsItemAdapter(newsItems);

                adapter_tem.setOnItemClickListener(new NewsItemAdapter.OnItemClickListener() {
    
    
                    @Override
                    public void onItemClick(int postion, View view) {
    
    
                        menu2 = postion;
//                        parent.removeView(newRecyclerView1);
//                        ConstraintLayout constraintLayout3 = (ConstraintLayout)inflater.inflate(R.layout.activity_menu2,null);
//                        RecyclerView newRecyclerView1 = (RecyclerView) constraintLayout3.findViewById(R.id.menu2RecycleView);
                        RecyclerView recycleView_tem2 = (RecyclerView) customViewMgr.getNewView(recycleView_tem, R.layout.activity_menu1, R.id.menuRecycleView);
                        //这一步是建立数据
                        List<NewsItem> newsItems = new ArrayList<>();

                        for (int i = 0; i < 15; i++) {
    
    
                            newsItems.add(new NewsItem("三级目录" + i, "this is a news about pure doing a new function in android studio"));
                        }
                        //这一步是绑定数据
                        NewsItemAdapter adapter1 = new NewsItemAdapter(newsItems);
                        //这一步是绑定点击事件
                        adapter1.setOnItemClickListener(new NewsItemAdapter.OnItemClickListener() {
    
    
                            @Override
                            public void onItemClick(int postion, View view) {
    
    
                                menu3 = postion;
                                RecyclerView recyclerView_tem3 = (RecyclerView) customViewMgr.getNewView(recycleView_tem2, R.layout.activity_menu1, R.id.menuRecycleView);
                                List<NewsItem> newsItems = new ArrayList<>();

                                for (int i = 0; i < 15; i++) {
    
    
                                    newsItems.add(new NewsItem("终极目录" + i, "this is a news about pure doing a new function in android studio"));
                                }
                                //这一步是绑定数据
                                NewsItemAdapter adapter1 = new NewsItemAdapter(newsItems);
                                adapter1.setOnItemClickListener(new NewsItemAdapter.OnItemClickListener() {
    
    
                                    @Override
                                    public void onItemClick(int postion, View view) {
    
    
                                        menu4 = postion;
//                                        Button test = (Button) getNewView( recyclerView_tem3,R.layout.activity_menu1,R.id.showRecycleView);
//                                        refreshView(test);
                                        show_last_view();
                                    }
                                });
                                customViewMgr.refreshRecycleView(recyclerView_tem3, adapter1, curView);
                                views.add(recyclerView_tem3);
                            }
                        });
                        customViewMgr.refreshRecycleView(recycleView_tem2, adapter1, curView);
                        views.add(recycleView_tem2);
                    }
                });

                customViewMgr.refreshRecycleView(recycleView_tem, adapter_tem, curView);
                views.add(recycleView_tem);
            }
        });
        customViewMgr.refreshRecycleView(newRecyclerView, adapter, curView);
        views.add(newRecyclerView);
    }


    @Override
    public void onBackPressed() {
    
    
        if (views.size() > 0) {
    
    
            //说明还有上一级,隐藏当前返回上一级
            if (views.size() != 1) {
    
    
                views.get(views.size() - 2).setVisibility(View.VISIBLE);
                curView.removeView(views.get(views.size() - 1));
                views.remove(views.get(views.size() - 1));
            } else {
    
    
                views.get(0).setVisibility(View.GONE);
                views.remove(views.get(views.size() - 1));
            }

        } else {
    
    
            super.onBackPressed();
        }
    }

	//这个是显示详情页面的view
    private void show_last_view() {
    
    
        String result = "   这是学生顶撞老师的最常见原因。\n" +
                "   解决方法——教师开口之前,先询问一下,调查一下,就可以避免很多师生冲突。";

        views.get(views.size() - 1).setVisibility(View.GONE);
        View inflate = customViewMgr.getInflater().inflate(R.layout.activity_menu1, null);
        LinearLayout linearLayout = (LinearLayout) inflate.findViewById(R.id.showNewView);
        ViewGroup parent = (ViewGroup) linearLayout.getParent();
        parent.removeView(linearLayout);
        TextView textView1 = (TextView) linearLayout.findViewById(R.id.menu1_text);
        textView1.setText("纪律问题");
        TextView textView2 = (TextView) linearLayout.findViewById(R.id.menu2_text);
        textView2.setText("顶撞老师");
        TextView textView3 = (TextView) linearLayout.findViewById(R.id.menu3_text);
        textView3.setText("从教师责任的角度分析");
        TextView textView4 = (TextView) linearLayout.findViewById(R.id.menu4_text);
        textView4.setText("(1)老师冤枉了学生");
        TextView textView = (TextView) linearLayout.findViewById(R.id.new_view_text);
        textView.setText(result);
        RecyclerView recyclerView = (RecyclerView) linearLayout.findViewById(R.id.showCommentView);
        List<NewsItem> items = new ArrayList<>();
        items.add(new NewsItem("Mr.王", "我觉得这么做会更好一点", "30"));
        items.add(new NewsItem("Mr.张", "我觉得这么做会更好一点", "20"));
        items.add(new NewsItem("Mr.赵", "我觉得这么做会更好一点", "10"));
        items.add(new NewsItem("Mr.赵", "我觉得这么做会更好一点", "10"));
        items.add(new NewsItem("Mr.赵", "我觉得这么做会更好一点", "10"));
        items.add(new NewsItem("Mr.赵", "我觉得这么做会更好一点", "10"));
        items.add(new NewsItem("Mr.李", "我觉得这么做会更好一点", "0"));
        NewsItemAdapter adapter = new NewsItemAdapter(items);
        recyclerView.setAdapter(adapter);
        adapter.setOnItemClickListener(new NewsItemAdapter.OnItemClickListener() {
    
    
            @Override
            public void onItemClick(int postion, View view) {
    
    
                AlertDialog.Builder builder = new AlertDialog.Builder(TestActivity.this);
                builder.setTitle("确认");
                builder.setMessage("你进行了点赞");
                builder.show();
            }
        });
        LinearLayout solve_ly = linearLayout.findViewById(R.id.solve_btn);
        solve_ly.setOnTouchListener(new View.OnTouchListener() {
    
    
            @Override
            public boolean onTouch(View v, MotionEvent event) {
    
    
                AlertDialog.Builder builder = new AlertDialog.Builder(TestActivity.this);
                builder.setTitle("确认");
                builder.setMessage("已标记为解决");
                builder.show();
                return false;
            }
        });
        LinearLayout mark_ly = linearLayout.findViewById(R.id.mark_btn);
        mark_ly.setOnTouchListener(new View.OnTouchListener() {
    
    
            @Override
            public boolean onTouch(View v, MotionEvent event) {
    
    
                AlertDialog.Builder builder = new AlertDialog.Builder(TestActivity.this);
                builder.setTitle("确认");
                builder.setMessage("已标记");
                builder.show();
                return false;
            }
        });
        LinearLayout add_ly = linearLayout.findViewById(R.id.add_btn);
        add_ly.setOnTouchListener(new View.OnTouchListener() {
    
    
            @Override
            public boolean onTouch(View v, MotionEvent event) {
    
    
                //进入编辑的view
                views.get(views.size() - 1).setVisibility(View.GONE);
                if (views.contains(edit_view)) {
    
    
                    int index = views.indexOf(views.contains(edit_view));
                    views.get(index).setVisibility(View.VISIBLE);
                    return false;
                }
                View inflate = customViewMgr.getInflater().inflate(R.layout.add_opinion, null);
                LinearLayout linearLayout = (LinearLayout) inflate.findViewById(R.id.add_view);
                ViewGroup parent1 = (ViewGroup) linearLayout.getParent();
                parent1.removeView(linearLayout);
                Button back_add_view = (Button) linearLayout.findViewById(R.id.back_add_view);
                EditText editText = (EditText) linearLayout.findViewById(R.id.add_opinion_text);
                editText.setHint(menu1 + "\n" + menu2 + "\n" + menu3 + "\n" + menu4 + "\n" + "请输入您的想法");
                back_add_view.setOnClickListener(new View.OnClickListener() {
    
    
                    @Override
                    public void onClick(View v) {
    
    
                        onBackPressed();
                    }
                });
                Button upload_opinion = (Button) linearLayout.findViewById(R.id.upload_new_opinion);
                upload_opinion.setOnClickListener(new View.OnClickListener() {
    
    
                    @Override
                    public void onClick(View v) {
    
    
                        onBackPressed();
                        AlertDialog.Builder builder = new AlertDialog.Builder(TestActivity.this);
                        builder.setTitle("确认");
                        builder.setMessage("上传完成");
                        builder.show();
                    }
                });
                curView.addView(linearLayout);
                edit_view = linearLayout;
                views.add(linearLayout);
                return false;
            }
        });
        curView.addView(linearLayout);
        views.add(linearLayout);

    }
}

If all the above can be run successfully, it means that there will be no problem in the demo stage.

Front-end code—server version

The following is a front-end code display related to the server
. Let me talk about it here, because we are connected to Tencent's instant messaging, and this requirement needs to be built here, so it is normal if you can't understand it.
I specially created one. A class that inherits Dialog CustomViewand is used to manage custom, newly created views.

logical explanation

The server-related code mainly needs to pull down the data from the server when creating each level of directory, and then perform real-time view rendering and display based on the data, which involves a delay issue. Because it is customized, there is no writing about the loading process. Add the function of prompting loading. Here we just make a simple callback interface. After waiting for the server response, the generation of the view is executed.
Because Dialog is inherited, there is a problem that all views will disappear when clicking on the interface other than the view. Therefore, You need to set setcancelable to false, and then rewrite the onBackPressed method.
The part about requesting the server is because it is a framework built by outsourcing, and it is made library_commomunder the module SubscribeUtils. The specific principle has not been studied in detail, and it is not the focus
of the method of requesting the server. Carrots and vegetables have their own methods. For
some parts of the details page I requested, I did not re-enter after requesting the server. Instead, I temporarily stored some data locally for recording, and then updated it in real time, reducing the number of requests to the server and increasing the experience.

package com.tencent.qcloud.tim.demo.helper;

import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;

import androidx.recyclerview.widget.RecyclerView;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.jbb.library_common.comfig.KeyContacts;
import com.jbb.library_common.retrofit.RetrofitManager;
import com.jbb.library_common.retrofit.other.BaseBean;
import com.jbb.library_common.retrofit.other.NetListeren;
import com.jbb.library_common.retrofit.other.SubscribeUtils;
import com.jbb.library_common.utils.ToastUtil;
import com.tencent.qcloud.tim.demo.R;
import com.tencent.qcloud.tim.demo.helper.custommsg.CustomMsgChooseListeren;
import com.tencent.qcloud.tim.demo.helper.custommsg.CustomMsgDialog;
import com.tencent.qcloud.tim.demo.helper.teacherquestion.CustomViewMgr;
import com.tencent.qcloud.tim.demo.helper.teacherquestion.NewsItem;
import com.tencent.qcloud.tim.demo.helper.teacherquestion.NewsItemAdapter;
import com.tencent.qcloud.tim.demo.helper.teacherquestion.TeacherPsyMethonResBean;
import com.tencent.qcloud.tim.demo.helper.teacherquestion.TeacherQuestionResBean;
import com.tencent.qcloud.tim.demo.utils.Constants;
import com.tencent.qcloud.tim.uikit.modules.chat.ChatLayout;
import com.tencent.qcloud.tim.uikit.modules.chat.layout.input.InputLayout;
import com.tencent.qcloud.tim.uikit.service.IMApiService;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;

import static com.tencent.liteav.base.ContextUtils.getApplicationContext;

public class CustomVIew extends Dialog {
    
    

    private Context curContext;
    private ChatLayout curLayout;
    private InputLayout curInputLayout;

    private CustomViewMgr customViewMgr;

    private List<NewsItem> curMenuInfo;
    private View curView;
    private int curIndex;
    private int curMenu;
    private List<List<NewsItem>> menuInfos;
    private List<View> views;

    private HashMap<Integer, NewsItem> psyDetailInfo;
    private Button toMenu1, toMenu2;

    public CustomVIew(Context context, ChatLayout layout, InputLayout inputLayout) {
    
    
        super(context);
        this.curContext = context;
        this.curLayout = layout;
        this.curInputLayout = inputLayout;
        this.curMenuInfo = new LinkedList<>();
        this.curIndex = 0;
        this.curMenu = 0;
        this.views = new LinkedList<>();
        this.menuInfos = new LinkedList<>();
        this.psyDetailInfo = new HashMap();
        customViewMgr = new CustomViewMgr(context);
        init();
    }

    private void init() {
    
    
        //先弹出两个选择框,用户选择,第一个进入语料库,第二个进入新的问题心理合集功能
        LayoutInflater inflater = LayoutInflater.from(curContext);
        curView = inflater.inflate(R.layout.pure_diy_view, (ViewGroup) getWindow().getDecorView(), false);

        LinearLayout btns = curView.findViewById(R.id.pure_show_zhixingyuku_btn);

        toMenu1 = (Button) btns.findViewById(R.id.to_teacher_zhixingyuku);
        toMenu2 = (Button) btns.findViewById(R.id.to_teacher_psyquestion);

        toMenu1.setOnClickListener(new View.OnClickListener() {
    
    
            @Override
            public void onClick(View v) {
    
    
                final CustomMsgDialog dialog = new CustomMsgDialog(curContext, curInputLayout);
                dialog.setListeren(new CustomMsgChooseListeren() {
    
    
                    @Override
                    public void messageChoose(String text) {
    
    
                        curLayout.getInputLayout().setTextInput(text);
                        dialog.dismiss();
                    }
                });
                dialog.showDialog();
            }
        });

        toMenu2.setOnClickListener(new View.OnClickListener() {
    
    
            @Override
            public void onClick(View v) {
    
    
                //这里要隐藏两个按钮的减轻事件
                toMenu1.setVisibility(View.GONE);
                toMenu2.setVisibility(View.GONE);
                setCancelable(false);
                add_menu(1, 0, new Callback() {
    
    
                    @Override
                    public void onSuccess() {
    
    
                        curMenu = 1;
                        //添加监听事件
                        add_menu(2, curMenuInfo.get(curIndex).getId(), new Callback() {
    
    
                            @Override
                            public void onSuccess() {
    
    
                                curMenu = 2;
                                add_menu(3, curMenuInfo.get(curIndex).getId(), new Callback() {
    
    
                                    @Override
                                    public void onSuccess() {
    
    
                                        curMenu = 3;
                                        add_menu(4, curMenuInfo.get(curIndex).getId(), new Callback() {
    
    
                                            @Override
                                            public void onSuccess() {
    
    
                                                curMenu = 4;
                                                //进入详情页面
                                                show_last_view();
                                            }

                                            @Override
                                            public void onFail() {
    
    

                                            }
                                        });
                                    }

                                    @Override
                                    public void onFail() {
    
    

                                    }
                                });
                            }

                            @Override
                            public void onFail() {
    
    

                            }
                        });
                    }

                    @Override
                    public void onFail() {
    
    

                    }
                });
            }
        });

        setContentView(curView);
        setCancelable(true);
        Window dialogWindow = getWindow();
        dialogWindow.setGravity(Gravity.CENTER);
        dialogWindow.setWindowAnimations(R.style.bottomdialogAnim);
        dialogWindow.setBackgroundDrawableResource(R.color.common_transparent);
        WindowManager.LayoutParams lp = dialogWindow.getAttributes();


        lp.width = ViewGroup.LayoutParams.MATCH_PARENT; //
        lp.height = ViewGroup.LayoutParams.WRAP_CONTENT;
        dialogWindow.setAttributes(lp);

    }

    private void getMenuInfo(int menu, int pid, final Callback callback) {
    
    
        List<NewsItem> result = new ArrayList<>();
        SubscribeUtils.subscribe(RetrofitManager.getInstance().getService(IMApiService.class)
                .loadTeacherQuestionList(KeyContacts.token, menu, pid), TeacherQuestionResBean.class, new NetListeren<TeacherQuestionResBean>() {
    
    
            @Override
            public void onSuccess(TeacherQuestionResBean teacherQuestionResBean) {
    
    
                if (teacherQuestionResBean.getData().size() <= 0) {
    
    
                    ToastUtil.showCustomToast("加载出现异常,请重启");
                    return;
                }
                curMenuInfo = teacherQuestionResBean.getData();
                menuInfos.add(curMenuInfo);
                callback.onSuccess();
            }

            @Override
            public void onError(Exception e) {
    
    
                callback.onFail();
            }
        });

    }

    public interface Callback {
    
    
        void onSuccess();

        void onFail();
    }

    private void add_menu(final int menu, final int pid, final Callback callback) {
    
    

        getMenuInfo(menu, pid, new Callback() {
    
    
            @Override
            public void onSuccess() {
    
    
//                setCancelable(false);
                View oldView = null;
                if (views.size() != 0) {
    
    
                    //说明有遗留的view,需要隐藏
                    oldView = views.get(views.size() - 1);
                }
                final RecyclerView newRecyclerView = (RecyclerView) customViewMgr.getNewView(oldView, R.layout.activity_menu1, R.id.menuRecycleView);
                NewsItemAdapter adapter = new NewsItemAdapter(curMenuInfo);

                adapter.setOnItemClickListener(new NewsItemAdapter.OnItemClickListener() {
    
    
                    @Override
                    public void onItemClick(int postion, View view) {
    
    
                        curIndex = postion;
                        System.out.println(curMenuInfo.get(postion));
                        psyDetailInfo.put(menu, curMenuInfo.get(postion));
                        callback.onSuccess();
                    }
                });
                customViewMgr.refreshRecycleView(newRecyclerView, adapter, (ViewGroup) curView);
                views.add(newRecyclerView);
            }

            @Override
            public void onFail() {
    
    
                ToastUtil.showCustomToast("加载失败~");
//                setCancelable(true);
            }
        });
    }

    private int final_menu = 4;

    @Override
    public void onBackPressed() {
    
    

        if (views.size() > 0) {
    
    
            //说明还有上一级,隐藏当前返回上一级
            if (views.size() != 1) {
    
    
                views.get(views.size() - 2).setVisibility(View.VISIBLE);
                ViewGroup tem = (ViewGroup) curView;
                tem.removeView(views.get(views.size() - 1));
                views.remove(views.get(views.size() - 1));

                curMenu--;
                if (curMenu < final_menu) {
    
    
                    menuInfos.remove(menuInfos.size() - 1);
                    curMenuInfo = menuInfos.get(menuInfos.size() - 1);
                }
            } else {
    
    
                views.get(0).setVisibility(View.GONE);
                views.remove(views.get(views.size() - 1));

                toMenu1.setVisibility(View.VISIBLE);
                toMenu2.setVisibility(View.VISIBLE);
                setCancelable(true);
            }

        } else {
    
    
            super.onBackPressed();
        }
    }

    private void show_last_view() {
    
    

        curMenu = 5;
        List<NewsItem> items = new ArrayList<>();
//        items.add(new NewsItem("Mr.王", "我觉得这么做会更好一点", "30"));

        SubscribeUtils.subscribe(RetrofitManager.getInstance().getService(IMApiService.class)
                        .getTeacherPsyMethodInfo(KeyContacts.token, psyDetailInfo.get(4).getId(),Constants.CUR_CHAT_ID), TeacherPsyMethonResBean.class
                , new NetListeren<TeacherPsyMethonResBean>() {
    
    
                    @Override
                    public void onSuccess(TeacherPsyMethonResBean teacherPsyMethonResBean) {
    
    
                        //这是解决方法
                        final JSONArray comments = (JSONArray) teacherPsyMethonResBean.getData().get("methods");
                        final List<NewsItem> comment = JSONObject.parseArray(comments.toJSONString(), NewsItem.class);
                        //这是解决方法对应用户是否点赞
                        final JSONArray isZans = (JSONArray) teacherPsyMethonResBean.getData().get("isZan");
                        final List<HashMap> isZan = JSONObject.parseArray(isZans.toJSONString(), HashMap.class);
                        //这是查看当前目录用户是否进行了标记
                        int status = Integer.parseInt(teacherPsyMethonResBean.getData().get("status").toString());
                        //这是查看当前目录用户是否觉得有效
                        int is_effect = Integer.parseInt(teacherPsyMethonResBean.getData().get("is_effect").toString());
                        final int[] tem_info = new int[]{
    
    status,is_effect};
                        if (comment.size() <= 0) {
    
    
                            ToastUtil.showCustomToast("期待您的填写");
                        }
                        if (isZan.size() != 0) {
    
    
                            for (int i = 0; i < comment.size(); i++) {
    
    
                                for (int j = 0; j < isZan.size(); j++) {
    
    
                                    if (isZan.get(j).get("zid").equals(comment.get(i).getId() + "")) {
    
    
                                        comment.get(i).setZan(true);
                                    }
                                }
                            }
                        }
                        String result = Objects.requireNonNull(psyDetailInfo.get(4)).getContent();
                        views.get(views.size() - 1).setVisibility(View.GONE);
                        View inflate = customViewMgr.getInflater().inflate(R.layout.activity_menu1, (ViewGroup) getWindow().getDecorView(), false);
                        LinearLayout linearLayout = (LinearLayout) inflate.findViewById(R.id.showNewView);
                        ViewGroup parent = (ViewGroup) linearLayout.getParent();
                        parent.removeView(linearLayout);
                        TextView textView1 = (TextView) linearLayout.findViewById(R.id.menu1_text);
                        textView1.setText(Objects.requireNonNull(psyDetailInfo.get(1)).getTitle());
                        TextView textView2 = (TextView) linearLayout.findViewById(R.id.menu2_text);
                        textView2.setText(Objects.requireNonNull(psyDetailInfo.get(2)).getTitle());
                        TextView textView3 = (TextView) linearLayout.findViewById(R.id.menu3_text);
                        textView3.setText(Objects.requireNonNull(psyDetailInfo.get(3)).getTitle());
                        TextView textView4 = (TextView) linearLayout.findViewById(R.id.menu4_text);
                        textView4.setText(Objects.requireNonNull(psyDetailInfo.get(4)).getTitle());
                        TextView textView = (TextView) linearLayout.findViewById(R.id.new_view_text);
                        textView.setText(result);
                        final RecyclerView recyclerView = (RecyclerView) linearLayout.findViewById(R.id.showCommentView);
                        final NewsItemAdapter adapter = new NewsItemAdapter(comment);
                        recyclerView.setAdapter(adapter);
                        adapter.setOnItemClickListener(new NewsItemAdapter.OnItemClickListener() {
    
    
                            @Override
                            public void onItemClick(final int postion, final View view) {
    
    
                                if (comment.get(postion).isZan()) {
    
    
                                    final AlertDialog.Builder builder = new AlertDialog.Builder(curContext);
//                        builder.setTitle("确认");
                                    builder.setMessage("是否取消点赞");
                                    builder.setPositiveButton("是的", new OnClickListener() {
    
    
                                        @Override
                                        public void onClick(final DialogInterface dialog, int which) {
    
    
                                            int zanId = comment.get(postion).getId();
                                            SubscribeUtils.subscribe(RetrofitManager.getInstance().getService(IMApiService.class).psyNoDizan(KeyContacts.token, zanId),
                                                    BaseBean.class, new NetListeren<BaseBean>() {
    
    
                                                        @Override
                                                        public void onSuccess(BaseBean baseBean) {
    
    
                                                            ToastUtil.showCustomToast("取消成功");
                                                            dialog.dismiss();
                                                            comment.get(postion).setZan(false);
                                                            comment.get(postion).setDizan(comment.get(postion).getDizan() - 1);
                                                            recyclerView.setAdapter(adapter);
                                                        }
                                                    });
                                        }
                                    });
                                    builder.show();
                                } else {
    
    
                                    AlertDialog.Builder builder = new AlertDialog.Builder(curContext);
//                        builder.setTitle("确认");
                                    builder.setMessage("是否进行点赞");
                                    builder.setPositiveButton("是的", new OnClickListener() {
    
    
                                        @Override
                                        public void onClick(final DialogInterface dialog, int which) {
    
    
                                            int zanId = comment.get(postion).getId();
                                            SubscribeUtils.subscribe(RetrofitManager.getInstance().getService(IMApiService.class).psyDizan(KeyContacts.token, zanId),
                                                    BaseBean.class, new NetListeren<BaseBean>() {
    
    
                                                        @Override
                                                        public void onSuccess(BaseBean baseBean) {
    
    
                                                            ToastUtil.showCustomToast("点赞成功");
                                                            dialog.dismiss();
                                                            comment.get(postion).setZan(true);
                                                            comment.get(postion).setDizan(comment.get(postion).getDizan() + 1);
                                                            recyclerView.setAdapter(adapter);
                                                        }
                                                    });
                                        }
                                    });
                                    builder.show();
                                }
                            }
                        });
                        LinearLayout solve_ly = linearLayout.findViewById(R.id.solve_btn);
                        solve_ly.setOnTouchListener(new View.OnTouchListener() {
    
    
                            @Override
                            public boolean onTouch(View v, MotionEvent event) {
    
    
                                if(tem_info[1]==0){
    
    
                                    //说明该问题用户没有标记为已解决
                                    AlertDialog.Builder builder = new AlertDialog.Builder(curContext);
                                    builder.setMessage("该问题的解决思路以及方法是否有效?");
                                    builder.setPositiveButton("是", new OnClickListener() {
    
    
                                        @Override
                                        public void onClick(final DialogInterface dialog, int which) {
    
    
                                            SubscribeUtils.subscribe(RetrofitManager.getInstance().getService(IMApiService.class).updatePosTeacherPsyMethodInfo(KeyContacts.token,
                                                    psyDetailInfo.get(4).getId(), tem_info[0], 1, Constants.CUR_CHAT_ID), BaseBean.class, new NetListeren<BaseBean>() {
    
    
                                                @Override
                                                public void onSuccess(BaseBean baseBean) {
    
    
                                                    tem_info[1] = 1;
                                                    ToastUtil.showCustomToast("感谢您的反馈");
                                                    dialog.dismiss();
                                                }
                                            });
                                        }
                                    });
                                    builder.setNegativeButton("取消", new OnClickListener() {
    
    
                                        @Override
                                        public void onClick(DialogInterface dialog, int which) {
    
    
                                            dialog.dismiss();
                                        }
                                    });
                                    builder.show();
                                }
                                else if(tem_info[1]==1){
    
    
                                    //说明该问题用户为已解决
                                    AlertDialog.Builder builder = new AlertDialog.Builder(curContext);
                                    builder.setMessage("是否取消有效?");
                                    builder.setPositiveButton("是", new OnClickListener() {
    
    
                                        @Override
                                        public void onClick(final DialogInterface dialog, int which) {
    
    
                                            SubscribeUtils.subscribe(RetrofitManager.getInstance().getService(IMApiService.class).updatePosTeacherPsyMethodInfo(KeyContacts.token,
                                                    psyDetailInfo.get(4).getId(), tem_info[0], 0, Constants.CUR_CHAT_ID), BaseBean.class, new NetListeren<BaseBean>() {
    
    
                                                @Override
                                                public void onSuccess(BaseBean baseBean) {
    
    
                                                    tem_info[1] = 0;
                                                    ToastUtil.showCustomToast("感谢您的反馈");
                                                    dialog.dismiss();
                                                }
                                            });
                                        }
                                    });
                                    builder.setNegativeButton("取消", new OnClickListener() {
    
    
                                        @Override
                                        public void onClick(DialogInterface dialog, int which) {
    
    
                                            dialog.dismiss();
                                        }
                                    });
                                    builder.show();
                                }
                                return false;
                            }
                        });
                        LinearLayout mark_ly = linearLayout.findViewById(R.id.mark_btn);
                        mark_ly.setOnTouchListener(new View.OnTouchListener() {
    
    
                            @Override
                            public boolean onTouch(View v, MotionEvent event) {
    
    
                                if(tem_info[0]==0){
    
    
                                    //说明该问题用户没有标记
                                    AlertDialog.Builder builder = new AlertDialog.Builder(curContext);
                                    builder.setMessage("是否标记该学生为此问题典型?");
                                    builder.setPositiveButton("是", new OnClickListener() {
    
    
                                        @Override
                                        public void onClick(final DialogInterface dialog, int which) {
    
    
                                            SubscribeUtils.subscribe(RetrofitManager.getInstance().getService(IMApiService.class).updatePosTeacherPsyMethodInfo(KeyContacts.token,
                                                    psyDetailInfo.get(4).getId(), 1, tem_info[1], Constants.CUR_CHAT_ID), BaseBean.class, new NetListeren<BaseBean>() {
    
    
                                                @Override
                                                public void onSuccess(BaseBean baseBean) {
    
    
                                                    tem_info[0] = 1;
                                                    ToastUtil.showCustomToast("感谢您的反馈");
                                                    dialog.dismiss();
                                                }
                                            });
                                        }
                                    });
                                    builder.setNegativeButton("否", new OnClickListener() {
    
    
                                        @Override
                                        public void onClick(DialogInterface dialog, int which) {
    
    
                                            dialog.dismiss();
                                        }
                                    });
                                    builder.show();
                                }else if(tem_info[0]==1){
    
    
                                    //说明该问题用户有标记
                                    AlertDialog.Builder builder = new AlertDialog.Builder(curContext);
                                    builder.setMessage("是否取消标记该学生为此问题典型?");
                                    builder.setPositiveButton("是", new OnClickListener() {
    
    
                                        @Override
                                        public void onClick(final DialogInterface dialog, int which) {
    
    
                                            SubscribeUtils.subscribe(RetrofitManager.getInstance().getService(IMApiService.class).updatePosTeacherPsyMethodInfo(KeyContacts.token,
                                                    psyDetailInfo.get(4).getId(), 0, tem_info[1], Constants.CUR_CHAT_ID), BaseBean.class, new NetListeren<BaseBean>() {
    
    
                                                @Override
                                                public void onSuccess(BaseBean baseBean) {
    
    
                                                    tem_info[0] = 0;
                                                    ToastUtil.showCustomToast("感谢您的反馈");
                                                    dialog.dismiss();
                                                }
                                            });
                                        }
                                    });
                                    builder.setNegativeButton("否", new OnClickListener() {
    
    
                                        @Override
                                        public void onClick(DialogInterface dialog, int which) {
    
    
                                            dialog.dismiss();
                                        }
                                    });
                                    builder.show();
                                }
                                return false;
                            }
                        });
                        LinearLayout add_ly = linearLayout.findViewById(R.id.add_btn);

                        final ViewGroup tem = (ViewGroup) curView;
                        add_ly.setOnTouchListener(new View.OnTouchListener() {
    
    
                            @Override
                            public boolean onTouch(View v, MotionEvent event) {
    
    
                                //进入编辑的view
                                curMenu = 6;
                                views.get(views.size() - 1).setVisibility(View.GONE);
//                if (views.contains(edit_view)) {
    
    
//                    int index = views.indexOf(views.contains(edit_view));
//                    views.get(index).setVisibility(View.VISIBLE);
//                    return false;
//                }
                                View inflate = customViewMgr.getInflater().inflate(R.layout.add_opinion, tem, false);
                                LinearLayout linearLayout = (LinearLayout) inflate.findViewById(R.id.add_view);
                                ViewGroup parent1 = (ViewGroup) linearLayout.getParent();
                                parent1.removeView(linearLayout);
                                Button back_add_view = (Button) linearLayout.findViewById(R.id.back_add_view);
                                TextView hintText = (TextView) linearLayout.findViewById(R.id.opinion_hint);
                                final EditText editText = (EditText) linearLayout.findViewById(R.id.add_opinion_text);
                                hintText.setText(Objects.requireNonNull(psyDetailInfo.get(1)).getTitle()
                                        + "\n" + Objects.requireNonNull(psyDetailInfo.get(2)).getTitle()
                                        + "\n" + Objects.requireNonNull(psyDetailInfo.get(3)).getTitle()
                                        + "\n" + Objects.requireNonNull(psyDetailInfo.get(4)).getTitle());
                                back_add_view.setOnClickListener(new View.OnClickListener() {
    
    
                                    @Override
                                    public void onClick(View v) {
    
    
                                        onBackPressed();
                                    }
                                });
                                Button upload_opinion = (Button) linearLayout.findViewById(R.id.upload_new_opinion);
                                upload_opinion.setOnClickListener(new View.OnClickListener() {
    
    
                                    @Override
                                    public void onClick(View v) {
    
    

                                        AlertDialog.Builder builder = new AlertDialog.Builder(curContext);
                                        builder.setTitle("是否上传");
                                        builder.setPositiveButton("确认", new OnClickListener() {
    
    
                                            @Override
                                            public void onClick(final DialogInterface dialog, int which) {
    
    
                                                SubscribeUtils.subscribe(RetrofitManager.getInstance().getService(IMApiService.class).uploadTeacherOpinion(KeyContacts.token,
                                                        psyDetailInfo.get(4).getId(), editText.getText().toString()), BaseBean.class, new NetListeren<BaseBean>() {
    
    
                                                    @Override
                                                    public void onSuccess(BaseBean baseBean) {
    
    
                                                        ToastUtil.showCustomToast("上传成功,请返回上一级再次进入");
                                                        dialog.dismiss();
                                                        onBackPressed();
                                                    }
                                                });
                                            }
                                        });
                                        builder.setNegativeButton("取消", new OnClickListener() {
    
    
                                            @Override
                                            public void onClick(DialogInterface dialog, int which) {
    
    
                                                dialog.dismiss();
                                            }
                                        });
                                        builder.show();
                                    }
                                });
                                tem.addView(linearLayout);
                                views.add(linearLayout);

//                setContentView(linearLayout);
                                return false;
                            }
                        });
                        tem.addView(linearLayout);
                        views.add(linearLayout);
                    }
                });


    }
}

backend development

table design

I used a DbSchematool to design the table. It was quite troublesome
to bind the id of the parent directory to the subdirectory as the association key
before writing it. However, it is not that complicated in practice.
DbSchemaThis tool has several useful functions. The first one is Fake data can be randomly generated in this designed table. The other is that you can export sql files like msyql, so that you can directly import mysql.
Insert image description here

writing interface

Currently, 5 interfaces have been created in the project to implement.
One is an interface for querying directory information at all levels. The query is performed through the requested directory level and the pid of the upper level.
The other is an interface for querying information on the details page, including all the previous information to which the details page belongs. The information of the parent directory, the information of the comment area, and whether the details page has been marked by the user and uploaded his or her own thoughts. One is the
interface for giving likes,
the other is the interface for canceling likes
, and the other is Interface for updating status of details page

Guess you like

Origin blog.csdn.net/pure81/article/details/130642114