百宝云注册码系统
3.1 注册码系统的设计图
注册码系统一般都有以下这些功能:
1) 试用登录与获取剩余试用时间
注册码系统一般都有以下这些功能:
1) 试用登录与获取剩余试用时间
2) 注册码登录与获取注册码的剩余使用时间
3) 生成注册码
4) 解绑注册码
5) 冻结注册码
6) 解冻注册码
7) 删除注册码
8) 续费注册码
<!--EndFragment-->
3.2 试用功能
由于要在存储试用的一些数据,因此需要使用到数据库来存储,下面是数据库中试用表的内容。
试用表
字段 |
字段描述 |
id |
序号 整型数据,为主键,且为自增 |
pcid |
机器码 |
begintime |
试用开始时间 |
endtime |
试用结束时间 |
num |
试用次数 |
创建试用表的百宝云代码如下:
// 创建试用数据表 function sqlCreatTestDataBase() var 返回数组,ret ret = sqlitesqlarray("regtest.db","create table IF NOT EXISTS testManager(id integer primary key autoincrement,pcid,begintime,endtime,num);",返回数组)//创建表 if(!ret) sendtextmsg("创建表失败:"& getlasterror(1)) return false else return true end end
试用的数据库创建完成之后,就需要完善试用的其他功能了,如:验证试用登录、获取使用时间。
验证试用登录主要是判断是否允许当前的机器试用软件,百宝云端代码如下:
// 判断试用者是否可以验证通过 功能 sqlCheckTesterLogin(pcID) // 通过传入的机器码,在数据库里查询,看数据库里是否有记录,没有则加入 变量 sqlstr = 字符串格式化("select * from testManager where pcid='%s';",pcID) 变量 返回数组,ret,retmsg="登录失败:未知错误" ret = sqlite数据库执行返回数组("regtest.db",sqlstr,返回数组) 如果(返回数组 != null) 发送文本消息("Select = "&返回数组) // 判断当前机器码的试用次数是否达到设定的最大值 变量 num = 返回数组[0]["num"] 发送文本消息("试用次数="&num) 如果(num > 100 ) retmsg = "失败:试用次数达到最大值" 发送文本消息("失败:试用次数达到最大值") 返回 "false" 结束 num++ 变量 begintime = 当前时间() 变量 endtime = 指定时间("n",20,begintime) // 试用时间20分钟 变量 update = 字符串格式化("update testManager set num='%s',begintime='%s',endtime='%s' where pcid='%s';",num,begintime,endtime,pcID) 发送文本消息("SQL: "&update) ret = sqlite数据库执行返回数组("regtest.db",update,返回数组) retmsg = "true" 否则 // 第一次试用软件 变量 begintime = 当前时间() 变量 endtime = 指定时间("n",20,begintime) // 试用时间20分钟 变量 insert = 字符串格式化("insert into testManager(pcid,begintime,endtime,num) values('%s','%s','%s','1')",pcID,begintime,endtime) 发送文本消息("SQL: "&insert) ret = sqlite数据库执行返回数组("regtest.db",insert,返回数组) retmsg = "true" 结束 返回 retmsg 结束
获取用户试用的剩余时间,方便在软件里限制运行的时间。百宝云端代码如下:
// 查询剩下的试用时间 功能 sql查询试用时间(pcid) // 参数格式: 机器码 变量 sqlstr = 字符串格式化("select * from testManager where pcid='%s';",pcid) 变量 返回数组,ret,retMsg ret = sqlite数据库执行返回数组("regtest.db",sqlstr,返回数组) 如果(返回数组 == null) 发送文本消息("Error:"&获取错误信息(1)) retMsg = "-1" 否则 变量 begintime = 返回数组[0]["begintime"] 变量 endtime = 返回数组[0]["endtime"] 变量 nowtime = 当前时间() 变量 min = 时间间隔("n",nowtime,endtime) 发送文本消息("leave Time: "&min) retMsg = min // 返回剩余的时间:多少分钟 结束 返回 retMsg 结束
为了注册码系统可以适用多平台,这里就使用百宝云内置的事件_post,把试用的验证、查询试用剩余时间都通过post请求来完成。
post传入的第二个参数是一个json格式的数据,格式为{"flag":"表示验证试用还是查询时间","pcid":"机器码"}
百宝云端的代码如下:
// 执行客户端发来的post请求,并返回执行的结果,以网页源码的形式返回. 功能 _post(token,arg) 发送文本消息("_post: " & arg) 变量 paramArr = json转数组(arg) 如果(!是否数组(paramArr)) 返回 "错误的参数列表" 结束 变量 flag = paramArr["flag"] 变量 pcID = paramArr["pcid"] 选择(flag) 条件 "试用" 返回 sqlCheckTesterLogin(pcID) 条件 "试用时间" 返回 sql查询试用时间(pcID) 结束 结束
这样,客户端只需要使用post请求访问百宝云就可以完成:试用的验证以及查询试用剩余时间。
注册码系统的试用功能就这样完成了。
TC语言使用此试用系统的代码如下:
// Post方法与百宝云应用通信 功能 runBbyFunctionPost(arg) //post提交 变量 token = "aac5ddb832bbca6d2db00a7557152d5c" 变量 params = "token="& token &"&funparams="&arg 变量 url = "http://api.baibaoyun.com/cloudapi/CloudAppGetOrPostAPI" 变量 post_ret = http提交请求("POST",url,params,"utf-8") 返回 post_ret 结束 // 检测软件的试用时间是否结束 功能 检测试用脚本运行时间(ID) 变量 param = 字符串格式化("{ \"flag\":\"试用时间\", \"pcid\":\"%s\", \"key\":\"%s\"}",pcID,"0") 循环(真) 等待(1000*60) 变量 ret = runBbyFunctionPost(param) 如果(是否整型(ret)) 如果( ret < 0) 线程关闭(线程ID) // 关闭正在运行的脚本,或者下面的消息框使用一个新的EXE程序来替代 消息框("试用时间到!") 退出() 结束 否则 变量 arr = json转数组(ret) 消息框("试用失败,原因:" & arr["errMsg"]) 结束 结束 结束
3.3 注册码相关功能
注册码表
字段 |
字段描述 |
id |
序号 整型数据,为主键,且为自增 |
regcode |
注册码 |
begintime |
注册码第一次启动的时间 |
endtime |
注册码的结束时间 |
bindDevicesName |
绑定的机器码 |
isbind |
是否绑定 |
isFrozen |
是否冻结 |
type |
注册码类型(天卡、周卡、月卡) |
isactive |
注册码是否启动 |
创建注册码表的百宝云代码如下:
// 创建数据库 function sqlCreatDataBase() var 返回数组,ret // id 数据库的自增编号 // regcode 注册码 // begintime 开始时间 // endtime 结束时间 // bindDevicesName 绑定的机器码 // isbind 是否绑定 // isFrozen 是否冻结 // type 注册码类型 // isactive 注册码是否启动 ret = sqlitesqlarray("regtest.db","create table IF NOT EXISTS regManager(id integer primary key autoincrement,regcode,begintime,endtime,bindDevicesName,isbind,isFrozen,type,isactive);",返回数组)//创建表 if(!ret) sendtextmsg("创建表失败:"& getlasterror(1)) return false else return true end end
以下将是注册码常规操作的功能代码。
3.3.1 生成注册码
根据传入的参数,生成相应类型的注册码。
// 生成注册码功能 功能 sql创建新注册码(param) 变量 timestr = 获取系统时间() 变量 md5str = md5(timestr) 变量 retArray = null,inserText 选择(param) 条件 "ji" inserText = 字符串格式化("insert into regManager(regcode,begintime,endtime,bindDevicesName,isbind,isFrozen,type,isactive) values('%s','','','','false','false','ji','false');",md5str) 条件 "mouth" inserText = 字符串格式化("insert into regManager(regcode,begintime,endtime,bindDevicesName,isbind,isFrozen,type,isactive) values('%s','','','','false','false','mouth','false');",md5str) 条件 "week" inserText = 字符串格式化("insert into regManager(regcode,begintime,endtime,bindDevicesName,isbind,isFrozen,type,isactive) values('%s','','','','false','false','week','false');",md5str) 条件 "day" inserText = 字符串格式化("insert into regManager(regcode,begintime,endtime,bindDevicesName,isbind,isFrozen,type,isactive) values('%s','','','','false','false','day','false');",md5str) 结束 变量 ret = sqlite数据库执行返回json("regtest.db",inserText,retArray) 变量 selectStr = 字符串格式化("select * from regManager where regcode='%s';",md5str) ret = sqlite数据库执行返回json("regtest.db",selectStr,retArray) 如果(ret) 发送文本消息("生成注册码["&md5str&"]成功") 返回 retArray 否则 发送文本消息("生成注册码["&md5str&"]失败") 返回 retArray 结束 结束
3.3.2 解绑注册码
// 解绑注册码 功能 sql解绑注册码(regKey) 变量 返回数组,ret 变量 sqlstr = 字符串格式化("select * from regManager where regcode='%s';",regKey) ret = sqlite数据库执行返回json("regtest.db",sqlstr,返回数组) 如果(ret && 返回数组 != null) sqlstr = 字符串格式化("update regManager set isbind='false' where regcode='%s';",regKey) ret = sqlite数据库执行返回json("regtest.db",sqlstr,返回数组) 发送文本消息("sql解绑注册码") 返回 真 否则 发送文本消息("sql解绑注册码") 返回 假 结束 结束
3.3.3 冻结注册码
// 冻结注册码 功能 sql冻结注册码(regKey) 变量 返回数组,ret 变量 sqlstr = 字符串格式化("select * from regManager where regcode='%s';",regKey) ret = sqlite数据库执行返回json("regtest.db",sqlstr,返回数组) 如果(ret && 返回数组 != null) sqlstr = 字符串格式化("update regManager set isFrozen='true' where regcode='%s';",regKey) ret = sqlite数据库执行返回json("regtest.db",sqlstr,返回数组) 发送文本消息("sql冻结注册码") 返回 真 否则 发送文本消息("sql冻结注册码") 返回 假 结束 结束
3.3.4 解冻注册码
// 解冻注册码 功能 sql解冻注册码(regKey) 变量 返回数组,ret 变量 sqlstr = 字符串格式化("select * from regManager where regcode='%s';",regKey) ret = sqlite数据库执行返回json("regtest.db",sqlstr,返回数组) 如果(ret && 返回数组 != null) sqlstr = 字符串格式化("update regManager set isFrozen='false' where regcode='%s';",regKey) ret = sqlite数据库执行返回json("regtest.db",sqlstr,返回数组) 发送文本消息("sql解冻注册码") 返回 真 否则 发送文本消息("sql解冻注册码") 返回 假 结束 结束
3.3.5 删除注册码
// 删除注册码 功能 sql删除注册码(regKey) 变量 返回数组,ret 变量 sqlstr = 字符串格式化("select * from regManager where regcode='%s';",regKey) ret = sqlite数据库执行返回json("regtest.db",sqlstr,返回数组) 如果(ret && 返回数组 != null) sqlstr = 字符串格式化("delete from regManager where regcode='%s';",regKey) ret = sqlite数据库执行返回json("regtest.db",sqlstr,返回数组) 发送文本消息("sql删除注册码") 返回 真 否则 发送文本消息("sql删除注册码") 返回 假 结束 结束
3.3.6 续费注册码
// sql续费注册码 功能 sql续费注册码(regKey,type) 变量 返回数组,ret 变量 sqlstr = 字符串格式化("select * from regManager where regcode='%s';",regKey) ret = sqlite数据库执行返回数组("regtest.db",sqlstr,返回数组) 如果(ret && 返回数组 != null) 变量 end1Time1 = 返回数组[0]["endtime"] 变量 endtime = 0 选择(type) 条件 "ji" endtime = 指定时间("m",3,end1Time1) 条件 "mouth" endtime = 指定时间("m",1,end1Time1) 条件 "week" endtime = 指定时间("d",7,end1Time1) 条件 "day" endtime = 指定时间("d",1,end1Time1) 结束 sqlstr = 字符串格式化("update regManager set endtime='%s' where regcode='%s';",endtime,regKey) 发送文本消息(sqlstr) ret = sqlite数据库执行返回json("regtest.db",sqlstr,返回数组) 发送文本消息("sql续费注册码成功") 返回 真 否则 发送文本消息("sql续费注册码成功") 返回 假 结束 结束
3.3.7 注册码登录的处理
// 判断登录者是否可以验证通过 功能 sqlCheckLoginInfo(pcID,regKey) 变量 sqlstr = 字符串格式化("select * from regManager where regcode='%s';",regKey) 变量 返回数组,ret,retmsg="登录失败:未知错误" ret = sqlite数据库执行返回数组("regtest.db",sqlstr,返回数组) 发送文本消息("机器码: " & pcID&" 注册码: " & regKey) //如果相同的机器码与注册码访问频繁,可以考虑是否有人在破解软件 发送文本消息("sqlCheckLoginInfo: " & 返回数组) 如果(返回数组 != null) // 判断注册码是否冻结了 如果(返回数组[0]["isFrozen"] == "true") retmsg = "登录失败:注册码已经冻结" 返回 retmsg 结束 // 判断注册码是否已经绑定了本机器 变量 bindDevicesName = 返回数组[0]["bindDevicesName"] // 第一次登录 如果(bindDevicesName == "") 变量 begintime = 当前时间() 变量 endtime = 0 选择(返回数组[0]["type"]) 条件 "ji" endtime = 指定时间("m",3,begintime) 条件 "mouth" endtime = 指定时间("m",1,begintime) 条件 "week" endtime = 指定时间("d",7,begintime) 条件 "day" endtime = 指定时间("d",1,begintime) 结束 变量 update = 字符串格式化("update regManager set bindDevicesName='%s',begintime='%s',endtime='%s',isbind='true',isactive='true' where regcode='%s';",pcID,begintime,endtime,regKey) 发送文本消息("SQL: "&update) ret = sqlite数据库执行返回数组("regtest.db",update,返回数组) 变量 min = 时间间隔("n",begintime,endtime) 如果(min>0) retmsg = "登录成功:剩余时间=" & min & "分钟" 结束 否则如果(bindDevicesName != "" && bindDevicesName == pcID) // 机器码相同的话,就直接返回剩余时间 变量 begintime = 返回数组[0]["begintime"] 变量 endtime = 返回数组[0]["endtime"] 变量 nowtime = 当前时间() 变量 min = 时间间隔("n",nowtime,endtime) 如果(min>0) retmsg = "登录成功:剩余时间=" & min & "分钟" 否则 retmsg = "登录失败:注册码已经过期" 结束 否则如果(bindDevicesName != "" && bindDevicesName != pcID) // 机器码不同的就判断是否绑定了 变量 isBind = 返回数组[0]["isbind"] 如果(isBind == "true") retmsg = "登录失败:注册码已经绑定其他机器" 否则 变量 update = 字符串格式化("update regManager set bindDevicesName='%s',isbind='true' where regcode='%s';",pcID,regKey) 发送文本消息("更换绑定机器码: "&update) ret = sqlite数据库执行返回数组("regtest.db",update,返回数组) 变量 endtime = 返回数组[0]["endtime"] 变量 nowtime = 当前时间() 变量 min = 时间间隔("n",nowtime,endtime) 如果(min>0) retmsg = "登录成功:剩余时间=" & min & "分钟" 否则 retmsg = "登录失败:注册码已经过期" 结束 结束 结束 否则 发送文本消息("查询失败:"&获取错误信息(1)) retmsg = "登录失败:注册码不存在" 结束 返回 retmsg 结束
3.3.8 查询注册码的使用时间
// 查询注册码使用时间 功能 sql查询注册码使用时间(pcID,regKey) 变量 sqlstr = 字符串格式化("select * from regManager where regcode='%s' and bindDevicesName='%s'",regKey,pcID) 变量 返回数组,ret,retMsg ret = sqlite数据库执行返回数组("regtest.db",sqlstr,返回数组) 如果(返回数组 == null) retMsg = "查询失败:查询失败." 否则如果(返回数组[0]["isFrozen"] == "true") retMsg = "查询失败:注册码已经冻结." 否则 发送文本消息("isFrozen:"&返回数组[0]["isFrozen"]) 变量 begintime = 返回数组[0]["begintime"] 变量 endtime = 返回数组[0]["endtime"] 变量 nowtime = 当前时间() 变量 min = 时间间隔("n",nowtime,endtime) retMsg = min 结束 返回 retMsg 结束
注册码的登录验证与剩余时间查询也是通过post的方法来实现的,具体代码如下:
// {"flag":"表示验证试用还是查询时间","pcid":"机器码"} // 执行客户端发来的post请求,并返回执行的结果,以网页源码的形式返回. 功能 _post(token,arg) 发送文本消息("_post: " & arg) 变量 paramArr = json转数组(arg) 如果(!是否数组(paramArr)) 返回 "错误的参数列表" 结束 变量 flag = paramArr["flag"] 变量 pcID = paramArr["pcid"] 选择(flag) 条件 "注册码登录" 发送文本消息("注册码登录:"&arg) 变量 regValue = paramArr["key"] 返回 sqlCheckLoginInfo(pcID,regValue) 条件 "查询注册码时间" 发送文本消息("查询注册码时间,机器码:"&arg) 变量 regValue = paramArr["key"] 返回 sql查询注册码使用时间(pcID,regValue) 结束 结束
3.4 注册码管理端
考虑到注册码管理端可以是任何语言编写的,因此对注册码的管理操作,就放到 _get事件里。
具体的百宝云端代码如下:
//arg参数格式: {"flag":"表示验证试用还是查询时间","pcid":"机器码","type":"注册码类型,续费用的"} 功能 _get(token,arg) 发送文本消息("_get: " & arg) 变量 paramArr = json转数组(arg) 如果(!是否数组(paramArr)) 返回 "错误的参数列表" 结束 变量 flag = paramArr["flag"] 变量 pcid = paramArr["pcid"] 选择(flag) 条件 "查询所有注册码" 发送文本消息("查询所有注册码") 返回 sql获取注册码所有信息() 条件 "解绑注册码" 发送文本消息("解绑注册码:"&pcid) 返回 sql解绑注册码(pcid) 条件 "冻结注册码" 发送文本消息("冻结注册码:"&pcid) 返回 sql冻结注册码(pcid) 条件 "解冻注册码" 发送文本消息("解冻注册码:"&pcid) 返回 sql解冻注册码(pcid) 条件 "删除注册码" 发送文本消息("删除注册码:"&pcid) 返回 sql删除注册码(pcid) 条件 "新建注册码" 发送文本消息("新建注册码,类型为:"&pcid) 返回 sql创建新注册码(pcid) 条件 "续费注册码" 变量 type = paramArr["type"] 发送文本消息("续费注册码,类型为:"&type&" 注册码:"&pcid) 返回 sql续费注册码(pcid,type) 结束 结束
查询所有注册码的功能代码如下:
// 返回所有注册码信息 功能 sql获取注册码所有信息() 变量 sqlstr = "select * from regManager" 变量 返回数组,ret ret = sqlite数据库执行返回json("regtest.db",sqlstr,返回数组) 发送文本消息("获取所有注册码:"&返回数组) 返回 返回数组 结束
3.5 数据安全性
针对数据的安全性,可以对get与post的数据做加密处理,加密算法可以自己编写,也可以试用百宝云提供的加解密算法,之后定期更新加解密算法,这样可以提升数据的安全性。
示例1:加解密解决方案
例如在客户端,Get与Post请求之前,我们对提交的参数做加密处理,之后再传输到百宝云端。
TC的代码如下:
// Get方式与百宝云应用通信 功能 runBbyFunction(arg) //Get提交 // 对arg的参数做加密处理 var aeskey = bby.aesencrypt(arg,"bby2015") 变量 token = "aac5ddb832bbca6d2db00a7557152d5c" 变量 params = "token="& token &"&funparams="&aeskey 变量 url = "http://api.baibaoyun.com/cloudapi/CloudAppGetOrPostAPI" 变量 post_ret = http提交请求("GET",url&"?"¶ms,"","utf-8") 返回 post_ret 结束 // Post方式与百宝云应用通信 功能 runBbyFunctionPost(arg) //post提交 // 对arg的参数做加密处理 var aeskey = bby.aesencrypt(arg,"bby2015") 变量 token = "aac5ddb832bbca6d2db00a7557152d5c" 变量 params = "token="& token &"&funparams="&aeskey 变量 url = "http://api.baibaoyun.com/cloudapi/CloudAppGetOrPostAPI" 变量 post_ret = http提交请求("POST",url,params,"utf-8") 返回 post_ret 结束
百宝云端在接收到数据之后,先解密再判断就可以了。代码如下:
功能 _get(token,arg) // 对接收的数据先解密,再处理 var 解密的字符串 = aesdecrypt(arg,"bby2015") 发送文本消息("解密的字符串:"&解密的字符串) 返回 "来自客户端的get请求" 结束 功能 _post(token,arg) // 对接收的数据先解密,再处理 var 解密的字符串 = aesdecrypt(arg,"bby2015") 发送文本消息("解密的字符串:"&解密的字符串) 返回 "来自客户端的post请求" 结束
上面
的百宝云端代码只是演示代码,所以没有做过多的处理,大家可以根据自己的项目修改即可。
示例2: 重要数据存储在百宝云服务器,只有登录成功的用户可以获取。
百宝云端代码:
// 按下主按钮触发函数方法 功能 _mainbutton() 写配置("第一NPC坐标","151,320") 写配置("第二NPC坐标","121,431") 写配置("第三NPC坐标","220,190") 结束 功能 _get(token,arg) 选择(arg) 条件 "第一NPC坐标" 返回 读配置(arg) 条件 "第二NPC坐标" 返回 读配置(arg) 条件 "第三NPC坐标" 返回 读配置(arg) 结束 返回 "未知请求" 结束
在
_get或者_post事件里,最好是做一次权限的验证,只有通过验证的客户端才能获取到这些数据。
TC端代码
变量 token = "aac5ddb832bbca6d2db00a7557152d5c" 变量 params = "token="& token &"&funparams="&"第一NPC坐标" 变量 url = "http://api.baibaoyun.com/cloudapi/CloudAppGetOrPostAPI" 变量 post_ret = http提交请求("GET",url&"?"¶ms,"","utf-8")
相关推荐
百宝云COM开发组件是...任何语言都可以做到无缝的与百宝云应用进行连接百宝云组件内置了数十种加解密算法,与百宝云内部数十种加密算法对应,可以无缝进行加解密操作。WIN7 WIN8 WIN10 系统注意事项 1、系统已经关闭UA
批量生成卡、查询卡、自动更新、加密、防破解、实时监控、管理等功能,最新、最全版本。
支持在线更新 对接百宝云编写代码 进行对接 详情
继之前开源的易语言网络验证系统V1版、V2.0版,本次百宝云给大家开源易语言网络验证V4版,功能完善,性能稳定,获得很多脚本作者的好评。整个管理端是纯易语言编写,全开源。 本套系统功能介绍: 1、支持批量生成...
狂风汉化百宝箱XP2.00a+注册码用于汉化,下载资源很少,供网友下载。
易语言百宝云网络验证系统V2.0版
亲爱的各位电脑爱好者,我跟大家一样是一位热爱封装系统的人,但现在封装工具纷繁复杂,没有一个统一的整理,...为了能让这个工具更加完善,经过两个多月的开发,系统封装百宝箱v2 beta2终于破壳了。赶紧下载看看吧!
百宝云开发工具是一款免费使用的云服务定制开发平台工具。可以轻松地开发APP,支持网络文件存储,网络数据库,有自己的云应用开发语言,还有强大的云交互功能。
百宝箱百宝箱百宝箱百宝箱百宝百宝箱百宝箱百宝箱百宝箱箱
易语言网络验证系统源码
百宝箱--百购网址导航百宝箱-天气、手机等查询系统
单机版与移动版产品均已实现注册码一码三用,可同时用于《EXCEL万能百宝箱》32位与64位以及《WPS万能百宝箱》。由全球顶尖级水平微软MVP专家与财会管理信息团队历时十年以上开发,是与EXCEL用户与爱好者共同努力的...
自动优化系统的小工具==优化百宝箱,优化百宝箱dowtools1.3
Excel、Wps、VBA、Office百宝箱 V31.6 32+64位完整珍藏版,包括Excel百宝箱、Wps百宝箱、VBA百宝箱、Office百宝箱以及完整教程功能演示。被誉为"全能的办公瑞士军刀"。助力办公文员、蓝领白领灵巧办公,办公必备利器...
是用JSP开发的一个类似于个人资料管理的系统
内置了图片百宝箱、财务百宝箱、函数百宝箱、二维码百宝箱。包括280个菜单功能和200个以上自定义函数,集480个宝贝于一身,但体积小于30MB。当安装万能百宝箱后,如果您使用Excel 2003,则将产生【万能百宝箱】菜单...
绑定机器码的网络验证系统,小巧玲珑,安全可靠,绝对源码.rar
WPS万能百宝箱2019 V27.0 全功能官方完整版,390个精品功能。支持XP至WIN10多个操作系统完美兼容,实现无缝隙对接,U盘版用户除了在原有可换机使用的基础上,实现XP--WIN10通行无阻。批量二维码识别、批量二维码生成、...
Excel百宝箱 Excel百宝箱