diff --git a/Env.js b/Env-lsp.js similarity index 59% rename from Env.js rename to Env-lsp.js index 57dfd76..1482827 100644 --- a/Env.js +++ b/Env-lsp.js @@ -1,4 +1,5 @@ // Variables used by Scriptable. +// This script was created by Max Zeryck. /* ----------------------------------------------- 这是一份模板,可以导入进行使用里面封装的方法变量,谨慎修改!! @@ -18,7 +19,7 @@ let configs = { leftPadding: 0, // 内容区边距 bottomPadding: 0, // 内容区边距 rightPadding: 0, // 内容区边距 - refreshInterval: 0 // 刷新间隔,单位分钟,非精准,会有3-5分钟差距 + refreshInterval: 1 // 刷新间隔,单位分钟,非精准,会有3-5分钟差距 } exports.configs = configs //------------------------------------------------ @@ -51,25 +52,58 @@ exports.imgStyle = textStyle - //------------------------------------------------ -exports.run = async function (scriptName, widget) { +exports.run = async function (scriptName, widget, autoDak = false, autoRun = true) { let appearance = (await exports.isUsingDarkAppearance()) ? 'dark' : 'light' let appearanceStr = appearance == 'dark' ? '暗黑模式' : '白天模式' + let fileImgName = `${scriptName}.jpg` + if (autoDak) { + fileImgName = `${scriptName}-${appearance}.jpg` + } else { + appearanceStr = "" + } - - let fileImgName = `${scriptName}-${appearance}.jpg` path = fm.joinPath(fm.documentsDirectory(), fileImgName) if (!exports.configs.changePicBg || exports.configs.colorMode || config.runsInWidget) { - // 结束并且进行预览 - completeWidget(widget) + if (autoRun) { + // 结束并且进行预览 + completeWidget(widget) + } return } - const okTips = `您的小部件【${appearanceStr}】背景已准备就绪,请退到桌面查看即可。` - let message = "图片模式支持相册照片&背景透明" - let options = ["图片选择", "透明背景"] + let subTips = "" + if (appearanceStr.length > 0) { + subTips = `在${appearanceStr}下的` + } + const okTips = `您的小部件${subTips}背景已准备就绪,请退到桌面查看即可。` + + + let message = "开始之前,请回到主屏幕并进入编辑模式。 滑到最右边的空白页并截图。" + let options = ["继续选择图片", "退出进行截图", "更新Env脚本"] + let response = await generateAlert(message, options) + if (response == 1) return + if (response == 2) { + let files = FileManager.local() + const iCloudInUse = files.isFileStoredIniCloud(module.filename) + files = iCloudInUse ? FileManager.iCloud() : files + try { + const req = new Request("https://gitee.com/enjoyee/scriptable/raw/master/Env-lsp.js") + const codeString = await req.loadString() + files.writeString(module.filename, codeString) + message = "Env脚本已更新,下次运行直接生效。" + } catch { + message = "更新失败,请稍后再试。" + } + options = ["好的"] + await generateAlert(message, options) + return + } + + + message = "支持相册照片&背景透明" + options = ["图片选择", "透明背景"] let isTransparentMode = await generateAlert(message, options) if (!isTransparentMode) { let img = await Photos.fromLibrary() @@ -78,13 +112,6 @@ exports.run = async function (scriptName, widget) { await generateAlert(message, resultOptions) fm.writeImage(path, img) } else { - message = "以下是【透明背景】生成步骤,如果你没有屏幕截图请退出,并返回主屏幕长按进入编辑模式。滑动到最右边的空白页截图,然后重新运行!" - let exitOptions = ["继续(已有截图)", "退出(没有截图)"] - - let shouldExit = await generateAlert(message, exitOptions) - if (shouldExit) return - - // Get screenshot and determine phone size. let img = await Photos.fromLibrary() let height = img.size.height let phone = phoneSizes()[height] @@ -94,7 +121,23 @@ exports.run = async function (scriptName, widget) { return } - // Prompt for widget size and position. + if (height == 2436) { + let files = FileManager.local() + let cacheName = "lsp-phone-type" + let cachePath = files.joinPath(files.libraryDirectory(), cacheName) + if (files.fileExists(cachePath)) { + let typeString = files.readString(cachePath) + phone = phone[typeString] + } else { + message = "你使用什么型号的iPhone?" + let types = ["iPhone 12 mini", "iPhone 11 Pro, XS, or X"] + let typeIndex = await generateAlert(message, types) + let type = (typeIndex == 0) ? "mini" : "x" + phone = phone[type] + files.writeString(cachePath, type) + } + } + message = "您想要创建什么尺寸的小部件?" let sizes = ["小号", "中号", "大号"] let size = await generateAlert(message, sizes) @@ -103,7 +146,6 @@ exports.run = async function (scriptName, widget) { message = "您想它在什么位置?" message += (height == 1136 ? " (请注意,您的设备仅支持两行小部件,因此中间和底部选项相同。)" : "") - // Determine image crop based on phone size. let crop = { w: "", h: "", x: "", y: "" } if (widgetSize == "小号") { crop.w = phone.小号 @@ -111,7 +153,6 @@ exports.run = async function (scriptName, widget) { let positions = ["顶部 左边", "顶部 右边", "中间 左边", "中间 右边", "底部 左边", "底部 右边"] let position = await generateAlert(message, positions) - // Convert the two words into two keys for the phone size dictionary. let keys = positions[position].split(' ') crop.y = phone[keys[0]] crop.x = phone[keys[1]] @@ -120,7 +161,6 @@ exports.run = async function (scriptName, widget) { crop.w = phone.中号 crop.h = phone.小号 - // 中号 and 大号 widgets have a fixed x-value. crop.x = phone.左边 let positions = ["顶部", "中间", "底部"] let position = await generateAlert(message, positions) @@ -134,48 +174,59 @@ exports.run = async function (scriptName, widget) { let positions = ["顶部", "底部"] let position = await generateAlert(message, positions) - // 大号 widgets at the 底部 have the "中间" y-value. crop.y = position ? phone.中间 : phone.顶部 } - // Crop image and finalize the widget. let imgCrop = cropImage(img, new Rect(crop.x, crop.y, crop.w, crop.h)) - message = okTips - const resultOptions = ["好的"] - await generateAlert(message, resultOptions) - fm.writeImage(path, imgCrop) + message = `${okTips} 是否需要保存图像?` + const exportPhotoOptions = ["导出到相册", "直接完成"] + const exportToFiles = await generateAlert(message, exportPhotoOptions) + + if (exportToFiles) { + fm.writeImage(path, imgCrop) + } else { + Photos.save(imgCrop) + } } - // 结束并且进行预览 - completeWidget(widget) + if (autoRun) { + // 结束并且进行预览 + completeWidget(widget) + } } //------------------------------------------------ -function completeWidget(widget) { - // 刷新间隔 - const refreshInterval = exports.configs.refreshInterval - if (refreshInterval > 0) { - widget.refreshAfterDate = new Date(new Date() + 1000*60*refreshInterval) - } +async function completeWidget(widget) { // 背景 if (exports.configs.colorMode) { widget.backgroundColor = exports.configs.bgColor } else { widget.backgroundImage = fm.readImage(path) } + exports.finish(widget) +} +//------------------------------------------------ +exports.readBgImg = function () { + return fm.readImage(path) +} +//------------------------------------------------ +exports.finish = function (widget, preview = true) { + widget.refreshAfterDate = new Date(exports.configs.refreshInterval * 60 * 1000) // 设置边距(上,左,下,右) widget.setPadding(exports.configs.topPadding, exports.configs.leftPadding, exports.configs.bottomPadding, exports.configs.rightPadding) // 设置组件 Script.setWidget(widget) // 完成脚本 Script.complete() - // 预览 - if (exports.configs.previewSize == "Large") { - widget.presentLarge() - } else if (exports.configs.previewSize == "Medium") { - widget.presentMedium() - } else { - widget.presentSmall() + if (preview) { + // 预览 + if (exports.configs.previewSize == "Large") { + widget.presentLarge() + } else if (exports.configs.previewSize == "Medium") { + widget.presentMedium() + } else { + widget.presentSmall() + } } } //------------------------------------------------ @@ -203,40 +254,32 @@ function cropImage(img, rect) { // Pixel sizes and positions for widgets on all supported phones. function phoneSizes() { let phones = { - "2340": { // 12mini - "小号": 436, - "中号": 936, - "大号": 980, - "左边": 72, - "右边": 570, - "顶部": 212, - "中间": 756, - "底部": 1300, - }, - - "2532": { // 12/12 Pro - "小号": 472, - "中号": 1012, - "大号": 1058, + "2532": { + "models": ["12", "12 Pro"], + "小号": 474, + "中号": 1014, + "大号": 1062, "左边": 78, "右边": 618, - "顶部": 230, - "中间": 818, - "底部": 1408, + "顶部": 231, + "中间": 819, + "底部": 1407, }, - "2778": { // 12 Pro Max - "小号": 518, - "中号": 1114, - "大号": 1162, - "左边": 86, + "2778": { + "models": ["12 Pro Max"], + "小号": 510, + "中号": 1092, + "大号": 1146, + "左边": 96, "右边": 678, - "顶部": 252, - "中间": 898, - "底部": 1544, + "顶部": 246, + "中间": 882, + "底部": 1518, }, "2688": { + "models": ["Xs Max", "11 Pro Max"], "小号": 507, "中号": 1080, "大号": 1137, @@ -248,6 +291,7 @@ function phoneSizes() { }, "1792": { + "models": ["11", "Xr"], "小号": 338, "中号": 720, "大号": 758, @@ -259,17 +303,33 @@ function phoneSizes() { }, "2436": { - "小号": 465, - "中号": 987, - "大号": 1035, - "左边": 69, - "右边": 591, - "顶部": 213, - "中间": 783, - "底部": 1353 + x: { + "models": ["X", "Xs", "11 Pro"], + "小号": 465, + "中号": 987, + "大号": 1035, + "左边": 69, + "右边": 591, + "顶部": 213, + "中间": 783, + "底部": 1353 + }, + + mini: { + "models": ["12 mini"], + "小号": 465, + "中号": 987, + "大号": 1035, + "左边": 69, + "右边": 591, + "顶部": 231, + "中间": 801, + "底部": 1371 + } }, "2208": { + "models": ["6+", "6s+", "7+", "8+"], "小号": 471, "中号": 1044, "大号": 1071, @@ -281,6 +341,7 @@ function phoneSizes() { }, "1334": { + "models": ["6", "6s", "7", "8"], "小号": 296, "中号": 642, "大号": 648, @@ -292,6 +353,7 @@ function phoneSizes() { }, "1136": { + "models": ["5", "5s", "5c", "SE"], "小号": 282, "中号": 584, "大号": 622, @@ -334,7 +396,6 @@ exports.getJson = async function (url) { request.headers = defaultHeaders const data = await request.loadJSON() - return data } //------------------------------------------------ @@ -469,6 +530,50 @@ exports.addStyleText = function () { resetTextStyle() } //------------------------------------------------ +exports.getLocation = async function () { + let locationData = { + "latitude": undefined, + "longitude": undefined, + "locality": undefined, + "subLocality": undefined + } + + // 缓存目录 + const cachePath = fm.joinPath(fm.documentsDirectory(), "env-lsp-location-cache") + + try { + const location = await Location.current() + const geocode = await Location.reverseGeocode(location.latitude, location.longitude, "zh_cn") + locationData.latitude = location.latitude + locationData.longitude = location.longitude + const geo = geocode[0] + // 市 + if (locationData.locality == undefined) { + locationData.locality = geo.locality + } + // 区 + if (locationData.subLocality == undefined) { + locationData.subLocality = geo.subLocality + } + // 街道 + locationData.street = geo.thoroughfare + + // 缓存数据 + fm.writeString(cachePath, JSON.stringify(locationData)) + + log("定位信息:latitude=" + location.latitude + ",longitude=" + location.longitude + ",locality=" + + locationData.locality + ",subLocality=" + locationData.subLocality + ",street=" + locationData.street) + } catch (e) { + log(`定位出错了,${e.toString()}`) + // 读取缓存数据 + const locationCache = fm.readString(cachePath) + log(`读取定位缓存数据:${locationCache}`) + locationData = JSON.parse(locationCache) + } + + return locationData +} +//------------------------------------------------ function resetImgStyle() { exports.imgStyle.stack = undefined // 加入到哪个内容栈显示 exports.textStyle.marginStart = 0 @@ -490,7 +595,91 @@ function resetTextStyle() { exports.textStyle.font = undefined // 字体 exports.textStyle.textColor = undefined // 文字颜色 } +//------------------------------------------------ +// 是否使用缓存 +exports.useCache = function (cachePath) { + let use = false + const cacheExists = fm.fileExists(cachePath) + const cacheDate = cacheExists ? fm.modificationDate(cachePath) : 0 + log(`缓存时间:${exports.getDateStr(new Date(cacheDate), "MM月dd日HH:mm")}`) + const refreshInterval = configs.refreshInterval * (60 * 1000) + log(`缓存过期:${configs.refreshInterval}min`) + if (cacheExists && ((new Date()).getTime() - cacheDate.getTime()) < refreshInterval) { + use = true + } + log(`是否使用缓存:${use}`) + + return use +} +//------------------------------------------------ +// 格式化时间 +exports.getDateStr = function (date, formatter = "yyyy年MM月d日 EEE", locale = "zh_cn") { + let df = new DateFormatter() + df.locale = locale + df.dateFormat = formatter + return df.string(date) +} +//------------------------------------------------ +/** + * 获取图片 + * @param {string} url 图片链接 + * @param {string} cacheKey 缓存的key + * @param {bool} useCache 是否使用缓存 + * @return {Image} + */ +exports.getImageByUrl = async function (url, cacheKey, useCache = true) { + const cacheFile = FileManager.local().joinPath(FileManager.local().temporaryDirectory(), cacheKey) + const exists = FileManager.local().fileExists(cacheFile) + // 判断是否有缓存 + if (useCache && exists) { + return Image.fromFile(cacheFile) + } + try { + const req = new Request(url) + const img = await req.loadImage() + // 存储到缓存 + FileManager.local().writeImage(cacheFile, img) + return img + } catch (e) { + console.error(`图片加载失败:${e}`) + if (exists) { + return Image.fromFile(cacheFile) + } + // 没有缓存+失败情况下,返回黑色背景 + let ctx = new DrawContext() + ctx.size = new Size(100, 100) + ctx.setFillColor(Color.black()) + ctx.fillRect(new Rect(0, 0, 100, 100)) + return await ctx.getImage() + } +} +//------------------------------------------------ +/** + * Http Get 请求接口 + * @param {string} url 请求的url + * @param {string} cacheKey 缓存key + * @param {bool} json 返回数据是否为json,默认true + * @return {string | json | null} + */ +exports.httpGet = async function (url, cacheKey, json = true) { + let data = null + try { + let req = new Request(url) + data = await (json ? req.loadJSON() : req.loadString()) + } catch (e) { + console.error(`httpGet请求失败:${e}`) + } + // 判断数据是否为空(加载失败) + if (!data && Keychain.contains(cacheKey)) { + // 判断是否有缓存 + let cache = Keychain.get(cacheKey) + return json ? JSON.parse(cache) : cache + } + // 存储缓存 + Keychain.set(cacheKey, json ? JSON.stringify(data) : data) + return data +} //------------------------------------------------ module.exports = exports //------------------------------------------------ diff --git a/README.md b/README.md index 0eb5eb0..3f8085a 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,25 @@ -# Scriptable -scriptable App 脚本分享 +#### **scriptable App 脚本分享** -新增模板js,可以通过封装函数进行积木一般的搭建进行搭建自己的小组件 -https://www.yuque.com/docs/share/9fa2aed5-b670-4d28-bd5e-9b622041eddd?# 《Scriptable简单教程》 +- 彩云曲线版本 +![image](https://i.loli.net/2020/11/14/AWrZmgNEjoS5zDU.png) + +- **main分支** 下的脚本已经适配 **12系列** 透明背景,**old分支** 还是之前的旧版本 + +- 使用该 **main分支** 下的任何脚本都要先加上 **Env-lsp.js** 这个脚本 + +- **日历-天气-电池** 这个小组件实现了 **自动切换暗黑跟白天模式**,不过并不是实时的,要等组件下一次刷新,或者你自己刷新也可以。 + +- 彩云天气小组件 **加入了数据缓存**,无网络情况下自动读取上一次成功的数据来展示,联网后下一次更新会从网络自动更新显示 ---【2020-10-26】 + +- 旧版本或者小组件UI展示效果可以访问文档https://www.yuque.com/docs/share/849b122b-9985-47e4-b043-c54b93562a6a?# 《Scriptable小组件系列》 + +- 新增模板js,可以通过封装函数进行积木一般的搭建进行搭建自己的小组件https://www.yuque.com/docs/share/9fa2aed5-b670-4d28-bd5e-9b622041eddd?# 《Scriptable简单教程》 +- 新增热搜榜单自动轮播,自行按照下方格式进行添加删除,榜单ID来源于摸鱼网站的分类,ID在点击分类后网站链接那里 +> // 热搜ID跟对应的标题,数据来源于 https://mo.fish/ +```JavaScript +const hotIdObjs = [ + {"1": "知乎の热搜"}, + {"58": "微博の热搜"}, + {"59": "V2EXの热搜"} +] +``` diff --git "a/\344\276\277\347\254\272.js" "b/\344\276\277\347\254\272.js" new file mode 100644 index 0000000..5ffc6a1 --- /dev/null +++ "b/\344\276\277\347\254\272.js" @@ -0,0 +1,140 @@ +//------------------------------------------------ +const env = importModule('Env-lsp.js') +//------------------------------------------------ +// 配置区 +env.configs.previewSize = "Small" // 预览大小【小:Small,中:Medium,大:Large】 +env.configs.changePicBg = false // 是否需要更换背景 +env.configs.colorMode = true // 是否是纯色背景 +env.configs.bgColor = new Color("ffffff") // 小组件背景色 +env.configs.topPadding = 0 // 内容区边距 +env.configs.leftPadding = 0 // 内容区边距 +env.configs.bottomPadding = 0 // 内容区边距 +env.configs.rightPadding = 0 // 内容区边距 +// +const imgStyle = env.imgStyle +const textStyle = env.textStyle +//------------------------------------------------ +// 脚本名字 +const name = Script.name() +//------------------------------------------------ + + +//↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓内容区↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ +//------------------------------------------------ + +// 获取外部输入的参数,格式:【文字+逗号分隔】 +let widgetInputRAW = args.widgetParameter +const defaultInput = "恭 喜,发 财" +try { + widgetInputRAW.toString() +} catch(e) { + // 默认值微博热搜 + widgetInputRAW = defaultInput +} +let inputStr = widgetInputRAW.toString() +if (inputStr.trim() == "") { + inputStr = defaultInput +} +// 获取外部输入 +const inputArr = inputStr.replace(/\,/g,",").split(",") + +/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ +// 文字颜色 +const fontColorStr = "333333" +// 文字默认大小 +const fonSize = 50 +/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ + +// 创建小组件 +const widget = await createWidget(inputArr) + + +//========================================================= +// 创建组件 +async function createWidget(data) { + let w = new ListWidget() + /* + ************************************************************* + */ + // 文字颜色 + const fontColor = new Color(fontColorStr) + const shadowColor= new Color(fontColorStr, 0.8) + // 计算文字最终大小 + const realFontSize = getRealFontSize(data) + + /* + ************************************************************* + */ + w.addSpacer() + let lineSpacing = 4 + for (let index in data) { + let titleStack = w.addStack() + titleStack.addSpacer() + let title = titleStack.addText(data[index] + "") + title.font = Font.lightMonospacedSystemFont(realFontSize) + title.textColor = fontColor + title.shadowColor = shadowColor + title.shadowOffset = new Point(1,1) + title.shadowRadius = 1 // 阴影半径 + title.centerAlignText() + if(index == data.length - 1) { + lineSpacing = 0 + } + w.addSpacer(lineSpacing) + titleStack.addSpacer() + } + w.addSpacer() + + w.useDefaultPadding() + return w +} +//========================================================= +// 获取最终的文字大小 +function getRealFontSize(data) { + var totalStr = "" + var maxStrLength = 0 + for (let index in data) { + let str = data[index] + const length = str.length + if (length > maxStrLength) { + maxStrLength = length + } + totalStr = totalStr + str + } + log("最大行的文字长度:" + maxStrLength) + + const rowLength = 132 + const columnLength = 100 + // 一行可以显示多少个字 + const rowFontCount = Math.floor(rowLength / fonSize) + // 总共要显示多少列 + const columnFontCount = data.length + log("总共要显示多少列:" + columnFontCount) + let columnFontSize = fonSize + let gap = columnLength - columnFontCount * columnFontSize + while(gap < 0) { + columnFontSize = columnFontSize - 1 + gap = columnLength - columnFontCount * columnFontSize + } + log("列方向所需的文字大小:" + columnFontSize) + + // 最大行的文字所需长度 + let rowFontSize = fonSize + gap = rowLength - maxStrLength * rowFontSize + while(gap < 0) { + rowFontSize = rowFontSize - 1 + gap = rowLength - maxStrLength * rowFontSize + } + log("行方向所需的文字大小:" + rowFontSize) + const realFontSize = Math.min(rowFontSize, columnFontSize) + + return realFontSize +} + +//------------------------------------------------ +//↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑内容区↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ + +//------------------------------------------------ +// 运行脚本、预览 +await env.run(name, widget) +//------------------------------------------------ \ No newline at end of file diff --git "a/\345\212\250\346\243\256\345\260\217\345\212\250\347\211\251.js" "b/\345\212\250\346\243\256.js" similarity index 69% rename from "\345\212\250\346\243\256\345\260\217\345\212\250\347\211\251.js" rename to "\345\212\250\346\243\256.js" index 35d195e..23ffc9d 100644 --- "a/\345\212\250\346\243\256\345\260\217\345\212\250\347\211\251.js" +++ "b/\345\212\250\346\243\256.js" @@ -1,80 +1,30 @@ -////////////////////////////////////////// -// 预览大小【小:Small,中:Medium,大:Large】 -const previewSize = "Small" - -// 是否需要更换背景 -const changePicBg = true - -// 是否是纯色背景 -const colorMode = false - -// 小组件背景色 -const bgColor = new Color("000000") - -// 默认字体 -const defaultFont = Font.systemFont(18) - -// 默认字体颜色 -const defaultTextColor = new Color("#ffffff") - -// 内容区左右边距 -const padding = { - top: 0, - left: 0, - bottom: 0, - right: 0 -} - -// 标题样式定义 -let textStyle = { - stack: undefined, // 加入到哪个内容栈显示 - marginStart: 0, // 开始距离,水平方向的就是左边距离,垂直方向的就是顶部距离 - marginEnd: 0, // 结束距离,水平方向的就是右边距离,垂直方向的就是底部距离 - text: "", // 显示的文字 - width: 0, // 宽 - height: 0, // 长 - lineLimit: 0, // 行数控制,0是全部展示 - font: undefined, // 字体 - textColor: defaultTextColor, // 文字颜色 -} - -// 图片样式定义 -let imgStyle = { - stack: undefined, // 加入到哪个内容栈显示 - marginStart: 0, // 开始距离,水平方向的就是左边距离,垂直方向的就是顶部距离 - marginEnd: 0, // 结束距离,水平方向的就是右边距离,垂直方向的就是底部距离 - img: undefined, // 图片资源 - width: 0, // 宽 - height: 0, // 长 - tintColor: undefined, // 图片渲染颜色 -} -//////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////// - - - - - -////////////////////////////////////// -// 组件Start -const filename = `${Script.name()}.jpg` -const files = FileManager.local() -const path = files.joinPath(files.documentsDirectory(), filename) +//------------------------------------------------ +const env = importModule('Env-lsp.js') +//------------------------------------------------ +// 配置区 +env.configs.previewSize = "Small" // 预览大小【小:Small,中:Medium,大:Large】 +env.configs.changePicBg = true // 是否需要更换背景 +env.configs.colorMode = false // 是否是纯色背景 +env.configs.bgColor = new Color("000000") // 小组件背景色 +env.configs.topPadding = 0 // 内容区边距 +env.configs.leftPadding = 0 // 内容区边距 +env.configs.bottomPadding = 0 // 内容区边距 +env.configs.rightPadding = 0 // 内容区边距 +env.configs.refreshInterval = 60 * 3 // 刷新间隔,单位分钟,非精准,会有3-5分钟差距 +// +const imgStyle = env.imgStyle +const textStyle = env.textStyle +//------------------------------------------------ +// 脚本名字 +const name = Script.name() +// 组件 const widget = new ListWidget() const contentStack = widget.addStack() -////////////////////////////////////// +//------------------------------------------------ - -/* -**************************************************************************** -↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ -下面添加你自己的组件内容/逻辑 -**************************************************************************** -*/ +//↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓内容区↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ +//------------------------------------------------ // 获取外部输入的参数 var widgetInputRAW = args.widgetParameter try { @@ -456,485 +406,23 @@ let monthDayStr = `${month}月${day}日` if(assignMonthDay.length > 0) { monthDayStr = assignMonthDay } -log(`日期:${monthDayStr}`) + +log(`>>日期:${monthDayStr}`) let imgUrl = imgObjs[monthDayStr] if(imgUrl == undefined) { imgUrl = imgObjs["12月4日"] } -let img = await getImage(imgUrl) +let img = await env.getImage(imgUrl) imgStyle.stack = contentStack imgStyle.width = 138 imgStyle.height = 138 imgStyle.img = img -addStyleImg() - - -/* -**************************************************************************** -上面添加你自己的组件内容/逻辑 -↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ -**************************************************************************** -*/ - - -/* -**************************************************************************** -* 这里是图片逻辑,不用修改 -**************************************************************************** -*/ - -if (!colorMode && !config.runsInWidget && changePicBg) { - const okTips = "您的小部件背景已准备就绪" - let message = "图片模式支持相册照片&背景透明" - let options = ["图片选择", "透明背景"] - let isTransparentMode = await generateAlert(message, options) - if (!isTransparentMode) { - let img = await Photos.fromLibrary() - message = okTips - const resultOptions = ["好的"] - await generateAlert(message, resultOptions) - files.writeImage(path, img) - } else { - message = "以下是【透明背景】生成步骤,如果你没有屏幕截图请退出,并返回主屏幕长按进入编辑模式。滑动到最右边的空白页截图。然后重新运行!" - let exitOptions = ["继续(已有截图)", "退出(没有截图)"] - - let shouldExit = await generateAlert(message, exitOptions) - if (shouldExit) return - - // Get screenshot and determine phone size. - let img = await Photos.fromLibrary() - let height = img.size.height - let phone = phoneSizes()[height] - if (!phone) { - message = "您似乎选择了非iPhone屏幕截图的图像,或者不支持您的iPhone。请使用其他图像再试一次!" - await generateAlert(message, ["好的!我现在去截图"]) - return - } - - // Prompt for widget size and position. - message = "您想要创建什么尺寸的小部件?" - let sizes = ["小号", "中号", "大号"] - let size = await generateAlert(message, sizes) - let widgetSize = sizes[size] - - message = "您想它在什么位置?" - message += (height == 1136 ? " (请注意,您的设备仅支持两行小部件,因此中间和底部选项相同。)" : "") - - // Determine image crop based on phone size. - let crop = { w: "", h: "", x: "", y: "" } - if (widgetSize == "小号") { - crop.w = phone.小号 - crop.h = phone.小号 - let positions = ["顶部 左边", "顶部 右边", "中间 左边", "中间 右边", "底部 左边", "底部 右边"] - let position = await generateAlert(message, positions) - - // Convert the two words into two keys for the phone size dictionary. - let keys = positions[position].split(' ') - crop.y = phone[keys[0]] - crop.x = phone[keys[1]] - - } else if (widgetSize == "中号") { - crop.w = phone.中号 - crop.h = phone.小号 - - // 中号 and 大号 widgets have a fixed x-value. - crop.x = phone.左边 - let positions = ["顶部", "中间", "底部"] - let position = await generateAlert(message, positions) - let key = positions[position].toLowerCase() - crop.y = phone[key] - - } else if (widgetSize == "大号") { - crop.w = phone.中号 - crop.h = phone.大号 - crop.x = phone.左边 - let positions = ["顶部", "底部"] - let position = await generateAlert(message, positions) - - // 大号 widgets at the 底部 have the "中间" y-value. - crop.y = position ? phone.中间 : phone.顶部 - } - - // Crop image and finalize the widget. - let imgCrop = cropImage(img, new Rect(crop.x, crop.y, crop.w, crop.h)) - - message = "您的小部件背景已准备就绪,退出到桌面预览。" - const resultOptions = ["好的"] - await generateAlert(message, resultOptions) - files.writeImage(path, imgCrop) - } - -} - - -////////////////////////////////////// -// 组件End -// 设置小组件的背景 -if (colorMode) { - widget.backgroundColor = bgColor -} else { - widget.backgroundImage = files.readImage(path) -} -// 设置边距(上,左,下,右) -widget.setPadding(padding.top, padding.left, padding.bottom, padding.right) -// 设置组件 -Script.setWidget(widget) -// 完成脚本 -Script.complete() -// 预览 -if (previewSize == "Large") { - widget.presentLarge() -} else if (previewSize == "Medium") { - widget.presentMedium() -} else { - widget.presentSmall() -} -////////////////////////////////////// - -/* -**************************************************************************** -* 重置文本样式 -**************************************************************************** -*/ -function resetTextStyle() { - textStyle.stack = undefined // 加入到哪个内容栈显示 - textStyle.marginStart = 0 - textStyle.marginEnd = 0 - textStyle.text = "" // 显示的文字 - textStyle.width = 0 // 宽 - textStyle.height = 0 // 长 - textStyle.lineLimit = 0 // 行数控制,0是全部展示 - textStyle.font = undefined // 字体 - textStyle.textColor = defaultTextColor // 文字颜色 -} - -/* -**************************************************************************** -* 重置图片样式 -**************************************************************************** -*/ -function resetImgStyle() { - imgStyle.stack = undefined // 加入到哪个内容栈显示 - textStyle.marginStart = 0 - textStyle.marginEnd = 0 - imgStyle.img = undefined // 图片资源 - imgStyle.width = 0 // 宽 - imgStyle.height = 0 // 长 - imgStyle.tintColor = undefined // 图片渲染颜色 -} - -/* -**************************************************************************** -* 添加一行文本数据进行显示 -**************************************************************************** -*/ -function addStyleText() { - const contentStack = textStyle.stack - if (contentStack == undefined) { - return - } - - const marginStart = textStyle.marginStart - if (marginStart != undefined && marginStart != 0) { - contentStack.addSpacer(marginStart) - } - - const textSpan = contentStack.addText(`${textStyle.text}`) - contentStack.size = new Size(textStyle.width, textStyle.height) - textSpan.lineLimit = textStyle.lineLimit - textSpan.font = textStyle.font - textSpan.textColor = textStyle.textColor - - const marginEnd = textStyle.marginEnd - if (marginStart != undefined && marginStart != 0) { - contentStack.addSpacer(marginEnd) - } - - // 重置样式 - resetTextStyle() -} - -/* -**************************************************************************** -* 添加图片进行显示 -**************************************************************************** -*/ -function addStyleImg() { - const contentStack = imgStyle.stack - if (contentStack == undefined) { - return - } - - const marginStart = textStyle.marginStart - if (marginStart != undefined && marginStart != 0) { - contentStack.addSpacer(marginStart) - } - - const imgSpan = contentStack.addImage(imgStyle.img) - imgSpan.imageSize = new Size(imgStyle.width, imgStyle.height) - const tintColor = imgStyle.tintColor - if (tintColor != undefined) { - imgSpan.tintColor = tintColor - } - - const marginEnd = textStyle.marginEnd - if (marginStart != undefined && marginStart != 0) { - contentStack.addSpacer(marginEnd) - } - - // 重置样式 - resetImgStyle() -} - -/* -**************************************************************************** -* 右对齐,水平方向排列 -**************************************************************************** -*/ -function alignRightStack(alignmentStack, marginRight) { - let contentStack = alignmentStack.addStack() - contentStack.layoutHorizontally() - contentStack.addSpacer() - - let returnStack = contentStack.addStack() - - // 添加右边距 - if (marginRight != undefined && marginRight != 0) { - contentStack.addSpacer(marginRight) - } - - return returnStack -} - - -/* -**************************************************************************** -* 左对齐,水平方向排列 -**************************************************************************** -*/ -function alignLeftStack(alignmentStack, marginLeft) { - let contentStack = alignmentStack.addStack() - contentStack.layoutHorizontally() - - let returnStack = contentStack.addStack() - returnStack.layoutHorizontally() - - // 添加左边距 - if (marginLeft != undefined && marginLeft != 0) { - returnStack.addSpacer(marginLeft) - } - - contentStack.addSpacer() - return returnStack -} - -/* -**************************************************************************** -* 上对齐,垂直方向排列 -**************************************************************************** -*/ -function alignTopStack(alignmentStack, marginTop) { - let contentStack = alignmentStack.addStack() - contentStack.layoutVertically() - - // 添加左边距 - if (marginTop != undefined && marginTop != 0) { - contentStack.addSpacer(marginTop) - } - - let returnStack = contentStack.addStack() - returnStack.layoutVertically() - - contentStack.addSpacer() - return returnStack -} - - -/* -**************************************************************************** -* 下对齐,垂直方向排列 -**************************************************************************** -*/ -function alignBottomStack(alignmentStack, marginBottom) { - let contentStack = alignmentStack.addStack() - contentStack.layoutVertically() - contentStack.addSpacer() - - let returnStack = contentStack.addStack() - - // 添加下边距 - if (marginBottom != undefined && marginBottom != 0) { - contentStack.addSpacer(marginBottom) - } - - return returnStack -} - -/* -**************************************************************************** -* 水平居中 -**************************************************************************** -*/ -function alignHorizontallyCenterStack(alignmentStack) { - let returnStack = alignmentStack.addStack() - returnStack.layoutHorizontally() - returnStack.centerAlignContent() - return returnStack -} - - -/* -**************************************************************************** -* 垂直居中 -**************************************************************************** -*/ -function alignVerticallyCenterStack(alignmentStack) { - let returnStack = alignmentStack.addStack() - returnStack.layoutVertically() - returnStack.centerAlignContent() - return returnStack -} - - -/* -**************************************************************************** -* 网络请求get封装 -**************************************************************************** -*/ -async function getJson(url) { - const request = new Request(url) - const defaultHeaders = { - "Accept": "*/*", - "Content-Type": "application/json" - } - - request.url = url - request.method = 'GET' - request.headers = defaultHeaders - - const data = await request.loadJSON() - - return data -} - - -/* -**************************************************************************** -* 网络请求获取图片 -**************************************************************************** -*/ -async function getImage(url) { - const request = new Request(url) - const data = await request.loadImage() - return data -} - - -/* -**************************************************************************** -* 图片裁剪相关 -**************************************************************************** -*/ -// Generate an alert with the provided array of options. -async function generateAlert(message, options) { - let alert = new Alert() - alert.message = message - - for (const option of options) { - alert.addAction(option) - } - - let response = await alert.presentAlert() - return response -} - -// Crop an image into the specified rect. -function cropImage(img, rect) { - let draw = new DrawContext() - draw.size = new Size(rect.width, rect.height) - draw.drawImageAtPoint(img, new Point(-rect.x, -rect.y)) - return draw.getImage() -} - -// Pixel sizes and positions for widgets on all supported phones. -function phoneSizes() { - let phones = { - "2688": { - "小号": 507, - "中号": 1080, - "大号": 1137, - "左边": 81, - "右边": 654, - "顶部": 228, - "中间": 858, - "底部": 1488 - }, - - "1792": { - "小号": 338, - "中号": 720, - "大号": 758, - "左边": 54, - "右边": 436, - "顶部": 160, - "中间": 580, - "底部": 1000 - }, - - "2436": { - "小号": 465, - "中号": 987, - "大号": 1035, - "左边": 69, - "右边": 591, - "顶部": 213, - "中间": 783, - "底部": 1353 - }, - - "2208": { - "小号": 471, - "中号": 1044, - "大号": 1071, - "左边": 99, - "右边": 672, - "顶部": 114, - "中间": 696, - "底部": 1278 - }, - - "1334": { - "小号": 296, - "中号": 642, - "大号": 648, - "左边": 54, - "右边": 400, - "顶部": 60, - "中间": 412, - "底部": 764 - }, - - "1136": { - "小号": 282, - "中号": 584, - "大号": 622, - "左边": 30, - "右边": 332, - "顶部": 59, - "中间": 399, - "底部": 399 - } - } - return phones -} - - -/* -**************************************************************************** -**************************************************************************** -**************************************************************************** -*/ - - - +env.addStyleImg() +//------------------------------------------------ +//↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑内容区↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ + +//------------------------------------------------ +// 运行脚本、预览 +await env.run(name, widget) +//------------------------------------------------ \ No newline at end of file diff --git "a/\345\237\272\351\207\221.js" "b/\345\237\272\351\207\221.js" new file mode 100644 index 0000000..ae71021 --- /dev/null +++ "b/\345\237\272\351\207\221.js" @@ -0,0 +1,131 @@ +//------------------------------------------------ +const env = importModule('Env-lsp.js') +//------------------------------------------------ +// 配置区 +env.configs.previewSize = "Medium" // 预览大小【小:Small,中:Medium,大:Large】 +env.configs.changePicBg = true // 是否需要更换背景 +env.configs.colorMode = false // 是否是纯色背景 +env.configs.bgColor = new Color("000000") // 小组件背景色 +env.configs.topPadding = 0 // 内容区边距 +env.configs.leftPadding = 0 // 内容区边距 +env.configs.bottomPadding = 0 // 内容区边距 +env.configs.rightPadding = 0 // 内容区边距 +env.configs.refreshInterval = 1 // 刷新间隔,单位分钟,非精准,会有3-5分钟差距 +// +const imgStyle = env.imgStyle +const textStyle = env.textStyle +//------------------------------------------------ +// 脚本名字 +const name = Script.name() +//------------------------------------------------ + + +//↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓内容区↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ +//------------------------------------------------ + +// 获取外部输入的参数 +var widgetInputRAW = args.widgetParameter +const defaultFund = "001838,002190,161725,160643,000336,161726,519019" +try { + widgetInputRAW.toString() +} catch(e) { + // 默认值招商白酒 + widgetInputRAW = defaultFund +} +// 初始化基金ID +var inputStr = widgetInputRAW.toString() +if (inputStr.length == 0) { + inputStr = defaultFund +} +var fid = inputStr.replace(/\,/g,",").split(",") +// 获取基金数据 +const fundJSON = await getFund() +// 创建小组件 +const widget = createWidget(fundJSON) + + +//====================================================== +// 基金数据获取 +async function getFund() { + // 拼接基金id + var fidFull = '' + for (let index in fid) { + fidFull = fidFull + fid[index] + "," + } + fidFull = fidFull.substring(0, fidFull.lastIndexOf(',')) + + // 请求基金数据 + const url = `https://api.doctorxiong.club/v1/fund?code=${fidFull}` + const res = await env.getJson(url) + + return res +} + +//====================================================== +// 创建 widget +function createWidget(fundJson) { + let listWidget = new ListWidget() + + const data = fundJson.data + for (let index in data) { + // 添加行距 + listWidget.addSpacer(4) + // 统一字体大小 + const fontSize = 11 + + //创建水平方向stack + let hStack0 = listWidget.addStack() + hStack0.layoutHorizontally() + hStack0.addSpacer(0) // Left spacing, 向左对齐间距 + + // 颜色值 + const expectGrowth = data[index].expectGrowth // 当前基金单位净值估算日涨幅 + var color = new Color('dc0000') + if (expectGrowth <= 0) { + color = new Color('1ba784') + } + + // 基金名称 + let title = hStack0.addText('>› ' + data[index].name) + title.font = new Font('Menlo', fontSize) //font and size,字体与大小 + title.textColor = color //font color,字体颜色 + title.textOpacity = (1) //opacity,不透明度 + title.leftAlignText() //Align,对齐方式(center,left,right)!在同一个stack内的对齐方式不能单独设置,只能调整向左对齐间距大小 + + // 净值估算更新日期 + let expectWorthDateStr = data[index].expectWorthDate + let expectWorthDateText = data[index].netWorthDate + + // 当前基金单位净值估算日涨幅,单位为百分比 + let expectGrowthStr = expectGrowth + if (expectWorthDateStr.search(expectWorthDateText) != -1) { + expectGrowthStr = data[index].dayGrowth + } + if (typeof(expectWorthDateStr) != "undefined") { + expectWorthDateText = expectWorthDateStr.substring(5) + } + + let expectWorth = hStack0.addText(' ‹' + expectGrowthStr + '› ') + expectWorth.font = Font.boldSystemFont(12) //font and size,字体与大小 + expectWorth.textColor = color //font color,字体颜色 + expectWorth.textOpacity = (1) //opacity,不透明度 + expectWorth.leftAlignText() //Align,对齐方式(center,left,right)!在同一个stack内的对齐方式不能单独设置,只能调整向左对齐间距大小 + + // 净值估算更新日期添加 + let expectWorthDate = hStack0.addText(expectWorthDateText + '') + expectWorthDate.font = new Font('Menlo', fontSize) //font and size,字体与大小 + expectWorthDate.textColor = color //font color,字体颜色 + expectWorthDate.textOpacity = (1) //opacity,不透明度 + expectWorthDate.leftAlignText() //Align,对齐方式(center,left,right)!在同一个stack内的对齐方式不能单独设置,只能调整向左对齐间距大小 + } + + return listWidget +} + +//------------------------------------------------ +//↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑内容区↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ + +//------------------------------------------------ +// 运行脚本、预览 +await env.run(name, widget) +//------------------------------------------------ \ No newline at end of file diff --git "a/\345\237\272\351\207\221\347\273\204\344\273\266.js" "b/\345\237\272\351\207\221\347\273\204\344\273\266.js" deleted file mode 100644 index e5d3243..0000000 --- "a/\345\237\272\351\207\221\347\273\204\344\273\266.js" +++ /dev/null @@ -1,320 +0,0 @@ -// Variables used by Scriptable. -// This widget was created by Max Zeryck,并在原来的基础上增加了更多内容显示 - - -/********************************************************************/ -/****************************定义小组件****************************/ -/********************************************************************/ -const filename = Script.name() + ".jpg" -const files = FileManager.local() -const path = files.joinPath(files.documentsDirectory(), filename) - -if (config.runsInWidget) { - /****************************小组件内容START****************************/ - // 获取外部输入的参数 - var widgetInputRAW = args.widgetParameter - // 默认值 - const defaultFund = "001838,002190" - try { - widgetInputRAW.toString() - } catch(e) { - widgetInputRAW = defaultFund - } - // 初始化基金ID - var inputStr = widgetInputRAW.toString() - if (inputStr.length == 0) { - inputStr = defaultFund - } - var fid = inputStr.replace(/\,/g,",").split(",") - // 获取基金数据 - const fundJSON = await getFund() - // 创建小组件 - const widget = createWidget(fundJSON) - widget.backgroundImage = files.readImage(path) - widget.addSpacer() - widget.setPadding(15, 2, 15, 2) - Script.setWidget(widget) - Script.complete() - // 直接预览中等大小的小组件 - widget.presentMedium() - /*****************************小组件内容ENd*****************************/ - -} else { - // Determine if user has taken the screenshot. - var message - message = "开始之前,请返回主屏幕并长按进入编辑模式。滑动到最右边的空白页并截图。" - let exitOptions = ["继续","退出以截图"] - let shouldExit = await generateAlert(message,exitOptions) - if (shouldExit) return - - // Get screenshot and determine phone size. - let img = await Photos.fromLibrary() - let height = img.size.height - let phone = phoneSizes()[height] - if (!phone) { - message = "您似乎选择了非iPhone屏幕截图的图像,或者不支持您的iPhone。请使用其他图像再试一次。" - await generateAlert(message,["OK"]) - return - } - - // Prompt for widget size and position. - message = "您想要创建什么尺寸的小部件?" - let sizes = ["Small","Medium","Large"] - let size = await generateAlert(message,sizes) - let widgetSize = sizes[size] - - message = "您想它在什么位置?" - message += (height == 1136 ? " (请注意,您的设备仅支持两行小部件,因此中间和底部选项相同。)" : "") - - // Determine image crop based on phone size. - let crop = { w: "", h: "", x: "", y: "" } - if (widgetSize == "Small") { - crop.w = phone.small - crop.h = phone.small - let positions = ["Top left","Top right","Middle left","Middle right","Bottom left","Bottom right"] - let position = await generateAlert(message,positions) - - // Convert the two words into two keys for the phone size dictionary. - let keys = positions[position].toLowerCase().split(' ') - crop.y = phone[keys[0]] - crop.x = phone[keys[1]] - - } else if (widgetSize == "Medium") { - crop.w = phone.medium - crop.h = phone.small - - // Medium and large widgets have a fixed x-value. - crop.x = phone.left - let positions = ["Top","Middle","Bottom"] - let position = await generateAlert(message,positions) - let key = positions[position].toLowerCase() - crop.y = phone[key] - - } else if(widgetSize == "Large") { - crop.w = phone.medium - crop.h = phone.large - crop.x = phone.left - let positions = ["Top","Bottom"] - let position = await generateAlert(message,positions) - - // Large widgets at the bottom have the "middle" y-value. - crop.y = position ? phone.middle : phone.top - } - - // Crop image and finalize the widget. - let imgCrop = cropImage(img, new Rect(crop.x,crop.y,crop.w,crop.h)) - - message = "您的小部件背景已准备就绪。您想在Scriptable的小部件中使用它还是导出图像?" - const exportPhotoOptions = ["在Scriptable中使用","导出图像"] - const exportPhoto = await generateAlert(message,exportPhotoOptions) - - if (exportPhoto) { - Photos.save(imgCrop) - } else { - files.writeImage(path,imgCrop) - } - - Script.complete() -} - -/* - ************************************************************************************ - */ - -// Generate an alert with the provided array of options. -async function generateAlert(message,options) { - - let alert = new Alert() - alert.message = message - - for (const option of options) { - alert.addAction(option) - } - - let response = await alert.presentAlert() - return response -} - -// Crop an image into the specified rect. -function cropImage(img,rect) { - - let draw = new DrawContext() - draw.size = new Size(rect.width, rect.height) - - draw.drawImageAtPoint(img,new Point(-rect.x, -rect.y)) - return draw.getImage() -} - -// Pixel sizes and positions for widgets on all supported phones. -function phoneSizes() { - let phones = { - "2688": { - "small": 507, - "medium": 1080, - "large": 1137, - "left": 81, - "right": 654, - "top": 228, - "middle": 858, - "bottom": 1488 - }, - - "1792": { - "small": 338, - "medium": 720, - "large": 758, - "left": 54, - "right": 436, - "top": 160, - "middle": 580, - "bottom": 1000 - }, - - "2436": { - "small": 465, - "medium": 987, - "large": 1035, - "left": 69, - "right": 591, - "top": 213, - "middle": 783, - "bottom": 1353 - }, - - "2208": { - "small": 471, - "medium": 1044, - "large": 1071, - "left": 99, - "right": 672, - "top": 114, - "middle": 696, - "bottom": 1278 - }, - - "1334": { - "small": 296, - "medium": 642, - "large": 648, - "left": 54, - "right": 400, - "top": 60, - "middle": 412, - "bottom": 764 - }, - - "1136": { - "small": 282, - "medium": 584, - "large": 622, - "left": 30, - "right": 332, - "top": 59, - "middle": 399, - "bottom": 399 - } - } - return phones -} - -/* - ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ - */ - - - // 基金数据获取 -async function getFund() { - // 拼接基金id - var fidFull = '' - for (let index in fid) { - fidFull = fidFull + fid[index] + "," - } - fidFull = fidFull.substring(0, fidFull.lastIndexOf(',')) - - // 请求基金数据 - const fundRequest = { - url: `https://api.doctorxiong.club/v1/fund?code=${fidFull}`, - } - const res = await get(fundRequest) - - return res -} - -// 创建 widget -function createWidget(fundJson) { - let listWidget = new ListWidget() - - const data = fundJson.data - for (let index in data) { - // 添加行距 - listWidget.addSpacer(4) - // 统一字体大小 - const fontSize = 11 - - //创建水平方向stack - let hStack0 = listWidget.addStack() - hStack0.layoutHorizontally() - hStack0.addSpacer(0) // Left spacing, 向左对齐间距 - - // 颜色值 - const expectGrowth = data[index].expectGrowth // 当前基金单位净值估算日涨幅 - var color = new Color('dc0000') - if (expectGrowth <= 0) { - color = new Color('1ba784') - } - - // 基金名称 - let title = hStack0.addText('>› ' + data[index].name) - title.font = new Font('Menlo', fontSize) //font and size,字体与大小 - title.textColor = color //font color,字体颜色 - title.textOpacity = (1) //opacity,不透明度 - title.leftAlignText() //Align,对齐方式(center,left,right)!在同一个stack内的对齐方式不能单独设置,只能调整向左对齐间距大小 - - // 净值估算更新日期 - let expectWorthDateStr = data[index].expectWorthDate - let expectWorthDateText = data[index].netWorthDate - - // 当前基金单位净值估算日涨幅,单位为百分比 - let expectGrowthStr = expectGrowth - if (expectWorthDateStr.search(expectWorthDateText) != -1) { - expectGrowthStr = data[index].dayGrowth - } - if (typeof(expectWorthDateStr) != "undefined") { - expectWorthDateText = expectWorthDateStr.substring(5) - } - - let expectWorth = hStack0.addText(' ‹' + expectGrowthStr + '› ') - expectWorth.font = Font.boldSystemFont(12) //font and size,字体与大小 - expectWorth.textColor = color //font color,字体颜色 - expectWorth.textOpacity = (1) //opacity,不透明度 - expectWorth.leftAlignText() //Align,对齐方式(center,left,right)!在同一个stack内的对齐方式不能单独设置,只能调整向左对齐间距大小 - - // 净值估算更新日期添加 - let expectWorthDate = hStack0.addText(expectWorthDateText + '') - expectWorthDate.font = new Font('Menlo', fontSize) //font and size,字体与大小 - expectWorthDate.textColor = color //font color,字体颜色 - expectWorthDate.textOpacity = (1) //opacity,不透明度 - expectWorthDate.leftAlignText() //Align,对齐方式(center,left,right)!在同一个stack内的对齐方式不能单独设置,只能调整向左对齐间距大小 - } - - return listWidget -} - -// 网络请求get封装 -async function get({ url, headers = {} }, callback = () => {}) { - const request = new Request('') - const defaultHeaders = { - "Accept": "*/*", - "Content-Type": "application/json" - } - - request.url = url - request.method = 'GET' - request.headers = { - ...headers, - ...defaultHeaders - } - const data = await request.loadJSON() - callback(request.response, data) - return data -} diff --git "a/\345\260\217\344\276\277\347\255\276.js" "b/\345\260\217\344\276\277\347\255\276.js" deleted file mode 100644 index 4779c1c..0000000 --- "a/\345\260\217\344\276\277\347\255\276.js" +++ /dev/null @@ -1,354 +0,0 @@ -// Variables used by Scriptable. -// This widget was created by Max Zeryck - -/* - * Author: Enjoyee - * Github: https://github.com/Enjoyee/Scriptable - */ - -/********************************************************************/ -/****************************定义小组件****************************/ -/********************************************************************/ -const filename = Script.name() + ".jpg" -const files = FileManager.local() -const path = files.joinPath(files.documentsDirectory(), filename) - -/********************************************************************/ -// 获取外部输入的参数,格式:【文字+逗号分隔】 -let widgetInputRAW = args.widgetParameter -const defaultInput = "恭 喜,发 财" -try { - widgetInputRAW.toString() -} catch(e) { - // 默认值微博热搜 - widgetInputRAW = defaultInput -} -let inputStr = widgetInputRAW.toString() -if (inputStr.trim() == "") { - inputStr = defaultInput -} -// 获取外部输入 -const inputArr = inputStr.replace(/\,/g,",").split(",") - -/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ -// 文字颜色 -const fontColorStr = "#333333" -// 背景是否是颜色 -const colorMode = false -// 背景颜色 -const bgColorStr = "#ffffff" -// 文字默认大小 -const fonSize = 50 -/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - - -// 创建小组件 -let widget = await createWidget(inputArr) -// 运行组件 -if (!config.runsInWidget && !colorMode) { - // Determine if user has taken the screenshot. - var message - message = "图片模式支持相册随意照片&背景透明" - let options = ["图片选择","透明背景"] - let isTransparentMode = await generateAlert(message, options) - if (!isTransparentMode) { - let img = await Photos.fromLibrary() - message = "您的小部件背景已准备就绪" - const resultOptions = ["好的"] - await generateAlert(message, resultOptions) - files.writeImage(path, img) - } else { - message = "透明模式开始之前,请返回主屏幕并长按进入编辑模式。滑动到最右边的空白页并截图。" - let exitOptions = ["继续","退出以截图"] - let shouldExit = await generateAlert(message,exitOptions) - if (shouldExit) return - - // Get screenshot and determine phone size. - let img = await Photos.fromLibrary() - let height = img.size.height - let phone = phoneSizes()[height] - if (!phone) { - message = "您似乎选择了非iPhone屏幕截图的图像,或者不支持您的iPhone。请使用其他图像再试一次。" - await generateAlert(message,["好的"]) - return - } - - // Prompt for widget size and position. - message = "您想要创建什么尺寸的小部件?" - let sizes = ["Small","Medium","Large"] - let size = await generateAlert(message,sizes) - let widgetSize = sizes[size] - - message = "您想它在什么位置?" - message += (height == 1136 ? " (请注意,您的设备仅支持两行小部件,因此中间和底部选项相同。)" : "") - - // Determine image crop based on phone size. - let crop = { w: "", h: "", x: "", y: "" } - if (widgetSize == "Small") { - crop.w = phone.small - crop.h = phone.small - let positions = ["Top left","Top right","Middle left","Middle right","Bottom left","Bottom right"] - let position = await generateAlert(message,positions) - - // Convert the two words into two keys for the phone size dictionary. - let keys = positions[position].toLowerCase().split(' ') - crop.y = phone[keys[0]] - crop.x = phone[keys[1]] - - } else if (widgetSize == "Medium") { - crop.w = phone.medium - crop.h = phone.small - - // Medium and large widgets have a fixed x-value. - crop.x = phone.left - let positions = ["Top","Middle","Bottom"] - let position = await generateAlert(message,positions) - let key = positions[position].toLowerCase() - crop.y = phone[key] - - } else if(widgetSize == "Large") { - crop.w = phone.medium - crop.h = phone.large - crop.x = phone.left - let positions = ["Top","Bottom"] - let position = await generateAlert(message,positions) - - // Large widgets at the bottom have the "middle" y-value. - crop.y = position ? phone.middle : phone.top - } - - // Crop image and finalize the widget. - let imgCrop = cropImage(img, new Rect(crop.x,crop.y,crop.w,crop.h)) - - message = "您的小部件背景已准备就绪" - const resultOptions = ["好的"] - await generateAlert(message, resultOptions) - files.writeImage(path, imgCrop) - } -} - -// 最后设置小组件 -if (colorMode) { - widget.backgroundColor = new Color(bgColorStr) -} else { - widget.backgroundImage = files.readImage(path) -} -Script.setWidget(widget) -// 脚本停止 -Script.complete() -// 直接预览中等大小的小组件 -widget.presentSmall() - -/* - ************************************************************************************ - */ - -// Generate an alert with the provided array of options. -async function generateAlert(message,options) { - let alert = new Alert() - alert.message = message - - for (const option of options) { - alert.addAction(option) - } - - let response = await alert.presentAlert() - return response -} - -// Crop an image into the specified rect. -function cropImage(img,rect) { - let draw = new DrawContext() - draw.size = new Size(rect.width, rect.height) - - draw.drawImageAtPoint(img,new Point(-rect.x, -rect.y)) - return draw.getImage() -} - -// Pixel sizes and positions for widgets on all supported phones. -function phoneSizes() { - let phones = { - "2688": { - "small": 507, - "medium": 1080, - "large": 1137, - "left": 81, - "right": 654, - "top": 228, - "middle": 858, - "bottom": 1488 - }, - - "1792": { - "small": 338, - "medium": 720, - "large": 758, - "left": 54, - "right": 436, - "top": 160, - "middle": 580, - "bottom": 1000 - }, - - "2436": { - "small": 465, - "medium": 987, - "large": 1035, - "left": 69, - "right": 591, - "top": 213, - "middle": 783, - "bottom": 1353 - }, - - "2208": { - "small": 471, - "medium": 1044, - "large": 1071, - "left": 99, - "right": 672, - "top": 114, - "middle": 696, - "bottom": 1278 - }, - - "1334": { - "small": 296, - "medium": 642, - "large": 648, - "left": 54, - "right": 400, - "top": 60, - "middle": 412, - "bottom": 764 - }, - - "1136": { - "small": 282, - "medium": 584, - "large": 622, - "left": 30, - "right": 332, - "top": 59, - "middle": 399, - "bottom": 399 - } - } - return phones -} - -/* - ************************************************************************************ - */ - - - /* - =================================================================================== - */ - -// 网络请求get封装 -async function getJson({ url, headers = {} }, callback = () => {}) { - const request = new Request('') - const defaultHeaders = { - "Accept": "*/*", - "Content-Type": "application/json" - } - - request.url = `https://www.tophub.fun:8888/v2/GetAllInfoGzip?id=${hotID}&page=0` - request.method = 'GET' - request.headers = { - ...headers, - ...defaultHeaders - } - const data = await request.loadJSON() - callback(request.response, data) - return data -} - -// 请求网络图片 -async function fetchImageUrl(imgUrl) { - const req = await new Request(imgUrl) - const img = await req.loadImage() - return img -} - -// 创建组件 -async function createWidget(data) { - let w = new ListWidget() - /* - ************************************************************* - */ - // 文字颜色 - const fontColor = new Color(fontColorStr) - const shadowColor= new Color(fontColorStr, 0.8) - // 计算文字最终大小 - const realFontSize = getRealFontSize(data) - - /* - ************************************************************* - */ - w.addSpacer() - let lineSpacing = 4 - for (let index in data) { - let titleStack = w.addStack() - titleStack.addSpacer() - let title = titleStack.addText(data[index] + "") - title.font = Font.lightMonospacedSystemFont(realFontSize) - title.textColor = fontColor - title.shadowColor = shadowColor - title.shadowOffset = new Point(1,1) - title.shadowRadius = 1 // 阴影半径 - title.centerAlignText() - if(index == data.length - 1) { - lineSpacing = 0 - } - w.addSpacer(lineSpacing) - titleStack.addSpacer() - } - w.addSpacer() - - w.useDefaultPadding() - return w -} - -// 获取最终的文字大小 -function getRealFontSize(data) { - var totalStr = "" - var maxStrLength = 0 - for (let index in data) { - let str = data[index] - const length = str.length - if (length > maxStrLength) { - maxStrLength = length - } - totalStr = totalStr + str - } - log("最大行的文字长度:" + maxStrLength) - - const rowLength = 132 - const columnLength = 100 - // 一行可以显示多少个字 - const rowFontCount = Math.floor(rowLength / fonSize) - // 总共要显示多少列 - const columnFontCount = data.length - log("总共要显示多少列:" + columnFontCount) - let columnFontSize = fonSize - let gap = columnLength - columnFontCount * columnFontSize - while(gap < 0) { - columnFontSize = columnFontSize - 1 - gap = columnLength - columnFontCount * columnFontSize - } - log("列方向所需的文字大小:" + columnFontSize) - - // 最大行的文字所需长度 - let rowFontSize = fonSize - gap = rowLength - maxStrLength * rowFontSize - while(gap < 0) { - rowFontSize = rowFontSize - 1 - gap = rowLength - maxStrLength * rowFontSize - } - log("行方向所需的文字大小:" + rowFontSize) - const realFontSize = Math.min(rowFontSize, columnFontSize) - - return realFontSize -} \ No newline at end of file diff --git "a/\345\275\251\345\250\203\345\244\251\346\260\224.js" "b/\345\260\217\351\235\222\350\233\231-\345\275\251\344\272\221\347\211\210.js" similarity index 63% rename from "\345\275\251\345\250\203\345\244\251\346\260\224.js" rename to "\345\260\217\351\235\222\350\233\231-\345\275\251\344\272\221\347\211\210.js" index 7534f31..0a65dcd 100644 --- "a/\345\275\251\345\250\203\345\244\251\346\260\224.js" +++ "b/\345\260\217\351\235\222\350\233\231-\345\275\251\344\272\221\347\211\210.js" @@ -1,17 +1,43 @@ -/* - * Enjoyee - * https://github.com/Enjoyee/Scriptable - */ +//------------------------------------------------ +const env = importModule('Env-lsp.js') +//------------------------------------------------ +// 配置区 +env.configs.previewSize = "Large" // 预览大小【小:Small,中:Medium,大:Large】 +env.configs.changePicBg = false // 是否需要更换背景 +env.configs.colorMode = false // 是否是纯色背景 +env.configs.bgColor = new Color("000000") // 小组件背景色 +env.configs.topPadding = 0 // 内容区边距 +env.configs.leftPadding = 20 // 内容区边距 +env.configs.bottomPadding = 0 // 内容区边距 +env.configs.rightPadding = 20 // 内容区边距 +env.configs.refreshInterval = 60 // 刷新间隔,单位分钟,非精准,会有3-5分钟差距 +// +const imgStyle = env.imgStyle +const textStyle = env.textStyle +//------------------------------------------------ +// 脚本名字 +const name = Script.name() +// 组件 +const widget = new ListWidget() +const contentStack = widget.addStack() +contentStack.layoutVertically() +// 当前日期 +const currentDate = new Date() +// 年份 +const year = currentDate.getFullYear() +// 月份 +const month = currentDate.getMonth() + 1 +// 日期 +const day = currentDate.getDate() +// 小时 +const hour = currentDate.getHours() +//------------------------------------------------ -// 内容区左右边距 -const padding = { - top: 0, - left: 20, - bottom: 0, - right: 20 -} - // 彩云天气的apiKey,自己去免费申请:https://caiyunapp.com +//↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓内容区↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ +//------------------------------------------------ + +// 彩云天气的apiKey,自己去免费申请:https://caiyunapp.com const apiKey = "TAkhjf8d1nlSlspN" // 锁定地区,直接使用上述填写的地址信息不进行定位 @@ -81,48 +107,6 @@ const weatherBgs = { WIND: "http://a.animedlweb.ga/weather/bg/50d_bg.png", // 大风 WIND } -// 标题样式定义 -let textStyle = { - stack: undefined, // 加入到哪个内容栈显示 - marginStart: 0, // 开始距离,水平方向的就是左边距离,垂直方向的就是顶部距离 - marginEnd: 0, // 结束距离,水平方向的就是右边距离,垂直方向的就是底部距离 - text: "", // 显示的文字 - width: 0, // 宽 - height: 0, // 长 - lineLimit: 0, // 行数控制,0是全部展示 - font: undefined, // 字体 - textColor: undefined, // 文字颜色 -} - -// 图片样式定义 -let imgStyle = { - stack: undefined, // 加入到哪个内容栈显示 - marginStart: 0, // 开始距离,水平方向的就是左边距离,垂直方向的就是顶部距离 - marginEnd: 0, // 结束距离,水平方向的就是右边距离,垂直方向的就是底部距离 - img: undefined, // 图片资源 - width: 0, // 宽 - height: 0, // 长 - tintColor: undefined, // 图片渲染颜色 -} - - -////////////////////////////////////// -// 组件Start -const widget = new ListWidget() -const contentStack = widget.addStack() -contentStack.layoutVertically() -// 当前日期 -const currentDate = new Date() -// 年份 -const year = currentDate.getFullYear() -// 月份 -const month = currentDate.getMonth() + 1 -// 日期 -const day = currentDate.getDate() -// 小时 -const hour = currentDate.getHours() -////////////////////////////////////// - // 获取天气 const weatherInfo = await getWeather() // 农历信息 @@ -132,9 +116,9 @@ const lunarInfo = await getLunar() const timeHour = hour - 12 let weatherIco = weatherInfo.weatherIco let weatherBg = weatherInfo.weatherBg -if (timeHour >= 7) { - weatherBg = weatherBg.replace(dayBgPng, nightBgPng) - weatherIco = weatherIco.replace(dayIcPng, nightIcPng) +if (timeHour >= 6) { + weatherBg = weatherBg.replace(dayBgPng, nightBgPng) + weatherIco = weatherIco.replace(dayIcPng, nightIcPng) } // 右上角天气icon @@ -144,11 +128,11 @@ weatherIcoStack.layoutHorizontally() weatherIcoStack.addSpacer() weatherIcoStack.setPadding(0, 0, -8, 0) imgStyle.stack = weatherIcoStack -const weatherImg = await getImage(weatherIco) +const weatherImg = await env.getImage(weatherIco) imgStyle.img = weatherImg imgStyle.width = 60 imgStyle.height = 60 -addStyleImg() +env.addStyleImg() // otherInfo let formatter = new DateFormatter() @@ -165,38 +149,36 @@ textStyle.stack = otherStack textStyle.text = `${dateString} ${infoLunarText}` textStyle.font = Font.systemFont(14) textStyle.textColor = new Color("ffffff", 0.8) -addStyleText() +env.addStyleText() // 温度 textStyle.stack = otherStack textStyle.text = `${weatherInfo.temperature}°C` textStyle.font = Font.systemFont(32) textStyle.textColor = new Color("ffffff", 0.9) -addStyleText() +env.addStyleText() // 体感温度 textStyle.stack = otherStack textStyle.text = `Feels like ${weatherInfo.bodyFeelingTemperature}°C, ${weatherInfo.weather}` textStyle.font = Font.systemFont(14) textStyle.textColor = new Color("ffffff", 0.8) -addStyleText() +env.addStyleText() // 地区 textStyle.stack = otherStack textStyle.marginStart = 2 textStyle.text = `${locationData.locality} の ${locationData.subLocality}` textStyle.font = Font.systemFont(11) textStyle.textColor = new Color("ffffff", 0.8) -addStyleText() +env.addStyleText() // contentStack.addSpacer() - - ////////////////////////////////////// // 组件End // 设置小组件的背景 -const bgImg = await getImage(weatherBg) +const bgImg = await env.getImage(weatherBg) widget.backgroundImage = bgImg // 设置边距(上,左,下,右) -widget.setPadding(padding.top, padding.left, padding.bottom, padding.right) +widget.setPadding(env.configs.topPadding, env.configs.leftPadding, env.configs.bottomPadding, env.configs.rightPadding) // 设置组件 Script.setWidget(widget) // 完成脚本 @@ -205,8 +187,7 @@ Script.complete() widget.presentLarge() ////////////////////////////////////// - - +//================================================ /* ************************************** * 获取彩云天气 @@ -218,7 +199,7 @@ async function getWeather() { log("定位信息:" + location.locality + "·" + location.subLocality) // 彩云天气域名 const DOMAIN = `https://api.caiyunapp.com/v2.5/${apiKey}/${location.longitude},${location.latitude}/weather.json?alert=true` - const weatherJsonData = await getJson(DOMAIN) + const weatherJsonData = await env.getJson(DOMAIN) if (weatherJsonData.status == "ok") { log("天气数据请求成功") // 天气突发预警 @@ -325,67 +306,12 @@ function airQuality(levelNum) { */ async function getLocation() { if (!lockLocation) { - try { - const location = await Location.current() - const geocode = await Location.reverseGeocode(location.latitude, location.longitude, "zh_cn") - locationData.latitude = location.latitude - locationData.longitude = location.longitude - const geo = geocode[0] - // 市 - if (locationData.locality == undefined) { - locationData.locality = geo.locality - } - // 区 - if (locationData.subLocality == undefined) { - locationData.subLocality = geo.subLocality - } - // 街道 - locationData.street = geo.thoroughfare - log("定位信息:latitude=" + location.latitude + ",longitude=" + location.longitude + ",locality=" - + locationData.locality + ",subLocality=" + locationData.subLocality + ",street=" + locationData.street) - } catch (e) { - log("定位出错了," + e.toString()) - } + locationData = await env.getLocation() } return locationData } - -/* -**************************************************************************** -* 网络请求get封装 -**************************************************************************** -*/ -async function getJson(url) { - const request = new Request(url) - const defaultHeaders = { - "Accept": "*/*", - "Content-Type": "application/json" - } - - request.url = url - request.method = 'GET' - request.headers = defaultHeaders - - const data = await request.loadJSON() - - return data -} - - -/* -**************************************************************************** -* 网络请求获取图片 -**************************************************************************** -*/ -async function getImage(url) { - const request = new Request(url) - const image = await request.loadImage() - return image -} - - /* ************************************** * 在线获取农历信息 @@ -407,101 +333,5 @@ async function getLunar() { return data } - -/* -**************************************************************************** -* 重置文本样式 -**************************************************************************** -*/ -function resetTextStyle() { - textStyle.stack = undefined // 加入到哪个内容栈显示 - textStyle.marginStart = 0 - textStyle.marginEnd = 0 - textStyle.text = "" // 显示的文字 - textStyle.width = 0 // 宽 - textStyle.height = 0 // 长 - textStyle.lineLimit = 0 // 行数控制,0是全部展示 - textStyle.font = undefined // 字体 - textStyle.textColor = undefined // 文字颜色 -} - - -/* -**************************************************************************** -* 重置图片样式 -**************************************************************************** -*/ -function resetImgStyle() { - imgStyle.stack = undefined // 加入到哪个内容栈显示 - textStyle.marginStart = 0 - textStyle.marginEnd = 0 - imgStyle.img = undefined // 图片资源 - imgStyle.width = 0 // 宽 - imgStyle.height = 0 // 长 - imgStyle.tintColor = undefined // 图片渲染颜色 -} - - -/* -**************************************************************************** -* 添加一行文本数据进行显示 -**************************************************************************** -*/ -function addStyleText() { - const contentStack = textStyle.stack - if (contentStack == undefined) { - return - } - - const marginStart = textStyle.marginStart - if (marginStart != undefined && marginStart != 0) { - contentStack.addSpacer(marginStart) - } - - const textSpan = contentStack.addText(`${textStyle.text}`) - contentStack.size = new Size(textStyle.width, textStyle.height) - textSpan.lineLimit = textStyle.lineLimit - textSpan.font = textStyle.font - textSpan.textColor = textStyle.textColor - - const marginEnd = textStyle.marginEnd - if (marginStart != undefined && marginStart != 0) { - contentStack.addSpacer(marginEnd) - } - - // 重置样式 - resetTextStyle() -} - - -/* -**************************************************************************** -* 添加图片进行显示 -**************************************************************************** -*/ -function addStyleImg() { - const contentStack = imgStyle.stack - if (contentStack == undefined) { - return - } - - const marginStart = textStyle.marginStart - if (marginStart != undefined && marginStart != 0) { - contentStack.addSpacer(marginStart) - } - - const imgSpan = contentStack.addImage(imgStyle.img) - imgSpan.imageSize = new Size(imgStyle.width, imgStyle.height) - const tintColor = imgStyle.tintColor - if (tintColor != undefined) { - imgSpan.tintColor = tintColor - } - - const marginEnd = textStyle.marginEnd - if (marginStart != undefined && marginStart != 0) { - contentStack.addSpacer(marginEnd) - } - - // 重置样式 - resetImgStyle() -} +//------------------------------------------------ +//↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑内容区↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ diff --git "a/\345\270\203\346\234\227-\345\217\257\345\246\256.js" "b/\345\270\203\346\234\227-\345\217\257\345\246\256.js" new file mode 100644 index 0000000..c8decee --- /dev/null +++ "b/\345\270\203\346\234\227-\345\217\257\345\246\256.js" @@ -0,0 +1,538 @@ +//------------------------------------------------ +const env = importModule('Env-lsp.js') +//------------------------------------------------ +// 配置区 +env.configs.previewSize = "Small" // 预览大小【小:Small,中:Medium,大:Large】 +env.configs.changePicBg = true // 是否需要更换背景 +env.configs.colorMode = false // 是否是纯色背景 +env.configs.bgColor = new Color("000000") // 小组件背景色 +env.configs.topPadding = 0 // 内容区边距 +env.configs.leftPadding = 0 // 内容区边距 +env.configs.bottomPadding = 0 // 内容区边距 +env.configs.rightPadding = 0 // 内容区边距 +env.configs.refreshInterval = 30 // 刷新间隔,单位分钟,非精准,会有3-5分钟差距 +// 文件 +const fm = FileManager.local() +// +const imgStyle = env.imgStyle +const textStyle = env.textStyle +//------------------------------------------------ +// 脚本名字 +const name = Script.name() +// 组件 +const widget = new ListWidget() +const contentStack = widget.addStack() +//------------------------------------------------ + + +//↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓内容区↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ +//------------------------------------------------ +// 图片数组 +const imgObjs = [ + "https://stickershop.line-scdn.net/stickershop/v1/sticker/18247802/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/18247803/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/18247804/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/18247805/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/18247806/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/18247807/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/18247808/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/18247809/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/18247810/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/18247811/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/18247812/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/18247813/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/18247814/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/18247815/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/18247816/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/18247817/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/18247818/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/18247819/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/18247820/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/18247821/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/18247822/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/18247823/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/18247824/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/18247825/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/15047/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/15048/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/15049/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/15050/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/15051/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/15052/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/15053/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/15054/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/15055/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/15056/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/15057/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/15058/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/15059/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/15060/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/15061/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/15062/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/15063/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/15064/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/15065/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/15066/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/15067/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/15068/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/15069/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/15070/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/15071/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/15072/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/15073/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/15074/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/15075/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/15076/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/15077/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/15078/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/15079/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/15080/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/15081/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/15082/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/15083/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/15084/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/15085/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/15086/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/72822926/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/72822927/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/72822928/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/72822929/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/72822930/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/72822931/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/72822932/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/72822933/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/72822934/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/72822935/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/72822936/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/72822937/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/72822938/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/72822939/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/72822940/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/72822941/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/72822942/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/72822943/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/72822944/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/72822945/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/72822946/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/72822947/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/72822948/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/72822949/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/27322/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/27323/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/27324/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/27325/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/27326/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/27327/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/27328/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/27329/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/27330/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/27331/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/27332/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/27333/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/27334/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/27335/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/27336/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/27337/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/27338/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/27339/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/27340/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/27341/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/27342/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/27343/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/27344/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/27345/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/27346/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/27347/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/27348/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/27349/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/27350/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/27351/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/27352/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/27353/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/27354/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/27355/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/27356/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/27357/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/27358/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/27359/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/27360/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/27361/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/49279742/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/49279743/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/49279744/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/49279745/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/49279746/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/49279747/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/49279748/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/49279749/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/49279750/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/49279751/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/49279752/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/49279753/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/49279754/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/49279755/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/49279756/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/49279757/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/49279758/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/49279759/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/49279760/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/49279761/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/49279762/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/49279763/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/49279764/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/49279765/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/13937750/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/13937751/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/13937752/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/13937753/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/13937754/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/13937755/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/13937756/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/13937757/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/13937758/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/13937759/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/13937760/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/13937761/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/13937762/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/13937763/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/13937764/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/13937765/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/13937766/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/13937767/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/13937768/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/13937769/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/13937770/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/13937771/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/13937772/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/13937773/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/14585982/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/14585983/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/14585984/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/14585985/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/14585986/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/14585987/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/14585988/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/14585989/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/14585990/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/14585991/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/14585992/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/14585993/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/14585994/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/14585995/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/14585996/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/14585997/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/14585998/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/14585999/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/14586000/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/14586001/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/14586002/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/14586003/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/14586004/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/14586005/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/11470496/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/11470497/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/11470498/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/11470499/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/11470500/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/11470501/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/11470502/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/11470503/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/11470504/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/11470505/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/11470506/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/11470507/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/11470508/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/11470509/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/11470510/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/11470511/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/4001/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/4002/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/4003/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/4004/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/4005/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/4006/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/4007/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/4008/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/4009/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/4010/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/4011/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/4012/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/4013/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/4014/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/4015/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/4016/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/4017/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/4018/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/4019/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/4020/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/4021/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/4022/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/4023/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/4024/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/4025/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/4026/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/4027/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/4028/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/4029/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/4030/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/4031/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/4032/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/4033/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/4034/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/4035/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/4036/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/4037/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/4038/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/4039/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/4040/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/11088016/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/11088017/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/11088018/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/11088019/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/11088020/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/11088021/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/11088022/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/11088023/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/11088024/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/11088025/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/11088026/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/11088027/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/11088028/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/11088029/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/11088030/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/11088031/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/11088032/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/11088033/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/11088034/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/11088035/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/11088036/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/11088037/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/11088038/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/11088039/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/16581266/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/16581267/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/16581268/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/16581269/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/16581270/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/16581271/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/16581272/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/16581273/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/16581274/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/16581275/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/16581276/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/16581277/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/16581278/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/16581279/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/16581280/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/16581281/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/16581282/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/16581283/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/16581284/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/16581285/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/16581286/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/16581287/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/16581288/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/16581289/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/35128160/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/35128161/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/35128162/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/35128163/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/35128164/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/35128165/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/35128166/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/35128167/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/35128168/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/35128169/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/35128170/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/35128171/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/35128172/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/35128173/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/35128174/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/35128175/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/35128176/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/35128177/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/35128178/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/35128179/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/35128180/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/35128181/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/35128182/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/35128183/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/183719790/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/183719791/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/183719792/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/183719793/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/183719794/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/183719795/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/183719796/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/183719797/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/183719798/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/183719799/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/183719800/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/183719801/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/183719802/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/183719803/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/183719804/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/183719805/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/183719806/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/183719807/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/183719808/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/183719809/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/183719810/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/183719811/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/183719812/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/183719813/iPhone/sticker@2x.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/239459438/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/239459439/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/239459440/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/239459441/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/239459442/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/239459443/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/239459444/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/239459445/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/239459446/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/239459447/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/239459448/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/239459449/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/239459450/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/239459451/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/239459452/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/239459453/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/239459454/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/239459455/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/239459456/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/239459457/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/239459458/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/239459459/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/239459460/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/239459461/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/239459462/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/239459463/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/239459464/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/239459465/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/239459466/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/239459467/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/239459468/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/239459469/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/239459470/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/239459471/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/239459472/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/239459473/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/239459474/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/239459475/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/239459476/android/sticker.png", + "https://stickershop.line-scdn.net/stickershop/v1/sticker/239459477/android/sticker.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5e156074040ab1eeafb83e32/iPhone/001.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5e156074040ab1eeafb83e32/iPhone/002.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5e156074040ab1eeafb83e32/iPhone/003.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5e156074040ab1eeafb83e32/iPhone/004.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5e156074040ab1eeafb83e32/iPhone/005.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5e156074040ab1eeafb83e32/iPhone/006.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5e156074040ab1eeafb83e32/iPhone/007.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5e156074040ab1eeafb83e32/iPhone/008.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5e156074040ab1eeafb83e32/iPhone/009.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5e156074040ab1eeafb83e32/iPhone/010.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5e156074040ab1eeafb83e32/iPhone/011.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5e156074040ab1eeafb83e32/iPhone/012.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5e156074040ab1eeafb83e32/iPhone/013.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5e156074040ab1eeafb83e32/iPhone/014.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5e156074040ab1eeafb83e32/iPhone/015.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5e156074040ab1eeafb83e32/iPhone/016.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5e156074040ab1eeafb83e32/iPhone/017.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5e156074040ab1eeafb83e32/iPhone/018.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5e156074040ab1eeafb83e32/iPhone/019.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5e156074040ab1eeafb83e32/iPhone/020.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5e156074040ab1eeafb83e32/iPhone/021.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5e156074040ab1eeafb83e32/iPhone/022.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5e156074040ab1eeafb83e32/iPhone/023.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5e156074040ab1eeafb83e32/iPhone/024.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5e156074040ab1eeafb83e32/iPhone/025.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5e156074040ab1eeafb83e32/iPhone/026.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5e156074040ab1eeafb83e32/iPhone/027.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5e156074040ab1eeafb83e32/iPhone/028.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5e156074040ab1eeafb83e32/iPhone/029.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5e156074040ab1eeafb83e32/iPhone/030.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5e156074040ab1eeafb83e32/iPhone/031.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5e156074040ab1eeafb83e32/iPhone/032.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5e156074040ab1eeafb83e32/iPhone/033.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5e156074040ab1eeafb83e32/iPhone/034.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5e156074040ab1eeafb83e32/iPhone/035.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5e156074040ab1eeafb83e32/iPhone/036.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5e156074040ab1eeafb83e32/iPhone/037.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5e156074040ab1eeafb83e32/iPhone/038.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5e156074040ab1eeafb83e32/iPhone/039.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5e156074040ab1eeafb83e32/iPhone/040.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5ac309f0031a6752fb806d8d/iPhone/001.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5ac309f0031a6752fb806d8d/iPhone/002.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5ac309f0031a6752fb806d8d/iPhone/003.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5ac309f0031a6752fb806d8d/iPhone/004.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5ac309f0031a6752fb806d8d/iPhone/005.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5ac309f0031a6752fb806d8d/iPhone/006.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5ac309f0031a6752fb806d8d/iPhone/007.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5ac309f0031a6752fb806d8d/iPhone/008.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5ac309f0031a6752fb806d8d/iPhone/009.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5ac309f0031a6752fb806d8d/iPhone/010.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5ac309f0031a6752fb806d8d/iPhone/011.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5ac309f0031a6752fb806d8d/iPhone/012.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5ac309f0031a6752fb806d8d/iPhone/013.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5ac309f0031a6752fb806d8d/iPhone/014.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5ac309f0031a6752fb806d8d/iPhone/015.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5ac309f0031a6752fb806d8d/iPhone/016.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5ac309f0031a6752fb806d8d/iPhone/017.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5ac309f0031a6752fb806d8d/iPhone/018.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5ac309f0031a6752fb806d8d/iPhone/019.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5ac309f0031a6752fb806d8d/iPhone/020.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5ac309f0031a6752fb806d8d/iPhone/021.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5ac309f0031a6752fb806d8d/iPhone/022.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5ac309f0031a6752fb806d8d/iPhone/023.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5ac309f0031a6752fb806d8d/iPhone/024.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5ac309f0031a6752fb806d8d/iPhone/025.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5ac309f0031a6752fb806d8d/iPhone/026.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5ac309f0031a6752fb806d8d/iPhone/027.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5ac309f0031a6752fb806d8d/iPhone/028.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5ac309f0031a6752fb806d8d/iPhone/029.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5ac309f0031a6752fb806d8d/iPhone/030.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5ac309f0031a6752fb806d8d/iPhone/031.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5ac309f0031a6752fb806d8d/iPhone/032.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5ac309f0031a6752fb806d8d/iPhone/033.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5ac309f0031a6752fb806d8d/iPhone/034.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5ac309f0031a6752fb806d8d/iPhone/035.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5ac309f0031a6752fb806d8d/iPhone/036.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5ac309f0031a6752fb806d8d/iPhone/037.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5ac309f0031a6752fb806d8d/iPhone/038.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5ac309f0031a6752fb806d8d/iPhone/039.png", + "https://stickershop.line-scdn.net/sticonshop/v1/sticon/5ac309f0031a6752fb806d8d/iPhone/040.png" +] + +// 索引 +const key = parseInt(Math.random() * imgObjs.length).toString() +let imgUrl = imgObjs[key] +if(imgUrl == undefined) { + imgUrl = imgObjs[0] +} +// 缓存目录 +const cachePath = fm.joinPath(fm.documentsDirectory(), "lsp-lovely-cache") + +let img = undefined +if (env.useCache(cachePath)) { + img = fm.readImage(cachePath) +} else { + try { + img = await env.getImage(imgUrl) + fm.writeImage(cachePath, img) + } catch(e) { + img = fm.readImage(cachePath) + } +} + +imgStyle.stack = contentStack +imgStyle.width = 170 +imgStyle.height = 170 +imgStyle.img = img +env.addStyleImg() +//------------------------------------------------ +//↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑内容区↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ + +//------------------------------------------------ +// 运行脚本、预览 +await env.run(name, widget) +//------------------------------------------------ diff --git "a/\345\275\251\344\272\221\345\215\225\350\241\214\347\211\210\346\234\254.js" "b/\345\275\251\344\272\221\345\215\225\350\241\214\347\211\210\346\234\254.js" new file mode 100644 index 0000000..b5da8a3 --- /dev/null +++ "b/\345\275\251\344\272\221\345\215\225\350\241\214\347\211\210\346\234\254.js" @@ -0,0 +1,810 @@ +const env = importModule('Env-lsp.js') +//------------------------------------------------ +// 配置区 +env.configs.previewSize = "Medium" // 预览大小【小:Small,中:Medium,大:Large】 +env.configs.changePicBg = true // 是否需要更换背景 +env.configs.colorMode = false // 是否是纯色背景 +env.configs.bgColor = new Color("000000") // 小组件背景色 +env.configs.topPadding = 2 // 内容区边距 +env.configs.leftPadding = 2 // 内容区边距 +env.configs.bottomPadding = 2 // 内容区边距 +env.configs.rightPadding = 2 // 内容区边距 +env.configs.refreshInterval = 10 // 刷新间隔,单位分钟,非精准,会有3-5分钟差距 +////////////////////////////////// +const imgStyle = env.imgStyle +const textStyle = env.textStyle +///////////////////////////////// + +// 地区 +const locale = "zh_cn" + +// 彩云天气的apiKey,自己去免费申请:https://caiyunapp.com +const apiKey = "" + +// 默认的定位信息,定位失败的时候默认读取 +// https://open.caiyunapp.com/File:Adcode-release-2020-06-10.xlsx.zip +// 上述链接查看对应地区的详细经纬度 +let locationData = { + "latitude": undefined, + "longitude": undefined, + "locality": undefined, + "subLocality": undefined +} +// 锁定地区,直接使用上述填写的地址信息不进行定位 +const lockLocation = false + +// 天气是否使用了上次的缓存 +let isUsedLastCache = false + +// 日程显示条数 +const maxSchedules = 1 + +// 顶部问候语,英文花样文字:https://beizhedenglong.github.io/weird-fonts/ +const greetingText = { + nightGreeting: "𝑇𝑖𝑚𝑒 𝑡𝑜 𝑔𝑒𝑡 𝑙𝑎𝑖𝑑~", + morningGreeting: "𝐺𝑜𝑜𝑑 𝑚𝑜𝑟𝑛𝑖𝑛𝑔~", + noonGreeting: "𝐺𝑜𝑜𝑑 𝑛𝑜𝑜𝑛~", + afternoonGreeting: "𝐺𝑜𝑜𝑑 𝑎𝑓𝑡𝑒𝑟𝑛𝑜𝑜𝑛~", + eveningGreeting: "𝐺𝑜𝑜𝑑 𝑒𝑣𝑒𝑛𝑖𝑛𝑔~" +} + +// 自定义日期对应的问候 +const anniversaryText = { + "1-1": "年之伊始,万事如意~", + "10-1": "举国同庆,与国同欢~" +} + +// 天气对应的icon +const weatherIcos = { + CLEAR_DAY: "https://s1.ax1x.com/2020/11/04/BcdaTJ.png", // 晴(白天) CLEAR_DAY + CLEAR_NIGHT: "https://s1.ax1x.com/2020/10/26/BukPhR.png", // 晴(夜间) CLEAR_NIGHT + PARTLY_CLOUDY_DAY: "https://s1.ax1x.com/2020/10/26/BuQHN6.png", // 多云(白天) PARTLY_CLOUDY_DAY + PARTLY_CLOUDY_NIGHT: "https://s1.ax1x.com/2020/10/26/BukcbF.png", // 多云(夜间) PARTLY_CLOUDY_NIGHT + CLOUDY: "https://s1.ax1x.com/2020/10/26/BuAbQ0.png", // 阴(白天) CLOUDY + CLOUDY_NIGHT: "https://s1.ax1x.com/2020/10/26/BuEmYd.png", // 阴(夜间) CLOUDY + LIGHT_HAZE: "https://s1.ax1x.com/2020/10/26/BuKk34.png", // 轻度雾霾 LIGHT_HAZE + MODERATE_HAZE: "https://s1.ax1x.com/2020/10/26/BuKk34.png", // 中度雾霾 MODERATE_HAZE + HEAVY_HAZE: "https://s1.ax1x.com/2020/10/26/BuKk34.png", // 重度雾霾 HEAVY_HAZE + LIGHT_RAIN: "https://s1.ax1x.com/2020/10/26/BuZTWd.png", // 小雨 LIGHT_RAIN + MODERATE_RAIN: "https://s1.ax1x.com/2020/10/26/BunhwV.png", // 中雨 MODERATE_RAIN + HEAVY_RAIN: "https://s1.ax1x.com/2020/10/26/BueSYQ.png", // 大雨 HEAVY_RAIN + STORM_RAIN: "https://s1.ax1x.com/2020/10/26/BueSYQ.png", // 暴雨 STORM_RAIN + FOG: "https://s1.ax1x.com/2020/10/26/BueAmV.png", // 雾 FOG + LIGHT_SNOW: "https://s1.ax1x.com/2020/10/26/BueW1s.png", // 小雪 LIGHT_SNOW + MODERATE_SNOW: "https://s1.ax1x.com/2020/10/26/BueW1s.png", // 中雪 MODERATE_SNOW + HEAVY_SNOW: "https://s1.ax1x.com/2020/10/26/BueXcR.png", // 大雪 HEAVY_SNOW + STORM_SNOW: "https://s1.ax1x.com/2020/10/26/BumM4g.png", // 暴雪 STORM_SNOW + DUST: "https://s1.ax1x.com/2020/10/26/BumW5D.png", // 浮尘 DUST + SAND: "https://s1.ax1x.com/2020/10/26/Bunez9.png", // 沙尘 SAND + WIND: "https://s1.ax1x.com/2020/10/26/BunEiF.png", // 大风 WIND +} + +// 默认字体颜色 +const defaultTextColor = new Color("ffffff") + +////////////////////////////////////////// +// 当前日期 +const currentDate = new Date() +// 年份 +const year = currentDate.getFullYear() +// 月份 +const month = currentDate.getMonth() + 1 +// 日期 +const day = currentDate.getDate() +// 小时 +const hour = currentDate.getHours() +// 分钟 +const minute = currentDate.getMinutes() +//------------------------------------------------ +// 脚本名字 +const name = Script.name() +// 文件 +const fm = FileManager.local() +//------------------------------------------------ + + +//↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓内容区↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ +//------------------------------------------------ + + +/****************************小组件内容START****************************/ +// 彩云天气信息 +const weatherInfo = await getWeather() +// 农历信息 +const lunarInfo = await getLunar() + + +////////////////////////////////////////// +// 内容排版 +const widget = new ListWidget() +let contentStack = widget.addStack() +contentStack.layoutVertically() +// 整体内容居中对齐 +contentStack.centerAlignContent() +////////////////////////////////////////// + + +//>>>>>1 +let titleStack = env.alignHorizontallyCenterStack(contentStack) +titleStack.addSpacer() +// 天气Icon +// 缓存目录 +const weatherImgCachePath = fm.joinPath(fm.documentsDirectory(), "lsp-weatherImg-cache-env") +let weatherImg = undefined +try { + weatherImg = await env.getImage(weatherInfo.weatherIco) + fm.writeImage(weatherImgCachePath, weatherImg) + log(`天气icon写入缓存`) +} catch (e) { + weatherImg = fm.readImage(weatherImgCachePath) + log(`读取天气icon缓存`) +} +// 显示天气 +imgStyle.stack = titleStack +imgStyle.width = 38 +imgStyle.height = 38 +imgStyle.img = weatherImg +env.addStyleImg() +// 体感温度 +titleStack.addSpacer(4) +const bodyFeelingTemperature = weatherInfo.bodyFeelingTemperature +// 显示体感温度 +textStyle.stack = titleStack +textStyle.text = `${bodyFeelingTemperature}°C` +textStyle.lineLimit = 1 +textStyle.font = Font.regularSystemFont(21) +textStyle.textColor = defaultTextColor +env.addStyleText() +////////////////////////////////// +// 添加显示符号 +textStyle.stack = titleStack +textStyle.marginStart = 6 +textStyle.text = `❦` +textStyle.font = Font.systemFont(16) +textStyle.textColor = defaultTextColor +textStyle.lineLimit = 1 +env.addStyleText() +// 问候语获取内容 +const greeting = provideGreeting(currentDate) +// 添加显示标题 +textStyle.stack = titleStack +textStyle.marginStart = 6 +textStyle.text = `${greeting}` +textStyle.font = Font.systemFont(21) +textStyle.textColor = defaultTextColor +textStyle.lineLimit = 1 +env.addStyleText() +titleStack.addSpacer() + + + +///////////////////////////////////////////////////////////// +//>>>>>2 +// 年月日周 +contentStack.addSpacer(4) +let dateStack = env.alignHorizontallyCenterStack(contentStack) +dateStack.addSpacer() +const dateStr = env.getDateStr(currentDate, "MM月dd日 EEE") +// 农历信息 +const lunarData = lunarInfo.data[0] +let infoLunarText = lunarData.lunarText +infoLunarText = infoLunarText.substring(5, infoLunarText.length) +// 节假期信息 +const lunarHoliday = lunarData.calendarDay.lunarHoliday.key +const solarHoliday = lunarData.calendarDay.solarHoliday.key +// 农历节气 +const solarTerm = lunarData.calendarDay.solarTerm +const holidayText = `${lunarHoliday ? "◇ " + lunarHoliday : ""}${solarHoliday ? "◇ " + solarHoliday : ""}${solarTerm ? "◇ " + solarTerm : ""}` +log(`节假日信息:${holidayText}`) +// 显示 +textStyle.stack = dateStack +textStyle.text = `${dateStr} ${infoLunarText} ${holidayText}` +textStyle.font = Font.systemFont(15) +textStyle.textColor = new Color("ffcc99", 0.9) +textStyle.lineLimit = 1 +env.addStyleText() +dateStack.addSpacer() + + + +///////////////////////////////////////////////////////////// +//>>>>>3 +contentStack.addSpacer(8) +let weatherTipsStack = env.alignHorizontallyCenterStack(contentStack) +weatherTipsStack.addSpacer() +// 天气预警、预告信息 +const weatherAlertInfo = weatherInfo.alertWeatherTitle +let weatherDesc = weatherInfo.weatherDesc +if (weatherAlertInfo != undefined) { + weatherDesc = weatherAlertInfo +} +// 添加显示天气预告信息 +textStyle.stack = weatherTipsStack +textStyle.text = `Φ ${weatherDesc} ⊙ 指数≒${weatherInfo.comfort} Φ` +textStyle.lineLimit = 1 +textStyle.font = Font.systemFont(12) +textStyle.textColor = defaultTextColor +env.addStyleText() +weatherTipsStack.addSpacer() + + +///////////////////////////////////////////////////////////// +//>>>>>4 +contentStack.addSpacer(8) +let infoStack = env.alignHorizontallyCenterStack(contentStack) +infoStack.addSpacer() +const rand = Boolean(Math.round(Math.random())) +// 内容 +let contentInfo = undefined +if (rand) { + // 请求今日诗词 + const poetry = await getPoetry() + const poetryInfo = poetry.data + const authorText = `⊱${poetryInfo.origin.dynasty}·${poetryInfo.origin.author}⊰` + contentInfo = `“${poetryInfo.content.substring(0, poetryInfo.content.length - 1)}” ━ ${authorText}` +} else { + // 请求丁香医生健康日历 + const dxHealthCalendar = await getDxHealthCalendar() + contentInfo = `“${dxHealthCalendar}” ━ ⊱丁香医生⊰` +} + +// 添加今日tips +// 背景 +infoStack.backgroundColor = new Color("666", 0.3) +infoStack.cornerRadius = 4 +infoStack.setPadding(6, 6, 6, 6) +// 添加内容 +textStyle.stack = infoStack +textStyle.text = contentInfo +textStyle.lineLimit = 1 +textStyle.font = Font.lightMonospacedSystemFont(11) +textStyle.textColor = new Color("ffffff", 0.7) +env.addStyleText() +infoStack.addSpacer() + + + +///////////////////////////////////////////////////////////// +//>>>>>5 +let useLovelyCache = false +contentStack.addSpacer(8) +let updateStack = env.alignHorizontallyCenterStack(contentStack) +updateStack.addSpacer() + +// 显示底部图标栏1 +// 缓存目录 +let lovelyImgCachePath1 = fm.joinPath(fm.documentsDirectory(), "lsp-lovely1-cache-env") +let lovelyImg1 = undefined +if (useLovelyCache) { + lovelyImg1 = fm.readImage(lovelyImgCachePath1) + log(`读取lovely icon缓存`) +} else { + try { + lovelyImg1 = await env.getImage("https://s1.ax1x.com/2020/11/05/BWQDOJ.png") + fm.writeImage(lovelyImgCachePath1, lovelyImg1) + log(`lovely icon写入缓存`) + } catch (e) { + lovelyImg1 = fm.readImage(lovelyImgCachePath1) + log(`读取lovely icon缓存`) + } +} +imgStyle.stack = updateStack +imgStyle.width = 18 +imgStyle.height = 18 +imgStyle.img = lovelyImg1 +env.addStyleImg() +updateStack.addSpacer(10) + +// 显示底部图标栏2 +// 缓存目录 +let lovelyImgCachePath2 = fm.joinPath(fm.documentsDirectory(), "lsp-lovely2-cache-env") +let lovelyImg2 = undefined +if (useLovelyCache) { + lovelyImg2 = fm.readImage(lovelyImgCachePath2) + log(`读取lovely icon缓存`) +} else { + try { + lovelyImg2 = await env.getImage("https://s1.ax1x.com/2020/11/05/BW1yPx.png") + fm.writeImage(lovelyImgCachePath2, lovelyImg2) + log(`lovely icon写入缓存`) + } catch (e) { + lovelyImg2 = fm.readImage(lovelyImgCachePath2) + log(`读取lovely icon缓存`) + } +} +imgStyle.stack = updateStack +imgStyle.width = 18 +imgStyle.height = 18 +imgStyle.img = lovelyImg2 +env.addStyleImg() +updateStack.addSpacer(10) + +// 显示底部图标栏3 +// 缓存目录 +let lovelyImgCachePath3 = fm.joinPath(fm.documentsDirectory(), "lsp-lovely3-cache-env") +let lovelyImg3 = undefined +if (useLovelyCache) { + lovelyImg3 = fm.readImage(lovelyImgCachePath3) + log(`读取lovely icon缓存`) +} else { + try { + lovelyImg3 = await env.getImage("https://s1.ax1x.com/2020/11/05/BRhoy8.png") + fm.writeImage(lovelyImgCachePath3, lovelyImg3) + log(`lovely icon写入缓存`) + } catch (e) { + lovelyImg3 = fm.readImage(lovelyImgCachePath3) + log(`读取lovely icon缓存`) + } +} +imgStyle.stack = updateStack +imgStyle.width = 18 +imgStyle.height = 18 +imgStyle.img = lovelyImg3 +env.addStyleImg() +updateStack.addSpacer(10) + +// 显示底部图标栏4 +// 缓存目录 +let lovelyImgCachePath4 = fm.joinPath(fm.documentsDirectory(), "lsp-lovely4-cache-env") +let lovelyImg4 = undefined +if (useLovelyCache) { + lovelyImg4 = fm.readImage(lovelyImgCachePath4) + log(`读取lovely icon缓存`) +} else { + try { + lovelyImg4 = await env.getImage("https://s1.ax1x.com/2020/11/05/BR4pOU.png") + fm.writeImage(lovelyImgCachePath4, lovelyImg4) + log(`lovely icon写入缓存`) + } catch (e) { + lovelyImg4 = fm.readImage(lovelyImgCachePath4) + log(`读取lovely icon缓存`) + } +} +imgStyle.stack = updateStack +imgStyle.width = 18 +imgStyle.height = 18 +imgStyle.img = lovelyImg4 +env.addStyleImg() +updateStack.addSpacer(10) + +// 添加更新时间 +textStyle.stack = updateStack +textStyle.text = `update at ${env.getDateStr(new Date(), "HH:mm")}` +textStyle.lineLimit = 1 +textStyle.font = Font.thinSystemFont(10) +textStyle.textColor = new Color("ffffff", 0.6) +env.addStyleText() +updateStack.addSpacer(6) + +// 显示底部图标栏5 +// 缓存目录 +let lovelyImgCachePath5 = fm.joinPath(fm.documentsDirectory(), "lsp-lovely5-cache-env") +let lovelyImg5 = undefined +if (useLovelyCache) { + lovelyImg5 = fm.readImage(lovelyImgCachePath5) + log(`读取lovely icon缓存`) +} else { + try { + lovelyImg5 = await env.getImage("https://s1.ax1x.com/2020/11/05/BR4Pw4.png") + fm.writeImage(lovelyImgCachePath5, lovelyImg5) + log(`lovely icon写入缓存`) + } catch (e) { + lovelyImg5 = fm.readImage(lovelyImgCachePath5) + log(`读取lovely icon缓存`) + } +} +imgStyle.stack = updateStack +imgStyle.width = 18 +imgStyle.height = 18 +imgStyle.img = lovelyImg5 +env.addStyleImg() +updateStack.addSpacer(10) + +// 显示底部图标栏6 +// 缓存目录 +let lovelyImgCachePath6 = fm.joinPath(fm.documentsDirectory(), "lsp-lovely6-cache-env") +let lovelyImg6 = undefined +if (useLovelyCache) { + lovelyImg6 = fm.readImage(lovelyImgCachePath6) + log(`读取lovely icon缓存`) +} else { + try { + lovelyImg6 = await env.getImage("https://s1.ax1x.com/2020/11/05/BR4kk9.png") + fm.writeImage(lovelyImgCachePath6, lovelyImg6) + log(`lovely icon写入缓存`) + } catch (e) { + lovelyImg6 = fm.readImage(lovelyImgCachePath6) + log(`读取lovely icon缓存`) + } +} +imgStyle.stack = updateStack +imgStyle.width = 18 +imgStyle.height = 18 +imgStyle.img = lovelyImg6 +env.addStyleImg() +updateStack.addSpacer(10) + +// 显示底部图标栏7 +// 缓存目录 +let lovelyImgCachePath7 = fm.joinPath(fm.documentsDirectory(), "lsp-lovely7-cache-env") +let lovelyImg7 = undefined +if (useLovelyCache) { + lovelyImg7 = fm.readImage(lovelyImgCachePath7) + log(`读取lovely icon缓存`) +} else { + try { + lovelyImg7 = await env.getImage("https://s1.ax1x.com/2020/11/05/BR4Ef1.png") + fm.writeImage(lovelyImgCachePath7, lovelyImg7) + log(`lovely icon写入缓存`) + } catch (e) { + lovelyImg7 = fm.readImage(lovelyImgCachePath7) + log(`读取lovely icon缓存`) + } +} +imgStyle.stack = updateStack +imgStyle.width = 18 +imgStyle.height = 18 +imgStyle.img = lovelyImg7 +env.addStyleImg() +updateStack.addSpacer(10) + +// 显示底部图标栏8 +// 缓存目录 +let lovelyImgCachePath8 = fm.joinPath(fm.documentsDirectory(), "lsp-lovely8-cache-env") +let lovelyImg8 = undefined +if (useLovelyCache) { + lovelyImg8 = fm.readImage(lovelyImgCachePath8) + log(`读取lovely icon缓存`) +} else { + try { + lovelyImg8 = await env.getImage("https://s1.ax1x.com/2020/11/05/BWnaKs.png") + fm.writeImage(lovelyImgCachePath8, lovelyImg8) + log(`lovely icon写入缓存`) + } catch (e) { + lovelyImg8 = fm.readImage(lovelyImgCachePath8) + log(`读取lovely icon缓存`) + } +} +imgStyle.stack = updateStack +imgStyle.width = 18 +imgStyle.height = 18 +imgStyle.img = lovelyImg8 +env.addStyleImg() +updateStack.addSpacer() + +/*****************************小组件内容ENd*****************************/ + + +/* +************************************** +* 获取彩云天气 +************************************** +*/ +async function getWeather() { + // 缓存目录 + const cachePath = fm.joinPath(fm.documentsDirectory(), "lsp-caiyun-cache-env") + // 天气数据 + let weatherInfo = {} + const location = await getLocation() + log("定位信息:" + location.locality + "·" + location.subLocality) + + // 彩云天气域名 + const url = `https://api.caiyunapp.com/v2.5/${apiKey}/${location.longitude},${location.latitude}/weather.json?alert=true` + + let weatherJsonData = undefined + + try { + log('请求彩云天气信息') + weatherJsonData = await env.getJson(url, false) + // 写入缓存 + fm.writeString(cachePath, JSON.stringify(weatherJsonData)) + } catch (e) { + isUsedLastCache = true + const cache = fm.readString(cachePath) + log(`读取彩云天气缓存数据`) + weatherJsonData = JSON.parse(cache) + } + + if (weatherJsonData.status == "ok") { + log("天气数据请求成功,进行缓存") + + // 天气突发预警 + const alertWeatherTitle = weatherJsonData.result.alert.content.title + log("突发的天气预警==>" + alertWeatherTitle) + weatherInfo.alertWeatherTitle = alertWeatherTitle + + // 温度范围 + const temperatureData = weatherJsonData.result.daily.temperature[0] + // 最低温度 + const minTemperature = temperatureData.min + // 最高温度 + const maxTemperature = temperatureData.max + log("温度==>" + minTemperature + "|" + maxTemperature) + weatherInfo.minTemperature = Math.round(minTemperature) + weatherInfo.maxTemperature = Math.round(maxTemperature) + + // 体感温度 + const bodyFeelingTemperature = weatherJsonData.result.realtime.apparent_temperature + log("体感温度==>" + bodyFeelingTemperature) + weatherInfo.bodyFeelingTemperature = Math.round(bodyFeelingTemperature) + + // 天气状况 weatherIcos[weatherIco] + let weather = weatherJsonData.result.realtime.skycon + log("天气状况==>" + weather + "|" + weatherIcos[weather]) + if (hour - 12 >= 7 && weather == "CLOUDY") { + weather = "CLOUDY_NIGHT" + } + weatherInfo.weatherIco = weatherIcos[weather] + + // 天气描述 + const weatherDesc = weatherJsonData.result.forecast_keypoint + log("天气描述==>" + weatherDesc) + weatherInfo.weatherDesc = weatherDesc.replace("。还在加班么?", ",") + + // 相对湿度 + const humidity = (Math.round(weatherJsonData.result.realtime.humidity * 100)) + "%" + log("相对湿度==>" + weatherJsonData.result.realtime.humidity) + weatherInfo.humidity = humidity + + // 舒适指数 + const comfort = weatherJsonData.result.realtime.life_index.comfort.desc + log("舒适指数==>" + comfort) + weatherInfo.comfort = comfort + + // 紫外线指数 + const ultraviolet = weatherJsonData.result.realtime.life_index.ultraviolet.desc + log("紫外线指数==>" + ultraviolet) + weatherInfo.ultraviolet = ultraviolet + + // 空气质量 + const aqi = weatherJsonData.result.realtime.air_quality.aqi.chn + const aqiInfo = airQuality(aqi) + log("空气质量==>" + aqiInfo) + weatherInfo.aqiInfo = aqiInfo + + // 日出日落 + const astro = weatherJsonData.result.daily.astro[0] + // 日出 + const sunrise = astro.sunrise.time + // 日落 + const sunset = astro.sunset.time + log("日出==>" + sunrise + ",日落==>" + sunset) + weatherInfo.sunrise = sunrise.toString() + weatherInfo.sunset = sunset.toString() + } + + return weatherInfo +} + + +/* +************************************** +* 空气质量指标 +************************************** +*/ +function airQuality(levelNum) { + // 0-50 优,51-100 良,101-150 轻度污染,151-200 中度污染 + // 201-300 重度污染,>300 严重污染 + if (levelNum >= 0 && levelNum <= 50) { + return "优秀" + } else if (levelNum >= 51 && levelNum <= 100) { + return "良好" + } else if (levelNum >= 101 && levelNum <= 150) { + return "轻度" + } else if (levelNum >= 151 && levelNum <= 200) { + return "中度" + } else if (levelNum >= 201 && levelNum <= 300) { + return "重度" + } else { + return "严重" + } +} + + +/* +************************************** +* 获取定位 +************************************** +*/ +async function getLocation() { + if (!lockLocation) { + locationData = env.getLocation() + } + + return locationData +} + + +/* +************************************** +* 日程筛选 +************************************** +*/ +function shouldShowSchedule(schedule) { + const currentDate = new Date() + // 被取消的日程不用显示 + if (schedule.title.startsWith("Canceled:")) { return false } + // 与当前时间做比较 + let timeInterval = schedule.startDate.getTime() > currentDate.getTime() + // 返回全天跟还没过去的 + return timeInterval || schedule.isAllDay +} + + +/* +************************************** +* 日程列表 +************************************** +*/ +async function getSchedules() { + let showSchedules = [] + const todaySchedules = await CalendarEvent.today([]) + for (const schedule of todaySchedules) { + if (shouldShowSchedule(schedule)) { + // 日程 + let scheduleObj = {} + // 开始时间 + const startDate = schedule.startDate + // 开始小时 + const startHour = ("0" + startDate.getHours()).slice(-2) + // 开始分钟 + const startMinute = ("0" + startDate.getMinutes()).slice(-2) + + // 结束时间 + const endDate = schedule.endDate + // 结束小时 + const endHour = ("0" + endDate.getHours()).slice(-2) + // 结束分钟 + const endMinute = ("0" + endDate.getMinutes()).slice(-2) + + // 时间安排展示 + let timeText = "▷" + startHour + ":" + startMinute + "→" + endHour + ":" + endMinute + if (schedule.isAllDay) { + timeText = "▷全天" + } + + // 构造格式后的日程 + scheduleObj.title = schedule.title + scheduleObj.timeText = timeText + log(">>日程:" + scheduleObj.title + "==>" + timeText) + showSchedules.push(scheduleObj) + } + } + + return showSchedules +} + + +/* +************************************** +* 获取电池信息 +************************************** +*/ +function getBatteryLevel() { + const batteryLevel = Device.batteryLevel() + const batteryAscii = `${Math.round(batteryLevel * 100)}%` + log("电池==>" + batteryAscii) + return batteryAscii; +} + + +/* +************************************** +* 在线获取农历信息 +************************************** +*/ +async function getLunar() { + // 缓存目录 + const cachePath = fm.joinPath(fm.documentsDirectory(), "lsp-lunar-cache-env") + + let dateString = env.getDateStr(new Date(), "yyyy-MM-dd") + const url = `http://calendar.netcore.show/api/day/days?day=${dateString}` + let data = undefined + + if (env.useCache(cachePath)) { + const cache = fm.readString(cachePath) + log(`刷新间隔触发,读取农历缓存数据`) + data = JSON.parse(cache) + } else { + try { + data = await env.getJson(url) + // 缓存数据 + fm.writeString(cachePath, JSON.stringify(data)) + log(`农历信息请求成功,数据缓存`) + } catch (e) { + const cache = fm.readString(cachePath) + log(`读取农历缓存数据`) + data = JSON.parse(cache) + } + } + + return data +} + +/* +************************************** +* 在线获取今日诗词 +************************************** +*/ +async function getPoetry() { + // 缓存目录 + const cachePath = fm.joinPath(fm.documentsDirectory(), "lsp-poetry-cache-env") + let data = undefined + + try { + data = await env.getJson("https://v2.jinrishici.com/sentence") + // 缓存数据 + fm.writeString(cachePath, JSON.stringify(data)) + log(`今日诗词:${data.status},数据缓存`) + } catch (e) { + const cache = fm.readString(cachePath) + log(`读取今日诗词缓存数据`) + data = JSON.parse(cache) + } + + return data +} + +/* +************************************** +* 获取丁香医生健康日历 +************************************** +*/ +async function getDxHealthCalendar() { + const url = 'https://dxy.com/app/i/ask/discover/todayfeed/healthcalendar' + + // 缓存目录 + const cachePath = fm.joinPath(fm.documentsDirectory(), "lsp-dx-cache-env") + let data = undefined + + try { + data = await env.getJson(url) + // 缓存数据 + fm.writeString(cachePath, JSON.stringify(data)) + log(`丁香日历:${data},数据缓存`) + } catch (e) { + const cache = fm.readString(cachePath) + log(`读取丁香日历缓存数据`) + data = JSON.parse(cache) + } + + return data.data.items[0].title.replace('[丁香医生] ', '') +} + + + +/* +************************************** +* 按照时间获取问候语 +************************************** +*/ +function provideGreeting(date) { + // 月份 + const month = currentDate.getMonth() + 1 + // 日期 + const day = currentDate.getDate() + // 小时 + const hour = date.getHours() + // 纪念日子 + let anniversary = anniversaryText[`${month}-${day}`] + if (anniversary == undefined) { + if (hour < 5) { return greetingText.nightGreeting } + if (hour < 11) { return greetingText.morningGreeting } + if (hour >= 11 && hour - 12 <= 1) { return greetingText.noonGreeting } + if (hour - 12 < 7) { return greetingText.afternoonGreeting } + if (hour - 12 < 10) { return greetingText.eveningGreeting } + return greetingText.nightGreeting + } else { + return anniversary + } +} + + +//------------------------------------------------ +//↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑内容区↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ + +//------------------------------------------------ +// 运行脚本、预览 +widget.refreshAfterDate = new Date(+new Date + 1000 * 30) +await env.run(name, widget) +//------------------------------------------------ diff --git "a/\345\275\251\344\272\221\345\244\251\346\260\224.js" "b/\345\275\251\344\272\221\345\244\251\346\260\224.js" new file mode 100644 index 0000000..e98b133 --- /dev/null +++ "b/\345\275\251\344\272\221\345\244\251\346\260\224.js" @@ -0,0 +1,889 @@ +const env = importModule('Env-lsp.js') +//------------------------------------------------ +// 配置区 +env.configs.previewSize = "Medium" // 预览大小【小:Small,中:Medium,大:Large】 +env.configs.changePicBg = true // 是否需要更换背景 +env.configs.colorMode = false // 是否是纯色背景 +env.configs.bgColor = new Color("000000") // 小组件背景色 +env.configs.topPadding = 3 // 内容区边距 +env.configs.leftPadding = 3 // 内容区边距 +env.configs.bottomPadding = 3 // 内容区边距 +env.configs.rightPadding = 3 // 内容区边距 +env.configs.refreshInterval = 10 // 刷新间隔,单位分钟,非精准,会有3-5分钟差距 +////////////////////////////////// +const imgStyle = env.imgStyle +const textStyle = env.textStyle +///////////////////////////////// + +// 地区 +const locale = "zh_cn" + +// 彩云天气的apiKey,自己去免费申请:https://caiyunapp.com +const apiKey = "ovH0dJfU5sO6SouB" + +// 默认的定位信息,定位失败的时候默认读取 +// https://open.caiyunapp.com/File:Adcode-release-2020-06-10.xlsx.zip +// 上述链接查看对应地区的详细经纬度 +let locationData = { + "latitude": undefined, + "longitude": undefined, + "locality": undefined, + "subLocality": undefined +} +// 锁定地区,直接使用上述填写的地址信息不进行定位 +const lockLocation = false + +// 天气是否使用了上次的缓存 +let isUsedLastCache = false + +// 日程显示条数 +const maxSchedules = 1 + +// 顶部问候语,英文花样文字:https://beizhedenglong.github.io/weird-fonts/ +const greetingText = { + nightGreeting: "🦉 𝑇𝑖𝑚𝑒 𝑡𝑜 𝑔𝑒𝑡 𝑙𝑎𝑖𝑑~", + morningGreeting: "🐓 𝐺𝑜𝑜𝑑 𝑚𝑜𝑟𝑛𝑖𝑛𝑔~", + noonGreeting: "🥳 𝐺𝑜𝑜𝑑 𝑛𝑜𝑜𝑛~", + afternoonGreeting: "🦍 𝐺𝑜𝑜𝑑 𝑎𝑓𝑡𝑒𝑟𝑛𝑜𝑜𝑛~", + eveningGreeting: "🦥 𝐺𝑜𝑜𝑑 𝑒𝑣𝑒𝑛𝑖𝑛𝑔~" +} + +// 自定义日期对应的问候 +const anniversaryText = { + "1-1": "年之伊始,万事如意~", + "10-1": "金秋十月,举国同庆~" +} + +// 天气对应的icon +const weatherIcos = { + CLEAR_DAY: "https://s1.ax1x.com/2020/11/04/BcdaTJ.png", // 晴(白天) CLEAR_DAY + CLEAR_NIGHT: "https://s1.ax1x.com/2020/10/26/BukPhR.png", // 晴(夜间) CLEAR_NIGHT + PARTLY_CLOUDY_DAY: "https://s1.ax1x.com/2020/10/26/BuQHN6.png", // 多云(白天) PARTLY_CLOUDY_DAY + PARTLY_CLOUDY_NIGHT: "https://s1.ax1x.com/2020/10/26/BukcbF.png", // 多云(夜间) PARTLY_CLOUDY_NIGHT + CLOUDY: "https://s1.ax1x.com/2020/10/26/BuAbQ0.png", // 阴(白天) CLOUDY + CLOUDY_NIGHT: "https://s1.ax1x.com/2020/10/26/BuEmYd.png", // 阴(夜间) CLOUDY + LIGHT_HAZE: "https://s1.ax1x.com/2020/10/26/BuKk34.png", // 轻度雾霾 LIGHT_HAZE + MODERATE_HAZE: "https://s1.ax1x.com/2020/10/26/BuKk34.png", // 中度雾霾 MODERATE_HAZE + HEAVY_HAZE: "https://s1.ax1x.com/2020/10/26/BuKk34.png", // 重度雾霾 HEAVY_HAZE + LIGHT_RAIN: "https://s1.ax1x.com/2020/10/26/BuZTWd.png", // 小雨 LIGHT_RAIN + MODERATE_RAIN: "https://s1.ax1x.com/2020/10/26/BunhwV.png", // 中雨 MODERATE_RAIN + HEAVY_RAIN: "https://s1.ax1x.com/2020/10/26/BueSYQ.png", // 大雨 HEAVY_RAIN + STORM_RAIN: "https://s1.ax1x.com/2020/10/26/BueSYQ.png", // 暴雨 STORM_RAIN + FOG: "https://s1.ax1x.com/2020/10/26/BueAmV.png", // 雾 FOG + LIGHT_SNOW: "https://s1.ax1x.com/2020/10/26/BueW1s.png", // 小雪 LIGHT_SNOW + MODERATE_SNOW: "https://s1.ax1x.com/2020/10/26/BueW1s.png", // 中雪 MODERATE_SNOW + HEAVY_SNOW: "https://s1.ax1x.com/2020/10/26/BueXcR.png", // 大雪 HEAVY_SNOW + STORM_SNOW: "https://s1.ax1x.com/2020/10/26/BumM4g.png", // 暴雪 STORM_SNOW + DUST: "https://s1.ax1x.com/2020/10/26/BumW5D.png", // 浮尘 DUST + SAND: "https://s1.ax1x.com/2020/10/26/Bunez9.png", // 沙尘 SAND + WIND: "https://s1.ax1x.com/2020/10/26/BunEiF.png", // 大风 WIND +} + +// 天气信息控制 +const weatherControl = { + HUMIDITY: true, // 是否显示相对湿度 + COMFORT: true, // 是否显示舒适指数 + ULTRAVIOLET: false, // 是否显示紫外线指数 + AQI: true, // 是否显示空气质量指数 + HEIGHT_LOW: false, // 是否显示温度范围 + SUNRISE_SUNSET: true, // 是否显示日出日落时间 + UPDATE_TIME: true, // 是否显示天气更新时间 +} + +// 天气行间距 +const weatherLineSpacing = 5 + +// 默认字体颜色 +const defaultTextColor = new Color("ffffff") + +////////////////////////////////////////// +// 当前日期 +const currentDate = new Date() +// 年份 +const year = currentDate.getFullYear() +// 月份 +const month = currentDate.getMonth() + 1 +// 日期 +const day = currentDate.getDate() +// 小时 +const hour = currentDate.getHours() +// 分钟 +const minute = currentDate.getMinutes() +//------------------------------------------------ +// 脚本名字 +const name = Script.name() +// 文件 +const fm = FileManager.local() +//------------------------------------------------ + + +//↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓内容区↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ +//------------------------------------------------ + + +/****************************小组件内容START****************************/ +// 彩云天气信息 +const weatherInfo = await getWeather() +// 农历信息 +const lunarInfo = await getLunar(day - 1) +// 日程信息 +const showSchedules = await getSchedules() + + +////////////////////////////////////////// +// 内容排版 +const widget = new ListWidget() +let contentStack = widget.addStack() +contentStack.layoutHorizontally() +// 整体内容居中对齐 +contentStack.centerAlignContent() +////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////////////////////// +// 左侧内容 +let leftStack = contentStack.addStack() +leftStack.layoutVertically() + +////////////////////////////////////////// +// 问候 +let titleStack = env.alignHorizontallyCenterStack(leftStack) +// 问候语获取内容 +const greeting = provideGreeting(currentDate) +// 添加显示标题 +textStyle.stack = titleStack +textStyle.text = greeting +textStyle.font = Font.systemFont(23) +textStyle.textColor = defaultTextColor +textStyle.lineLimit = 1 +env.addStyleText() + + +////////////////////////////////////////// +// 年月日周 +leftStack.addSpacer(4) +let dateStack = env.alignHorizontallyCenterStack(leftStack) +const dateStr = env.getDateStr(currentDate, "MM月dd日 EEE") +// 农历信息 +const infoLunarText = lunarInfo.infoLunarText +// 显示 +textStyle.stack = dateStack +textStyle.text = `${dateStr} ${infoLunarText}` +textStyle.font = Font.systemFont(15) +textStyle.textColor = new Color("ffcc99", 0.9) +textStyle.lineLimit = 1 +env.addStyleText() + + +////////////////////////////////////////// +// 节假期信息 +const holidayText = `${lunarInfo.holidayText}` +log(`节假日信息:${holidayText}`) +if(holidayText.length != 0) { + // 农历日期 + const lunarDayColor = new Color("ffffff", 0.8) + leftStack.addSpacer(5) + let lunarDayStack = env.alignHorizontallyCenterStack(leftStack) + + // 添加显示农历 + textStyle.stack = lunarDayStack + textStyle.text = `☉ ${holidayText}` + textStyle.font = Font.systemFont(12) + textStyle.textColor = lunarDayColor + textStyle.lineLimit = 1 + env.addStyleText() +} + +////////////////////////////////////////// +// 天气预警、预告信息 +const weatherAlertInfo = weatherInfo.alertWeatherTitle +let weatherDesc = weatherInfo.weatherDesc +if (weatherAlertInfo != undefined) { + weatherDesc = weatherAlertInfo +} +// 添加显示天气预告信息 +textStyle.stack = leftStack +textStyle.marginStart = 5 +textStyle.text = `☉ ${weatherDesc}` +textStyle.lineLimit = 1 +textStyle.font = Font.systemFont(12) +textStyle.textColor = defaultTextColor +env.addStyleText() + + +////////////////////////////////////////// +// 日程、tips +const schedulePoetryColor = new Color("ffffff", 0.7) +const scheduleSize = showSchedules.length +if (scheduleSize > 0) { + leftStack.addSpacer(1) + // 添加分割线 + textStyle.stack = leftStack + textStyle.marginStart = 3 + textStyle.text = "---------------------------------------" + textStyle.lineLimit = 1 + textStyle.font = Font.systemFont(10) + textStyle.textColor = schedulePoetryColor + env.addStyleText() + // 添加日程 + leftStack.addSpacer(4) + let scheduleIndex = 0 + for (let schedule of showSchedules) { + // 索引值 + scheduleIndex++ + if (scheduleIndex > maxSchedules) { + return + } + + const scheduleStack = env.alignHorizontallyCenterStack(leftStack) + // 图片 + const img = SFSymbol.named("rosette").image + // 展示ico + imgStyle.stack = scheduleStack + imgStyle.width = 15 + imgStyle.height = 15 + imgStyle.img = img + imgStyle.tintColor = schedulePoetryColor + env.addStyleImg() + scheduleStack.addSpacer(4) + + // 日程标题 + textStyle.stack = scheduleStack + textStyle.text = schedule.title + textStyle.lineLimit = 1 + textStyle.font = Font.systemFont(11) + textStyle.textColor = schedulePoetryColor + env.addStyleText() + + // 开始时间 + leftStack.addSpacer(2) + const scheduleTimeStack = leftStack.addStack() + scheduleTimeStack.layoutHorizontally() + scheduleTimeStack.addSpacer(18) + // 展示时间 + textStyle.stack = scheduleTimeStack + textStyle.text = schedule.timeText + textStyle.lineLimit = 1 + textStyle.font = Font.systemFont(10) + textStyle.textColor = schedulePoetryColor + env.addStyleText() + } +} else { + const rand = Boolean(Math.round(Math.random())) + // 内容 + let contentInfo = undefined + // 作者 + let authorInfo = undefined + if (rand) { + // 请求今日诗词 + const poetry = await getPoetry() + const poetryInfo = poetry.data + contentInfo = `“${poetryInfo.content.substring(0, poetryInfo.content.length - 1)}”` + authorInfo = `⊱${poetryInfo.origin.dynasty}·${poetryInfo.origin.author}⊰` + } else { + // 请求丁香医生健康日历 + const dxHealthCalendar = await getDxHealthCalendar() + contentInfo = `“${dxHealthCalendar}”` + authorInfo = `⊱丁香医生·健康日历⊰` + } + + // 添加今日tips + leftStack.addSpacer(4) + const tipsStack = leftStack.addStack() + // 背景 + tipsStack.backgroundColor = new Color("666", 0.6) + tipsStack.cornerRadius = 4 + tipsStack.layoutVertically() + tipsStack.setPadding(4, 6, 4, 6) + // + const tipsInfoStack = tipsStack.addStack() + tipsInfoStack.layoutHorizontally() + // 添加内容 + textStyle.stack = tipsInfoStack + textStyle.text = contentInfo + textStyle.lineLimit = 1 + textStyle.font = Font.systemFont(11) + textStyle.textColor = schedulePoetryColor + env.addStyleText() + + // 添加作者 + tipsStack.addSpacer(2) + const authStack = tipsStack.addStack() + authStack.layoutHorizontally() + authStack.addSpacer() + // 显示作者 + textStyle.stack = authStack + textStyle.text = authorInfo + textStyle.lineLimit = 1 + textStyle.font = Font.systemFont(11) + textStyle.textColor = schedulePoetryColor + env.addStyleText() +} + +//////////////////////////////////////////////////////////////////////////////////// + + + + +//////////////////////////////////////////////////////////////////////////////////// +// 右侧内容 +contentStack.addSpacer() +let rightStack = contentStack.addStack() +// 写死右侧宽度 +rightStack.size = new Size(112, 0) +rightStack.layoutVertically() +////////////////////////////////////////// + + +////////////////////////////////////////// +// 天气Icon +const weatherStack = env.alignRightStack(rightStack) +weatherStack.bottomAlignContent() +// 缓存目录 +const weatherImgCachePath = fm.joinPath(fm.documentsDirectory(), "lsp-weatherImg-cache") +let weatherImg = undefined +try { + weatherImg = await env.getImage(weatherInfo.weatherIco) + fm.writeImage(weatherImgCachePath, weatherImg) + log(`天气icon写入缓存`) +} catch (e) { + weatherImg = fm.readImage(weatherImgCachePath) + log(`读取天气icon缓存`) +} + +// 显示天气 +imgStyle.stack = weatherStack +imgStyle.width = 36 +imgStyle.height = 36 +imgStyle.img = weatherImg +env.addStyleImg() +// 体感温度 +weatherStack.addSpacer(4) +const bodyFeelingTemperature = weatherInfo.bodyFeelingTemperature +// 显示体感温度 +textStyle.stack = weatherStack +textStyle.text = `${bodyFeelingTemperature}°` +textStyle.lineLimit = 1 +textStyle.font = Font.boldMonospacedSystemFont(25) +textStyle.textColor = defaultTextColor +env.addStyleText() +////////////////////////////////////////// + +// 相对湿度 +if (weatherControl.HUMIDITY) { + rightStack.addSpacer(weatherLineSpacing + 4) + const humidityStack = env.alignRightStack(rightStack) + // 显示 + textStyle.stack = humidityStack + textStyle.text = `相对湿度:${weatherInfo.humidity}` + textStyle.lineLimit = 1 + textStyle.font = Font.systemFont(11) + textStyle.textColor = defaultTextColor + env.addStyleText() +} + +////////////////////////////////////////// +// 舒适指数 +if (weatherControl.COMFORT) { + rightStack.addSpacer(weatherLineSpacing) + const comfortStack = env.alignRightStack(rightStack) + // 显示 + textStyle.stack = comfortStack + textStyle.text = `舒适指数:${weatherInfo.comfort}` + textStyle.lineLimit = 1 + textStyle.font = Font.systemFont(11) + textStyle.textColor = defaultTextColor + env.addStyleText() +} + +////////////////////////////////////////// +// 紫外线指数 +if (weatherControl.ULTRAVIOLET) { + rightStack.addSpacer(weatherLineSpacing) + const ultravioletStack = env.alignRightStack(rightStack) + // 显示 + textStyle.stack = ultravioletStack + textStyle.text = `紫外线:${weatherInfo.ultraviolet}` + textStyle.lineLimit = 1 + textStyle.font = Font.systemFont(11) + textStyle.textColor = defaultTextColor + env.addStyleText() +} + +////////////////////////////////////////// +// 空气质量 +if (weatherControl.AQI) { + rightStack.addSpacer(weatherLineSpacing) + const aqiInfoStack = env.alignRightStack(rightStack) + // 显示 + textStyle.stack = aqiInfoStack + textStyle.marginStart = 8 + textStyle.text = `空气质量:${weatherInfo.aqiInfo}` + textStyle.lineLimit = 1 + textStyle.font = Font.systemFont(11) + textStyle.textColor = defaultTextColor + env.addStyleText() +} + +////////////////////////////////////////// +// 高低温 +if (weatherControl.HEIGHT_LOW) { + const minTemperature = weatherInfo.minTemperature + const maxTemperature = weatherInfo.maxTemperature + // 右对齐 + rightStack.addSpacer(weatherLineSpacing) + const tempStack = env.alignRightStack(rightStack) + // 显示箭头 + textStyle.stack = tempStack + textStyle.text = `↑` + textStyle.lineLimit = 1 + textStyle.font = Font.systemFont(10) + textStyle.textColor = new Color("ff0000") + env.addStyleText() + // 高温温度 + tempStack.addSpacer(2) + textStyle.stack = tempStack + textStyle.text = `${weatherInfo.maxTemperature}°` + textStyle.lineLimit = 1 + textStyle.font = Font.systemFont(10) + textStyle.textColor = defaultTextColor + env.addStyleText() + // 低温箭头 + tempStack.addSpacer(6) + textStyle.stack = tempStack + textStyle.text = `↓` + textStyle.lineLimit = 1 + textStyle.font = Font.systemFont(10) + textStyle.textColor = new Color("2bae85") + env.addStyleText() + // 低温温度 + tempStack.addSpacer(2) + textStyle.stack = tempStack + textStyle.text = `${weatherInfo.minTemperature}°` + textStyle.lineLimit = 1 + textStyle.font = Font.systemFont(10) + textStyle.textColor = defaultTextColor + env.addStyleText() +} + +////////////////////////////////////////// +// 日出 +if (weatherControl.SUNRISE_SUNSET) { + rightStack.addSpacer(weatherLineSpacing - 2) + let symbolStack = rightStack.addStack() + symbolStack.layoutHorizontally() + symbolStack.addSpacer() + symbolStack.bottomAlignContent() + // 添加日出icon + let sunriseImg = SFSymbol.named("sunrise.fill").image + imgStyle.stack = symbolStack + imgStyle.width = 15 + imgStyle.height = 15 + imgStyle.img = sunriseImg + env.addStyleImg() + symbolStack.addSpacer(4) + // 日出时间 / 样式 + textStyle.stack = symbolStack + textStyle.text = weatherInfo.sunrise + textStyle.lineLimit = 1 + textStyle.font = Font.systemFont(10) + textStyle.textColor = defaultTextColor + env.addStyleText() + //***********************// + // 日落 + symbolStack.addSpacer(6) + // 添加日落icon + let sunsetImg = SFSymbol.named("sunset.fill").image + imgStyle.stack = symbolStack + imgStyle.width = 15 + imgStyle.height = 15 + imgStyle.img = sunsetImg + env.addStyleImg() + symbolStack.addSpacer(4) + // 日落时间 / 样式 + textStyle.stack = symbolStack + textStyle.text = weatherInfo.sunset + textStyle.lineLimit = 1 + textStyle.font = Font.systemFont(10) + textStyle.textColor = defaultTextColor + env.addStyleText() +} + +////////////////////////////////////////// +// 天气更新时间 +if (weatherControl.UPDATE_TIME) { + // 缓存目录 + const cachePath = fm.joinPath(fm.documentsDirectory(), "weather-uptime-cache") + // 更新时间 + let updateTime = env.getDateStr(new Date(), "HH:mm") + if (isUsedLastCache) { + updateTime = fm.readString(cachePath) + } + // 写入缓存 + fm.writeString(cachePath, updateTime) + // 更新时间 + rightStack.addSpacer(weatherLineSpacing) + const updateTimeStack = env.alignRightStack(rightStack) + textStyle.stack = updateTimeStack + textStyle.text = `上次更新 → ${updateTime}` + textStyle.lineLimit = 1 + textStyle.font = Font.systemFont(8) + textStyle.textColor = new Color("ffffff", 0.8) + env.addStyleText() + updateTimeStack.addSpacer(4) +} + +/*****************************小组件内容ENd*****************************/ + + +/* +************************************** +* 获取彩云天气 +************************************** +*/ +async function getWeather() { + // 缓存目录 + const cachePath = fm.joinPath(fm.documentsDirectory(), "lsp-caiyun-cache") + // 天气数据 + let weatherInfo = {} + const location = await getLocation() + log("定位信息:" + location.locality + "·" + location.subLocality) + + // 彩云天气域名 + const DOMAIN = `https://api.caiyunapp.com/v2.5/${apiKey}/${location.longitude},${location.latitude}/weather.json?alert=true` + + let weatherJsonData = undefined + + try { + log('请求彩云天气信息') + weatherJsonData = await env.getJson(DOMAIN, false) + // 写入缓存 + fm.writeString(cachePath, JSON.stringify(weatherJsonData)) + } catch (e) { + isUsedLastCache = true + const cache = fm.readString(cachePath) + log(`读取彩云天气缓存数据`) + weatherJsonData = JSON.parse(cache) + } + + if (weatherJsonData.status == "ok") { + log("天气数据请求成功,进行缓存") + + // 天气突发预警 + const alertWeatherTitle = weatherJsonData.result.alert.content.title + log("突发的天气预警==>" + alertWeatherTitle) + weatherInfo.alertWeatherTitle = alertWeatherTitle + + // 温度范围 + const temperatureData = weatherJsonData.result.daily.temperature[0] + // 最低温度 + const minTemperature = temperatureData.min + // 最高温度 + const maxTemperature = temperatureData.max + log("温度==>" + minTemperature + "|" + maxTemperature) + weatherInfo.minTemperature = Math.round(minTemperature) + weatherInfo.maxTemperature = Math.round(maxTemperature) + + // 体感温度 + const bodyFeelingTemperature = weatherJsonData.result.realtime.apparent_temperature + log("体感温度==>" + bodyFeelingTemperature) + weatherInfo.bodyFeelingTemperature = Math.round(bodyFeelingTemperature) + + // 天气状况 weatherIcos[weatherIco] + let weather = weatherJsonData.result.realtime.skycon + log("天气状况==>" + weather + "|" + weatherIcos[weather]) + if (hour - 12 >= 7 && weather == "CLOUDY") { + weather = "CLOUDY_NIGHT" + } + weatherInfo.weatherIco = weatherIcos[weather] + + // 天气描述 + const weatherDesc = weatherJsonData.result.forecast_keypoint + log("天气描述==>" + weatherDesc) + weatherInfo.weatherDesc = weatherDesc.replace("。还在加班么?", ",") + + // 相对湿度 + const humidity = (Math.round(weatherJsonData.result.realtime.humidity * 100)) + "%" + log("相对湿度==>" + weatherJsonData.result.realtime.humidity) + weatherInfo.humidity = humidity + + // 舒适指数 + const comfort = weatherJsonData.result.realtime.life_index.comfort.desc + log("舒适指数==>" + comfort) + weatherInfo.comfort = comfort + + // 紫外线指数 + const ultraviolet = weatherJsonData.result.realtime.life_index.ultraviolet.desc + log("紫外线指数==>" + ultraviolet) + weatherInfo.ultraviolet = ultraviolet + + // 空气质量 + const aqi = weatherJsonData.result.realtime.air_quality.aqi.chn + const aqiInfo = airQuality(aqi) + log("空气质量==>" + aqiInfo) + weatherInfo.aqiInfo = aqiInfo + + // 日出日落 + const astro = weatherJsonData.result.daily.astro[0] + // 日出 + const sunrise = astro.sunrise.time + // 日落 + const sunset = astro.sunset.time + log("日出==>" + sunrise + ",日落==>" + sunset) + weatherInfo.sunrise = sunrise.toString() + weatherInfo.sunset = sunset.toString() + } + + return weatherInfo +} + + +/* +************************************** +* 空气质量指标 +************************************** +*/ +function airQuality(levelNum) { + // 0-50 优,51-100 良,101-150 轻度污染,151-200 中度污染 + // 201-300 重度污染,>300 严重污染 + if (levelNum >= 0 && levelNum <= 50) { + return "优秀" + } else if (levelNum >= 51 && levelNum <= 100) { + return "良好" + } else if (levelNum >= 101 && levelNum <= 150) { + return "轻度" + } else if (levelNum >= 151 && levelNum <= 200) { + return "中度" + } else if (levelNum >= 201 && levelNum <= 300) { + return "重度" + } else { + return "严重" + } +} + + +/* +************************************** +* 获取定位 +************************************** +*/ +async function getLocation() { + if (!lockLocation) { + locationData = env.getLocation() + } + + return locationData +} + + +/* +************************************** +* 日程筛选 +************************************** +*/ +function shouldShowSchedule(schedule) { + const currentDate = new Date() + // 被取消的日程不用显示 + if (schedule.title.startsWith("Canceled:")) { return false } + // 与当前时间做比较 + let timeInterval = schedule.startDate.getTime() > currentDate.getTime() + // 返回全天跟还没过去的 + return timeInterval || schedule.isAllDay +} + + +/* +************************************** +* 日程列表 +************************************** +*/ +async function getSchedules() { + let showSchedules = [] + const todaySchedules = await CalendarEvent.today([]) + for (const schedule of todaySchedules) { + if (shouldShowSchedule(schedule)) { + // 日程 + let scheduleObj = {} + // 开始时间 + const startDate = schedule.startDate + // 开始小时 + const startHour = ("0" + startDate.getHours()).slice(-2) + // 开始分钟 + const startMinute = ("0" + startDate.getMinutes()).slice(-2) + + // 结束时间 + const endDate = schedule.endDate + // 结束小时 + const endHour = ("0" + endDate.getHours()).slice(-2) + // 结束分钟 + const endMinute = ("0" + endDate.getMinutes()).slice(-2) + + // 时间安排展示 + let timeText = "▷" + startHour + ":" + startMinute + "→" + endHour + ":" + endMinute + if (schedule.isAllDay) { + timeText = "▷全天" + } + + // 构造格式后的日程 + scheduleObj.title = schedule.title + scheduleObj.timeText = timeText + log(">>日程:" + scheduleObj.title + "==>" + timeText) + showSchedules.push(scheduleObj) + } + } + + return showSchedules +} + + +/* +************************************** +* 获取电池信息 +************************************** +*/ +function getBatteryLevel() { + const batteryLevel = Device.batteryLevel() + const batteryAscii = `${Math.round(batteryLevel * 100)}%` + log("电池==>" + batteryAscii) + return batteryAscii; +} + + +/* +************************************** +* 在线获取农历信息 +************************************** +*/ +async function getLunar(day) { + // 缓存key + const cacheKey = "lsp-lunar-cache" + // 万年历数据 + let response = undefined + try { + const request = new Request("https://wannianrili.51240.com/") + const defaultHeaders = { + "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.67 Safari/537.36" + } + request.method = 'GET' + request.headers = defaultHeaders + const html = await request.loadString() + let webview = new WebView() + await webview.loadHTML(html) + var getData = ` +            function getData() { +                try { +                    infoLunarText = document.querySelector('div#wnrl_k_you_id_${day}.wnrl_k_you .wnrl_k_you_id_wnrl_nongli').innerText +                    holidayText = document.querySelectorAll('div.wnrl_k_zuo div.wnrl_riqi')[${day}].querySelector('.wnrl_td_bzl').innerText +                    if(infoLunarText.search(holidayText) != -1) { +                        holidayText = '' +                    } +                } catch { +                    holidayText = '' +                } +                return {infoLunarText: infoLunarText, holidayText: holidayText} +            } +             +            getData() +            ` + // 节日数据   + response = await webview.evaluateJavaScript(getData, false) + Keychain.set(cacheKey, JSON.stringify(response)) + console.log(`农历输出:${JSON.stringify(response)}`); + } catch (e) { + console.error(`农历请求出错:${e}`) + if (Keychain.contains(cacheKey)) { + const cache = Keychain.get(cacheKey) + response = JSON.parse(cache) + } + } + + return response +} + +/* +************************************** +* 在线获取今日诗词 +************************************** +*/ +async function getPoetry() { + // 缓存目录 + const cachePath = fm.joinPath(fm.documentsDirectory(), "lsp-poetry-cache") + let data = undefined + + try { + data = await env.getJson("https://v2.jinrishici.com/sentence") + // 缓存数据 + fm.writeString(cachePath, JSON.stringify(data)) + log(`今日诗词:${data.status},数据缓存`) + } catch (e) { + const cache = fm.readString(cachePath) + log(`读取今日诗词缓存数据`) + data = JSON.parse(cache) + } + + return data +} + +/* +************************************** +* 获取丁香医生健康日历 +************************************** +*/ +async function getDxHealthCalendar() { + const url = 'https://dxy.com/app/i/ask/discover/todayfeed/healthcalendar' + + // 缓存目录 + const cachePath = fm.joinPath(fm.documentsDirectory(), "lsp-dx-cache") + let data = undefined + + try { + data = await env.getJson(url) + // 缓存数据 + fm.writeString(cachePath, JSON.stringify(data)) + log(`丁香日历:${data},数据缓存`) + } catch (e) { + const cache = fm.readString(cachePath) + log(`读取丁香日历缓存数据`) + data = JSON.parse(cache) + } + + return data.data.items[0].title.replace('[丁香医生] ', '') +} + + + +/* +************************************** +* 按照时间获取问候语 +************************************** +*/ +function provideGreeting(date) { + // 月份 + const month = currentDate.getMonth() + 1 + // 日期 + const day = currentDate.getDate() + // 小时 + const hour = date.getHours() + // 纪念日子 + let anniversary = anniversaryText[`${month}-${day}`] + if (anniversary == undefined) { + if (hour < 5) { return greetingText.nightGreeting } + if (hour < 11) { return greetingText.morningGreeting } + if (hour >= 11 && hour - 12 <= 1) { return greetingText.noonGreeting } + if (hour - 12 < 7) { return greetingText.afternoonGreeting } + if (hour - 12 < 10) { return greetingText.eveningGreeting } + return greetingText.nightGreeting + } else { + return anniversary + } +} + + +//------------------------------------------------ +//↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑内容区↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ + +//------------------------------------------------ +// 运行脚本、预览 +widget.refreshAfterDate = new Date(+new Date + 1000 * 30) +await env.run(name, widget) +//------------------------------------------------ diff --git "a/\345\275\251\344\272\221\346\212\230\347\272\277\345\233\276.js" "b/\345\275\251\344\272\221\346\212\230\347\272\277\345\233\276.js" new file mode 100644 index 0000000..f428085 --- /dev/null +++ "b/\345\275\251\344\272\221\346\212\230\347\272\277\345\233\276.js" @@ -0,0 +1,949 @@ +const env = importModule('Env-lsp.js') +//------------------------------------------------ +// 配置区 +env.configs.previewSize = "Medium" // 预览大小【小:Small,中:Medium,大:Large】 +env.configs.changePicBg = true // 是否需要更换背景 +env.configs.colorMode = false // 是否是纯色背景 +env.configs.bgColor = new Color("000000") // 小组件背景色 +env.configs.topPadding = 2 // 内容区边距 +env.configs.leftPadding = 2 // 内容区边距 +env.configs.bottomPadding = 2 // 内容区边距 +env.configs.rightPadding = 2 // 内容区边距 +env.configs.refreshInterval = 10 // 刷新间隔,单位分钟,非精准,会有3-5分钟差距 +////////////////////////////////// +const imgStyle = env.imgStyle +const textStyle = env.textStyle +///////////////////////////////// + +// 地区 +const locale = "zh-cn" + +// 彩云天气的apiKey,自己去免费申请:https://caiyunapp.com +const apiKey = "" + +// 默认的定位信息,定位失败的时候默认读取 +// https://open.caiyunapp.com/File:Adcode-release-2020-06-10.xlsx.zip +// 上述链接查看对应地区的详细经纬度 +let locationData = { + "latitude": undefined, + "longitude": undefined, + "locality": undefined, + "subLocality": undefined +} +// 锁定地区,直接使用上述填写的地址信息不进行定位 +const lockLocation = false + +// 是否使用上次图片的缓存 +let isUsedPicCache = false // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<-------- + +// 顶部问候语,英文花样文字:https://beizhedenglong.github.io/weird-fonts/ +const greetingText = { + nightGreeting: "Time to get laid~", + morningGreeting: "Good morning~", + noonGreeting: "Good noon~", + afternoonGreeting: "Good afternoon~", + eveningGreeting: "Good evening~" +} + +// 自定义日期对应的问候 +const anniversaryText = { + "1-1": "年之伊始,万事如意~" +} + +// 天气对应的icon +const weatherIcos = { + CLEAR_DAY: "https://s1.ax1x.com/2020/11/04/BcdaTJ.png", // 晴(白天) CLEAR_DAY + CLEAR_NIGHT: "https://s1.ax1x.com/2020/10/26/BukPhR.png", // 晴(夜间) CLEAR_NIGHT + PARTLY_CLOUDY_DAY: "https://s1.ax1x.com/2020/10/26/BuQHN6.png", // 多云(白天) PARTLY_CLOUDY_DAY + PARTLY_CLOUDY_NIGHT: "https://s1.ax1x.com/2020/10/26/BukcbF.png", // 多云(夜间) PARTLY_CLOUDY_NIGHT + CLOUDY: "https://s1.ax1x.com/2020/10/26/BuAbQ0.png", // 阴(白天) CLOUDY + CLOUDY_NIGHT: "https://s1.ax1x.com/2020/10/26/BuEmYd.png", // 阴(夜间) CLOUDY + LIGHT_HAZE: "https://s1.ax1x.com/2020/10/26/BuKk34.png", // 轻度雾霾 LIGHT_HAZE + MODERATE_HAZE: "https://s1.ax1x.com/2020/10/26/BuKk34.png", // 中度雾霾 MODERATE_HAZE + HEAVY_HAZE: "https://s1.ax1x.com/2020/10/26/BuKk34.png", // 重度雾霾 HEAVY_HAZE + LIGHT_RAIN: "https://s1.ax1x.com/2020/10/26/BuZTWd.png", // 小雨 LIGHT_RAIN + MODERATE_RAIN: "https://s1.ax1x.com/2020/10/26/BunhwV.png", // 中雨 MODERATE_RAIN + HEAVY_RAIN: "https://s1.ax1x.com/2020/10/26/BueSYQ.png", // 大雨 HEAVY_RAIN + STORM_RAIN: "https://s1.ax1x.com/2020/10/26/BueSYQ.png", // 暴雨 STORM_RAIN + FOG: "https://s1.ax1x.com/2020/10/26/BueAmV.png", // 雾 FOG + LIGHT_SNOW: "https://s1.ax1x.com/2020/10/26/BueW1s.png", // 小雪 LIGHT_SNOW + MODERATE_SNOW: "https://s1.ax1x.com/2020/10/26/BueW1s.png", // 中雪 MODERATE_SNOW + HEAVY_SNOW: "https://s1.ax1x.com/2020/10/26/BueXcR.png", // 大雪 HEAVY_SNOW + STORM_SNOW: "https://s1.ax1x.com/2020/10/26/BumM4g.png", // 暴雪 STORM_SNOW + DUST: "https://s1.ax1x.com/2020/10/26/BumW5D.png", // 浮尘 DUST + SAND: "https://s1.ax1x.com/2020/10/26/Bunez9.png", // 沙尘 SAND + WIND: "https://s1.ax1x.com/2020/10/26/BunEiF.png", // 大风 WIND +} +// 天气小图标,一定要是32x32的!!!!!! +const weatherSmallIcos = { + CLEAR_DAY: "https://s3.ax1x.com/2020/11/13/DpxSWd.png", // 晴(白天) CLEAR_DAY + CLEAR_NIGHT: "https://s3.ax1x.com/2020/11/13/DpxCQI.png", // 晴(夜间) CLEAR_NIGHT + PARTLY_CLOUDY_DAY: "https://s3.ax1x.com/2020/11/13/DpxeYQ.png", // 多云(白天) PARTLY_CLOUDY_DAY + PARTLY_CLOUDY_NIGHT: "https://s3.ax1x.com/2020/11/13/DpxKln.png", // 多云(夜间) PARTLY_CLOUDY_NIGHT + CLOUDY: "https://s3.ax1x.com/2020/11/13/Dpx8TU.png", // 阴(白天) CLOUDY + CLOUDY_NIGHT: "https://s3.ax1x.com/2020/11/13/DpxtfJ.png", // 阴(夜间) CLOUDY + LIGHT_HAZE: "https://s3.ax1x.com/2020/11/13/DpxwOx.png", // 轻度雾霾 LIGHT_HAZE + MODERATE_HAZE: "https://s3.ax1x.com/2020/11/13/DpxwOx.png", // 中度雾霾 MODERATE_HAZE + HEAVY_HAZE: "https://s3.ax1x.com/2020/11/13/DpxwOx.png", // 重度雾霾 HEAVY_HAZE + LIGHT_RAIN: "https://s3.ax1x.com/2020/11/13/DpxfXt.png", // 小雨 LIGHT_RAIN + MODERATE_RAIN: "https://s3.ax1x.com/2020/11/13/DpxTAS.png", // 中雨 MODERATE_RAIN + HEAVY_RAIN: "https://s3.ax1x.com/2020/11/13/DpxXXq.png", // 大雨 HEAVY_RAIN + STORM_RAIN: "https://s3.ax1x.com/2020/11/13/DpxXXq.png", // 暴雨 STORM_RAIN + FOG: "https://s3.ax1x.com/2020/11/13/DpzpAU.png", // 雾 FOG + LIGHT_SNOW: "https://s3.ax1x.com/2020/11/13/Dpzi9J.png", // 小雪 LIGHT_SNOW + MODERATE_SNOW: "https://s3.ax1x.com/2020/11/13/Dpzi9J.png", // 中雪 MODERATE_SNOW + HEAVY_SNOW: "https://s3.ax1x.com/2020/11/13/DpzeHK.png", // 大雪 HEAVY_SNOW + STORM_SNOW: "https://s3.ax1x.com/2020/11/13/DpzQ9H.png", // 暴雪 STORM_SNOW + DUST: "https://s3.ax1x.com/2020/11/13/Dpz1gA.png", // 浮尘 DUST + SAND: "https://s3.ax1x.com/2020/11/13/DpzwCQ.png", // 沙尘 SAND + WIND: "https://s3.ax1x.com/2020/11/13/DpzBgs.png", // 大风 WIND +} + +// 底部的小图标 +const lovelyImgArr = [ + "https://s1.ax1x.com/2020/11/05/BWQDOJ.png", + "https://s1.ax1x.com/2020/11/05/BW1yPx.png", + "https://s1.ax1x.com/2020/11/05/BRhoy8.png", + "https://s1.ax1x.com/2020/11/05/BR4pOU.png", + "https://s1.ax1x.com/2020/11/05/BR4Pw4.png", + "https://s1.ax1x.com/2020/11/05/BR4kk9.png", + "https://s1.ax1x.com/2020/11/05/BR4Ef1.png", + "https://s1.ax1x.com/2020/11/05/BWnaKs.png" +] + +// 默认字体颜色 +const defaultTextColor = new Color("ffffff", 0.95) + +////////////////////////////////////////// +// 当前日期 +const currentDate = new Date() +// 年份 +const year = currentDate.getFullYear() +// 月份 +const month = currentDate.getMonth() + 1 +// 日期 +const day = currentDate.getDate() +// 小时 +const hour = currentDate.getHours() +// 分钟 +const minute = currentDate.getMinutes() +//------------------------------------------------ +// 脚本名字 +const name = Script.name() +// 文件 +const fm = FileManager.local() +//------------------------------------------------ + + +//↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓内容区↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ +//------------------------------------------------ + + +/****************************小组件内容START****************************/ +// 彩云天气信息 +const weatherInfo = await getWeather() +// 农历信息 +const lunarInfo = await getLunar() +// 日程 +const schedules = await getSchedules() + +// 加载图片 +if (!isUsedPicCache) { + // 加载天气icon + for (var key in weatherIcos) { + await loadImg(key, weatherIcos[key]) + } + // 加载天气小icon + for (var key in weatherSmallIcos) { + await loadImg(`${key}-small`, weatherSmallIcos[key]) + } + // 加载底部小图标 + for (var key in lovelyImgArr) { + await loadImg(`lovely-${key}`, lovelyImgArr[key]) + } +} +log('~~~下载图片完成~~~') + + +////////////////////////////////////////// +// 内容排版 +const widget = new ListWidget() +let contentStack = widget.addStack() +contentStack.layoutVertically() +// 整体内容居中对齐 +contentStack.centerAlignContent() + +// 运行 +await env.run(name, widget, false, false) +const bgImg = env.readBgImg() +const widgetWidth = bgImg.size.width +const widgetHeight = bgImg.size.height + +// 准备画笔 +let drawContext = new DrawContext(); +drawContext.size = new Size(widgetWidth, widgetHeight) +drawContext.opaque = false +drawContext.setTextAlignedCenter() +var rect = new Rect(0, 0, widgetWidth, widgetHeight) +drawContext.drawImageInRect(bgImg, rect) +////////////////////////////////////////// + + +//>>>>>1 +contentStack.addSpacer(10) +let titleStack = env.alignHorizontallyCenterStack(contentStack) +titleStack.addSpacer() +// 天气Icon +// 缓存目录 +const weatherImgCachePath = fm.joinPath(fm.documentsDirectory(), "lsp-weatherImg-cache-env") +let weatherImg = undefined +try { + weatherImg = await loadImg(weatherInfo.weatherIco, weatherIcos[weatherInfo.weatherIco]) + fm.writeImage(weatherImgCachePath, weatherImg) + log(`天气icon写入缓存`) +} catch (e) { + weatherImg = fm.readImage(weatherImgCachePath) + log(`读取天气icon缓存`) +} +// 显示天气 +imgStyle.stack = titleStack +imgStyle.width = 35 +imgStyle.height = 35 +imgStyle.img = weatherImg +env.addStyleImg() +// 体感温度 +titleStack.addSpacer(6) +const bodyFeelingTemperature = weatherInfo.bodyFeelingTemperature +// 显示体感温度 +textStyle.stack = titleStack +textStyle.text = `${bodyFeelingTemperature}°C` +textStyle.lineLimit = 1 +textStyle.font = Font.regularMonospacedSystemFont(22) +textStyle.textColor = defaultTextColor +env.addStyleText() +////////////////////////////////// +// 添加显示符号 +textStyle.stack = titleStack +textStyle.marginStart = 6 +textStyle.text = `❦` +textStyle.font = Font.systemFont(22) +textStyle.textColor = defaultTextColor +textStyle.lineLimit = 1 +env.addStyleText() +// 问候语获取内容 +const greeting = provideGreeting(currentDate) +// 添加显示标题 +textStyle.stack = titleStack +textStyle.marginStart = 6 +textStyle.text = `${greeting}` +textStyle.font = new Font("HoeflerText-Italic", 22) +textStyle.textColor = defaultTextColor +textStyle.lineLimit = 1 +env.addStyleText() +titleStack.addSpacer() + + + +///////////////////////////////////////////////////////////// +//>>>>>2 +// 年月日周 +contentStack.addSpacer(3) +let dateStack = env.alignHorizontallyCenterStack(contentStack) +dateStack.addSpacer() +const dateStr = env.getDateStr(currentDate, "MM月d日 EEE", locale) +// 农历信息 +const lunarData = lunarInfo.data[0] +let infoLunarText = lunarData.lunarText +infoLunarText = infoLunarText.substring(5, infoLunarText.length) +// 节假期信息 +const lunarHoliday = lunarData.calendarDay.lunarHoliday.key +const solarHoliday = lunarData.calendarDay.solarHoliday.key +// 农历节气 +const solarTerm = lunarData.calendarDay.solarTerm +const holidayText = `${lunarHoliday ? "⊙ " + lunarHoliday : ""}${solarHoliday ? "⊙ " + solarHoliday : ""}${solarTerm ? "⊙ " + solarTerm : ""}` +log(`节假日信息:${holidayText}`) +// 显示 +textStyle.stack = dateStack +textStyle.text = `${dateStr} ⊙ ${infoLunarText} ${holidayText}` +textStyle.font = Font.systemFont(14) +textStyle.textColor = new Color("ffcc99", 0.8) +textStyle.lineLimit = 1 +env.addStyleText() +dateStack.addSpacer() + + +///////////////////////////////////////////////////////////// +let graphMode = Boolean(Math.round(Math.random())) +// graphMode = false +///////////////////////////////////////////////////////////// +if (!graphMode) { + //>>>>>3 + contentStack.addSpacer(8) + let weatherTipsStack = env.alignHorizontallyCenterStack(contentStack) + weatherTipsStack.addSpacer() + // 天气预警、预告信息 + const weatherAlertInfo = weatherInfo.alertWeatherTitle + let weatherDesc = weatherInfo.weatherDesc + if (weatherAlertInfo != undefined) { + weatherDesc = weatherAlertInfo + } + // 添加显示天气预告信息 + textStyle.stack = weatherTipsStack + textStyle.text = `Φ ${weatherDesc} ⊙ 指数≒${weatherInfo.comfort} Φ` + textStyle.lineLimit = 1 + textStyle.font = Font.systemFont(12) + textStyle.textColor = defaultTextColor + env.addStyleText() + weatherTipsStack.addSpacer() + + + // 随机大图跟小图模式切换 + let randMode = Boolean(Math.round(Math.random())) + ///////////////////////////////////////////////////////////// + //>>>>>4 + if (!randMode) { + contentStack.addSpacer(8) + let infoStack = env.alignHorizontallyCenterStack(contentStack) + infoStack.addSpacer() + // 内容 + let contentInfo = undefined + if (schedules.length != 0) { + const scheduleObj = schedules[0] + contentInfo = `“${scheduleObj.title}” ━ ⊱${scheduleObj.timeText}⊰` + } else { + const rand = Math.round(Math.random()) + if (rand % 2 == 0) { + // 请求一言 + const oneWord = await getOneWord() + contentInfo = `“${oneWord.hitokoto}”` + } else if (rand % 3 == 0) { + // 请求丁香医生健康日历 + const dxHealthCalendar = await getDxHealthCalendar() + contentInfo = `“${dxHealthCalendar}”` + } else { + // 请求今日诗词 + const poetry = await getPoetry() + const poetryInfo = poetry.data + const authorText = `⊱${poetryInfo.origin.dynasty}·${poetryInfo.origin.author}⊰` + contentInfo = `“${poetryInfo.content.substring(0, poetryInfo.content.length - 1)}” ━ ${authorText}` + } + } + // 添加今日tips + // 背景 + infoStack.backgroundColor = new Color("666", 0.3) + infoStack.cornerRadius = 4 + infoStack.setPadding(6, 6, 6, 6) + // 添加内容 + textStyle.stack = infoStack + textStyle.text = contentInfo + textStyle.lineLimit = 1 + textStyle.font = Font.lightMonospacedSystemFont(11) + textStyle.textColor = new Color("ffffff", 0.7) + env.addStyleText() + infoStack.addSpacer() + } + + + ///////////////////////////////////////////////////////////// + //>>>>>5 + // 图标大小 + let iconSize = 18 + let spacer = 8 + // 图标边距 + let iconMargin = 10 + if (randMode) { + iconSize = 25 + spacer = 15 + iconMargin = 15 + } + contentStack.addSpacer(spacer) + let updateStack = env.alignHorizontallyCenterStack(contentStack) + updateStack.addSpacer() + // 显示底部图标栏1 + // 缓存目录 + let lovelyImg1 = await loadImg('lovely-0', lovelyImgArr[0]) + imgStyle.stack = updateStack + imgStyle.width = iconSize + imgStyle.height = iconSize + imgStyle.img = lovelyImg1 + env.addStyleImg() + updateStack.addSpacer(iconMargin) + + // 显示底部图标栏2 + // 缓存目录 + let lovelyImg2 = await loadImg('lovely-1', lovelyImgArr[1]) + imgStyle.stack = updateStack + imgStyle.width = iconSize + imgStyle.height = iconSize + imgStyle.img = lovelyImg2 + env.addStyleImg() + updateStack.addSpacer(iconMargin) + + // 显示底部图标栏3 + // 缓存目录 + let lovelyImg3 = await loadImg('lovely-2', lovelyImgArr[2]) + imgStyle.stack = updateStack + imgStyle.width = iconSize + imgStyle.height = iconSize + imgStyle.img = lovelyImg3 + env.addStyleImg() + updateStack.addSpacer(iconMargin) + + // 显示底部图标栏4 + // 缓存目录 + let lovelyImg4 = await loadImg('lovely-3', lovelyImgArr[3]) + imgStyle.stack = updateStack + imgStyle.width = iconSize + imgStyle.height = iconSize + imgStyle.img = lovelyImg4 + env.addStyleImg() + updateStack.addSpacer(iconMargin) + + if (!randMode) { + // 添加更新时间 + textStyle.stack = updateStack + textStyle.text = `update at ${env.getDateStr(new Date(), "HH:mm")}` + textStyle.lineLimit = 1 + textStyle.font = Font.thinSystemFont(10) + textStyle.textColor = new Color("ffffff", 0.6) + env.addStyleText() + updateStack.addSpacer(iconMargin) + } + + // 显示底部图标栏5 + // 缓存目录 + let lovelyImg5 = await loadImg('lovely-4', lovelyImgArr[4]) + imgStyle.stack = updateStack + imgStyle.width = iconSize + imgStyle.height = iconSize + imgStyle.img = lovelyImg5 + env.addStyleImg() + updateStack.addSpacer(iconMargin) + + // 显示底部图标栏6 + // 缓存目录 + let lovelyImg6 = await loadImg('lovely-5', lovelyImgArr[5]) + imgStyle.stack = updateStack + imgStyle.width = iconSize + imgStyle.height = iconSize + imgStyle.img = lovelyImg6 + env.addStyleImg() + updateStack.addSpacer(iconMargin) + + // 显示底部图标栏7 + // 缓存目录 + let lovelyImg7 = await loadImg('lovely-6', lovelyImgArr[6]) + imgStyle.stack = updateStack + imgStyle.width = iconSize + imgStyle.height = iconSize + imgStyle.img = lovelyImg7 + env.addStyleImg() + updateStack.addSpacer(iconMargin) + + // 显示底部图标栏8 + // 缓存目录 + let lovelyImg8 = await loadImg('lovely-7', lovelyImgArr[7]) + imgStyle.stack = updateStack + imgStyle.width = iconSize + imgStyle.height = iconSize + imgStyle.img = lovelyImg8 + env.addStyleImg() + updateStack.addSpacer() +} else { + ///////////////////////////////////////////////////////////// + //>>>>> 折线图 + const startX = 50 // 起点 + const weatherIcoCount = 8 // icon数量 + const perSize = (widgetWidth - 2 * startX) / (weatherIcoCount - 1) // 每个item间隔 + let coordArr = [] // 所有坐标 + const foldArea = 50 // 温度曲线所占高度 + + // 温度差 + let subWeatherArr = weatherInfo.hourly.slice(0, 8) + subWeatherArr = subWeatherArr.sort(function (a, b) { return a.temperature - b.temperature }) + const maxTemperature = subWeatherArr[subWeatherArr.length - 1].temperature + const minTemperature = subWeatherArr[0].temperature + const temperatureDifference = maxTemperature - minTemperature + // 每一度所占高度 + const perTemperatureSize = (foldArea - 10) / temperatureDifference + const foldY = 132 // 垂直开始位置 + const areaSize = 15 + + for (var index = 0; index < weatherIcoCount; index++) { + let hourlyTemperature = weatherInfo.hourly[index] + let imgCoorX = startX - 16 + perSize * index + let imgCoorY = foldY + (maxTemperature - hourlyTemperature.temperature) * perTemperatureSize + coordArr.push(imgCoorX) + coordArr.push(imgCoorY) + } + + let temperatureIndex = 0 + for (var index = 0; index < weatherIcoCount * 2; index = index + 2) { + let hourlyTemperature = weatherInfo.hourly[temperatureIndex] + + // 连线 + if (index <= weatherIcoCount * 2 - 2 * 2) { + let x1 = coordArr[index] + areaSize + let y1 = coordArr[index + 1] + areaSize + let x2 = coordArr[index + 2] + areaSize + let y2 = coordArr[index + 3] + areaSize + drawLine(x1, y1, x2, y2, 3, new Color("fbda41", 0.8)) + } + + // 天气图标 + let weatherIco = await loadImg(hourlyTemperature.skycon, weatherSmallIcos[hourlyTemperature.skycon]) + const weatherX = coordArr[index] + const weatherY = coordArr[index + 1] + drawImage(weatherIco, weatherX, weatherY) + + // 温度 + drawText(`${hourlyTemperature.temperature}°`, 16, coordArr[index] + 5, coordArr[index + 1] - 18) + + // 时间 + const timeX = coordArr[index] + 5 + const timeY = foldY + foldArea + 38 + const timeText = env.getDateStr(new Date(hourlyTemperature.datetime), "HH", locale) + drawText(`${timeText}`, 16, timeX, timeY) + + // 垂直方向线条 + drawLine(weatherX + areaSize, weatherY + 2 * areaSize, timeX + 10, timeY, 1, new Color('FFFFFF', 0.6)) + + temperatureIndex++ + } +} +contentStack.addSpacer() +/*****************************小组件内容ENd*****************************/ + + +/* +************************************** +* 画图 +************************************** +*/ +function drawImage(image, x, y) { + drawContext.drawImageAtPoint(image, new Point(x, y)) +} + +/* +************************************** +* 画文本 +************************************** +*/ +function drawText(text, fontSize, x, y, color = Color.white()) { + drawContext.setFont(Font.boldSystemFont(fontSize)) + drawContext.setTextColor(color) + drawContext.drawText(new String(text).toString(), new Point(x, y)) +} + +/* +************************************** +* 画线 +************************************** +*/ +function drawLine(x1, y1, x2, y2, width = 3, color = Color.white()) { + const path = new Path() + path.move(new Point(x1, y1)) + path.addLine(new Point(x2, y2)) + drawContext.addPath(path) + drawContext.setStrokeColor(color) + drawContext.setLineWidth(width) + drawContext.strokePath() +} + + +/* +************************************** +* 获取图片 +************************************** +*/ +async function loadImg(key, url) { + // 缓存目录 + const cachePath = fm.joinPath(fm.documentsDirectory(), `lsp-img-cache-env-${key}`) + let loadedImg = undefined + if (isUsedPicCache) { + loadedImg = fm.readImage(cachePath) + } + if (loadedImg == undefined) { + try { + loadedImg = await env.getImage(url) + fm.writeImage(cachePath, loadedImg) + } catch (e) { + log(`加载图片出错:${e}`) + } + } else { + return loadedImg + } +} + + +/* +************************************** +* 获取彩云天气 +************************************** +*/ +async function getWeather() { + // 缓存目录 + const cachePath = fm.joinPath(fm.documentsDirectory(), "lsp-caiyun-cache-env") + // 天气数据 + let weatherInfo = {} + const location = await getLocation() + log("定位信息:" + location.locality + "·" + location.subLocality) + + // 彩云天气域名 + const url = `https://api.caiyunapp.com/v2.5/${apiKey}/${location.longitude},${location.latitude}/weather.json?alert=true` + + let weatherJsonData = undefined + + try { + log('请求彩云天气信息') + weatherJsonData = await env.getJson(url, false) + // 写入缓存 + fm.writeString(cachePath, JSON.stringify(weatherJsonData)) + } catch (e) { + const cache = fm.readString(cachePath) + log(`读取彩云天气缓存数据`) + weatherJsonData = JSON.parse(cache) + } + + if (weatherJsonData.status == "ok") { + log("天气数据请求成功,进行缓存") + + // 天气突发预警 + const alertWeatherTitle = weatherJsonData.result.alert.content.title + log("突发的天气预警==>" + alertWeatherTitle) + weatherInfo.alertWeatherTitle = alertWeatherTitle + + // 温度范围 + const temperatureData = weatherJsonData.result.daily.temperature[0] + // 最低温度 + const minTemperature = temperatureData.min + // 最高温度 + const maxTemperature = temperatureData.max + weatherInfo.minTemperature = Math.round(minTemperature) + weatherInfo.maxTemperature = Math.round(maxTemperature) + + // 体感温度 + const bodyFeelingTemperature = weatherJsonData.result.realtime.apparent_temperature + weatherInfo.bodyFeelingTemperature = Math.round(bodyFeelingTemperature) + + // 天气状况 weatherIcos[weatherIco] + let weather = weatherJsonData.result.realtime.skycon + let nightCloudy = hour - 12 >= 7 && weather == "CLOUDY" + if (nightCloudy) { + weather = "CLOUDY_NIGHT" + } + weatherInfo.weatherIco = weather + + // 天气描述 + const weatherDesc = weatherJsonData.result.forecast_keypoint + log("天气描述==>" + weatherDesc) + weatherInfo.weatherDesc = weatherDesc.replace("。还在加班么?", ",") + + // 相对湿度 + const humidity = (Math.round(weatherJsonData.result.realtime.humidity * 100)) + "%" + weatherInfo.humidity = humidity + + // 舒适指数 + const comfort = weatherJsonData.result.realtime.life_index.comfort.desc + weatherInfo.comfort = comfort + + // 紫外线指数 + const ultraviolet = weatherJsonData.result.realtime.life_index.ultraviolet.desc + weatherInfo.ultraviolet = ultraviolet + + // 空气质量 + const aqi = weatherJsonData.result.realtime.air_quality.aqi.chn + const aqiInfo = airQuality(aqi) + weatherInfo.aqiInfo = aqiInfo + + // 日出日落 + const astro = weatherJsonData.result.daily.astro[0] + // 日出 + const sunrise = astro.sunrise.time + // 日落 + const sunset = astro.sunset.time + weatherInfo.sunrise = sunrise.toString() + weatherInfo.sunset = sunset.toString() + + // 小时预告 + let hourlyArr = [] + const hourlyData = weatherJsonData.result.hourly + const temperatureArr = hourlyData.temperature + const temperatureSkyconArr = hourlyData.skycon + for (var i = 0; i < temperatureArr.length; i++) { + let hourlyObj = {} + hourlyObj.datetime = temperatureArr[i].datetime + hourlyObj.temperature = Math.round(temperatureArr[i].value) + + let weather = temperatureSkyconArr[i].value + if (nightCloudy) { + weather = "CLOUDY_NIGHT" + } + hourlyObj.skycon = `${weather}-small` + hourlyArr.push(hourlyObj) + } + weatherInfo.hourly = hourlyArr + } + + return weatherInfo +} + + +/* +************************************** +* 空气质量指标 +************************************** +*/ +function airQuality(levelNum) { + // 0-50 优,51-100 良,101-150 轻度污染,151-200 中度污染 + // 201-300 重度污染,>300 严重污染 + if (levelNum >= 0 && levelNum <= 50) { + return "优秀" + } else if (levelNum >= 51 && levelNum <= 100) { + return "良好" + } else if (levelNum >= 101 && levelNum <= 150) { + return "轻度" + } else if (levelNum >= 151 && levelNum <= 200) { + return "中度" + } else if (levelNum >= 201 && levelNum <= 300) { + return "重度" + } else { + return "严重" + } +} + + +/* +************************************** +* 获取定位 +************************************** +*/ +async function getLocation() { + if (!lockLocation) { + locationData = env.getLocation() + } + + return locationData +} + + +/* +************************************** +* 日程筛选 +************************************** +*/ +function shouldShowSchedule(schedule) { + const currentDate = new Date() + // 被取消的日程不用显示 + if (schedule.title.startsWith("Canceled:")) { return false } + // 与当前时间做比较 + let timeInterval = schedule.endDate.getTime() > currentDate.getTime() + // 返回全天跟还没过去的 + return timeInterval || schedule.isAllDay +} + + +/* +************************************** +* 日程列表 +************************************** +*/ +async function getSchedules() { + let showSchedules = [] + const todaySchedules = await CalendarEvent.today([]) + for (const schedule of todaySchedules) { + if (shouldShowSchedule(schedule)) { + // 日程 + let scheduleObj = {} + // 开始时间 + const startDate = schedule.startDate + // 开始小时 + const startHour = ("0" + startDate.getHours()).slice(-2) + // 开始分钟 + const startMinute = ("0" + startDate.getMinutes()).slice(-2) + + // 结束时间 + const endDate = schedule.endDate + // 结束小时 + const endHour = ("0" + endDate.getHours()).slice(-2) + // 结束分钟 + const endMinute = ("0" + endDate.getMinutes()).slice(-2) + + // 时间安排展示 + let timeText = startHour + ":" + startMinute + "~" + endHour + ":" + endMinute + if (schedule.isAllDay) { + timeText = "全天" + } + + // 构造格式后的日程 + scheduleObj.title = schedule.title + scheduleObj.timeText = timeText + log(">>日程:" + scheduleObj.title + "==>" + timeText) + showSchedules.push(scheduleObj) + } + } + + return showSchedules +} + + +/* +************************************** +* 获取电池信息 +************************************** +*/ +function getBatteryLevel() { + const batteryLevel = Device.batteryLevel() + const batteryAscii = `${Math.round(batteryLevel * 100)}%` + log("电池==>" + batteryAscii) + return batteryAscii; +} + + +/* +************************************** +* 在线获取农历信息 +************************************** +*/ +async function getLunar() { + // 缓存目录 + const cachePath = fm.joinPath(fm.documentsDirectory(), "lsp-lunar-cache-env") + + let dateString = env.getDateStr(new Date(), "yyyy-MM-dd") + const url = `http://calendar.netcore.show/api/day/days?day=${dateString}` + let data = undefined + + if (env.useCache(cachePath)) { + const cache = fm.readString(cachePath) + log(`刷新间隔触发,读取农历缓存数据`) + data = JSON.parse(cache) + } else { + try { + data = await env.getJson(url) + // 缓存数据 + fm.writeString(cachePath, JSON.stringify(data)) + log(`农历信息请求成功,数据缓存`) + } catch (e) { + const cache = fm.readString(cachePath) + log(`读取农历缓存数据`) + data = JSON.parse(cache) + } + } + + return data +} + +/* +************************************** +* 在线获取今日诗词 +************************************** +*/ +async function getPoetry() { + // 缓存目录 + const cachePath = fm.joinPath(fm.documentsDirectory(), "lsp-poetry-cache-env") + let data = undefined + + try { + data = await env.getJson("https://v2.jinrishici.com/sentence") + // 缓存数据 + fm.writeString(cachePath, JSON.stringify(data)) + log(`今日诗词:${data.status},数据缓存`) + } catch (e) { + const cache = fm.readString(cachePath) + log(`读取今日诗词缓存数据`) + data = JSON.parse(cache) + } + + return data +} + +/* +************************************** +* 获取丁香医生健康日历 +************************************** +*/ +async function getDxHealthCalendar() { + const url = 'https://dxy.com/app/i/ask/discover/todayfeed/healthcalendar' + + // 缓存目录 + const cachePath = fm.joinPath(fm.documentsDirectory(), "lsp-dx-cache-env") + let data = undefined + + try { + data = await env.getJson(url) + // 缓存数据 + fm.writeString(cachePath, JSON.stringify(data)) + log(`丁香日历:${data},数据缓存`) + } catch (e) { + const cache = fm.readString(cachePath) + log(`读取丁香日历缓存数据`) + data = JSON.parse(cache) + } + + return data.data.items[0].title.replace('[丁香医生] ', '') +} + +/* +************************************** +* 获取一言 +************************************** +*/ +async function getOneWord() { + const url = 'https://v1.hitokoto.cn/?encode=json' + + // 缓存目录 + const cachePath = fm.joinPath(fm.documentsDirectory(), "lsp-one_word-cache-env") + let data = undefined + + try { + data = await env.getJson(url) + // 缓存数据 + fm.writeString(cachePath, JSON.stringify(data)) + log(`一言:${data},数据缓存`) + } catch (e) { + const cache = fm.readString(cachePath) + log(`读取一言缓存数据`) + data = JSON.parse(cache) + } + + return data +} + + + +/* +************************************** +* 按照时间获取问候语 +************************************** +*/ +function provideGreeting(date) { + // 月份 + const month = currentDate.getMonth() + 1 + // 日期 + const day = currentDate.getDate() + // 小时 + const hour = date.getHours() + // 纪念日子 + let anniversary = anniversaryText[`${month}-${day}`] + if (anniversary == undefined) { + if (hour < 5) { return greetingText.nightGreeting } + if (hour < 11) { return greetingText.morningGreeting } + if (hour >= 11 && hour - 12 <= 1) { return greetingText.noonGreeting } + if (hour - 12 < 7) { return greetingText.afternoonGreeting } + if (hour - 12 < 10) { return greetingText.eveningGreeting } + return greetingText.nightGreeting + } else { + return anniversary + } +} + + +//------------------------------------------------ +//↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑内容区↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ + +//------------------------------------------------ +// 运行脚本、预览 +widget.backgroundImage = drawContext.getImage() +// 设置组件 +env.finish(widget, false) +//------------------------------------------------ diff --git "a/\345\275\251\344\272\221\346\241\214\351\235\242\345\244\251\346\260\224.js" "b/\345\275\251\344\272\221\346\241\214\351\235\242\345\244\251\346\260\224.js" deleted file mode 100644 index 465ecf4..0000000 --- "a/\345\275\251\344\272\221\346\241\214\351\235\242\345\244\251\346\260\224.js" +++ /dev/null @@ -1,1065 +0,0 @@ -// Variables used by Scriptable. -// This transparent bg was created by Max Zeryck - -/* - ************************************** - * 配置项 - ************************************** - */ - -// 地区 -const locale = "zh_cn" - -// 背景是否是颜色 -const colorMode = false - -// 背景颜色 -const bgColorStr = "#000000" - -// 预览大小【小:Small,中:Medium,大:Large】 -const previewSize = "Medium" - -// 彩云天气的apiKey,自己去免费申请:https://caiyunapp.com -const apiKey = "TAkhjf8d1nlSlspN" - -// 默认的定位信息,定位失败的时候默认读取 -// https://open.caiyunapp.com/File:Adcode-release-2020-06-10.xlsx.zip -// 上述链接查看对应地区的详细经纬度 -let locationData = { - "latitude": undefined, - "longitude": undefined, - "locality": undefined, - "subLocality": undefined -} -// 锁定地区,直接使用上述填写的地址信息不进行定位 -const lockLocation = false - -// 是否需要选择图片背景 -const changePicBg = true - -// 日程显示条数 -const maxSchedules = 2 - -// 提醒事项显示条数 -const maxReminders = 2 - -// 内容区左右边距 -const padding = { - top: 0, - left: 4, - bottom: 0, - right: 4 -} - -// 顶部问候语,英文花样文字:https://beizhedenglong.github.io/weird-fonts/ -const greetingText = { - nightGreeting: "🦉 𝑇𝑖𝑚𝑒 𝑡𝑜 𝑔𝑒𝑡 𝑙𝑎𝑖𝑑~", - morningGreeting: "💫 𝐺𝑜𝑜𝑑 𝑚𝑜𝑟𝑛𝑖𝑛𝑔~", - noonGreeting: "🥳 𝐺𝑜𝑜𝑑 𝑛𝑜𝑜𝑛~", - afternoonGreeting: "🐡 𝐺𝑜𝑜𝑑 𝑎𝑓𝑡𝑒𝑟𝑛𝑜𝑜𝑛~", - eveningGreeting: "🐳 𝐺𝑜𝑜𝑑 𝑒𝑣𝑒𝑛𝑖𝑛𝑔~" -} - -// 天气对应的icon -const weatherIcos = { - CLEAR_DAY: "http://worldweather.wmo.int/images/24a.png", // 晴(白天) CLEAR_DAY - CLEAR_NIGHT: "http://worldweather.wmo.int/images/24b.png", // 晴(夜间) CLEAR_NIGHT - PARTLY_CLOUDY_DAY: "http://worldweather.wmo.int/images/23a.png", // 多云(白天) PARTLY_CLOUDY_DAY - PARTLY_CLOUDY_NIGHT: "http://worldweather.wmo.int/images/23b.png", // 多云(夜间) PARTLY_CLOUDY_NIGHT - CLOUDY: "http://worldweather.wmo.int/images/20.png", // 阴 CLOUDY - LIGHT_HAZE: "http://worldweather.wmo.int/images/17.png", // 轻度雾霾 LIGHT_HAZE - MODERATE_HAZE: "http://worldweather.wmo.int/images/18.png", // 中度雾霾 MODERATE_HAZE - HEAVY_HAZE: "http://worldweather.wmo.int/images/19.png", // 重度雾霾 HEAVY_HAZE - LIGHT_RAIN: "http://worldweather.wmo.int/images/15.png", // 小雨 LIGHT_RAIN - MODERATE_RAIN: "http://worldweather.wmo.int/images/14.png", // 中雨 MODERATE_RAIN - HEAVY_RAIN: "http://worldweather.wmo.int/images/12.png", // 大雨 HEAVY_RAIN - STORM_RAIN: "http://worldweather.wmo.int/images/9.png", // 暴雨 STORM_RAIN - FOG: "http://worldweather.wmo.int/images/16.png", // 雾 FOG - LIGHT_SNOW: "http://worldweather.wmo.int/images/7.png", // 小雪 LIGHT_SNOW - MODERATE_SNOW: "http://worldweather.wmo.int/images/5.png", // 中雪 MODERATE_SNOW - HEAVY_SNOW: "http://worldweather.wmo.int/images/6.png", // 大雪 HEAVY_SNOW - STORM_SNOW: "http://worldweather.wmo.int/images/4.png", // 暴雪 STORM_SNOW - DUST: "http://worldweather.wmo.int/images/1.png", // 浮尘 DUST - SAND: "http://worldweather.wmo.int/images/1.png", // 沙尘 SAND - WIND: "http://worldweather.wmo.int/images/26.png", // 大风 WIND -} - -// 天气信息控制 -const weatherControl = { - HUMIDITY: true, // 是否显示相对湿度 - COMFORT: true, // 是否显示舒适指数 - ULTRAVIOLET: true, // 是否显示紫外线指数 - AQI: true, // 是否显示空气质量指数 - HEIGHT_LOW: true, // 是否显示温度范围 - SUNRISE_SUNSET: true, // 是否显示日出日落时间 - UPDATE_TIME: true, // 是否显示天气更新时间 -} - -// 周标题 -const weekTitle = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'] - -// 默认文字颜色 -const defaultTextColor = new Color("#ffffff") - -////////////////////////////////////////// -// 标题样式 -let textStyle = { - stack: undefined, // 加入到哪个内容栈显示 - topMargin: 0, // 顶部距离 - text: "", // 显示的文字 - lineLimit: 0, // 行数控制,0是全部展示 - font: Font.systemFont(18), // 字体 - textColor: defaultTextColor, // 文字颜色 -} - -// 图片样式 -let imgStyle = { - stack: undefined, // 加入到哪个内容栈显示 - topMargin: 0, // 顶部距离 - img: undefined, // 图片资源 - width: 0, // 宽 - length: 0, // 长 - tintColor: undefined, // 图片渲染颜色 -} -////////////////////////////////////////// - -// 当前日期 -const currentDate = new Date() -// 年份 -const year = currentDate.getFullYear() -// 月份 -const month = currentDate.getMonth() + 1 -// 日期 -const day = currentDate.getDate() -// 小时 -const hour = currentDate.getHours() -// 分钟 -const minute = currentDate.getMinutes() - -/* - **************************************************************************** - **************************************************************************** - **************************************************************************** - */ - - -/********************************************************************/ -/****************************定义小组件****************************/ -/********************************************************************/ -const filename = `${Script.name()}.jpg` -const files = FileManager.local() -const path = files.joinPath(files.documentsDirectory(), filename) -const widget = new ListWidget() - - -/****************************小组件内容START****************************/ -// 彩云天气信息 -const weatherInfo = await getWeather() -// 农历信息 -const lunarInfo = await getLunar() -// 今日诗词 -const poetry = await getPoetry() -// // 日程信息 -const showSchedules = await getSchedules() -// 提醒事项 -// const showReminders = await getReminders() - - -////////////////////////////////////////// -// 内容排版 -let contentStack = widget.addStack() -contentStack.layoutHorizontally() -// 整体内容居中对齐 -contentStack.centerAlignContent() -// 背景 -widget.backgroundColor = new Color(bgColorStr) -////////////////////////////////////////// - - -//////////////////////////////////////////////////////////////////////////////////// -// 左侧内容 -let leftStack = contentStack.addStack() -leftStack.layoutVertically() - -////////////////////////////////////////// -// 问候 -let titleStack = horizontallyCenterStack(leftStack) -// 问候语获取内容 -const greeting = provideGreeting(currentDate) -// 添加显示标题 -addStyleText(titleStack, 0, greeting, 1, Font.systemFont(22), defaultTextColor) - - -////////////////////////////////////////// -// 年月日 -const dateStr = getDateStr(currentDate) -addStyleText(leftStack, 2, dateStr, 1, Font.systemFont(16), new Color("#ffcc99")) - -////////////////////////////////////////// -// 星期几 / 农历日期 -const weekDayColor = new Color("#ffffff", 0.9) -leftStack.addSpacer(2) -let dateStack = horizontallyCenterStack(leftStack) -// 添加显示星期几 -const weekDayTitle = getDayWeekTitle(currentDate) -addStyleText(dateStack, 0, weekDayTitle, 1, Font.systemFont(16), weekDayColor) -dateStack.addSpacer(4) - -// 农历信息 -let infoLunarText = lunarInfo.data.lunar -infoLunarText = infoLunarText.substring(12, infoLunarText.length) -// 添加显示农历 -addStyleText(dateStack, 0, infoLunarText, 1, Font.systemFont(16), weekDayColor) - -// 电池信息 -dateStack.addSpacer(2) -const batteryLevel = Device.batteryLevel() * 100 -const batteryStr = `〓 ${getBatteryLevel()} 〓` -// 添加显示电池具体信息 -addStyleText(dateStack, 0, batteryStr, 1, Font.systemFont(15), weekDayColor) - - -////////////////////////////////////////// -// 天气预警、预告信息 -const weatherAlertInfo = weatherInfo.alertWeatherTitle -let weatherDesc = weatherInfo.weatherDesc -if (weatherAlertInfo != undefined) { - weatherDesc = weatherAlertInfo -} -// 添加显示天气预告信息 -addStyleText(leftStack, 3, weatherDesc, 1, Font.systemFont(12), defaultTextColor) - -////////////////////////////////////////// -// 日程、诗词 -const schedulePoetryColor = new Color("#ffffff", 0.7) -const scheduleSize = showSchedules.length -if (scheduleSize > 0) { - addStyleText(leftStack, 1, "----------------------------------", 1, Font.systemFont(10), schedulePoetryColor) - // 添加日程 - let scheduleIndex = 0 - for (let schedule of showSchedules) { - // 索引值 - scheduleIndex++ - if (scheduleIndex > maxSchedules) { - return - } - - const scheduleStack = horizontallyCenterStack(leftStack) - // 图片 - const img = SFSymbol.named("megaphone").image - // 展示ico - addStyleImg(scheduleStack, 0, img, 12, 12, schedulePoetryColor) - scheduleStack.addSpacer(4) - - // 日程标题 - addStyleText(scheduleStack, 0, schedule.title, 1, Font.systemFont(11), schedulePoetryColor) - - // 开始时间 - const scheduleTimeStack = leftStack.addStack() - scheduleTimeStack.layoutHorizontally() - scheduleTimeStack.addSpacer(17) - // 展示时间 - addStyleText(scheduleTimeStack, 0, schedule.timeText, 1, Font.systemFont(11), schedulePoetryColor) - } -} else { - // 添加今日诗词 - leftStack.addSpacer(8) - const poetryStack = leftStack.addStack() - // 诗词背景 - poetryStack.backgroundColor = new Color("#666", 0.5) - poetryStack.cornerRadius = 4 - poetryStack.layoutVertically() - poetryStack.addSpacer(4) - // - const poetryInfoStack = poetryStack.addStack() - poetryInfoStack.layoutHorizontally() - poetryInfoStack.addSpacer(4) - const poetryInfo = poetry.data - // 添加显示诗词 - const potryContent = `"${poetryInfo.content.substring(0, poetryInfo.content.length - 1)}"` - addStyleText(poetryInfoStack, 0, potryContent, 1, Font.systemFont(11), schedulePoetryColor) - - // 添加作者 - const authStack = poetryStack.addStack() - authStack.layoutHorizontally() - authStack.addSpacer() - // 显示作者 - const authorText = `⊱${poetryInfo.origin.dynasty}·${poetryInfo.origin.author}⊰` - addStyleText(authStack, 0, authorText, 1, Font.systemFont(11), schedulePoetryColor) - authStack.addSpacer(4) - poetryStack.addSpacer(4) -} - -//////////////////////////////////////////////////////////////////////////////////// - - - - -//////////////////////////////////////////////////////////////////////////////////// -// 右侧内容 -contentStack.addSpacer() -let rightStack = contentStack.addStack() -// 写死右侧宽度 -rightStack.size = new Size(110, 0) -rightStack.layoutVertically() -////////////////////////////////////////// - - -////////////////////////////////////////// -// 天气Icon -const weatherStack = alignRightStack(rightStack) -weatherStack.bottomAlignContent() -let weatherImg = await getImage(weatherInfo.weatherIco) -// 显示天气 -addStyleImg(weatherStack, 0, weatherImg, 32, 32) -// 体感温度 -weatherStack.addSpacer(4) -const bodyFeelingTemperature = weatherInfo.bodyFeelingTemperature -addStyleText(weatherStack, 0, `${bodyFeelingTemperature}°C`, 1, Font.boldMonospacedSystemFont(22), defaultTextColor) -////////////////////////////////////////// - -// 相对湿度 -if (weatherControl.HUMIDITY) { - rightStack.addSpacer(4) - const humidityStack = alignRightStack(rightStack) - addStyleText(humidityStack, 0, `相对湿度:${weatherInfo.humidity}`, 1, Font.systemFont(11), defaultTextColor) -} - -////////////////////////////////////////// -// 舒适指数 -if (weatherControl.COMFORT) { - rightStack.addSpacer(1) - const comfortStack = alignRightStack(rightStack) - addStyleText(comfortStack, 0, `舒适指数:${weatherInfo.comfort}`, 1, Font.systemFont(11), defaultTextColor) -} - -////////////////////////////////////////// -// 紫外线指数 -if (weatherControl.ULTRAVIOLET) { - rightStack.addSpacer(1) - const ultravioletStack = alignRightStack(rightStack) - addStyleText(ultravioletStack, 0, `紫外线:${weatherInfo.ultraviolet}`, 1, Font.systemFont(11), defaultTextColor) -} - -////////////////////////////////////////// -// 空气质量 -if (weatherControl.AQI) { - rightStack.addSpacer(1) - const aqiInfoStack = alignRightStack(rightStack) - addStyleText(aqiInfoStack, 8, `空气质量:${weatherInfo.aqiInfo}`, 1, Font.systemFont(11), defaultTextColor) -} - -////////////////////////////////////////// -// 高低温 -if (weatherControl.HEIGHT_LOW) { - const minTemperature = weatherInfo.minTemperature - const maxTemperature = weatherInfo.maxTemperature - // 右对齐 - rightStack.addSpacer(3) - const tempStack = alignRightStack(rightStack) - // 高温 - addStyleText(tempStack, 0, `↑`, 1, Font.systemFont(10), new Color("#ff0000")) - addStyleText(tempStack, 0, `${weatherInfo.maxTemperature}°`, 1, Font.systemFont(10), defaultTextColor) - // 低温 - tempStack.addSpacer(6) - addStyleText(tempStack, 0, `↓`, 1, Font.systemFont(10), new Color("#2bae85")) - addStyleText(tempStack, 0, `${weatherInfo.minTemperature}°`, 1, Font.systemFont(10), defaultTextColor) -} - -////////////////////////////////////////// -// 日出 -if (weatherControl.SUNRISE_SUNSET) { - rightStack.addSpacer(2) - let symbolStack = rightStack.addStack() - symbolStack.layoutHorizontally() - symbolStack.addSpacer() - symbolStack.bottomAlignContent() - // 添加日出icon - let sunriseImg = SFSymbol.named("sunrise.fill").image - addStyleImg(symbolStack, 0, sunriseImg, 15, 15) - symbolStack.addSpacer(4) - // 日出时间 / 样式 - addStyleText(symbolStack, 0, weatherInfo.sunrise, 1, Font.systemFont(10), defaultTextColor) - //***********************// - // 日落 - symbolStack.addSpacer(4) - // 添加日落icon - let sunsetImg = SFSymbol.named("sunset.fill").image - addStyleImg(symbolStack, 0, sunsetImg, 15, 15) - symbolStack.addSpacer(4) - // 日落时间 / 样式 - addStyleText(symbolStack, 0, weatherInfo.sunset, 1, Font.systemFont(10), defaultTextColor) -} - -////////////////////////////////////////// -// 天气更新时间 -if (weatherControl.UPDATE_TIME) { - // 更新时间 - rightStack.addSpacer(2) - const updateTimeStack = alignRightStack(rightStack) - addStyleText(updateTimeStack, 0, `上次更新 → ${num2Str(hour)}:${num2Str(minute)}`, 1, Font.systemFont(8), new Color("#ffffff", 0.8)) -} - -/*****************************小组件内容ENd*****************************/ - -if (!colorMode && !config.runsInWidget && changePicBg) { - // Determine if user has taken the screenshot. - const okTips = "您的小部件背景已准备就绪" - let message = "图片模式支持相册照片&背景透明" - let options = ["图片选择","透明背景"] - let isTransparentMode = await generateAlert(message, options) - if (!isTransparentMode) { - let img = await Photos.fromLibrary() - message = okTips - const resultOptions = ["好的"] - await generateAlert(message, resultOptions) - files.writeImage(path, img) - } else { - message = "以下是【透明背景】生成步骤,如果你没有屏幕截图请退出,并返回主屏幕长按进入编辑模式。滑动到最右边的空白页截图。然后重新运行!" - let exitOptions = ["继续(已有截图)","退出(没有截图)"] - - let shouldExit = await generateAlert(message,exitOptions) - if (shouldExit) return - - // Get screenshot and determine phone size. - let img = await Photos.fromLibrary() - let height = img.size.height - let phone = phoneSizes()[height] - if (!phone) { - message = "您似乎选择了非iPhone屏幕截图的图像,或者不支持您的iPhone。请使用其他图像再试一次!" - await generateAlert(message,["好的!我现在去截图"]) - return - } - - // Prompt for widget size and position. - message = "您想要创建什么尺寸的小部件?" - let sizes = ["小号","中号","大号"] - let size = await generateAlert(message,sizes) - let widgetSize = sizes[size] - - message = "您想它在什么位置?" - message += (height == 1136 ? " (请注意,您的设备仅支持两行小部件,因此中间和底部选项相同。)" : "") - - // Determine image crop based on phone size. - let crop = { w: "", h: "", x: "", y: "" } - if (widgetSize == "小号") { - crop.w = phone.小号 - crop.h = phone.小号 - let positions = ["顶部 左边","顶部 右边","中间 左边","中间 右边","底部 左边","底部 右边"] - let position = await generateAlert(message,positions) - - // Convert the two words into two keys for the phone size dictionary. - let keys = positions[position].split(' ') - crop.y = phone[keys[0]] - crop.x = phone[keys[1]] - - } else if (widgetSize == "中号") { - crop.w = phone.中号 - crop.h = phone.小号 - - // 中号 and 大号 widgets have a fixed x-value. - crop.x = phone.左边 - let positions = ["顶部","中间","底部"] - let position = await generateAlert(message,positions) - let key = positions[position].toLowerCase() - crop.y = phone[key] - - } else if(widgetSize == "大号") { - crop.w = phone.中号 - crop.h = phone.大号 - crop.x = phone.左边 - let positions = ["顶部","底部"] - let position = await generateAlert(message,positions) - - // 大号 widgets at the 底部 have the "中间" y-value. - crop.y = position ? phone.中间 : phone.顶部 - } - - // Crop image and finalize the widget. - let imgCrop = cropImage(img, new Rect(crop.x,crop.y,crop.w,crop.h)) - - message = "您的小部件背景已准备就绪,退出到桌面预览。" - const resultOptions = ["好的"] - await generateAlert(message, resultOptions) - files.writeImage(path, imgCrop) - } - -} - - -//////////////////////////////////////////////////////////////////////////////////// -if (colorMode) { - widget.backgroundColor = new Color(bgColorStr) -} else { - widget.backgroundImage = files.readImage(path) -} -// 设置边距(上,左,下,右) -widget.setPadding(padding.top, padding.left, padding.bottom, padding.right) -// 设置组件 -Script.setWidget(widget) -// 完成脚本 -Script.complete() -// 预览 -if (previewSize == "Large") { - widget.presentLarge() -} else if (previewSize == "Medium") { - widget.presentMedium() -} else { - widget.presentSmall() -} -//////////////////////////////////////////////////////////////////////////////////// - - - - - - -/* - ************************************************************************************ - */ - -// Generate an alert with the provided array of options. -async function generateAlert(message,options) { - let alert = new Alert() - alert.message = message - - for (const option of options) { - alert.addAction(option) - } - - let response = await alert.presentAlert() - return response -} - -// Crop an image into the specified rect. -function cropImage(img,rect) { - let draw = new DrawContext() - draw.size = new Size(rect.width, rect.height) - draw.drawImageAtPoint(img,new Point(-rect.x, -rect.y)) - return draw.getImage() -} - -// Pixel sizes and positions for widgets on all supported phones. -function phoneSizes() { - let phones = { - "2688": { - "小号": 507, - "中号": 1080, - "大号": 1137, - "左边": 81, - "右边": 654, - "顶部": 228, - "中间": 858, - "底部": 1488 - }, - - "1792": { - "小号": 338, - "中号": 720, - "大号": 758, - "左边": 54, - "右边": 436, - "顶部": 160, - "中间": 580, - "底部": 1000 - }, - - "2436": { - "小号": 465, - "中号": 987, - "大号": 1035, - "左边": 69, - "右边": 591, - "顶部": 213, - "中间": 783, - "底部": 1353 - }, - - "2208": { - "小号": 471, - "中号": 1044, - "大号": 1071, - "左边": 99, - "右边": 672, - "顶部": 114, - "中间": 696, - "底部": 1278 - }, - - "1334": { - "小号": 296, - "中号": 642, - "大号": 648, - "左边": 54, - "右边": 400, - "顶部": 60, - "中间": 412, - "底部": 764 - }, - - "1136": { - "小号": 282, - "中号": 584, - "大号": 622, - "左边": 30, - "右边": 332, - "顶部": 59, - "中间": 399, - "底部": 399 - } - } - return phones -} - - -/* - **************************************************************************************************************************** - **************************************************************************************************************************** - **************************************************************************************************************************** - */ - -/* - ************************************** - * 添加一行文本数据显示 - ************************************** - */ -function addStyleText(stack, topMargin, text, lineLimit, font, textColor, width = 0) { - textStyle.stack = stack - textStyle.topMargin = topMargin - textStyle.text = text - textStyle.lineLimit = lineLimit - textStyle.font = font - textStyle.textColor = textColor - addText(textStyle) - textStyle.lineLimit = 0 -} - -function addText(style, width = 0) { - style.stack.size = new Size(width, 0) - style.stack.addSpacer(style.topMargin) - let textSpan = style.stack.addText(style.text + "") - textSpan.font = style.font - textSpan.lineLimit = style.lineLimit - textSpan.textColor = style.textColor -} - - -/* - ************************************** - * 添加图片显示 - ************************************** - */ -function addStyleImg(stack, topMargin, img, width, length, tintColor) { - imgStyle.stack = stack - imgStyle.topMargin = topMargin - imgStyle.img = img - imgStyle.width = width - imgStyle.length = length - imgStyle.tintColor = tintColor - addImg(imgStyle) -} - -function addImg(style) { - const stack = style.stack - stack.addSpacer(style.topMargin) - let imgSpan = stack.addImage(style.img) - imgSpan.imageSize = new Size(style.width, style.length) - const tintColor = style.tintColor - if (tintColor != undefined) { - imgSpan.tintColor = tintColor - } -} - - -/* - ************************************** - * 格式化时间 - ************************************** - */ -function getDateStr(date, formatter = "yyyy年MM月d日") { - let df = new DateFormatter() - df.locale = locale - df.dateFormat = formatter - return df.string(date) -} - -/* - ************************************** - * 按照时间获取问候语 - ************************************** - */ -function provideGreeting(date) { - const hour = date.getHours() - if (hour < 5) { return greetingText.nightGreeting } - if (hour < 11) { return greetingText.morningGreeting } - if (hour > 11 && hour-12 < 1) { return greetingText.noonGreeting } - if (hour-12 < 7) { return greetingText.afternoonGreeting } - if (hour-12 < 10) { return greetingText.eveningGreeting } - return greetingText.nightGreeting -} - - -/* - ************************************** - * 获取彩云天气 - ************************************** - */ -async function getWeather() { - let weatherInfo = {} - const location = await getLocation() - log("定位信息:" + location.locality + "·" + location.subLocality) - // 彩云天气域名 - const DOMAIN = `https://api.caiyunapp.com/v2.5/${apiKey}/${location.longitude},${location.latitude}/weather.json?alert=true` - const weatherJsonData = await getJson(DOMAIN) - if (weatherJsonData.status == "ok") { - log("天气数据请求成功") - // 天气突发预警 - const alertWeatherTitle = weatherJsonData.result.alert.content.title - log("突发的天气预警==>" + alertWeatherTitle) - weatherInfo.alertWeatherTitle = alertWeatherTitle - - // 温度范围 - const temperatureData = weatherJsonData.result.daily.temperature[0] - // 最低温度 - const minTemperature = temperatureData.min - // 最高温度 - const maxTemperature = temperatureData.max - log("温度==>" + minTemperature + "|" + maxTemperature) - weatherInfo.minTemperature = Math.round(minTemperature) - weatherInfo.maxTemperature = Math.round(maxTemperature) - - // 体感温度 - const bodyFeelingTemperature = weatherJsonData.result.realtime.apparent_temperature - log("体感温度==>" + bodyFeelingTemperature) - weatherInfo.bodyFeelingTemperature = Math.round(bodyFeelingTemperature) - - // 天气状况 weatherIcos[weatherIco] - const weather = weatherJsonData.result.realtime.skycon - log("天气状况==>" + weather + "|" + weatherIcos[weather]) - weatherInfo.weatherIco = weatherIcos[weather] - - // 天气描述 - const weatherDesc = weatherJsonData.result.forecast_keypoint - log("天气描述==>" + weatherDesc) - weatherInfo.weatherDesc = weatherDesc - - // 相对湿度 - const humidity = (Math.round(weatherJsonData.result.realtime.humidity * 100)) + "%" - log("相对湿度==>" + weatherJsonData.result.realtime.humidity) - weatherInfo.humidity = humidity - - // 舒适指数 - const comfort = weatherJsonData.result.realtime.life_index.comfort.desc - log("舒适指数==>" + comfort) - weatherInfo.comfort = comfort - - // 紫外线指数 - const ultraviolet = weatherJsonData.result.realtime.life_index.ultraviolet.desc - log("紫外线指数==>" + ultraviolet) - weatherInfo.ultraviolet = ultraviolet - - // 空气质量 - const aqi = weatherJsonData.result.realtime.air_quality.aqi.chn - const aqiInfo = airQuality(aqi) - log("空气质量==>" + aqiInfo) - weatherInfo.aqiInfo = aqiInfo - - // 日出日落 - const astro = weatherJsonData.result.daily.astro[0] - // 日出 - const sunrise = astro.sunrise.time - // 日落 - const sunset = astro.sunset.time - log("日出==>" + sunrise + ",日落==>" + sunset) - weatherInfo.sunrise = sunrise.toString() - weatherInfo.sunset = sunset.toString() - } - - return weatherInfo -} - - -/* - ************************************** - * 获取定位 - ************************************** - */ -async function getLocation() { - if (!lockLocation) { - try { - const location = await Location.current() - const geocode = await Location.reverseGeocode(location.latitude, location.longitude, locale) - locationData.latitude = location.latitude - locationData.longitude = location.longitude - const geo = geocode[0] - // 市 - locationData.locality = geo.locality - // 区 - locationData.subLocality = geo.subLocality - // 街道 - locationData.street = geo.thoroughfare - log("定位信息:latitude=" + location.latitude + ",longitude=" + location.longitude + ",locality=" - + locationData.locality + ",subLocality=" + locationData.subLocality + ",street=" + locationData.street) - } catch(e) { - log("定位出错了," + e.toString()) - } - } - - return locationData -} - - -/* - ************************************** - * 日程筛选 - ************************************** - */ -function shouldShowSchedule(schedule) { - const currentDate = new Date() - // 被取消的日程不用显示 - if (schedule.title.startsWith("Canceled:")) { return false } - // 与当前时间做比较 - let timeInterval = schedule.startDate.getTime() > currentDate.getTime() - // 返回全天跟还没过去的 - return timeInterval || schedule.isAllDay -} - - -/* - ************************************** - * 日程列表 - ************************************** - */ -async function getSchedules() { - let showSchedules = [] - const todaySchedules = await CalendarEvent.today([]) - for (const schedule of todaySchedules) { - if (shouldShowSchedule(schedule)) { - // 日程 - let scheduleObj = {} - // 开始时间 - const startDate = schedule.startDate - // 开始小时 - const startHour = ("0" + startDate.getHours()).slice(-2) - // 开始分钟 - const startMinute = ("0" + startDate.getMinutes()).slice(-2) - - // 结束时间 - const endDate = schedule.endDate - // 结束小时 - const endHour = ("0" + endDate.getHours()).slice(-2) - // 结束分钟 - const endMinute = ("0" + endDate.getMinutes()).slice(-2) - - // 时间安排展示 - let timeText = startHour + ":" + startMinute + "→" + endHour + ":" + endMinute - if (schedule.isAllDay) { - timeText = "全天" - } - - // 构造格式后的日程 - scheduleObj.title = schedule.title - scheduleObj.timeText = timeText - log(">>日程:" + scheduleObj.title + "==>" + timeText) - showSchedules.push(scheduleObj) - } - } - - return showSchedules -} - - -/* - ************************************** - * 提醒事项列表 - ************************************** - */ -async function getReminders() { - let showReminders = [] - const allReminders = await Reminder.all(); - for (const reminder of allReminders) { - if (!reminder.isCompleted) { - let reminderObj = {} - // 构造格式后的提醒事项 - reminderObj.title = reminder.title - reminderObj.dueDate = reminder.dueDate - log(">>提醒事项:" + reminderObj.title + "==>" + reminderObj.dueDate) - showReminders.push(reminder) - } - } - - return showReminders -} - - -/* - ************************************** - * 网络请求get封装 - ************************************** - */ -async function getJson(url) { - const request = new Request(url) - const defaultHeaders = { - "Accept": "*/*", - "Content-Type": "application/json" - } - - request.url = url - request.method = 'GET' - request.headers = defaultHeaders - - const data = await request.loadJSON() - - return data -} - - -/* - ************************************** - * 空气质量指标 - ************************************** - */ -function airQuality(levelNum) { - // 0-50 优,51-100 良,101-150 轻度污染,151-200 中度污染 - // 201-300 重度污染,>300 严重污染 - if (levelNum >= 0 && levelNum <= 50) { - return "优秀" - } else if (levelNum >= 51 && levelNum <= 100) { - return "良好" - } else if (levelNum >= 101 && levelNum <= 150) { - return "轻度" - } else if (levelNum >= 151 && levelNum <= 200) { - return "中度" - } else if (levelNum >= 201 && levelNum <= 300) { - return "重度" - } else { - return "严重" - } -} - - -/* - ************************************** - * 获取电池信息 - ************************************** - */ -function getBatteryLevel() { - const batteryLevel = Device.batteryLevel() - const batteryAscii = `${Math.round(batteryLevel * 100)}%` - log("电池==>" + batteryAscii) - return batteryAscii; -} - - -/* - ************************************** - * 在线获取农历信息 - ************************************** - */ -async function getLunar() { - const request = new Request("https://www.iamwawa.cn/home/nongli/ajax") - const defaultHeaders = { - "Accept": "*/*", - "Content-Type": "application/json" - } - request.method = 'POST' - request.headers = defaultHeaders - request.addParameterToMultipart("type", "solar") - request.addParameterToMultipart("year", year + "") - request.addParameterToMultipart("month", month + "") - request.addParameterToMultipart("day", day + "") - const data = await request.loadJSON() - return data -} - -/* - ************************************** - * 在线获取今日诗词 - ************************************** - */ -async function getPoetry() { - const request = new Request("https://v2.jinrishici.com/sentence") - const defaultHeaders = { - "Accept": "*/*", - "Content-Type": "application/json" - } - request.method = 'GET' - request.headers = defaultHeaders - const data = await request.loadJSON() - log("诗词==>" + data.status) - return data - } - - -/* - ************************************** - * 获取星期几 - ************************************** - */ - function getDayWeekTitle(date) { - return weekTitle[date.getDay()] - } - - -/* - ************************************** - * 右对齐 - ************************************** - */ -function alignRightStack(alignmentStack) { - let returnStack = alignmentStack.addStack() - returnStack.layoutHorizontally() - returnStack.addSpacer() - return returnStack -} - - -/* - ************************************** - * 水平居中 - ************************************** - */ -function horizontallyCenterStack(alignmentStack) { - let returnStack = alignmentStack.addStack() - returnStack.layoutHorizontally() - returnStack.centerAlignContent() - return returnStack -} - - -/* - ************************************** - * 垂直居中 - ************************************** - */ -function verticallyCenterStack(alignmentStack) { - let returnStack = alignmentStack.addStack() - returnStack.layoutVertically() - returnStack.centerAlignContent() - return returnStack -} - - -/* - ************************************** - * 数字加0 - ************************************** - */ -function num2Str(num) { - if (num < 10) { - return `0${num}` - } else { - return `${num}` - } -} - -/* -**************************************************************************** -* 网络请求获取图片 -**************************************************************************** -*/ -async function getImage(url) { - const request = new Request(url) - const data = await request.loadImage() - return data -} diff --git "a/\346\226\260\347\263\273\345\210\227/material_weather.js" "b/\346\226\260\347\263\273\345\210\227/material_weather.js" new file mode 100644 index 0000000..6762a38 --- /dev/null +++ "b/\346\226\260\347\263\273\345\210\227/material_weather.js" @@ -0,0 +1,1156 @@ +/** +* Author:LSP +* Date:2021-03-01 +*/ +// @导入引用开发环境 +if (typeof require === 'undefined') require = importModule +const { Base } = require("./lsp环境") + +// @小组件配置 +const widgetConfigs = { + // 打开更新,直接同步脚本 + openDownload: true, + + // 彩云key + apiKey: "", + + // 是否是iPhone12mini + isIphone12Mini: false, + // 缓存刷新时间--估算(单位:分钟) + refreshInterval: 10, + + // 组件样式:1、2(选择样式2推荐打开透明背景开关【selectPicBg:true】) + widgetStyle: 1, + // 组件背景样式:1、2、3、4、5、6 + widgetUIBg: 6, + // 组件天气icon样式:1、2、3、4、5(开启useSF的话则此选项无效) + widgetUIIcon: 5, + // 是否使用SF系统天气图标 + useSF: false, + + // 是否显示定位 + showLocation: true, + // 是否显示具体天气文本 + showWeatherDesc: true, + // 是否显示农历 + showLunar: true, + // 是否显示更新时间 + showUpdateTime: true, + // 备用仓库地址 + useGithub: false, + + selectPicBg: false, // 透明背景图片 + colorBgMode: false, // 纯色背景模式 + bgColor: Color.black(), // 背景色 + + // 位置,可以不进行定位,或者定位为出错的时候使用 + location: { + "latitude": undefined, + "longitude": undefined, + "locality": undefined, + "subLocality": undefined + }, + // 锁定地区,直接使用上述填写的地址信息不进行定位 + lockLocation: false, + // 地区 + locale: "zh-cn", + + padding: { + top: 0, // 上边距 + left: 0, // 左边距 + bottom: 0, // 底边距 + right: 0, // 右边距 + }, + + // 英文字体 + enFontUrl: "https://mashangkaifa.coding.net/p/coding-code-guide/d/coding-code-guide/git/raw/master/HelveticaNeue-Thin.otf", + + // 预览模式:0:小尺寸,1:中等尺寸,2:大尺寸,负数:不预览 + previewMode: 1, + + //********************************************************************** + // 天气描述 + weatherDesc: { + CLEAR_DAY: "Sunny", + CLEAR_NIGHT: "Sunny", + PARTLY_CLOUDY_DAY: "Cloudy", + PARTLY_CLOUDY_NIGHT: "Cloudy", + CLOUDY: "Cloudy", + CLOUDY_NIGHT: "Cloudy", + LIGHT_HAZE: "Haze", + LIGHT_HAZE_NIGHT: "Haze", + MODERATE_HAZE: "Haze", + MODERATE_HAZE_NIGHT: "Haze", + HEAVY_HAZE: "Haze", + HEAVY_HAZE_NIGHT: "Haze", + LIGHT_RAIN: "Rain", + MODERATE_RAIN: "Rain", + HEAVY_RAIN: "Rain", + STORM_RAIN: "Rain", + FOG: "Fog", + LIGHT_SNOW: "Snow", + MODERATE_SNOW: "Snow", + HEAVY_SNOW: "Snow", + STORM_SNOW: "Snow", + DUST: "Dust", + SAND: "Sand", + WIND: "Wind", + }, + // 自定义天气对应的icon-->1 + weatherOneIcos: { + CLEAR_DAY: "https://s3.ax1x.com/2020/12/08/rpVVhD.png", // 晴(白天) CLEAR_DAY + CLEAR_NIGHT: "https://s1.ax1x.com/2020/10/26/BukPhR.png", // 晴(夜间) CLEAR_NIGHT + PARTLY_CLOUDY_DAY: "https://s1.ax1x.com/2020/10/26/BuQHN6.png", // 多云(白天) PARTLY_CLOUDY_DAY + PARTLY_CLOUDY_NIGHT: "https://s1.ax1x.com/2020/10/26/BukcbF.png", // 多云(夜间) PARTLY_CLOUDY_NIGHT + CLOUDY: "https://s3.ax1x.com/2020/12/10/ripz8J.png", // 阴(白天) CLOUDY + CLOUDY_NIGHT: "https://s3.ax1x.com/2020/12/10/ripz8J.png", // 阴(夜间) CLOUDY + LIGHT_HAZE: "https://s3.ax1x.com/2021/01/15/s009Mj.png", // 轻度雾霾 LIGHT_HAZE + LIGHT_HAZE_NIGHT: "https://s3.ax1x.com/2021/01/15/s00dOA.png", // 轻度雾霾 LIGHT_HAZE + MODERATE_HAZE: "https://s3.ax1x.com/2021/01/15/s009Mj.png", // 中度雾霾 MODERATE_HAZE + MODERATE_HAZE_NIGHT: "https://s3.ax1x.com/2021/01/15/s00dOA.png", // 中度雾霾 MODERATE_HAZE + HEAVY_HAZE: "https://s3.ax1x.com/2021/01/15/s009Mj.png", // 重度雾霾 HEAVY_HAZE + HEAVY_HAZE_NIGHT: "https://s3.ax1x.com/2021/01/15/s00dOA.png", // 重度雾霾 HEAVY_HAZE + LIGHT_RAIN: "https://s3.ax1x.com/2020/12/15/rMkQVx.png", // 小雨 LIGHT_RAIN + MODERATE_RAIN: "https://s3.ax1x.com/2020/12/15/rMkBIf.png", // 中雨 MODERATE_RAIN + HEAVY_RAIN: "https://s3.ax1x.com/2020/12/15/rMk6zQ.png", // 大雨 HEAVY_RAIN + STORM_RAIN: "https://s3.ax1x.com/2020/12/15/rMk6zQ.png", // 暴雨 STORM_RAIN + FOG: "https://s3.ax1x.com/2020/12/15/rMAYkV.png", // 雾 FOG + LIGHT_SNOW: "https://s3.ax1x.com/2020/12/15/rMActK.png", // 小雪 LIGHT_SNOW + MODERATE_SNOW: "https://s3.ax1x.com/2020/12/15/rMActK.png", // 中雪 MODERATE_SNOW + HEAVY_SNOW: "https://s3.ax1x.com/2020/12/15/rMActK.png", // 大雪 HEAVY_SNOW + STORM_SNOW: "https://s3.ax1x.com/2020/12/15/rMActK.png", // 暴雪 STORM_SNOW + DUST: "https://s3.ax1x.com/2020/12/08/rpupes.png", // 浮尘 DUST + SAND: "https://s3.ax1x.com/2020/12/08/rpupes.png", // 沙尘 SAND + WIND: "https://s3.ax1x.com/2020/12/15/rMEeBR.png", // 大风 WIND + }, + // 自定义天气对应的icon-->2 + weatherTwoIcos: { + CLEAR_DAY: "https://s3.ax1x.com/2021/01/23/s7tKd1.png", // 晴(白天) CLEAR_DAY + CLEAR_NIGHT: "https://s3.ax1x.com/2021/01/23/s7tli6.png", // 晴(夜间) CLEAR_NIGHT + PARTLY_CLOUDY_DAY: "https://s3.ax1x.com/2021/01/23/s7t3RO.png", // 多云(白天) PARTLY_CLOUDY_DAY + PARTLY_CLOUDY_NIGHT: "hhttps://s3.ax1x.com/2021/01/23/s7tJQe.png", // 多云(夜间) PARTLY_CLOUDY_NIGHT + CLOUDY: "https://s3.ax1x.com/2021/01/23/s7tdot.png", // 阴(白天) CLOUDY + CLOUDY_NIGHT: "https://s3.ax1x.com/2021/01/23/s7tdot.png", // 阴(夜间) CLOUDY + LIGHT_HAZE: "https://s3.ax1x.com/2021/01/23/s7tDW8.png", // 轻度雾霾 LIGHT_HAZE + LIGHT_HAZE_NIGHT: "https://s3.ax1x.com/2021/01/23/s7tDW8.png", // 轻度雾霾 LIGHT_HAZE + MODERATE_HAZE: "https://s3.ax1x.com/2021/01/23/s7tDW8.png", // 中度雾霾 MODERATE_HAZE + MODERATE_HAZE_NIGHT: "https://s3.ax1x.com/2021/01/23/s7tDW8.png", // 中度雾霾 MODERATE_HAZE + HEAVY_HAZE: "https://s3.ax1x.com/2021/01/23/s7tDW8.png", // 重度雾霾 HEAVY_HAZE + HEAVY_HAZE_NIGHT: "https://s3.ax1x.com/2021/01/23/s7tDW8.png", // 重度雾霾 HEAVY_HAZE + LIGHT_RAIN: "https://s3.ax1x.com/2021/01/23/s7NCOH.png", // 小雨 LIGHT_RAIN + MODERATE_RAIN: "https://s3.ax1x.com/2021/01/23/s7NCOH.png", // 中雨 MODERATE_RAIN + HEAVY_RAIN: "https://s3.ax1x.com/2021/01/23/s7NCOH.png", // 大雨 HEAVY_RAIN + STORM_RAIN: "https://s3.ax1x.com/2021/01/23/s7NCOH.png", // 暴雨 STORM_RAIN + FOG: "https://s3.ax1x.com/2021/01/23/s7tDW8.png", // 雾 FOG + LIGHT_SNOW: "https://s3.ax1x.com/2021/01/23/s7Nmp8.png", // 小雪 LIGHT_SNOW + MODERATE_SNOW: "https://s3.ax1x.com/2021/01/23/s7Nmp8.png", // 中雪 MODERATE_SNOW + HEAVY_SNOW: "https://s3.ax1x.com/2021/01/23/s7Nmp8.png", // 大雪 HEAVY_SNOW + STORM_SNOW: "https://s3.ax1x.com/2021/01/23/s7Nmp8.png", // 暴雪 STORM_SNOW + DUST: "https://s3.ax1x.com/2021/01/23/s7txfK.png", // 浮尘 DUST + SAND: "https://s3.ax1x.com/2021/01/23/s7txfK.png", // 沙尘 SAND + WIND: "https://s3.ax1x.com/2021/01/23/s7txfK.png", // 大风 WIND + }, + // 自定义天气对应的icon-->3 + weatherThreeIcos: { + CLEAR_DAY: "https://s3.ax1x.com/2021/01/24/sHAD1K.png", // 晴(白天) CLEAR_DAY + CLEAR_NIGHT: "https://s3.ax1x.com/2021/01/24/sHABp6.png", // 晴(夜间) CLEAR_NIGHT + PARTLY_CLOUDY_DAY: "https://s3.ax1x.com/2021/01/24/sHAwfx.png", // 多云(白天) PARTLY_CLOUDY_DAY + PARTLY_CLOUDY_NIGHT: "https://s3.ax1x.com/2021/01/24/sHAdt1.png", // 多云(夜间) PARTLY_CLOUDY_NIGHT + CLOUDY: "https://s3.ax1x.com/2021/01/24/sHAakR.png", // 阴(白天) CLOUDY + CLOUDY_NIGHT: "https://s3.ax1x.com/2021/01/24/sHAr6O.png", // 阴(夜间) CLOUDY + LIGHT_HAZE: "https://s3.ax1x.com/2021/01/24/sHAsXD.png", // 轻度雾霾 LIGHT_HAZE + LIGHT_HAZE_NIGHT: "https://s3.ax1x.com/2021/01/24/sHAsXD.png", // 轻度雾霾 LIGHT_HAZE + MODERATE_HAZE: "https://s3.ax1x.com/2021/01/24/sHAsXD.png", // 中度雾霾 MODERATE_HAZE + MODERATE_HAZE_NIGHT: "https://s3.ax1x.com/2021/01/24/sHAsXD.png", // 中度雾霾 MODERATE_HAZE + HEAVY_HAZE: "https://s3.ax1x.com/2021/01/24/sHAsXD.png", // 重度雾霾 HEAVY_HAZE + HEAVY_HAZE_NIGHT: "https://s3.ax1x.com/2021/01/24/sHAsXD.png", // 重度雾霾 HEAVY_HAZE + LIGHT_RAIN: "https://s3.ax1x.com/2021/01/24/sHA6ne.png", // 小雨 LIGHT_RAIN + MODERATE_RAIN: "https://s3.ax1x.com/2021/01/24/sHAc0H.png", // 中雨 MODERATE_RAIN + HEAVY_RAIN: "https://s3.ax1x.com/2021/01/24/sHARAA.png", // 大雨 HEAVY_RAIN + STORM_RAIN: "https://s3.ax1x.com/2021/01/24/sHARAA.png", // 暴雨 STORM_RAIN + FOG: "https://s3.ax1x.com/2021/01/24/sHAsXD.png", // 雾 FOG + LIGHT_SNOW: "https://s3.ax1x.com/2021/01/24/sHAg7d.png", // 小雪 LIGHT_SNOW + MODERATE_SNOW: "https://s3.ax1x.com/2021/01/24/sHAg7d.png", // 中雪 MODERATE_SNOW + HEAVY_SNOW: "https://s3.ax1x.com/2021/01/24/sHAWtI.png", // 大雪 HEAVY_SNOW + STORM_SNOW: "https://s3.ax1x.com/2021/01/24/sHAWtI.png", // 暴雪 STORM_SNOW + DUST: "https://s3.ax1x.com/2021/01/24/sHVnGq.png", // 浮尘 DUST + SAND: "https://s3.ax1x.com/2021/01/24/sHVnGq.png", // 沙尘 SAND + WIND: "https://s3.ax1x.com/2021/01/24/sHVuR0.png", // 大风 WIND + }, + // 自定义天气对应的icon-->4 + weatherFourIcos: { + CLEAR_DAY: "https://s3.ax1x.com/2021/01/26/svnyF0.png", // 晴(白天) CLEAR_DAY + CLEAR_NIGHT: "https://s3.ax1x.com/2021/01/26/svnfOJ.png", // 晴(夜间) CLEAR_NIGHT + PARTLY_CLOUDY_DAY: "https://s3.ax1x.com/2021/01/26/svn2SU.png", // 多云(白天) PARTLY_CLOUDY_DAY + PARTLY_CLOUDY_NIGHT: "https://s3.ax1x.com/2021/01/26/svnRlF.png", // 多云(夜间) PARTLY_CLOUDY_NIGHT + CLOUDY: "https://s3.ax1x.com/2021/01/26/svnroq.png", // 阴(白天) CLOUDY + CLOUDY_NIGHT: "https://s3.ax1x.com/2021/01/26/svnroq.png", // 阴(夜间) CLOUDY + LIGHT_HAZE: "https://s3.ax1x.com/2021/01/26/svnWy4.png", // 轻度雾霾 LIGHT_HAZE + LIGHT_HAZE_NIGHT: "https://s3.ax1x.com/2021/01/26/svncWT.png", // 轻度雾霾 LIGHT_HAZE + MODERATE_HAZE: "https://s3.ax1x.com/2021/01/26/svnWy4.png", // 中度雾霾 MODERATE_HAZE + MODERATE_HAZE_NIGHT: "https://s3.ax1x.com/2021/01/26/svncWT.png", // 中度雾霾 MODERATE_HAZE + HEAVY_HAZE: "https://s3.ax1x.com/2021/01/26/svnWy4.png", // 重度雾霾 HEAVY_HAZE + HEAVY_HAZE_NIGHT: "https://s3.ax1x.com/2021/01/26/svncWT.png", // 重度雾霾 HEAVY_HAZE + LIGHT_RAIN: "https://s3.ax1x.com/2021/01/26/svnBes.png", // 小雨 LIGHT_RAIN + MODERATE_RAIN: "https://s3.ax1x.com/2021/01/26/svn5wR.png", // 中雨 MODERATE_RAIN + HEAVY_RAIN: "https://s3.ax1x.com/2021/01/26/svn4m9.png", // 大雨 HEAVY_RAIN + STORM_RAIN: "https://s3.ax1x.com/2021/01/26/svnDwn.png", // 暴雨 STORM_RAIN + FOG: "https://s3.ax1x.com/2021/01/26/svn6YV.png", // 雾 FOG + LIGHT_SNOW: "https://s3.ax1x.com/2021/01/26/svnwLj.png", // 小雪 LIGHT_SNOW + MODERATE_SNOW: "https://s3.ax1x.com/2021/01/26/svnwLj.png", // 中雪 MODERATE_SNOW + HEAVY_SNOW: "https://s3.ax1x.com/2021/01/26/svnwLj.png", // 大雪 HEAVY_SNOW + STORM_SNOW: "https://s3.ax1x.com/2021/01/26/svnwLj.png", // 暴雪 STORM_SNOW + DUST: "https://s3.ax1x.com/2021/01/26/svuh38.png", // 浮尘 DUST + SAND: "https://s3.ax1x.com/2021/01/26/svuh38.png", // 沙尘 SAND + WIND: "https://s3.ax1x.com/2021/01/26/svndyQ.png", // 大风 WIND + }, + // 自定义天气对应的icon-->5 + weatherFiveIcos: { + CLEAR_DAY: "https://s3.ax1x.com/2021/01/26/svubEn.png", // 晴(白天) CLEAR_DAY + CLEAR_NIGHT: "https://s3.ax1x.com/2021/01/26/svuqNq.png", // 晴(夜间) CLEAR_NIGHT + PARTLY_CLOUDY_DAY: "https://s3.ax1x.com/2021/01/26/svu5jg.png", // 多云(白天) PARTLY_CLOUDY_DAY + PARTLY_CLOUDY_NIGHT: "https://s3.ax1x.com/2021/01/26/svuTBj.png", // 多云(夜间) PARTLY_CLOUDY_NIGHT + CLOUDY: "https://s3.ax1x.com/2021/01/26/svu4gS.png", // 阴(白天) CLOUDY + CLOUDY_NIGHT: "https://s3.ax1x.com/2021/01/26/svu4gS.png", // 阴(夜间) CLOUDY + LIGHT_HAZE: "https://s3.ax1x.com/2021/01/26/svu7Hs.png", // 轻度雾霾 LIGHT_HAZE + LIGHT_HAZE_NIGHT: "https://s3.ax1x.com/2021/01/26/svu7Hs.png", // 轻度雾霾 LIGHT_HAZE + MODERATE_HAZE: "https://s3.ax1x.com/2021/01/26/svu7Hs.png", // 中度雾霾 MODERATE_HAZE + MODERATE_HAZE_NIGHT: "https://s3.ax1x.com/2021/01/26/svu7Hs.png", // 中度雾霾 MODERATE_HAZE + HEAVY_HAZE: "https://s3.ax1x.com/2021/01/26/svu7Hs.png", // 重度雾霾 HEAVY_HAZE + HEAVY_HAZE_NIGHT: "https://s3.ax1x.com/2021/01/26/svu7Hs.png", // 重度雾霾 HEAVY_HAZE + LIGHT_RAIN: "https://s3.ax1x.com/2021/01/26/svuR4P.png", // 小雨 LIGHT_RAIN + MODERATE_RAIN: "https://s3.ax1x.com/2021/01/26/svuR4P.png", // 中雨 MODERATE_RAIN + HEAVY_RAIN: "https://s3.ax1x.com/2021/01/26/svuR4P.png", // 大雨 HEAVY_RAIN + STORM_RAIN: "https://s3.ax1x.com/2021/01/26/svuR4P.png", // 暴雨 STORM_RAIN + FOG: "https://s3.ax1x.com/2021/01/26/svu2Nt.png", // 雾 FOG + LIGHT_SNOW: "https://s3.ax1x.com/2021/01/26/svuouQ.png", // 小雪 LIGHT_SNOW + MODERATE_SNOW: "https://s3.ax1x.com/2021/01/26/svuouQ.png", // 中雪 MODERATE_SNOW + HEAVY_SNOW: "https://s3.ax1x.com/2021/01/26/svuouQ.png", // 大雪 HEAVY_SNOW + STORM_SNOW: "https://s3.ax1x.com/2021/01/26/svuouQ.png", // 暴雪 STORM_SNOW + DUST: "https://s3.ax1x.com/2021/01/26/svuh38.png", // 浮尘 DUST + SAND: "https://s3.ax1x.com/2021/01/26/svuh38.png", // 沙尘 SAND + WIND: "https://s3.ax1x.com/2021/01/26/svuL40.png", // 大风 WIND + }, + // SF对应的天气icon + weatherSFIcos: { + CLEAR_DAY: "sun.max.fill", // 晴(白天) CLEAR_DAY + CLEAR_NIGHT: "moon.stars.fill", // 晴(夜间) CLEAR_NIGHT + PARTLY_CLOUDY_DAY: "cloud.sun.fill", // 多云(白天) PARTLY_CLOUDY_DAY + PARTLY_CLOUDY_NIGHT: "cloud.moon.fill", // 多云(夜间) PARTLY_CLOUDY_NIGHT + CLOUDY: "cloud.fill", // 阴(白天) CLOUDY + CLOUDY_NIGHT: "cloud.fill", // 阴(夜间) CLOUDY + LIGHT_HAZE: "sun.haze.fill", // 轻度雾霾 LIGHT_HAZE + LIGHT_HAZE_NIGHT: "sun.haze.fill", // 轻度雾霾 LIGHT_HAZE + MODERATE_HAZE: "sun.haze.fill", // 中度雾霾 MODERATE_HAZE + MODERATE_HAZE_NIGHT: "sun.haze.fill", // 中度雾霾 MODERATE_HAZE + HEAVY_HAZE: "sun.haze.fill", // 重度雾霾 HEAVY_HAZE + HEAVY_HAZE_NIGHT: "sun.haze.fill", // 重度雾霾 HEAVY_HAZE + LIGHT_RAIN: "cloud.drizzle.fill", // 小雨 LIGHT_RAIN + MODERATE_RAIN: "cloud.drizzle.fill", // 中雨 MODERATE_RAIN + HEAVY_RAIN: "cloud.rain.fill", // 大雨 HEAVY_RAIN + STORM_RAIN: "cloud.heavyrain.fill", // 暴雨 STORM_RAIN + FOG: "cloud.fog.fill", // 雾 FOG + LIGHT_SNOW: "cloud.snow.fill", // 小雪 LIGHT_SNOW + MODERATE_SNOW: "cloud.snow.fill", // 中雪 MODERATE_SNOW + HEAVY_SNOW: "cloud.snow.fill", // 大雪 HEAVY_SNOW + STORM_SNOW: "cloud.snow.fill", // 暴雪 STORM_SNOW + DUST: "sun.dust.fill", // 浮尘 DUST + SAND: "smoke.fill", // 沙尘 SAND + WIND: "wind", // 大风 WIND + }, + //********************************************************************** + // 天气对应的背景->1 + weatherBgOneUrls: { + CLEAR_DAY: "https://s3.ax1x.com/2021/01/23/s78p4S.png", // 晴(白天) CLEAR_DAY + CLEAR_NIGHT: "https://s3.ax1x.com/2021/01/23/s73zAf.jpg", // 晴(夜间) CLEAR_NIGHT + PARTLY_CLOUDY_DAY: "https://s3.ax1x.com/2021/01/23/s73vHP.png", // 多云(白天) PARTLY_CLOUDY_DAY + PARTLY_CLOUDY_NIGHT: "https://s3.ax1x.com/2021/01/23/s73zAf.jpg", // 多云(夜间) PARTLY_CLOUDY_NIGHT + CLOUDY: "https://s3.ax1x.com/2021/01/23/s73jBt.png", // 阴(白天) CLOUDY + CLOUDY_NIGHT: "https://s3.ax1x.com/2021/01/23/s73zAf.jpg", // 阴(夜间) CLOUDY + LIGHT_HAZE: "https://s3.ax1x.com/2021/01/23/s78SN8.png", // 轻度雾霾 LIGHT_HAZE + LIGHT_HAZE_NIGHT: "https://s3.ax1x.com/2021/01/23/s73zAf.jpg", // 轻度雾霾 LIGHT_HAZE + MODERATE_HAZE: "https://s3.ax1x.com/2021/01/23/s78SN8.png", // 中度雾霾 MODERATE_HAZE + MODERATE_HAZE_NIGHT: "https://s3.ax1x.com/2021/01/23/s73zAf.jpg", // 中度雾霾 MODERATE_HAZE + HEAVY_HAZE: "https://s3.ax1x.com/2021/01/23/s78SN8.png", // 重度雾霾 HEAVY_HAZE + HEAVY_HAZE_NIGHT: "https://s3.ax1x.com/2021/01/23/s73zAf.jpg", // 重度雾霾 HEAVY_HAZE + LIGHT_RAIN: "https://s3.ax1x.com/2021/01/23/s78C9g.png", // 小雨 LIGHT_RAIN + MODERATE_RAIN: "https://s3.ax1x.com/2021/01/23/s78C9g.png", // 中雨 MODERATE_RAIN + HEAVY_RAIN: "https://s3.ax1x.com/2021/01/23/s78C9g.png", // 大雨 HEAVY_RAIN + STORM_RAIN: "https://s3.ax1x.com/2021/01/23/s78C9g.png", // 暴雨 STORM_RAIN + FOG: "https://s3.ax1x.com/2021/01/23/s78SN8.png", // 雾 FOG + LIGHT_SNOW: "https://s3.ax1x.com/2021/01/23/s78P3Q.png", // 小雪 LIGHT_SNOW + MODERATE_SNOW: "https://s3.ax1x.com/2021/01/23/s78P3Q.png", // 中雪 MODERATE_SNOW + HEAVY_SNOW: "https://s3.ax1x.com/2021/01/23/s78P3Q.png", // 大雪 HEAVY_SNOW + STORM_SNOW: "https://s3.ax1x.com/2021/01/23/s78P3Q.png", // 暴雪 STORM_SNOW + DUST: "https://s3.ax1x.com/2021/01/23/s78SN8.png", // 浮尘 DUST + SAND: "https://s3.ax1x.com/2021/01/23/s78SN8.png", // 沙尘 SAND + WIND: "https://s3.ax1x.com/2021/01/23/s78icj.jpg", // 大风 WIND + }, + // 天气对应的背景->2 + weatherBgTwoUrls: { + CLEAR_DAY: "https://s3.ax1x.com/2021/01/23/s74MGT.png", // 晴(白天) CLEAR_DAY + CLEAR_NIGHT: "https://s3.ax1x.com/2021/01/23/s74maq.png", // 晴(夜间) CLEAR_NIGHT + PARTLY_CLOUDY_DAY: "https://s3.ax1x.com/2021/01/23/s74nI0.png", // 多云(白天) PARTLY_CLOUDY_DAY + PARTLY_CLOUDY_NIGHT: "https://s3.ax1x.com/2021/01/23/s74KiV.png", // 多云(夜间) PARTLY_CLOUDY_NIGHT + CLOUDY: "https://s3.ax1x.com/2021/01/23/s74QRU.png", // 阴(白天) CLOUDY + CLOUDY_NIGHT: "https://s3.ax1x.com/2021/01/23/s74KiV.png", // 阴(夜间) CLOUDY + LIGHT_HAZE: "https://s3.ax1x.com/2021/01/23/s74eZn.jpg", // 轻度雾霾 LIGHT_HAZE + LIGHT_HAZE_NIGHT: "https://s3.ax1x.com/2021/01/23/s74KiV.png", // 轻度雾霾 LIGHT_HAZE + MODERATE_HAZE: "https://s3.ax1x.com/2021/01/23/s74eZn.jpg", // 中度雾霾 MODERATE_HAZE + MODERATE_HAZE_NIGHT: "https://s3.ax1x.com/2021/01/23/s74KiV.png", // 中度雾霾 MODERATE_HAZE + HEAVY_HAZE: "https://s3.ax1x.com/2021/01/23/s74eZn.jpg", // 重度雾霾 HEAVY_HAZE + HEAVY_HAZE_NIGHT: "https://s3.ax1x.com/2021/01/23/s74KiV.png", // 重度雾霾 HEAVY_HAZE + LIGHT_RAIN: "https://s3.ax1x.com/2021/01/23/s74lzF.jpg", // 小雨 LIGHT_RAIN + MODERATE_RAIN: "https://s3.ax1x.com/2021/01/23/s74lzF.jpg", // 中雨 MODERATE_RAIN + HEAVY_RAIN: "https://s3.ax1x.com/2021/01/23/s74lzF.jpg", // 大雨 HEAVY_RAIN + STORM_RAIN: "https://s3.ax1x.com/2021/01/23/s74lzF.jpg", // 暴雨 STORM_RAIN + FOG: "https://s3.ax1x.com/2021/01/23/s74eZn.jpg", // 雾 FOG + LIGHT_SNOW: "https://s3.ax1x.com/2021/01/23/s748sJ.jpg", // 小雪 LIGHT_SNOW + MODERATE_SNOW: "https://s3.ax1x.com/2021/01/23/s748sJ.jpg", // 中雪 MODERATE_SNOW + HEAVY_SNOW: "https://s3.ax1x.com/2021/01/23/s748sJ.jpg", // 大雪 HEAVY_SNOW + STORM_SNOW: "https://s3.ax1x.com/2021/01/23/s748sJ.jpg", // 暴雪 STORM_SNOW + DUST: "https://s3.ax1x.com/2021/01/23/s74eZn.jpg", // 浮尘 DUST + SAND: "https://s3.ax1x.com/2021/01/23/s74eZn.jpg", // 沙尘 SAND + WIND: "https://s3.ax1x.com/2021/01/23/s743M4.jpg", // 大风 WIND + }, + // 天气对应的背景->3 + weatherBgThreeUrls: { + CLEAR_DAY: "https://s3.ax1x.com/2021/01/23/s75PT1.png", // 晴(白天) CLEAR_DAY + CLEAR_NIGHT: "https://s3.ax1x.com/2021/01/23/s75PT1.png", // 晴(夜间) CLEAR_NIGHT + PARTLY_CLOUDY_DAY: "https://s3.ax1x.com/2021/01/23/s75VSO.png", // 多云(白天) PARTLY_CLOUDY_DAY + PARTLY_CLOUDY_NIGHT: "https://s3.ax1x.com/2021/01/23/s75VSO.png", // 多云(夜间) PARTLY_CLOUDY_NIGHT + CLOUDY: "https://s3.ax1x.com/2021/01/23/s75FFx.png", // 阴(白天) CLOUDY + CLOUDY_NIGHT: "https://s3.ax1x.com/2021/01/23/s75FFx.png", // 阴(夜间) CLOUDY + LIGHT_HAZE: "https://s3.ax1x.com/2021/01/23/s75kY6.png", // 轻度雾霾 LIGHT_HAZE + LIGHT_HAZE_NIGHT: "https://s3.ax1x.com/2021/01/23/s75kY6.png", // 轻度雾霾 LIGHT_HAZE + MODERATE_HAZE: "https://s3.ax1x.com/2021/01/23/s75kY6.png", // 中度雾霾 MODERATE_HAZE + MODERATE_HAZE_NIGHT: "https://s3.ax1x.com/2021/01/23/s75kY6.png", // 中度雾霾 MODERATE_HAZE + HEAVY_HAZE: "https://s3.ax1x.com/2021/01/23/s75kY6.png", // 重度雾霾 HEAVY_HAZE + HEAVY_HAZE_NIGHT: "https://s3.ax1x.com/2021/01/23/s75kY6.png", // 重度雾霾 HEAVY_HAZE + LIGHT_RAIN: "https://s3.ax1x.com/2021/01/23/s75AfK.png", // 小雨 LIGHT_RAIN + MODERATE_RAIN: "https://s3.ax1x.com/2021/01/23/s75AfK.png", // 中雨 MODERATE_RAIN + HEAVY_RAIN: "https://s3.ax1x.com/2021/01/23/s75AfK.png", // 大雨 HEAVY_RAIN + STORM_RAIN: "https://s3.ax1x.com/2021/01/23/s75AfK.png", // 暴雨 STORM_RAIN + FOG: "https://s3.ax1x.com/2021/01/23/s75kY6.png", // 雾 FOG + LIGHT_SNOW: "https://s3.ax1x.com/2021/01/23/s75e6e.png", // 小雪 LIGHT_SNOW + MODERATE_SNOW: "https://s3.ax1x.com/2021/01/23/s75e6e.png", // 中雪 MODERATE_SNOW + HEAVY_SNOW: "https://s3.ax1x.com/2021/01/23/s75e6e.png", // 大雪 HEAVY_SNOW + STORM_SNOW: "https://s3.ax1x.com/2021/01/23/s75e6e.png", // 暴雪 STORM_SNOW + DUST: "https://s3.ax1x.com/2021/01/23/s75kY6.png", // 浮尘 DUST + SAND: "https://s3.ax1x.com/2021/01/23/s75kY6.png", // 沙尘 SAND + WIND: "https://s3.ax1x.com/2021/01/23/s75ZlD.png", // 大风 WIND + }, + // 天气对应的背景->4 + weatherBgFourUrls: { + CLEAR_DAY: "https://s3.ax1x.com/2021/01/23/s7Iy5t.jpg", // 晴(白天) CLEAR_DAY + CLEAR_NIGHT: "https://s3.ax1x.com/2021/01/23/s7I0DH.jpg", // 晴(夜间) CLEAR_NIGHT + PARTLY_CLOUDY_DAY: "https://s3.ax1x.com/2021/01/23/s7IBbd.jpg", // 多云(白天) PARTLY_CLOUDY_DAY + PARTLY_CLOUDY_NIGHT: "https://s3.ax1x.com/2021/01/23/s7IsUI.jpg", // 多云(夜间) PARTLY_CLOUDY_NIGHT + CLOUDY: "https://s3.ax1x.com/2021/01/23/s7IBbd.jpg", // 阴(白天) CLOUDY + CLOUDY_NIGHT: "https://s3.ax1x.com/2021/01/23/s7IsUI.jpg", // 阴(夜间) CLOUDY + LIGHT_HAZE: "https://s3.ax1x.com/2021/01/23/s7IwKe.jpg", // 轻度雾霾 LIGHT_HAZE + LIGHT_HAZE_NIGHT: "https://s3.ax1x.com/2021/01/23/s7IwKe.jpg", // 轻度雾霾 LIGHT_HAZE + MODERATE_HAZE: "https://s3.ax1x.com/2021/01/23/s7IwKe.jpg", // 中度雾霾 MODERATE_HAZE + MODERATE_HAZE_NIGHT: "https://s3.ax1x.com/2021/01/23/s7IwKe.jpg", // 中度雾霾 MODERATE_HAZE + HEAVY_HAZE: "https://s3.ax1x.com/2021/01/23/s7IwKe.jpg", // 重度雾霾 HEAVY_HAZE + HEAVY_HAZE_NIGHT: "https://s3.ax1x.com/2021/01/23/s7IwKe.jpg", // 重度雾霾 HEAVY_HAZE + LIGHT_RAIN: "https://s3.ax1x.com/2021/01/23/s7IcPP.jpg", // 小雨 LIGHT_RAIN + MODERATE_RAIN: "https://s3.ax1x.com/2021/01/23/s7IcPP.jpg", // 中雨 MODERATE_RAIN + HEAVY_RAIN: "https://s3.ax1x.com/2021/01/23/s7IcPP.jpg", // 大雨 HEAVY_RAIN + STORM_RAIN: "https://s3.ax1x.com/2021/01/23/s7IcPP.jpg", // 暴雨 STORM_RAIN + FOG: "https://s3.ax1x.com/2021/01/23/s7IwKe.jpg", // 雾 FOG + LIGHT_SNOW: "https://s3.ax1x.com/2021/01/23/s748sJ.jpg", // 小雪 LIGHT_SNOW + MODERATE_SNOW: "https://s3.ax1x.com/2021/01/23/s748sJ.jpg", // 中雪 MODERATE_SNOW + HEAVY_SNOW: "https://s3.ax1x.com/2021/01/23/s748sJ.jpg", // 大雪 HEAVY_SNOW + STORM_SNOW: "https://s3.ax1x.com/2021/01/23/s748sJ.jpg", // 暴雪 STORM_SNOW + DUST: "https://s3.ax1x.com/2021/01/23/s7IwKe.jpg", // 浮尘 DUST + SAND: "https://s3.ax1x.com/2021/01/23/s7IwKe.jpg", // 沙尘 SAND + WIND: "https://s3.ax1x.com/2021/01/23/s743M4.jpg", // 大风 WIND + }, + // 天气对应的背景->5 + weatherBgFiveUrls: { + CLEAR_DAY: "https://s3.ax1x.com/2021/01/23/s7o5QO.png", // 晴(白天) CLEAR_DAY + CLEAR_NIGHT: "https://s3.ax1x.com/2021/01/23/s7ofW6.png", // 晴(夜间) CLEAR_NIGHT + PARTLY_CLOUDY_DAY: "https://s3.ax1x.com/2021/01/23/s7oIyD.png", // 多云(白天) PARTLY_CLOUDY_DAY + PARTLY_CLOUDY_NIGHT: "https://s3.ax1x.com/2021/01/23/s7oIyD.png", // 多云(夜间) PARTLY_CLOUDY_NIGHT + CLOUDY: "https://s3.ax1x.com/2021/01/23/s7oIyD.png", // 阴(白天) CLOUDY + CLOUDY_NIGHT: "https://s3.ax1x.com/2021/01/23/s7oIyD.png", // 阴(夜间) CLOUDY + LIGHT_HAZE: "https://s3.ax1x.com/2021/01/23/s7o4SK.png", // 轻度雾霾 LIGHT_HAZE + LIGHT_HAZE_NIGHT: "https://s3.ax1x.com/2021/01/23/s7o4SK.png", // 轻度雾霾 LIGHT_HAZE + MODERATE_HAZE: "https://s3.ax1x.com/2021/01/23/s7o4SK.png", // 中度雾霾 MODERATE_HAZE + MODERATE_HAZE_NIGHT: "https://s3.ax1x.com/2021/01/23/s7o4SK.png", // 中度雾霾 MODERATE_HAZE + HEAVY_HAZE: "https://s3.ax1x.com/2021/01/23/s7o4SK.png", // 重度雾霾 HEAVY_HAZE + HEAVY_HAZE_NIGHT: "https://s3.ax1x.com/2021/01/23/s7o4SK.png", // 重度雾霾 HEAVY_HAZE + LIGHT_RAIN: "https://s3.ax1x.com/2021/01/23/s7oHwd.png", // 小雨 LIGHT_RAIN + MODERATE_RAIN: "https://s3.ax1x.com/2021/01/23/s7oHwd.png", // 中雨 MODERATE_RAIN + HEAVY_RAIN: "https://s3.ax1x.com/2021/01/23/s7oHwd.png", // 大雨 HEAVY_RAIN + STORM_RAIN: "https://s3.ax1x.com/2021/01/23/s7oHwd.png", // 暴雨 STORM_RAIN + FOG: "https://s3.ax1x.com/2021/01/23/s7ooOe.png", // 雾 FOG + LIGHT_SNOW: "https://s3.ax1x.com/2021/01/23/s7obTA.png", // 小雪 LIGHT_SNOW + MODERATE_SNOW: "https://s3.ax1x.com/2021/01/23/s7obTA.png", // 中雪 MODERATE_SNOW + HEAVY_SNOW: "https://s3.ax1x.com/2021/01/23/s7obTA.png", // 大雪 HEAVY_SNOW + STORM_SNOW: "https://s3.ax1x.com/2021/01/23/s7obTA.png", // 暴雪 STORM_SNOW + DUST: "https://s3.ax1x.com/2021/01/23/s7o4SK.png", // 浮尘 DUST + SAND: "https://s3.ax1x.com/2021/01/23/s7o4SK.png", // 沙尘 SAND + WIND: "https://s3.ax1x.com/2021/01/23/s7ooOe.png", // 大风 WIND + }, + // 天气对应的背景->6 + weatherBgSixUrls: { + CLEAR_DAY: "https://s3.ax1x.com/2021/01/23/s7xrZV.jpg", // 晴(白天) CLEAR_DAY + CLEAR_NIGHT: "https://s3.ax1x.com/2021/01/23/s7xsaT.jpg", // 晴(夜间) CLEAR_NIGHT + PARTLY_CLOUDY_DAY: "https://s3.ax1x.com/2021/01/23/s7xyIU.jpg", // 多云(白天) PARTLY_CLOUDY_DAY + PARTLY_CLOUDY_NIGHT: "https://s3.ax1x.com/2021/01/23/s7xciF.jpg", // 多云(夜间) PARTLY_CLOUDY_NIGHT + CLOUDY: "https://s3.ax1x.com/2021/01/23/s7xyIU.jpg", // 阴(白天) CLOUDY + CLOUDY_NIGHT: "https://s3.ax1x.com/2021/01/23/s7xciF.jpg", // 阴(夜间) CLOUDY + LIGHT_HAZE: "https://s3.ax1x.com/2021/01/23/s7xgG4.jpg", // 轻度雾霾 LIGHT_HAZE + LIGHT_HAZE_NIGHT: "https://s3.ax1x.com/2021/01/23/s7xgG4.jpg", // 轻度雾霾 LIGHT_HAZE + MODERATE_HAZE: "https://s3.ax1x.com/2021/01/23/s7xgG4.jpg", // 中度雾霾 MODERATE_HAZE + MODERATE_HAZE_NIGHT: "https://s3.ax1x.com/2021/01/23/s7xgG4.jpg", // 中度雾霾 MODERATE_HAZE + HEAVY_HAZE: "https://s3.ax1x.com/2021/01/23/s7xgG4.jpg", // 重度雾霾 HEAVY_HAZE + HEAVY_HAZE_NIGHT: "https://s3.ax1x.com/2021/01/23/s7xgG4.jpg", // 重度雾霾 HEAVY_HAZE + LIGHT_RAIN: "https://s3.ax1x.com/2021/01/23/s7x2RJ.jpg", // 小雨 LIGHT_RAIN + MODERATE_RAIN: "https://s3.ax1x.com/2021/01/23/s7x2RJ.jpg", // 中雨 MODERATE_RAIN + HEAVY_RAIN: "https://s3.ax1x.com/2021/01/23/s7x2RJ.jpg", // 大雨 HEAVY_RAIN + STORM_RAIN: "https://s3.ax1x.com/2021/01/23/s7x2RJ.jpg", // 暴雨 STORM_RAIN + FOG: "https://s3.ax1x.com/2021/01/23/s7xBq0.jpg", // 雾 FOG + LIGHT_SNOW: "https://s3.ax1x.com/2021/01/23/s7xRz9.jpg", // 小雪 LIGHT_SNOW + MODERATE_SNOW: "https://s3.ax1x.com/2021/01/23/s7xRz9.jpg", // 中雪 MODERATE_SNOW + HEAVY_SNOW: "https://s3.ax1x.com/2021/01/23/s7xRz9.jpg", // 大雪 HEAVY_SNOW + STORM_SNOW: "https://s3.ax1x.com/2021/01/23/s7xRz9.jpg", // 暴雪 STORM_SNOW + DUST: "https://s3.ax1x.com/2021/01/23/s7xgG4.jpg", // 浮尘 DUST + SAND: "https://s3.ax1x.com/2021/01/23/s7xgG4.jpg", // 沙尘 SAND + WIND: "https://s3.ax1x.com/2021/01/23/s7xfMR.jpg", // 大风 WIND + }, + //********************************************************************** +} + + +// @定义小组件 +class Widget extends Base { + constructor(scriptName) { + super(scriptName) + // 初始化其他变量 + this.setSelectPicBg(widgetConfigs.selectPicBg) + this.setColorBgMode(widgetConfigs.colorBgMode, widgetConfigs.bgColor) + this.paddingSetting(Object.assign(widgetConfigs.padding)) + this.refreshIntervalTime(widgetConfigs.refreshInterval) + this.setPreViewSizeMode(widgetConfigs.previewMode) + } + + /** + * 获取彩云天气信息 + */ + async getWeather(dailysteps = 7) { + // 获取位置 + let location = widgetConfigs.location + if (!widgetConfigs.lockLocation) { + location = await this.getLocation(widgetConfigs.locale) + widgetConfigs.location = location + } + // 小时 + const hour = new Date().getHours() + + // 彩云天气域名 + const url = `https://api.caiyunapp.com/v2.5/${widgetConfigs.apiKey}/${location.longitude},${location.latitude}/weather.json?alert=true&dailysteps=${dailysteps}` + const weatherJsonData = await this.httpGet(url, true, null, 'weatherMultiInfo') + + // 天气数据 + let weatherInfo = {} + if (weatherJsonData.status == "ok") { + log("天气数据请求成功") + + // 天气突发预警 + let alertWeather = weatherJsonData.result.alert.content + if (alertWeather.length > 0) { + const alertWeatherTitle = alertWeather[0].title + log(`突发的天气预警==>${alertWeatherTitle}`) + weatherInfo.alertWeatherTitle = alertWeatherTitle + } + + // 全部温度 + weatherInfo.daily = weatherJsonData.result.daily + // 温度范围 + const temperatureData = weatherInfo.daily.temperature[0] + // 最低温度 + const minTemperature = temperatureData.min + // 最高温度 + const maxTemperature = temperatureData.max + weatherInfo.minTemperature = Math.round(minTemperature) + weatherInfo.maxTemperature = Math.round(maxTemperature) + + // 体感温度 + const bodyFeelingTemperature = weatherJsonData.result.realtime.apparent_temperature + weatherInfo.bodyFeelingTemperature = Math.floor(bodyFeelingTemperature) + + // 显示温度 + const temperature = weatherJsonData.result.realtime.temperature + weatherInfo.temperature = Math.floor(temperature) + + // 天气状况 weatherIcos[weatherIco] + let weather = weatherJsonData.result.realtime.skycon + let night = hour - 12 >= 7 + let nightCloudy = night && weather == "CLOUDY" + let nightLightHaze = night && weather == "LIGHT_HAZE" + let nightModerateHaze = night && weather == "MODERATE_HAZE" + let nightHeavyHaze = night && weather == "HEAVY_HAZE" + if (nightCloudy) { + weather = "CLOUDY_NIGHT" + } + if (nightLightHaze) { + weather = "LIGHT_HAZE_NIGHT" + } + if (nightModerateHaze) { + weather = "MODERATE_HAZE_NIGHT" + } + if (nightHeavyHaze) { + weather = "HEAVY_HAZE_NIGHT" + } + weatherInfo.weatherIco = weather + log(`天气:${weather}`) + + // 天气描述 + const weatherDesc = weatherJsonData.result.forecast_keypoint + weatherInfo.weatherDesc = weatherDesc.replace("。还在加班么?", ",") + log("天气预告==>" + weatherDesc) + + // 降水率 + weatherInfo.probability = weatherJsonData.result.minutely.probability + + // 相对湿度 + const humidity = (Math.floor(weatherJsonData.result.realtime.humidity * 100)) + "%" + weatherInfo.humidity = humidity + + // 舒适指数 + const comfort = weatherJsonData.result.realtime.life_index.comfort.desc + weatherInfo.comfort = comfort + log(`舒适指数:${comfort}`) + + // 紫外线指数 + const ultraviolet = weatherJsonData.result.realtime.life_index.ultraviolet.desc + weatherInfo.ultraviolet = ultraviolet + + // 空气质量 + const aqi = weatherJsonData.result.realtime.air_quality.aqi.chn + const aqiInfo = this.airQuality(aqi) + weatherInfo.aqiInfo = aqiInfo + + // 日出日落 + const astro = weatherJsonData.result.daily.astro[0] + // 日出 + const sunrise = astro.sunrise.time + // 日落 + const sunset = astro.sunset.time + weatherInfo.sunrise = sunrise.toString() + weatherInfo.sunset = sunset.toString() + + // 小时预告 + let hourlyArr = [] + const hourlyData = weatherJsonData.result.hourly + const temperatureArr = hourlyData.temperature + const temperatureSkyconArr = hourlyData.skycon + for (var i = 0; i < temperatureArr.length; i++) { + let hourlyObj = {} + hourlyObj.datetime = temperatureArr[i].datetime + hourlyObj.temperature = Math.round(temperatureArr[i].value) + + let weather = temperatureSkyconArr[i].value + if (nightCloudy) { + weather = "CLOUDY_NIGHT" + } + hourlyObj.skycon = `${weather}` + hourlyArr.push(hourlyObj) + } + weatherInfo.hourly = hourlyArr + } else { + log(`请求彩云天气出错:${weatherJsonData.status}`) + } + + return weatherInfo + } + + + /** + * 空气指标质量 + * @param {number} levelNum 控制aiq + */ + airQuality(levelNum) { + // 0-50 优,51-100 良,101-150 轻度污染,151-200 中度污染 + // 201-300 重度污染,>300 严重污染 + if (levelNum >= 0 && levelNum <= 50) { + return "优秀" + } else if (levelNum >= 51 && levelNum <= 100) { + return "良好" + } else if (levelNum >= 101 && levelNum <= 150) { + return "轻度" + } else if (levelNum >= 151 && levelNum <= 200) { + return "中度" + } else if (levelNum >= 201 && levelNum <= 300) { + return "重度" + } else { + return "严重" + } + } + + /** + * 获取农历信息 + */ + async getLunar() { + const day = new Date().getDate() - 1 + // 万年历数据 + const url = "https://wannianrili.51240.com/" + const defaultHeaders = { + "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.67 Safari/537.36" + } + const html = await this.httpGet(url, false, defaultHeaders) + let webview = new WebView() + await webview.loadHTML(html) + var getData = ` +function getData() { +try { +infoLunarText = document.querySelector('div#wnrl_k_you_id_${day}.wnrl_k_you .wnrl_k_you_id_wnrl_nongli').innerText +holidayText = document.querySelectorAll('div.wnrl_k_zuo div.wnrl_riqi')[${day}].querySelector('.wnrl_td_bzl').innerText +if(infoLunarText.search(holidayText) != -1) { +holidayText = '' +} +} catch { +holidayText = '' +} +return {infoLunarText: infoLunarText, holidayText: holidayText} +} + +getData() +` + + // 节日数据 + const response = await webview.evaluateJavaScript(getData, false) + console.log(`农历输出:${JSON.stringify(response)}`); + + return response + } + + /** + * 筛选日程 + * @param {CalendarEvent} schedule 日程 + * @return 返回符合条件的日程 + */ + shouldShowSchedule(schedule) { + const currentDate = new Date() + // 被取消的日程不用显示 + if (schedule.title.startsWith("Canceled:")) { return false } + // 与当前时间做比较 + let timeInterval = schedule.endDate.getTime() > currentDate.getTime() + // 返回全天跟还没过去的 + return timeInterval && !schedule.isAllDay + } + + /** + * 获取手机日程 + */ + async getSchedules() { + let showSchedules = [] + const todaySchedules = await CalendarEvent.today([]) + for (const schedule of todaySchedules) { + if (this.shouldShowSchedule(schedule)) { + // 日程 + let scheduleObj = {} + // 开始时间 + const startDate = schedule.startDate + // 年 + const startYear = startDate.getFullYear() + // 月 + const month = startDate.getMonth() + 1 + // 日 + const day = startDate.getDate() + // 开始小时 + const startHour = ("0" + startDate.getHours()).slice(-2) + // 开始分钟 + const startMinute = ("0" + startDate.getMinutes()).slice(-2) + + // 结束时间 + const endDate = schedule.endDate + // 结束小时 + const endHour = ("0" + endDate.getHours()).slice(-2) + // 结束分钟 + const endMinute = ("0" + endDate.getMinutes()).slice(-2) + + // 时间安排展示 + let timeText = month + "月" + day + "日 " + startHour + ":" + startMinute + "~" + endHour + ":" + endMinute + if (schedule.isAllDay) { + timeText = "全天" + } + + // 构造格式后的日程 + scheduleObj.title = schedule.title + scheduleObj.timeText = timeText + log(`>>日程:${scheduleObj.title} ==> ${timeText}`) + showSchedules.push(scheduleObj) + } + } + + return showSchedules + } + + /** + * 下载更新 + */ + async downloadUpdate() { + let files = FileManager.local() + const iCloudInUse = files.isFileStoredIniCloud(module.filename) + files = iCloudInUse ? FileManager.iCloud() : files + let message = '' + try { + let downloadURL = "https://mashangkaifa.coding.net/p/coding-code-guide/d/Scriptable/git/raw/master/material_weather.js" + if(widgetConfigs.useGithub) { + downloadURL = "https://raw.githubusercontent.com/Enjoyee/Scriptable/main/%E6%96%B0%E7%B3%BB%E5%88%97/material_weather.js" + } + const req = new Request(downloadURL) + const codeString = await req.loadString() + files.writeString(module.filename, codeString) + message = "天气脚本已更新,请退出脚本重新进入运行生效。" + } catch { + message = "更新失败,请稍后再试。" + } + const options = ["好的"] + await this.generateAlert(message, options) + Script.complete() + } + + /** + * 获取天气背景图 + */ + weatherBgUrls() { + let weatherBgUrls = widgetConfigs.weatherBgOneUrls + const widgetUIBg = widgetConfigs.widgetUIBg + if (widgetUIBg == 2) { + weatherBgUrls = widgetConfigs.weatherBgTwoUrls + } else if (widgetUIBg == 3) { + weatherBgUrls = widgetConfigs.weatherBgThreeUrls + } else if (widgetUIBg == 4) { + weatherBgUrls = widgetConfigs.weatherBgFourUrls + } else if (widgetUIBg == 5) { + weatherBgUrls = widgetConfigs.weatherBgFiveUrls + } else if (widgetUIBg == 6) { + weatherBgUrls = widgetConfigs.weatherBgSixUrls + } + return weatherBgUrls + } + + /** + * 获取天气icon + */ + weatherIcos() { + let weatherIcos = widgetConfigs.weatherOneIcos + const widgetUIIcon = widgetConfigs.widgetUIIcon + if (widgetUIIcon == 2) { + weatherIcos = widgetConfigs.weatherTwoIcos + } else if (widgetUIIcon == 3) { + weatherIcos = widgetConfigs.weatherThreeIcos + } else if (widgetUIIcon == 4) { + weatherIcos = widgetConfigs.weatherFourIcos + } else if (widgetUIIcon == 5) { + weatherIcos = widgetConfigs.weatherFiveIcos + } + return weatherIcos + } + + /** + * 组件样式1 + */ + async renderUIStyle1() { + //------------------------------------- + // 天气对应的背景 + let weatherBgUrls = this.weatherBgUrls() + // 天气对应的图标 + let weatherIcos = this.weatherIcos() + //------------------------------------- + const widget = new ListWidget() + widget.addSpacer(20) + const widgetWidth = this.getWidgetWidthSize('中号', widgetConfigs.isIphone12Mini) + //------------------------------------- + const currentDate = new Date() + // 获取天气信息 + const sizeCount = 6 + // 六天内天气 + const weatherInfo = await this.getWeather(sizeCount) + + // 当前信息 + const currentInfoStack = widget.addStack() + currentInfoStack.layoutHorizontally() + currentInfoStack.addSpacer(15) + // + const stackTopFont = Font.systemFont(10) + const temStack = currentInfoStack.addStack() + temStack.layoutVertically() + temStack.addSpacer(10) + // 定位图标 + let dividerDesc = '' + if (widgetConfigs.showLocation) { + // 天气 + const locationStack = temStack.addStack() + locationStack.centerAlignContent() + locationStack.addSpacer(3) + const locationImg = await this.getImageByUrl("https://s3.ax1x.com/2021/01/24/sH8Hk6.png") + const locationImgSpan = locationStack.addImage(locationImg) + locationImgSpan.imageSize = new Size(10, 10) + // 定位 + locationStack.addSpacer(7) + let textWidget = locationStack.addText(`${widgetConfigs.location.subLocality}`) + textWidget.textColor = Color.white() + textWidget.font = stackTopFont + } + // 天气文字 + dividerDesc = '' + if (widgetConfigs.showWeatherDesc) { + dividerDesc = ' • ' + textWidget = locationStack.addText(`${dividerDesc}${widgetConfigs.weatherDesc[weatherInfo.weatherIco]}`) + textWidget.textColor = Color.white() + textWidget.font = stackTopFont + } + // 农历 + dividerDesc = '' + if (widgetConfigs.showLunar) { + dividerDesc = ' • ' + const lunarInfo = await this.getLunar() + // 农历信息 + const infoLunarText = lunarInfo.infoLunarText + const holidayText = lunarInfo.holidayText + let dateFullText = `${infoLunarText}` + if (holidayText.length != 0) { + dateFullText = `${dateFullText} ⊙ ${holidayText}` + } + textWidget = locationStack.addText(`${dividerDesc}${dateFullText}`) + textWidget.textColor = Color.white() + textWidget.font = stackTopFont + } + dividerDesc = '' + if (widgetConfigs.showUpdateTime) { + dividerDesc = ' • ' + // 更新时间 + const updateText = `${this.getDateStr(new Date(), "HH:mm")} ⊹` + textWidget = locationStack.addText(`${dividerDesc}${updateText}`) + textWidget.textColor = Color.white() + textWidget.font = stackTopFont + } + locationStack.addSpacer() + // + temStack.addSpacer(15) + let image = await this.drawTextWithCustomFont(widgetConfigs.enFontUrl, `${weatherInfo.temperature}°c`, 40, "FFFFFF", "left") + let imgSpan = temStack.addImage(image) + imgSpan.imageSize = new Size(image.size.width / 2, image.size.height / 2) + imgSpan.leftAlignImage() + currentInfoStack.addSpacer() + //------ + const topRightStack = currentInfoStack.addStack() + topRightStack.layoutVertically() + topRightStack.addSpacer(20) + const previewSize = new Size(11, 11) + // + let stackWidth = 60 + const comfort = weatherInfo.comfort + if (comfort.length > 2) { + stackWidth = 67 + } + const singleSize = new Size(stackWidth, 0) + const comfortStack = topRightStack.addStack() + comfortStack.layoutHorizontally() + comfortStack.size = singleSize + let img = await this.getImageByUrl("https://s3.ax1x.com/2021/01/23/sHiv9K.png") + imgSpan = comfortStack.addImage(img) + imgSpan.imageSize = previewSize + comfortStack.addSpacer(5) + textWidget = comfortStack.addText(`${weatherInfo.comfort}`) + textWidget.textColor = Color.white() + textWidget.font = Font.mediumSystemFont(10) + comfortStack.addSpacer() + // ----- + topRightStack.addSpacer(5) + const aqStack = topRightStack.addStack() + aqStack.layoutHorizontally() + aqStack.size = singleSize + img = await this.getImageByUrl("https://s3.ax1x.com/2021/01/23/sHPrZR.png") + imgSpan = aqStack.addImage(img) + imgSpan.imageSize = previewSize + aqStack.addSpacer(6) + textWidget = aqStack.addText(`${weatherInfo.aqiInfo}`) + textWidget.textColor = Color.white() + textWidget.font = Font.mediumSystemFont(10) + aqStack.addSpacer() + // ----- + topRightStack.addSpacer(6) + const rainStack = topRightStack.addStack() + rainStack.layoutHorizontally() + rainStack.size = singleSize + img = await this.getImageByUrl("https://s3.ax1x.com/2021/01/23/sHic0s.png") + imgSpan = rainStack.addImage(img) + imgSpan.imageSize = previewSize + rainStack.addSpacer(8) + textWidget = rainStack.addText(`${Math.floor(weatherInfo.probability[0] * 100)}%`) + textWidget.textColor = Color.white() + textWidget.font = Font.mediumSystemFont(10) + rainStack.addSpacer() + topRightStack.addSpacer() + + // ======================================================== + // 未来天气信息 + widget.addSpacer(5) + const weatherInfoStack = widget.addStack() + weatherInfoStack.layoutHorizontally() + weatherInfoStack.size = new Size(widgetWidth, 0) + // 日温度 + const daily = weatherInfo.daily + // 日温度 + const temperatureArr = daily.temperature + const perSize = widgetWidth / sizeCount + for (let index = 0; index < temperatureArr.length; index++) { + let itemStack = weatherInfoStack.addStack() + itemStack.size = new Size(perSize, 0) + itemStack.setPadding(0, 0, 10, 0) + itemStack.layoutVertically() + itemStack.centerAlignContent() + + // 日期 + let dateStack = itemStack.addStack() + dateStack.layoutHorizontally() + dateStack.addSpacer() + const dailyTemperature = temperatureArr[index] + let dateText = dailyTemperature.date.slice(8, 10) + // 替换实时天气icon + let realtimeIcon = weatherInfo.weatherIco + if (dateText == currentDate.getDate()) { + dateText = `今天` + } else { + dateText = `${dateText}日` + realtimeIcon = daily.skycon[index].value + } + textWidget = dateStack.addText(dateText) + textWidget.textColor = Color.white() + textWidget.font = Font.systemFont(10) + dateStack.addSpacer() + itemStack.addSpacer(6) + + // 天气图标 + let weatherIco = this.getSFSymbol(widgetConfigs.weatherSFIcos[realtimeIcon]) + if (!widgetConfigs.useSF) { + weatherIco = await this.getImageByUrl(weatherIcos[realtimeIcon]) + } + let icoStack = itemStack.addStack() + icoStack.layoutHorizontally() + icoStack.addSpacer() + let imgStack = icoStack.addImage(weatherIco) + imgStack.imageSize = new Size(22, 22) + icoStack.addSpacer() + itemStack.addSpacer(6) + + // 温度区间 + let temperatureStack = itemStack.addStack() + temperatureStack.setPadding(0, 0, 0, 0) + temperatureStack.layoutHorizontally() + temperatureStack.addSpacer() + textWidget = temperatureStack.addText(`${Math.floor(dailyTemperature.min)}/${Math.floor(dailyTemperature.max)}°`) + textWidget.textColor = Color.white() + textWidget.font = Font.systemFont(11) + temperatureStack.addSpacer() + } + + //------------------------------------- + widget.addSpacer(15) + const selectPicBg = widgetConfigs.selectPicBg + this.setSelectPicBg(selectPicBg) + if (!selectPicBg) { + // 天气背景 + let bgImg = await this.getImageByUrl(weatherBgUrls[weatherInfo.weatherIco]) + bgImg = await this.loadShadowColor2Image(bgImg, new Color("000", 0.3)) + await this.saveImgCache(this.scriptName, bgImg) + } + return widget + } + + /** + * 组件样式2 + */ + async renderUIStyle2() { + //------------------------------------- + // 字体颜色 + const fontColorHex = "FFFFFF" + //------------------------------------- + // 天气对应的背景 + let weatherBgUrls = this.weatherBgUrls() + // 天气对应的图标 + let weatherIcos = this.weatherIcos() + //------------------------------------- + // 获取天气信息 + const sizeCount = 6 + // 六天内天气 + const weatherInfo = await this.getWeather(sizeCount) + // 获取农历信息 + const lunarInfo = await this.getLunar() + //------------------------------------- + const widget = new ListWidget() + //------------------------------------- + let fontUrl = "https://mashangkaifa.coding.net/p/coding-code-guide/d/coding-code-guide/git/raw/master/harmony-2.otf" + let image = await this.drawTextWithCustomFont(fontUrl, `${this.getDateStr(new Date(), "EEEE", "en")}`, 40, fontColorHex) + let imgSpan = widget.addImage(image) + imgSpan.imageSize = new Size(image.size.width / 2, image.size.height / 2) + imgSpan.centerAlignImage() + + // 日历信息 + widget.addSpacer(10) + let stack = widget.addStack() + stack.layoutHorizontally() + stack.centerAlignContent() + stack.addSpacer() + const infoLunarText = lunarInfo.infoLunarText + const holidayText = lunarInfo.holidayText + const dateFullText = `${infoLunarText}` + if (holidayText.length != 0) { + dateFullText = `${dateFullText} ⊙ ${holidayText}` + } + fontUrl = "https://mashangkaifa.coding.net/p/coding-code-guide/d/coding-code-guide/git/raw/master/jf-openhuninn-1.0.ttf" + let text = `${dateFullText}` + image = await this.drawTextWithCustomFont(fontUrl, `${text}`, 14, fontColorHex) + imgSpan = stack.addImage(image) + imgSpan.imageSize = new Size(image.size.width / 2, image.size.height / 2) + imgSpan.centerAlignImage() + // 当前日期 + const dateArr = [ + "January", + "February", + "March", + "April", + "May", + "June", + "July", + "August", + "September", + "October", + "November", + "December" + ] + const currentDate = new Date() + fontUrl = "https://mashangkaifa.coding.net/p/coding-code-guide/d/coding-code-guide/git/raw/master/quicksand_regular.ttf" + text = ` ⊙ ${currentDate.getDate()} ${dateArr[currentDate.getMonth()]}` + image = await this.drawTextWithCustomFont(fontUrl, `${text}`, 16, fontColorHex) + imgSpan = stack.addImage(image) + imgSpan.imageSize = new Size(image.size.width / 2, image.size.height / 2) + imgSpan.centerAlignImage() + // 电池信息 + if (holidayText.length == 0) { + const batteryLevel = Math.floor(Device.batteryLevel() * 100) + text = ` ⊙ ${batteryLevel}%` + image = await this.drawTextWithCustomFont(fontUrl, `${text}`, 15, fontColorHex) + imgSpan = stack.addImage(image) + imgSpan.imageSize = new Size(image.size.width / 2, image.size.height / 2) + imgSpan.centerAlignImage() + } + stack.addSpacer() + + // 当前天气 + //--------- + widget.addSpacer(5) + stack = widget.addStack() + stack.layoutHorizontally() + stack.centerAlignContent() + stack.addSpacer() + //--------- + let weatherIco = this.getSFSymbol(widgetConfigs.weatherSFIcos[weatherInfo.weatherIco]) + if (!widgetConfigs.useSF) { + weatherIco = await this.getImageByUrl(weatherIcos[weatherInfo.weatherIco]) + } + imgSpan = stack.addImage(weatherIco) + imgSpan.imageSize = new Size(23, 23) + imgSpan.centerAlignImage() + //--------- + stack.addSpacer(10) + text = `${widgetConfigs.weatherDesc[weatherInfo.weatherIco]} ${weatherInfo.temperature}°` + image = await this.drawTextWithCustomFont(fontUrl, `${text}`, 16, fontColorHex) + imgSpan = stack.addImage(image) + imgSpan.imageSize = new Size(image.size.width / 2, image.size.height / 2) + imgSpan.centerAlignImage() + //--------- + // 舒适指数 + stack.addSpacer(10) + image = await this.getImageByUrl("https://s3.ax1x.com/2021/01/23/sHPrZR.png") + imgSpan = stack.addImage(image) + imgSpan.tintColor = new Color(fontColorHex, 0.8) + imgSpan.imageSize = new Size(14, 14) + stack.addSpacer(6) + text = `${weatherInfo.aqiInfo}` + let textWidget = stack.addText(`${text}`) + textWidget.textColor = new Color(fontColorHex, 0.8) + textWidget.font = Font.lightSystemFont(13) + // 降雨率 + stack.addSpacer(10) + image = await this.getImageByUrl("https://s3.ax1x.com/2021/01/23/sHic0s.png") + imgSpan = stack.addImage(image) + imgSpan.tintColor = new Color(fontColorHex, 0.8) + imgSpan.imageSize = new Size(14, 14) + stack.addSpacer(6) + text = `${Math.floor(weatherInfo.probability[0] * 100)}%` + textWidget = stack.addText(`${text}`) + textWidget.textColor = new Color(fontColorHex, 0.8) + textWidget.font = Font.lightSystemFont(13) + //--------- + stack.addSpacer() + + // 天气预告 + //--------- + widget.addSpacer(7) + stack = widget.addStack() + stack.layoutHorizontally() + stack.centerAlignContent() + stack.addSpacer() + //--------- + text = `⊱ ${weatherInfo.weatherDesc} ⊰` + textWidget = stack.addText(`${text}`) + textWidget.textColor = new Color(fontColorHex, 0.8) + textWidget.font = Font.lightSystemFont(13) + stack.addSpacer() + + //------------------------------------- + const selectPicBg = widgetConfigs.selectPicBg + this.setSelectPicBg(selectPicBg) + if (!selectPicBg) { + // 天气背景 + let bgImg = await this.getImageByUrl(weatherBgUrls[weatherInfo.weatherIco]) + bgImg = await this.loadShadowColor2Image(bgImg, new Color("333", 0.25)) + await this.saveImgCache(this.scriptName, bgImg) + } + //------------------------------------- + return widget + } + + /** + * 组件渲染 + */ + async renderUI() { + if (widgetConfigs.widgetStyle == 1) { + return await this.renderUIStyle1() + } else if (widgetConfigs.widgetStyle == 2) { + return await this.renderUIStyle2() + } + } + + //------------------------------------- + /** + * @渲染小组件 + */ + async render() { + // 下载更新 + if (widgetConfigs.openDownload && config.runsInApp) { + const message = "同步天气远程脚本?" + const options = ["运行脚本", "下载脚本"] + let typeIndex = await this.generateAlert(message, options) + if (typeIndex == 1) { + await this.downloadUpdate() + } else { + return await this.renderUI() + } + } else { + return await this.renderUI() + } + } +} + +// @运行测试 +const { Running } = require("./lsp环境") +await Running(Widget, Script.name()) diff --git "a/\346\227\245\345\216\206-\344\270\255.js" "b/\346\227\245\345\216\206-\344\270\255.js" new file mode 100644 index 0000000..c3a3454 --- /dev/null +++ "b/\346\227\245\345\216\206-\344\270\255.js" @@ -0,0 +1,386 @@ +//------------------------------------------------ +const env = importModule('Env-lsp.js') +//------------------------------------------------ +// 配置区 +env.configs.previewSize = "Medium" // 预览大小【小:Small,中:Medium,大:Large】 +env.configs.changePicBg = false // 是否需要更换背景 +env.configs.colorMode = true // 是否是纯色背景 +env.configs.bgColor = new Color("ffffff") // 小组件背景色 +env.configs.topPadding = 0 // 内容区边距 +env.configs.leftPadding = 0 // 内容区边距 +env.configs.bottomPadding = 0 // 内容区边距 +env.configs.rightPadding = 0 // 内容区边距 +env.configs.refreshInterval = 0 // 刷新间隔,单位分钟,非精准,会有3-5分钟差距 +// +const imgStyle = env.imgStyle +const textStyle = env.textStyle +//------------------------------------------------ +// 脚本名字 +const name = Script.name() +//------------------------------------------------ + + +//↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓内容区↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ +//------------------------------------------------ + +// 周标题 +const weekTitle = ['🙄 周日', '😪 周一', '😩 周二', '🤨 周三', '🤓 周四', '🤩 周五', '🥳 周六'] + +// 日期文字大小 +const dayFont = Font.ultraLightMonospacedSystemFont(12) +// 日期文字颜色 +const dayColor = new Color('#000') +// 今天日期文字颜色 +const currDayColor = new Color('#ff0000') +// 非本月日期文字颜色 +const nonDayColor = new Color('#000', 0) + +// 日期 +const thisDate = new Date() +// 年份 +const year = thisDate.getFullYear() +// 月份 +const month = thisDate.getMonth() + 1 +// 日期 +const currDay = thisDate.getDate() +// 格式化日期 +const yearMonthText = year + "-" + numFormatStr(month) + +// 上一个月的年份 +let preMonthYear +// 上个月份 +let preMonth +if (month == 1) { + preMonthYear = year - 1 + preMonth = 12 +} else { + preMonthYear = year + preMonth = month - 1 +} +// 上个月有多少天 +const preMonthDays = getDays(preMonthYear, preMonth) +// 当前月份有多少天 +const currMonthDays = getDays(year, month) +// 当前月份1号是星期几 +const currMonthFirstDay = getFirstDayWeek(year, month) +// 开始日期数字 +const startNum = preMonthDays - currMonthFirstDay + 1 +// 日历总数字 +var totalDays = currMonthDays + preMonthDays +// 总日期数字 +var totalNumArr = [] +for (var index = startNum; index <= totalDays; index++) { + totalNumArr.push(index) +} + + +////////////////////////////////////////////////////////// +// 创建列表 +let widget = new ListWidget() + // 内容排版 +let contentStack = widget.addStack() +contentStack.layoutHorizontally() +contentStack.addSpacer() + +// 左侧内容 +let leftStack = contentStack.addStack() +leftStack.layoutVertically() +leftStack.addSpacer() +// 日期 +let monthText = leftStack.addText(numFormatStr(month) + "月" + currDay + "日") +monthText.font = Font.systemFont(18) +monthText.textColor = new Color('#000') +monthText.leftAlignText() +// 星期几 +leftStack.addSpacer(8) +let currWeekDayText = leftStack.addText(getCurrDayWeekTitle() + " ☞☞") +currWeekDayText.font = Font.systemFont(14) +currWeekDayText.textColor = new Color('#ff0000') +currWeekDayText.leftAlignText() +// 农历信息 +leftStack.addSpacer(8) +let lunarInfo = await getLunar() +let infoLunarText = lunarInfo.data.lunar +let infoSolarText = lunarInfo.data.solar +infoLunarText = infoLunarText.substring(12, infoLunarText.length) +let constellationText = lunarInfo.data.constellation +let lunarText = leftStack.addText(infoLunarText) +lunarText.font = Font.systemFont(18) +lunarText.textColor = new Color('#000') +lunarText.leftAlignText() + +// 间隔 +leftStack.addSpacer() +contentStack.addSpacer() + +// 日期填充 +let dayColumnArr1 = [] +let dayColumnArr2 = [] +let dayColumnArr3 = [] +let dayColumnArr4 = [] +let dayColumnArr5 = [] +let dayColumnArr6 = [] +let dayColumnArr7 = [] + +// 日期行数 +var rowSize = Math.round(totalDays / 7) +for (var index = 0; index < totalDays; index=index+7) { + var size = index + dayColumnArr1.push(totalNumArr[size]) + + var size1 = size + 1 + if (size1 < totalDays) { + dayColumnArr2.push(totalNumArr[size1]) + } + + var size2 = size + 2 + if (size2 < totalDays) { + dayColumnArr3.push(totalNumArr[size2]) + } + + var size3 = size + 3 + if (size3 < totalDays) { + dayColumnArr4.push(totalNumArr[size3]) + } + + var size4 = size + 4 + if (size4 < totalDays) { + dayColumnArr5.push(totalNumArr[size4]) + } + + var size5 = size + 5 + if (size5 < totalDays) { + dayColumnArr6.push(totalNumArr[size5]) + } + + var size6 = size + 6 + if (size6 < totalDays) { + dayColumnArr7.push(totalNumArr[size6]) + } +} + +// 行间距 +const columnSpacer = 10 +// 列间距 +const rowSpacer = 8 +// 周日标题 +let weekColumn1 = contentStack.addStack() +weekColumn1.layoutVertically() +weekColumn1.addSpacer() +// 第一列日期 +for (var index = 0; index < dayColumnArr1.length; index++) { + let day = dayColumnArr1[index] + let color = dayColor + if (day > preMonthDays) { + day = day - preMonthDays + } else { + color = nonDayColor + } + createDayColumn(weekColumn1, day, dayFont, color, columnSpacer) +} +weekColumn1.addSpacer() +contentStack.addSpacer(rowSpacer) + +// 周一标题 +let weekColumn2 = contentStack.addStack() +weekColumn2.layoutVertically() +weekColumn2.addSpacer() +// 第二列日期 +for (var index = 0; index < dayColumnArr2.length; index++) { + let day = dayColumnArr2[index] + let color = dayColor + if (day > preMonthDays) { + day = day - preMonthDays + } else { + color = nonDayColor + } + createDayColumn(weekColumn2, day, dayFont, color, columnSpacer) +} +weekColumn2.addSpacer() +contentStack.addSpacer(rowSpacer) + +// 周二标题 +let weekColumn3 = contentStack.addStack() +weekColumn3.layoutVertically() +weekColumn3.addSpacer() +// 第三列日期 +for (var index = 0; index < dayColumnArr3.length; index++) { + let day = dayColumnArr3[index] + let color = dayColor + if (day > preMonthDays) { + day = day - preMonthDays + } else { + color = nonDayColor + } + createDayColumn(weekColumn3, day, dayFont, color, columnSpacer) +} +weekColumn3.addSpacer() +contentStack.addSpacer(rowSpacer) + +// 周三标题 +let weekColumn4 = contentStack.addStack() +weekColumn4.layoutVertically() +weekColumn4.addSpacer() +// 第四列日期 +for (var index = 0; index < dayColumnArr4.length; index++) { + let day = dayColumnArr4[index] + let color = dayColor + if (day > preMonthDays) { + day = day - preMonthDays + } else { + color = nonDayColor + } + createDayColumn(weekColumn4, day, dayFont, color, columnSpacer) +} +weekColumn4.addSpacer() +contentStack.addSpacer(rowSpacer) + +// 周四标题 +let weekColumn5 = contentStack.addStack() +weekColumn5.layoutVertically() +weekColumn5.addSpacer() +// 第五列日期 +for (var index = 0; index < dayColumnArr5.length; index++) { + let day = dayColumnArr5[index] + let color = dayColor + if (day > preMonthDays) { + day = day - preMonthDays + } else { + color = nonDayColor + } + createDayColumn(weekColumn5, day, dayFont, color, columnSpacer) +} +weekColumn5.addSpacer() +contentStack.addSpacer(rowSpacer) + +// 周五标题 +let weekColumn6 = contentStack.addStack() +weekColumn6.layoutVertically() +weekColumn6.addSpacer() +// 第六列日期 +for (var index = 0; index < dayColumnArr6.length; index++) { + let day = dayColumnArr6[index] + let color = dayColor + if (day > preMonthDays) { + day = day - preMonthDays + } else { + color = nonDayColor + } + createDayColumn(weekColumn6, day, dayFont, color, columnSpacer) +} +weekColumn6.addSpacer() +contentStack.addSpacer(rowSpacer) + +// 周六标题 +let weekColumn7 = contentStack.addStack() +weekColumn7.layoutVertically() +weekColumn7.addSpacer() +// 第七列日期 +for (var index = 0; index < dayColumnArr7.length; index++) { + let day = dayColumnArr7[index] + let color = dayColor + if (day > preMonthDays) { + day = day - preMonthDays + } else { + color = nonDayColor + } + createDayColumn(weekColumn7, day, dayFont, color, columnSpacer) +} +weekColumn7.addSpacer() +contentStack.addSpacer() + + +//================================================ +/* + * 创建行 + ================================================ + */ +function createDayColumn(stack, day, font, color, spacer) { + if (day == undefined) return + let dayText = stack.addText(day.toString()) + dayText.font = font + let textColor = color + if (day == currDay) { + textColor = currDayColor + } + dayText.textColor = textColor + dayText.shadowColor = textColor + dayText.shadowOffset = new Point(1,1) + dayText.shadowRadius = 1 + dayText.rightAlignText() + stack.addSpacer(spacer) +} + +/* + * 数字格式化 + ================================================ + */ +function numFormatStr(num) { + if (num > 0 && num < 10) { + return `0${num}` + } else { + return `${num}` + } +} + +/* + * 获取月份有多少天 + ================================================ + */ + function getDays(year, month) { + var date = new Date(year, month, 0) + return date.getDate() + } + +/* + * 获取指定月份的1号是星期几(0~6) + ================================================ + */ + function getFirstDayWeek(year, month) { + var date = new Date(year, month - 1) + return date.getDay() + } + +/* + * 获取今天是星期几 + ================================================ + */ + function getCurrDayWeekTitle() { + var date = new Date() + return weekTitle[date.getDay()] + } + +/* + * 在线获取农历信息 + ================================================ + */ +async function getLunar() { + const request = new Request("https://www.iamwawa.cn/home/nongli/ajax") + const defaultHeaders = { + "Accept": "*/*", + "Content-Type": "application/json" + } + + request.method = 'POST' + request.headers = defaultHeaders + + request.addParameterToMultipart("type", "solar") + request.addParameterToMultipart("year", year + "") + request.addParameterToMultipart("month", month + "") + request.addParameterToMultipart("day", currDay + "") + + const data = await request.loadJSON() + log(data) + + return data +} + + + +//------------------------------------------------ +//↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑内容区↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ + +//------------------------------------------------ +// 运行脚本、预览 +await env.run(name, widget) +//------------------------------------------------ \ No newline at end of file diff --git "a/\346\227\245\345\216\206\345\244\251\346\260\224.js" "b/\346\227\245\345\216\206-\345\244\251\346\260\224-\347\224\265\346\261\240.js" similarity index 56% rename from "\346\227\245\345\216\206\345\244\251\346\260\224.js" rename to "\346\227\245\345\216\206-\345\244\251\346\260\224-\347\224\265\346\261\240.js" index 0f8d38c..9726ab5 100644 --- "a/\346\227\245\345\216\206\345\244\251\346\260\224.js" +++ "b/\346\227\245\345\216\206-\345\244\251\346\260\224-\347\224\265\346\261\240.js" @@ -1,72 +1,48 @@ -/* - * Enjoyee - * https://github.com/Enjoyee/Scriptable - */ +//------------------------------------------------ +const env = importModule('Env-lsp.js') +//------------------------------------------------ +// 配置区 +env.configs.previewSize = "Medium" // 预览大小【小:Small,中:Medium,大:Large】 +env.configs.changePicBg = false // 是否需要更换背景 +env.configs.colorMode = true // 是否是纯色背景 +env.configs.bgColor = new Color("000000") // 小组件背景色 +env.configs.topPadding = 0 // 内容区边距 +env.configs.leftPadding = 0 // 内容区边距 +env.configs.bottomPadding = 0 // 内容区边距 +env.configs.rightPadding = 0 // 内容区边距 +env.configs.refreshInterval = 1 // 刷新间隔,单位分钟,非精准,会有3-5分钟差距 +// +const imgStyle = env.imgStyle +const textStyle = env.textStyle +//------------------------------------------------ +// 脚本名字 +const name = Script.name() +// 组件 +const widget = new ListWidget() +const contentStack = widget.addStack() +//------------------------------------------------ + + +//↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓内容区↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ +//------------------------------------------------ // 是否暗黑模式 -const darkMode = "false" -let widgetInputRAW = args.widgetParameter -try { - widgetInputRAW.toString() -} catch(e) { - // 默认值白色 - widgetInputRAW = darkMode -} -// 获取外部输入 -let inputArr = widgetInputRAW.toString() -if (inputArr.length == 0) { - inputArr = darkMode +const appearance = (await env.isUsingDarkAppearance()) ? 'dark' : 'light' +let darkMode = true +if (appearance == 'light') { + darkMode = false } - function isDarkMode() { - return inputArr == "true" + return darkMode } -const previewSize = "Medium" - // 小组件背景色 -let bgColor = new Color("e5e6e7") +env.configs.bgColor = new Color("e5e6e7") if (isDarkMode()) { - bgColor = new Color("151517") + env.configs.bgColor = new Color("151517") } -// 默认字体 -const defaultFont = Font.systemFont(18) -// 默认字体颜色 -const defaultTextColor = new Color("ffffff") - -// 内容区左右边距 -const padding = { - top: 0, - left: 0, - bottom: 0, - right: 0 -} - -// 标题样式定义 -let textStyle = { - stack: undefined, // 加入到哪个内容栈显示 - marginStart: 0, // 开始距离,水平方向的就是左边距离,垂直方向的就是顶部距离 - marginEnd: 0, // 结束距离,水平方向的就是右边距离,垂直方向的就是底部距离 - text: "", // 显示的文字 - width: 0, // 宽 - height: 0, // 长 - lineLimit: 0, // 行数控制,0是全部展示 - font: undefined, // 字体 - textColor: defaultTextColor, // 文字颜色 -} - -// 图片样式定义 -let imgStyle = { - stack: undefined, // 加入到哪个内容栈显示 - marginStart: 0, // 开始距离,水平方向的就是左边距离,垂直方向的就是顶部距离 - marginEnd: 0, // 结束距离,水平方向的就是右边距离,垂直方向的就是底部距离 - img: undefined, // 图片资源 - width: 0, // 宽 - height: 0, // 长 - tintColor: undefined, // 图片渲染颜色 -} //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// @@ -74,18 +50,6 @@ let imgStyle = { //////////////////////////////////////////////////////////////////////////////// - -////////////////////////////////////// -// 组件Start -const filename = `${Script.name()}.jpg` -const files = FileManager.local() -const path = files.joinPath(files.documentsDirectory(), filename) -const widget = new ListWidget() -const contentStack = widget.addStack() -////////////////////////////////////// - - - /* **************************************************************************** ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ @@ -99,17 +63,6 @@ const apiKey = "TAkhjf8d1nlSlspN" // 锁定地区,直接使用上述填写的地址信息不进行定位 const lockLocation = false -// 默认的定位信息,定位失败的时候默认读取 -// https://open.caiyunapp.com/File:Adcode-release-2020-06-10.xlsx.zip -// 上述链接查看对应地区的详细经纬度 -let locationData = { - "latitude": undefined, - "longitude": undefined, - "locality": undefined, - "subLocality": undefined -} -// - // 天气对应的icon const weatherIcos = { CLEAR_DAY: "http://worldweather.wmo.int/images/24a.png", // 晴(白天) CLEAR_DAY @@ -178,7 +131,7 @@ textStyle.stack = numStack textStyle.text = "TODAY" textStyle.font = Font.systemFont(10) textStyle.textColor = new Color("ff0000") -addStyleText() +env.addStyleText() // 日期 let numFontColor = new Color("000000") if (isDarkMode()) { @@ -188,7 +141,7 @@ textStyle.stack = numStack textStyle.text = `${date.getDate()}` textStyle.font = Font.systemFont(30) textStyle.textColor = numFontColor -addStyleText() +env.addStyleText() numStack.addSpacer() //////////////////// // 周几内容 @@ -205,11 +158,8 @@ textStyle.stack = weekMonthStack textStyle.text = `${weekString}` textStyle.font = Font.systemFont(10) textStyle.textColor = weekFontColor -addStyleText() -// 月份对齐 -for (let index = monthString.length; index < 9; index++) { - monthString = " " + monthString -} +env.addStyleText() +// 月份 weekMonthStack.addSpacer(4) textStyle.stack = weekMonthStack textStyle.text = `${monthString}` @@ -220,7 +170,7 @@ if (isDarkMode()) { monFontColor = new Color("ffffff", 0.6) } textStyle.textColor = monFontColor -addStyleText() +env.addStyleText() //////////////////////////// weekMonthStack.addSpacer() topStack.addSpacer(10) @@ -245,7 +195,7 @@ textStyle.stack = batteryInfoStack textStyle.text = "Battery" textStyle.font = Font.systemFont(10) textStyle.textColor = new Color("ffffff", 0.8) -addStyleText() +env.addStyleText() // 电池信息 const batteryLevel = Device.batteryLevel() const batteryAscii = `${Math.round(batteryLevel * 100)}%` @@ -253,7 +203,7 @@ textStyle.stack = batteryInfoStack textStyle.text = `${batteryAscii}` textStyle.font = Font.systemFont(18) textStyle.textColor = new Color("ffffff", 0.9) -addStyleText() +env.addStyleText() batteryInfoStack.addSpacer() ////////// batteryStack.addSpacer(30) @@ -272,7 +222,7 @@ imgStyle.img = batteryImg imgStyle.tintColor = new Color("ffffff") imgStyle.width = 30 imgStyle.height = 30 -addStyleImg() +env.addStyleImg() batteryImgStack.addSpacer() @@ -306,12 +256,12 @@ weatherInfoStack.centerAlignContent() imgStyle.stack = weatherInfoStack imgStyle.width = 25 imgStyle.height = 25 -let img = await getImage(weatherInfo.weather) +let img = await env.getImage(weatherInfo.weather) imgStyle.img = img if (date.getHours() - 12 > 6 && isDarkMode()) { imgStyle.tintColor = new Color("ffffff", 0.8) } -addStyleImg() +env.addStyleImg() // 天气预告信息 const weatherAlertInfo = weatherInfo.alertWeatherTitle let weatherDesc = weatherInfo.weatherDesc @@ -328,7 +278,7 @@ if (isDarkMode()) { } textStyle.textColor = weatherInfoFontColor textStyle.lineLimit = 1 -addStyleText() +env.addStyleText() weatherInfoStack.addSpacer(4) ////////////////////////// bottomStack.addSpacer(4) @@ -348,7 +298,7 @@ if (isDarkMode()) { sunriseTintColor = new Color("ffffff", 0.6) } imgStyle.tintColor = sunriseTintColor -addStyleImg() +env.addStyleImg() // otherWeatherStack.addSpacer(2) textStyle.stack = otherWeatherStack @@ -360,7 +310,7 @@ if (isDarkMode()) { } textStyle.textColor = sunriseFontColor textStyle.lineLimit = 1 -addStyleText() +env.addStyleText() // 日落ico otherWeatherStack.addSpacer(10) imgStyle.stack = otherWeatherStack @@ -373,7 +323,7 @@ if (isDarkMode()) { sunsetTintColor = new Color("ffffff", 0.6) } imgStyle.tintColor = sunsetTintColor -addStyleImg() +env.addStyleImg() // otherWeatherStack.addSpacer(2) textStyle.stack = otherWeatherStack @@ -385,21 +335,21 @@ if (isDarkMode()) { } textStyle.textColor = sunsetFontColor textStyle.lineLimit = 1 -addStyleText() +env.addStyleText() // 体感 otherWeatherStack.addSpacer(10) // 体感ico imgStyle.stack = otherWeatherStack imgStyle.width = 15 imgStyle.height = 15 -img = await getImage("http://worldweather.wmo.int/images/34.png") +img = await env.getImage("http://worldweather.wmo.int/images/34.png") imgStyle.img = img let feelingTintColor = new Color("000000", 0.6) if (isDarkMode()) { feelingTintColor = new Color("ffffff", 0.6) } imgStyle.tintColor = feelingTintColor -addStyleImg() +env.addStyleImg() // 体感温度内容 textStyle.stack = otherWeatherStack textStyle.text = `${weatherInfo.bodyFeelingTemperature}°C` @@ -410,12 +360,15 @@ if (isDarkMode()) { } textStyle.textColor = feelingFontColor textStyle.lineLimit = 1 -addStyleText() +env.addStyleText() // bottomStack.addSpacer() bottomContentStack.addSpacer() + + +//====================================================================== /* ************************************** * 获取彩云天气 @@ -427,7 +380,7 @@ async function getWeather() { log("定位信息:" + location.locality + "·" + location.subLocality) // 彩云天气域名 const DOMAIN = `https://api.caiyunapp.com/v2.5/${apiKey}/${location.longitude},${location.latitude}/weather.json?alert=true` - const weatherJsonData = await getJson(DOMAIN) + const weatherJsonData = await env.getJson(DOMAIN) if (weatherJsonData.status == "ok") { log("天气数据请求成功") // 天气突发预警 @@ -503,23 +456,7 @@ async function getWeather() { */ async function getLocation() { if (!lockLocation) { - try { - const location = await Location.current() - const geocode = await Location.reverseGeocode(location.latitude, location.longitude, "zh_cn") - locationData.latitude = location.latitude - locationData.longitude = location.longitude - const geo = geocode[0] - // 市 - locationData.locality = geo.locality - // 区 - locationData.subLocality = geo.subLocality - // 街道 - locationData.street = geo.thoroughfare - log("定位信息:latitude=" + location.latitude + ",longitude=" + location.longitude + ",locality=" - + locationData.locality + ",subLocality=" + locationData.subLocality + ",street=" + locationData.street) - } catch (e) { - log("定位出错了," + e.toString()) - } + locationData = await env.getLocation() } return locationData @@ -548,266 +485,11 @@ function airQuality(levelNum) { } } -/* -**************************************************************************** -上面添加你自己的组件内容/逻辑 -↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ -**************************************************************************** -*/ - - -////////////////////////////////////// -// 组件End -// 设置小组件的背景 -widget.backgroundColor = bgColor -// 设置边距(上,左,下,右) -widget.setPadding(padding.top, padding.left, padding.bottom, padding.right) -// 设置组件 -Script.setWidget(widget) -// 完成脚本 -Script.complete() -// 预览 -widget.presentMedium() -////////////////////////////////////// - -/* -**************************************************************************** -* 重置文本样式 -**************************************************************************** -*/ -function resetTextStyle() { - textStyle.stack = undefined // 加入到哪个内容栈显示 - textStyle.marginStart = 0 - textStyle.marginEnd = 0 - textStyle.text = "" // 显示的文字 - textStyle.width = 0 // 宽 - textStyle.height = 0 // 长 - textStyle.lineLimit = 0 // 行数控制,0是全部展示 - textStyle.font = undefined // 字体 - textStyle.textColor = defaultTextColor // 文字颜色 -} - -/* -**************************************************************************** -* 重置图片样式 -**************************************************************************** -*/ -function resetImgStyle() { - imgStyle.stack = undefined // 加入到哪个内容栈显示 - textStyle.marginStart = 0 - textStyle.marginEnd = 0 - imgStyle.img = undefined // 图片资源 - imgStyle.width = 0 // 宽 - imgStyle.height = 0 // 长 - imgStyle.tintColor = undefined // 图片渲染颜色 -} - -/* -**************************************************************************** -* 添加一行文本数据进行显示 -**************************************************************************** -*/ -function addStyleText() { - const contentStack = textStyle.stack - if (contentStack == undefined) { - return - } - - const marginStart = textStyle.marginStart - if (marginStart != undefined && marginStart != 0) { - contentStack.addSpacer(marginStart) - } - - const textSpan = contentStack.addText(`${textStyle.text}`) - contentStack.size = new Size(textStyle.width, textStyle.height) - textSpan.lineLimit = textStyle.lineLimit - textSpan.font = textStyle.font - textSpan.textColor = textStyle.textColor - - const marginEnd = textStyle.marginEnd - if (marginStart != undefined && marginStart != 0) { - contentStack.addSpacer(marginEnd) - } - - // 重置样式 - resetTextStyle() -} - -/* -**************************************************************************** -* 添加图片进行显示 -**************************************************************************** -*/ -function addStyleImg() { - const contentStack = imgStyle.stack - if (contentStack == undefined) { - return - } - - const marginStart = textStyle.marginStart - if (marginStart != undefined && marginStart != 0) { - contentStack.addSpacer(marginStart) - } - - const imgSpan = contentStack.addImage(imgStyle.img) - imgSpan.imageSize = new Size(imgStyle.width, imgStyle.height) - const tintColor = imgStyle.tintColor - if (tintColor != undefined) { - imgSpan.tintColor = tintColor - } - - const marginEnd = textStyle.marginEnd - if (marginStart != undefined && marginStart != 0) { - contentStack.addSpacer(marginEnd) - } - - // 重置样式 - resetImgStyle() -} - -/* -**************************************************************************** -* 右对齐,水平方向排列 -**************************************************************************** -*/ -function alignRightStack(alignmentStack, marginRight) { - let contentStack = alignmentStack.addStack() - contentStack.layoutHorizontally() - contentStack.addSpacer() - - let returnStack = contentStack.addStack() - - // 添加右边距 - if (marginRight != undefined && marginRight != 0) { - contentStack.addSpacer(marginRight) - } - - return returnStack -} - - -/* -**************************************************************************** -* 左对齐,水平方向排列 -**************************************************************************** -*/ -function alignLeftStack(alignmentStack, marginLeft) { - let contentStack = alignmentStack.addStack() - contentStack.layoutHorizontally() - - let returnStack = contentStack.addStack() - returnStack.layoutHorizontally() - - // 添加左边距 - if (marginLeft != undefined && marginLeft != 0) { - returnStack.addSpacer(marginLeft) - } - - contentStack.addSpacer() - return returnStack -} - -/* -**************************************************************************** -* 上对齐,垂直方向排列 -**************************************************************************** -*/ -function alignTopStack(alignmentStack, marginTop) { - let contentStack = alignmentStack.addStack() - contentStack.layoutVertically() - - // 添加左边距 - if (marginTop != undefined && marginTop != 0) { - contentStack.addSpacer(marginTop) - } - - let returnStack = contentStack.addStack() - returnStack.layoutVertically() - - contentStack.addSpacer() - return returnStack -} - - -/* -**************************************************************************** -* 下对齐,垂直方向排列 -**************************************************************************** -*/ -function alignBottomStack(alignmentStack, marginBottom) { - let contentStack = alignmentStack.addStack() - contentStack.layoutVertically() - contentStack.addSpacer() - - let returnStack = contentStack.addStack() - - // 添加下边距 - if (marginBottom != undefined && marginBottom != 0) { - contentStack.addSpacer(marginBottom) - } - - return returnStack -} - -/* -**************************************************************************** -* 水平居中 -**************************************************************************** -*/ -function alignHorizontallyCenterStack(alignmentStack) { - let returnStack = alignmentStack.addStack() - returnStack.layoutHorizontally() - returnStack.centerAlignContent() - return returnStack -} - - -/* -**************************************************************************** -* 垂直居中 -**************************************************************************** -*/ -function alignVerticallyCenterStack(alignmentStack) { - let returnStack = alignmentStack.addStack() - returnStack.layoutVertically() - returnStack.centerAlignContent() - return returnStack -} - - -/* -**************************************************************************** -* 网络请求get封装 -**************************************************************************** -*/ -async function getJson(url) { - const request = new Request(url) - const defaultHeaders = { - "Accept": "*/*", - "Content-Type": "application/json" - } - - request.url = url - request.method = 'GET' - request.headers = defaultHeaders - - const data = await request.loadJSON() - - return data -} - - -/* -**************************************************************************** -* 网络请求获取图片 -**************************************************************************** -*/ -async function getImage(url) { - const request = new Request(url) - const data = await request.loadImage() - return data -} - - +//------------------------------------------------ +//↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑内容区↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ +//------------------------------------------------ +// 运行脚本、预览 +await env.run(name, widget) +//------------------------------------------------ \ No newline at end of file diff --git "a/\346\227\245\345\216\206\344\270\255\347\273\204\344\273\266.js" "b/\346\227\245\345\216\206\344\270\255\347\273\204\344\273\266.js" deleted file mode 100644 index 44ec9bb..0000000 --- "a/\346\227\245\345\216\206\344\270\255\347\273\204\344\273\266.js" +++ /dev/null @@ -1,571 +0,0 @@ -// Variables used by Scriptable. -// This transparent bg was created by Max Zeryck - - -/********************************************************************/ -/****************************定义小组件****************************/ -/********************************************************************/ -const filename = Script.name() + ".jpg" -const files = FileManager.local() -const path = files.joinPath(files.documentsDirectory(), filename) - -////////////////////////////////////////////////////////// -// 背景是否是颜色 -const colorMode = true -// 背景颜色 -const bgColorStr = "#ffffff" - -// 周标题 -const weekTitle = ['🙄 周日', '😪 周一', '😩 周二', '🤨 周三', '🤓 周四', '🤩 周五', '🥳 周六'] - -// 日期文字大小 -const dayFont = Font.ultraLightMonospacedSystemFont(12) -// 日期文字颜色 -const dayColor = new Color('#000') -// 今天日期文字颜色 -const currDayColor = new Color('#ff0000') -// 非本月日期文字颜色 -const nonDayColor = new Color('#000', 0) - -// 日期 -const thisDate = new Date() -// 年份 -const year = thisDate.getFullYear() -// 月份 -const month = thisDate.getMonth() + 1 -// 日期 -const currDay = thisDate.getDate() -// 格式化日期 -const yearMonthText = year + "-" + numFormatStr(month) - -////////////////////////////////////////////////////////// -if (config.runsInWidget || colorMode) { - /****************************小组件内容START****************************/ - // 上一个月的年份 - let preMonthYear - // 上个月份 - let preMonth - if (month == 1) { - preMonthYear = year - 1 - preMonth = 12 - } else { - preMonthYear = year - preMonth = month - 1 - } - // 上个月有多少天 - const preMonthDays = getDays(preMonthYear, preMonth) - // 当前月份有多少天 - const currMonthDays = getDays(year, month) - // 当前月份1号是星期几 - const currMonthFirstDay = getFirstDayWeek(year, month) - // 开始日期数字 - const startNum = preMonthDays - currMonthFirstDay + 1 - // 日历总数字 - var totalDays = currMonthDays + preMonthDays - // 总日期数字 - var totalNumArr = [] - for (var index = startNum; index <= totalDays; index++) { - totalNumArr.push(index) - } - - - ////////////////////////////////////////////////////////// - // 创建列表 - let widget = new ListWidget() - - // 内容排版 - let contentStack = widget.addStack() - contentStack.layoutHorizontally() - contentStack.addSpacer() - - // 左侧内容 - let leftStack = contentStack.addStack() - leftStack.layoutVertically() - leftStack.addSpacer() - // 日期 - let monthText = leftStack.addText(numFormatStr(month) + "月" + currDay + "日") - monthText.font = Font.systemFont(18) - monthText.textColor = new Color('#000') - monthText.leftAlignText() - // 星期几 - leftStack.addSpacer(8) - let currWeekDayText = leftStack.addText(getCurrDayWeekTitle() + " ☞☞") - currWeekDayText.font = Font.systemFont(14) - currWeekDayText.textColor = new Color('#ff0000') - currWeekDayText.leftAlignText() - // 农历信息 - leftStack.addSpacer(8) - let lunarInfo = await getLunar() - let infoLunarText = lunarInfo.data.lunar - let infoSolarText = lunarInfo.data.solar - infoLunarText = infoLunarText.substring(12, infoLunarText.length) - let constellationText = lunarInfo.data.constellation - let lunarText = leftStack.addText(infoLunarText) - lunarText.font = Font.systemFont(18) - lunarText.textColor = new Color('#000') - lunarText.leftAlignText() - - // 间隔 - leftStack.addSpacer() - contentStack.addSpacer() - - // 日期填充 - let dayColumnArr1 = [] - let dayColumnArr2 = [] - let dayColumnArr3 = [] - let dayColumnArr4 = [] - let dayColumnArr5 = [] - let dayColumnArr6 = [] - let dayColumnArr7 = [] - - // 日期行数 - var rowSize = Math.round(totalDays / 7) - for (var index = 0; index < totalDays; index=index+7) { - var size = index - dayColumnArr1.push(totalNumArr[size]) - - var size1 = size + 1 - if (size1 < totalDays) { - dayColumnArr2.push(totalNumArr[size1]) - } - - var size2 = size + 2 - if (size2 < totalDays) { - dayColumnArr3.push(totalNumArr[size2]) - } - - var size3 = size + 3 - if (size3 < totalDays) { - dayColumnArr4.push(totalNumArr[size3]) - } - - var size4 = size + 4 - if (size4 < totalDays) { - dayColumnArr5.push(totalNumArr[size4]) - } - - var size5 = size + 5 - if (size5 < totalDays) { - dayColumnArr6.push(totalNumArr[size5]) - } - - var size6 = size + 6 - if (size6 < totalDays) { - dayColumnArr7.push(totalNumArr[size6]) - } - } - - // 行间距 - const columnSpacer = 10 - // 列间距 - const rowSpacer = 8 - // 周日标题 - let weekColumn1 = contentStack.addStack() - weekColumn1.layoutVertically() - weekColumn1.addSpacer() - // 第一列日期 - for (var index = 0; index < dayColumnArr1.length; index++) { - let day = dayColumnArr1[index] - let color = dayColor - if (day > preMonthDays) { - day = day - preMonthDays - } else { - color = nonDayColor - } - createDayColumn(weekColumn1, day, dayFont, color, columnSpacer) - } - weekColumn1.addSpacer() - contentStack.addSpacer(rowSpacer) - - // 周一标题 - let weekColumn2 = contentStack.addStack() - weekColumn2.layoutVertically() - weekColumn2.addSpacer() - // 第二列日期 - for (var index = 0; index < dayColumnArr2.length; index++) { - let day = dayColumnArr2[index] - let color = dayColor - if (day > preMonthDays) { - day = day - preMonthDays - } else { - color = nonDayColor - } - createDayColumn(weekColumn2, day, dayFont, color, columnSpacer) - } - weekColumn2.addSpacer() - contentStack.addSpacer(rowSpacer) - - // 周二标题 - let weekColumn3 = contentStack.addStack() - weekColumn3.layoutVertically() - weekColumn3.addSpacer() - // 第三列日期 - for (var index = 0; index < dayColumnArr3.length; index++) { - let day = dayColumnArr3[index] - let color = dayColor - if (day > preMonthDays) { - day = day - preMonthDays - } else { - color = nonDayColor - } - createDayColumn(weekColumn3, day, dayFont, color, columnSpacer) - } - weekColumn3.addSpacer() - contentStack.addSpacer(rowSpacer) - - // 周三标题 - let weekColumn4 = contentStack.addStack() - weekColumn4.layoutVertically() - weekColumn4.addSpacer() - // 第四列日期 - for (var index = 0; index < dayColumnArr4.length; index++) { - let day = dayColumnArr4[index] - let color = dayColor - if (day > preMonthDays) { - day = day - preMonthDays - } else { - color = nonDayColor - } - createDayColumn(weekColumn4, day, dayFont, color, columnSpacer) - } - weekColumn4.addSpacer() - contentStack.addSpacer(rowSpacer) - - // 周四标题 - let weekColumn5 = contentStack.addStack() - weekColumn5.layoutVertically() - weekColumn5.addSpacer() - // 第五列日期 - for (var index = 0; index < dayColumnArr5.length; index++) { - let day = dayColumnArr5[index] - let color = dayColor - if (day > preMonthDays) { - day = day - preMonthDays - } else { - color = nonDayColor - } - createDayColumn(weekColumn5, day, dayFont, color, columnSpacer) - } - weekColumn5.addSpacer() - contentStack.addSpacer(rowSpacer) - - // 周五标题 - let weekColumn6 = contentStack.addStack() - weekColumn6.layoutVertically() - weekColumn6.addSpacer() - // 第六列日期 - for (var index = 0; index < dayColumnArr6.length; index++) { - let day = dayColumnArr6[index] - let color = dayColor - if (day > preMonthDays) { - day = day - preMonthDays - } else { - color = nonDayColor - } - createDayColumn(weekColumn6, day, dayFont, color, columnSpacer) - } - weekColumn6.addSpacer() - contentStack.addSpacer(rowSpacer) - - // 周六标题 - let weekColumn7 = contentStack.addStack() - weekColumn7.layoutVertically() - weekColumn7.addSpacer() - // 第七列日期 - for (var index = 0; index < dayColumnArr7.length; index++) { - let day = dayColumnArr7[index] - let color = dayColor - if (day > preMonthDays) { - day = day - preMonthDays - } else { - color = nonDayColor - } - createDayColumn(weekColumn7, day, dayFont, color, columnSpacer) - } - weekColumn7.addSpacer() - - - ////////////////////////////////////////////////////////// - if (colorMode) { - widget.backgroundColor = new Color(bgColorStr) - } else { - widget.backgroundImage = files.readImage(path) - } - contentStack.addSpacer() - widget.setPadding(0, 4, 0, 4) - Script.setWidget(widget) - Script.complete() - // 预览中等尺寸 - widget.presentMedium() - /*****************************小组件内容ENd*****************************/ - -} else if(!colorMode) { - // Determine if user has taken the screenshot. - var message - message = "图片模式支持相册随意照片&背景透明" - let options = ["图片选择","透明背景"] - let isTransparentMode = await generateAlert(message, options) - if (!isTransparentMode) { - let img = await Photos.fromLibrary() - message = "您的小部件背景已准备就绪" - const resultOptions = ["好的"] - await generateAlert(message, resultOptions) - files.writeImage(path, img) - } else { - message = "透明模式开始之前,请返回主屏幕并长按进入编辑模式。滑动到最右边的空白页并截图。" - let exitOptions = ["继续","退出以截图"] - let shouldExit = await generateAlert(message,exitOptions) - if (shouldExit) return - - // Get screenshot and determine phone size. - let img = await Photos.fromLibrary() - let height = img.size.height - let phone = phoneSizes()[height] - if (!phone) { - message = "您似乎选择了非iPhone屏幕截图的图像,或者不支持您的iPhone。请使用其他图像再试一次。" - await generateAlert(message,["好的"]) - return - } - - // Prompt for widget size and position. - message = "您想要创建什么尺寸的小部件?" - let sizes = ["Small","Medium","Large"] - let size = await generateAlert(message,sizes) - let widgetSize = sizes[size] - - message = "您想它在什么位置?" - message += (height == 1136 ? " (请注意,您的设备仅支持两行小部件,因此中间和底部选项相同。)" : "") - - // Determine image crop based on phone size. - let crop = { w: "", h: "", x: "", y: "" } - if (widgetSize == "Small") { - crop.w = phone.small - crop.h = phone.small - let positions = ["Top left","Top right","Middle left","Middle right","Bottom left","Bottom right"] - let position = await generateAlert(message,positions) - - // Convert the two words into two keys for the phone size dictionary. - let keys = positions[position].toLowerCase().split(' ') - crop.y = phone[keys[0]] - crop.x = phone[keys[1]] - - } else if (widgetSize == "Medium") { - crop.w = phone.medium - crop.h = phone.small - - // Medium and large widgets have a fixed x-value. - crop.x = phone.left - let positions = ["Top","Middle","Bottom"] - let position = await generateAlert(message,positions) - let key = positions[position].toLowerCase() - crop.y = phone[key] - - } else if(widgetSize == "Large") { - crop.w = phone.medium - crop.h = phone.large - crop.x = phone.left - let positions = ["Top","Bottom"] - let position = await generateAlert(message,positions) - - // Large widgets at the bottom have the "middle" y-value. - crop.y = position ? phone.middle : phone.top - } - - // Crop image and finalize the widget. - let imgCrop = cropImage(img, new Rect(crop.x,crop.y,crop.w,crop.h)) - - message = "您的小部件背景已准备就绪" - const resultOptions = ["好的"] - await generateAlert(message, resultOptions) - files.writeImage(path, imgCrop) - } - - Script.complete() -} - -/* - ************************************************************************************ - */ - -// Generate an alert with the provided array of options. -async function generateAlert(message,options) { - - let alert = new Alert() - alert.message = message - - for (const option of options) { - alert.addAction(option) - } - - let response = await alert.presentAlert() - return response -} - -// Crop an image into the specified rect. -function cropImage(img,rect) { - - let draw = new DrawContext() - draw.size = new Size(rect.width, rect.height) - - draw.drawImageAtPoint(img,new Point(-rect.x, -rect.y)) - return draw.getImage() -} - -// Pixel sizes and positions for widgets on all supported phones. -function phoneSizes() { - let phones = { - "2688": { - "small": 507, - "medium": 1080, - "large": 1137, - "left": 81, - "right": 654, - "top": 228, - "middle": 858, - "bottom": 1488 - }, - - "1792": { - "small": 338, - "medium": 720, - "large": 758, - "left": 54, - "right": 436, - "top": 160, - "middle": 580, - "bottom": 1000 - }, - - "2436": { - "small": 465, - "medium": 987, - "large": 1035, - "left": 69, - "right": 591, - "top": 213, - "middle": 783, - "bottom": 1353 - }, - - "2208": { - "small": 471, - "medium": 1044, - "large": 1071, - "left": 99, - "right": 672, - "top": 114, - "middle": 696, - "bottom": 1278 - }, - - "1334": { - "small": 296, - "medium": 642, - "large": 648, - "left": 54, - "right": 400, - "top": 60, - "middle": 412, - "bottom": 764 - }, - - "1136": { - "small": 282, - "medium": 584, - "large": 622, - "left": 30, - "right": 332, - "top": 59, - "middle": 399, - "bottom": 399 - } - } - return phones -} - -/* - ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ - */ - /* - * 创建行 - ================================================ - */ -function createDayColumn(stack, day, font, color, spacer) { - if (day == undefined) return - let dayText = stack.addText(day.toString()) - dayText.font = font - let textColor = color - if (day == currDay) { - textColor = currDayColor - } - dayText.textColor = textColor - dayText.shadowColor = textColor - dayText.shadowOffset = new Point(1,1) - dayText.shadowRadius = 1 - dayText.rightAlignText() - stack.addSpacer(spacer) -} - -/* - * 数字格式化 - ================================================ - */ -function numFormatStr(num) { - if (num > 0 && num < 10) { - return `0${num}` - } else { - return `${num}` - } -} - -/* - * 获取月份有多少天 - ================================================ - */ - function getDays(year, month) { - var date = new Date(year, month, 0) - return date.getDate() - } - -/* - * 获取指定月份的1号是星期几(0~6) - ================================================ - */ - function getFirstDayWeek(year, month) { - var date = new Date(year, month - 1) - return date.getDay() - } - -/* - * 获取今天是星期几 - ================================================ - */ - function getCurrDayWeekTitle() { - var date = new Date() - return weekTitle[date.getDay()] - } - -/* - * 在线获取农历信息 - ================================================ - */ -async function getLunar() { - const request = new Request("https://www.iamwawa.cn/home/nongli/ajax") - const defaultHeaders = { - "Accept": "*/*", - "Content-Type": "application/json" - } - - request.method = 'POST' - request.headers = defaultHeaders - - request.addParameterToMultipart("type", "solar") - request.addParameterToMultipart("year", year + "") - request.addParameterToMultipart("month", month + "") - request.addParameterToMultipart("day", currDay + "") - - const data = await request.loadJSON() - log(data) - - return data -} \ No newline at end of file diff --git "a/\346\227\245\345\216\206\345\260\217\347\273\204\344\273\266.js" "b/\346\227\245\345\216\206\345\260\217\347\273\204\344\273\266.js" deleted file mode 100644 index 06b48a7..0000000 --- "a/\346\227\245\345\216\206\345\260\217\347\273\204\344\273\266.js" +++ /dev/null @@ -1,526 +0,0 @@ -// Variables used by Scriptable. -// This transparent bg was created by Max Zeryck - - -/********************************************************************/ -/****************************定义小组件****************************/ -/********************************************************************/ -const filename = Script.name() + ".jpg" -const files = FileManager.local() -const path = files.joinPath(files.documentsDirectory(), filename) - -////////////////////////////////////////////////////////// -// 背景是否是颜色 -const colorMode = false -// 背景颜色 -const bgColorStr = "#ffffff" - -// 年月标题大小 -const yearMonthFont = Font.systemFont(20) -// 年月标题文字颜色 -const yearMonthColor = new Color('#9A6D38') - -// 周标题大小 -const weekFont = Font.lightMonospacedSystemFont(9) -// 周标题文字颜色 -const weekColor = new Color('#999') - -// 日期文字大小 -const dayFont = Font.ultraLightMonospacedSystemFont(9) -// 日期文字颜色 -const dayColor = new Color('#000') -// 今天日期文字颜色 -const currDayColor = new Color('#ff0000') -// 非本月日期文字颜色 -const nonDayColor = new Color('#000', 0) - -// 日期 -const thisDate = new Date() -// 年份 -const year = thisDate.getFullYear() -// 月份 -const month = thisDate.getMonth() + 1 -// 日期 -const currDay = thisDate.getDate() -// 格式化日期 -const yearMonthText = year + "-" + numFormatStr(month) - -// 周标题 -const weekDays = ['日', '一', '二', '三', '四', '五', '六'] -////////////////////////////////////////////////////////// - -if (config.runsInWidget || colorMode) { - // 透明背景设置:widget.backgroundImage = files.readImage(path) - - /****************************小组件内容START****************************/ - // 上一个月的年份 - let preMonthYear - // 上个月份 - let preMonth - if (month == 1) { - preMonthYear = year - 1 - preMonth = 12 - } else { - preMonthYear = year - preMonth = month - 1 - } - // 上个月有多少天 - const preMonthDays = getDays(preMonthYear, preMonth) - // 当前月份有多少天 - const currMonthDays = getDays(year, month) - // 当前月份1号是星期几 - const currMonthFirstDay = getFirstDayWeek(year, month) - // 开始日期数字 - const startNum = preMonthDays - currMonthFirstDay + 1 - // 日历总数字 - var totalDays = currMonthDays + preMonthDays - // 总日期数字 - var totalNumArr = [] - for (var index = startNum; index <= totalDays; index++) { - totalNumArr.push(index) - } - - - ////////////////////////////////////////////////////////// - // 创建列表 - let widget = new ListWidget() - - // 年月标题 - let yearMonthRow = widget.addStack() - yearMonthRow.addSpacer() - yearMonthRow.layoutHorizontally() - // 年月 - let yearText = yearMonthRow.addText(yearMonthText) - yearText.font = yearMonthFont - yearText.textColor = yearMonthColor - yearText.shadowColor = yearMonthColor - yearText.shadowOffset = new Point(1,1) - yearText.shadowRadius = 1 - yearText.leftAlignText() - yearMonthRow.addSpacer() - - widget.addSpacer(10) - - // 日期填充 - let dayColumnArr1 = [] - let dayColumnArr2 = [] - let dayColumnArr3 = [] - let dayColumnArr4 = [] - let dayColumnArr5 = [] - let dayColumnArr6 = [] - let dayColumnArr7 = [] - - // 日期行数 - var rowSize = Math.round(totalDays / 7) - for (var index = 0; index < totalDays; index=index+7) { - var size = index - dayColumnArr1.push(totalNumArr[size]) - - var size1 = size + 1 - if (size1 < totalDays) { - dayColumnArr2.push(totalNumArr[size1]) - } - - var size2 = size + 2 - if (size2 < totalDays) { - dayColumnArr3.push(totalNumArr[size2]) - } - - var size3 = size + 3 - if (size3 < totalDays) { - dayColumnArr4.push(totalNumArr[size3]) - } - - var size4 = size + 4 - if (size4 < totalDays) { - dayColumnArr5.push(totalNumArr[size4]) - } - - var size5 = size + 5 - if (size5 < totalDays) { - dayColumnArr6.push(totalNumArr[size5]) - } - - var size6 = size + 6 - if (size6 < totalDays) { - dayColumnArr7.push(totalNumArr[size6]) - } - } - - - // 内容排版 - let contentStack = widget.addStack() - contentStack.layoutHorizontally() - contentStack.addSpacer() - - // 列间距 - const columnSpacer = 2 - // 周日标题 - let weekColumn1 = contentStack.addStack(); - weekColumn1.layoutVertically(); - createDayColumn(weekColumn1, weekDays[0], weekFont, weekColor, columnSpacer) - // 第一列日期 - for (var index = 0; index < dayColumnArr1.length; index++) { - let day = dayColumnArr1[index] - let color = dayColor - if (day > preMonthDays) { - day = day - preMonthDays - } else { - color = nonDayColor - } - createDayColumn(weekColumn1, day, dayFont, color, columnSpacer) - } - contentStack.addSpacer() - - // 周一标题 - let weekColumn2 = contentStack.addStack(); - weekColumn2.layoutVertically(); - createDayColumn(weekColumn2, weekDays[1], weekFont, weekColor, columnSpacer) - // 第二列日期 - for (var index = 0; index < dayColumnArr2.length; index++) { - let day = dayColumnArr2[index] - let color = dayColor - if (day > preMonthDays) { - day = day - preMonthDays - } else { - color = nonDayColor - } - createDayColumn(weekColumn2, day, dayFont, color, columnSpacer) - } - contentStack.addSpacer() - - // 周二标题 - let weekColumn3 = contentStack.addStack(); - weekColumn3.layoutVertically(); - createDayColumn(weekColumn3, weekDays[2], weekFont, weekColor, columnSpacer) - // 第三列日期 - for (var index = 0; index < dayColumnArr3.length; index++) { - let day = dayColumnArr3[index] - let color = dayColor - if (day > preMonthDays) { - day = day - preMonthDays - } else { - color = nonDayColor - } - createDayColumn(weekColumn3, day, dayFont, color, columnSpacer) - } - contentStack.addSpacer() - - // 周三标题 - let weekColumn4 = contentStack.addStack(); - weekColumn4.layoutVertically(); - createDayColumn(weekColumn4, weekDays[3], weekFont, weekColor, columnSpacer) - // 第四列日期 - for (var index = 0; index < dayColumnArr4.length; index++) { - let day = dayColumnArr4[index] - let color = dayColor - if (day > preMonthDays) { - day = day - preMonthDays - } else { - color = nonDayColor - } - createDayColumn(weekColumn4, day, dayFont, color, columnSpacer) - } - contentStack.addSpacer() - - // 周四标题 - let weekColumn5 = contentStack.addStack(); - weekColumn5.layoutVertically(); - createDayColumn(weekColumn5, weekDays[4], weekFont, weekColor, columnSpacer) - // 第五列日期 - for (var index = 0; index < dayColumnArr5.length; index++) { - let day = dayColumnArr5[index] - let color = dayColor - if (day > preMonthDays) { - day = day - preMonthDays - } else { - color = nonDayColor - } - createDayColumn(weekColumn5, day, dayFont, color, columnSpacer) - } - contentStack.addSpacer() - - // 周五标题 - let weekColumn6 = contentStack.addStack(); - weekColumn6.layoutVertically(); - createDayColumn(weekColumn6, weekDays[5], weekFont, weekColor, columnSpacer) - // 第六列日期 - for (var index = 0; index < dayColumnArr6.length; index++) { - let day = dayColumnArr6[index] - let color = dayColor - if (day > preMonthDays) { - day = day - preMonthDays - } else { - color = nonDayColor - } - createDayColumn(weekColumn6, day, dayFont, color, columnSpacer) - } - contentStack.addSpacer() - - // 周六标题 - let weekColumn7 = contentStack.addStack(); - weekColumn7.layoutVertically(); - createDayColumn(weekColumn7, weekDays[6], weekFont, weekColor, columnSpacer) - // 第七列日期 - for (var index = 0; index < dayColumnArr7.length; index++) { - let day = dayColumnArr7[index] - let color = dayColor - if (day > preMonthDays) { - day = day - preMonthDays - } else { - color = nonDayColor - } - createDayColumn(weekColumn7, day, dayFont, color, columnSpacer) - } - contentStack.addSpacer() - - - ////////////////////////////////////////////////////////// - if (colorMode) { - widget.backgroundColor = new Color(bgColorStr) - } else { - widget.backgroundImage = files.readImage(path) - } - widget.setPadding(0, 4, 0, 4) - Script.setWidget(widget) - Script.complete() - // 预览小尺寸 - widget.presentSmall() - /*****************************小组件内容ENd*****************************/ - -} else if(!colorMode) { - // Determine if user has taken the screenshot. - var message - message = "图片模式支持相册随意照片&背景透明" - let options = ["图片选择","透明背景"] - let isTransparentMode = await generateAlert(message, options) - if (!isTransparentMode) { - let img = await Photos.fromLibrary() - message = "您的小部件背景已准备就绪" - const resultOptions = ["好的"] - await generateAlert(message, resultOptions) - files.writeImage(path, img) - } else { - message = "透明模式开始之前,请返回主屏幕并长按进入编辑模式。滑动到最右边的空白页并截图。" - let exitOptions = ["继续","退出以截图"] - let shouldExit = await generateAlert(message,exitOptions) - if (shouldExit) return - - // Get screenshot and determine phone size. - let img = await Photos.fromLibrary() - let height = img.size.height - let phone = phoneSizes()[height] - if (!phone) { - message = "您似乎选择了非iPhone屏幕截图的图像,或者不支持您的iPhone。请使用其他图像再试一次。" - await generateAlert(message,["好的"]) - return - } - - // Prompt for widget size and position. - message = "您想要创建什么尺寸的小部件?" - let sizes = ["Small","Medium","Large"] - let size = await generateAlert(message,sizes) - let widgetSize = sizes[size] - - message = "您想它在什么位置?" - message += (height == 1136 ? " (请注意,您的设备仅支持两行小部件,因此中间和底部选项相同。)" : "") - - // Determine image crop based on phone size. - let crop = { w: "", h: "", x: "", y: "" } - if (widgetSize == "Small") { - crop.w = phone.small - crop.h = phone.small - let positions = ["Top left","Top right","Middle left","Middle right","Bottom left","Bottom right"] - let position = await generateAlert(message,positions) - - // Convert the two words into two keys for the phone size dictionary. - let keys = positions[position].toLowerCase().split(' ') - crop.y = phone[keys[0]] - crop.x = phone[keys[1]] - - } else if (widgetSize == "Medium") { - crop.w = phone.medium - crop.h = phone.small - - // Medium and large widgets have a fixed x-value. - crop.x = phone.left - let positions = ["Top","Middle","Bottom"] - let position = await generateAlert(message,positions) - let key = positions[position].toLowerCase() - crop.y = phone[key] - - } else if(widgetSize == "Large") { - crop.w = phone.medium - crop.h = phone.large - crop.x = phone.left - let positions = ["Top","Bottom"] - let position = await generateAlert(message,positions) - - // Large widgets at the bottom have the "middle" y-value. - crop.y = position ? phone.middle : phone.top - } - - // Crop image and finalize the widget. - let imgCrop = cropImage(img, new Rect(crop.x,crop.y,crop.w,crop.h)) - - message = "您的小部件背景已准备就绪" - const resultOptions = ["好的"] - await generateAlert(message, resultOptions) - files.writeImage(path, imgCrop) - } - - Script.complete() -} - -/* - ************************************************************************************ - */ - -// Generate an alert with the provided array of options. -async function generateAlert(message,options) { - - let alert = new Alert() - alert.message = message - - for (const option of options) { - alert.addAction(option) - } - - let response = await alert.presentAlert() - return response -} - -// Crop an image into the specified rect. -function cropImage(img,rect) { - - let draw = new DrawContext() - draw.size = new Size(rect.width, rect.height) - - draw.drawImageAtPoint(img,new Point(-rect.x, -rect.y)) - return draw.getImage() -} - -// Pixel sizes and positions for widgets on all supported phones. -function phoneSizes() { - let phones = { - "2688": { - "small": 507, - "medium": 1080, - "large": 1137, - "left": 81, - "right": 654, - "top": 228, - "middle": 858, - "bottom": 1488 - }, - - "1792": { - "small": 338, - "medium": 720, - "large": 758, - "left": 54, - "right": 436, - "top": 160, - "middle": 580, - "bottom": 1000 - }, - - "2436": { - "small": 465, - "medium": 987, - "large": 1035, - "left": 69, - "right": 591, - "top": 213, - "middle": 783, - "bottom": 1353 - }, - - "2208": { - "small": 471, - "medium": 1044, - "large": 1071, - "left": 99, - "right": 672, - "top": 114, - "middle": 696, - "bottom": 1278 - }, - - "1334": { - "small": 296, - "medium": 642, - "large": 648, - "left": 54, - "right": 400, - "top": 60, - "middle": 412, - "bottom": 764 - }, - - "1136": { - "small": 282, - "medium": 584, - "large": 622, - "left": 30, - "right": 332, - "top": 59, - "middle": 399, - "bottom": 399 - } - } - return phones -} - -/* - ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ - */ - /* - * 创建行 - ================================================ - */ -function createDayColumn(stack, day, font, color, spacer) { - if (day == undefined) return - let dayText = stack.addText(day.toString()) - dayText.font = font - let textColor = color - if (day == currDay) { - textColor = currDayColor - } - dayText.textColor = textColor - dayText.shadowColor = textColor - dayText.shadowOffset = new Point(1,1) - dayText.shadowRadius = 1 - dayText.centerAlignText() - stack.addSpacer(spacer) -} - -/* - * 数字格式化 - ================================================ - */ -function numFormatStr(num) { - if (num > 0 && num < 10) { - return `0${num}` - } else { - return `${num}` - } -} - -/* - * 获取月份有多少天 - ================================================ - */ - function getDays(year, month) { - var date = new Date(year, month, 0) - return date.getDate() - } - -/* - * 获取指定月份的1号是星期几(0~6) - ================================================ - */ - function getFirstDayWeek(year, month) { - var date = new Date(year, month - 1) - return date.getDay() - } \ No newline at end of file diff --git "a/\346\250\241\346\235\277-new.js" "b/\346\250\241\346\235\277-new.js" new file mode 100644 index 0000000..c29c99c --- /dev/null +++ "b/\346\250\241\346\235\277-new.js" @@ -0,0 +1,34 @@ +//------------------------------------------------ +const env = importModule('Env-lsp.js') +//------------------------------------------------ +// 配置区 +env.configs.previewSize = "Small" // 预览大小【小:Small,中:Medium,大:Large】 +env.configs.changePicBg = true // 是否需要更换背景 +env.configs.colorMode = false // 是否是纯色背景 +env.configs.bgColor = new Color("000000") // 小组件背景色 +env.configs.topPadding = 0 // 内容区边距 +env.configs.leftPadding = 0 // 内容区边距 +env.configs.bottomPadding = 0 // 内容区边距 +env.configs.rightPadding = 0 // 内容区边距 +// +const imgStyle = env.imgStyle +const textStyle = env.textStyle +//------------------------------------------------ +// 脚本名字 +const name = Script.name() +// 组件 +const widget = new ListWidget() +const contentStack = widget.addStack() +//------------------------------------------------ + + +//↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓内容区↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ +//------------------------------------------------ + +//------------------------------------------------ +//↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑内容区↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ + +//------------------------------------------------ +// 运行脚本、预览 +await env.run(name, widget) +//------------------------------------------------ \ No newline at end of file diff --git "a/\346\250\241\346\235\277.js" "b/\346\250\241\346\235\277.js" deleted file mode 100644 index 6b2ed9e..0000000 --- "a/\346\250\241\346\235\277.js" +++ /dev/null @@ -1,552 +0,0 @@ -////////////////////////////////////////// -// 预览大小【小:Small,中:Medium,大:Large】 -const previewSize = "Medium" - -// 是否需要更换背景 -const changePicBg = true - -// 是否是纯色背景 -const colorMode = false - -// 小组件背景色 -const bgColor = new Color("000000") - -// 默认字体 -const defaultFont = Font.systemFont(18) - -// 默认字体颜色 -const defaultTextColor = new Color("#ffffff") - -// 内容区左右边距 -const padding = { - top: 0, - left: 0, - bottom: 0, - right: 0 -} - -// 标题样式定义 -let textStyle = { - stack: undefined, // 加入到哪个内容栈显示 - marginStart: 0, // 开始距离,水平方向的就是左边距离,垂直方向的就是顶部距离 - marginEnd: 0, // 结束距离,水平方向的就是右边距离,垂直方向的就是底部距离 - text: "", // 显示的文字 - width: 0, // 宽 - height: 0, // 长 - lineLimit: 0, // 行数控制,0是全部展示 - font: undefined, // 字体 - textColor: defaultTextColor, // 文字颜色 -} - -// 图片样式定义 -let imgStyle = { - stack: undefined, // 加入到哪个内容栈显示 - marginStart: 0, // 开始距离,水平方向的就是左边距离,垂直方向的就是顶部距离 - marginEnd: 0, // 结束距离,水平方向的就是右边距离,垂直方向的就是底部距离 - img: undefined, // 图片资源 - width: 0, // 宽 - height: 0, // 长 - tintColor: undefined, // 图片渲染颜色 -} -//////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////// - - - - - -////////////////////////////////////// -// 组件Start -const filename = `${Script.name()}.jpg` -const files = FileManager.local() -const path = files.joinPath(files.documentsDirectory(), filename) -const widget = new ListWidget() -const contentStack = widget.addStack() -////////////////////////////////////// - - - -/* -**************************************************************************** -↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ -下面添加你自己的组件内容/逻辑 -**************************************************************************** -*/ - - - - - - -/* -**************************************************************************** -上面添加你自己的组件内容/逻辑 -↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ -**************************************************************************** -*/ - - -/* -**************************************************************************** -* 这里是图片逻辑,不用修改 -**************************************************************************** -*/ - -if (!colorMode && !config.runsInWidget && changePicBg) { - const okTips = "您的小部件背景已准备就绪" - let message = "图片模式支持相册照片&背景透明" - let options = ["图片选择", "透明背景"] - let isTransparentMode = await generateAlert(message, options) - if (!isTransparentMode) { - let img = await Photos.fromLibrary() - message = okTips - const resultOptions = ["好的"] - await generateAlert(message, resultOptions) - files.writeImage(path, img) - } else { - message = "以下是【透明背景】生成步骤,如果你没有屏幕截图请退出,并返回主屏幕长按进入编辑模式。滑动到最右边的空白页截图。然后重新运行!" - let exitOptions = ["继续(已有截图)", "退出(没有截图)"] - - let shouldExit = await generateAlert(message, exitOptions) - if (shouldExit) return - - // Get screenshot and determine phone size. - let img = await Photos.fromLibrary() - let height = img.size.height - let phone = phoneSizes()[height] - if (!phone) { - message = "您似乎选择了非iPhone屏幕截图的图像,或者不支持您的iPhone。请使用其他图像再试一次!" - await generateAlert(message, ["好的!我现在去截图"]) - return - } - - // Prompt for widget size and position. - message = "您想要创建什么尺寸的小部件?" - let sizes = ["小号", "中号", "大号"] - let size = await generateAlert(message, sizes) - let widgetSize = sizes[size] - - message = "您想它在什么位置?" - message += (height == 1136 ? " (请注意,您的设备仅支持两行小部件,因此中间和底部选项相同。)" : "") - - // Determine image crop based on phone size. - let crop = { w: "", h: "", x: "", y: "" } - if (widgetSize == "小号") { - crop.w = phone.小号 - crop.h = phone.小号 - let positions = ["顶部 左边", "顶部 右边", "中间 左边", "中间 右边", "底部 左边", "底部 右边"] - let position = await generateAlert(message, positions) - - // Convert the two words into two keys for the phone size dictionary. - let keys = positions[position].split(' ') - crop.y = phone[keys[0]] - crop.x = phone[keys[1]] - - } else if (widgetSize == "中号") { - crop.w = phone.中号 - crop.h = phone.小号 - - // 中号 and 大号 widgets have a fixed x-value. - crop.x = phone.左边 - let positions = ["顶部", "中间", "底部"] - let position = await generateAlert(message, positions) - let key = positions[position].toLowerCase() - crop.y = phone[key] - - } else if (widgetSize == "大号") { - crop.w = phone.中号 - crop.h = phone.大号 - crop.x = phone.左边 - let positions = ["顶部", "底部"] - let position = await generateAlert(message, positions) - - // 大号 widgets at the 底部 have the "中间" y-value. - crop.y = position ? phone.中间 : phone.顶部 - } - - // Crop image and finalize the widget. - let imgCrop = cropImage(img, new Rect(crop.x, crop.y, crop.w, crop.h)) - - message = "您的小部件背景已准备就绪,退出到桌面预览。" - const resultOptions = ["好的"] - await generateAlert(message, resultOptions) - files.writeImage(path, imgCrop) - } - -} - - -////////////////////////////////////// -// 组件End -// 设置小组件的背景 -if (colorMode) { - widget.backgroundColor = bgColor -} else { - widget.backgroundImage = files.readImage(path) -} -// 设置边距(上,左,下,右) -widget.setPadding(padding.top, padding.left, padding.bottom, padding.right) -// 设置组件 -Script.setWidget(widget) -// 完成脚本 -Script.complete() -// 预览 -if (previewSize == "Large") { - widget.presentLarge() -} else if (previewSize == "Medium") { - widget.presentMedium() -} else { - widget.presentSmall() -} -////////////////////////////////////// - -/* -**************************************************************************** -* 重置文本样式 -**************************************************************************** -*/ -function resetTextStyle() { - textStyle.stack = undefined // 加入到哪个内容栈显示 - textStyle.marginStart = 0 - textStyle.marginEnd = 0 - textStyle.text = "" // 显示的文字 - textStyle.width = 0 // 宽 - textStyle.height = 0 // 长 - textStyle.lineLimit = 0 // 行数控制,0是全部展示 - textStyle.font = undefined // 字体 - textStyle.textColor = defaultTextColor // 文字颜色 -} - -/* -**************************************************************************** -* 重置图片样式 -**************************************************************************** -*/ -function resetImgStyle() { - imgStyle.stack = undefined // 加入到哪个内容栈显示 - textStyle.marginStart = 0 - textStyle.marginEnd = 0 - imgStyle.img = undefined // 图片资源 - imgStyle.width = 0 // 宽 - imgStyle.height = 0 // 长 - imgStyle.tintColor = undefined // 图片渲染颜色 -} - -/* -**************************************************************************** -* 添加一行文本数据进行显示 -**************************************************************************** -*/ -function addStyleText() { - const contentStack = textStyle.stack - if (contentStack == undefined) { - return - } - - const marginStart = textStyle.marginStart - if (marginStart != undefined && marginStart != 0) { - contentStack.addSpacer(marginStart) - } - - const textSpan = contentStack.addText(`${textStyle.text}`) - contentStack.size = new Size(textStyle.width, textStyle.height) - textSpan.lineLimit = textStyle.lineLimit - textSpan.font = textStyle.font - textSpan.textColor = textStyle.textColor - - const marginEnd = textStyle.marginEnd - if (marginStart != undefined && marginStart != 0) { - contentStack.addSpacer(marginEnd) - } - - // 重置样式 - resetTextStyle() -} - -/* -**************************************************************************** -* 添加图片进行显示 -**************************************************************************** -*/ -function addStyleImg() { - const contentStack = imgStyle.stack - if (contentStack == undefined) { - return - } - - const marginStart = textStyle.marginStart - if (marginStart != undefined && marginStart != 0) { - contentStack.addSpacer(marginStart) - } - - const imgSpan = contentStack.addImage(imgStyle.img) - imgSpan.imageSize = new Size(imgStyle.width, imgStyle.height) - const tintColor = imgStyle.tintColor - if (tintColor != undefined) { - imgSpan.tintColor = tintColor - } - - const marginEnd = textStyle.marginEnd - if (marginStart != undefined && marginStart != 0) { - contentStack.addSpacer(marginEnd) - } - - // 重置样式 - resetImgStyle() -} - -/* -**************************************************************************** -* 右对齐,水平方向排列 -**************************************************************************** -*/ -function alignRightStack(alignmentStack, marginRight) { - let contentStack = alignmentStack.addStack() - contentStack.layoutHorizontally() - contentStack.addSpacer() - - let returnStack = contentStack.addStack() - - // 添加右边距 - if (marginRight != undefined && marginRight != 0) { - contentStack.addSpacer(marginRight) - } - - return returnStack -} - - -/* -**************************************************************************** -* 左对齐,水平方向排列 -**************************************************************************** -*/ -function alignLeftStack(alignmentStack, marginLeft) { - let contentStack = alignmentStack.addStack() - contentStack.layoutHorizontally() - - let returnStack = contentStack.addStack() - returnStack.layoutHorizontally() - - // 添加左边距 - if (marginLeft != undefined && marginLeft != 0) { - returnStack.addSpacer(marginLeft) - } - - contentStack.addSpacer() - return returnStack -} - -/* -**************************************************************************** -* 上对齐,垂直方向排列 -**************************************************************************** -*/ -function alignTopStack(alignmentStack, marginTop) { - let contentStack = alignmentStack.addStack() - contentStack.layoutVertically() - - // 添加左边距 - if (marginTop != undefined && marginTop != 0) { - contentStack.addSpacer(marginTop) - } - - let returnStack = contentStack.addStack() - returnStack.layoutVertically() - - contentStack.addSpacer() - return returnStack -} - - -/* -**************************************************************************** -* 下对齐,垂直方向排列 -**************************************************************************** -*/ -function alignBottomStack(alignmentStack, marginBottom) { - let contentStack = alignmentStack.addStack() - contentStack.layoutVertically() - contentStack.addSpacer() - - let returnStack = contentStack.addStack() - - // 添加下边距 - if (marginBottom != undefined && marginBottom != 0) { - contentStack.addSpacer(marginBottom) - } - - return returnStack -} - -/* -**************************************************************************** -* 水平居中 -**************************************************************************** -*/ -function alignHorizontallyCenterStack(alignmentStack) { - let returnStack = alignmentStack.addStack() - returnStack.layoutHorizontally() - returnStack.centerAlignContent() - return returnStack -} - - -/* -**************************************************************************** -* 垂直居中 -**************************************************************************** -*/ -function alignVerticallyCenterStack(alignmentStack) { - let returnStack = alignmentStack.addStack() - returnStack.layoutVertically() - returnStack.centerAlignContent() - return returnStack -} - - -/* -**************************************************************************** -* 网络请求get封装 -**************************************************************************** -*/ -async function getJson(url) { - const request = new Request(url) - const defaultHeaders = { - "Accept": "*/*", - "Content-Type": "application/json" - } - - request.url = url - request.method = 'GET' - request.headers = defaultHeaders - - const data = await request.loadJSON() - - return data -} - - -/* -**************************************************************************** -* 网络请求获取图片 -**************************************************************************** -*/ -async function getImage(url) { - const request = new Request(url) - const data = await request.loadImage() - return data -} - - -/* -**************************************************************************** -* 图片裁剪相关 -**************************************************************************** -*/ -// Generate an alert with the provided array of options. -async function generateAlert(message, options) { - let alert = new Alert() - alert.message = message - - for (const option of options) { - alert.addAction(option) - } - - let response = await alert.presentAlert() - return response -} - -// Crop an image into the specified rect. -function cropImage(img, rect) { - let draw = new DrawContext() - draw.size = new Size(rect.width, rect.height) - draw.drawImageAtPoint(img, new Point(-rect.x, -rect.y)) - return draw.getImage() -} - -// Pixel sizes and positions for widgets on all supported phones. -function phoneSizes() { - let phones = { - "2688": { - "小号": 507, - "中号": 1080, - "大号": 1137, - "左边": 81, - "右边": 654, - "顶部": 228, - "中间": 858, - "底部": 1488 - }, - - "1792": { - "小号": 338, - "中号": 720, - "大号": 758, - "左边": 54, - "右边": 436, - "顶部": 160, - "中间": 580, - "底部": 1000 - }, - - "2436": { - "小号": 465, - "中号": 987, - "大号": 1035, - "左边": 69, - "右边": 591, - "顶部": 213, - "中间": 783, - "底部": 1353 - }, - - "2208": { - "小号": 471, - "中号": 1044, - "大号": 1071, - "左边": 99, - "右边": 672, - "顶部": 114, - "中间": 696, - "底部": 1278 - }, - - "1334": { - "小号": 296, - "中号": 642, - "大号": 648, - "左边": 54, - "右边": 400, - "顶部": 60, - "中间": 412, - "底部": 764 - }, - - "1136": { - "小号": 282, - "中号": 584, - "大号": 622, - "左边": 30, - "右边": 332, - "顶部": 59, - "中间": 399, - "底部": 399 - } - } - return phones -} - - -/* -**************************************************************************** -**************************************************************************** -**************************************************************************** -*/ - - - - diff --git "a/\347\203\255\346\220\234\350\275\256\346\222\255.js" "b/\347\203\255\346\220\234\350\275\256\346\222\255.js" new file mode 100644 index 0000000..672c3a5 --- /dev/null +++ "b/\347\203\255\346\220\234\350\275\256\346\222\255.js" @@ -0,0 +1,116 @@ +//------------------------------------------------ +const env = importModule('Env-lsp.js') +//------------------------------------------------ +// 配置区 +env.configs.previewSize = "Medium" // 预览大小【小:Small,中:Medium,大:Large】 +env.configs.changePicBg = true // 是否需要更换背景 +env.configs.colorMode = false // 是否是纯色背景 +env.configs.bgColor = new Color("000000") // 小组件背景色 +env.configs.topPadding = 0 // 内容区边距 +env.configs.leftPadding = 0 // 内容区边距 +env.configs.bottomPadding = 0 // 内容区边距 +env.configs.rightPadding = 0 // 内容区边距 +// env.configs.refreshInterval = 30 // 刷新间隔,单位分钟,非精准,会有3-5分钟差距 +////////////////////////////////// +// 大标题文字颜色 +const headTitleFontColor = new Color("FF7F00", 0.8) +// 列表文字颜色 +const listTitleFontColor = new Color("ffffff", 0.8) +// 热搜ID跟对应的标题,数据来源于 https://mo.fish/ +const hotIdObjs = [ + {"1": "知乎の热搜"}, + {"58": "微博の热搜"}, + {"59": "V2EXの热搜"} +] +////////////////////////////////// +const imgStyle = env.imgStyle +const textStyle = env.textStyle +//------------------------------------------------ +// 脚本名字 +const name = Script.name() +// 文件 +const fm = FileManager.local() +// 组件 +const widget = new ListWidget() +const contentStack = widget.addStack() +//------------------------------------------------ + + +//↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓内容区↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ +//------------------------------------------------ +const splitStr = "@" +// 缓存目录 +const cachePath = fm.joinPath(fm.documentsDirectory(), "lsp-hot-cache") +let cache = undefined +let index = 0 +let start = 0 + +if(fm.fileExists(cachePath)) { + cache = fm.readString(cachePath) + start = cache.indexOf(splitStr) + const indexStr = cache.slice(0, start) + index = (parseInt(indexStr) + 1) % hotIdObjs.length +} + +let obj = hotIdObjs[index] +// 热榜ID +let hotID = Object.keys(obj)[0] + +// 请求热榜数据 +let response = undefined +try { + response = await env.getJson(`https://www.tophub.fun:8888/v2/GetAllInfoGzip?id=${hotID}&page=0`) +} catch(e) { + index -= 1 + if (index < 0) { + index = 0 + } + log("请求网络失败,读取缓存数据") + response = JSON.parse(cache.slice(start+1, cache.length)) +} + +log(`本次轮询索引:${index}`) +obj = hotIdObjs[index] +// 热榜ID +hotID = Object.keys(obj)[0] +// 热榜标题 +const hotTitle = Object.values(obj)[0] +log(`标题:${hotTitle},ID:${hotID}`) + +// 写入缓存 +fm.writeString(cachePath, `${index}${splitStr}${JSON.stringify(response)}`) + +// 截取前5条 +const hotData = response.Data.data.slice(1, 6) + +// 设置大标题 +widget.addSpacer(15) +const titleStack = widget.addStack() +let title = titleStack.addText(`🔥 ${hotTitle}`) +title.font = Font.boldRoundedSystemFont(17) // 大标题字体样式/大小 +title.textColor = headTitleFontColor // 大标题的颜色 +titleStack.addSpacer() +widget.addSpacer(5) + +// 列表 +for (let index in hotData) { + let itemStack = widget.addStack() + // 标题 + let title = itemStack.addText(`☞ ${hotData[index].Title}`) + title.font = Font.boldRoundedSystemFont(13) // 热搜列表标题字体样式/大小 + title.textColor = listTitleFontColor // 热搜列表标题的颜色 + title.url = hotData[index].Url + title.lineLimit = 1 + itemStack.addSpacer() + widget.addSpacer(5) +} + +widget.addSpacer() + +//------------------------------------------------ +//↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑内容区↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ + +//------------------------------------------------ +// 运行脚本、预览 +await env.run(name, widget) +//------------------------------------------------ \ No newline at end of file diff --git "a/\347\203\255\346\246\234.js" "b/\347\203\255\346\246\234.js" deleted file mode 100644 index ebf6e0b..0000000 --- "a/\347\203\255\346\246\234.js" +++ /dev/null @@ -1,330 +0,0 @@ -// Variables used by Scriptable. -// This widget was created by Max Zeryck - -/* - * Author: Enjoyee - * Github: https://github.com/Enjoyee/Scriptable - * 热榜数据源自: https://mo.fish - */ - -/********************************************************************/ -/****************************定义小组件****************************/ -/********************************************************************/ -const filename = Script.name() + ".jpg" -const files = FileManager.local() -const path = files.joinPath(files.documentsDirectory(), filename) - -/********************************************************************/ -// 获取外部输入的参数,格式:【大标题,ID,大标题文字颜色,列表文字颜色】 -let widgetInputRAW = args.widgetParameter -try { - widgetInputRAW.toString() -} catch(e) { - // 默认值微博热搜 - widgetInputRAW = "微博热搜,58" -} -// 获取外部输入 -let inputArr = widgetInputRAW.toString().replace(",", ",").split(",") -// 热榜标题 -const hotTitle = inputArr[0] -// 热榜ID -const hotID = inputArr[1] - - -if (config.runsInWidget) { - // 透明背景设置:widget.backgroundImage = files.readImage(path) - - /****************************小组件内容START****************************/ - // 请求地址 - let requestUrl = "https://www.tophub.fun:8888/v2/GetAllInfoGzip?id=58&page=0" - // 获取热榜数据 - let jsonResponse = await getJson(requestUrl) - // 调用创建小组件 - if (jsonResponse.Code == 0) { - createWidget(jsonResponse.Data.data.slice(1, 6)) - } - /*****************************小组件内容ENd*****************************/ - -} else { - // Determine if user has taken the screenshot. - var message - message = "开始之前,请返回主屏幕并长按进入编辑模式。滑动到最右边的空白页并截图。" - let exitOptions = ["继续","退出以截图"] - let shouldExit = await generateAlert(message,exitOptions) - if (shouldExit) return - - // Get screenshot and determine phone size. - let img = await Photos.fromLibrary() - let height = img.size.height - let phone = phoneSizes()[height] - if (!phone) { - message = "您似乎选择了非iPhone屏幕截图的图像,或者不支持您的iPhone。请使用其他图像再试一次。" - await generateAlert(message,["OK"]) - return - } - - // Prompt for widget size and position. - message = "您想要创建什么尺寸的小部件?" - let sizes = ["Small","Medium","Large"] - let size = await generateAlert(message,sizes) - let widgetSize = sizes[size] - - message = "您想它在什么位置?" - message += (height == 1136 ? " (请注意,您的设备仅支持两行小部件,因此中间和底部选项相同。)" : "") - - // Determine image crop based on phone size. - let crop = { w: "", h: "", x: "", y: "" } - if (widgetSize == "Small") { - crop.w = phone.small - crop.h = phone.small - let positions = ["Top left","Top right","Middle left","Middle right","Bottom left","Bottom right"] - let position = await generateAlert(message,positions) - - // Convert the two words into two keys for the phone size dictionary. - let keys = positions[position].toLowerCase().split(' ') - crop.y = phone[keys[0]] - crop.x = phone[keys[1]] - - } else if (widgetSize == "Medium") { - crop.w = phone.medium - crop.h = phone.small - - // Medium and large widgets have a fixed x-value. - crop.x = phone.left - let positions = ["Top","Middle","Bottom"] - let position = await generateAlert(message,positions) - let key = positions[position].toLowerCase() - crop.y = phone[key] - - } else if(widgetSize == "Large") { - crop.w = phone.medium - crop.h = phone.large - crop.x = phone.left - let positions = ["Top","Bottom"] - let position = await generateAlert(message,positions) - - // Large widgets at the bottom have the "middle" y-value. - crop.y = position ? phone.middle : phone.top - } - - // Crop image and finalize the widget. - let imgCrop = cropImage(img, new Rect(crop.x,crop.y,crop.w,crop.h)) - - message = "您的小部件背景已准备就绪。您想在Scriptable的小部件中使用它还是导出图像?" - const exportPhotoOptions = ["在Scriptable中使用","导出图像"] - const exportPhoto = await generateAlert(message,exportPhotoOptions) - - if (exportPhoto) { - Photos.save(imgCrop) - } else { - files.writeImage(path,imgCrop) - } - - Script.complete() -} - -/* - ************************************************************************************ - */ - -// Generate an alert with the provided array of options. -async function generateAlert(message,options) { - - let alert = new Alert() - alert.message = message - - for (const option of options) { - alert.addAction(option) - } - - let response = await alert.presentAlert() - return response -} - -// Crop an image into the specified rect. -function cropImage(img,rect) { - - let draw = new DrawContext() - draw.size = new Size(rect.width, rect.height) - - draw.drawImageAtPoint(img,new Point(-rect.x, -rect.y)) - return draw.getImage() -} - -// Pixel sizes and positions for widgets on all supported phones. -function phoneSizes() { - let phones = { - "2688": { - "small": 507, - "medium": 1080, - "large": 1137, - "left": 81, - "right": 654, - "top": 228, - "middle": 858, - "bottom": 1488 - }, - - "1792": { - "small": 338, - "medium": 720, - "large": 758, - "left": 54, - "right": 436, - "top": 160, - "middle": 580, - "bottom": 1000 - }, - - "2436": { - "small": 465, - "medium": 987, - "large": 1035, - "left": 69, - "right": 591, - "top": 213, - "middle": 783, - "bottom": 1353 - }, - - "2208": { - "small": 471, - "medium": 1044, - "large": 1071, - "left": 99, - "right": 672, - "top": 114, - "middle": 696, - "bottom": 1278 - }, - - "1334": { - "small": 296, - "medium": 642, - "large": 648, - "left": 54, - "right": 400, - "top": 60, - "middle": 412, - "bottom": 764 - }, - - "1136": { - "small": 282, - "medium": 584, - "large": 622, - "left": 30, - "right": 332, - "top": 59, - "middle": 399, - "bottom": 399 - } - } - return phones -} - -/* - ************************************************************************************ - */ - - - /* - =================================================================================== - */ - -// 网络请求get封装 -async function getJson({ url, headers = {} }, callback = () => {}) { - const request = new Request('') - const defaultHeaders = { - "Accept": "*/*", - "Content-Type": "application/json" - } - - request.url = `https://www.tophub.fun:8888/v2/GetAllInfoGzip?id=${hotID}&page=0` - request.method = 'GET' - request.headers = { - ...headers, - ...defaultHeaders - } - const data = await request.loadJSON() - callback(request.response, data) - return data -} - -// 请求网络图片 -async function fetchImageUrl(imgUrl) { - const req = await new Request(imgUrl) - const img = await req.loadImage() - return img -} - -// 创建组件 -async function createWidget(hotData) { - let w = new ListWidget() - /* - ************************************************************* - */ - - // // 1.自定义颜色背景 - // const customColorBg = new LinearGradient() - // // 背景渐变色 - // customColorBg.colors = [new Color("#29323c"), new Color("#1c1c1c")] - // customColorBg.locations = [0.0, 1.0] - // w.backgroundGradient = customColorBg - - // // 2.自定义图片背景 - // 图片链接 - // const customImgBgUrl = "https://images.unsplash.com/photo-1602408959965-cbde35cfab50?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=900&q=60" - // const imgReq = new Request(customImgBgUrl) - // const customImgBg = await imgReq.loadImage() - // w.backgroundImage=customImgBg - - // 3.下面是设置透明背景 - w.backgroundImage = files.readImage(path) - - // 大标题文字颜色 - const headTitleFontColor = new Color("#FF7F00") - // 列表文字颜色 - const listTitleFontColor = new Color("#E9C2A6") - /* - ************************************************************* - */ - - // 设置大标题 - w.addSpacer(15) - let titleStack = w.addStack() - let title = titleStack.addText(`🔥 ${hotTitle}`) - title.font = Font.boldRoundedSystemFont(17) // 大标题字体样式/大小 - title.textColor = headTitleFontColor // 大标题的颜色 - title.shadowColor = headTitleFontColor // 大标题的阴影颜色 - title.shadowOffset = new Point(1,1) // 阴影偏移 - title.shadowRadius = 1 // 阴影半径 - title.leftAlignText() - w.addSpacer() - - // 列表 - for (let index in hotData) { - let itemStack = w.addStack() - // 标题 - let title = itemStack.addText(`☞ ${hotData[index].Title}`) - title.font = Font.boldRoundedSystemFont(13) // 热搜列表标题字体样式/大小 - title.textColor = listTitleFontColor // 热搜列表标题的颜色 - title.url = hotData[index].Url - title.leftAlignText() - w.addSpacer(5) - } - - // 占位 - let spaceStack = w.addStack() - let space = spaceStack.addText("这是占位用的这是占位用的这是占位用的这是占位用的这是占位用的这是占位用的这是占位用的") - space.font = Font.boldRoundedSystemFont(8) // 热搜列表标题字体样式/大小 - space.textOpacity = 0 - - w.addSpacer() - - Script.setWidget(w) - Script.complete() - - // 直接预览中等大小的小组件 - w.presentMedium() -} \ No newline at end of file diff --git "a/\347\275\221\347\273\234\345\233\276\347\211\207\350\275\256\346\222\255.scriptable.js" "b/\347\275\221\347\273\234\345\233\276\347\211\207\350\275\256\346\222\255.js" similarity index 84% rename from "\347\275\221\347\273\234\345\233\276\347\211\207\350\275\256\346\222\255.scriptable.js" rename to "\347\275\221\347\273\234\345\233\276\347\211\207\350\275\256\346\222\255.js" index 8a0e482..d232dd9 100644 --- "a/\347\275\221\347\273\234\345\233\276\347\211\207\350\275\256\346\222\255.scriptable.js" +++ "b/\347\275\221\347\273\234\345\233\276\347\211\207\350\275\256\346\222\255.js" @@ -1,5 +1,5 @@ //------------------------------------------------ -const env = importModule('Env.js') +const env = importModule('Env-lsp.js') //------------------------------------------------ // 配置区 env.configs.previewSize = "Small" // 预览大小【小:Small,中:Medium,大:Large】 @@ -10,36 +10,39 @@ env.configs.topPadding = 0 // 内容区边距 env.configs.leftPadding = 0 // 内容区边距 env.configs.bottomPadding = 0 // 内容区边距 env.configs.rightPadding = 0 // 内容区边距 +env.configs.refreshInterval = 20 // 刷新间隔,单位分钟,非精准,会有3-5分钟差距 // const imgStyle = env.imgStyle const textStyle = env.textStyle //------------------------------------------------ // 脚本名字 const name = Script.name() +// 组件 +const widget = new ListWidget() +const contentStack = widget.addStack() //------------------------------------------------ //↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓内容区↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ //------------------------------------------------ -const widget = new ListWidget() -const contentStack = widget.addStack() -// 图片链接 +// 图片数组 const imgObjs = [ "https://patchwiki.biligame.com/images/dongsen/a/a2/3f1qchqu7q74dsis7uyz7jfqt6xgo0d.png", "https://patchwiki.biligame.com/images/dongsen/7/7e/awj7kx6aqiuoventjw1w3qu7imv1f9n.png", "https://patchwiki.biligame.com/images/dongsen/0/01/mnuuv9nmyb8q7qv8fuqflzn8ds465zp.png" ] -// 索引值 -const key = parseInt(Math.random() * Object.keys(imgObjs).length).toString() + +// 索引 +const key = parseInt(Math.random() * imgObjs.length).toString() let imgUrl = imgObjs[key] if(imgUrl == undefined) { imgUrl = imgObjs[0] } -log(`图片链接:${imgUrl}`) + let img = await env.getImage(imgUrl) imgStyle.stack = contentStack -imgStyle.width = 138 -imgStyle.height = 138 +imgStyle.width = 150 +imgStyle.height = 150 imgStyle.img = img env.addStyleImg() //------------------------------------------------ @@ -48,4 +51,4 @@ env.addStyleImg() //------------------------------------------------ // 运行脚本、预览 await env.run(name, widget) -//------------------------------------------------ +//------------------------------------------------ \ No newline at end of file