├── src ├── utils │ ├── index.js │ ├── db.js │ └── utools.js ├── assets │ └── logo.png ├── main.js ├── store │ └── index.js ├── vant.js ├── App.vue └── components │ ├── title.vue │ ├── schedule.vue │ ├── list.vue │ └── calendar.vue ├── public ├── icon.png ├── favicon.ico ├── preload.js └── index.html ├── vue.config.js ├── run.sh ├── babel.config.js ├── .gitignore ├── plugin.json ├── README.md └── package.json /src/utils/index.js: -------------------------------------------------------------------------------- 1 | import * as db from './db' 2 | 3 | export default { 4 | ...db 5 | } -------------------------------------------------------------------------------- /public/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xkloveme/utools-calendar/HEAD/public/icon.png -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xkloveme/utools-calendar/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xkloveme/utools-calendar/HEAD/src/assets/logo.png -------------------------------------------------------------------------------- /public/preload.js: -------------------------------------------------------------------------------- 1 | 2 | const shell = require('electron').shell 3 | 4 | window.openExternal = function (url) { 5 | shell.openExternal(url) 6 | } -------------------------------------------------------------------------------- /vue.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | // 根路径 默认使用/ vue cli 3.3+ 弃用 baseUrl 3 | publicPath: './', // 此处改为 './' 即可 4 | productionSourceMap: false, 5 | outputDir: './data/dist' 6 | } -------------------------------------------------------------------------------- /run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | rm -rf data/ 3 | mkdir data 4 | npm run build 5 | # rm -rf data/dist 6 | # cp -r dist/. data 7 | # cp -r public/. data/public 8 | cp -r README.md data 9 | cp -r plugin.json data -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@vue/cli-plugin-babel/preset' 4 | ], 5 | plugins: [ 6 | ['import', { 7 | libraryName: 'vant', 8 | libraryDirectory: 'es', 9 | style: true 10 | }, 'vant'] 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | /data 5 | # local env files 6 | .env.local 7 | .env.*.local 8 | 9 | # Log files 10 | npm-debug.log* 11 | yarn-debug.log* 12 | yarn-error.log* 13 | 14 | # Editor directories and files 15 | .idea 16 | .vscode 17 | *.suo 18 | *.ntvs* 19 | *.njsproj 20 | *.sln 21 | *.sw? 22 | 23 | #Electron-builder output 24 | /dist_electron -------------------------------------------------------------------------------- /plugin.json: -------------------------------------------------------------------------------- 1 | { 2 | "pluginName": "calendar", 3 | "description": "日历", 4 | "version": "0.0.4", 5 | "main": "dist/index.html", 6 | "preload": "dist/preload.js", 7 | "author": "xkloveme", 8 | "homepage": "https://github.com/xkloveme", 9 | "logo": "dist/icon.png", 10 | "features": [ 11 | { 12 | "code": "calendar", 13 | "explain": "日历", 14 | "cmds": ["calendar", "日历", "时间"], 15 | "icon": "dist/icon.png" 16 | } 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | <%= htmlWebpackPlugin.options.title %> 9 | 10 | 11 | 18 |
19 | 20 | 21 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from "vue"; 2 | import App from "./App.vue"; 3 | import Api from "./utils/index"; 4 | import store from "./store"; 5 | import Vant from "./vant.js"; 6 | // import "vuesax/dist/vuesax.min.css"; 7 | 8 | Vue.use(Vant); 9 | Vue.config.productionTip = false; 10 | Vue.prototype.utools = window.utools; 11 | Vue.prototype.$api = Api; 12 | // eslint-disable-next-line no-undef 13 | if (process.env.NODE_ENV === "production") { 14 | window.utools.onPluginReady(() => { 15 | console.log("插件装配完成,已准备好"); 16 | new Vue({ 17 | render: (h) => h(App), 18 | store: store, 19 | }).$mount("#app"); 20 | }); 21 | } else { 22 | new Vue({ 23 | render: (h) => h(App), 24 | store: store, 25 | }).$mount("#app"); 26 | } 27 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 日历 时间 2 | 3 | ![t5FjVs.png](https://s1.ax1x.com/2020/06/09/t5FjVs.png) 4 | 5 | # ⌚️📅 一个简单的日历 6 | 7 | ![image](https://forthebadge.com/images/badges/built-with-love.svg) 8 | 9 | ![image](https://github.com/aleen42/badges/raw/master/src/vue_flat_square.svg?sanitize=true) 10 | ![image](https://github.com/aleen42/badges/raw/master/src/javascript_flat_square.svg?sanitize=true) 11 | 12 | ![UpmMee.png](https://s1.ax1x.com/2020/07/05/UpmMee.png) 13 | ## 地址 14 | 15 | - [项目源码](https://github.com/xkloveme/utools-calendar) 16 | - [反馈](https://github.com/xkloveme/utools-calendar/issues) 17 | 18 | ## 日历插件 19 | 20 | 1. 全平台支持. windows, mac, linux. 21 | 22 | ## 更新日志 23 | 24 | - ### 0.0.3 25 | > - 新增日程 26 | > - UI调整 27 | 28 | - ### 0.0.1 29 | > - 上架应用市场 30 | > - 三剑客之日历,欢迎搜索笔记和日历 31 | 32 | ## 打赏 33 | > 开发不易,您的鼓励会让我走的更远,一分也是情一分也是爱❤️ 34 | ![UpeRIA.jpg](https://s1.ax1x.com/2020/07/05/UpeRIA.jpg) 35 | 36 | ## 关注我 37 | 38 | 觉得不错的话给个`star` 39 | 40 | - [xkloveme](https://github.com/xkloveme) 41 | -------------------------------------------------------------------------------- /src/store/index.js: -------------------------------------------------------------------------------- 1 | import Vue from "vue"; 2 | import Vuex from "vuex"; 3 | import { getApi } from "./../utils/db.js"; 4 | Vue.use(Vuex); 5 | const store = new Vuex.Store({ 6 | state: { 7 | config: { 8 | bg: false, 9 | layout: 1, 10 | width: 600, 11 | height: 450, 12 | background: 1, 13 | dataColor: "FFFFFF", 14 | borderRadius: 5, 15 | language: "zh", // zh en 16 | key: "75f7ef04ec64481cb131ff6621b8c8c1", 17 | }, 18 | }, 19 | mutations: { 20 | SET_CONFIG: (state, config) => { 21 | for (const key in config) { 22 | if (config[key]) { 23 | state.config[key] = config[key]; 24 | } 25 | } 26 | }, 27 | }, 28 | actions: { 29 | // 获取当前状态 30 | getConfig({ commit }, id = "weather") { 31 | return new Promise((resolve, reject) => { 32 | getApi(id) 33 | .then((res) => { 34 | if (res.layout) { 35 | commit("SET_CONFIG", res); 36 | } 37 | resolve(res); 38 | }) 39 | .catch((error) => { 40 | reject(error); 41 | }); 42 | }); 43 | }, 44 | }, 45 | modules: {}, 46 | }); 47 | export default store; 48 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "utools-calendar", 3 | "version": "v1.0.0", 4 | "main": "index.js", 5 | "license": "MIT", 6 | "scripts": { 7 | "dev": "vue-cli-service serve", 8 | "serve": "vue-cli-service serve", 9 | "build": "vue-cli-service build", 10 | "lint": "vue-cli-service lint" 11 | }, 12 | "dependencies": { 13 | "chinese-holidays": "^1.2.1", 14 | "core-js": "^3.6.4", 15 | "dayjs": "^1.8.28", 16 | "vue": "^2.6.11", 17 | "vuex": "^3.4.0" 18 | }, 19 | "devDependencies": { 20 | "@vue/cli-plugin-babel": "~4.3.0", 21 | "@vue/cli-plugin-eslint": "~4.3.0", 22 | "@vue/cli-service": "~4.3.0", 23 | "babel-eslint": "^10.1.0", 24 | "babel-plugin-import": "^1.13.0", 25 | "eslint": "^6.7.2", 26 | "eslint-plugin-vue": "^6.2.2", 27 | "himmas-vue-calendar": "^1.3.3", 28 | "vant": "^2.8.4", 29 | "vue-template-compiler": "^2.6.11" 30 | }, 31 | "eslintConfig": { 32 | "root": true, 33 | "env": { 34 | "node": true 35 | }, 36 | "extends": [ 37 | "plugin:vue/essential", 38 | "eslint:recommended" 39 | ], 40 | "parserOptions": { 41 | "parser": "babel-eslint" 42 | }, 43 | "rules": {} 44 | }, 45 | "browserslist": [ 46 | "> 1%", 47 | "last 2 versions", 48 | "not dead" 49 | ] 50 | } 51 | -------------------------------------------------------------------------------- /src/vant.js: -------------------------------------------------------------------------------- 1 | import { 2 | Button, 3 | // Col, 4 | // Row, 5 | Popup, 6 | // Checkbox, 7 | // CheckboxGroup, 8 | Field, 9 | // Picker, 10 | // RadioGroup, 11 | // Radio, 12 | // Search, 13 | // ActionSheet, 14 | Dialog, 15 | // PullRefresh, 16 | Toast, 17 | // Divider, 18 | // Empty, 19 | List, 20 | // Progress, 21 | NavBar, 22 | // Pagination, 23 | // Tab, 24 | // Tabs, 25 | // Sticky, 26 | // DatetimePicker, 27 | Panel, 28 | Cell, 29 | CellGroup, 30 | Icon, 31 | Calendar, 32 | Form, 33 | Switch, 34 | Tag 35 | // Skeleton, 36 | } from "vant"; 37 | const components = [ 38 | Button, 39 | // Col, 40 | // Row, 41 | Popup, 42 | // Checkbox, 43 | // CheckboxGroup, 44 | Field, 45 | // Picker, 46 | // RadioGroup, 47 | // Radio, 48 | // Search, 49 | // ActionSheet, 50 | Dialog, 51 | // PullRefresh, 52 | Toast, 53 | // Divider, 54 | // Empty, 55 | List, 56 | // Progress, 57 | NavBar, 58 | // Pagination, 59 | // Tab, 60 | // Tabs, 61 | // Sticky, 62 | // DatetimePicker, 63 | Panel, 64 | Cell, 65 | CellGroup, 66 | Icon, 67 | Calendar, 68 | Form, 69 | Switch, 70 | Tag 71 | // Skeleton, 72 | ]; 73 | const install = (Vue) => { 74 | components.forEach((component) => { 75 | Vue.component(component.name, component); 76 | }); 77 | Vue.prototype.$toast = Toast; 78 | }; 79 | if (typeof window !== "undefined" && window.Vue) { 80 | install(window.Vue); 81 | } 82 | export default { install }; 83 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 25 | 26 | 62 | 63 | 86 | -------------------------------------------------------------------------------- /src/components/title.vue: -------------------------------------------------------------------------------- 1 | 56 | 57 | 86 | 87 | -------------------------------------------------------------------------------- /src/utils/db.js: -------------------------------------------------------------------------------- 1 | import utoolsDemo from "./utools.js"; 2 | function createRandomId() { 3 | return ( 4 | new Date().getFullYear() + 5 | "/" + 6 | (new Date().getMonth() + 1) + 7 | "/" + 8 | new Date().getDate() + 9 | "/" + 10 | new Date().getTime() + 11 | "/" + 12 | (Math.random() * 10000000).toString(16).substr(0, 4) + 13 | Math.random() 14 | .toString() 15 | .substr(2, 5) 16 | ); 17 | } 18 | 19 | export const toLocaleString = function(dateTime) { 20 | let cdate = new Date(dateTime); 21 | var year = cdate.getFullYear(); //取得4位数的年份 22 | var month = 23 | cdate.getMonth() + 1 > 9 24 | ? cdate.getMonth() + 1 25 | : "0" + (cdate.getMonth() + 1); //取得日期中的月份,其中0表示1月,11表示12月 26 | var date = cdate.getDate() > 9 ? cdate.getDate() : "0" + cdate.getDate(); //返回日期月份中的天数(1到31) 27 | var hour = cdate.getHours() > 9 ? cdate.getHours() : "0" + cdate.getHours(); //返回日期中的小时数(0到23) 28 | var minute = 29 | cdate.getMinutes() > 9 ? cdate.getMinutes() : "0" + cdate.getMinutes(); //返回日期中的分钟数(0到59) 30 | var second = 31 | cdate.getSeconds() > 9 ? cdate.getSeconds() : "0" + cdate.getSeconds(); //返回日期中的秒数(0到59) 32 | return ( 33 | year + "-" + month + "-" + date + " " + hour + ":" + minute + ":" + second 34 | ); 35 | }; 36 | let utools = window.utools; 37 | if (process.env.NODE_ENV === "production") { 38 | utools = window.utools || utoolsDemo; 39 | } else { 40 | utools = utoolsDemo; 41 | } 42 | // 上传数据更新数据 43 | export const putApi = (data) => { 44 | console.log("上传数据更新数据", { 45 | ...data, 46 | _id: data["id"] || createRandomId(), 47 | }); 48 | return new Promise((resolve, reject) => { 49 | let res = utools.db.put({ 50 | ...data, 51 | _id: data["id"] || createRandomId(), 52 | }); 53 | if (res) { 54 | console.log("🐛:: putApi -> res", res); 55 | resolve(res); 56 | } else { 57 | reject("出错"); 58 | } 59 | }); 60 | }; 61 | 62 | // 获取数据 63 | export const getApi = (id) => { 64 | return new Promise((resolve, reject) => { 65 | let res = utools.db.get(id); 66 | if (res) { 67 | console.log("🐛:: getApi -> res", res); 68 | resolve(res); 69 | } else { 70 | reject("出错"); 71 | } 72 | }); 73 | }; 74 | 75 | // 移除数据 76 | export const removeApi = (id) => { 77 | console.log("🐛:: removeApi -> id", id); 78 | return new Promise((resolve, reject) => { 79 | let res = utools.db.remove(id); 80 | if (res) { 81 | console.log("🐛:: removeApi -> res", res); 82 | resolve(res); 83 | } else { 84 | reject("出错"); 85 | } 86 | }); 87 | }; 88 | 89 | // 批量更新数组 90 | export const bulkDocsApi = (data) => { 91 | return new Promise((resolve, reject) => { 92 | let res = utools.db.bulkDocs(data); 93 | if (res) { 94 | resolve(res); 95 | } else { 96 | reject("出错"); 97 | } 98 | }); 99 | }; 100 | 101 | // 获取所有数据 102 | export const allDocsApi = (data) => { 103 | return new Promise((resolve, reject) => { 104 | let res = utools.db.allDocs(data); 105 | if (res) { 106 | console.log("🐛:: allDocsApi -> res", res); 107 | resolve(res); 108 | } else { 109 | reject("出错"); 110 | } 111 | }); 112 | }; 113 | 114 | // 获取城市 115 | export const getCityApi = (location) => { 116 | return new Promise((resolve, reject) => { 117 | var requestOptions = { 118 | method: "GET", 119 | redirect: "follow", 120 | }; 121 | fetch( 122 | `https://free-api.heweather.net/s6/weather/now?location=${location}&key=7028306c100b4aac98539d549c53cff7`, 123 | requestOptions 124 | ) 125 | .then((response) => response.text()) 126 | .then((result) => { 127 | resolve(result); 128 | }) 129 | .catch((error) => { 130 | reject("出错"); 131 | console.log("error", error); 132 | }); 133 | }); 134 | }; 135 | -------------------------------------------------------------------------------- /src/utils/utools.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @description 文档链接: https://u.tools/docs/developer/api.html 3 | */ 4 | // eslint-disable-next-line no-undef 5 | export default { 6 | // 事件相关API 7 | /** 8 | * @description 当插件装载成功,uTools将会主动调用这个方法(生命周期内仅调用一次) 9 | * @description 注意:uTools 的其他api以及preload.js中定义的方法,都需要在此回调被执行后才可被调用,否则将报错。 10 | * @param cb 回调函数 11 | */ 12 | onPluginReady: "", 13 | 14 | /** 15 | * @description 每当插件从后台进入到前台时,uTools将会主动调用这个方法 16 | * @param cb 回调函数 17 | */ 18 | onPluginEnter: "", 19 | 20 | /** 21 | * @description 每当插件从前台进入到后台时,uTools将会主动调用这个方法 22 | * @param cb 回调函数 23 | */ 24 | onPluginOut: "", 25 | 26 | /** 27 | * @description 用户对插件进行分离操作时,uTools将会主动调用这个方法 28 | * @param cb 回调函数 29 | */ 30 | onPluginDetach: "", 31 | 32 | /** 33 | * @description 当此插件的数据在其他设备上被更改后同步到此设备时,uTools将会主动调用这个方法 34 | * @param cb 回调函数 35 | */ 36 | onDbPull: "", 37 | 38 | // 数据库 api 39 | db: {}, 40 | 41 | // 窗口交互 API 42 | /** 43 | * @description 执行该方法将会隐藏uTools主窗口,包括此时正在主窗口运行的插件,分离的插件不会被隐藏。 44 | */ 45 | hideMainWindow: "", 46 | 47 | /** 48 | * @description 执行该方法将会显示uTools主窗口,包括此时正在主窗口运行的插件。 49 | */ 50 | showMainWindow: "", 51 | 52 | /** 53 | * 执行该方法将会修改插件窗口的高度。 54 | * @param height 窗口的高度 55 | */ 56 | setExpendHeight: "", 57 | 58 | /** 59 | * @description 设置子输入框,进入插件后,原本uTools的搜索条主输入框将会变成子输入框,子输入框可以为插件所使用。 60 | * @param onChange 回调函数 61 | * @param placeholder 自输入框提示 62 | * @param isFocus 是否聚焦 63 | */ 64 | setSubInput: "", 65 | 66 | /** 67 | * @description 移出先前设置的子输入框,在插件切换到其他页面时可以重新设置子输入框为其所用。 68 | */ 69 | removeSubInput: "", 70 | 71 | /** 72 | * @description 直接对子输入框的值进行设置。 73 | * @param val 需要输入的值 74 | */ 75 | setSubInputValue: "", 76 | 77 | /** 78 | * @description 子输入框获得焦点 79 | */ 80 | subInputFocus: "", 81 | 82 | /** 83 | * @description 子输入框获得焦点并选中 84 | */ 85 | subInputSelect: "", 86 | 87 | /** 88 | * @description 子输入框失去焦点,插件获得焦点 89 | */ 90 | subInputBlur: "", 91 | 92 | /** 93 | * @description 执行该方法将会退出当前插件。 94 | */ 95 | outPlugin: "", 96 | 97 | /** 98 | * 该方法可以携带数据,跳转到另一个插件进行处理,如果用户未安装对应的插件,uTools会弹出提醒并引导进入插件中心下载。 99 | * @param cmd 插件关键词 100 | * @param content 101 | */ 102 | redirect: "", 103 | 104 | // 动态增减 105 | /** 106 | * @description 返回本插件所有动态增加的功能。 107 | */ 108 | getFeatures: "", 109 | 110 | /** 111 | * @description 为本插件动态新增某个功能。 112 | * @param feature feature 113 | */ 114 | setFeature: "", 115 | 116 | /** 117 | * @description 动态删除本插件的某个功能。 118 | * @param code feature.code 119 | */ 120 | removeFeature: "", 121 | 122 | // 其他 123 | /** 124 | * @description 执行该方法将会弹出一个系统通知。 125 | * @param body 显示的内容 126 | * @param code 用户点击系统通知时,uTools将会使用此`code`进入插件 127 | * @param silent 是否播放声音 128 | */ 129 | showNotification: "", 130 | 131 | /** 132 | * @description 该方法只适用于在macOS下执行,用于判断uTools是否拥有辅助权限,如果没有可以调用API方法requestPrivilege请求 133 | */ 134 | isHadPrivilege: "", 135 | 136 | /** 137 | * @description 该方法只适用于在macOS下执行,该方法调用后会弹出窗口向用户申请辅助权限。 138 | */ 139 | requestPrivilege: "", 140 | 141 | /** 142 | * @description 你可以通过名称请求以下的路径 143 | * home 用户的 home 文件夹(主目录) 144 | * appData 当前用户的应用数据文件夹,默认对应: 145 | * %APPDATA% Windows 中 146 | * ~/Library/Application Support macOS 中 147 | * userData 储存你应用程序设置文件的文件夹,默认是 appData 文件夹附加应用的名称 148 | * temp 临时文件夹 149 | * exe 当前的可执行文件 150 | * desktop 当前用户的桌面文件夹 151 | * documents 用户文档目录的路径 152 | * downloads 用户下载目录的路径 153 | * music 用户音乐目录的路径 154 | * pictures 用户图片目录的路径 155 | * videos 用户视频目录的路径 156 | * logs 应用程序的日志文件夹 157 | * @param name 158 | */ 159 | getPath: "", 160 | /** 161 | * @description 复制文件或文件夹到剪贴板 162 | * @param paths 163 | */ 164 | copyFile: "", 165 | /** 166 | * @description 复制图片到剪贴板 167 | * @param buffer 168 | */ 169 | copyImage: "", 170 | /** 171 | * @description 屏幕取色 172 | * @param cb 173 | */ 174 | screenColorPick: "", 175 | /** 176 | * @description 获取当前浏览器URL (呼出uTools前的活动窗口) 177 | */ 178 | getCurrentBrowserUrl: "", 179 | /** 180 | * @description 获取本地机器唯一ID,可以根据此值区分同一用户的不同设备 181 | */ 182 | getLocalId: "", 183 | 184 | /** 185 | * robotjs是一个优秀的自动化库,可以实现控制鼠标、键盘、获取屏幕信息等功能,可以实现很多自动化操作。 186 | */ 187 | robot: "", 188 | }; 189 | -------------------------------------------------------------------------------- /src/components/schedule.vue: -------------------------------------------------------------------------------- 1 | 86 | -------------------------------------------------------------------------------- /src/components/list.vue: -------------------------------------------------------------------------------- 1 | 52 | 53 | 159 | 160 | 173 | -------------------------------------------------------------------------------- /src/components/calendar.vue: -------------------------------------------------------------------------------- 1 | 55 | 56 | 346 | --------------------------------------------------------------------------------