(四)制作JSON,自动将图标填充进所有工具
首先是JSON,因为工具很多,所以JSON内容很长。
具体而言,JSON是一个数组中的对象(只有这一个对象),他有两个属性:BigImg和CommonImg。
这两个属性都是数组类型;
BigImg里面,他用于存放最上面的三个大图标;
CommonImg里面,存放其他工具图标。
BigImg单个数组元素的结构如下:
<span style="font-family:SimSun;">{
"title": "微信清理",
"description": "定期清理微信,节省手机空间",
"bigImg": {
"ImgPosition": {
"x": "0px",
"y": "0px"
}
},
"commonImg": {
"ImgPosition": {
"x": "-100px",
"y": "0px"
}
}
},</span>
前两个属性看值就知道了;
bingImg和commonImg属性中的ImgPosition中的两个属性,主要是描述这个图标在图片中的位置;
CommonImg结构类似:
{
"title": "手游模拟器",
"description": "电脑玩手游,挂机辅助神器",
"type": "title",
"commonImg": {
"ImgPosition": {
"x": "-100px",
"y": "-100px"
}
}
},
只不过少了一个bigImg属性(因为他不需要);
但多了一个type属性,用于描述其将放置于哪个分类下面。
下面上JSON的全部内容:(共计661行)
[
{
"BigImg": [
{
"title": "微信清理",
"description": "定期清理微信,节省手机空间",
"bigImg": {
"ImgPosition": {
"x": "0px",
"y": "0px"
}
},
"commonImg": {
"ImgPosition": {
"x": "-100px",
"y": "0px"
}
}
},
{
"title": "雷电OS",
"description": "雷电OS Editor 旧机变新机",
"bigImg": {
"ImgPosition": {
"x": "-350px",
"y": "0px"
}
},
"commonImg": {
"ImgPosition": {
"x": "-600px",
"y": "-500px"
}
}
},
{
"title": "手机相册扩容",
"description": "无损处理图片,腾出50%空间",
"bigImg": {
"ImgPosition": {
"x": "-700px",
"y": "0px"
}
},
"commonImg": {
"ImgPosition": {
"x": "-700px",
"y": "-500px"
}
}
}
],
"CommonImg": [
{
"title": "手游模拟器",
"description": "电脑玩手游,挂机辅助神器",
"type": "title",
"commonImg": {
"ImgPosition": {
"x": "-100px",
"y": "-100px"
}
}
},
{
"title": "360连回家",
"description": "随时随地,清理家中电脑",
"type": "title",
"commonImg": {
"ImgPosition": {
"x": "-200px",
"y": "-100px"
}
}
},
{
"title": "驱动大师",
"description": "驱动安装一键解决",
"type": "title",
"commonImg": {
"ImgPosition": {
"x": "-300px",
"y": "-100px"
}
}
},
{
"title": "安全桌面",
"description": "一键整理您的桌面",
"type": "safe",
"commonImg": {
"ImgPosition": {
"x": "-400px",
"y": "-100px"
}
}
},
{
"title": "隐私保镖",
"description": "五层隐私防护,清理隐私痕迹",
"type": "safe",
"commonImg": {
"ImgPosition": {
"x": "-500px",
"y": "-100px"
}
}
},
{
"title": "防黑加固",
"description": "修补可能会被黑客利用的",
"type": "safe",
"commonImg": {
"ImgPosition": {
"x": "-600px",
"y": "-100px"
}
}
},
{
"title": "软件管家",
"description": "安全下载,轻松管理您的软件",
"type": "safe",
"commonImg": {
"ImgPosition": {
"x": "-400px",
"y": "0px"
}
}
},
{
"title": "人工服务",
"description": "7*24小时为您解决电脑问题",
"type": "safe",
"commonImg": {
"ImgPosition": {
"x": "-500px",
"y": "0px"
}
}
},
{
"title": "手机助手",
"description": "免费手机应用,资源下载平台",
"type": "safe",
"commonImg": {
"ImgPosition": {
"x": "-700px",
"y": "-100px"
}
}
},
{
"title": "弹窗拦截",
"description": "拦弹窗,去广告,就是给力",
"type": "safe",
"commonImg": {
"ImgPosition": {
"x": "-800px",
"y": "-100px"
}
}
},
{
"title": "隔离沙箱",
"description": "隔离系统真实环境运行软件",
"type": "safe",
"commonImg": {
"ImgPosition": {
"x": "-900px",
"y": "-100px"
}
}
},
{
"title": "软件小助手",
"description": "快速启动您常用软件",
"type": "safe",
"commonImg": {
"ImgPosition": {
"x": "0px",
"y": "-200px"
}
}
},
{
"title": "主页防护",
"description": "防止恶意程序篡改浏览器主页",
"type": "safe",
"commonImg": {
"ImgPosition": {
"x": "-100px",
"y": "-200px"
}
}
},
{
"title": "主页修复",
"description": "一键解决浏览器主页相关问题",
"type": "safe",
"commonImg": {
"ImgPosition": {
"x": "-200px",
"y": "-200px"
}
}
},
{
"title": "文件解密",
"description": "免费还原被木马加密的文件",
"type": "safe",
"commonImg": {
"ImgPosition": {
"x": "-300px",
"y": "-200px"
}
}
},
{
"title": "网络优化",
"description": "全新家庭网络管理,秒踢蹭网",
"type": "network",
"commonImg": {
"ImgPosition": {
"x": "-400px",
"y": "-200px"
}
}
},
{
"title": "断网急救箱",
"description": "上不了网?就用断网急救箱",
"type": "network",
"commonImg": {
"ImgPosition": {
"x": "-600px",
"y": "0px"
}
}
},
{
"title": "免费WiFi",
"description": "电脑变热点,免费无线上网",
"type": "network",
"commonImg": {
"ImgPosition": {
"x": "-700px",
"y": "0px"
}
}
},
{
"title": "宽带测速器",
"description": "获取网络带宽和上网速度数值",
"type": "network",
"commonImg": {
"ImgPosition": {
"x": "-800px",
"y": "0px"
}
}
},
{
"title": "WiFi体检",
"description": "检测并修复路由器安全隐患",
"type": "network",
"commonImg": {
"ImgPosition": {
"x": "-500px",
"y": "-200px"
}
}
},
{
"title": "流量防火墙",
"description": "发现并阻止偷偷占流量的程序",
"type": "network",
"commonImg": {
"ImgPosition": {
"x": "0px",
"y": "-100px"
}
}
},
{
"title": "LSP修复",
"description": "修复网络异常和不能上网",
"type": "network",
"commonImg": {
"ImgPosition": {
"x": "-600px",
"y": "-200px"
}
}
},
{
"title": "DNS优选",
"description": "杜绝网络差,启用更优DNS",
"type": "network",
"commonImg": {
"ImgPosition": {
"x": "-700px",
"y": "-200px"
}
}
},
{
"title": "寝室必备",
"description": "看看哪个室友在占网速",
"type": "network",
"commonImg": {
"ImgPosition": {
"x": "-800px",
"y": "-200px"
}
}
},
{
"title": "360壁纸",
"description": "海量高清壁纸,美化电脑桌面",
"type": "system",
"commonImg": {
"ImgPosition": {
"x": "-900px",
"y": "-200px"
}
}
},
{
"title": "急救盘",
"description": "一盘在手,系统无忧",
"type": "system",
"commonImg": {
"ImgPosition": {
"x": "0px",
"y": "-300px"
}
}
},
{
"title": "任务管理器",
"description": "找出当前占用资源的程序",
"type": "system",
"commonImg": {
"ImgPosition": {
"x": "-300px",
"y": "0px"
}
}
},
{
"title": "鲁大师",
"description": "辨别硬件真伪,实时监测温度",
"type": "system",
"commonImg": {
"ImgPosition": {
"x": "-100px",
"y": "-300px"
}
}
},
{
"title": "默认软件",
"description": "帮您设置常用的默认软件",
"type": "system",
"commonImg": {
"ImgPosition": {
"x": "-200px",
"y": "-300px"
}
}
},
{
"title": "查找大文件",
"description": "找出占用磁盘空间的大文件",
"type": "system",
"commonImg": {
"ImgPosition": {
"x": "-300px",
"y": "-300px"
}
}
},
{
"title": "注册表瘦身",
"description": "清理无效、错误的注册表键值",
"type": "system",
"commonImg": {
"ImgPosition": {
"x": "-400px",
"y": "-300px"
}
}
},
{
"title": "系统盘瘦身",
"description": "通过瘦身解决系统盘空间不足",
"type": "system",
"commonImg": {
"ImgPosition": {
"x": "-500px",
"y": "-300px"
}
}
},
{
"title": "文件恢复",
"description": "快速帮您恢复被误删的文件",
"type": "system",
"commonImg": {
"ImgPosition": {
"x": "-600px",
"y": "-300px"
}
}
},
{
"title": "系统急救箱",
"description": "查杀顽固木马,修复系统异常",
"type": "system",
"commonImg": {
"ImgPosition": {
"x": "-600px",
"y": "0px"
}
}
},
{
"title": "磁盘擦除",
"description": "彻底清除磁盘数据,保护隐私",
"type": "system",
"commonImg": {
"ImgPosition": {
"x": "-700px",
"y": "-300px"
}
}
},
{
"title": "一键装机",
"description": "装机必备软件一键搞定",
"type": "system",
"commonImg": {
"ImgPosition": {
"x": "-800px",
"y": "-300px"
}
}
},
{
"title": "右键管理",
"description": "管理鼠标的右键菜单",
"type": "system",
"commonImg": {
"ImgPosition": {
"x": "-900px",
"y": "-300px"
}
}
},
{
"title": "系统重装",
"description": "无需光盘,恢复系统初始状态",
"type": "system",
"commonImg": {
"ImgPosition": {
"x": "0px",
"y": "-400px"
}
}
},
{
"title": "网游加速器",
"description": "解决游戏卡机掉线,永久免费",
"type": "game",
"commonImg": {
"ImgPosition": {
"x": "-100px",
"y": "-400px"
}
}
},
{
"title": "游戏大厅",
"description": "小号多开不串号,键鼠回放爽",
"type": "game",
"commonImg": {
"ImgPosition": {
"x": "-200px",
"y": "-400px"
}
}
},
{
"title": "游戏保险箱",
"description": "保护游戏网银账号安全",
"type": "game",
"commonImg": {
"ImgPosition": {
"x": "-300px",
"y": "-400px"
}
}
},
{
"title": "游戏优化器",
"description": "一键解决玩游戏卡、慢问题",
"type": "game",
"commonImg": {
"ImgPosition": {
"x": "-400px",
"y": "-400px"
}
}
},
{
"title": "360理财",
"description": "360互联网金融服务平台",
"type": "smalltools",
"commonImg": {
"ImgPosition": {
"x": "-500px",
"y": "-400px"
}
}
},
{
"title": "360看图",
"description": "防范图片木马,安全查看照片",
"type": "smalltools",
"commonImg": {
"ImgPosition": {
"x": "-600px",
"y": "-400px"
}
}
},
{
"title": "魔法摄像头",
"description": "让视频聊天既安全又有趣",
"type": "smalltools",
"commonImg": {
"ImgPosition": {
"x": "-700px",
"y": "-400px"
}
}
},
{
"title": "360云盘",
"description": "安全免费,超大空间的云盘",
"type": "smalltools",
"commonImg": {
"ImgPosition": {
"x": "-200px",
"y": "0px"
}
}
},
{
"title": "C盘搬家",
"description": "转移系统盘重要资料和文件",
"type": "smalltools",
"commonImg": {
"ImgPosition": {
"x": "-800px",
"y": "-400px"
}
}
},
{
"title": "360问答",
"description": "提出你的问题,分分钟有答案",
"type": "smalltools",
"commonImg": {
"ImgPosition": {
"x": "-900px",
"y": "-400px"
}
}
},
{
"title": "苹果设备清理",
"description": "清理App垃圾,节省手机空间",
"type": "smalltools",
"commonImg": {
"ImgPosition": {
"x": "0px",
"y": "-500px"
}
}
},
{
"title": "360压缩",
"description": "新一代的压缩软件,永久免费",
"type": "smalltools",
"commonImg": {
"ImgPosition": {
"x": "-100px",
"y": "-500px"
}
}
},
{
"title": "健康精灵",
"description": "可爱精灵,助您健康使用电脑",
"type": "smalltools",
"commonImg": {
"ImgPosition": {
"x": "-200px",
"y": "-500px"
}
}
},
{
"title": "小清新日历",
"description": "查询天气、农历和节假日",
"type": "smalltools",
"commonImg": {
"ImgPosition": {
"x": "0px",
"y": "0px"
}
}
},
{
"title": "安全浏览器",
"description": "恶意网站拦截,下载保护",
"type": "smalltools",
"commonImg": {
"ImgPosition": {
"x": "-300px",
"y": "-500px"
}
}
},
{
"title": "文件粉碎机",
"description": "彻底粉碎无法删除的文件",
"type": "smalltools",
"commonImg": {
"ImgPosition": {
"x": "-400px",
"y": "-500px"
}
}
},
{
"title": "U盘鉴定器",
"description": "鉴定U盘真实容量",
"type": "smalltools",
"commonImg": {
"ImgPosition": {
"x": "-500px",
"y": "-500px"
}
}
}
]
}
]
为了适应type,接下来我们需要改造html模板:
将div.toolbox-all的dom结构改装成如下:
div.toolbox-all
//这个是最上面的大图标那一行
div.firstRow
//以下是单个按钮
//横线那一行,如果是多行app,应考虑使用另外一个
div.dotted
div.commonRow.title
div.titleRow
span.titleRow-left
span.titleRow-text 电脑安全
div.commonRow.safe
div.titleRow
span.titleRow-left
span.titleRow-text 网络优化
div.commonRow.network
div.titleRow
span.titleRow-left
span.titleRow-text 系统工具
div.commonRow.system
div.titleRow
span.titleRow-left
span.titleRow-text 游戏优化
div.commonRow.game
div.titleRow
span.titleRow-left
span.titleRow-text 实用小工具
div.commonRow.smalltools
这样通过type来定位该图标被添加的dom位置即可。
顺便,以上订正了一个之前把commonRow打成commanRow的问题。记得修改样式表(尴尬)
再顺便订正三个样式需要被调整的地方:
.back .contentbox .commonRow .normalTool .text .title {
line-height: 25px;
font-size: 16px;
}
.back .contentbox .commonRow .normalTool .text .description {
line-height: 30px;
font-size: 12px;
color: #aaa;
}
.back .contentbox .commonRow .normalTool .addButton {
display: none;
position: absolute;
top: 7px;
right: 15px;
width: 60px;
height: 22px;
background-image: linear-gradient(rgb(98, 227, 25) 0%, rgb(68, 208, 27) 100%);
font-size: 12px;
color: white;
text-align: center;
line-height: 20px;
border: 1px solid rgb(65, 199, 36);
-webkit-border-radius: 1px;
-moz-border-radius: 1px;
border-radius: 1px;
}
下来呢,我们需要读取JSON,然后将其添加入页面之中;
首先,创建一个Tool类,他表示一个图标;
//单个工具
var Tool = function (obj) {
this.obj = obj;
// 0表示未加载到我的工具,1表示加载到我的工具,2表示加载到我的工具的右下小窗处
// 为了方便测试,这里先默认设置为1
this.state = 1;
//用于在全部工具页面
this.createBigImgDom = function (callback) {
var self = this;
var obj = this.obj
var str = '<div class="BigTool">' +
'<span class="img" style="background-position: ' + obj.bigImg.ImgPosition.x + ' ' + obj.bigImg.ImgPosition.y + '"></span>' +
'<span class="mask"></span>' +
'<div class="text">' +
'<div class="title">' + obj.title + '</div>' +
'<div class="description">' + obj.description + '</div>' +
'</div>' +
'<div class="addButton">添加</div>' +
'</div>';
var node = $(str);
node.click(function () {
if (self.state) {
callback();
}
})
return node;
};
this.createNormalTool = function (callback) {
var self = this;
var obj = this.obj
var str = '<div class="normalTool">' +
'<div class="img" style="background-position: ' + obj.commonImg.ImgPosition.x + ' ' + obj.commonImg.ImgPosition.y + '"></div>' +
'<div class="text">' +
'<div class="title">' + obj.title + '</div>' +
'<div class="description">' + obj.description + '</div>' +
'</div>' +
'<div class="addButton">添加</div>' +
'</div>';
var node = $(str);
node.click(function () {
if (self.state) {
callback();
}
})
return node;
};
this.createSmallTool = function (callback) {
var obj = this.obj
var position_x = parseInt(obj.commonImg.ImgPosition.x) * 0.615 + "px";
var position_y = parseInt(obj.commonImg.ImgPosition.y) * 0.615 + "px";
var str = '<div class="tool-foot">' +
'<div class="img" style="background-position: ' + position_x + ' ' + position_y + '"></div>' +
'<div class="text"></div>' +
'</div>';
var node = $(str);
node.click(function () {
if (self.state) {
callback();
}
})
return node;
};
}
他有三个方法,两个属性;
①obj属性是在创建的时候赋值给他的,方便读取创建实例时的初始值。这个初始值就是上面那个JSON中的一个元素(BigImg或CommonImg中的一个元素);
②state属性表示该按钮状态,具体看注释
三个方法的作用依次为:
①返回一个用于所有工具最顶端的大图标的dom;
②返回一个用于放置在所有工具、我的工具普通位置的dom;
③返回一个用于放在我的工具右下角小位置的dom;
④他们都有一个点击事件,会判断当前状态来进行。为了方便测试,我这里并没有针对性的设置。在之后会进行修改。
我们还缺一些其他的方法,例如将移动用的函数,点击后触发事件的函数等等;
还缺一些属性,例如,设置其目前是否可以移动,目前处于什么位置的东西等等;
等等我们再补全这个Tool类。
然后,我们需要创建一个加载JSON,处理数据的类。
在创建这个类之前,我们建立一个data文件夹,和img、javascripts、stylesheets文件夹平级;
将JSON命名为tools.json,并放于data文件夹中;
下面是处理这个JSON的JS代码类:
var ToolsConfigJsonLoad = function (url) {
this.url = url ? url : "data/tools.json";
this.load = function () {
var self = this;
$.ajax({
url: self.url,
dataType: "json",
type: "GET",
success: function (data) {
self.addToolsInToolbox_all(data);
}
})
};
//将内容添加到全部工具页面中
this.addToolsInToolbox_all = function (data) {
var type = [];
data[0].BigImg.forEach(function (obj) {
var tool = new Tool(obj);
var mixin = new MixinTool(tool);
var callback = mixin.mixin()
$(".firstRow").append(tool.createBigImgDom(callback));
})
data[0].CommonImg.forEach(function (obj) {
if (type.indexOf(obj.type) < 0) {
type.push(obj.type);
}
var tool = new Tool(obj);
var mixin = new MixinTool(tool);
var callback = mixin.mixin()
$(".commonRow." + obj.type).append(tool.createNormalTool(callback));
})
this.addPlaceHolderWhenOnlyTwoToolsInToolbox_All(type);
this.addDottedLineInToolbox_All();
};
// 这个目的是当某一行只有两个图标时,创造一个占位的图标
this.addPlaceHolderWhenOnlyTwoToolsInToolbox_All = function (type) {
type.forEach(function (obj) {
var length = $(".commonRow." + obj + " > *").length;
if (length % 3 == 2) {
$(".commonRow." + obj).append($('<div class="normalToolHolder"></div>'));
}
})
};
// 这个目的是为了给全部工具中的多行工具之间添加分割线
this.addDottedLineInToolbox_All = function () {
$(".commonRow .normalTool:nth-child(3n+4)").before('<div class="dotted"></div>');
}
}
这部分代码最重要的是load函数;
①他会发起一个ajax请求,来读取这个json;
②ajax请求可以使用用户自己给的url(如果有的话),或者默认url;
③在请求成功后,会对数据进行处理,简单来说,分别遍历BigImg这个属性的每个元素以及CommonImg这个属性的每个元素;
④利用这些元素的数据,生成一个Tool实例,然后又对她做了一些其他事情(具体之后再说),然后生成一个dom对象,插入到指定位置。
在生成工具的时候,显然每个工具的用途是不同的,因此我们希望这个工具在点击的时候,执行不同的处理方法,具体做法有以下几种。
①生成Tool实例的时候,手动给起赋予一个处理函数(缺点:生成代码虎非常长,而且堆积在一起会很乱);
②将处理函数放在Tool类里,然后生成dom的时候,点击事件触发Tool了的不同方法(缺点:Tool类会非常长,并且可以通过Tool类的实例来调用本来不希望他调用的方法);
③将所有的处理方法集中在一个类之中,我们需要编辑的时候只需要编辑这个类即可,然后将对应的方法,作为回调函数传递给这个dom的创建函数,在创建函数里,调用这个回调函数(我的选择)。
我这里选择的是第三种方法,因此需要生成一个MixinTool类,他具备将对应的方法返回给对应的Tool类实例的功能。
为了区别不同按钮,我在JSON里每个元素里新加了一个属性ID,具体修改后内容如下;
{
"title": "微信清理",
"ID":"No0",
"description": "定期清理微信,节省手机空间",
"bigImg": {
"ImgPosition": {
"x": "0px",
"y": "0px"
}
},
"commonImg": {
"ImgPosition": {
"x": "-100px",
"y": "0px"
}
}
},
这里的ID的值,就是利用该元素生成Tool实例时,我们写在MixinTool类里,该元素预期拿取的点击事件处理函数。
MixinTool类的代码如下:
var MixinTool = function (tool) {
this.mixin = function () {
var self = this;
if ("ID" in tool.obj & tool.obj.ID in this) {
//console.log(self[tool.obj.ID])
return self[tool.obj.ID];
} else {
return self.default;
}
};
this.default = function () {
console.log("No thing will happen");
}
this.No0 = function () {
console.log("No 0 you click it");
};
this.No1 = function () {
console.log("No 1 you click it");
};
this.No2 = function () {
console.log("No 2 you click it");
};
this.No3 = function () {
console.log("No 3 you click it");
};
this.No4 = function () {
console.log("No 4 you click it");
};
this.No5 = function () {
console.log("No 5 you click it");
};
}
他有一些方法,假如某个Tool实例没有对应的方法,他会执行default这个函数作为点击的响应事件;否则执行对应的。
mixin函数需要显示调用,作为Tool类创建dom结点时的参数使用。
具体如何使用参照上面的例子。
由于我们已经抽象出来多个类了,因此不如将之前页面切换的逻辑也抽象成一个类,具体代码如下:
//注意,这些其实都是全局变量
var Tab = function () {
//以下代码大量考虑到扩展性,例如,可以新增一个tab和content页面
this.tabClick = function () {
$(".tool").click(function () {
//这里是上面的图标的逻辑变换
if (!($(this.children[0]).hasClass("select"))) {
$(".select").removeClass("select");
$(this.children[0]).addClass("select");
//这里是hover的横线的位置变化
var node = $(".tool .hover");
node.remove();
//当动画需要停止的时候,让他停止
if ('stop' in node) {
node.stop();
}
node.css("left", "0px");
$(this).append(node);
//以下应该是切换页面的逻辑
//获取切换到哪一个页面,
var index = null;
for (var i = 0; i < this.parentNode.children.length; i++) {
if (this == this.parentNode.children[i]) {
index = i;
}
}
$(".contentbox > div").addClass("displayNONE");
$(".contentbox > div:nth-child(" + (index + 1) + ")").removeClass("displayNONE");
}
})
};
this.tabMouseEnter = function () {
$(".tool").mouseenter(function (evt) {
//只有当鼠标移动到非当前选中的tab上时,才会移动
if (!($(this.children[0]).hasClass("select"))) {
var self = this;
var node = $(".tool .hover");
var start = null;
var end = null;
var tools = $(".toolTab")[0].children
for (var i = 0; i < tools.length; i++) {
if (self == tools[i]) {
end = i;
} else if ($(".select")[0].parentNode == tools[i]) {
start = i;
}
}
//停止之前的动画
if ('stop' in node) {
node.stop();
}
//现在开始动画效果
node.animate({"left": (end - start) * 160 + "px"})
}
})
};
this.tabMouseLeave = function () {
$(".tool").mouseleave(function () {
//只有当鼠标移动到非当前选中的tab上时,才会移动
if (!($(this.children[0]).hasClass("select"))) {
var node = $(".tool .hover");
//停止之前的动画
if ('stop' in node) {
node.stop();
}
node.animate({"left": "0px"})
}
})
}
}
而调用到目前为止的类和函数,十分简单,如代码:
$(document).ready(function () {
//这里是点击切换显示页面
var toolboxTab = new Tab();
toolboxTab.tabClick();
toolboxTab.tabMouseEnter();
toolboxTab.tabMouseLeave();
var jsonLoad = new ToolsConfigJsonLoad();
jsonLoad.load();
})
目前进度:
①自动生成所有工具里的所有工具;
②给工具添加点击响应事件;
目前还欠缺的内容:
①将所有工具里的工具,添加进我的工具;
②我的工具页面的各种逻辑;
③视情况,让工具可以被添加、或不能被添加(添加按钮在已添加后禁止显示)。
网友评论