1 Star 0 Fork 2

Admin/EasyClick津彩函数

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
Jc.js 25.14 KB
一键复制 编辑 原始数据 按行查看 历史
津彩 提交于 2021-04-19 15:50 . 函数库
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938
/*
* 津彩插件beta 1.1.2
* date 20210310
* create by 刘百浲
* QQ:50494558
* */
/***************************图色系列***************************/
function getHexFromInt(argb){
return ((argb)>>>0).toString(16).slice(-6);
}
function getRbgFromHex(hex) {
return [
parseInt(hex.substr(0,2),16),
parseInt(hex.substr(2,2),16),
parseInt(hex.substr(4,2),16)
]
}
function getRgbFromInt(argb){
let rgb = [];
rgb[0] = (argb & 0xff0000) >> 16;
rgb[1] = (argb & 0xff00) >> 8;
rgb[2] = (argb & 0xff);
return [rgb[0],rgb[1],rgb[2]];
}
function getIntFromHex(color){
let data=[];
data[0]=parseInt(color.substr(0,2),16);
data[1]=parseInt(color.substr(2,2),16);
data[2]=parseInt(color.substr(4,2),16);
return getIntFromColor(data[0],data[1],data[2])
}
function getIntFromColor(r,g,b){
return ((0xFF << 24)|(r << 16)|(g << 8)|b);
}
function getHexFromColor(r,g,b) {
return getHexFromInt(((0xFF << 24)|(r << 16)|(g << 8)|b))
}
/**
*ret = cmpColorEx(481|138|0x24A060-0x101010,214|124|0x24A060-0x101010,408|280|0xEEEEEE-0x101010,553|359|0xFFFFFF-0x101010,553|444|0xFFFFFF-0x101010, "0.95");
* @param str 多点比色
* */
function parseColor(str) {
let ret=[];
str=str.replace(/0x/g,'');
str=str.replace(/0x/g,'');
let data = str.split(',');
let res=[];
let temp;
for(let v in data){
res=data[v].split('|');
if(res[2].indexOf('-')!==-1){
temp = res[2].split('-');
ret.push([parseInt(res[0]),parseInt(res[1]),getIntFromHex(temp[0]),temp[1]])
}else {
ret.push([parseInt(res[0]),parseInt(res[1]),getIntFromHex(res[2]),''])
}
}
return ret
}
/**
* @description 多点比色点击
* <Br/>other int大于1正整数:超时时间毫秒
* <Br/>int负整数:找到(点击)后延时
* <Br/>int 0-1小米:查找的精度
* <Br/>string:debug会执行调试所有的点,其它的string是点击后执行logi()
* <Br/>传入数组:则点击数组的坐标例如[100,88]
* <Br/>布尔值true需要点击,false不点击
* <Br/>所有参数不区分顺序
* @return boolean|布尔型
* @param str 默认是text搜索
* */
function cmpColorEx(str) {
let sim=0.9,debug=false,click=false,tb,delay=0,waiting=0,say='';
if(!str){
return false
}
if(typeof (str)!=='string'){
return false
}
let data=parseColor(str),color;
tb=[data[0][0],data[0][1]];
//处理可变参数
if(arguments.length>=1){
for (let i = 1; i < arguments.length; i++) {
switch (typeof (arguments[i])) {
case "boolean":
click=arguments[i]?true:click;
break;
case "number":
if(arguments[i]<1){
waiting=Math.abs(arguments[i]);
}else if (arguments[i]>0&&arguments[i]<=1) {
sim=arguments[i];
}else {
delay=arguments[i];
}
break;
case "object":
//传入点击的xy后,click强制为true
tb=[arguments[i][0],arguments[i][1]];
click=true;
break;
case "string":
if(arguments[i]==='debug'){
debug=true
}else {
//输出到日志文件
say=arguments[i];
}
break;
default:
//参数错误
break
}
}
}
if(debug){
let bitmap = JcScreen();
for(let i in data){
color=image.pixel(bitmap,data[i][0],data[i][1]);
if(colorSim(color,data[i][2],sim,data[i][3])){
logi(''+i+'个找到了,填入颜色为:'+getHexFromInt(data[i][2])+'|实际颜色为:'+getHexFromInt(color))
}else {
logw(''+i+'个未找到,填入颜色为:'+getHexFromInt(data[i][2])+'|实际颜色为:'+getHexFromInt(color))
}
}
image.recycle(bitmap);
return false
}
let times=time()+waiting/1000;
do {
let result = image.cmpColorEx(str,sim,0,0,0,0);
if(result){
if(click){
clickPoint(tb[0],tb[1])
}
if(say){
//输出到日志文件
logi(say)
}
if(delay>0){
sleep(delay)
}
return true
}else if(waiting>0){
//继续等待
sleep(350);
}
}while (times>time());
return false
}
/**
* @description 多点或者多点数组比色,找到所有符合标准的点,依次查找,如果找到就返回当前points的索引值,如果返回-1,说明都没有找到
* 运行环境: 无限制
* <Br/>
* 可变参数
* @param str 多组多点比色
*/
function cmpColorExArray(str){
let t=new Date().getTime();
if(typeof (str)!=='object'){
return -1
}
let sim=0.85,click=false,tb,delay=0,waiting=0,say='';
let find = -1;
if(!str){
return find;
}
//处理可变参数
if(arguments.length>=1){
for (let i = 1; i < arguments.length; i++) {
switch (typeof (arguments[i])) {
case "boolean":
click=arguments[i];
break;
case "number":
if(arguments[i]>1){
delay=arguments[i];
}else if (arguments[i]>0&&arguments[i]<=1) {
sim=arguments[i];
}else {
waiting=Math.abs(arguments[i]);
}
break;
case "object":
//传入点击的xy后,click强制为true
tb=[arguments[i][0],arguments[i][1]];
click=true;
break;
case "string":
//输出到日志文件
say=arguments[i];
break;
default:
//参数错误
break
}
}
}
do {
let times=time();
let bitmap = JcScreen();
let result = image.cmpMultiColor(bitmap,str,sim,0,0,0,0);
image.recycle(bitmap);
if(result>=0){
if(click){
if(!tb){
let temp=parseColor(str[result]);
tb=[temp[0][0],temp[0][1]];
}
clickPoint(tb[0],tb[1])
}
if(say){
//输出到日志文件
logi(say)
}
if(delay>0){
sleep(delay)
}
return result;
}else if(waiting>0){
//继续等待
sleep(350);
waiting-=time()-times;
}
}while (waiting>0);
return -1
}
/**
* @return {null|AutoImage}
*/
function JcScreen() {
for (let i = 0; i < 3; i++) {
let pic=image.captureFullScreenEx();
if(pic){
return pic
}
logi('截图失败尝试重启服务');
let temp=CheckEnv();
if(!temp){
break;
}
}
return null;
}
/**
* @param a 找到的点
* @param b 需要匹配的点
* @param sim 精度
* @param offset 偏差
* @description color对比
* */
function colorSim(a,b,sim,offset) {
let de=[0,0,0];
offset=offset||'';
if(offset!==''){
de=getRbgFromHex(offset)
}
a=getRgbFromInt(a);
b=getRgbFromInt(b);
//logd([a,b,de]);
for (let i = 0; i <=2 ; i++) {
if(colorCompare(a[i],b[i],de[i],sim)===false){
return false
}else {
//logd(i+'符合');
}
}
return true
}
function colorCompare(a,b,c,sim) {
let max=b+c+(255-sim*255);
max=max>255?255:max;
let min=b-c-(255-sim*255);
min=min<0?0:min;
return a>=min&&a<=max;
}
/***************************节点系列************************/
/**
* @description 津彩插件点击
* <Br/>other int大于0正整数:超时时间毫秒
* <Br/>int负整数:点击后延时
* <Br/>string:点击后执行logi(),string:id,desc,则搜索的是id,desc;fix是text和desc同时搜索,加上Match则用上正则
* <Br/>传入数组:则点击数组的坐标
* <Br/>所有参数不区分顺序
* <Br/>如传入布尔值true,则搜节点期间不会锁定节点
* @return boolean|布尔型
* @param str 默认是text搜索
*/
JcClick = function (str) {
let set = {
'waitTime': 0,
'delay': 0,
'say': '',
'type': 'text',
'tap': false,
'fixMatch':false,
'fix':false
};
let selectors ;
if(arguments.length>=1){
for (let v=1;v<arguments.length;v++) {
switch (typeof (arguments[v])) {
case "boolean":
set['fixMatch']=arguments[v];
break;
case "object":
try {
if (typeof (arguments[v][0]) == 'number' && typeof (arguments[v][1]) == 'number') {
set['tap'] = [arguments[v][0], arguments[v][1]];
}
} catch (e) {
logd(e);
}
break;
case "number":
if (arguments[v] < 0) {
set['delay'] = Math.abs(parseInt(arguments[v]));
} else {
set['waitTime'] = arguments[v];
}
break;
case "string":
switch (arguments[v]) {
case 'id':
set['type'] = 'id';
break;
case 'idMatch':
set['type'] = 'idMatch';
break;
case 'textMatch':
set['type'] = 'textMatch';
break;
case 'desc':
set['type'] = 'desc';
break;
case 'descMatch':
set['type'] = 'descMatch';
break;
case 'fix':
set.fix=true;
break;
case 'fixMatch':
set.fixMatch=true;
break;
default:
set['say'] = arguments[v];
break;
}
break;
default:
loge('JcClick包含错误参数');
break;
}
}
}
let node;
if(set.fixMatch||set.fix){
let over=time()+set.waitTime/1000;
do {
lockNode();
if(set.fixMatch){
node=textMatch(str).getOneNodeInfo(0);
if(!node){
node=descMatch(str).getOneNodeInfo(0);
}
}else {
node=text(str).getOneNodeInfo(0);
if(!node){
node=desc(str).getOneNodeInfo(0);
}
}
releaseNode();
if(node){
break;
}
if(set.waitTime>0){
sleep(200)
}
}while (over>time());
}else {
switch (set.type) {
case "id":
selectors =id(str);
break;
case "desc":
selectors = desc(str);
break;
case "idMatch":
selectors =idMatch(str);
break;
case "textMatch":
selectors =textMatch(str);
break;
case "descMatch":
selectors =descMatch(str);
break;
default:
selectors = text(str);
break;
}
node =selectors.getOneNodeInfo(set.waitTime);
}
if(node){
if(set['say']){
logi(set['say'])
}
if (set['tap']) {
clickPoint(set['tap'][0],set['tap'][1]);
if(set['delay']){
sleep(set['delay'])
}
}else {
JcRandClick(node,set.delay);
}
return true
}
return false
};
/**
* @description 津彩节点搜索插件text和desc同时搜索
* <Br/>other int:超时时间毫秒
* <Br/>string:非空字符串,或者非fix则使用正则
* <Br/>boolean:false当前未锁定 ,将自动锁点;true表示已经锁了的节点,fix则搜节点期间不会再次锁定节点和解锁节点
* <Br/>从第2个参数开始,不区分顺序
* @param str string 待搜索文字,默认是fix搜索
*@return {NodeInfo} 对象或者null
*/
function JcNode(str) {
let delay=0;
let type='fix';
let lock=false;
if(arguments.length>=1){
for (let v=1;v<arguments.length;v++) {
switch (typeof (arguments[v])) {
case "boolean":
lock=arguments[v]/1000;
break;
case "number":
delay=arguments[v];
break;
case "string":
type=arguments[v]==='fix'?'fix':'fixMatch';
break;
default:
loge('JcNode包含错误参数');
break;
}
}
}
let node;
let timeOver=time()+delay/1000;
do {
if(!lock){
lockNode();
}
if(type==='fixMatch'){
node=textMatch(str).getOneNodeInfo(0);
}else {
node=text(str).getOneNodeInfo(0);
}
if(!node){
if(type==='fixMatch'){
node=descMatch(str).getOneNodeInfo(0);
}else {
node=desc(str).getOneNodeInfo(0);
}
}
if(!lock){
releaseNode();
}
if(node){
break;
}
if(delay>0){
sleep(500);
}
}while (timeOver>time());
return node;
}
/**
* @description 等待节点消失
* @param str 节点标识
* @param waitTime 超时时长(单位:秒)
* @param type id,desc,text等
* @return {boolean}
*/
function waitNodeDisappear(str,waitTime,type) {
//等节点消失
waitTime=waitTime||0;
type=type||'text';
let selectors,temp,fix=0;
switch (type) {
case "id":
selectors =id(str);
break;
case "desc":
selectors = desc(str);
break;
case "idMatch":
selectors =idMatch(str);
break;
case "textMatch":
selectors =textMatch(str);
break;
case "descMatch":
selectors =descMatch(str);
break;
case "fix":
fix=1;
break;
case "fixMatch":
fix=2;
break;
default:
selectors = text(str);
break;
}
let overTime=time()+waitTime;
do {
if(fix>0){
temp=JcNode('str',fix===1?'fix':'fixMatch');
}else {
temp=has(selectors);
}
if(temp){
sleep(500);
}else {
return true
}
}while (time()<overTime);
return false
}
function reLockNode() {
releaseNode();sleep(200);lockNode();
}
function getCenter(data) {
let ret=[];
//data=JSON.parse(data);
if(data.top){
ret[0]=parseInt((data.right+data.left)/2);
ret[1]=parseInt((data.bottom+data.top)/2);
}
return ret
}
/**
* @description 拟人节点点击
* @param data 节点或节点的范围
* @param delay 第1次点击后延时[可缺省]
* @param num 第2次点击后延时[可缺省]
* @return {boolean}
*/
function JcRandClick(data,delay,num) {
if(!data){
return false;
}
num=num||0;
if(typeof (data)==='object'){
if(data.bounds){
data=data.bounds;
}
}
delay=delay||0;
//data=JSON.parse(data);
let x=JcRnd((data.right-data.left)*0.4+data.left,(data.right-data.left)*0.6+data.left);
let y=JcRnd((data.bottom-data.top)*0.4+data.top,(data.bottom-data.top)*0.6+data.top);
let times=num>0?2:1;
let temp=false;
for (let i = 0; i < times; i++) {
temp=clickPoint(x,y);
if(!temp){
temp=AdbClick([x,y],delay);
}
if(delay&&i===0){
sleep(delay);
}else if (i===1&&num>0) {
sleep(num)
}
}
return temp;
}
/***************************数据库系列************************/
/**
* @return {boolean}
*/
function SQLCreate(Db,tableName,sql,close) {
close =close||false;
if(close===false){
sqlite.connectOrCreateDb(Db);
}
let createTable=false;
try {
createTable=sqlite.execSql("CREATE TABLE "+ tableName+"("+sql+');');
}catch (e) {
logd(false)
}
if(close===false){
sqlite.close();
}
return createTable
}
/**
* @return {boolean}
*/
function SQLAddField(Db,tableName,sql,close) {
close =close||false;
if(close===false){
sqlite.connectOrCreateDb(Db);
}
let result=false;
try {
result = sqlite.execSql("ALTER TABLE "+ tableName+' ADD '+sql);sleep(30);
}catch (e) {
logd(false)
}
if(close===false){
sqlite.close();
}
sleep(20);
return result
}
/**
* @return {null,object};
*/
function SQLSelect(Db, tableName, column, where, close) {
close =close||false;
column = column||'*';
if(close===false){
try {
sqlite.connectOrCreateDb(Db);
}catch (e) {
logw('查询数据库时连接出错');
sqlite.close();
return null
}
}
let sql="SELECT "+column+" FROM "+tableName;
if(where){
sql=sql+' WHERE '+where;
}
let result=null;
try {
result = sqlite.query(sql);sleep(30);
}catch (e) {
logd('查询数据库时读取数据错误');
return null
}
if(close===false){
sqlite.close();
}
sleep(30);
if(result){
if(typeof(result)==='object'){
if(result.length===0){
return null
}
}
}
return result
}
/**
* @return {boolean}
*/
function SQLInsert(Db,tableName,data,close) {
close =close||false;
if(close===false){
sqlite.connectOrCreateDb(Db);
}
let insert=false;
try {
insert = sqlite.insert(tableName,data);sleep(35);
}catch (e) {
logd(false)
}
if(close===false){
sqlite.close();
}
sleep(15);
return insert
}
/**
* @return {boolean}
*/
function SQLUpdate(Db,tableName,map,where,close) {
close =close||false;
where=where||'';
if(close===false){
let create=false;
try{
create = sqlite.connectOrCreateDb(Db);
}catch (e) {
logw('SQLUpdate时连接数据库失败')
}
if(!create){
sqlite.close();sleep(50);
return false;
}
}
let update = sqlite.update(tableName,map,where);
if(close===false){
sqlite.close();
}
sleep(50);
return update;
}
/**
* @return {boolean}
*/
function SQLDelete(Db,tableName,where,close) {
close =close||false;
where=where||'';
if(close===false){
sqlite.connectOrCreateDb(Db);
}
let result =false;
let sql="DELETE FROM "+tableName;
if(where){
sql=sql+' WHERE '+where;
}
try {
result = sqlite.delete(sql);sleep(40);
}catch (e) {
logd(false)
}
if(close===false){
sqlite.close();
}
sleep(50);
return result
}
/***************************系统工具***************************/
function CheckEnv() {
let temp=isServiceOk();
if(!temp){
let result = startEnv();
logi('重启为'+result);
sleep(500);
if(result){
temp=isServiceOk();
}
}
return temp;
}
function LogChang() {
shell.execCommand("cp /sdcard/logger/logs_0.csv /sdcard/logger/nb/."+time()+"csv");
file.deleteAllFile('/sdcard/logger/logs_0.csv')
}
function RefreshPicture(pic) {
shell.execCommand("am broadcast -a android.intent.action.MEDIA_SCANNER_SCAN_FILE -d file://"+pic);
shell.execCommand("am broadcast -a android.intent.action.MEDIA_MOUNTED -d file://"+pic);
}
/**
* @return {number}
*/
function JcRnd(min,max){
return Math.floor(Math.random() * (max - min + 1) + min);
}
function getAndroidVerFloat() {
let temp=device.getOSVersion();
temp=temp.split('.');
return parseFloat(temp[0]+'.'+temp[1]+temp[2]);
}
/**
* @return {boolean}
*/
function HasNavigationBar() {
let temp = shell.execCommand("dumpsys window windows");
if(!temp){
return true;
}
let ret=temp.indexOf('name=NavigationBar');
if(ret>-1){
//此处点击隐藏虚拟按钮处
AdbClick(GXY.closeNavigationBar);
}
return ret > -1;
}
function AdbClick(tb,delay) {
delay=delay||0;
let x=tb[0]+utils.getRangeInt(-10,11);
let y=tb[1]+utils.getRangeInt(-10,11);
shell.execCommand("input tap "+x+' '+y);
if(delay>0){
sleep(delay)
}
}
function JcLongClick(tx,ty,times){
agentEvent.touchDown(tx,ty);
sleep(times);
agentEvent.touchUp(tx,ty);
}
/***************************应用系列***************************/
function JcPkg() {
let temp=shell.execAgentCommand('dumpsys activity | grep "Focus"');
if(typeof temp==='string'){
let res=temp.match(/\s([^/\s]+)\//);
if(res){
if(typeof res==='object'){
return res[res.length-1];
}
}
}
return null
}
/***************************时间日期***************************/
function today(num) {
let date;
if(num){
date =new Date(num)
}else {
date =new Date();
}
let mon=date.getMonth()+1;
let day=date.getDate();
let M=doHandleMonth(mon);
let D=doHandleMonth(day);
return parseInt(date.getFullYear()+''+M+''+D)
}
function toDay(type) {
type=type||'-';
let now = new Date();
let nowYear = now.getFullYear();
let nowMonth = now.getMonth();
let nowDate = now.getDate();
nowMonth = doHandleMonth(nowMonth + 1);
nowDate = doHandleMonth(nowDate);
return nowYear+type+nowMonth+type+nowDate
}
function doHandleMonth(month){
if(month.toString().length===1){
month = "0" + month;
}
return month;
}
/**
* @description 获取今天是今年的第几周
* */
function getWeek(){
let date=new Date();
let date2=new Date(date.getFullYear(), 0, 1);
let day1=date.getDay();
if(day1===0) day1=7;
let day2=date2.getDay();
if(day2===0) day2=7;
let d = Math.round((date.getTime() - date2.getTime()+(day2-day1)*(24*60*60*1000)) / 86400000);
return Math.ceil(d /7)+1;
}
function time(){return Math.floor((new Date).getTime()/1e3)}
/**
* @description 获取时分组成的数值,如2100是21点,830是8点30分
* @return {number}
*/
function timeInt() {
let temp=new Date();
let ret=temp.getMinutes();
if(ret<10){
ret=temp.getHours()+'0'+ret;
}else {
ret=temp.getHours()+''+ret;
}
return parseInt(ret)
}
/***************************其它系列***************************/
function dump(arr) {
for (let key in arr) {
if (typeof (arr[key]) == 'array' || typeof (arr[key]) === 'object') {//递归调用
logd(key + '[');
dump(arr[key]);
logd(']')
} else {
logd(key + ' = ' + arr[key]);
}
}
}
function printJson(data){
logd(JSON.stringify(data));
}
function isJsonString(str) {
if(typeof (str)!=='string'){
return false
}
if (/\{/.test(str)) {
try {
JSON.parse(str);
return true
} catch (err) {
return false
}
}
return false
}
/**
* @return {boolean}
*/
function JcClickArr(Arr) {
try{
return clickPoint(Arr[0],Arr[1])
}catch (e) {
return false
}
}
/**
* @return {boolean}
* @description 检测是否已经上锁了,自动执行上锁,返回解锁前的状态
*/
function UnLock() {
let ret=false;
let result = shell.execAgentCommand("dumpsys window policy|grep mShowingLockscreen");
if(result){
if(result.indexOf('mShowingLockscreen=true')>-1){
logi('需要解锁屏幕');
ret=true;
shell.execAgentCommand("input keyevent 26");
sleep(1200);
if(phoneInfo.height===1280){
swipeToPoint(500,700,500,50,400);
}else {
swipeToPoint(500,1000,500,80,400);
}
}else {
logi('不需要解锁')
}
}
return ret;
}
function DoubleClick(num) {
num=num||12;
let w=device.getScreenWidth()/2,h=device.getScreenHeight()/2;
let x=[
JcRnd(w-num,w+num),
JcRnd(h-num,h+num),
JcRnd(w-num,w+num),
JcRnd(h-num,h+num),
];
clickPoint(x[0],x[1]);
sleep(180);
clickPoint(x[0],x[1]);
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
JavaScript
1
https://gitee.com/juding-xdm/JcFunction.git
git@gitee.com:juding-xdm/JcFunction.git
juding-xdm
JcFunction
EasyClick津彩函数
master

搜索帮助