├── 日历运行效果.gif ├── 项目运行效果.gif ├── App.vue ├── static └── zsy-calendar │ └── arrow.png ├── .gitignore ├── main.js ├── pages.json ├── index.html ├── .hbuilderx └── launch.json ├── pages └── index │ └── calendar.vue ├── uni.scss ├── components └── zsy-calendar │ ├── js │ └── utils.js │ ├── dateBox.vue │ ├── zsy-calendar.vue │ └── zsy-calendar v1.0.vue ├── 使用说明.md └── manifest.json /日历运行效果.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhengsenyi/zsy-calendar/HEAD/日历运行效果.gif -------------------------------------------------------------------------------- /项目运行效果.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhengsenyi/zsy-calendar/HEAD/项目运行效果.gif -------------------------------------------------------------------------------- /App.vue: -------------------------------------------------------------------------------- 1 | 3 | 4 | 7 | -------------------------------------------------------------------------------- /static/zsy-calendar/arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhengsenyi/zsy-calendar/HEAD/static/zsy-calendar/arrow.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | unpackage/release 4 | dist/ 5 | 6 | # local env files 7 | .env.local 8 | .env.*.local 9 | 10 | # Log files 11 | npm-debug.log* 12 | yarn-debug.log* 13 | yarn-error.log* 14 | 15 | # Editor directories and files 16 | .project 17 | .idea 18 | .vscode 19 | *.suo 20 | *.ntvs* 21 | *.njsproj 22 | *.sln 23 | *.sw* 24 | *.zip 25 | -------------------------------------------------------------------------------- /main.js: -------------------------------------------------------------------------------- 1 | import App from './App' 2 | 3 | // #ifndef VUE3 4 | import Vue from 'vue' 5 | Vue.config.productionTip = false 6 | App.mpType = 'app' 7 | const app = new Vue({ 8 | ...App 9 | }) 10 | app.$mount() 11 | // #endif 12 | 13 | // #ifdef VUE3 14 | import { createSSRApp } from 'vue' 15 | export function createApp() { 16 | const app = createSSRApp(App) 17 | return { 18 | app 19 | } 20 | } 21 | // #endif -------------------------------------------------------------------------------- /pages.json: -------------------------------------------------------------------------------- 1 | { 2 | "pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages 3 | { 4 | "path": "pages/index/calendar", 5 | "style": { 6 | "navigationBarTitleText": "仿钉钉打卡日历" 7 | } 8 | } 9 | ], 10 | "globalStyle": { 11 | "navigationBarTextStyle": "black", 12 | "navigationBarTitleText": "uni-app", 13 | "navigationBarBackgroundColor": "#F8F8F8", 14 | "backgroundColor": "#F8F8F8" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /.hbuilderx/launch.json: -------------------------------------------------------------------------------- 1 | { // launch.json 配置了启动调试时相关设置,configurations下节点名称可为 app-plus/h5/mp-weixin/mp-baidu/mp-alipay/mp-qq/mp-toutiao/mp-360/ 2 | // launchtype项可配置值为local或remote, local代表前端连本地云函数,remote代表前端连云端云函数 3 | "version": "0.0", 4 | "configurations": [{ 5 | "app-plus" : 6 | { 7 | "launchtype" : "local" 8 | }, 9 | "default" : 10 | { 11 | "launchtype" : "local" 12 | }, 13 | "h5" : 14 | { 15 | "launchtype" : "local" 16 | }, 17 | "mp-weixin" : 18 | { 19 | "launchtype" : "local" 20 | }, 21 | "type" : "uniCloud" 22 | } 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /pages/index/calendar.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 25 | 26 | 34 | -------------------------------------------------------------------------------- /uni.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * 这里是uni-app内置的常用样式变量 3 | * 4 | * uni-app 官方扩展插件及插件市场(https://ext.dcloud.net.cn)上很多三方插件均使用了这些样式变量 5 | * 如果你是插件开发者,建议你使用scss预处理,并在插件代码中直接使用这些变量(无需 import 这个文件),方便用户通过搭积木的方式开发整体风格一致的App 6 | * 7 | */ 8 | 9 | /** 10 | * 如果你是App开发者(插件使用者),你可以通过修改这些变量来定制自己的插件主题,实现自定义主题功能 11 | * 12 | * 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件 13 | */ 14 | 15 | /* 颜色变量 */ 16 | 17 | /* 行为相关颜色 */ 18 | $uni-color-primary: #007aff; 19 | $uni-color-success: #4cd964; 20 | $uni-color-warning: #f0ad4e; 21 | $uni-color-error: #dd524d; 22 | 23 | /* 文字基本颜色 */ 24 | $uni-text-color:#333;//基本色 25 | $uni-text-color-inverse:#fff;//反色 26 | $uni-text-color-grey:#999;//辅助灰色,如加载更多的提示信息 27 | $uni-text-color-placeholder: #808080; 28 | $uni-text-color-disable:#c0c0c0; 29 | 30 | /* 背景颜色 */ 31 | $uni-bg-color:#ffffff; 32 | $uni-bg-color-grey:#f8f8f8; 33 | $uni-bg-color-hover:#f1f1f1;//点击状态颜色 34 | $uni-bg-color-mask:rgba(0, 0, 0, 0.4);//遮罩颜色 35 | 36 | /* 边框颜色 */ 37 | $uni-border-color:#c8c7cc; 38 | 39 | /* 尺寸变量 */ 40 | 41 | /* 文字尺寸 */ 42 | $uni-font-size-sm:12px; 43 | $uni-font-size-base:14px; 44 | $uni-font-size-lg:16; 45 | 46 | /* 图片尺寸 */ 47 | $uni-img-size-sm:20px; 48 | $uni-img-size-base:26px; 49 | $uni-img-size-lg:40px; 50 | 51 | /* Border Radius */ 52 | $uni-border-radius-sm: 2px; 53 | $uni-border-radius-base: 3px; 54 | $uni-border-radius-lg: 6px; 55 | $uni-border-radius-circle: 50%; 56 | 57 | /* 水平间距 */ 58 | $uni-spacing-row-sm: 5px; 59 | $uni-spacing-row-base: 10px; 60 | $uni-spacing-row-lg: 15px; 61 | 62 | /* 垂直间距 */ 63 | $uni-spacing-col-sm: 4px; 64 | $uni-spacing-col-base: 8px; 65 | $uni-spacing-col-lg: 12px; 66 | 67 | /* 透明度 */ 68 | $uni-opacity-disabled: 0.3; // 组件禁用态的透明度 69 | 70 | /* 文章场景相关 */ 71 | $uni-color-title: #2C405A; // 文章标题颜色 72 | $uni-font-size-title:20px; 73 | $uni-color-subtitle: #555555; // 二级标题颜色 74 | $uni-font-size-subtitle:26px; 75 | $uni-color-paragraph: #3F536E; // 文章段落颜色 76 | $uni-font-size-paragraph:15px; 77 | -------------------------------------------------------------------------------- /components/zsy-calendar/js/utils.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 时间格式化 3 | * @param {String} time 4 | * @param {String} cFormat 5 | */ 6 | export function parseTime(time, cFormat) { 7 | if (arguments.length === 0) { 8 | return null 9 | } 10 | if (!time) return '' 11 | /* 修复IOS系统上面的时间不兼容*/ 12 | if (time.toString().indexOf('-') > 0) { 13 | time = time.replace(/-/g, '/') 14 | } 15 | const format = cFormat || '{y}-{m}-{d} {h}:{i}:{s}' 16 | let date 17 | if (typeof time === 'object') { 18 | date = time 19 | } else { 20 | if ((typeof time === 'string') && (/^[0-9]+$/.test(time))) { 21 | time = parseInt(time) 22 | } 23 | if ((typeof time === 'number') && (time.toString().length === 10)) { 24 | time = time * 1000 25 | } 26 | date = new Date(time) 27 | } 28 | const formatObj = { 29 | y: date.getFullYear(), 30 | m: date.getMonth() + 1, 31 | d: date.getDate(), 32 | h: date.getHours(), 33 | i: date.getMinutes(), 34 | s: date.getSeconds(), 35 | a: date.getDay() 36 | } 37 | const time_str = format.replace(/{([ymdhisa])+}/g, (result, key) => { 38 | const value = formatObj[key] 39 | // Note: getDay() returns 0 on Sunday 40 | if (key === 'a') { 41 | return ['日', '一', '二', '三', '四', '五', '六'][value] 42 | } 43 | return value.toString().padStart(2, '0') 44 | }) 45 | return time_str 46 | } 47 | 48 | /** 49 | * This is just a simple version of deep copy 50 | * Has a lot of edge cases bug 51 | * If you want to use a perfect deep copy, use lodash's _.cloneDeep 52 | * @param {Object} source 53 | * @returns {Object} 54 | */ 55 | export function deepClone(source) { 56 | if (!source && typeof source !== 'object') { 57 | throw new Error('error arguments', 'deepClone') 58 | } 59 | const targetObj = Object.prototype.toString.call(source) === "[object Array]" ? [] : {} 60 | Object.keys(source).forEach(keys => { 61 | if (source[keys] && typeof source[keys] === 'object') { 62 | targetObj[keys] = deepClone(source[keys]) 63 | } else { 64 | targetObj[keys] = source[keys] 65 | } 66 | }) 67 | return targetObj 68 | } -------------------------------------------------------------------------------- /使用说明.md: -------------------------------------------------------------------------------- 1 | # 仿钉钉日历组件 支持月与周两种模式的左右滑动切换 支持在APP、小程序、H5运行 2 | 3 | ```javascript 4 | 12 | 13 | 28 | 36 | // Vue 37 | ``` 38 | *** 39 | ##### 通用日历,可标记,支持自定义主题颜色,列高度的自定义 40 | 41 | 1. 日历展开模式显示的是月历,上月份跟下月份的日期呈灰色显示,点击对应的日期可滑动到相应的月份并且高亮显示; 42 | 2. 日历收缩时显示的是周历,可以进行周之间滑动的切换,且点击上月份的日期时自动切换到上月,具体请看效果演示图或自行尝试; 43 | 3. 因本人工作项目需求暂没有做日期选择器,但我在里面增加了一个goToDate方法可以切换到某一天,并且加了一个回到今天的功能,如果你们有这个需求可以自行二次开发; 44 | 4. 该日历组件共使用了两个swiper组件分别对应月历跟周历,使用三个swiper-item并且显示相邻的数据,即可以达到无限循环的效果又可以节省性能,并且当组件滑动完毕后才进行数据的预生成,避免滑动过程中计算数据造成页面不流畅卡顿; 45 | 5. 项目源码注释清晰且不难理解,可自行根据实际需求进行二次开发; 46 | 6. 本插件本人还未进行深度测试,可能还有些隐藏BUG暂未发现,若有小伙伴发现可进行评论留言; 47 | 7. 本人刚入行时间也不长,可能一些思路大佬看了会觉得比较简单低级,如果大佬有更好的思路,欢迎在评论区指出留言,我后续也会出一篇关于源码解析的文章; 48 | *** 49 | ##### 组件属性说明: 50 | |属性名|类型|默认值|说明| 51 | |:--:|:--:|:--:|:--:| 52 | |duration|Number|300|动画时长| 53 | |cellHeight|Number|75|日历每一列的高度,单位为rpx| 54 | |dateActiveColor|String|#FE6601|日期选中颜色| 55 | |sundayIndex|Number|6|星期天所在位置,范围为0~6| 56 | |mode|String|'open'|日历模式 'open'为月历 'close'为周历| 57 | |changeSetDefault|Boolean|true|月历切换是否默认选中1号| 58 | |defaultSelectedDate|String Null|null|选中日期,默认为当天| 59 | *** 60 | ##### 方法说明: 61 | |属性名|说明| 62 | |:--:|:--:| 63 | |goToDate|切换到某一天日期 格式 YYYY-MM 或者 YYYY-MM-DD| 64 | *** 65 | ##### 事件说明: 66 | |属性名|说明| 67 | |:--:|:--:| 68 | |change|日历选中日期改变事件回调| 69 | *** 70 | ##### 插件实际运行效果预览: 71 | ![avatar](https://vkceyugu.cdn.bspapp.com/VKCEYUGU-ffcb1110-1b39-410a-b1f6-c2e57fd34cd4/738e9c5d-cedf-4e91-afbe-ffe8d91ae174.gif) 72 | ##### 项目实际运行效果预览: 73 | ![avatar](https://vkceyugu.cdn.bspapp.com/VKCEYUGU-ffcb1110-1b39-410a-b1f6-c2e57fd34cd4/f3f83e4d-689a-4937-a3c8-c1e5a0b49252.gif) 74 | ##### 线上预览地址: 75 | [点击访问](https://static-ffcb1110-1b39-410a-b1f6-c2e57fd34cd4.bspapp.com/zsy-calendar) -------------------------------------------------------------------------------- /components/zsy-calendar/dateBox.vue: -------------------------------------------------------------------------------- 1 | 27 | 28 | 68 | 69 | 114 | -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name" : "仿钉钉打卡日历", 3 | "appid" : "__UNI__AD5A07B", 4 | "description" : "", 5 | "versionName" : "1.0.0", 6 | "versionCode" : "100", 7 | "transformPx" : false, 8 | /* 5+App特有相关 */ 9 | "app-plus" : { 10 | "usingComponents" : true, 11 | "nvueStyleCompiler" : "uni-app", 12 | "compilerVersion" : 3, 13 | "splashscreen" : { 14 | "alwaysShowBeforeRender" : true, 15 | "waiting" : true, 16 | "autoclose" : true, 17 | "delay" : 0 18 | }, 19 | /* 模块配置 */ 20 | "modules" : {}, 21 | /* 应用发布信息 */ 22 | "distribute" : { 23 | /* android打包配置 */ 24 | "android" : { 25 | "permissions" : [ 26 | "", 27 | "", 28 | "", 29 | "", 30 | "", 31 | "", 32 | "", 33 | "", 34 | "", 35 | "", 36 | "", 37 | "", 38 | "", 39 | "", 40 | "" 41 | ] 42 | }, 43 | /* ios打包配置 */ 44 | "ios" : {}, 45 | /* SDK配置 */ 46 | "sdkConfigs" : {} 47 | } 48 | }, 49 | /* 快应用特有相关 */ 50 | "quickapp" : {}, 51 | /* 小程序特有相关 */ 52 | "mp-weixin" : { 53 | "appid" : "", 54 | "setting" : { 55 | "urlCheck" : false 56 | }, 57 | "usingComponents" : true 58 | }, 59 | "mp-alipay" : { 60 | "usingComponents" : true 61 | }, 62 | "mp-baidu" : { 63 | "usingComponents" : true 64 | }, 65 | "mp-toutiao" : { 66 | "usingComponents" : true 67 | }, 68 | "uniStatistics" : { 69 | "enable" : false 70 | }, 71 | "vueVersion" : "2", 72 | "h5" : { 73 | "router" : { 74 | "mode" : "hash", 75 | "base" : "/zsy-calendar" 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /components/zsy-calendar/zsy-calendar.vue: -------------------------------------------------------------------------------- 1 | 49 | 50 | 427 | 428 | 512 | -------------------------------------------------------------------------------- /components/zsy-calendar/zsy-calendar v1.0.vue: -------------------------------------------------------------------------------- 1 | 71 | 72 | 558 | 559 | 642 | --------------------------------------------------------------------------------