go-dongle 轻量级 Golang 编码解码、加密解密库开源项目

我要开发同款
匿名用户2021年08月11日
34阅读
开发技术GO语言
所属分类Google Go、加密/解密软件包、程序开发
授权协议MIT

作品详情

go-dongle是一个轻量级、语义化、对开发者友好的golang编码解码、加密解密库。

如果您觉得不错,请给个star吧

github.com/golang-module/dongle

gitee.com/golang-module/dongle

安装使用

//使用github库goget-ugithub.com/golang-module/dongleimport("github.com/golang-module/dongle")//使用gitee库goget-ugitee.com/golang-module/dongleimport("gitee.com/golang-module/dongle")

用法示例

Hex编码、解码

//对字符串进行hex编码,输出字符串dongle.Encode.FromString("helloworld").ByHex().ToString()//68656c6c6f20776f726c64//对字符串进行hex解码,输出字符串dongle.Decode.FromString("68656c6c6f20776f726c64").ByHex().ToString()//helloworld//对字节切片进行hex编码,输出字符串dongle.Encode.FromBytes([]byte("helloworld")).ByHex().ToString()//68656c6c6f20776f726c64//对字节切片进行hex解码,输出字符串dongle.Decode.FromBytes([]byte("68656c6c6f20776f726c64")).ByHex().ToString()//helloworld//对字符串进行hex编码,输出字节切片dongle.Encode.FromString("helloworld").ByHex().ToBytes()//[]byte("68656c6c6f20776f726c64")//对字符串进行hex解码,输出字节切片dongle.Decode.FromString("68656c6c6f20776f726c64").ByHex().ToBytes()//[]byte("helloworld")//对字节切片进行hex编码,输出字节切片dongle.Encode.FromBytes([]byte("helloworld")).ByHex().ToBytes()//[]byte("68656c6c6f20776f726c64")//对字节切片进行hex解码,输出字节切片dongle.Decode.FromBytes([]byte("68656c6c6f20776f726c64")).ByHex().ToBytes()//[]byte("helloworld")

Base32编码、解码

//对字符进行base32编码,输出字符串dongle.Encode.FromString("helloworld").ByBase32().ToString()//NBSWY3DPEB3W64TMMQ======//对字符串进行base32解码,输出字符串dongle.Decode.FromString("NBSWY3DPEB3W64TMMQ======").ByBase32().ToString()//helloworld//对字节切片进行base32编码,输出字符串dongle.Encode.FromBytes([]byte("helloworld")).ByBase32().ToString()//NBSWY3DPEB3W64TMMQ======//对字节切片进行base32解码,输出字符串dongle.Decode.FromBytes([]byte("NBSWY3DPEB3W64TMMQ======")).ByBase32().ToString()//helloworld//对字符串进行base32编码,输出字节切片dongle.Encode.FromString("helloworld").ByBase32().ToBytes()//[]byte("NBSWY3DPEB3W64TMMQ======")//对字符串进行base32解码,输出字节切片dongle.Decode.FromString("NBSWY3DPEB3W64TMMQ======").ByBase32().ToBytes()//[]byte("helloworld")//对字节切片进行base32编码,输出字节切片dongle.Encode.FromBytes([]byte("helloworld")).ByBase32().ToBytes()//[]byte("NBSWY3DPEB3W64TMMQ======")//对字节切片进行base32解码,输出字节切片dongle.Decode.FromBytes([]byte("NBSWY3DPEB3W64TMMQ======")).ByBase32().ToBytes()//[]byte("helloworld")

Base64编码、解码

//对字符串进行base64编码,输出字符串dongle.Encode.FromString("helloworld").ByBase64().ToString()//aGVsbG8gd29ybGQ=//对字符串进行base64解码,输出字符串dongle.Decode.FromString("aGVsbG8gd29ybGQ=").ByBase64().ToString()//helloworld//对字节切片进行base64编码,输出字符串dongle.Encode.FromBytes([]byte("helloworld")).ByBase64().ToString()//aGVsbG8gd29ybGQ=//对字节切片进行base64解码,输出字符串dongle.Decode.FromBytes([]byte("aGVsbG8gd29ybGQ=")).ByBase64().ToString()//helloworld//对字符串进行base64编码,输出字节切片dongle.Encode.FromBytes([]byte("helloworld")).ByBase64().ToString()//aGVsbG8gd29ybGQ=//对字符串进行base64解码,输出字节切片dongle.Decode.FromString("aGVsbG8gd29ybGQ=").ByBase64().ToBytes()//[]byte("helloworld")//对字节切片进行base64编码,输出字节切片dongle.Encode.FromString("helloworld").ByBase64().ToBytes()//[]byte("aGVsbG8gd29ybGQ=")//对字节切片进行base64解码,输出字节切片dongle.Decode.FromBytes([]byte("aGVsbG8gd29ybGQ=")).ByBase64().ToBytes()//[]byte("helloworld")

Base64URL编码、解码

//对url字符进行base64编码,输出字符串dongle.Encode.FromString("www.gouguoyin.cn").ByBase64URL().ToString()//d3d3LmdvdWd1b3lpbi5jbg==//对url字符进行base64解码,输出字符串dongle.Decode.FromString("d3d3LmdvdWd1b3lpbi5jbg==").ByBase64URL().ToString()//www.gouguoyin.cn//对url字节切片进行base64编码,输出字符串dongle.Encode.FromBytes([]byte("www.gouguoyin.cn")).ByBase64URL().ToString()//d3d3LmdvdWd1b3lpbi5jbg==//对url字节切片进行base64解码,输出字符串dongle.Decode.FromBytes([]byte("d3d3LmdvdWd1b3lpbi5jbg==")).ByBase64URL().ToString()//www.gouguoyin.cn//对url字符进行base64编码,输出字节切片dongle.Encode.FromString("www.gouguoyin.cn").ByBase64URL().ToBytes()//[]byte("d3d3LmdvdWd1b3lpbi5jbg==")//对url字符进行base64解码,输出字节切片dongle.Decode.FromString("d3d3LmdvdWd1b3lpbi5jbg==").ByBase64URL().ToBytes()//[]byte("www.gouguoyin.cn")//对url字节切片进行base64编码,输出字节切片dongle.Encode.FromBytes([]byte("www.gouguoyin.cn")).ByBase64URL().ToBytes()//[]byte("d3d3LmdvdWd1b3lpbi5jbg==")//对url字符进行base64解码,输出字节切片dongle.Decode.FromBytes([]byte("d3d3LmdvdWd1b3lpbi5jbg==")).ByBase64URL().ToBytes()//[]byte("www.gouguoyin.cn")

SafeURL编码、解码

//对url字符进行转义编码,输出字符串dongle.Encode.FromString("www.gouguoyin.cn?sex=男&age=18").BySafeURL().ToString()//www.gouguoyin.cn%3Fsex%3D%E7%94%B7%26age%3D18//对url字符进行转义解码,输出字符串dongle.Decode.FromString("www.gouguoyin.cn%3Fsex%3D%E7%94%B7%26age%3D18").BySafeURL().ToString()//www.gouguoyin.cn?sex=男&age=18//对url字节切片进行转义编码,输出字符串dongle.Encode.FromBytes([]byte("www.gouguoyin.cn?sex=男&age=18")).BySafeURL().ToString()//www.gouguoyin.cn%3Fsex%3D%E7%94%B7%26age%3D18//对url字节切片进行转义解码,输出字符串dongle.Decode.FromBytes([]byte("www.gouguoyin.cn%3Fsex%3D%E7%94%B7%26age%3D18")).BySafeURL().ToString()//www.gouguoyin.cn?sex=男&age=18//对url字符进行转义编码,输出字节切片dongle.Encode.FromString("www.gouguoyin.cn?sex=男&age=18").BySafeURL().ToBytes()//[]byte("www.gouguoyin.cn%3Fsex%3D%E7%94%B7%26age%3D18")//对url字符进行转义解码,输出字节切片dongle.Decode.FromString("www.gouguoyin.cn%3Fsex%3D%E7%94%B7%26age%3D18").BySafeURL().ToBytes()//[]byte("www.gouguoyin.cn?sex=男&age=18")//对url字节切片进行转义编码,输出字节切片dongle.Encode.FromBytes([]byte("www.gouguoyin.cn?sex=男&age=18")).BySafeURL().ToBytes()//[]byte("www.gouguoyin.cn%3Fsex%3D%E7%94%B7%26age%3D18")//对url字符进行转义解码,输出字节切片dongle.Decode.FromBytes([]byte("www.gouguoyin.cn%3Fsex%3D%E7%94%B7%26age%3D18")).BySafeURL().ToBytes()//[]byte("www.gouguoyin.cn?sex=男&age=18")

Md4加密

//对字符串进行md4加密,输出经过hex编码的字符串dongle.Encrypt.FromString("helloworld").ByMd4().ToHexString()//aa010fbc1d14c795d86ef98c95479d17//对字符串进行md4加密,输出经过base32编码的字符串dongle.Encrypt.FromString("helloworld").ByMd4().ToBase32String()//VIAQ7PA5CTDZLWDO7GGJKR45C4======//对字符串进行md4加密,输出经过base64编码的字符串dongle.Encrypt.FromString("helloworld").ByMd4().ToBase64String()//qgEPvB0Ux5XYbvmMlUedFw==//对字节切片进行md4加密,输出经过hex编码的字节切片dongle.Encrypt.FromBytes([]byte("helloworld")).ByMd4().ToHexBytes()//[]byte("aa010fbc1d14c795d86ef98c95479d17")//对字节切片进行md4加密,输出经过base32编码的字节切片dongle.Encrypt.FromBytes([]byte("helloworld")).ByMd4().ToBase32Bytes()//[]byte("VIAQ7PA5CTDZLWDO7GGJKR45C4======")//对字节切片进行md4加密,输出经过base64编码的字节切片dongle.Encrypt.FromBytes([]byte("helloworld")).ByMd4().ToBase64Bytes()//[]byte("qgEPvB0Ux5XYbvmMlUedFw==")//对文件进行md4加密,输出经过hex编码的字符串dongle.Encrypt.FromFile("./LICENSE").ByMd4().ToHexString()//1240c5c0fb26b585999357915c56b511//对文件进行md4加密,输出经过base32编码的字符串dongle.Encrypt.FromFile("./LICENSE").ByMd4().ToBase32String()//CJAMLQH3E22YLGMTK6IVYVVVCE======//对文件进行md4加密,输出经过base64编码的字符串dongle.Encrypt.FromFile("./LICENSE").ByMd4().ToBase64String()//EkDFwPsmtYWZk1eRXFa1EQ==//对文件进行md4加密,输出经过hex编码的字节切片dongle.Encrypt.FromFile([]byte("./LICENSE")).ByMd4().ToHexBytes()//[]byte("1240c5c0fb26b585999357915c56b511")//对文件进行md4加密,输出经过base32编码的字节切片dongle.Encrypt.FromFile([]byte("./LICENSE")).ByMd4().ToBase32Bytes()//[]byte("CJAMLQH3E22YLGMTK6IVYVVVCE======")//对文件进行md4加密,输出经过base64编码的字节切片dongle.Encrypt.FromFile([]byte("./LICENSE")).ByMd4().ToBase64Bytes()//[]byte("EkDFwPsmtYWZk1eRXFa1EQ==")

Hmac-md4加密

//对字符串进行hmac-md4加密,输出经过hex编码的字符串dongle.Encrypt.FromString("helloworld").ByHmacMd4("dongle").ToHexString()//7a9df5247cbf76a8bc17c9c4f5a75b6b//对字符串进行hmac-md4加密,输出经过base32编码的字符串dongle.Encrypt.FromString("helloworld").ByHmacMd4("dongle").ToBase32String()//PKO7KJD4X53KRPAXZHCPLJ23NM======//对字符串进行hmac-md4加密,输出经过base64编码的字符串dongle.Encrypt.FromString("helloworld").ByHmacMd4("dongle").ToBase64String()//ep31JHy/dqi8F8nE9adbaw==//对字节切片进行hmac-md4加密,输出经过hex编码的字节切片dongle.Encrypt.FromBytes([]byte("helloworld")).ByHmacMd4([]byte("dongle")).ToHexBytes()//[]byte("7a9df5247cbf76a8bc17c9c4f5a75b6b")//对字节切片进行hmac-md4加密,输出经过base32编码的字节切片dongle.Encrypt.FromBytes([]byte("helloworld")).ByHmacMd4([]byte("dongle")).ToBase32Bytes()//[]byte("PKO7KJD4X53KRPAXZHCPLJ23NM======")//对字节切片进行hmac-md4加密,输出经过base64编码的字节切片dongle.Encrypt.FromBytes([]byte("helloworld")).ByHmacMd4([]byte("dongle")).ToBase64Bytes()//[]byte("ep31JHy/dqi8F8nE9adbaw==")

Md5加密

//对字符串进行md5加密,输出经过hex编码的字符串dongle.Encrypt.FromString("helloworld").ByMd5().ToHexString()//5eb63bbbe01eeed093cb22bb8f5acdc3//对字符串进行md5加密,输出经过base32编码的字符串dongle.Encrypt.FromString("helloworld").ByMd5().ToBase32String()//L23DXO7AD3XNBE6LEK5Y6WWNYM======//对字符串进行md5加密,输出经过base64编码的字符串dongle.Encrypt.FromString("helloworld").ByMd5().ToBase64String()//XrY7u+Ae7tCTyyK7j1rNww==//对字节切片进行md5加密,输出经过hex编码的字节切片dongle.Encrypt.FromBytes([]byte("helloworld")).ByMd5().ToHexBytes()//[]byte("5eb63bbbe01eeed093cb22bb8f5acdc3")//对字节切片进行md5加密,输出经过base32编码的字节切片dongle.Encrypt.FromBytes([]byte("helloworld")).ByMd5().ToBase32Bytes()//[]byte("L23DXO7AD3XNBE6LEK5Y6WWNYM======")//对字节切片进行md5加密,输出经过base64编码的字节切片dongle.Encrypt.FromBytes([]byte("helloworld")).ByMd5().ToBase64Bytes()//[]byte("XrY7u+Ae7tCTyyK7j1rNww==")//对文件进行md5加密,输出经过hex编码的字符串dongle.Encrypt.FromFile("./LICENSE").ByMd5().ToHexString()//014f03f9025ea81a8a0e9734be540c53//对文件进行md5加密,输出经过base32编码的字符串dongle.Encrypt.FromFile("./LICENSE").ByMd5().ToBase32String()//AFHQH6ICL2UBVCQOS42L4VAMKM======//对文件进行md5加密,输出经过base64编码的字符串dongle.Encrypt.FromFile("./LICENSE").ByMd5().ToBase64String()//AU8D+QJeqBqKDpc0vlQMUw==//对文件进行md5加密,输出经过hex编码的字节切片dongle.Encrypt.FromFile([]byte("./LICENSE")).ByMd5().ToHexBytes()//[]byte("014f03f9025ea81a8a0e9734be540c53")//对文件进行md5加密,输出经过base32编码的字节切片dongle.Encrypt.FromFile([]byte("./LICENSE")).ByMd5().ToBase32Bytes()//[]byte("AFHQH6ICL2UBVCQOS42L4VAMKM======")//对文件进行md5加密,输出经过base64编码的字节切片dongle.Encrypt.FromFile([]byte("./LICENSE")).ByMd5().ToBase64Bytes()//[]byte("AU8D+QJeqBqKDpc0vlQMUw==")

Hmac-md5加密

//对字符串进行hmac-md5加密,输出经过hex编码的字符串dongle.Encrypt.FromString("helloworld").ByHmacMd5("dongle").ToHexString()//4790626a275f776956386e5a3ea7b726//对字符串进行hmac-md5加密,输出经过base32编码的字符串dongle.Encrypt.FromString("helloworld").ByHmacMd5("dongle").ToBase32String()//I6IGE2RHL53WSVRYNZND5J5XEY======//对字符串进行hmac-md5加密,输出经过base64编码的字符串dongle.Encrypt.FromString("helloworld").ByHmacMd5("dongle").ToBase64String()//R5Biaidfd2lWOG5aPqe3Jg==//对字节切片进行hmac-md5加密,输出经过hex编码的字节切片dongle.Encrypt.FromBytes([]byte("helloworld")).ByHmacMd5([]byte("dongle")).ToHexBytes()//[]byte("4790626a275f776956386e5a3ea7b726")//对字节切片进行hmac-md5加密,输出经过base32编码的字节切片dongle.Encrypt.FromBytes([]byte("helloworld")).ByHmacMd5([]byte("dongle")).ToBase32Bytes()//[]byte("I6IGE2RHL53WSVRYNZND5J5XEY======")//对字节切片进行hmac-md5加密,输出经过base64编码的字节切片dongle.Encrypt.FromBytes([]byte("helloworld")).ByHmacMd5([]byte("dongle")).ToBase64Bytes()//[]byte("R5Biaidfd2lWOG5aPqe3Jg==")

Sha1加密

//对字符串进行sha1加密,输出经过hex编码的字符串dongle.Encrypt.FromString("helloworld").BySha1().ToHexString()//2aae6c35c94fcfb415dbe95f408b9ce91ee846ed//对字符串进行sha1加密,输出经过base32编码的字符串dongle.Encrypt.FromString("helloworld").BySha1().ToBase32String()//FKXGYNOJJ7H3IFO35FPUBC445EPOQRXN//对字符串进行sha1加密,输出经过base64编码的字符串dongle.Encrypt.FromString("helloworld").BySha1().ToBase64String()//Kq5sNclPz7QV2+lfQIuc6R7oRu0=//对字节切片进行sha1加密,输出经过hex编码的字节切片dongle.Encrypt.FromBytes([]byte("helloworld")).BySha1().ToHexBytes()//[]byte("2aae6c35c94fcfb415dbe95f408b9ce91ee846ed")//对字节切片进行sha1加密,输出经过base32编码的字节切片dongle.Encrypt.FromBytes([]byte("helloworld")).BySha1().ToBase32Bytes()//[]byte("FKXGYNOJJ7H3IFO35FPUBC445EPOQRXN")//对字节切片进行sha1加密,输出经过base64编码的字节切片dongle.Encrypt.FromBytes([]byte("helloworld")).BySha1().ToBase64Bytes()//[]byte("Kq5sNclPz7QV2+lfQIuc6R7oRu0=")

Hmac-sha1加密

//对字符串进行hmac-sha1加密,输出经过hex编码的字符串dongle.Encrypt.FromString("helloworld").ByHmacSha1("dongle").ToHexString()//91c103ef93ba7420902b0d1bf0903251c94b4a62//对字符串进行hmac-sha1加密,输出经过base22编码的字符串dongle.Encrypt.FromString("helloworld").ByHmacSha1("dongle").ToBase32String()//SHAQH34TXJ2CBEBLBUN7BEBSKHEUWSTC//对字符串进行hmac-sha1加密,输出经过base64编码的字符串dongle.Encrypt.FromString("helloworld").ByHmacSha1("dongle").ToBase64String()//kcED75O6dCCQKw0b8JAyUclLSmI=//对字节切片进行hmac-sha1加密,输出经过hex编码的字节切片dongle.Encrypt.FromBytes([]byte("helloworld")).ByHmacSha1([]byte("dongle")).ToHexBytes()//[]byte("91c103ef93ba7420902b0d1bf0903251c94b4a62")//对字节切片进行hmac-sha1加密,输出经过base22编码的字节切片dongle.Encrypt.FromBytes([]byte("helloworld")).ByHmacSha1([]byte("dongle")).ToBase32Bytes()//[]byte("SHAQH34TXJ2CBEBLBUN7BEBSKHEUWSTC")//对字节切片进行hmac-sha1加密,输出经过base64编码的字节切片dongle.Encrypt.FromBytes([]byte("helloworld")).ByHmacSha1([]byte("dongle")).ToBase64Bytes()//[]byte("kcED75O6dCCQKw0b8JAyUclLSmI=")

Rc4加密

//对字符串进行rc4加密,输出经过hex编码的字符串dongle.Encrypt.FromString("helloworld").ByRc4("dongle").ToHexString()//eba154b4cb5a9038dbbf9d//对字符串进行rc4加密,输出经过base32编码的字符串dongle.Encrypt.FromString("helloworld").ByRc4("dongle").ToBase32String()//5OQVJNGLLKIDRW57TU======//对字符串进行rc4加密,输出经过base64编码的字符串dongle.Encrypt.FromString("helloworld").ByRc4("dongle").ToBase64String()//66FUtMtakDjbv50=//对字节切片进行rc4加密,输出经过hex编码的字节切片dongle.Encrypt.FromBytes([]byte("helloworld")).ByRc4("dongle").ToHexBytes()//[]byte("eba154b4cb5a9038dbbf9d")//对字节切片进行rc4加密,输出经过base32编码的字节切片dongle.Encrypt.FromBytes([]byte("helloworld")).ByRc4("dongle").ToBase32Bytes()//[]byte("5OQVJNGLLKIDRW57TU======")//对字节切片进行rc4加密,输出经过base64编码的字节切片dongle.Encrypt.FromBytes([]byte("helloworld")).ByRc4("dongle").ToBase64Bytes()//[]byte("66FUtMtakDjbv50=")

Aes加密、解密

cipher:=NewCipher()cipher.SetMode(dongle.CBC)//CBC、ECB、CFB、OFB、CTR、GCMcipher.SetPadding(dongle.PKCS7)//No、Zero、PKCS5、PKCS7cipher.SetKey("1234567887654321")//key长度必须是16、24或32cipher.SetIV("1234567887654321")//iv长度必须是16、24或32//对字符串进行aes加密,输出经过hex编码的字符串dongle.Encrypt.FromString("helloworld").ByAes(cipher).ToHexString()//65d823bdf1c581a1ded1cba42e03ca52//对经过hex编码的字符串进行aes解密,输出字符串dongle.Decrypt.FromHexString("65d823bdf1c581a1ded1cba42e03ca52").ByAes(cipher).ToString()//helloworld//对字符串进行aes加密,输出经过base32编码的字符串dongle.Encrypt.FromString("helloworld").ByAes(cipher).ToBase32String()//MXMCHPPRYWA2DXWRZOSC4A6KKI======//对经过base32编码的字符串进行aes解密,输出字符串dongle.Decrypt.FromBase32String("MXMCHPPRYWA2DXWRZOSC4A6KKI======").ByAes(cipher).ToString()//helloworld//对字符串进行aes加密,输出经过base64编码的字符串dongle.Encrypt.FromString("helloworld").ByAes(cipher).ToBase64String()//ZdgjvfHFgaHe0cukLgPKUg==//对经过base64编码的字符串进行aes解密,输出字符串dongle.Decrypt.FromBase64String("ZdgjvfHFgaHe0cukLgPKUg==").ByAes(cipher).ToString()//helloworld//对字节切片进行aes加密,输出经过hex编码的字节切片dongle.Encrypt.FromBytes([]byte("helloworld")).ByAes(cipher).ToHexBytes()//[]byte("65d823bdf1c581a1ded1cba42e03ca52")//对经过hex编码的字符串进行aes解密,输出字符串dongle.Decrypt.FromHexBytes([]byte("65d823bdf1c581a1ded1cba42e03ca52")).ByAes(cipher).ToBytes()//[]byte("helloworld")//对字节切片进行aes加密,输出经过base32编码的字节切片dongle.Encrypt.FromBytes([]byte("helloworld")).ByAes(cipher).ToBase32Bytes()//[]byte("MXMCHPPRYWA2DXWRZOSC4A6KKI======")//对经过base32编码的字节切片进行aes解密,输出字节切片dongle.Decrypt.FromBase32Bytes([]byte("MXMCHPPRYWA2DXWRZOSC4A6KKI======")).ByAes(cipher).ToBytes()//[]byte("helloworld")//对字节切片进行aes加密,输出经过base64编码的字节切片dongle.Encrypt.FromBytes([]byte("helloworld")).ByAes(cipher).ToBase64Bytes()//[]byte("ZdgjvfHFgaHe0cukLgPKUg==")//对经过base64编码的字节切片进行aes解密,输出字节切片dongle.Decrypt.FromBase64Bytes(()byte("ZdgjvfHFgaHe0cukLgPKUg==")).ByAes(cipher).ToBytes()//[]byte("helloworld")

错误处理

如果有多个错误发生,只返回第一个错误,前一个错误排除后才返回下一个错误

e:=dongle.Encrypy.FromFile("./demo.txt").ByMd5()ife.Error!=nil{//错误处理...log.Fatal(e.Error)}fmt.Println(e.ToString())//输出invalidfile"./demo.txt",pleasemakesurethefileexists

更多用法请查看下方软件文档

查看全文
声明:本文仅代表作者观点,不代表本站立场。如果侵犯到您的合法权益,请联系我们删除侵权资源!如果遇到资源链接失效,请您通过评论或工单的方式通知管理员。未经允许,不得转载,本站所有资源文章禁止商业使用运营!
下载安装【程序员客栈】APP
实时对接需求、及时收发消息、丰富的开放项目需求、随时随地查看项目状态

评论