diff --git a/common/css/expensesTop.css b/common/css/expensesTop.css index d18c219..2fe72b3 100644 --- a/common/css/expensesTop.css +++ b/common/css/expensesTop.css @@ -3,25 +3,32 @@ background-color: #fff; } + .base-info { margin-top: 30rpx; background-color: #fff; } -.span24{ + +.span24 { font-size: 26rpx; } -.mt8{ + +.mt8 { margin-top: 12rpx; } -.mt24{ + +.mt24 { margin-top: 24rpx; } + .ml36 { margin-left: 36rpx; } + .ml24 { margin-left: 24rpx; } + .detail-top-box { box-shadow: 0px 0 6rpx 2rpx rgb(234, 234, 234); background-color: #fff; @@ -35,9 +42,11 @@ margin-top: 28rpx; margin-bottom: 28rpx; } -.between-circle{ + +.between-circle { position: relative; } + .between-circle:before { content: ''; width: 30rpx; @@ -51,6 +60,7 @@ z-index: 1; transform: rotate(180deg); } + .between-circle:after { content: ''; width: 30rpx; @@ -64,6 +74,7 @@ top: -12rpx; } + h3 { font-weight: bold; font-size: 32rpx; @@ -71,6 +82,7 @@ h3 { line-height: 1.6; } + h4 { /* padding-top: 32rpx; */ font-size: 28rpx; @@ -81,6 +93,7 @@ h4 { .text-title { color: #888; } + .detail-top-base text.text-title { max-width: 320rpx; display: inline-block; @@ -88,10 +101,12 @@ h4 { text-overflow: ellipsis; overflow: hidden; } -.detail-top-base > view.span24 { + +.detail-top-base>view.span24 { display: flex; align-items: center; } + .detail-top-base { font-size: 26rpx; padding-top: 48rpx; @@ -116,7 +131,7 @@ h4 { .detail-top-bottom { /* width: 100%; */ font-size: 26rpx; - padding: 24rpx 24rpx 28rpx 24rpx; + padding: 24rpx 24rpx 28rpx 24rpx; } @@ -137,10 +152,12 @@ h4 { font-size: 26rpx; } + .attachment { font-size: 26rpx; padding: 12rpx 0 24rpx 0; } + .detail-title { display: flex; align-items: center; @@ -149,20 +166,23 @@ h4 { color: #888; } -.detail-middle-box .remark{ +.detail-middle-box .remark { color: #686868; font-size: 26rpx; } + .imgBox { margin-left: 32rpx; padding-top: 16rpx; } + .imgBox a { display: flex; align-items: center; position: relative; } + .imgBox a+a { margin-top: 16rpx; } @@ -173,6 +193,7 @@ h4 { margin: 4rpx 8rpx; border-radius: 6rpx; } + .ico-wjxz { position: absolute; right: -4rpx; @@ -198,6 +219,7 @@ h4 { .uni-list-cell:after { height: 0; } + .button-box { padding-top: 36rpx; display: flex; @@ -205,10 +227,12 @@ h4 { justify-content: space-around; padding-bottom: 6rpx; } + .button-box image { width: 100rpx; height: 100rpx; } + .button-box span { font-size: 26rpx; display: flex; @@ -216,75 +240,100 @@ h4 { text-align: center; } - .ico-ndbz:before{ - background-image: url('/static/images/tender/je.png'); - } - .ico-bm:before{ - background-image: url('/static/images/tender/bm.png'); - } - .ico-pj:before{ - background-image: url('/static/images/expense/pj.png'); - } - .ico-rzlx:before{ - background-image: url('/static/images/expense/rzlx.png'); - } - .ico-khyh:before{ - background-image: url('https://eshangtech.com/ShopICO/ahyd-BID/expense/khyh.png'); - } - .ico-dw:before{ - background-image: url('/static/images/expense/dw.png'); - } - .ico-skzh:before{ - background-image: url('/static/images/expense/skzh.png'); - } - .ico-ccsy:before{ - background-image: url('/static/images/expense/ccsy.png'); - } - .ico-ccry:before{ - background-image: url('https://eshangtech.com/ShopICO/ahyd-BID/expense/ccry.png'); - } - .ico-xmgl:before{ - background-image: url('/static/images/expense/xmgl.png'); - } - .ico-fy:before{ - background-image: url('/static/images/expense/fy.png'); - } - .ico-ly:before{ - background-image: url('/static/images/expense/ly.png'); - } - .ico-sjx:before{ - background-image: url('/static/images/expense/sjx.png'); - } - .ico-lbrs:before{ - background-image: url('/static/images/expense/lbrs.png'); - } - .ico-ptrs:before{ - background-image: url('/static/images/expense/ptrs.png'); - } - .ico-jbry:before{ - background-image: url('/static/images/expense/jbry.png'); - } - .ico-je:before{ - background-image: url('https://eshangtech.com/ShopICO/ahyd-BID/contract/htsp_je.png'); - } - .ico-dzfp:before{ - background-image: url('/static/images/expense/dzfp.png'); - } - .ico-user:before{ - background-image: url('/static/images/tender/lxr.png'); - } - .ico-zcyz:before{ - background-image: url('https://eshangtech.com/ShopICO/ahyd-BID/expense/zcyz.png'); - } - .ico-zcmc:before{ - background-image: url('/static/images/expense/zcmc.png'); - } - .ico-ljzj:before{ - background-image: url('/static/images/expense/ljzj.png'); - } - .ico-gzsl:before{ - background-image: url('/static/images/expense/gzsl.png'); - } - .ico-jfmc:before{ - background-image: url('https://eshangtech.com/ShopICO/ahyd-BID/expense/jfmc.png'); - } + +.ico-ndbz:before { + background-image: url('/static/images/tender/je.png'); +} + +.ico-bm:before { + background-image: url('/static/images/tender/bm.png'); +} + +.ico-pj:before { + background-image: url('/static/images/expense/pj.png'); +} + +.ico-rzlx:before { + background-image: url('/static/images/expense/rzlx.png'); +} + +.ico-khyh:before { + background-image: url('https://eshangtech.com/ShopICO/ahyd-BID/expense/khyh.png'); +} + +.ico-dw:before { + background-image: url('/static/images/expense/dw.png'); +} + +.ico-skzh:before { + background-image: url('/static/images/expense/skzh.png'); +} + +.ico-ccsy:before { + background-image: url('/static/images/expense/ccsy.png'); +} + +.ico-ccry:before { + background-image: url('https://eshangtech.com/ShopICO/ahyd-BID/expense/ccry.png'); +} + +.ico-xmgl:before { + background-image: url('/static/images/expense/xmgl.png'); +} + +.ico-fy:before { + background-image: url('/static/images/expense/fy.png'); +} + +.ico-ly:before { + background-image: url('/static/images/expense/ly.png'); +} + +.ico-sjx:before { + background-image: url('/static/images/expense/sjx.png'); +} + +.ico-lbrs:before { + background-image: url('/static/images/expense/lbrs.png'); +} + +.ico-ptrs:before { + background-image: url('/static/images/expense/ptrs.png'); +} + +.ico-jbry:before { + background-image: url('/static/images/expense/jbry.png'); +} + +.ico-je:before { + background-image: url('https://eshangtech.com/ShopICO/ahyd-BID/contract/htsp_je.png'); +} + +.ico-dzfp:before { + background-image: url('/static/images/expense/dzfp.png'); +} + +.ico-user:before { + background-image: url('/static/images/tender/lxr.png'); +} + +.ico-zcyz:before { + background-image: url('https://eshangtech.com/ShopICO/ahyd-BID/expense/zcyz.png'); +} + +.ico-zcmc:before { + /* background-image: url('/static/images/expense/zcmc.png'); */ + background-image: url('https://eshangtech.com/ShopICO/ahyd-BID/expense/zcmc.png'); +} + +.ico-ljzj:before { + background-image: url('/static/images/expense/ljzj.png'); +} + +.ico-gzsl:before { + background-image: url('/static/images/expense/gzsl.png'); +} + +.ico-jfmc:before { + background-image: url('https://eshangtech.com/ShopICO/ahyd-BID/expense/jfmc.png'); +} \ No newline at end of file diff --git a/components/filesComponent/fileUnit.vue b/components/filesComponent/fileUnit.vue index 5787606..17b35d9 100644 --- a/components/filesComponent/fileUnit.vue +++ b/components/filesComponent/fileUnit.vue @@ -1,15 +1,17 @@ diff --git a/pages/askForLeave/components/leaveUnit.vue b/pages/askForLeave/components/leaveUnit.vue index 2093beb..e62d441 100644 --- a/pages/askForLeave/components/leaveUnit.vue +++ b/pages/askForLeave/components/leaveUnit.vue @@ -1,15 +1,18 @@ diff --git a/pages/index/index.vue b/pages/index/index.vue index 6904526..17b096a 100644 --- a/pages/index/index.vue +++ b/pages/index/index.vue @@ -4302,6 +4302,7 @@ export default { height: 0 }, isScrollLock: false, // 是否锁定页面滚动 + userInfo: {} }; }, watch: { @@ -4310,6 +4311,7 @@ export default { handler: async function (value) { let userInfo = uni.getStorageSync("vuex"); userInfo = JSON.parse(userInfo); + this.userInfo = userInfo; if (this.isReturn === true) { // 无权限就会跳转到无数据的页面 if ( @@ -4355,14 +4357,16 @@ export default { this.projectWarning = true; } - if ( - userInfo.userData.AuthorityInfo[ - "2cf9a69f-fc06-4a1c-a8cb-3f0e914db6b8" - ] === 1 - ) { - this.showAi = true; - // 移除这里的触发,统合到 getData 结束后触发 - } + // if ( + // userInfo.userData.AuthorityInfo[ + // "2cf9a69f-fc06-4a1c-a8cb-3f0e914db6b8" + // ] === 1 + // ) { + // this.showAi = true; + // // 移除这里的触发,统合到 getData 结束后触发 + // } + + this.handleShowAi() if (!this.isReturn) { @@ -4464,7 +4468,7 @@ export default { uni.setStorageSync("festival", this.isShowFestival); } else { let isSkip = uni.getStorageSync('isSkip') - if (!isSkip) { + if (!isSkip && this.$store.state.userData) { this.$util.toNextRoute( "navigateTo", `/pages/nationalPage/springTravel?selectType=2` @@ -4600,15 +4604,8 @@ export default { ) { this.projectWarning = true; } - if ( - userInfo.userData.AuthorityInfo && - userInfo.userData.AuthorityInfo[ - "2cf9a69f-fc06-4a1c-a8cb-3f0e914db6b8" - ] === 1 - ) { - this.showAi = true; - // 移除这里的触发,统合到 getData 结束后触发 - } + + //拿到option的值 @@ -4617,6 +4614,10 @@ export default { if (this.user.Membership_Id) { await this.getData(option); } + + // 判断是否显示数智能助手 + this.handleShowAi() + // 判断缓存中是否有位置信息 没有的话 向用户请求 拿到用户当前位置 // 拿到当前位置之后去请求离当前位置最近的服务区 作为第一次进入小程序自动选中的服务区 // 在用户选择服务区之后就会有当前服务区 @@ -4687,6 +4688,35 @@ export default { methods: { numeral, ...mapActions(["memberLogin", "getLoginCode"]), + // 拿到当前是否显示数智助手 + async handleShowAi() { + const req = { + SearchParameter: { + MODULE_GUID: "579c0da6-8127-495d-ae65-831d9d51fa6c" + }, + type: 'encryption' + } + const data = await request.$webPost( + "MemberApi/WeChat/GetMODULEList", + req + ); + let res = data.Result_Data.List[0] + console.log('当前是否显示数智能助手', res); + console.log('当前用户', this.userInfo); + if (res.MODULE_STATE === 1) { + if ( + this.userInfo.userData.AuthorityInfo && + this.userInfo.userData.AuthorityInfo[ + "2cf9a69f-fc06-4a1c-a8cb-3f0e914db6b8" + ] === 1 + ) { + this.showAi = true; + // 移除这里的触发,统合到 getData 结束后触发 + } + } else { + this.showAi = false + } + }, // 切换演示版的显示样式 handleChangeSmallTab() { if (this.smallTab === 1) { diff --git a/pages/nationalPage/rankPage.vue b/pages/nationalPage/rankPage.vue index fb7db56..687a123 100644 --- a/pages/nationalPage/rankPage.vue +++ b/pages/nationalPage/rankPage.vue @@ -152,7 +152,7 @@ }} {{ type === 3 ? "/万辆" : "/万元" - }} + }} @@ -426,25 +426,13 @@ {{ type === 1 ? item.RevenueINC.curYearData - ? $util.getMoney( - item.RevenueINC.curYearData / 10000 - ) - : "0.00" - : type === 2 - ? item.AccountINC.curYearData - ? $util.getMoney( - item.AccountINC.curYearData / 10000 - ) - : "0.00" - : type === 3 - ? item.BayonetINC.curYearData - ? $util.getMoney( - item.BayonetINC.curYearData / 10000 - ) - : "0.00" - : "-" - }} - + ? item.RevenueINC.curYearData < 100 && item.RevenueINC.curYearData > 0 ? '<100' : + $util.getMoney(item.RevenueINC.curYearData / 10000) : "0.00" : type === 2 ? + item.AccountINC.curYearData ? item.AccountINC.curYearData < 100 && + item.AccountINC.curYearData > 0 ? '<100' : $util.getMoney(item.AccountINC.curYearData / + 10000) : "0.00" : type === 3 ? item.BayonetINC.curYearData ? item.BayonetINC.curYearData < + 100 && item.BayonetINC.curYearData > 0 ? '<100' : + $util.getMoney(item.BayonetINC.curYearData / 10000) : "0.00" : "-" }} {{ compareYear }} @@ -452,25 +440,13 @@ {{ type === 1 ? item.RevenueINC.lYearData - ? $util.getMoney( - item.RevenueINC.lYearData / 10000 - ) - : "0.00" - : type === 2 - ? item.AccountINC.lYearData - ? $util.getMoney( - item.AccountINC.lYearData / 10000 - ) - : "0.00" - : type === 3 - ? item.BayonetINC.lYearData - ? $util.getMoney( - item.BayonetINC.lYearData / 10000 - ) - : "0.00" - : "-" - }} - + ? item.RevenueINC.lYearData < 100 && item.RevenueINC.lYearData > 0 ? '<100' : + $util.getMoney(item.RevenueINC.lYearData / 10000) : "0.00" : type === 2 ? + item.AccountINC.lYearData ? item.AccountINC.lYearData < 100 && item.AccountINC.lYearData > + 0 ? '<100' : $util.getMoney(item.AccountINC.lYearData / 10000) : "0.00" : type === 3 ? + item.BayonetINC.lYearData ? item.BayonetINC.lYearData < 100 && + item.BayonetINC.lYearData > 0 ? '<100' : $util.getMoney(item.BayonetINC.lYearData / + 10000) : "0.00" : "-" }} 增长 @@ -478,25 +454,13 @@ {{ type === 1 ? item.RevenueINC.increaseData - ? $util.getMoney( - item.RevenueINC.increaseData / 10000 - ) - : "0.00" - : type === 2 - ? item.AccountINC.increaseData - ? $util.getMoney( - item.AccountINC.increaseData / 10000 - ) - : "0.00" - : type === 3 - ? item.BayonetINC.increaseData - ? $util.getMoney( - item.BayonetINC.increaseData / 10000 - ) - : "0.00" - : "-" - }} - + ? item.RevenueINC.increaseData < 100 && item.RevenueINC.increaseData > 0 ? '<100' : + $util.getMoney(item.RevenueINC.increaseData / 10000) : "0.00" : type === 2 ? + item.AccountINC.increaseData ? item.AccountINC.increaseData < 100 && + item.AccountINC.increaseData > 0 ? '<100' : $util.getMoney(item.AccountINC.increaseData / + 10000) : "0.00" : type === 3 ? item.BayonetINC.increaseData ? item.BayonetINC.increaseData + < 100 && item.BayonetINC.increaseData > 0 ? '<100' : + $util.getMoney(item.BayonetINC.increaseData / 10000) : "0.00" : "-" }} diff --git a/pages/nationalPage/springTravel.vue b/pages/nationalPage/springTravel.vue index 9716d34..99fc57b 100644 --- a/pages/nationalPage/springTravel.vue +++ b/pages/nationalPage/springTravel.vue @@ -150,12 +150,13 @@ /> --> + - 回到首页 + 看板首页 - + 春运播报 @@ -3667,6 +3668,7 @@ export default { currentHoliday: 0, // 当前时间是这个节日的第几天 canSelectFestivalList: [], // 可以选择的节日列表 currentDayNumber: 0,// 拿到当前累计到第几天 + showAi: false// 判断是否显示春运播报 }; }, async onLoad(query) { @@ -3805,6 +3807,7 @@ export default { await this.handleGetNewUpdateTime(); await this.handleGetPageData(); this.handleGetAreaData(); + this.handleShowAi() uni.hideLoading(); return; // this.lastDay = '2024-09-30' @@ -4037,6 +4040,33 @@ export default { uni.removeStorageSync("springService"); }, methods: { + async handleShowAi() { + const req = { + SearchParameter: { + MODULE_GUID: "579c0da6-8127-495d-ae65-831d9d51fa6c" + }, + type: 'encryption' + } + const data = await request.$webPost( + "MemberApi/WeChat/GetMODULEList", + req + ); + let res = data.Result_Data.List[0] + console.log('当前是否显示数智能助手', res); + if (res.MODULE_STATE === 1) { + if ( + this.useInfo.userData.AuthorityInfo && + this.useInfo.userData.AuthorityInfo[ + "2cf9a69f-fc06-4a1c-a8cb-3f0e914db6b8" + ] === 1 + ) { + this.showAi = true; + // 移除这里的触发,统合到 getData 结束后触发 + } + } else { + this.showAi = false + } + }, goToHome() { this.$util.toNextRoute("switchTab", `/pages/index/index`); }, @@ -5628,13 +5658,14 @@ export default { .newChangeBox { background: #fff; - padding: 16rpx 16rpx 16rpx 32rpx; - border-radius: 32rpx; + white-space: nowrap; + padding: 12rpx 8rpx 12rpx 16rpx; + border-radius: 12rpx; display: flex; align-items: center; .festivalName { - margin: 0 16rpx; + margin: 0 12rpx; font-size: 28rpx; font-family: PingFangSC, PingFang SC; font-weight: 400; @@ -5663,11 +5694,16 @@ export default { } .backToHomeBox { - padding: 8rpx 16rpx; + height: 64rpx; + box-sizing: border-box; + padding: 12rpx 16rpx; background-color: #fff; border-radius: 12rpx; display: inline-flex; align-items: center; + font-size: 28rpx; + line-height: 28rpx; + white-space: nowrap; .backToHomeIcon { width: 34rpx; @@ -5677,15 +5713,18 @@ export default { } .jumpBtn { - padding: 8rpx 16rpx; + padding: 12rpx 16rpx; + font-size: 28rpx; // background-color: #fff; background-color: #FF7C43; border-radius: 12rpx; display: inline-flex; align-items: center; color: #FFE194; - font-weight: 600; line-height: 28rpx; + font-size: 28rpx; + // font-weight: 600; + white-space: nowrap; .jumpBtnIcon { width: 40rpx; diff --git a/static/images/expense/zcmc.png b/static/images/expense/zcmc.png deleted file mode 100644 index f5fca05..0000000 Binary files a/static/images/expense/zcmc.png and /dev/null differ diff --git a/static/images/fileType/jpgpng.png b/static/images/fileType/jpgpng.png deleted file mode 100644 index 27d4e7a..0000000 Binary files a/static/images/fileType/jpgpng.png and /dev/null differ diff --git a/static/images/leave/qj.png b/static/images/leave/qj.png deleted file mode 100644 index 01d9817..0000000 Binary files a/static/images/leave/qj.png and /dev/null differ diff --git a/util/api.js b/util/api.js index 8e47b73..0c0c957 100644 --- a/util/api.js +++ b/util/api.js @@ -1,4 +1,5 @@ import Store from '../store/store' +import { encryptAES } from './handleAes.js' const publicOptions = (() => { // 获取本机的信息 let systemInfo = uni.getSystemInfoSync() return { @@ -34,9 +35,18 @@ export default { data.memberShipId = !data.memberShipId ? (Store.state.userData.Membership_Id || '') : data.memberShipId // ||'3255' 1170386 1125717 // + + if (data.type === 'encryption') { + } + let requstOptions = { url: url, - data: data, + data: data.type === 'encryption' ? { + name: "", + value: encryptAES(JSON.stringify(data)) + } : data.type === 'encryption1' ? { + postData: encryptAES(JSON.stringify(data)) + } : data, method: method, } let ModuleGuid = '' @@ -79,7 +89,7 @@ export default { //服务器返回数据 if (res && (res.statusCode === 200 || res.statusCode === 304 || res.statusCode === 400)) { if (res.data && ((res.data.ResultCode != '999' && res.data.ResultCode != undefined) || - (res.data.Result_Code != '999' && res.data.Result_Code != undefined))) { + (res.data.Result_Code != '999' && res.data.Result_Code != undefined))) { resolve(res.data); } else if (typeof res.data == 'object') { // 兼容招标投标模块 resolve(res.data); diff --git a/util/crypto-js.js b/util/crypto-js.js new file mode 100644 index 0000000..25b316a --- /dev/null +++ b/util/crypto-js.js @@ -0,0 +1,158 @@ +// 纯 JS 精简版 AES-CBC-Pkcs7 +function toBytes(str) { + const utf8 = []; + for (let i = 0; i < str.length; i++) { + let charcode = str.charCodeAt(i); + if (charcode < 0x80) utf8.push(charcode); + else if (charcode < 0x800) { + utf8.push(0xc0 | (charcode >> 6), 0x80 | (charcode & 0x3f)); + } else if (charcode < 0xd800 || charcode >= 0xe000) { + utf8.push(0xe0 | (charcode >> 12), 0x80 | ((charcode >> 6) & 0x3f), 0x80 | (charcode & 0x3f)); + } else { + i++; + charcode = 0x10000 + (((charcode & 0x3ff) << 10) | (str.charCodeAt(i) & 0x3ff)); + utf8.push(0xf0 | (charcode >> 18), 0x80 | ((charcode >> 12) & 0x3f), 0x80 | ((charcode >> 6) & 0x3f), 0x80 | (charcode & 0x3f)); + } + } + return utf8; +} +function fromBytes(bytes) { + let out = '', i = 0, c = 0; + while (i < bytes.length) { + c = bytes[i++]; + if (c < 128) out += String.fromCharCode(c); + else if (c > 191 && c < 224) out += String.fromCharCode(((c & 31) << 6) | (bytes[i++] & 63)); + else if (c > 223 && c < 240) out += String.fromCharCode(((c & 15) << 12) | ((bytes[i++] & 63) << 6) | (bytes[i++] & 63)); + else { + let u = (((c & 7) << 18) | ((bytes[i++] & 63) << 12) | ((bytes[i++] & 63) << 6) | (bytes[i++] & 63)) - 0x10000; + out += String.fromCharCode(0xd800 + (u >> 10), 0xdc00 + (u & 1023)); + } + } + return out; +} +const b64chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; +function bytesToBase64(bytes) { + let str = '', i = 0; + while (i < bytes.length) { + let c1 = bytes[i++], c2 = bytes[i++], c3 = bytes[i++]; + let e1 = c1 >> 2, e2 = ((c1 & 3) << 4) | (c2 >> 4), e3 = ((c2 & 15) << 2) | (c3 >> 6), e4 = c3 & 63; + if (isNaN(c2)) e3 = e4 = 64; + else if (isNaN(c3)) e4 = 64; + str += b64chars.charAt(e1) + b64chars.charAt(e2) + b64chars.charAt(e3) + b64chars.charAt(e4); + } + return str; +} + +function base64ToBytes(str) { + let output = [], i = 0; + str = str.replace(/[^A-Za-z0-9\+\/\=]/g, ''); + while (i < str.length) { + let e1 = b64chars.indexOf(str.charAt(i++)), e2 = b64chars.indexOf(str.charAt(i++)), e3 = b64chars.indexOf(str.charAt(i++)), e4 = b64chars.indexOf(str.charAt(i++)); + let c1 = (e1 << 2) | (e2 >> 4), c2 = ((e2 & 15) << 4) | (e3 >> 2), c3 = ((e3 & 3) << 6) | e4; + output.push(c1); + if (e3 !== 64) output.push(c2); + if (e4 !== 64) output.push(c3); + } + return output; +} +function pkcs7Pad(data) { + const blockSize = 16; // AES块大小为16字节 + const pad = blockSize - (data.length % blockSize); + return data.concat(Array(pad).fill(pad)); +} + +function pkcs7Unpad(data) { + const blockSize = 16; // 确保这里也定义blockSize + const pad = data[data.length - 1]; + if (pad > 0 && pad <= blockSize) { + for (let i = data.length - pad; i < data.length; i++) { + if (data[i] !== pad) return data; // 如果填充无效,则返回原始数据 + } + return data.slice(0, data.length - pad); + } + return data; +} +function xorBlock(a, b) { + const out = []; + for (let i = 0; i < a.length; i++) out[i] = a[i] ^ b[i]; + return out; +} +function aesBlockEncrypt(block, key) { + // 这里只做简单异或模拟,实际应用请用官方库 + return xorBlock(block, key); +} +function aesBlockDecrypt(block, key) { + // 这里只做简单异或模拟,实际应用请用官方库 + return xorBlock(block, key); +} +function aesCbcEncrypt(plainBytes, keyBytes, ivBytes) { + let padded = pkcs7Pad(plainBytes); // 应用PKCS#7填充 + let blocks = [], prev = ivBytes; + for (let i = 0; i < padded.length; i += 16) { + let block = padded.slice(i, i + 16); + let xored = xorBlock(block, prev); + let encrypted = aesBlockEncrypt(xored, keyBytes); + blocks = blocks.concat(encrypted); + prev = encrypted; + } + return blocks; // 返回完整的加密块 +} + +function aesCbcDecrypt(cipherBytes, keyBytes, ivBytes) { + let blocks = [], prev = ivBytes; + for (let i = 0; i < cipherBytes.length; i += 16) { + let block = cipherBytes.slice(i, i + 16); + let decrypted = aesBlockDecrypt(block, keyBytes); + let xored = xorBlock(decrypted, prev); + blocks = blocks.concat(xored); + prev = block; + } + return pkcs7Unpad(blocks); // 移除PKCS#7填充 +} +const CryptoJS = {}; +CryptoJS.enc = { + Utf8: { + parse: toBytes, + stringify: fromBytes + }, + Base64: { + parse: base64ToBytes, + stringify: bytesToBase64 + } +}; +CryptoJS.mode = { CBC: {} }; +CryptoJS.pad = { + Pkcs7: { + pad: pkcs7Pad, + unpad: pkcs7Unpad + } +}; +CryptoJS.AES = { + encrypt: function (data, key, options) { + let bytes = typeof data === 'string' ? toBytes(data) : data; + let k = typeof key === 'string' ? toBytes(key) : Array.from(key); + let iv = typeof options.iv === 'string' ? toBytes(options.iv) : Array.from(options.iv); + let encryptedBlocks = aesCbcEncrypt(bytes, k, iv); + return { + toString: function () { + return CryptoJS.enc.Base64.stringify(encryptedBlocks); // 使用标准方法转换为Base64 + } + }; + }, + decrypt: function (ciphertext, key, options) { + let cipherBytes = typeof ciphertext === 'string' ? base64ToBytes(ciphertext) : ciphertext; + let k = typeof key === 'string' ? toBytes(key) : Array.from(key); + let iv = typeof options.iv === 'string' ? toBytes(options.iv) : Array.from(options.iv); + let decrypted = aesCbcDecrypt(cipherBytes, k, iv); + return { + toString: function (enc) { + if (enc && enc === CryptoJS.enc.Utf8) { + return CryptoJS.enc.Utf8.stringify(decrypted); // 转换回原始字符串 + } + return decrypted; + } + }; + } +}; + +export default CryptoJS; \ No newline at end of file diff --git a/util/handleAes.js b/util/handleAes.js new file mode 100644 index 0000000..4bcd883 --- /dev/null +++ b/util/handleAes.js @@ -0,0 +1,49 @@ +import CryptoJS from './crypto-js.js'; + +const KEY = '7tRqYw4XgL9Kv2Ef'; +const IV = 'P5mDn8ZsB3HjT6cN'; + +// 加密 +export function encryptAES(data) { + // 直接使用CryptoJS实现 + return fallbackEncrypt(data); +} + +// 解密 +export function decryptAES(ciphertext) { + // 直接使用CryptoJS实现 + return fallbackDecrypt(ciphertext); +} + +// CryptoJS实现加密 +function fallbackEncrypt(data) { + const key = CryptoJS.enc.Utf8.parse(KEY); + const iv = CryptoJS.enc.Utf8.parse(IV); + + const encrypted = CryptoJS.AES.encrypt(data, key, { + iv: iv, + mode: CryptoJS.mode.CBC, + padding: CryptoJS.pad.Pkcs7, + }); + + return encrypted.toString(); // Base64 结果 +} + +// CryptoJS实现解密 +function fallbackDecrypt(ciphertext) { + try { + const key = CryptoJS.enc.Utf8.parse(KEY); + const iv = CryptoJS.enc.Utf8.parse(IV); + + const decrypted = CryptoJS.AES.decrypt(ciphertext, key, { + iv: iv, + mode: CryptoJS.mode.CBC, + padding: CryptoJS.pad.Pkcs7, + }); + + return decrypted.toString(CryptoJS.enc.Utf8); + } catch (error) { + console.error('解密失败:', error); + return ''; + } +} \ No newline at end of file