数据流图 和 数据字典

1、数据流图和数据字典是用来干啥的?

一、数据流图(Data Flow Diagram, DFD)

​ 从"数据(Data)"一词中咱们能够看出它是用来描述数据的,也就是说它的对象(或者说核心)应该是数据,要描述“(数据)是什么?”;从"流(Flow)"一词中咱们又能够提炼出它的角度是(数据的)传递过程与加工,即“(数据)由有哪些属性构成?从哪儿来?到哪儿去?要干啥?”;最后着眼"图(Diagram)"能够得出这是以图形为基础的模型,也就是用不一样的图形区分不一样的类别。html

​ 因此总结起来,一句话归纳:数据流图(DFD)是从数据(Data)传递和加工(Flow)角度,以图形(Diagram)的方式来表达系统的逻辑功能、数据在系统内部的逻辑流向和逻辑变换(Flow)过程。数据库

​ 来,咱们先看一个简单的实例(如今不知道怎么作很正常,一下子详细解释)。数据结构

数据流图-实例(学生选课)



二、数据字典(Data Dictionary)

​ 你们试想一下,咱们如今已经拥有了一张"数据流图(DFD)",那么光有这么一张图能够吗?好比说,你知道\(Entity\_001\)具体是啥嘛?不知道叭,这时确定有吐槽“那就把名称加上呗”,但\(Entity\_001\)仅仅只是一个名称嘛,既然是一个实体那是否是就还有属性呢?这时将这些属性一一标记上去这张图会是什么样,显然就很是的凌乱。因此咱们就用一个代号来表示一个对象(包括实体、数据流、加工、存储),在图以外引入新概念——数据字典(DD)来对这些代号进行解释。下面就来简单看一下数据字典是什么。运维

​ 不用多说确定是一个描述"数据(Data)"的东西,那怎么描述的呢?答案就是用"字典(Dictionary)"。字典是啥,只知道《辞海》、《康熙》或者《牛津》?umm……我能够说这差很少,字典就是一种映射关系,咱们小时候“做弊”用的“暗号”就是一个不成文的字典,譬如\(X\)同窗规定揿动一次就选\(A\)、揿动两次就选\(B\)……,那么咱们就能够获得以下的字典:编码

明文(也能够是id号) 密文(也能够是对对应id号的解释)
1 \(A\)
2 \(B\)
…… ……
26 \(Z\)

因此字典的本质也就是一张表,又因为是对数据流图的描述,那很天然地就包括以下几个方面:(Ⅰ)数据项;(Ⅱ)数据结构;(Ⅲ)数据流;(Ⅳ)数据存储;(Ⅴ)处理过程;这里先各出一个实例(用上面的数据流图为例,构造一个合理的、简化的数据字典):spa

(ⅰ)数据项:操作系统

\(ID\) \(Name\) 含义
\(studentID\) 学生的\(ID\) 对学生实体集有惟一标识的标识符
\(studentName\) 学生的姓名 每个学生实体在社会中的代号

(ⅱ)数据结构:.net

\(ID\) \(Name\) 组成(实体的属性)
\(Entity\_001\) 学生实体 \(ID\)号、姓名

(ⅲ)数据流:设计

\(ID\) \(Name\)
\(DataFlow\_001\) 排课信息
\(DataFlow\_002\) 学生信息
\(DataFlow\_003\) 课程信息
\(DataFlow\_004\) 学生选课信息

(ⅳ)数据存储:3d

\(ID\) \(Name\)
\(DataStorage\_001\) 学生天然状况(学生信息表)
\(DataStorage\_002\) 课程信息表
\(DataStorage\_003\) 学生的选课表

(ⅴ)处理及加工:

\(ID\) \(Name\) 处理
\(DataProcess\_001\) 学生选课 记录学生的\(ID\)、被选课程的\(ID\)






2、详细介绍数据流图和数据字典

一、数据流图

(Ⅰ)数据流图的基本图形和符号

​ 咱们先从最简单的图形分类入手,这里给出经常使用的四种基本图形及其含义【在图形中标注编号(\(ID\))或者名称(\(name\)),或者二者都标上,这样看图的时候既更直观还容易查找\(ID\)索引】:

图形(符号) 类别名称 含义说明
圆形-数据处理或者 椭圆形-数据处理
数据的加工和处理
\(Data Process, DP\)
必须有输入流和输出流,缺一不可
矩形-实体
数据的源点或汇点,
也就是外部实体(\(Entity\)
数据加工的一端,要么提供数据,
要么聚集数据造成新的外部实体
平行线-数据存储文件
数据存储文件
\(DataStorage\)
数据加工的一端,
能够提供数据或者存储数据
箭头-数据流
数据流
\(DataFlow\)
一边为实体或者数据存储文件,
另外一边为数据的加工和处理,
其名称清晰表达传递的主要数据

​ 在加工的时候不可避免会出现多种数据进出的状况,那么数据流图是怎样表示的呢?在作表以前咱们先画出数据加工和数据流的图【\((\theta_1,\theta_2) \in \theta=\{+, *, \bigoplus\}\)】:

数据加工和数据流-符号
\(\theta\)所表明的符号为 含义(令true = 1)
* 交集,同时成立(能够省略):\(\sum_{i=1}^{N}{DF_{(input,i)}}=N\)\(\sum_{j=1}^{M}{DF_{(output,j)}}=M\)
+ 并集,至少有一个成立:\(\sum_{i=1}^{N}{DF_{(input,i)}}\ge 1\)\(\sum_{j=1}^{M}{DF_{(output,j)}}\ge 1\)
\(\bigoplus\) 其中之一:\(\sum_{i=1}^{N}{DF_{(input,i)}}=1\)\(\sum_{j=1}^{M}{DF_{(output,j)}}=1\)



(Ⅱ)数据流图设计的原则

(1)、任意流不能重名 由于流的名字即为他们的\(ID\)号,常识告诉咱们不存在两个彻底同样的物体,为了区分必须避免重名;

(2)、数据守恒原则 对于任意一个数据处理来讲,其所有的输出数据流中的数据一定能从其输入数据流中的数据直接得到。这一原则也说明了数据流是必须与数据处理有关的,应该也只能依附与数据流。咱们能够用能量守恒来理解这一原则,将数据存储和外部实体比做物体、数据比做能量,数据处理即为物体之间的相互做用,只有在物体进行相互做用的时候才会存在能量的流动(传递),因此同理可得只有在数据处理的推进下,数据才得以传递,从而造成数据流

①、外部实体与外部实体之间不存在数据流;

②、外部实体与数据存储之间不存在数据流;

③、数据存储与数据存储之间不存在数据流;

④、数据流必须通过(其中一端为)数据处理(加工);

(3)、守恒加工原则 (前两条都是针对加工而言)

①、对于任意一个加工,至少有一个数据输入流和一个数据输出流;

②、由任意流不能重名能够推出:对于任意一个加工,输入数据流与输出数据流必须不一样名,即便输入的数据与输出的数据结构如出一辙,可是这样的状况常见于向数据存储文件写入数据的时候:因为数据守恒原则,数据流必须通过数据加工,可是这样的数据加工并不会改变数据流中的数据。因此人们规定:对流进或者流出数据存储文件的数据流不须要标注名字,由于文件自己就足以说明数据流。因此,若是一种数据流须要被屡次引用时能够创建一个临时的数据存储(对应的就是内存数据库),这样就没有必要为同一种数据流进行标号。另外,当输入输出流如出一辙的状况发生在非数据存储文件操做时,就要考虑其加工或者数据源存在的合理性和必要性了,由于这至关于没有对数据进行处理,属于冗余操做;

③、数据源包含数据存储文件、最终新造成的外部实体和数据存储文件必须与数据源同级,也就是说数据流的终点必定是在外部而且指向外部实体或者数据存储文件。由于只要有外部数据流参与,那么有入必有出,这个出就是指向新造成外部实体或数据文件的输出数据流;好比下图中的数据文件:\(Student\_Course\)

③

④、与③相对应的,若是新造成的外部实体或者数据存储文件在图的内部,就代表它不是数据流的终点而是一个结点,那么必须具有一条输入流和一条输出流;好比说在②中说起的临时数据存储文件。

⑤、与③和④相反的,若是在内部的数据存储文件不是新造成的,也就是说它们是该数据库管理系统直接向操做系统中发送请求并载入内存的数据存储文件,那么这些文件能够只含有输入或者输出流;好比说,如图③所示,显然\(Course\)\(Student\)都不是新造成的数据存储文件,因此它们虽然在顶层数据流图的内部,可是只有一条数据流(输出)。

⑥、每个(或一组)输入流与特定的一个(或一组)造成对应,这样一对数据输入输出流在同层级图中的同深度处以及彼此的后继(更深层的)输入输出流对应该是相互独立的,去掉其中任意一对或多对以后数据流图仍然保持守恒加工原则;如图:

(ⅰ)\(DF-A\)系列与\(DF-B\)系列相互独立;

(ⅱ)\(DF-A1\)系列之间(\(DF-A1\_1\)\(DF-A1\_2\))相互独立;

(ⅲ)彼此的后继之间(\(DF-A1\_1\)\(DF-A1\_2-A2\)系列、\(DF-A1\_2\)\(DF-A1\_1-A2\)系列、\(DF-A1\_1-A2\)系列与\(DF-A1\_2-A2\)系列)相互独立。

⑦、很容易被忽视的一点:数据存储不可能凭空出如今数据库管理系统中,必须经过操做系统从磁盘中读取相应的文件载入内存,当对数据存储文件操做完成以后,再写入磁盘。可是正是由于全部的数据流图都有这一类数据流,因此经常被做为枝节被省略,这致使在研究细节的时候发现不少数据流图都没有遵照守恒加工原则;因此完整的数据流图应该是这样(用虚线表示省略的):

这个时候咱们就能够理解为:从操做系统中读取的文件与外部实体给予的信息进行组合(数据加工),最后造成了新的文件并写入磁盘中。

(4)、父图与子图应该统一输入输出流: 父图能够看作是一个总体,也就是一个黑盒子,其中包含了不少个子图,那么子图的输入输出流固然就源自黑盒子(父图);好比学生选课后出了成绩:

父图与子图输入输出一致-学生选课出成绩

一共分了两个区域(上下),上部分为总体的局部数据流图,数据处理由一个父图构成;下部分即为父图中更加细节的子图数据流图。这个时候咱们能够看到父图由外部数据流(\(CourseSchedulingInfo\)\(ScoreInfo\)\(CourseInfo\)\(StudentInfo\))的参与产生了一个新的数据存储(\(Student\_Course\)),必须将其提出放在父图的外部,若是不这样作的话就会违反守恒加工原则。由父图子图流一致原则咱们能够得出另外一重要的原则:加工细节隐蔽原则,就是说没有必要一味地对父图进行拆分,能够适当地只保留父图不去关心子图的内在联系(类比总体法)。

(5)、简化加工之间的关系 加工间的数据流越少,各个加工就越相对独立、耦合度就越低,若是数据流不少的话,虽然能够实现较为复杂的功能可是也增长了运维成本,甚至可能形成动一发而牵全身的混乱局面。这就要求咱们作到先抓住主要矛盾,暂时忽略枝节

(6)、均匀分解父图 尽可能不要出现对数据处理分解的两极化,好比一个分了七八层而另外一个只分了两三层,这样会形成轻重不一的局面存在考虑不周的潜在隐患。

(7)、是数据流而不是控制流 数据流是控制流上的操做表示,只有在控制流上进行的数据流分析才有价值。也就是说数据流图只须要表达出数据的结构、来源、流向、加工,并不关心数据流在融入控制层以后进行的逻辑处理与程序跳转的结果(程序元素逻辑执行的前后顺序)。

在这些原则中最重要的当属:保持父图与子图平衡保持数据平衡加工细节隐蔽





二、数据字典

(Ⅰ)数据字典的用途与组成

​ 根据以前的分析,咱们能够得出:数据字典的就是对数据流图中出现的全部被命名的图形元素在数据字典中做为一个词条加以定义,使每一个图形元素的名称都有一个确切的解释。

​ 最初只给了二级表头,如今给出更加精细的三级表头,画一个思惟导图会更加清晰。

数据字典的组成部分

具体实例请看传送门:数据字典举例。(想要\(PDF\)版的能够私聊哦)


(Ⅱ)数据结构的描述

​ 在数据字典中最特殊的当属数据结构了,由于数据结构是描述其余字典条目的基础,因此准确来讲,数据字典中应该是包含下面4种条目:

①、数据项条目:数据类型、取值范围……等;

②、数据流条目:定义、给出组成数据流的数据项(利用数据结构描述);

③、文件条目:定义、给出组成文件的数据项(利用数据结构描述);

④、加工条目:加工条目必须具有原子性,给出说明(激发条件、逻辑、处理顺序……等);

咱们言归正传,数据结构的描述一般采用以下表中的符号:

符号 含义 说明
= 被定义为(赋值) \(x=a\)\(x\)由且仅由\(a\)构成
+ \(x=a+b\)\(x\)\(a\)\(b\)构成
[…|…]或者[…, …] \(x=[a,b]\)\(x\)\(a\)或者\(b\)构成
\(m\){…}\(n\)、{…}\(_{N}^{M}\) 重复(\(m,n\)的默认值为0和\(+\infty\) \(x=3\{a\}六、\{a\}_3^6\)\(a\)能够重复3~5次
(…) 可选(非必须项) \(x=(a)\)\(a\)能够出如今\(x\)
"…" 基本数据元素 \(x="a"\)\(x\)取值为\(a\)的数据元素
·· 链接 \(x=a··f\)\(x\)\(a\sim f\)组成

好比咱们要表示学生这个实体集(或者学生表)时,就能够这样:

\(StudentEntity=studentID+studentName+studentIDCard+studentSex+\{studentInterest\}+(studentInfo)\),

再好比咱们新建一个能够实现查询的任务,包括查询学生信息、课程信息以及学生选课信息,这是当数据库管理员(或者教务系统管理员)向教务管理系统发出查询请求(数据流)的时候就能够这样表示:

\(selectRequestInfo=[selectStudentInfo\ |\ selectCourseInfo\ |\ selectStudent\_CourseInfo]+\{IllegalRequest\}\)








3、数据流图 & 数据字典 综合应用问题

一、需求

​ 某教务管理系统的主要功能为:师生教学管理和信息查询。对于新招的师生,系统按照既定的法则自动生成师生的编号,并和他们的基本信息一块儿分别写入学生文件和教师文件,一样适用于新开设的课程。

(Ⅰ)师生教学管理功能:新增师生和课程、注销师生和课程、学生选课出成绩

(1)、新增师生和课程 新招师生和课程的时候须要分别编制《入校学生单》、《新招教师单》以及《新开设课程单》以便直接对新增对象进行管理与研究,而后将信息分别写入《学生表》、《教师表》和《课程表》。

①、《入校学生单》:\(ID\)号、姓名、身份证、出生年月日、性别、入校时间;

②、《新招教师单》:\(ID\)号、姓名、身份证、出生年月日、性别、新招时间;

③、《新开设课程单》:\(ID\)号、课程名、课时、上课信息(日期时间教室列表)、新开设时间;

(2)、注销师生和课程 学生毕业、老师退休以及课程结课的时候须要分别编制《学生毕业单》、《老师退休单》、《课程结课单》,而后分别修改《学生表》、《教师表》、《课程表》中的注销时间以及是否注销(默认值为\(NO\),现改成\(YES\))。

①、《学生毕业单》:\(ID\)号、毕业时间、是否毕业(只能填写\(YES\),用于覆盖《学生表》);

②、《老师退休单》:\(ID\)号、退休时间、是否退休(只能填写\(YES\),用于覆盖《教师表》);

③、《课程结课单》:\(ID\)号、结课时间、是否结课(只能填写\(YES\),用于覆盖《课程表》);

(3)、学生选课出成绩 学生选课时须要编制《学生选课申请单》和《学生最新选课单》。

①、《学生选课申请提交单》:学生的\(ID\)号、课程的\(ID\)号、选课权重

②、《学生最新选课单》:学生的\(ID\)号、课程的\(ID\)号、选课权重;

假设选课权重在同一学号记录中不能重复,且为[1, 6]之间的整数,当学生提交《学生选课申请单》时系统给出选项,学生自行选择,即限定每一个学生的选课门数最多为6门。此外系统应该有三层过滤网(这三层过滤能够放置在一个加工中——加工细节隐蔽原则):

(ⅰ)系统首先经过聚合运算检查在《学生最新选课单》中该学生的选课门数是否为6,若不是则容许将该学生《学生选课申请提交单》的选课信息添加至《学生最新选课单》;如果则拒绝添加。

(ⅱ)若是选课门数小于6则进行冲突检查,查找《学生选课表》中该学号对应的选课课程号集合,再在《课程表》中查找"上课信息"这一字段,而后与该学生新选课程的上课信息进行比对。若这时没有冲突才能将《学生选课申请提交单》的选课信息写入《学生最新选课单》;如有冲突则拒绝写入。

(ⅲ)排处第一层冲突以后,系统应该检查该学生全部新选课程的"上课信息"进行比对,并按照选课权重选取权重最大的课程,其余与之相冲突的选课记录将被删去。

通过系统的三层排除冲突以后的《学生最新选课单》方能写入《学生选课表》。以后学生考试填写试卷,教师批阅提供分数信息,将分数信息与选课信息合并存入《学生选课表》。


(Ⅱ)信息查询功能:查询教师学生和课程的基本信息、学生成绩

(1)、查询教师的基本信息 能够查询到教师的基本信息;

(2)、查询学生的基本信息 能够查询到学生的基本信息;

(3)、查询课程的基本信息 能够查询到课程的基本信息;

(4)、查询学生成绩的基本信息 能够查询到学生选课的信息以及学生在此课程中的分数状况;





二、数据流图

(Ⅰ)顶层图:

顶层图

(Ⅱ)第0层图:

(Ⅲ)加工的分解:

(ⅰ)对处理学生选课以及成绩信息的分解:

三、数据字典

\(Excel\)查看传送门:数据字典-教务管理系统部分功能

\(Excel\)下载传送门:数据字典-教务管理系统部分功能

4、数据字典的补充

​ 数据字典不仅仅是用于解释数据流图,还能在数据存储文件设计的时候提供援助。当现实世界中的主体有不断变化的属性时(属性的数量和属性的取值),尤为是变化得很是频繁的时候,就会引入数据字典辅助数据表设计。

​ 这里简单地介绍一下由\(rongwenbin\)先生总结的两种用于辅助设计数据库表的数据字典,原文传送门:数据字典。为了更好理解我将先生用到的实例换作咱们常见的教务管理系统,其主要功能为管理并查询学生、教师、课程……等实体集的基本信息。

​ 在构建数据库管理系统以前,我先将两种数据字典摆出来:

(Ⅰ)将主体的属性编码(设置每个属性\(ID\)号),并将这些\(ID\)号放入独立的数据库表中做为主键,其对应的值就是属性的取值;(这对应于数据库表规范化中的模式分解)

(Ⅱ)将结构(模式)相同的数据库表整合在一块儿,用统一的编码规范设置\(ID\)号并将其做为主键,对应的值为属性的名称以及属性的取值;(这对应于数据库表规范化中的模式合并)

​ 咱们来看这样一个需求:假设咱们已经设计出了该教务管理系统的逻辑模型初稿,其中有一个模式为“学生(学号,姓名,系别名称)”。在这一模式中体现出了“学生”实体和“学生属于系别”联系,虽然一举两得提升了查询的效率,可是这里很明显存在一个问题:系别的名称若是更改,则学生表中的"系别名称"属性的取值都要作出相应的调整,这系别名称还好,若是是国籍呢,好比前苏联到俄罗斯,这就要涉及到上亿份数据。怎样解决这一问题呢?先生指出咱们能够参考(Ⅰ)数据字典,新建一张《系别表》,其中存放"系别\(ID\)"和"系别名称",这样在学生表中直接引入外键"系别\(ID\)"便可,这是更改系别名称就只用在《系别表》中更改"系别名称"而"系别\(ID\)"不用改,保证了《学生表》的稳定性。上述文字转换为数据表的动态变换就是:

更改以前的数据库表《学生表》及实例:

学号 姓名 系别名称
180502304 BN2U 地理信息系统

更改以后的数据库表《学生表》及实例:

学号 姓名 系别\(ID\)
180502304 BN2U 001

新建的《系别表》及实例:

系别\(ID\) 系别名称
001 地理信息系统

根据上级的命令更改数据,将“地理信息系统”改成“地理信息科学”这样的话就会有:

更改以后的数据库表《学生表》及实例:

学号 姓名 系别\(ID\)
180502304 BN2U 001

新建的《系别表》及实例:

系别\(ID\) 系别名称
001 地理信息科学

显然《学生表》没有任何改动。

​ 这样很\(nice\)可是有没有想过若是一个主体中的属性不是两三个,而是几十个甚至上百个,那么每一次查询都涉及到上百个夺标链接操做,这时的查询效率简直不敢恭维。因而先生又提出了第二种方案:(Ⅱ)数据字典,将属性数据表进行合并,可是并非将全部的数据表进行合并,而是针对模式(结构)同样的一组表。这样就能将查询所涉及到的表大幅度的减小,从而提升了查询的效率。下面咱们来看一个案例,解释(Ⅰ)的缺点和(Ⅱ)。

​ 咱们如今有一个需求:假设咱们更新了模式,最后变为“学生(学号,姓名,证件类型,证件号,国籍,民族,系别名称,政治面貌)”,根据(Ⅰ)的分解,咱们能够将模式继续升级为“学生(学号,姓名,证件类型\(ID\),国籍\(ID\),民族\(ID\),系别\(ID\),政治面貌\(ID\))”、“证件类型(证件类型\(ID\),证件类型,证件号)”、“国籍(国籍\(ID\),国籍)”、“民族(民族\(ID\),民族名称)”、“系别(系别\(ID\),系别名称)”、“政治面貌(政治面貌\(ID\),政治面貌名称)”,就这样一直被分解,若是只是5个左右的表那查询起来也不是很费劲,可是一个学生显然不可能只有这样几个属性,因此若是继续分解下去就会带来过于沉重的查询计算量。

​ 既然咱们的目的是为了提升查询效率,那个合并数据表显然是一个不错的选择,可是咱们知道一个数据表的模式是定死了的,而且属性的取值是必须规定在同一个域,因此只有表结构相同、对应属性的取值范围相同的表才可以合并。咱们将目光转移至分解以后的属性表,发现除了《证件类型》这张表以外都很类似,模式都是“属性的名称(ID,属性的值)”,那咱们就能够合并了。回过头看《证件类型》这张表,不难发现"证件号"能够做为主码,从而代替"证件类型\(ID\)",这样《证件类型》表的模式为“证件类型(证件号,证件类型)”。这时咱们整合这些属性表,获得一个新的表模式“属性(属性\(ID\)号,属性分类\(ID\)号,属性取值)”,构造一个实例:

《系统属性代码表》

属性\(ID\) 属性分类 属性取值
001 身份证 xxxxxx20010202xxxx
002 身份证 xxxxxx20000302xxxx
003 暂居证 yyyyyy
004 国籍 中国
005 国籍 萨摩亚
006 国籍 美国
007 系别 地理信息科学
008 政治面貌 团员
009 政治面貌 党员
…… …… ……

《学生表》

学生\(ID\) 学生姓名
180502304 BN2U
180502305 \(\pi\)
180502302 \(e\)

《属性表》

学生\(ID\) 属性\(ID\)
180502304 001
180502304 004
180502304 007
180502304 008
180502302 002
180502302 004
…… ……

这样在查询任意一个学生的时候最多也就是3张表的查询,一张差姓名、另外两张查找其余属性\(ID\)以及对应的内容,这样查询效率是否是就大大提高了呢?可是细心的同窗会发现这样作的后果就是形成了最开始的问题:对数据库进行更改很麻烦。因此这里我想作的一点补充就是:这两种数据字典的思想要相结合,咱们能够在需求分析阶段调查不易改变的属性名称,将这些属性名称利用(Ⅱ)数据字典整合成为一张表;相应地将容易改变的属性名称利用(Ⅰ)数据字典构造一张新的属性表。就拿上面这个例子来讲,对于“国籍”、“证件类型”、“民族”、“政治面貌”对于咱们来讲在至关长的一段时期内属性的名称是不会变化的(可能咱们会变成党员,可是团员仍是叫作团员),而“系别”可能就会有所调整,因此咱们能够构建这样4张表:“学生(学号,姓名)”、“系别(系别\(ID\),系别名称)”、“系统属性代码(属性\(ID\),属性分类,属性取值)”、“属性表(学生\(ID\)\(ID\)属性\(ID\))”,其中表示系的时候在《系统属性代码表》中体现:

《系统属性代码表》

属性\(ID\) 属性分类 属性取值
001 001
002 004
003 国籍 中国

《系别表》

系别\(ID\) 系别名称
001 食品科学与工程
004 地理信息科学
数据流图 && 数据字典就到这了,不知道大家有没有弄懂?(反正我是明白了【狗头保命】)
相关文章
相关标签/搜索