-
Notifications
You must be signed in to change notification settings - Fork 87
Expand file tree
/
Copy pathJD-in-one-v2.scriptable
More file actions
12 lines (11 loc) · 75.9 KB
/
Copy pathJD-in-one-v2.scriptable
File metadata and controls
12 lines (11 loc) · 75.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
{
"always_run_in_app" : false,
"icon" : {
"color" : "pink",
"glyph" : "shopping-cart"
},
"name" : "JD-in-one-v2",
"script" : "\/\/ Author: 脑瓜\n\/\/ 电报群: https:\/\/t.me\/Scriptable_JS @anker1209\n\/\/ 采用了2Ya美女的京豆收支脚本及DmYY依赖 https:\/\/github.com\/dompling\/Scriptable\/tree\/master\/Scripts\n\/\/ version:2.3.1\n\/\/ update:2023\/01\/24\n\nif (typeof require === 'undefined') require = importModule;\nconst {DmYY, Runing} = require('.\/DmYY');\n\nclass Widget extends DmYY {\n constructor(arg) {\n super(arg);\n this.name = '京东多合一';\n this.en = 'jd_in_one';\n this.run(module.filename, args);\n }\n fm = FileManager.local();\n CACHE_FOLDER = 'JD_in_one';\n cachePath = null;\n\n logo = 'https:\/\/pic.imgdb.cn\/item\/6187994b2ab3f51d919028cc.png';\n JDImg = 'https:\/\/pic.imgdb.cn\/item\/63132fbf16f2c2beb1f33a97.png';\n beanImg = 'https:\/\/pic.imgdb.cn\/item\/63132fda16f2c2beb1f35611.png';\n plusFG = 'https:\/\/raw.githubusercontent.com\/githubdulong\/Script\/master\/Images\/plusFG.png';\n plusBG = 'https:\/\/raw.githubusercontent.com\/githubdulong\/Script\/master\/Images\/plusBG.png';\n baitiaoImg = 'https:\/\/pic.imgdb.cn\/item\/6313300f16f2c2beb1f387f0.png';\n plusIcon = 'https:\/\/raw.githubusercontent.com\/githubdulong\/Script\/master\/Images\/IMG_0610.png';\n walletImg = 'https:\/\/pic.imgdb.cn\/item\/6313303716f2c2beb1f3ace2.png';\n jingtieImg = 'https:\/\/pic.imgdb.cn\/item\/6313312416f2c2beb1f48141.png';\n gangbengImg = 'https:\/\/pic.imgdb.cn\/item\/6313313516f2c2beb1f4905d.png';\n userImage = 'https:\/\/img11.360buyimg.com\/jdphoto\/s120x120_jfs\/t21160\/90\/706848746\/2813\/d1060df5\/5b163ef9N4a3d7aa6.png';\n nameImg = 'https:\/\/pic.imgdb.cn\/item\/6188bfb62ab3f51d91bca276.png';\n tagImg = 'https:\/\/pic.imgdb.cn\/item\/6188bfc72ab3f51d91bcbcb0.png';\n\n \/\/ 请勿在此修改参数值\n\n version = '2.2.9';\n basicSetting = {\n scale: 1.00,\n logo: 30,\n userImage: 69,\n userStack: 103,\n division: 25,\n interval: 10,\n directory: 'Local',\n customizeName: '',\n customizeAvatar: '',\n smallShowType: '京豆、钱包数据',\n walletShowType: '红包',\n };\n chartSetting = {\n height: 130,\n daySize: 9,\n dayText: '',\n textSize: 18,\n textDayColor: '999999', \n textNightColor: '999999',\n lineColor: '#FA6859',\n linePadding: 15,\n barPadding: 5,\n smallShowType: '双日视图',\n showType: '双日视图',\n countBean: '收入-支出',\n colorful: '关闭',\n };\n funcSetting = {\n showBaitiao: '打开',\n showPackage: '关闭',\n showFruit: '打开',\n logable: '关闭',\n alwaysRefreshChart: '打开',\n };\n package = {\n number: 0,\n title: '',\n desc: '',\n time: '',\n status: '',\n };\n baitiao = {\n title: '',\n number: 0,\n desc: '',\n };\n redPackage = {\n title: '红包',\n number: 0,\n desc: '今日无过期',\n };\n extra = {\n jingtie: 0,\n gangbeng: 0,\n };\n bean = {\n todayIncome: 0,\n todayExpense: 0,\n ydayIncome: 0,\n ydayExpense: 0,\n };\n\n nickName = '未知用户';\n jValue = '0';\n isPlus = false;\n\n cookie = '';\n userName = '';\n CookiesData = [];\n cacheChart = false;\n beanCount = 0;\n maxDays = 6;\n rangeTimer = {};\n timerKeys = [];\n fruitState = \"😢\";\n \n doubleDate = this.getDay(1);\n doubleDay = Object.keys(this.doubleDate);\n yestoday = this.doubleDay[0];\n today = this.doubleDay[1];\n CACHES = [];\n\n lineChart(labels = [], datas = [], chartTextSize, topPadding) {\n let chartTextColor = Color.dynamic(new Color(this.chartSetting.textDayColor),new Color(this.chartSetting.textNightColor),);\n let lineColor = this.chartSetting.lineColor.split(',');\n const chartStr = `\n {\n type: 'bar',\n data: {\n labels: ${JSON.stringify(labels)},\n datasets: [\n {\n type: 'line',\n backgroundColor: '#FFFFFF',\n borderColor: getGradientFillHelper('horizontal', ${JSON.stringify(lineColor)}),\n borderWidth: ${this.isSmall(true) ? 4 : 3},\n pointRadius: ${this.isSmall(true) ? 8 : 6},\n fill: false,\n showLine: true,\n data: ${JSON.stringify(datas)},\n },\n ],\n },\n options: {\n plugins: {\n datalabels: {\n display: true,\n align: 'top',\n color: '#${chartTextColor.hex}',\n font: {\n family: 'ArialMT',\n size: ${chartTextSize}\n }\n },\n },\n layout: {\n padding: {\n left: -20,\n right: 0,\n top: ${topPadding},\n bottom: 0\n }\n },\n responsive: true,\n maintainAspectRatio: true,\n legend: {\n display: false,\n },\n scales: {\n xAxes: [\n {\n gridLines: {\n display: false,\n },\n ticks: {\n display: false,\n },\n },\n ],\n yAxes: [\n {\n ticks: {\n display: false,\n beginAtZero: false,\n },\n gridLines: {\n display: false,\n },\n },\n ],\n },\n },\n }`;\n return chartStr;\n }\n\n barChart(labels = [], datas = [], chartTextSize, topPadding, showType) {\n let chartTextColor = Color.dynamic(new Color(this.chartSetting.textDayColor),new Color(this.chartSetting.textNightColor),);\n let backgroundColor = [];\n if (this.chartSetting.colorful === '打开') backgroundColor = JSON.stringify(this.colorfulBar())\n else backgroundColor = `getGradientFillHelper('vertical', ${JSON.stringify(this.chartColors())})`\n const chartStr = `\n {\n type: 'bar',\n data: {\n labels: ${JSON.stringify(labels)},\n datasets: [\n {\n type: '${showType}',\n borderWidth: 0,\n pointRadius: 0,\n barPercentage: 0.5,\n backgroundColor: ${backgroundColor},\n borderColor: false,\n data: ${JSON.stringify(datas)},\n },\n ],\n },\n options: {\n plugins: {\n datalabels: {\n display: true,\n align: 'top',\n offset: -4,\n anchor:'end',\n color: '#${chartTextColor.hex}',\n font: {\n family: 'ArialMT',\n size: ${chartTextSize}\n }\n },\n },\n layout: {\n padding: {\n left: -20,\n right: 0,\n top: ${topPadding},\n bottom: 0\n }\n },\n responsive: true,\n maintainAspectRatio: true,\n legend: {\n display: false,\n },\n title: {\n display: false,\n },\n scales: {\n xAxes: [\n {\n gridLines: {\n offsetGridLines: true,\n display: false,\n },\n ticks: {\n display: false,\n },\n },\n ],\n yAxes: [\n {\n ticks: {\n display: false,\n beginAtZero: true,\n },\n gridLines: {\n offsetGridLines: true,\n display: false,\n },\n },\n ],\n },\n },\n }`;\n return chartStr;\n }\n\n chartColors () {\n let colorArr = [['#FFF000', '#E62490'], ['#FDEB71', '#F8D800'], ['#ABDCFF', '#0396FF'], ['#FEB692', '#EA5455'], ['#FEB692', '#EA5455'], ['#CE9FFC', '#7367F0'], ['#90F7EC', '#32CCBC'], ['#FFF6B7', '#F6416C'], ['#E2B0FF', '#9F44D3'], ['#F97794', '#F072B6'], ['#FCCF31', '#F55555'], ['#5EFCE8', '#736EFE'], ['#FAD7A1', '#E96D71'], ['#FFFF1C', '#00C3FF'], ['#FEC163', '#DE4313'], ['#F6CEEC', '#D939CD'], ['#FDD819', '#E80505'], ['#FFF3B0', '#CA26FF'], ['#2AFADF', '#4C83FF'], ['#EECDA3', '#EF629F'], ['#C2E59C', '#64B3F4'], ['#FFF886', '#F072B6'], ['#F5CBFF', '#C346C2'], ['#FFF720', '#3CD500'], ['#EE9AE5', '#5961F9'], ['#FFC371', '#FF5F6D'], ['#FFD3A5', '#FD6585'], ['#C2FFD8', '#465EFB'], ['#FFC600', '#FD6E6A'], ['#FFC600', '#FD6E6A'], ['#92FE9D', '#00C9FF'], ['#FFDDE1', '#EE9CA7'], ['#F0FF00', '#58CFFB'], ['#FFE985', '#FA742B'], ['#72EDF2', '#5151E5'], ['#F6D242', '#FF52E5'], ['#F9D423', '#FF4E50'], ['#3C8CE7', '#00EAFF'], ['#FCFF00', '#FFA8A8'], ['#FF96F9', '#C32BAC'], ['#D0E6A5', '#FFDD94'], ['#FFDD94', '#FA897B'], ['#FFCC4B', '#FF7D58'], ['#D0E6A5', '#86E3CE'], ['#F0D5B6', '#F16238'], ['#F8EC70', '#F9C708'], ['#C4E86B', '#00BCB4'], ['#F5CEC7', '#E79796'], ['#FFC446', '#FA0874'], ['#E1EE32', '#FFB547'], ['#FFD804', '#2ACCC8'], ['#E9A6D2', '#E9037B'], ['#F8EC70', '#49E2F6'], ['#A2F8CD', '#A2F852'], ['#49E2F6', '#A2F8CD'], ['#FDEFE2', '#FE214F'], ['#F8EC70', '#A2F8CD'], ['#F8EC70', '#49E2F6'], ['#D1FFB7', '#FFB7D1'], ['#B7FFE4', '#E4B7FF'], ['#FFB7D1', '#E4B7FF'], ['#D0E6A5', '#86E3CE'], ['#E8E965', '#64C5C7']];\n let chartColors = colorArr[Math.floor(Math.random() * colorArr.length)];\n \/\/chartColors = ['#DB36A4', '#F7FF00']; \/\/ 固定京豆图表填充颜色\n return chartColors;\n }\n\n colorfulBar () {\n let colorArr = [['#1B9E77', '#D95F02', '#7570B3', '#E7298A', '#66A61E', '#E6AB02'], ['#F46277', '#FC8D59', '#FEE08B', '#E6F598', '#99D594', '#3288BD'], ['#A6CEE3', '#1F78B4', '#B2DF8A', '#33A02C', '#FB9A99', '#E31A1C'], ['#E41A1C', '#377EB8', '#4DAF4A', '#984EA3', '#FF7F00', '#9ED80E'], ['#F81B02', '#FC7715', '#AFBF41', '#50C49F', '#3B95C4', '#B560D4'], ['#FFC000', '#A5D028', '#08CC78', '#F24099', '#5AA6C0', '#F56617'], ['#F09415', '#C1B56B', '#4BAF73', '#5AA6C0', '#D17DF9', '#FA7E5C'], ['#0F6FC6', '#009DD9', '#0BD0D9', '#10CF9B', '#7CCA62', '#A5C249'], ['#9ACD4C', '#FAA93A', '#D35940', '#B258D3', '#63A0CC', '#8AC4A7'], ['#A7EA52', '#EFAB16', '#78AC35', '#35ACA2', '#4083CF', '#FF8021'], ['#9EC544', '#50BEA3', '#4A9CCC', '#9A66CA', '#C54F71', '#DE9C3C'], ['#41AEBD', '#97E9D5', '#A2CF49', '#608F3D', '#F4DE3A', '#FCB11C'], ['#2FA3EE', '#4BCAAD', '#86C157', '#D99C3F', '#CE6633', '#A35DD1'], ['#3399FF', '#69FFFF', '#CCFF33', '#3333FF', '#9933FF', '#FF33FF'], ['#FBC01E', '#EFE1A2', '#FA8716', '#F2575F', '#A5D848', '#A155F9'], ['#90C226', '#54A021', '#E6B91E', '#E76618', '#C42F1A', '#FA8716'], ['#0F6FC6', '#009DD9', '#0BD0D9', '#10CF9B', '#7CCA62', '#A5C249'], ['#FFB91D', '#F97817', '#6DE304', '#F98080', '#8F58F9', '#F789EA'], ['#C70F0C', '#DD6B0D', '#FAA700', '#93E50D', '#17C7BA', '#0A96E4'], ['#40BAD2', '#FAB900', '#90BB23', '#EE7008', '#1AB39F', '#D5393D'], ['#80B606', '#E29F1D', '#2397E2', '#35ACA2', '#5430BB', '#8D34E0'], ['#549E39', '#8AB833', '#C0CF3A', '#029676', '#4AB5C4', '#0989B1'], ['#99CB38', '#63A537', '#37A76F', '#44C1A3', '#4EB3CF', '#51C3F9'], ['#8C73D0', '#C2E8C4', '#C5A6E8', '#B45EC7', '#9FDAFB', '#95C5B0'], ['#1CADE4', '#2683C6', '#27CED7', '#42BA97', '#3E8853', '#62A39F'], ['#B31166', '#E33D6F', '#E45F3C', '#E9943A', '#9B6BF2', '#D53DD0'], ['#76C5EF', '#FEA022', '#FF6700', '#70A525', '#A5D848', '#20768C'], ['#A1D68B', '#5EC795', '#4DADCF', '#CDB756', '#E29C36', '#8EC0C1'], ['#418AB3', '#A6B727', '#F69200', '#80C34F', '#FEC306', '#DF5327'], ['#7FD13B', '#EA157A', '#FEB80A', '#00ADDC', '#738AC8', '#1AB39F'], ['#F0AD00', '#60B5CC', '#E66C7D', '#6BB76D', '#E88651', '#C64847'], ['#5B9BD5', '#ED7D31', '#A5D848', '#FFC000', '#4472C4', '#70AD47'], ['#4F81BD', '#C0504D', '#9BBB59', '#8064A2', '#4BACC6', '#F79646'], ['#F95F9A', '#AC66BB', '#DE6C36', '#F9B639', '#CF6DA4', '#FA8D3D'], ['#F2D908', '#9DE61E', '#0D8BE6', '#C61B1B', '#E26F08', '#8D35D1'], ['#A5B592', '#F3A447', '#E7BC29', '#D092A7', '#9C85C0', '#809EC2'], ['#30ACEC', '#80C34F', '#E29D3E', '#D64A3B', '#D64787', '#A666E1'], ['#A2C816', '#E07602', '#E4C402', '#7DC1EF', '#21449B', '#A2B170'], ['#FF7F01', '#F1B015', '#FBEC85', '#D2C2F1', '#DA5AF4', '#9D09D1'], ['#FDA023', '#A7EA52', '#5ECCF3', '#64A73B', '#EB5605', '#B9CA1A'], ['#00C6BB', '#6FEBA0', '#B6DF5E', '#EFB251', '#EF755F', '#ED515C'], ['#E32D91', '#C830CC', '#4EA6DC', '#4775E7', '#8971E1', '#D54773'], ['#1CADE4', '#2683C6', '#27CED7', '#42BA97', '#3E8853', '#62A39F'], ['#073779', '#8FD9FB', '#FFCC00', '#EB6615', '#C76402', '#B523B4'], ['#4E67C8', '#5ECCF3', '#A7EA52', '#5DCEAF', '#FF8021', '#F14124'], ['#3891A7', '#FEB80A', '#FC8389', '#84AA33', '#F9934E', '#4379EF'], ['#990000', '#FF6600', '#FFBA00', '#99CC00', '#528A02', '#9C007F'], ['#F7901E', '#FEC60B', '#9FE62F', '#4EA5D1', '#4282EA', '#854FED'], ['#E8BC4A', '#83C1C6', '#E78D35', '#909CE1', '#839C41', '#F9826E'], ['#86CE24', '#00A2E6', '#FAC810', '#AA69F7', '#D06B20', '#FF8021'], ['#DF2E28', '#FE801A', '#E9BF35', '#81BB42', '#32C7A9', '#4A9BDC'], ['#31B6FD', '#4584D3', '#5BD078', '#A5D028', '#F5C040', '#05E0DB'], ['#FFCA08', '#F8931D', '#CE8D3E', '#EC7016', '#E64823', '#9C6A6A'], ['#4E79A7', '#F28E2B', '#E15759', '#76B7B2', '#59A14F', '#EDC948'], ['#4E79A7', '#A0CBE8', '#F28E2B', '#FFBE7D', '#59A14F', '#8CD17D'], ['#E03531', '#F0BD27', '#51B364', '#FF684C', '#FFDA66', '#8ACE7E'], ['#4E9F50', '#87D180', '#EF8A0C', '#FCC66D', '#3CA8BC', '#98D9E4'], ['#1F77B4', '#FF7F0E', '#2CA02C', '#D62728', '#9467BD', '#E377C2'], ['#32A251', '#ACD98D', '#FF7F0F', '#FFB977', '#3CB7CC', '#98D9E4'], ];\n let chartColors = colorArr[Math.floor(Math.random() * colorArr.length)];\n \/\/chartColors = ['#C1B14A','#6FBC75','#39B6B3','#86A1CD','#D083AB','#DF786B']; \/\/ 固定京豆图表填充颜色\n return chartColors;\n }\n\n isSmall (a = false) {\n if (a) return config.widgetFamily == 'small' ? true : false;\n else return config.widgetFamily == 'small' ? '_small' : '';\n }\n\n \/\/ #####################小组件###################\n renderSmall = async (w) => {\n const bodyStack = w.addStack();\n bodyStack.layoutVertically();\n if (this.basicSetting.smallShowType === '个人信息') {\n await this.setUserShow(bodyStack);\n } else {\n await this.setHeaderShow(bodyStack);\n bodyStack.addSpacer();\n switch (this.chartSetting.smallShowType) {\n case '折线图表' :\n await this.setChartShow(bodyStack, 1);\n break;\n case '柱状图表' :\n await this.setChartShow(bodyStack, 2);\n break;\n case '曲线面积图':\n await this.setChartShow(bodyStack, 3);\n break;\n default:\n await this.setBeanShow(bodyStack, 22 * this.basicSetting.scale, 40 * this.basicSetting.scale);\n }\n bodyStack.addSpacer(5 * this.basicSetting.scale);\n if (this.funcSetting.showBaitiao === '打开' && this.baitiao.number > 0) {\n await this.setBaitiaoShow(bodyStack, true);\n } else if (this.basicSetting.walletShowType === '红包') {\n await this.setRedPackageShow(bodyStack, true);\n } else {\n await this.setCoinShow(bodyStack, true);\n }\n }\n return w;\n }\n\n \/\/ #####################中组件###################\n renderMedium = async (w) => {\n const bodyStack = w.addStack();\n await this.setUserShow(bodyStack);\n bodyStack.addSpacer(this.basicSetting.division * this.basicSetting.scale);\n const mainStack = bodyStack.addStack();\n mainStack.layoutVertically();\n await this.setHeaderShow(mainStack, this.JDImg);\n mainStack.addSpacer();\n if (this.funcSetting.showPackage === '打开' && this.package.number > 0) {\n await this.setPackageShow(mainStack);\n mainStack.addSpacer();\n } else {\n switch (this.chartSetting.showType) {\n case '折线图表':\n await this.setChartShow(mainStack, 1);\n mainStack.addSpacer(5 * this.basicSetting.scale);\n break;\n case '柱状图表':\n await this.setChartShow(mainStack, 2);\n mainStack.addSpacer(5 * this.basicSetting.scale);\n break;\n case '曲线面积图':\n await this.setChartShow(mainStack, 3);\n mainStack.addSpacer(5 * this.basicSetting.scale);\n break;\n default:\n await this.setBeanShow(mainStack, 30 * this.basicSetting.scale, 50 * this.basicSetting.scale);\n mainStack.addSpacer();\n }\n }\n if (this.funcSetting.showBaitiao === '打开' && this.baitiao.number > 0) {\n await this.setBaitiaoShow(mainStack);\n } else if (this.basicSetting.walletShowType === '红包') {\n await this.setRedPackageShow(mainStack);\n } else {\n await this.setCoinShow(mainStack);\n }\n return w;\n }\n\n \/\/ #####################大组件###################\n renderLarge = async (w) => {\n const bodyStack = w.addStack();\n bodyStack.size = new Size(0, 150);\n bodyStack.addSpacer();\n await this.setUserShow(bodyStack);\n bodyStack.addSpacer();\n w.addSpacer(20);\n const text = w.addText('\\u6211\\u600e\\u4e48\\u8fd9\\u4e48\\u597d\\u770b');\n w.addSpacer(20);\n text.font = Font.thinSystemFont(30);\n text.centerAlignText();\n const emoji = w.addText('🤣🥰🤪');\n emoji.centerAlignText();\n w.addSpacer();\n return w;\n }\n\n \/\/ #####################用户信息###################\n async setUserShow(stack) {\n const userStack = stack.addStack();\n userStack.size = new Size(this.basicSetting.userStack * this.basicSetting.scale, 0);\n userStack.layoutVertically();\n \/\/ 头像\n const userImgStack = userStack.addStack();\n userImgStack.addSpacer();\n const imgStack = userImgStack.addStack();\n if (this.isPlus) {\n imgStack.size = new Size(this.basicSetting.userImage * this.basicSetting.scale, this.basicSetting.userImage * this.basicSetting.scale * 1.039);\n imgStack.backgroundImage = await this.getImageByUrl(this.plusBG, 'plusBGImage.png');\n }\n const subStack = imgStack.addStack();\n subStack.url = 'openapp.jdmobile:\/\/';\n subStack.size = new Size(this.basicSetting.userImage * this.basicSetting.scale, this.basicSetting.userImage * this.basicSetting.scale);\n subStack.cornerRadius = this.basicSetting.userImage \/ 2 * this.basicSetting.scale;\n subStack.backgroundImage = await this.getImageByUrl(this.basicSetting.customizeAvatar || this.userImage, `userImage_${this.userName}.png`);\n if (this.isPlus) {\n const userImg = subStack.addImage(await this.getImageByUrl(this.plusFG, 'plusFGImage.png'));\n }\n userImgStack.addSpacer();\n userStack.addSpacer();\n \/\/ 物流提示\n const tipStack = userStack.addStack();\n tipStack.addSpacer();\n const signStack = tipStack.addStack();\n signStack.size = new Size(14 * this.basicSetting.scale, 14 * this.basicSetting.scale)\n signStack.backgroundColor = new Color('0dD6A0');\n signStack.cornerRadius = 14 * this.basicSetting.scale \/ 2;\n signStack.centerAlignContent();\n let signIcon = SFSymbol.named('checkmark');\n const signItem = signStack.addImage(signIcon.image);\n signItem.imageSize = new Size(8 * this.basicSetting.scale, 8 * this.basicSetting.scale);\n signItem.tintColor = new Color('FFFFFF');\n if (this.package.number > 0) {\n tipStack.addSpacer(3 * this.basicSetting.scale);\n const packageStack = tipStack.addStack();\n packageStack.size = new Size(14 * this.basicSetting.scale, 14 * this.basicSetting.scale)\n packageStack.backgroundColor = new Color('FC8600');\n packageStack.cornerRadius = 14 * this.basicSetting.scale \/ 2;\n packageStack.centerAlignContent();\n packageStack.setPadding(1 * this.basicSetting.scale, 2 * this.basicSetting.scale, 1 * this.basicSetting.scale, 2 * this.basicSetting.scale);\n let packageNum = packageStack.addText(this.package.number.toString());\n packageNum.font = Font.mediumSystemFont(15 * this.basicSetting.scale);\n packageNum.textColor = new Color('FFFFFF');\n packageNum.minimumScaleFactor = 0.1;\n }\n if (this.funcSetting.showFruit === '打开') {\n tipStack.addSpacer(3 * this.basicSetting.scale);\n const fruitStack = tipStack.addStack();\n fruitStack.size = new Size(14 * this.basicSetting.scale, 14 * this.basicSetting.scale)\n fruitStack.backgroundColor = new Color('118AB2');\n fruitStack.cornerRadius = 14 * this.basicSetting.scale \/ 2;\n fruitStack.centerAlignContent();\n fruitStack.setPadding(1 * this.basicSetting.scale, 2 * this.basicSetting.scale, 1 * this.basicSetting.scale, 2 * this.basicSetting.scale);\n let fruitText = fruitStack.addText(this.fruitState);\n fruitText.font = Font.mediumSystemFont(15 * this.basicSetting.scale);\n fruitText.textColor = new Color('FFFFFF');\n fruitText.minimumScaleFactor = 0.1;\n }\n tipStack.addSpacer();\n userStack.addSpacer();\n \/\/ 用户名\n const nameStack = userStack.addStack();\n nameStack.centerAlignContent();\n if (this.isPlus) {\n const nameImg = nameStack.addImage(await this.getImageByUrl(this.plusIcon, 'plusIcon.png'));\n nameImg.imageSize = new Size(15 * this.basicSetting.scale, 15 * this.basicSetting.scale);\n } else {\n const nameIcon = nameStack.addImage(await this.getImageByUrl(this.nameImg, 'nameImg.png'));\n nameIcon.imageSize = new Size(15 * this.basicSetting.scale, 15 * this.basicSetting.scale);\n }\n nameStack.addSpacer(5 * this.basicSetting.scale);\n const name = nameStack.addText(this.basicSetting.customizeName || this.nickName);\n name.lineLimit = 1;\n name.font = Font.regularSystemFont(14 * this.basicSetting.scale);\n userStack.addSpacer(5 * this.basicSetting.scale);\n \/\/ 京享值\n const valueStack = userStack.addStack();\n valueStack.centerAlignContent();\n const lableIcon = valueStack.addImage(await this.getImageByUrl(this.tagImg, 'tagImg.png'));\n lableIcon.imageSize = new Size(15 * this.basicSetting.scale, 15 * this.basicSetting.scale);\n valueStack.addSpacer(5 * this.basicSetting.scale);\n const value = valueStack.addText(this.jValue.toString());\n value.font = Font.mediumSystemFont(14 * this.basicSetting.scale);\n\n valueStack.addSpacer(5 * this.basicSetting.scale);\n const jStack = valueStack.addStack();\n jStack.backgroundColor = new Color('fa2d19'); \/\/ “京享”二字背景颜色\n jStack.cornerRadius = 5;\n jStack.setPadding(1 * this.basicSetting.scale, 4 * this.basicSetting.scale, 1 * this.basicSetting.scale, 4 * this.basicSetting.scale);\n const jLable = jStack.addText('京享');\n jLable.font = Font.systemFont(8 * this.basicSetting.scale);\n jLable.textColor = new Color('FFFFFF') \/\/ “京享”二字字体颜色\n ;[name, value].map(t => t.textColor = this.widgetColor);\n }\n\n \/\/ #####################顶部内容###################\n async setHeaderShow(stack, image) {\n const topStack = stack.addStack();\n topStack.centerAlignContent();\n if (image) {\n const JDLogo = topStack.addImage(await this.getImageByUrl(this.logo, 'logoImage.png'));\n JDLogo.imageSize = new Size(this.basicSetting.logo * this.basicSetting.scale, this.basicSetting.logo * this.basicSetting.scale);\n topStack.addSpacer(10 * this.basicSetting.scale);\n const JD = topStack.addImage(await this.getImageByUrl(image, 'jingdongImage.png'));\n JD.imageSize = new Size(194 * 0.2 * this.basicSetting.scale, 78 * 0.2 * this.basicSetting.scale);\n } else {\n const imgStack = topStack.addStack();\n if (this.isPlus) {\n imgStack.size = new Size(30 * this.basicSetting.scale, 30 * this.basicSetting.scale * 1.039);\n imgStack.backgroundImage = await this.getImageByUrl(this.plusBG, 'plusBGImage.png');\n }\n const subStack = imgStack.addStack();\n subStack.url = 'openapp.jdmobile:\/\/';\n subStack.size = new Size(30 * this.basicSetting.scale, 30 * this.basicSetting.scale);\n subStack.cornerRadius = 30 \/ 2 * this.basicSetting.scale;\n subStack.backgroundImage = await this.getImageByUrl(this.basicSetting.customizeAvatar || this.userImage, `userImage_${this.userName}.png`);\n if (this.isPlus) {\n const userImg = subStack.addImage(await this.getImageByUrl(this.plusFG, 'plusFGImage.png'));\n }\n }\n topStack.addSpacer();\n const jdBean = topStack.addText(this.beanCount.toString());\n jdBean.font = Font.mediumSystemFont(20 * this.basicSetting.scale);\n jdBean.textColor = new Color('fa2d19'); \/\/ 右上角京豆数颜色\n jdBean.url = 'openapp.jdmobile:\/\/virtual?params=%7B%22category%22%3A%22jump%22%2C%22des%22%3A%22m%22%2C%22url%22%3A%22https%3A%2F%2Fbean.m.jd.com%2FbeanDetail%2Findex.action%3FresourceValue%3Dbean%22%7D';\n const desStack = topStack.addStack();\n desStack.layoutVertically();\n desStack.addSpacer(5.5 * this.basicSetting.scale);\n const desText = desStack.addText(' 京豆');\n desText.font = Font.mediumSystemFont(10 * this.basicSetting.scale);\n desText.textColor = new Color('fa2d19', 0.7);\n }\n\n \/\/ #####################京豆收支###################\n async setBeanShow(stack, textSize, imageSize) {\n const beanStack = stack.addStack();\n \/\/ 今日收支\n const yestodayStack = beanStack.addStack();\n yestodayStack.layoutVertically();\n try {\n this.bean.ydayIncome = this.rangeTimer[this.yestoday][0] - this.rangeTimer[this.yestoday][1];\n this.bean.ydayExpense = this.rangeTimer[this.yestoday][1];\n this.bean.todayIncome = this.rangeTimer[this.today][0] - this.rangeTimer[this.today][1];;\n this.bean.todayExpense = this.rangeTimer[this.today][1];\n } catch (e) {\n this.notify(this.name, '\\u597d\\u50cf\\u4f60\\u6628\\u5929\\u6ca1\\u6709\\u4f7f\\u7528\\u8be5\\u5c0f\\u7ec4\\u4ef6\\uff0c\\u8bf7\\u91cd\\u7f6e\\u4eac\\u8c46\\u6570\\u636e');\n }\n this.rowBeanCell(\n yestodayStack,\n this.bean.ydayExpense.toString(),\n this.bean.ydayIncome.toString(),\n textSize,\n '昨日',\n );\n beanStack.addSpacer();\n \/\/ 京豆图片\n const ddStack = beanStack.addStack();\n ddStack.layoutVertically();\n const ddImg = ddStack.addImage(await this.getImageByUrl(this.beanImg, 'beanImage.png'));\n ddImg.imageSize = new Size(imageSize, imageSize);\n beanStack.addSpacer();\n \/\/ 昨日收支\n const todayStack = beanStack.addStack();\n todayStack.layoutVertically();\n this.rowBeanCell(\n todayStack,\n this.bean.todayExpense.toString(),\n this.bean.todayIncome.toString(),\n textSize,\n '今日',\n );\n }\n\n \/\/ #####################京豆图表###################\n async setChartShow(stack, type) {\n let labels = [], data = [];\n Object.keys(this.rangeTimer).forEach((day) => {\n const value = this.rangeTimer[day];\n const arrDay = day.split('-');\n labels.push(arrDay[2]);\n if (this.chartSetting.countBean === '收入-支出')\n data.push(value[0]);\n else data.push(value[0] - value[1]);\n });\n let cacheKey = `chart${type}Image${this.isSmall()}_${this.userName}.png`;\n let textSize = this.chartSetting.textSize;\n let linePadding = this.chartSetting.linePadding;\n let barPadding = this.chartSetting.barPadding;\n if (config.widgetFamily === 'small') {\n data.splice(0, 2);\n labels.splice(0, 2);\n textSize = this.chartSetting.textSize + 7;\n linePadding = this.chartSetting.linePadding + 10;\n barPadding = this.chartSetting.barPadding + 5;\n }\n let chartStr;\n switch (type) {\n case 2:\n chartStr = this.barChart(labels, data, textSize, barPadding, 'bar');\n break;\n case 3:\n chartStr = this.barChart(labels, data, textSize, barPadding, 'line');\n break;\n default:\n chartStr = this.lineChart(labels, data, textSize, linePadding);\n }\n const url = `https:\/\/quickchart.io\/chart?w=${400}&h=${this.chartSetting.height}&f=png&c=${encodeURIComponent(chartStr)}`;\n const chart = await this.getImageByUrl(url, cacheKey, this.cacheChart);\n\n const chartStack = stack.addStack();\n const chartImage = chartStack.addImage(chart);\n const beanDateStack = stack.addStack();\n let showDays = data.length;\n for (let i = 0; i < showDays; i++) {\n beanDateStack.addSpacer();\n let subStack = beanDateStack.addStack();\n let beanDay = beanDateStack.addText(`${labels[i]}${this.chartSetting.dayText}`);\n beanDay.textColor = this.widgetColor;\n beanDay.font = new Font('ArialMT', this.chartSetting.daySize * this.basicSetting.scale);\n beanDay.textOpacity = 0.8;\n beanDateStack.addSpacer();\n }\n }\n\n \/\/ #####################物流信息###################\n setPackageShow(stack) {\n const packageStack = stack.addStack();\n const detailStack = packageStack.addStack();\n detailStack.layoutVertically();\n const titleStack = detailStack.addStack();\n titleStack.centerAlignContent();\n const title = titleStack.addText(this.package.title);\n title.lineLimit = 1;\n title.font = Font.mediumSystemFont(12 * this.basicSetting.scale);\n detailStack.addSpacer(2 * this.basicSetting.scale);\n const desc = detailStack.addText(this.package.desc);\n desc.lineLimit = 3;\n desc.font = Font.regularSystemFont(12 * this.basicSetting.scale);\n detailStack.addSpacer(2 * this.basicSetting.scale);\n const statusStack = detailStack.addStack();\n const time = statusStack.addText(this.package.time);\n statusStack.addSpacer();\n const status = statusStack.addText(this.package.status);\n ;[title, desc, time, status].map(t => t.textColor = this.widgetColor);\n ;[time, status].map(t => t.font = Font.regularSystemFont(9 * this.basicSetting.scale));\n ;[time, status].map(t => t.textOpacity = 0.7);\n }\n\n \/\/ #####################金贴&钢镚##################\n async setCoinShow(stack, vertical = false) {\n await this.getExtraData();\n const extraDataStack = stack.addStack();\n const jtImage = await this.getImageByUrl(this.jingtieImg, 'jtImage.png');\n const gbImage = await this.getImageByUrl(this.gangbengImg, 'gbImage.png');\n const dataStack = extraDataStack.addStack();\n if (vertical) dataStack.layoutVertically();\n this.rowCell(dataStack, jtImage, this.extra.jingtie.toString(), '金贴');\n if (vertical) extraDataStack.addSpacer(5 * this.basicSetting.scale);\n if (!vertical) dataStack.addSpacer(20 * this.basicSetting.scale);\n this.rowCell(dataStack, gbImage, this.extra.gangbeng.toString(), '钢镚');\n }\n\n \/\/ #####################京东红包##################\n async setRedPackageShow(stack, small = false) {\n await this.getRedPackageData();\n const walletImage = await this.getImageByUrl(this.walletImg, 'walletImage.png');\n small ? this.rowSmallWalletCell(stack, walletImage, this.redPackage) : this.rowWalletCell(stack, walletImage, this.redPackage);\n }\n\n \/\/ #####################京东白条##################\n async setBaitiaoShow(stack, small = false) {\n const baitiaoImage = await this.getImageByUrl(this.baitiaoImg, 'baitiaoImage.png');\n small ? this.rowSmallWalletCell(stack, baitiaoImage, this.baitiao) : this.rowWalletCell(stack, baitiaoImage, this.baitiao);\n }\n\n rowCell(stack, image, value, title) {\n const rowStack = stack.addStack();\n rowStack.centerAlignContent();\n const rowImage = rowStack.addImage(image);\n rowImage.imageSize = new Size(13 * this.basicSetting.scale, 13 * this.basicSetting.scale);\n rowStack.addSpacer();\n const rowValue = rowStack.addText(value);\n rowValue.font = Font.mediumSystemFont(15 * this.basicSetting.scale);\n rowStack.addSpacer();\n const rowTitle = rowStack.addText(title);\n rowTitle.font = Font.regularSystemFont(13 * this.basicSetting.scale);\n ;[rowValue, rowTitle].map(t => t.textColor = this.widgetColor);\n }\n\n rowBeanCell(stack, min, add, textSize, label) {\n const rowOne = stack.addStack();\n const labelText = rowOne.addText(label);\n labelText.font = Font.regularSystemFont(10 * this.basicSetting.scale);\n labelText.textOpacity = 0.7;\n const rowTwo = stack.addStack();\n const rowNumber = rowTwo.addText(add);\n rowNumber.font = Font.lightSystemFont(textSize);\n if (min < 0) {\n const rowThree = stack.addStack();\n const minText = rowThree.addText(min);\n minText.font = Font.mediumSystemFont(10 * this.basicSetting.scale);\n minText.textColor = new Color('fa2d19'); \/\/ 支出京豆颜色\n }\n ;[labelText, rowNumber].map(t => t.textColor = this.widgetColor);\n }\n\n rowWalletCell(stack, image, data) {\n const stackOne = stack.addStack();\n stackOne.centerAlignContent();\n const stackImage = stackOne.addImage(image);\n stackImage.imageSize = new Size(127 * 0.17 * this.basicSetting.scale, 75 * 0.17 * this.basicSetting.scale);\n stackOne.addSpacer(5 * this.basicSetting.scale);\n const title = stackOne.addText(data.title);\n title.font = Font.regularSystemFont(13 * this.basicSetting.scale);\n stackOne.addSpacer();\n const number = stackOne.addText(`${data.number}`);\n number.font = Font.mediumSystemFont(15 * this.basicSetting.scale);\n stackOne.addSpacer();\n const desc = stackOne.addText(data.desc);\n desc.font = Font.regularSystemFont(10 * this.basicSetting.scale);\n desc.textOpacity = 0.7;\n ;[title, number, desc].map(t => t.textColor = this.widgetColor);\n }\n\n rowSmallWalletCell(stack, image, data) {\n const stackOne = stack.addStack();\n stackOne.centerAlignContent();\n const stackImage = stackOne.addImage(image);\n stackImage.imageSize = new Size(127 * 0.17 * this.basicSetting.scale, 75 * 0.17 * this.basicSetting.scale);\n stackOne.addSpacer();\n const number = stackOne.addText(`${data.number}`);\n number.font = Font.mediumSystemFont(15 * this.basicSetting.scale);\n stack.addSpacer(5 * this.basicSetting.scale);\n const stackTwo = stack.addStack();\n stackTwo.centerAlignContent();\n const title = stackTwo.addText(data.title);\n title.font = Font.regularSystemFont(13 * this.basicSetting.scale);\n stackTwo.addSpacer();\n const desc = stackTwo.addText(data.desc);\n desc.font = Font.regularSystemFont(10 * this.basicSetting.scale);\n desc.textOpacity = 0.7;\n ;[number, title, desc].map(t => t.textColor = this.widgetColor);\n }\n\n init = async () => {\n try {\n let beanCacheKey = `beanData${this.isSmall()}_${this.userName}`;\n let beanCacheData = !this.loadStringCache(beanCacheKey) ? {} : JSON.parse(this.loadStringCache(beanCacheKey));\n let beanCache = beanCacheData.data ? beanCacheData.data.assetInfo.beanNum : 0;\n await this.TotalBean();\n await this.getJValue();\n console.log(`京豆数据:${beanCache}`);\n console.log(`京豆数据:${this.beanCount}`);\n\n if (!this.cookie) return;\n if (Keychain.contains(this.CACHE_KEY)) {\n this.rangeTimer = JSON.parse(Keychain.get(this.CACHE_KEY));\n if (this.rangeTimer.hasOwnProperty(this.today) && beanCache !== 0 && beanCache == this.beanCount) {\n this.cacheChart = this.funcSetting.alwaysRefreshChart ==='打开' ? false : true;\n console.log('京豆数据:无变化,使用缓存数据');\n return;\n }\n\n this.rangeTimer[this.today] = [0, 0];\n const timerKeys = Object.keys(this.rangeTimer);\n if (timerKeys.length > this.maxDays) {\n for (let i = 0; i < timerKeys.length - this.maxDays; i++) {\n delete this.rangeTimer[timerKeys[i]];\n }\n Keychain.set(this.CACHE_KEY, JSON.stringify(this.rangeTimer));\n }\n\n this.timerKeys = [this.today];\n } else {\n this.rangeTimer = this.getDay(5);\n this.timerKeys = Object.keys(this.rangeTimer);\n }\n await this.getAmountData();\n } catch (e) {\n console.log(e);\n }\n };\n\n getAmountData = async () => {\n let i = 0,\n page = 1;\n do {\n const response = await this.getJingBeanBalanceDetail(page);\n const result = response.code === '0';\n console.log(`第${page}页:${result ? '请求成功' : '请求失败'}`);\n if (response.code === '3') {\n i = 1;\n \/\/ this.notify(this.name, response.message)\n console.log(response);\n }\n if (response && result) {\n page++;\n let detailList = response.jingDetailList;\n if (detailList && detailList.length > 0) {\n for (let item of detailList) {\n const dates = item.date.split(' ');\n if (this.timerKeys.indexOf(dates[0]) > -1) {\n const amount = Number(item.amount);\n this.rangeTimer[dates[0]][0] += amount;\n if (amount < 0)\n this.rangeTimer[dates[0]][1] += amount;\n } else {\n i = 1;\n Keychain.set(this.CACHE_KEY, JSON.stringify(this.rangeTimer));\n break;\n }\n }\n }\n }\n } while (i === 0);\n }\n\n getDay(dayNumber) {\n let data = {};\n let i = dayNumber;\n do {\n const today = new Date();\n const year = today.getFullYear();\n const targetday_milliseconds = today.getTime() - 1000 * 60 * 60 * 24 * i;\n today.setTime(targetday_milliseconds);\n let month = today.getMonth() + 1;\n month = month >= 10 ? month : `0${month}`;\n let day = today.getDate();\n day = day >= 10 ? day : `0${day}`;\n data[`${year}-${month}-${day}`] = [0, 0];\n i--;\n } while (i >= 0);\n return data;\n }\n\n TotalBean = async () => {\n const dataName = '京豆数据';\n let userCache = `beanData${this.isSmall()}`;\n const url = 'https:\/\/me-api.jd.com\/user_new\/info\/GetJDUserInfoUnion?isLogin=1';\n const options = {\n headers: {\n cookie: this.cookie,\n },\n };\n const response = await this.httpRequest(dataName, url, true, options, userCache);\n try {\n if (response.retcode === '0' && response['data']) {\n this.beanCount = response.data.assetInfo.beanNum;\n this.userImage = response.data.userInfo.baseInfo.headImageUrl.replace(\/big\/, 'mid') || 'https:\/\/img11.360buyimg.com\/jdphoto\/s120x120_jfs\/t21160\/90\/706848746\/2813\/d1060df5\/5b163ef9N4a3d7aa6.png';\n this.nickName = response.data.userInfo.baseInfo.nickname;\n this.isPlus = response.data.userInfo.isPlusVip === '1' ? true : true;\n } else {\n this.notify(this.name, response.msg);\n console.log('京豆数据:获取失败,' + response.msg)\n }\n } catch (e) {\n console.log(e);\n console.log('京豆数据:获取失败,')\n }\n }\n\n wxData = async () => {\n const dataName = '微信数据';\n let userCache = `wxData${this.isSmall()}`;\n const url = 'https:\/\/wxapp.m.jd.com\/kwxhome\/myJd\/home.json?&useGuideModule=0&bizId=&brandId=&fromType=wxapp&isLogin=1';\n const options = {\n headers: {\n cookie: this.cookie,\n },\n };\n const response = await this.httpRequest(dataName, url, true, options, userCache);\n try {\n if (response['user']) {\n this.jValue = response.user.uclass.replace(\/[^0-9]\/ig, '');\n } else {\n \/\/ this.notify(this.name, response.msg);\n console.log('微信数据:获取失败,' + response.msg)\n }\n } catch (e) {\n console.log(e);\n }\n }\n\n getJingBeanBalanceDetail = async (page) => {\n try {\n const options = {\n url: `https:\/\/bean.m.jd.com\/beanDetail\/detail.json`,\n body: `page=${page}`,\n headers: {\n 'X-Requested-With': `XMLHttpRequest`,\n Connection: `keep-alive`,\n 'Accept-Encoding': `gzip, deflate, br`,\n 'Content-Type': `application\/x-www-form-urlencoded; charset=UTF-8`,\n Origin: `https:\/\/bean.m.jd.com`,\n 'User-Agent': `Mozilla\/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit\/605.1.15 (KHTML, like Gecko) Version\/14.0.1 Safari\/605.1.15`,\n Cookie: this.cookie,\n Host: `bean.m.jd.com`,\n Referer: `https:\/\/bean.m.jd.com\/beanDetail\/index.action?resourceValue=bean`,\n 'Accept-Language': `zh-cn`,\n Accept: `application\/json, text\/javascript, *\/*; q=0.01`,\n },\n };\n let params = {...options, method: 'POST'};\n let request = new Request(params.url);\n Object.keys(params).forEach((key) => {\n request[key] = params[key];\n });\n return await request.loadJSON();\n } catch (e) {\n console.log(e);\n }\n }\n\n getExtraData = async () => {\n const JTDataName = '金贴数据';\n const JTUrl = 'https:\/\/ms.jr.jd.com\/gw\/generic\/uc\/h5\/m\/mySubsidyBalance';\n const GBDataName = '钢镚数据';\n const GBUrl = 'https:\/\/coin.jd.com\/m\/gb\/getBaseInfo.html';\n const options = {\n headers: {\n cookie: this.cookie,\n Referer: 'https:\/\/home.m.jd.com\/myJd\/newhome.action?sceneval=2&ufc=&',\n },\n };\n try {\n const JTData = await this.httpRequest(JTDataName, JTUrl, true, options, 'jintieData');\n const GBData = await this.httpRequest(GBDataName, GBUrl, true, options, 'gangbengData');\n if (JTData.resultCode === 0) {\n this.extra.jingtie = JTData.resultData.data['balance'];\n } else {\n \/\/ this.notify(this.name, JTdata.resultMsg);\n console.log('金贴数据:获取失败,' + JTdata.resultMsg);\n };\n if (GBData.gbBalance) this.extra.gangbeng = GBData.gbBalance;\n } catch(e) {\n console.log(e);\n }\n }\n\n getPackageData = async () => {\n const dataName = '包裹数据';\n const url ='https:\/\/wq.jd.com\/bases\/wuliudetail\/notify?sceneval=2&sceneval=2&g_login_type=1&callback';\n const options = {\n headers: {\n cookie: this.cookie,\n Referer: 'https:\/\/home.m.jd.com\/myJd\/newhome.action?sceneval=2&ufc=&',\n },\n };\n try {\n const data = await this.httpRequest(dataName, url, true, options, 'packageData');\n if (data.errCode == 0 && data['dealLogList']) {\n console.log('包裹数据:获取成功');\n console.log(`包裹数据:您有${data['dealLogList'].length}个包裹`);\n if (data['dealLogList'].length > 0) {\n let item = data.dealLogList[Math.floor(Math.random() * data['dealLogList'].length)]\n this.package.number = data.dealLogList.length;\n this.package.title = item['name'];\n this.package.desc = item['wlStateDesc'];\n this.package.time = item['createTime'];\n this.package.status = item['stateName'];\n }\n } else {\n console.log('包裹数据:获取失败');\n } \n } catch (e) {\n console.log(e);\n }\n }\n\n getRedPackageData = async () => {\n const dataName = '红包数据';\n const url =\n 'https:\/\/wq.jd.com\/user\/info\/QueryUserRedEnvelopesV2?type=1&orgFlag=JD_PinGou_New&page=1&cashRedType=1&redBalanceFlag=1&channel=3&sceneval=2&g_login_type=1';\n const options = {\n headers: {\n cookie: this.cookie,\n Referer: 'https:\/\/home.m.jd.com\/myJd\/newhome.action?sceneval=2&ufc=&',\n },\n };\n try {\n const data = await this.httpRequest(dataName, url, true, options, 'redPackageData');\n if (data.errcode === 0) {\n this.redPackage.number = data.data.balance ? data.data.balance : 0;\n if (data.data.expiredBalance && data.data.expiredBalance !== '') this.redPackage.desc = `即将过期${data.data.expiredBalance}`+\"元\";\n } else {\n \/\/ this.notify(this.name, data.msg);\n console.log('红包数据:获取失败,' + data.msg);\n }\n } catch (e) {\n console.log(e);\n }\n }\n\n getJValue = async () => {\n const dataName = '京享数据';\n const url = \"https:\/\/api.m.jd.com\/?functionId=pg_channel_page_data&appid=vip_h5&body=%7BparamData:%7Btoken:%20'a243ca12-6642-4754-bc5e-0ff012681710'%7D%7D\";\n const options = {\n headers: {\n cookie: this.cookie,\n },\n };\n try {\n const data = await this.httpRequest(dataName, url, true, options, 'JValue');\n if (data['success'] === true) {\n this.jValue = data.data.floorInfoList[1].floorData.userInfo.score\n;\n } else {\n console.log('京享数据:获取失败');\n };\n } catch (e) {\n console.log(e);\n }\n }\n\n getBaitiaoData = async () => {\n const dataName = '白条数据';\n const url = 'https:\/\/ms.jr.jd.com\/gw\/generic\/bt\/h5\/m\/firstScreenNew';\n const options = {\n body: 'reqData={\"clientType\":\"ios\",\"clientVersion\":\"13.2.3\",\"deviceId\":\"\",\"environment\":\"3\"}',\n headers: {\n cookie: this.cookie,\n },\n };\n try {\n const data = await this.httpRequest(dataName, url, true, options, 'baitiaoData', 'POST', false);\n if (data.resultCode !== 0) {\n \/\/ this.notify(this.name, data['resultMsg']);\n return\n }\n this.baitiao.title = data['resultData']['data']['bill']['title'];\n this.baitiao.number = data['resultData']['data']['bill']['amount'].replace(\/,\/g, '');\n this.baitiao.desc = data['resultData']['data']['bill']['buttonName'].replace(\/最近还款日\/, '');\n } catch (e) {\n console.log(e);\n }\n }\n\n getFruitData = async () => {\n const dataName = '东东农场';\n const url = 'https:\/\/api.m.jd.com\/client.action?functionId=initForFarm';\n const options = {\n body: 'body=version:4&appid=wh5&clientVersion=9.1.0',\n headers: {\n 'User-Agent': 'jdapp;iPhone;9.2.2;14.2;%E4%BA%AC%E4%B8%9C\/9.2.2 CFNetwork\/1206 Darwin\/20.1.0',\n 'Content-Type': 'application\/x-www-form-urlencoded',\n 'cookie': this.cookie,\n },\n };\n try {\n const data = await this.httpRequest(dataName, url, true, options, 'FruitData', 'POST', false);\n if (data.msg && data.msg == 'not login') {\n this.fruitState = \"X\";\n }\n else if (data.farmUserPro.treeState == 2 || data.farmUserPro.treeState == 3) {\n this.fruitState = \"100\";\n }\n else if (data.farmUserPro.treeState == 0) {\n this.fruitState = \"X\";\n }\n else {\n this.fruitState = Math.floor((data.farmUserPro.treeEnergy \/ data.farmUserPro.treeTotalEnergy) * 100).toString();\n }\n } catch (e) {\n console.log(e);\n }\n }\n \n getImageByUrl = async(url, cacheKey, useCache = true, logable = true) => {\n if (this.CACHES.indexOf(cacheKey) < 0) {\n this.CACHES.push(cacheKey);\n this.settings.CACHES = this.CACHES;\n this.saveSettings(false);\n }\n if (useCache) {\n const cacheImg = this.loadImgCache(cacheKey);\n if (cacheImg != undefined && cacheImg != null) {\n if (logable) console.log(`使用缓存:${cacheKey}`);\n return this.loadImgCache(cacheKey);\n }\n }\n\n try {\n if (logable) console.log(`在线请求:${cacheKey}`);\n const req = new Request(url);\n const imgData = await req.load();\n const img = Image.fromData(imgData);\n this.saveImgCache(cacheKey, img);\n return img;\n } catch (e) {\n console.error(`图片加载失败:${e}`);\n let cacheImg = this.loadImgCache(cacheKey);\n if (cacheImg != undefined) {\n console.log(`使用缓存图片:${cacheKey}`);\n return cacheImg;\n }\n console.log(`使用预设图片`);\n let ctx = new DrawContext();\n ctx.size = new Size(80, 80);\n ctx.setFillColor(Color.darkGray());\n ctx.fillRect(new Rect(0, 0, 80, 80));\n return await ctx.getImage();\n }\n }\n\n saveImgCache(cacheKey, img) {\n if (!this.fm.fileExists(this.cachePath)) {\n this.fm.createDirectory(this.cachePath, true);\n };\n const cacheFile = this.fm.joinPath(this.cachePath, cacheKey);\n this.fm.writeImage(cacheFile, img);\n }\n\n loadImgCache(cacheKey) {\n const cacheFile = this.fm.joinPath(this.cachePath, cacheKey);\n const fileExists = this.fm.fileExists(cacheFile);\n let img = undefined;\n if (fileExists) {\n img = Image.fromFile(cacheFile);\n }\n return img;\n }\n\n httpRequest = async(dataName, url, json = true, options, key, method = 'GET', logable = this.funcSetting.logable === '打开') => {\n let cacheKey = `${key}_${this.userName}`;\n if (this.CACHES.indexOf(cacheKey) < 0) {\n this.CACHES.push(cacheKey);\n this.settings.CACHES = this.CACHES;\n this.saveSettings(false);\n }\n let localCache = this.loadStringCache(cacheKey);\n const lastCacheTime = this.getCacheModificationDate(cacheKey);\n const timeInterval = Math.floor((this.getCurrentTimeStamp() - lastCacheTime) \/ 60);\n \n console.log(`${dataName}:缓存${timeInterval}分钟前,有效期${this.basicSetting.interval}分钟,${localCache.length}`);\n\n if (timeInterval < this.basicSetting.interval && localCache != null && localCache.length > 0) {\n console.log(`${dataName}:读取缓存`);\n return json ? JSON.parse(localCache) : localCache;\n }\n\n let data = null;\n try {\n console.log(`${dataName}:在线请求`);\n let req = new Request(url);\n req.method = method;\n Object.keys(options).forEach((key) => {\n req[key] = options[key];\n });\n data = await (json ? req.loadJSON() : req.loadString());\n if (\n data.errCode === '0' ||\n data.msg === 'success' ||\n data.resultCode === 0\n ) {\n this.saveStringCache(cacheKey, json ? JSON.stringify(data) : data)\n }\n } catch (e) {\n console.error(`${dataName}:请求失败:${e}`);\n }\n\n localCache = this.loadStringCache(cacheKey);\n\n if (!data && localCache != null && localCache.length > 0) {\n console.log(`${dataName}:获取失败,读取缓存`);\n return json ? JSON.parse(localCache) : localCache;\n }\n \n if (logable) {\n console.log(`${dataName}:在线请求响应数据:${JSON.stringify(data)}`);\n }\n return data;\n }\n\n loadStringCache(cacheKey) {\n const cacheFile = this.fm.joinPath(this.cachePath, cacheKey);\n const fileExists = this.fm.fileExists(cacheFile);\n let cacheString = '';\n if (fileExists) {\n cacheString = this.fm.readString(cacheFile);\n }\n return cacheString;\n }\n\n saveStringCache(cacheKey, content) {\n if (!this.fm.fileExists(this.cachePath)) {\n this.fm.createDirectory(this.cachePath, true);\n };\n const cacheFile = this.fm.joinPath(this.cachePath, cacheKey);\n this.fm.writeString(cacheFile, content);\n }\n\n getCacheModificationDate(cacheKey) {\n const cacheFile = this.fm.joinPath(this.cachePath, cacheKey);\n const fileExists = this.fm.fileExists(cacheFile);\n if (fileExists) {\n return this.fm.modificationDate(cacheFile).getTime() \/ 1000;\n } else {\n return 0;\n }\n }\n\n getCurrentTimeStamp() {\n return new Date().getTime() \/ 1000;\n }\n\n timeFormat(time) {\n let date;\n if (time) {\n date = new Date(time);\n } else {\n date = new Date();\n }\n return ((date.getMonth() + 1) >= 10 ? (date.getMonth() + 1) : '0' + (date.getMonth() + 1)) + '月' + (date.getDate() >= 10 ? date.getDate() : '0' + date.getDate()) + '日';\n }\n\n async updateCheck(version){\n let data;\n try {\n let updateCheck = new Request('https:\/\/raw.githubusercontent.com\/anker1209\/Scriptable\/main\/upcoming.json');\n data = await updateCheck.loadJSON();\n if (data.version != version) {\n let updata = new Alert();\n updata.title = `有新版 ${data.version} 可用`;\n updata.addAction('去Github更新');\n updata.addAction('网页版商店更新');\n updata.addCancelAction('稍后');\n updata.message = '\\n更新说明:\\n' + data.notes + '\\n\\n点击相应按钮更新脚本';\n let id = await updata.present();\n if (id == 0) {\n Safari.openInApp('https:\/\/raw.githubusercontent.com\/anker1209\/Scriptable\/main\/scripts\/JD-in-one-v2.js');\n } else if (id == 1) {\n Safari.openInApp('http:\/\/scriptablejs.gitee.io\/store\/#\/menu\/myInfo');\n } else {\n return;\n }\n } else {\n let updata = new Alert();\n updata.title = '暂无更新';\n updata.addCancelAction('好的');\n updata.message = `\\n当前版本 ${version} 为最新版本`;\n await updata.present();\n }\n } catch(e) {\n console.log(e);\n }\n }\n\n async faqTable() {\n const table = new UITable();\n table.showSeparators = false;\n let data;\n try {\n let faq = new Request('https:\/\/raw.githubusercontent.com\/anker1209\/Scriptable\/main\/faq.json');\n data = await faq.loadJSON();\n let info = new UITableRow();\n info.height = parseFloat(data.height);\n let desc = info.addText(data.update, data.desc);\n desc.subtitleColor = Color.blue();\n desc.titleFont = Font.mediumSystemFont(14);\n desc.subtitleFont = Font.systemFont(14);\n table.addRow(info);\n for (let i = 0; i < data.data.length; i++) {\n let header = new UITableRow();\n header.backgroundColor = Color.dynamic(new Color('F5F5F5'), new Color('000000'));;\n let heading = header.addText(data.data[i].name)\n heading.titleFont = Font.mediumSystemFont(17);\n heading.centerAligned();\n table.addRow(header);\n data.data[i].item.forEach((faq) => {\n let row = new UITableRow();\n row.height = parseFloat(faq['height']);\n let rowtext = row.addText(faq['question'], faq['answer']);\n rowtext.titleFont = Font.mediumSystemFont(16);\n rowtext.titleColor = Color.blue();\n rowtext.subtitleFont = Font.systemFont(14);\n rowtext.subtitleColor = Color.dynamic(new Color('000000', 0.7), new Color('ffffff', 0.7));\n table.addRow(row);\n });\n }\n } catch (e) {\n console.log(e);\n }\n await table.present();\n }\n\n async settingCategory(table, item, outfit, category) {\n let header = new UITableRow();\n let heading = header.addText(outfit)\n heading.titleFont = Font.mediumSystemFont(17);\n heading.centerAligned();\n table.addRow(header);\n item.forEach((data) => {\n Object.keys(data.option).forEach((key) => {\n let row = new UITableRow();\n let rowIcon = row.addImageAtURL(data['icon']);\n rowIcon.widthWeight = 100;\n let rowtext = row.addText(data['title']);\n rowtext.widthWeight = 400;\n let rowNumber = row.addText(`${this.settings[category][key]} >`);\n rowNumber.widthWeight = 500;\n rowNumber.rightAligned();\n rowNumber.titleColor = Color.gray();\n rowNumber.titleFont = Font.systemFont(16);\n rowtext.titleFont = Font.systemFont(16);\n row.dismissOnSelect = false;\n row.onSelect = async () => {\n if (data.type == 'text') {\n await this.alertInput(data['title'], data['desc'], category, data['option']);\n } else if (data.type == 'menu') {\n await this.showAlert(data['title'], data['desc'], data['menu'], category, key,);\n }\n await this.tableContent(table);\n }\n table.addRow(row);\n });\n });\n table.reload();\n }\n\n async tableContent(table) {\n const basic = [\n {type: 'text', title: '全局缩放比例', desc: '排版溢出、显示不全的请优先调低此数,建议递减0.05调整,如0.95、0.90……\\n\\n缺省值:1.00', option: {scale: ''}, icon: 'https:\/\/pic1.imgdb.cn\/item\/63315c3116f2c2beb1a28cfd.png'},\n {type: 'text', title: '京东标志大小', desc: '京东logo(形象狗)大小\\n\\n缺省值:30', option: {logo: ''}, icon: 'https:\/\/pic1.imgdb.cn\/item\/63315c2c16f2c2beb1a286f1.png'},\n {type: 'text', title: '用户头像大小', desc: '⚠️注意:若要修改头像,请在京东app上传后将缓存清除再运行脚本。\\n\\n缺省值:69', option: {userImage: ''}, icon: 'https:\/\/pic1.imgdb.cn\/item\/63315c3a16f2c2beb1a29a07.png'},\n {type: 'text', title: '左侧栏宽度', desc: '左侧用户信息栏整体宽度\\n\\n缺省值:103', option: {userStack: ''}, icon: 'https:\/\/pic1.imgdb.cn\/item\/63315c3a16f2c2beb1a29a1d.png'},\n {type: 'text', title: '左右栏间距', desc: '左侧用户信息栏与右侧京豆数据间距\\n\\n缺省值:25', option: {division: ''}, icon: 'https:\/\/pic1.imgdb.cn\/item\/63315c2216f2c2beb1a27870.png'},\n {type: 'text', title: '缓存时间', desc: '数据请求间隔时间\\n请设置合适时间,避免频繁访问接口数据以及加载缓慢。单位:分钟\\n\\n缺省值:10', option: {interval: ''}, icon: 'https:\/\/pic1.imgdb.cn\/item\/63315c2716f2c2beb1a27f10.png'},\n {type: 'menu', title: '缓存位置', desc: '将缓存保存在Local或者iCloud。\\n\\n缺省值:Local', option: {directory: ''}, menu: ['Local', 'iCloud'], icon: 'https:\/\/pic1.imgdb.cn\/item\/63315c2216f2c2beb1a27868.png'},\n {type: 'text', title: '自定义昵称', desc: '自定义用户信息栏的昵称名称,\\n留空将显示京东账号昵称。\\n\\n注意:单脚本多账户若使用自定义昵称,所有账户将同时显示此昵称,如需单独自定义昵称,请复制脚本单独设置。', option: {customizeName: ''}, icon: 'https:\/\/pic1.imgdb.cn\/item\/63315c1e16f2c2beb1a2734a.png'},\n {type: 'text', title: '自定义头像', desc: '自定义用户信息栏的头像,\\n留空将显示京东APP头像。\\n\\n注意:单脚本多账户若使用自定义头像,所有账户将同时显示此头像,如需单独自定义头像,请复制脚本单独设置。', option: {customizeAvatar: ''}, icon: 'https:\/\/pic1.imgdb.cn\/item\/63315c1e16f2c2beb1a27341.png'},\n {type: 'menu', title: '小组件显示内容', desc: '\\n缺省值:京豆、钱包数据', option: {smallShowType: ''}, menu: ['京豆、钱包数据', '个人信息'], icon: 'https:\/\/pic1.imgdb.cn\/item\/63315c3616f2c2beb1a29323.png'},\n {type: 'menu', title: '钱包显示类型', desc: '若要显示钱包内容,白条需关闭或者白条打开的情况下无待还白条。\\n\\n缺省值:红包', option: {walletShowType: ''}, menu: ['红包', '钢镚和金贴'], icon: 'https:\/\/pic1.imgdb.cn\/item\/63315c3a16f2c2beb1a299f3.png'},\n ];\n const chart = [\n {type: 'text', title: '图表高度', desc: '京豆数据未与日期对齐的,\\n请调低此数值\\n\\n⚠️如需即时查看调整效果,\\n[功能设置]-->刷新图表 需打开。\\n\\n缺省值:130', option: {height: ''}, icon: 'https:\/\/pic1.imgdb.cn\/item\/63315c2216f2c2beb1a27858.png'},\n {type: 'text', title: '日期文字大小', desc: '京豆图表底部日期文字大小\\n\\n缺省值:9', option: {daySize: ''}, icon: 'https:\/\/pic1.imgdb.cn\/item\/63315c1e16f2c2beb1a27355.png'},\n {type: 'text', title: '日期文字后缀', desc: '京豆图表底部日期文字后缀', option: {dayText: ''}, icon: 'https:\/\/pic1.imgdb.cn\/item\/63315c2216f2c2beb1a2785e.png'},\n {type: 'text', title: '京豆数文字大小', desc: '京豆图表数据文字大小\\n\\n⚠️如需即时查看调整效果,\\n[功能设置]-->刷新图表 需打开。\\n\\n缺省值:18', option: {textSize: ''}, icon: 'https:\/\/pic1.imgdb.cn\/item\/63315c3a16f2c2beb1a29a00.png'},\n {type: 'text', title: '京豆数白天颜色', desc: '⚠️如需即时查看调整效果,\\n[功能设置]-->刷新图表 需打开。\\n\\n缺省值:999999', option: {textDayColor: ''}, icon: 'https:\/\/pic1.imgdb.cn\/item\/63315c3616f2c2beb1a29310.png'},\n {type: 'text', title: '京豆数晚上颜色', desc: '⚠️如需即时查看调整效果,\\n[功能设置]-->刷新图表 需打开。\\n\\n缺省值:999999', option: {textNightColor: ''}, icon: 'https:\/\/pic1.imgdb.cn\/item\/63315c3a16f2c2beb1a299f8.png'},\n {type: 'text', title: '折线图线条颜色', desc: '支持渐变色,每个颜色之间以英文逗号分隔,颜色值必须带“#”。\\n\\n缺省值:#FA6859', option: {lineColor: ''}, icon: 'https:\/\/pic1.imgdb.cn\/item\/63315c2716f2c2beb1a27f2e.png'},\n {type: 'text', title: '折线图表顶边距', desc: '京豆折线图顶边距\\n京豆数据在顶部被剪切显示不全的,\\n请调高此数值。\\n\\n⚠️如需即时查看调整效果,\\n[功能设置]-->刷新图表 需打开。\\n\\n缺省值:15', option: {linePadding: ''}, icon: 'https:\/\/pic1.imgdb.cn\/item\/63315c2716f2c2beb1a27f3a.png'},\n {type: 'text', title: '柱状图表顶边距', desc: '京豆柱状图和曲线面积图顶边距\\n京豆数据在顶部被剪切显示不全的,\\n请调高此数值。\\n\\n⚠️如需即时查看调整效果,\\n[功能设置]-->刷新图表 需打开。\\n\\n缺省值:5', option: {barPadding: ''}, icon: 'https:\/\/pic1.imgdb.cn\/item\/63315c0816f2c2beb1a25263.png'},\n {type: 'menu', title: '小组件图表类型', desc: '\\n缺省值:双日视图', option: {smallShowType: ''}, menu: ['双日视图', '折线图表', '柱状图表', '曲线面积图'], icon: 'https:\/\/pic1.imgdb.cn\/item\/63315c3616f2c2beb1a29330.png'},\n {type: 'menu', title: '中组件图表类型', desc: '\\n缺省值:双日视图', option: {showType: ''}, menu: ['双日视图', '折线图表', '柱状图表', '曲线面积图'], icon: 'https:\/\/pic1.imgdb.cn\/item\/63315c3616f2c2beb1a29315.png'},\n {type: 'menu', title: '每日京豆数计算', desc: '\\n缺省值:收入-支出', option: {countBean: ''}, menu: ['收入-支出', '收入'], icon: 'https:\/\/pic1.imgdb.cn\/item\/63315c1e16f2c2beb1a27376.png'},\n {type: 'menu', title: '多彩柱状图', desc: '设置为打开时仅对柱状图表生效\\n\\n缺省值:关闭', option: {colorful: ''}, menu: ['打开', '关闭'], icon: 'https:\/\/pic1.imgdb.cn\/item\/63315c0816f2c2beb1a2524a.png'},\n ];\n const func = [\n {type: 'menu', title: '白条信息', desc: '关闭或者打开后无待还白条的情况下,\\n会显示基础设置里选择的钱包内容。\\n\\n缺省值:打开', option: {showBaitiao: ''}, menu: ['打开', '关闭'], icon: 'https:\/\/pic1.imgdb.cn\/item\/63315c3116f2c2beb1a28d19.png'},\n {type: 'menu', title: '包裹信息', desc: '只有中组件显示一条物流信息,\\n若无物流信息会显示图表设置里选择的图表类型。\\n\\n缺省值:关闭', option: {showPackage: ''}, menu: ['打开', '关闭'], icon: 'https:\/\/pic1.imgdb.cn\/item\/63315c3016f2c2beb1a28cf8.png'},\n {type: 'menu', title: '农场进度', desc: '显示东东农场种植进度。\\n\\n缺省值:打开', option: {showFruit: ''}, menu: ['打开', '关闭'], icon: 'https:\/\/pic1.imgdb.cn\/item\/63315c3116f2c2beb1a28d24.png'},\n {type: 'menu', title: '运行日志', desc: '出现数据异常请将此值设为true,\\n查看运行日志。\\n\\n⚠️注意:\\n查看运行日志需将缓存时间更改为0。\\n\\n缺省值:关闭', option: {logable: ''}, menu: ['打开', '关闭'], icon: 'https:\/\/pic1.imgdb.cn\/item\/63315c2716f2c2beb1a27f0a.png'},\n {type: 'menu', title: '刷新图表', desc: '打开,每次刷新组件会随机刷新图表颜色(仅柱状图表和曲线面积图);关闭,则只有在京豆数据有变化的情况下刷新图表颜色及数据。建议在排版调整没有问题后,设置为关闭。设置为打开会加长数据载入时间。\\n\\n⚠️注意:图表设置选项里修改图表高度、颜色、文字大小、顶边距需打开此选项以查看即时反馈。\\n\\n缺省值:打开', option: {alwaysRefreshChart: ''}, menu: ['打开', '关闭'], icon: 'https:\/\/pic1.imgdb.cn\/item\/63315c0816f2c2beb1a25259.png'},\n ];\n table.removeAllRows();\n let topRow = new UITableRow();\n let leftText = topRow.addButton('教程');\n leftText.widthWeight = 0.25;\n leftText.onTap = async () => {\n await Safari.open('https:\/\/github.com\/anker1209\/Scriptable#jd_in_one');\n }\n let faqText = topRow.addButton('常见问题');\n faqText.widthWeight = 0.25;\n faqText.leftAligned();\n faqText.onTap = async () => {\n await this.faqTable();\n }\n let versionText = topRow.addButton('版本检测');\n versionText.widthWeight = 0.25;\n versionText.rightAligned();\n versionText.onTap = async () => {\n await this.updateCheck(this.version);\n }\n let rightText = topRow.addButton('电报群');\n rightText.widthWeight = 0.25;\n rightText.rightAligned();\n rightText.onTap = async () => {\n await Safari.open('https:\/\/t.me\/Scriptable_JS');\n }\n table.addRow(topRow);\n\n let header = new UITableRow();\n let heading = header.addText('重置设置')\n heading.titleFont = Font.mediumSystemFont(17);\n heading.centerAligned();\n table.addRow(header);\n let row1 = new UITableRow();\n let rowtext1 = row1.addText('重置缓存','若需要修改头像或数据显示错误,尝试此操作');\n rowtext1.titleFont = Font.systemFont(16);\n rowtext1.subtitleFont = Font.systemFont(12);\n rowtext1.subtitleColor = new Color('999999');\n row1.dismissOnSelect = false;\n row1.onSelect = async () => {\n const options = ['取消', '重置'];\n const message = '所有在线请求的数据缓存将会被清空';\n const index = await this.generateAlert(message, options);\n if (index === 0) return;\n this.fm.remove(this.cachePath);\n delete this.settings['CACHES'];\n this.saveSettings();\n }\n table.addRow(row1);\n let row2 = new UITableRow();\n let rowtext2 = row2.addText('重置京豆数据','若京豆数据缺失或显示有误,尝试此操作');\n rowtext2.titleFont = Font.systemFont(16);\n rowtext2.subtitleFont = Font.systemFont(12);\n rowtext2.subtitleColor = new Color('999999');\n row2.dismissOnSelect = false;\n row2.onSelect = async () => {\n const options = ['取消', '重置'];\n const message = '若缺少京豆数据或显示为0(双日视图或图表的京豆数)采用此操作。京豆数据重置后,将会重新抓取近6天的京豆明细。请勿频繁使用,会产生大量数据';\n const index = await this.generateAlert(message, options);\n if (index === 0) return;\n Keychain.remove(this.settings.CACHE_KEY);\n delete this.settings.CACHE_KEY;\n this.saveSettings();\n }\n table.addRow(row2);\n let row3 = new UITableRow();\n let rowtext3 = row3.addText('重置设置参数','设置参数绑定脚本文件名,请勿随意更改脚本文件名');\n rowtext3.titleFont = Font.systemFont(16);\n rowtext3.subtitleFont = Font.systemFont(12);\n rowtext3.subtitleColor = new Color('999999');\n row3.dismissOnSelect = false;\n row3.onSelect = async () => {\n const options = ['取消', '重置'];\n const message = '本菜单里的所有设置参数将会重置为默认值,重置后请重新打开设置菜单';\n const index = await this.generateAlert(message, options);\n if (index === 0) return;\n delete this.settings['basicSetting'];\n delete this.settings['chartSetting'];\n delete this.settings['funcSetting'];\n this.saveSettings();\n }\n table.addRow(row3);\n await this.settingCategory(table, basic, '基础设置', 'basicSetting');\n await this.settingCategory(table, chart, '图表设置', 'chartSetting');\n await this.settingCategory(table, func, '功能设置', 'funcSetting');\n }\n\n async editSettings() {\n const table = new UITable();\n table.showSeparators = true;\n await this.tableContent(table);\n await table.present(true);\n }\n\n alertInput = async (title, desc, category, opt = {}) => {\n const a = new Alert();\n a.title = title;\n a.message = !desc ? '' : desc;\n let key = Object.keys(opt)[0];\n a.addTextField(key, `${this.settings[category][key]}`);\n a.addAction('确定');\n a.addCancelAction('取消');\n const id = await a.presentAlert();\n if (id === -1) return;\n this.settings[category][key] = a.textFieldValue(0);\n this.saveSettings();\n };\n\n async showAlert(title, message, options, category, key) {\n let alert = new Alert();\n alert.title = title;\n alert.message = message;\n alert.addCancelAction('取消')\n for (const option of options) {\n alert.addAction(option);\n };\n let id = await alert.presentAlert();\n if (id === -1) return;\n this.settings[category][key] = options[id];\n this.saveSettings();\n }\n\n run = (filename, args) => {\n if(!this.settings.basicSetting) this.settings.basicSetting = this.basicSetting;\n Object.keys(this.basicSetting).forEach((key) => {\n if(!this.settings.basicSetting.hasOwnProperty(key))\n this.settings['basicSetting'][key] = this.basicSetting[key];\n });\n if(!this.settings.chartSetting) this.settings.chartSetting = this.chartSetting;\n Object.keys(this.chartSetting).forEach((key) => {\n if(!this.settings.chartSetting.hasOwnProperty(key))\n this.settings['chartSetting'][key] = this.chartSetting[key];\n });\n if(!this.settings.funcSetting) this.settings.funcSetting = this.funcSetting;\n Object.keys(this.funcSetting).forEach((key) => {\n if(!this.settings.funcSetting.hasOwnProperty(key))\n this.settings['funcSetting'][key] = this.funcSetting[key];\n });\n if(!this.settings.CACHES) this.settings.CACHES = [];\n this.CACHES = this.settings.CACHES;\n if (this.settings['basicSetting']['directory'] === 'iCloud') this.fm = FileManager.iCloud();\n this.cachePath = this.fm.joinPath(this.fm.documentsDirectory(), this.CACHE_FOLDER);\n\n if (config.runsInApp) {\n this.registerAction('参数配置', this.editSettings, 'https:\/\/raw.githubusercontent.com\/githubdulong\/Script\/master\/Images\/setting.png');\n this.registerAction('账号设置', async () => {\n const index = await this.generateAlert('设置账号信息', [\n '网站登录',\n '手动输入',\n ]);\n if (index === 0) {\n await this.jdWebView();\n } else {\n await this.setAlertInput('账号设置', '京东账号cookie\\n\\n⚠️\\n用户名和cookie必须输入!\\n多账号注意用户名不要重复!', {\n username: '用户名,必须输入!多账号勿重复!',\n cookie: 'Cookie',\n });\n }\n }, 'https:\/\/raw.githubusercontent.com\/githubdulong\/Script\/master\/Images\/account.png');\n this.registerAction('代理缓存', this.actionSettings, 'https:\/\/raw.githubusercontent.com\/githubdulong\/Script\/master\/Images\/boxjs.png');\n this.registerAction('基础设置', this.setWidgetConfig, 'https:\/\/raw.githubusercontent.com\/githubdulong\/Script\/master\/Images\/preferences.png');\n }\n Object.keys(this.settings['basicSetting']).forEach((key) => {\n if (key == 'customizeName' || key == 'customizeAvatar' || key == 'smallShowType' || key == 'walletShowType' || key == 'directory') {\n this.basicSetting[key] = this.settings['basicSetting'][key];\n } else if (!isNaN(this.settings['basicSetting'][key])) {\n this.basicSetting[key] = parseFloat(this.settings['basicSetting'][key]);\n }\n });\n Object.keys(this.settings['chartSetting']).forEach((key) => {\n if (key == 'textDayColor' || key == 'textNightColor' || key =='showType' || key == 'smallShowType' || key == 'countBean' || key == 'colorful' || key == 'lineColor' || key == 'dayText') {\n this.chartSetting[key] = this.settings['chartSetting'][key];\n } else if (!isNaN(this.settings['chartSetting'][key])) {\n this.chartSetting[key] = parseFloat(this.settings['chartSetting'][key]);\n }\n });\n Object.keys(this.settings['funcSetting']).forEach((key) => {\n this.funcSetting[key] = this.settings['funcSetting'][key];\n });\n\n \n };\n\n jdWebView = async () => {\n const webView = new WebView();\n const url =\n 'https:\/\/mcr.jd.com\/credit_home\/pages\/index.html?btPageType=BT&channelName=024';\n await webView.loadURL(url);\n await webView.present(true);\n const req = new Request(\n 'https:\/\/ms.jr.jd.com\/gw\/generic\/bt\/h5\/m\/firstScreenNew',\n );\n req.method = 'POST';\n req.body =\n 'reqData={\"clientType\":\"ios\",\"clientVersion\":\"13.2.3\",\"deviceId\":\"\",\"environment\":\"3\"}';\n await req.loadJSON();\n const cookies = req.response.cookies;\n const account = {username: '', cookie: ''};\n const cookie = [];\n cookies.forEach((item) => {\n const value = `${item.name}=${item.value}`;\n if (item.name === 'pt_key') cookie.push(value);\n if (item.name === 'pt_pin') {\n account.username = item.value;\n cookie.push(value);\n }\n });\n account.cookie = cookie.join('; ');\n console.log(account);\n\n if (account.cookie) {\n this.settings = {...this.settings, ...account};\n this.saveSettings(false);\n console.log(`${this.name}: cookie获取成功,请关闭窗口!`);\n this.notify(this.name, 'cookie获取成功,请关闭窗口!');\n }\n };\n\n _loadJDCk = async () => {\n try {\n this.CookiesData = await this.getCache('CookiesJD', false)\n if (this.CookiesData) {\n this.CookiesData = this.transforJSON(this.CookiesData)\n } else {\n throw \"未获取到数据\"\n }\n return true;\n } catch (e) {\n console.log(e);\n this.CookiesData = [];\n return false;\n }\n };\n\n async actionSettings() {\n try {\n const table = new UITable();\n if (!(await this._loadJDCk())) throw 'BoxJS 数据读取失败';\n \/\/ 如果是节点,则先远程获取\n this.settings.cookieData = this.CookiesData;\n this.saveSettings(false);\n this.CookiesData.map((t, index) => {\n const r = new UITableRow();\n r.addText(`parameter:${index} ${t.userName}`);\n r.onSelect = (n) => {\n this.settings.username = t.userName;\n this.settings.cookie = t.cookie;\n this.saveSettings();\n };\n table.addRow(r);\n });\n let body = '京东 Ck 缓存成功,根据下标选择相应的 Ck';\n if (this.settings.cookie) {\n body += ',或者使用当前选中Ck:' + this.settings.username;\n }\n this.notify(this.name, body);\n table.present(false);\n } catch (e) {\n console.log(e);\n await this.notify(\n `${this.name} - BoxJS 数据读取失败`,\n '请检查 BoxJS 域名是否为代理复写的域名,如(boxjs.net 或 boxjs.com)。\\n若没有配置 BoxJS 相关模块,请点击通知查看教程',\n 'https:\/\/chavyleung.gitbook.io\/boxjs\/awesome\/videos'\n )\n }\n }\n\n async getCookie() {\n this.JDindex = typeof args.widgetParameter === 'string'\n ? parseInt(args.widgetParameter)\n : false;\n let _md5 = this.md5(module.filename + this.en);\n if (this.funcSetting.logable === '打开') console.log('当前配置内容:' + JSON.stringify(this.settings));\n try {\n if (this.JDindex !== false && this.JDindex + 1 > 0) {\n \n if (!(await this._loadJDCk())) this.CookiesData = this.settings.cookieData\n \n this.cookie = this.CookiesData[this.JDindex]['cookie'];\n this.userName =this.CookiesData[this.JDindex][\"userName\"];\n } else {\n this.userName = this.settings.username;\n this.cookie = this.settings.cookie;\n }\n if (!this.cookie) throw \"京东 CK 获取失败\";\n this.userName = decodeURI(this.userName);\n this.CACHE_KEY = `cache_${_md5}_` + this.userName;\n this.settings.CACHE_KEY = this.CACHE_KEY;\n this.saveSettings(false);\n return true;\n } catch (e) {\n this.notify(\"错误提示\", e);\n return false;\n }\n }\n\n async render() {\n await this.getCookie();\n if (!this.cookie || !this.userName) {\n this.notify(this.name, 'cookie或用户名未设置');\n return;\n };\n await this.init();\n await this.getPackageData();\n if (this.funcSetting.showBaitiao === '打开') await this.getBaitiaoData();\n if (this.funcSetting.showFruit === '打开') await this.getFruitData();\n if (this.funcSetting.logable === '打开') console.log(this.rangeTimer);\n const widget = new ListWidget();\n const padding = 14 * this.basicSetting.scale;\n widget.setPadding(padding, padding, padding, padding);\n await this.getWidgetBackgroundImage(widget);\n if (this.widgetFamily === 'medium') {\n return await this.renderMedium(widget);\n } else if (this.widgetFamily === 'large') {\n return await this.renderLarge(widget);\n } else {\n return await this.renderSmall(widget);\n }\n }\n}\n\nawait Runing(Widget, '', false);\n\n\/\/version:2.2.9",
"share_sheet_inputs" : [
]
}