├── static └── .gitkeep ├── .eslintignore ├── test ├── unit │ ├── setup.js │ ├── .eslintrc │ ├── specs │ │ └── HelloWorld.spec.js │ └── jest.conf.js └── e2e │ ├── specs │ └── test.js │ ├── custom-assertions │ └── elementCount.js │ ├── nightwatch.conf.js │ └── runner.js ├── config ├── prod.env.js ├── test.env.js ├── dev.env.js └── index.js ├── src ├── assets │ ├── logo.png │ ├── one.png │ └── range.png ├── components │ ├── calendar │ │ ├── calendar_arrow_left.png │ │ ├── calendar_arrow_right.png │ │ ├── calendar.result.js │ │ ├── show.day.js │ │ └── index.vue │ └── HelloWorld.vue ├── plugs │ ├── holiday.data.js │ └── chinese-calendar.js ├── router │ └── index.js ├── main.js └── App.vue ├── .editorconfig ├── .gitignore ├── .postcssrc.js ├── index.html ├── .babelrc ├── README.md ├── .eslintrc.js └── package.json /static/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | /build/ 2 | /config/ 3 | /dist/ 4 | /*.js 5 | /test/unit/coverage/ 6 | -------------------------------------------------------------------------------- /test/unit/setup.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | 3 | Vue.config.productionTip = false 4 | -------------------------------------------------------------------------------- /config/prod.env.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | module.exports = { 3 | NODE_ENV: '"production"' 4 | } 5 | -------------------------------------------------------------------------------- /src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WangYanup/calendar-vue-mpvue/HEAD/src/assets/logo.png -------------------------------------------------------------------------------- /src/assets/one.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WangYanup/calendar-vue-mpvue/HEAD/src/assets/one.png -------------------------------------------------------------------------------- /src/assets/range.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WangYanup/calendar-vue-mpvue/HEAD/src/assets/range.png -------------------------------------------------------------------------------- /test/unit/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "jest": true 4 | }, 5 | "globals": { 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/components/calendar/calendar_arrow_left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WangYanup/calendar-vue-mpvue/HEAD/src/components/calendar/calendar_arrow_left.png -------------------------------------------------------------------------------- /src/components/calendar/calendar_arrow_right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WangYanup/calendar-vue-mpvue/HEAD/src/components/calendar/calendar_arrow_right.png -------------------------------------------------------------------------------- /config/test.env.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const merge = require('webpack-merge') 3 | const devEnv = require('./dev.env') 4 | 5 | module.exports = merge(devEnv, { 6 | NODE_ENV: '"testing"' 7 | }) 8 | -------------------------------------------------------------------------------- /config/dev.env.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const merge = require('webpack-merge') 3 | const prodEnv = require('./prod.env') 4 | 5 | module.exports = merge(prodEnv, { 6 | NODE_ENV: '"development"' 7 | }) 8 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | /dist/ 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | /test/unit/coverage/ 8 | /test/e2e/reports/ 9 | selenium-debug.log 10 | 11 | # Editor directories and files 12 | .idea 13 | .vscode 14 | *.suo 15 | *.ntvs* 16 | *.njsproj 17 | *.sln 18 | -------------------------------------------------------------------------------- /.postcssrc.js: -------------------------------------------------------------------------------- 1 | // https://github.com/michael-ciniawsky/postcss-load-config 2 | 3 | module.exports = { 4 | "plugins": { 5 | "postcss-import": {}, 6 | "postcss-url": {}, 7 | // to edit target browsers: use "browserslist" field in package.json 8 | "autoprefixer": {} 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | test-vue 7 | 8 | 9 |
10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/plugs/holiday.data.js: -------------------------------------------------------------------------------- 1 | // 可以自由设置假期日期,对应日期会显示“休” 2 | const Holiday = { 3 | '2019': { 4 | '10': [29, 30] 5 | } 6 | } 7 | 8 | let constHolidayData = () => { 9 | let now = new Date() 10 | Holiday[now.getFullYear()][now.getMonth() + 1] = [1, 3, 5, 10, 15] 11 | } 12 | constHolidayData() 13 | 14 | export default Holiday 15 | -------------------------------------------------------------------------------- /src/router/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Router from 'vue-router' 3 | import HelloWorld from '@/components/HelloWorld' 4 | 5 | Vue.use(Router) 6 | 7 | export default new Router({ 8 | routes: [ 9 | { 10 | path: '/', 11 | name: 'HelloWorld', 12 | component: HelloWorld 13 | } 14 | ] 15 | }) 16 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | // The Vue build version to load with the `import` command 2 | // (runtime-only or standalone) has been set in webpack.base.conf with an alias. 3 | import Vue from 'vue' 4 | import App from './App' 5 | import router from './router' 6 | 7 | Vue.config.productionTip = false 8 | 9 | /* eslint-disable no-new */ 10 | new Vue({ 11 | el: '#app', 12 | router, 13 | components: { App }, 14 | template: '' 15 | }) 16 | -------------------------------------------------------------------------------- /test/unit/specs/HelloWorld.spec.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import HelloWorld from '@/components/HelloWorld' 3 | 4 | describe('HelloWorld.vue', () => { 5 | it('should render correct contents', () => { 6 | const Constructor = Vue.extend(HelloWorld) 7 | const vm = new Constructor().$mount() 8 | expect(vm.$el.querySelector('.hello h1').textContent) 9 | .toEqual('Welcome to Your Vue.js App') 10 | }) 11 | }) 12 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | ["env", { 4 | "modules": false, 5 | "targets": { 6 | "browsers": ["> 1%", "last 2 versions", "not ie <= 8"] 7 | } 8 | }], 9 | "stage-2" 10 | ], 11 | "plugins": ["transform-vue-jsx", "transform-runtime"], 12 | "env": { 13 | "test": { 14 | "presets": ["env", "stage-2"], 15 | "plugins": ["transform-vue-jsx", "transform-es2015-modules-commonjs", "dynamic-import-node"] 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 13 | 14 | 24 | -------------------------------------------------------------------------------- /test/e2e/specs/test.js: -------------------------------------------------------------------------------- 1 | // For authoring Nightwatch tests, see 2 | // http://nightwatchjs.org/guide#usage 3 | 4 | module.exports = { 5 | 'default e2e tests': function (browser) { 6 | // automatically uses dev Server port from /config.index.js 7 | // default: http://localhost:8080 8 | // see nightwatch.conf.js 9 | const devServer = browser.globals.devServerURL 10 | 11 | browser 12 | .url(devServer) 13 | .waitForElementVisible('#app', 5000) 14 | .assert.elementPresent('.hello') 15 | .assert.containsText('h1', 'Welcome to Your Vue.js App') 16 | .assert.elementCount('img', 1) 17 | .end() 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # calendar-vue-mpvue 2 | 3 | > vue 和 mpvue 通用的移动设备组件 4 | 5 | 文件路径: src/components/calendar.vue 6 | 7 | ## 功能 8 | ``` bash 9 | 1.支持农历和节假日(农历1900-2100) 10 | 2.支持左右滑动切换,和点击箭头切换 11 | 3.点击‘重置’按钮,回到当前日期 12 | 4.点击‘取消’按钮和灰色背景隐藏组件 13 | 5.支持特殊日期标记圆点 14 | 6.假期显示,已修改为props传参 【原:需要在plugs/holida.data.js手动添加数据】 15 | 7.支持日期范围选择 16 | ``` 17 | 18 | 截图: 19 | ![单个日期选择](https://github.com/WangYanup/calendar-vue-mpvue/blob/master/src/assets/one.png) 20 | ![范围日期选择](https://github.com/WangYanup/calendar-vue-mpvue/blob/master/src/assets/range.png) 21 | 22 | ## 项目构建 23 | ``` bash 24 | # install dependencies 25 | npm install 26 | 27 | # serve with hot reload at localhost:8080 28 | npm run dev 29 | ``` 30 | ## 更新描述 31 | ``` bash 32 | 本次更新的内容对整体进行了优化,所以和上一个版本有些不同,但是使用方式会更加简单 33 | ``` 34 | -------------------------------------------------------------------------------- /test/unit/jest.conf.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | 3 | module.exports = { 4 | rootDir: path.resolve(__dirname, '../../'), 5 | moduleFileExtensions: [ 6 | 'js', 7 | 'json', 8 | 'vue' 9 | ], 10 | moduleNameMapper: { 11 | '^@/(.*)$': '/src/$1' 12 | }, 13 | transform: { 14 | '^.+\\.js$': '/node_modules/babel-jest', 15 | '.*\\.(vue)$': '/node_modules/vue-jest' 16 | }, 17 | testPathIgnorePatterns: [ 18 | '/test/e2e' 19 | ], 20 | snapshotSerializers: ['/node_modules/jest-serializer-vue'], 21 | setupFiles: ['/test/unit/setup'], 22 | mapCoverage: true, 23 | coverageDirectory: '/test/unit/coverage', 24 | collectCoverageFrom: [ 25 | 'src/**/*.{js,vue}', 26 | '!src/main.js', 27 | '!src/router/index.js', 28 | '!**/node_modules/**' 29 | ] 30 | } 31 | -------------------------------------------------------------------------------- /test/e2e/custom-assertions/elementCount.js: -------------------------------------------------------------------------------- 1 | // A custom Nightwatch assertion. 2 | // The assertion name is the filename. 3 | // Example usage: 4 | // 5 | // browser.assert.elementCount(selector, count) 6 | // 7 | // For more information on custom assertions see: 8 | // http://nightwatchjs.org/guide#writing-custom-assertions 9 | 10 | exports.assertion = function (selector, count) { 11 | this.message = 'Testing if element <' + selector + '> has count: ' + count 12 | this.expected = count 13 | this.pass = function (val) { 14 | return val === this.expected 15 | } 16 | this.value = function (res) { 17 | return res.value 18 | } 19 | this.command = function (cb) { 20 | var self = this 21 | return this.api.execute(function (selector) { 22 | return document.querySelectorAll(selector).length 23 | }, [selector], function (res) { 24 | cb.call(self, res) 25 | }) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | // https://eslint.org/docs/user-guide/configuring 2 | 3 | module.exports = { 4 | root: true, 5 | parserOptions: { 6 | parser: 'babel-eslint' 7 | }, 8 | env: { 9 | browser: true, 10 | }, 11 | extends: [ 12 | // https://github.com/vuejs/eslint-plugin-vue#priority-a-essential-error-prevention 13 | // consider switching to `plugin:vue/strongly-recommended` or `plugin:vue/recommended` for stricter rules. 14 | 'plugin:vue/essential', 15 | // https://github.com/standard/standard/blob/master/docs/RULES-en.md 16 | 'standard' 17 | ], 18 | // required to lint *.vue files 19 | plugins: [ 20 | 'vue' 21 | ], 22 | // add your custom rules here 23 | rules: { 24 | // allow async-await 25 | 'generator-star-spacing': 'off', 26 | // allow debugger during development 27 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off' 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/components/calendar/calendar.result.js: -------------------------------------------------------------------------------- 1 | class CalendarResultDate { 2 | /** 3 | 4 | * @param {String} params 2019-11-10 5 | 6 | */ 7 | constructor ({id}) { 8 | this.id = id || 'default' 9 | } 10 | 11 | setForDate (params) { 12 | if (!this.startDate) { 13 | this.setStartTime(params) 14 | return 15 | } 16 | if (this.getLocalString(params.id) > this.getLocalString(this.startDate)) { 17 | this.endDate = params.id 18 | } else { 19 | this.setStartTime(params) 20 | } 21 | } 22 | 23 | setStartTime (params) { 24 | this.startDate = params.id 25 | } 26 | 27 | getLocalString (date) { 28 | return new Date(date).getTime() 29 | } 30 | 31 | get resetResult () { 32 | this.startDate = undefined 33 | this.endDate = undefined 34 | return this.resultVal 35 | } 36 | 37 | get resultVal () { 38 | return { 39 | startDate: this.startDate, 40 | endDate: this.endDate, 41 | id: this.id 42 | } 43 | } 44 | } 45 | 46 | export default CalendarResultDate 47 | -------------------------------------------------------------------------------- /test/e2e/nightwatch.conf.js: -------------------------------------------------------------------------------- 1 | require('babel-register') 2 | var config = require('../../config') 3 | 4 | // http://nightwatchjs.org/gettingstarted#settings-file 5 | module.exports = { 6 | src_folders: ['test/e2e/specs'], 7 | output_folder: 'test/e2e/reports', 8 | custom_assertions_path: ['test/e2e/custom-assertions'], 9 | 10 | selenium: { 11 | start_process: true, 12 | server_path: require('selenium-server').path, 13 | host: '127.0.0.1', 14 | port: 4444, 15 | cli_args: { 16 | 'webdriver.chrome.driver': require('chromedriver').path 17 | } 18 | }, 19 | 20 | test_settings: { 21 | default: { 22 | selenium_port: 4444, 23 | selenium_host: 'localhost', 24 | silent: true, 25 | globals: { 26 | devServerURL: 'http://localhost:' + (process.env.PORT || config.dev.port) 27 | } 28 | }, 29 | 30 | chrome: { 31 | desiredCapabilities: { 32 | browserName: 'chrome', 33 | javascriptEnabled: true, 34 | acceptSslCerts: true 35 | } 36 | }, 37 | 38 | firefox: { 39 | desiredCapabilities: { 40 | browserName: 'firefox', 41 | javascriptEnabled: true, 42 | acceptSslCerts: true 43 | } 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /test/e2e/runner.js: -------------------------------------------------------------------------------- 1 | // 1. start the dev server using production config 2 | process.env.NODE_ENV = 'testing' 3 | 4 | const webpack = require('webpack') 5 | const DevServer = require('webpack-dev-server') 6 | 7 | const webpackConfig = require('../../build/webpack.prod.conf') 8 | const devConfigPromise = require('../../build/webpack.dev.conf') 9 | 10 | let server 11 | 12 | devConfigPromise.then(devConfig => { 13 | const devServerOptions = devConfig.devServer 14 | const compiler = webpack(webpackConfig) 15 | server = new DevServer(compiler, devServerOptions) 16 | const port = devServerOptions.port 17 | const host = devServerOptions.host 18 | return server.listen(port, host) 19 | }) 20 | .then(() => { 21 | // 2. run the nightwatch test suite against it 22 | // to run in additional browsers: 23 | // 1. add an entry in test/e2e/nightwatch.conf.js under "test_settings" 24 | // 2. add it to the --env flag below 25 | // or override the environment flag, for example: `npm run e2e -- --env chrome,firefox` 26 | // For more information on Nightwatch's config file, see 27 | // http://nightwatchjs.org/guide#settings-file 28 | let opts = process.argv.slice(2) 29 | if (opts.indexOf('--config') === -1) { 30 | opts = opts.concat(['--config', 'test/e2e/nightwatch.conf.js']) 31 | } 32 | if (opts.indexOf('--env') === -1) { 33 | opts = opts.concat(['--env', 'chrome']) 34 | } 35 | 36 | const spawn = require('cross-spawn') 37 | const runner = spawn('./node_modules/.bin/nightwatch', opts, { stdio: 'inherit' }) 38 | 39 | runner.on('exit', function (code) { 40 | server.close() 41 | process.exit(code) 42 | }) 43 | 44 | runner.on('error', function (err) { 45 | server.close() 46 | throw err 47 | }) 48 | }) 49 | -------------------------------------------------------------------------------- /src/components/HelloWorld.vue: -------------------------------------------------------------------------------- 1 | 27 | 28 | 76 | 77 | 78 | 94 | -------------------------------------------------------------------------------- /config/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | // Template version: 1.3.1 3 | // see http://vuejs-templates.github.io/webpack for documentation. 4 | 5 | const path = require('path') 6 | 7 | module.exports = { 8 | dev: { 9 | 10 | // Paths 11 | assetsSubDirectory: 'static', 12 | assetsPublicPath: '/', 13 | proxyTable: {}, 14 | 15 | // Various Dev Server settings 16 | host: 'localhost', // can be overwritten by process.env.HOST 17 | port: 8080, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined 18 | autoOpenBrowser: false, 19 | errorOverlay: true, 20 | notifyOnErrors: true, 21 | poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions- 22 | 23 | // Use Eslint Loader? 24 | // If true, your code will be linted during bundling and 25 | // linting errors and warnings will be shown in the console. 26 | useEslint: true, 27 | // If true, eslint errors and warnings will also be shown in the error overlay 28 | // in the browser. 29 | showEslintErrorsInOverlay: false, 30 | 31 | /** 32 | * Source Maps 33 | */ 34 | 35 | // https://webpack.js.org/configuration/devtool/#development 36 | devtool: 'cheap-module-eval-source-map', 37 | 38 | // If you have problems debugging vue-files in devtools, 39 | // set this to false - it *may* help 40 | // https://vue-loader.vuejs.org/en/options.html#cachebusting 41 | cacheBusting: true, 42 | 43 | cssSourceMap: true 44 | }, 45 | 46 | build: { 47 | // Template for index.html 48 | index: path.resolve(__dirname, '../dist/index.html'), 49 | 50 | // Paths 51 | assetsRoot: path.resolve(__dirname, '../dist'), 52 | assetsSubDirectory: 'static', 53 | assetsPublicPath: '/', 54 | 55 | /** 56 | * Source Maps 57 | */ 58 | 59 | productionSourceMap: true, 60 | // https://webpack.js.org/configuration/devtool/#production 61 | devtool: '#source-map', 62 | 63 | // Gzip off by default as many popular static hosts such as 64 | // Surge or Netlify already gzip all static assets for you. 65 | // Before setting to `true`, make sure to: 66 | // npm install --save-dev compression-webpack-plugin 67 | productionGzip: false, 68 | productionGzipExtensions: ['js', 'css'], 69 | 70 | // Run the build command with an extra argument to 71 | // View the bundle analyzer report after build finishes: 72 | // `npm run build --report` 73 | // Set to `true` or `false` to always turn it on or off 74 | bundleAnalyzerReport: process.env.npm_config_report 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "test-vue", 3 | "version": "1.0.0", 4 | "description": "A Vue.js project", 5 | "author": "wangyan ", 6 | "private": true, 7 | "scripts": { 8 | "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js", 9 | "start": "npm run dev", 10 | "unit": "jest --config test/unit/jest.conf.js --coverage", 11 | "e2e": "node test/e2e/runner.js", 12 | "test": "npm run unit && npm run e2e", 13 | "lint": "eslint --ext .js,.vue src test/unit test/e2e/specs", 14 | "build": "node build/build.js" 15 | }, 16 | "dependencies": { 17 | "vue": "^2.5.2", 18 | "vue-router": "^3.0.1", 19 | "sass-loader": "^7.1.0", 20 | "node-sass": "^4.10.0" 21 | }, 22 | "devDependencies": { 23 | "autoprefixer": "^7.1.2", 24 | "babel-core": "^6.22.1", 25 | "babel-eslint": "^8.2.1", 26 | "babel-helper-vue-jsx-merge-props": "^2.0.3", 27 | "babel-jest": "^21.0.2", 28 | "babel-loader": "^7.1.1", 29 | "babel-plugin-dynamic-import-node": "^1.2.0", 30 | "babel-plugin-syntax-jsx": "^6.18.0", 31 | "babel-plugin-transform-es2015-modules-commonjs": "^6.26.0", 32 | "babel-plugin-transform-runtime": "^6.22.0", 33 | "babel-plugin-transform-vue-jsx": "^3.5.0", 34 | "babel-preset-env": "^1.3.2", 35 | "babel-preset-stage-2": "^6.22.0", 36 | "babel-register": "^6.22.0", 37 | "chalk": "^2.0.1", 38 | "chromedriver": "^2.27.2", 39 | "copy-webpack-plugin": "^4.0.1", 40 | "cross-spawn": "^5.0.1", 41 | "css-loader": "^0.28.0", 42 | "eslint": "^4.15.0", 43 | "eslint-config-standard": "^10.2.1", 44 | "eslint-friendly-formatter": "^3.0.0", 45 | "eslint-loader": "^1.7.1", 46 | "eslint-plugin-import": "^2.7.0", 47 | "eslint-plugin-node": "^5.2.0", 48 | "eslint-plugin-promise": "^3.4.0", 49 | "eslint-plugin-standard": "^3.0.1", 50 | "eslint-plugin-vue": "^4.0.0", 51 | "extract-text-webpack-plugin": "^3.0.0", 52 | "file-loader": "^1.1.4", 53 | "friendly-errors-webpack-plugin": "^1.6.1", 54 | "html-webpack-plugin": "^2.30.1", 55 | "jest": "^22.0.4", 56 | "jest-serializer-vue": "^0.3.0", 57 | "nightwatch": "^0.9.12", 58 | "node-notifier": "^5.1.2", 59 | "node-sass": "^4.10.0", 60 | "optimize-css-assets-webpack-plugin": "^3.2.0", 61 | "ora": "^1.2.0", 62 | "portfinder": "^1.0.13", 63 | "postcss-import": "^11.0.0", 64 | "postcss-loader": "^2.0.8", 65 | "postcss-url": "^7.2.1", 66 | "rimraf": "^2.6.0", 67 | "sass-loader": "^7.1.0", 68 | "selenium-server": "^3.0.1", 69 | "semver": "^5.3.0", 70 | "shelljs": "^0.7.6", 71 | "uglifyjs-webpack-plugin": "^1.1.1", 72 | "url-loader": "^0.5.8", 73 | "vue-jest": "^1.0.2", 74 | "vue-loader": "^13.3.0", 75 | "vue-style-loader": "^3.0.1", 76 | "vue-template-compiler": "^2.5.2", 77 | "webpack": "^3.6.0", 78 | "webpack-bundle-analyzer": "^2.9.0", 79 | "webpack-dev-server": "^2.9.1", 80 | "webpack-merge": "^4.1.0" 81 | }, 82 | "engines": { 83 | "node": ">= 6.0.0", 84 | "npm": ">= 3.0.0" 85 | }, 86 | "browserslist": [ 87 | "> 1%", 88 | "last 2 versions", 89 | "not ie <= 8" 90 | ] 91 | } 92 | -------------------------------------------------------------------------------- /src/components/calendar/show.day.js: -------------------------------------------------------------------------------- 1 | import Calendar from '@/plugs/chinese-calendar' 2 | 3 | let showDayGolbal = {} 4 | export const setCalendarGlobalParams = (objects) => { 5 | showDayGolbal = Object.assign(showDayGolbal, objects) 6 | } 7 | 8 | class ShowDayObjectList { 9 | constructor ({year, month}) { 10 | this.year = year 11 | this.month = month 12 | this.dayData = [] 13 | this.row = [] 14 | this.init() 15 | } 16 | 17 | init () { 18 | for (let index = 1; index < 42; index++) { // 7 * 5line 19 | let day = new Date(this.year, this.month - 1, index) 20 | this.row = new ShowDayRow({ 21 | day, 22 | index, 23 | row: this.row, 24 | inputMonth: this.month 25 | }).getResult() 26 | 27 | this.setRowData({index}) 28 | } 29 | } 30 | 31 | setRowData ({index}) { 32 | if (this.row.length % 7 !== 0) { 33 | return 34 | } 35 | // 第六行如果第一个数据是空,则不添加到结果中 36 | if (index > 35 && this.row[0] === '') { 37 | this.row = [] 38 | return 39 | } 40 | 41 | this.dayData.push(this.row) 42 | this.row = [] 43 | } 44 | 45 | getVal () { 46 | return this.dayData 47 | } 48 | } 49 | 50 | class ShowDayRow { 51 | constructor ({day, index, row, inputMonth}) { 52 | this.result = row 53 | this.monthDay = day.getDate() 54 | this.resultMonth = day.getMonth() + 1 55 | this.resultYear = day.getFullYear() 56 | this.weekDay = this.setWeekDay(day) 57 | this.obj = { 58 | text: null, 59 | id: `${this.resultYear}-${this.resultMonth}-${this.monthDay}`, 60 | timestamp: day.getTime(), 61 | number: null, 62 | disabled: false, 63 | haveFlag: false 64 | } 65 | 66 | this.setHaveFlag() 67 | this.setHoliday() 68 | this.setLunarCalendar() 69 | this.setMinDateStatus() 70 | this.setMaxDateStatus() 71 | this.constMonthData({index, inputMonth}) 72 | } 73 | 74 | setWeekDay (day) { 75 | if (day.getDay() === 0) { 76 | return 7 77 | } 78 | return day.getDay() 79 | } 80 | 81 | // 判断是否突出显示当天日期,例如当天有活动 82 | setHaveFlag () { 83 | if (!showDayGolbal.flagArr) { 84 | return 85 | } 86 | showDayGolbal.flagArr.some(item => { 87 | if (parseInt(item.day) === this.monthDay) { 88 | this.obj.haveFlag = true 89 | return true 90 | } 91 | }) 92 | } 93 | 94 | // 判断是否为假期 95 | setHoliday () { 96 | if (!showDayGolbal.holidayData || !showDayGolbal.holidayData[this.resultYear] || !showDayGolbal.holidayData[this.resultYear][this.resultMonth]) { 97 | return 98 | } 99 | 100 | let holidayArr = showDayGolbal.holidayData[this.resultYear][this.resultMonth] 101 | if (holidayArr.length === 0) { 102 | return 103 | } 104 | 105 | if (holidayArr.indexOf(this.monthDay) > -1) { 106 | this.obj.holiday = true 107 | } 108 | } 109 | 110 | setLunarCalendar () { 111 | // 农历显示 112 | let calendarTextObj = Calendar.solar2lunar(this.resultYear, this.resultMonth, this.monthDay) 113 | // 有节日 114 | if (calendarTextObj.festival.length > 0) { 115 | this.obj.text = calendarTextObj.festival[0] 116 | return 117 | } 118 | 119 | if (calendarTextObj.IDayCn === '初一') { 120 | this.obj.text = calendarTextObj.IMonthCn 121 | return 122 | } 123 | 124 | // 无节日 125 | this.obj.text = calendarTextObj.IDayCn 126 | } 127 | 128 | setMinDateStatus () { 129 | // 限制选取最小日期 130 | if (!showDayGolbal.limitMinDate) { 131 | return 132 | } 133 | let targetDate = this.getTimestamp({y: this.resultYear, m: this.resultMonth, d: this.monthDay}) 134 | let limitDate = this.getTimestamp({y: showDayGolbal.limitMinDate.y, m: showDayGolbal.limitMinDate.m, d: showDayGolbal.limitMinDate.d}) 135 | if (targetDate < limitDate) { 136 | this.obj.disabled = true 137 | } 138 | } 139 | 140 | setMaxDateStatus () { 141 | // 限制选取最大日期 142 | if (!showDayGolbal.limitMaxDate) { 143 | return 144 | } 145 | let targetDate = this.getTimestamp({y: this.resultYear, m: this.resultMonth, d: this.monthDay}) 146 | let limitDate = this.getTimestamp({y: showDayGolbal.limitMaxDate.y, m: showDayGolbal.limitMaxDate.m, d: showDayGolbal.limitMaxDate.d}) 147 | if (targetDate > limitDate) { 148 | this.obj.disabled = true 149 | } 150 | } 151 | 152 | getTimestamp ({y, m, d}) { 153 | return new Date(y, m - 1, d).getTime() 154 | } 155 | 156 | constMonthData ({index, inputMonth}) { 157 | // 构造本月的日历数据 158 | if (this.resultMonth !== inputMonth) { 159 | this.result.push('') 160 | return 161 | } 162 | 163 | if (index !== 1) { 164 | this.obj.number = this.monthDay 165 | this.result.push(this.obj) 166 | return 167 | } 168 | 169 | this.setMonthFirstDay() 170 | } 171 | 172 | // 如果第一天的日期 173 | // @d 用于控制第一天显示的星期 (d = 0 开头为星期日 / d = 1 开头为星期一) 174 | setMonthFirstDay () { 175 | for (let d = 1; d < this.weekDay; d++) { 176 | this.result.push('') 177 | } 178 | 179 | this.obj.number = this.monthDay 180 | this.result.push(this.obj) 181 | } 182 | 183 | getResult () { 184 | return this.result 185 | } 186 | } 187 | 188 | export default ShowDayObjectList 189 | -------------------------------------------------------------------------------- /src/components/calendar/index.vue: -------------------------------------------------------------------------------- 1 | 50 | 326 | 511 | -------------------------------------------------------------------------------- /src/plugs/chinese-calendar.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @1900-2100区间内的公历、农历互转 3 | * @charset UTF-8 4 | * @公历转农历:Calendar.solar2lunar(1987,11,01); //[you can ignore params of prefix 0] 5 | */ 6 | const calendar = { 7 | 8 | /** 9 | * 农历1900-2100的润大小信息表 10 | * @Array Of Property 11 | * @return Hex 12 | */ 13 | lunarInfo: [0x04bd8, 0x04ae0, 0x0a570, 0x054d5, 0x0d260, 0x0d950, 0x16554, 0x056a0, 0x09ad0, 0x055d2, //1900-1909 14 | 0x04ae0, 0x0a5b6, 0x0a4d0, 0x0d250, 0x1d255, 0x0b540, 0x0d6a0, 0x0ada2, 0x095b0, 0x14977, //1910-1919 15 | 0x04970, 0x0a4b0, 0x0b4b5, 0x06a50, 0x06d40, 0x1ab54, 0x02b60, 0x09570, 0x052f2, 0x04970, //1920-1929 16 | 0x06566, 0x0d4a0, 0x0ea50, 0x06e95, 0x05ad0, 0x02b60, 0x186e3, 0x092e0, 0x1c8d7, 0x0c950, //1930-1939 17 | 0x0d4a0, 0x1d8a6, 0x0b550, 0x056a0, 0x1a5b4, 0x025d0, 0x092d0, 0x0d2b2, 0x0a950, 0x0b557, //1940-1949 18 | 0x06ca0, 0x0b550, 0x15355, 0x04da0, 0x0a5b0, 0x14573, 0x052b0, 0x0a9a8, 0x0e950, 0x06aa0, //1950-1959 19 | 0x0aea6, 0x0ab50, 0x04b60, 0x0aae4, 0x0a570, 0x05260, 0x0f263, 0x0d950, 0x05b57, 0x056a0, //1960-1969 20 | 0x096d0, 0x04dd5, 0x04ad0, 0x0a4d0, 0x0d4d4, 0x0d250, 0x0d558, 0x0b540, 0x0b6a0, 0x195a6, //1970-1979 21 | 0x095b0, 0x049b0, 0x0a974, 0x0a4b0, 0x0b27a, 0x06a50, 0x06d40, 0x0af46, 0x0ab60, 0x09570, //1980-1989 22 | 0x04af5, 0x04970, 0x064b0, 0x074a3, 0x0ea50, 0x06b58, 0x055c0, 0x0ab60, 0x096d5, 0x092e0, //1990-1999 23 | 0x0c960, 0x0d954, 0x0d4a0, 0x0da50, 0x07552, 0x056a0, 0x0abb7, 0x025d0, 0x092d0, 0x0cab5, //2000-2009 24 | 0x0a950, 0x0b4a0, 0x0baa4, 0x0ad50, 0x055d9, 0x04ba0, 0x0a5b0, 0x15176, 0x052b0, 0x0a930, //2010-2019 25 | 0x07954, 0x06aa0, 0x0ad50, 0x05b52, 0x04b60, 0x0a6e6, 0x0a4e0, 0x0d260, 0x0ea65, 0x0d530, //2020-2029 26 | 0x05aa0, 0x076a3, 0x096d0, 0x04afb, 0x04ad0, 0x0a4d0, 0x1d0b6, 0x0d250, 0x0d520, 0x0dd45, //2030-2039 27 | 0x0b5a0, 0x056d0, 0x055b2, 0x049b0, 0x0a577, 0x0a4b0, 0x0aa50, 0x1b255, 0x06d20, 0x0ada0, //2040-2049 28 | /**Add By JJonline@JJonline.Cn**/ 29 | 0x14b63, 0x09370, 0x049f8, 0x04970, 0x064b0, 0x168a6, 0x0ea50, 0x06b20, 0x1a6c4, 0x0aae0, //2050-2059 30 | 0x0a2e0, 0x0d2e3, 0x0c960, 0x0d557, 0x0d4a0, 0x0da50, 0x05d55, 0x056a0, 0x0a6d0, 0x055d4, //2060-2069 31 | 0x052d0, 0x0a9b8, 0x0a950, 0x0b4a0, 0x0b6a6, 0x0ad50, 0x055a0, 0x0aba4, 0x0a5b0, 0x052b0, //2070-2079 32 | 0x0b273, 0x06930, 0x07337, 0x06aa0, 0x0ad50, 0x14b55, 0x04b60, 0x0a570, 0x054e4, 0x0d160, //2080-2089 33 | 0x0e968, 0x0d520, 0x0daa0, 0x16aa6, 0x056d0, 0x04ae0, 0x0a9d4, 0x0a2d0, 0x0d150, 0x0f252, //2090-2099 34 | 0x0d520 35 | ], //2100 36 | 37 | /** 38 | * 公历每个月份的天数普通表 39 | * @Array Of Property 40 | * @return Number 41 | */ 42 | solarMonth: [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31], 43 | 44 | /** 45 | * 天干地支之天干速查表 46 | * @Array Of Property trans["甲","乙","丙","丁","戊","己","庚","辛","壬","癸"] 47 | * @return Cn string 48 | */ 49 | Gan: ["\u7532", "\u4e59", "\u4e19", "\u4e01", "\u620a", "\u5df1", "\u5e9a", "\u8f9b", "\u58ec", "\u7678"], 50 | 51 | /** 52 | * 天干地支之地支速查表 53 | * @Array Of Property 54 | * @trans["子","丑","寅","卯","辰","巳","午","未","申","酉","戌","亥"] 55 | * @return Cn string 56 | */ 57 | Zhi: ["\u5b50", "\u4e11", "\u5bc5", "\u536f", "\u8fb0", "\u5df3", "\u5348", "\u672a", "\u7533", "\u9149", "\u620c", "\u4ea5"], 58 | 59 | /** 60 | * 天干地支之地支速查表<=>生肖 61 | * @Array Of Property 62 | * @trans["鼠","牛","虎","兔","龙","蛇","马","羊","猴","鸡","狗","猪"] 63 | * @return Cn string 64 | */ 65 | Animals: ["\u9f20", "\u725b", "\u864e", "\u5154", "\u9f99", "\u86c7", "\u9a6c", "\u7f8a", "\u7334", "\u9e21", "\u72d7", "\u732a"], 66 | 67 | /** 68 | * 24节气速查表 69 | * @Array Of Property 70 | * @trans["小寒","大寒","立春","雨水","惊蛰","春分","清明","谷雨","立夏","小满","芒种","夏至","小暑","大暑","立秋","处暑","白露","秋分","寒露","霜降","立冬","小雪","大雪","冬至"] 71 | * @return Cn string 72 | */ 73 | solarTerm: ["\u5c0f\u5bd2", "\u5927\u5bd2", "\u7acb\u6625", "\u96e8\u6c34", "\u60ca\u86f0", "\u6625\u5206", "\u6e05\u660e", "\u8c37\u96e8", "\u7acb\u590f", "\u5c0f\u6ee1", "\u8292\u79cd", "\u590f\u81f3", "\u5c0f\u6691", "\u5927\u6691", "\u7acb\u79cb", "\u5904\u6691", "\u767d\u9732", "\u79cb\u5206", "\u5bd2\u9732", "\u971c\u964d", "\u7acb\u51ac", "\u5c0f\u96ea", "\u5927\u96ea", "\u51ac\u81f3"], 74 | 75 | /** 76 | * 1900-2100各年的24节气日期速查表 77 | * @Array Of Property 78 | * @return 0x string For splice 79 | */ 80 | sTermInfo: ['9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e', '97bcf97c3598082c95f8c965cc920f', 81 | '97bd0b06bdb0722c965ce1cfcc920f', 'b027097bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e', 82 | '97bcf97c359801ec95f8c965cc920f', '97bd0b06bdb0722c965ce1cfcc920f', 'b027097bd097c36b0b6fc9274c91aa', 83 | '97b6b97bd19801ec9210c965cc920e', '97bcf97c359801ec95f8c965cc920f', '97bd0b06bdb0722c965ce1cfcc920f', 84 | 'b027097bd097c36b0b6fc9274c91aa', '9778397bd19801ec9210c965cc920e', '97b6b97bd19801ec95f8c965cc920f', 85 | '97bd09801d98082c95f8e1cfcc920f', '97bd097bd097c36b0b6fc9210c8dc2', '9778397bd197c36c9210c9274c91aa', 86 | '97b6b97bd19801ec95f8c965cc920e', '97bd09801d98082c95f8e1cfcc920f', '97bd097bd097c36b0b6fc9210c8dc2', 87 | '9778397bd097c36c9210c9274c91aa', '97b6b97bd19801ec95f8c965cc920e', '97bcf97c3598082c95f8e1cfcc920f', 88 | '97bd097bd097c36b0b6fc9210c8dc2', '9778397bd097c36c9210c9274c91aa', '97b6b97bd19801ec9210c965cc920e', 89 | '97bcf97c3598082c95f8c965cc920f', '97bd097bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa', 90 | '97b6b97bd19801ec9210c965cc920e', '97bcf97c3598082c95f8c965cc920f', '97bd097bd097c35b0b6fc920fb0722', 91 | '9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e', '97bcf97c359801ec95f8c965cc920f', 92 | '97bd097bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e', 93 | '97bcf97c359801ec95f8c965cc920f', '97bd097bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa', 94 | '97b6b97bd19801ec9210c965cc920e', '97bcf97c359801ec95f8c965cc920f', '97bd097bd07f595b0b6fc920fb0722', 95 | '9778397bd097c36b0b6fc9210c8dc2', '9778397bd19801ec9210c9274c920e', '97b6b97bd19801ec95f8c965cc920f', 96 | '97bd07f5307f595b0b0bc920fb0722', '7f0e397bd097c36b0b6fc9210c8dc2', '9778397bd097c36c9210c9274c920e', 97 | '97b6b97bd19801ec95f8c965cc920f', '97bd07f5307f595b0b0bc920fb0722', '7f0e397bd097c36b0b6fc9210c8dc2', 98 | '9778397bd097c36c9210c9274c91aa', '97b6b97bd19801ec9210c965cc920e', '97bd07f1487f595b0b0bc920fb0722', 99 | '7f0e397bd097c36b0b6fc9210c8dc2', '9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e', 100 | '97bcf7f1487f595b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa', 101 | '97b6b97bd19801ec9210c965cc920e', '97bcf7f1487f595b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722', 102 | '9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e', '97bcf7f1487f531b0b0bb0b6fb0722', 103 | '7f0e397bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e', 104 | '97bcf7f1487f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa', 105 | '97b6b97bd19801ec9210c9274c920e', '97bcf7f0e47f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722', 106 | '9778397bd097c36b0b6fc9210c91aa', '97b6b97bd197c36c9210c9274c920e', '97bcf7f0e47f531b0b0bb0b6fb0722', 107 | '7f0e397bd07f595b0b0bc920fb0722', '9778397bd097c36b0b6fc9210c8dc2', '9778397bd097c36c9210c9274c920e', 108 | '97b6b7f0e47f531b0723b0b6fb0722', '7f0e37f5307f595b0b0bc920fb0722', '7f0e397bd097c36b0b6fc9210c8dc2', 109 | '9778397bd097c36b0b70c9274c91aa', '97b6b7f0e47f531b0723b0b6fb0721', '7f0e37f1487f595b0b0bb0b6fb0722', 110 | '7f0e397bd097c35b0b6fc9210c8dc2', '9778397bd097c36b0b6fc9274c91aa', '97b6b7f0e47f531b0723b0b6fb0721', 111 | '7f0e27f1487f595b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa', 112 | '97b6b7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722', 113 | '9778397bd097c36b0b6fc9274c91aa', '97b6b7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722', 114 | '7f0e397bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa', '97b6b7f0e47f531b0723b0b6fb0721', 115 | '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722', '9778397bd097c36b0b6fc9274c91aa', 116 | '97b6b7f0e47f531b0723b0787b0721', '7f0e27f0e47f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722', 117 | '9778397bd097c36b0b6fc9210c91aa', '97b6b7f0e47f149b0723b0787b0721', '7f0e27f0e47f531b0723b0b6fb0722', 118 | '7f0e397bd07f595b0b0bc920fb0722', '9778397bd097c36b0b6fc9210c8dc2', '977837f0e37f149b0723b0787b0721', 119 | '7f07e7f0e47f531b0723b0b6fb0722', '7f0e37f5307f595b0b0bc920fb0722', '7f0e397bd097c35b0b6fc9210c8dc2', 120 | '977837f0e37f14998082b0787b0721', '7f07e7f0e47f531b0723b0b6fb0721', '7f0e37f1487f595b0b0bb0b6fb0722', 121 | '7f0e397bd097c35b0b6fc9210c8dc2', '977837f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721', 122 | '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722', '977837f0e37f14998082b0787b06bd', 123 | '7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722', 124 | '977837f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722', 125 | '7f0e397bd07f595b0b0bc920fb0722', '977837f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721', 126 | '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722', '977837f0e37f14998082b0787b06bd', 127 | '7f07e7f0e47f149b0723b0787b0721', '7f0e27f0e47f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722', 128 | '977837f0e37f14998082b0723b06bd', '7f07e7f0e37f149b0723b0787b0721', '7f0e27f0e47f531b0723b0b6fb0722', 129 | '7f0e397bd07f595b0b0bc920fb0722', '977837f0e37f14898082b0723b02d5', '7ec967f0e37f14998082b0787b0721', 130 | '7f07e7f0e47f531b0723b0b6fb0722', '7f0e37f1487f595b0b0bb0b6fb0722', '7f0e37f0e37f14898082b0723b02d5', 131 | '7ec967f0e37f14998082b0787b0721', '7f07e7f0e47f531b0723b0b6fb0722', '7f0e37f1487f531b0b0bb0b6fb0722', 132 | '7f0e37f0e37f14898082b0723b02d5', '7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721', 133 | '7f0e37f1487f531b0b0bb0b6fb0722', '7f0e37f0e37f14898082b072297c35', '7ec967f0e37f14998082b0787b06bd', 134 | '7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e37f0e37f14898082b072297c35', 135 | '7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722', 136 | '7f0e37f0e366aa89801eb072297c35', '7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f149b0723b0787b0721', 137 | '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e37f0e366aa89801eb072297c35', '7ec967f0e37f14998082b0723b06bd', 138 | '7f07e7f0e47f149b0723b0787b0721', '7f0e27f0e47f531b0723b0b6fb0722', '7f0e37f0e366aa89801eb072297c35', 139 | '7ec967f0e37f14998082b0723b06bd', '7f07e7f0e37f14998083b0787b0721', '7f0e27f0e47f531b0723b0b6fb0722', 140 | '7f0e37f0e366aa89801eb072297c35', '7ec967f0e37f14898082b0723b02d5', '7f07e7f0e37f14998082b0787b0721', 141 | '7f07e7f0e47f531b0723b0b6fb0722', '7f0e36665b66aa89801e9808297c35', '665f67f0e37f14898082b0723b02d5', 142 | '7ec967f0e37f14998082b0787b0721', '7f07e7f0e47f531b0723b0b6fb0722', '7f0e36665b66a449801e9808297c35', 143 | '665f67f0e37f14898082b0723b02d5', '7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721', 144 | '7f0e36665b66a449801e9808297c35', '665f67f0e37f14898082b072297c35', '7ec967f0e37f14998082b0787b06bd', 145 | '7f07e7f0e47f531b0723b0b6fb0721', '7f0e26665b66a449801e9808297c35', '665f67f0e37f1489801eb072297c35', 146 | '7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722' 147 | ], 148 | 149 | /** 150 | * 数字转中文速查表 151 | * @Array Of Property 152 | * @trans ['日','一','二','三','四','五','六','七','八','九','十'] 153 | * @return Cn string 154 | */ 155 | nStr1: ["\u65e5", "\u4e00", "\u4e8c", "\u4e09", "\u56db", "\u4e94", "\u516d", "\u4e03", "\u516b", "\u4e5d", "\u5341"], 156 | 157 | /** 158 | * 日期转农历称呼速查表 159 | * @Array Of Property 160 | * @trans ['初','十','廿','卅'] 161 | * @return Cn string 162 | */ 163 | nStr2: ["\u521d", "\u5341", "\u5eff", "\u5345"], 164 | 165 | /** 166 | * 月份转农历称呼速查表 167 | * @Array Of Property 168 | * @trans ['正','一','二','三','四','五','六','七','八','九','十','冬','腊'] 169 | * @return Cn string 170 | */ 171 | nStr3: ["\u6b63", "\u4e8c", "\u4e09", "\u56db", "\u4e94", "\u516d", "\u4e03", "\u516b", "\u4e5d", "\u5341", "\u51ac", "\u814a"], 172 | 173 | /** 174 | * 返回农历y年一整年的总天数 175 | * @param lunar Year 176 | * @return Number 177 | * @eg:var count = calendar.lYearDays(1987) ;//count=387 178 | */ 179 | lYearDays: function (y) { 180 | var i, sum = 348; 181 | for (i = 0x8000; i > 0x8; i >>= 1) { 182 | sum += (calendar.lunarInfo[y - 1900] & i) ? 1 : 0; 183 | } 184 | return (sum + calendar.leapDays(y)); 185 | }, 186 | 187 | /** 188 | * 返回农历y年闰月是哪个月;若y年没有闰月 则返回0 189 | * @param lunar Year 190 | * @return Number (0-12) 191 | * @eg:var leapMonth = calendar.leapMonth(1987) ;//leapMonth=6 192 | */ 193 | leapMonth: function (y) { //闰字编码 \u95f0 194 | return (calendar.lunarInfo[y - 1900] & 0xf); 195 | }, 196 | 197 | /** 198 | * 返回农历y年闰月的天数 若该年没有闰月则返回0 199 | * @param lunar Year 200 | * @return Number (0、29、30) 201 | * @eg:var leapMonthDay = calendar.leapDays(1987) ;//leapMonthDay=29 202 | */ 203 | leapDays: function (y) { 204 | if (calendar.leapMonth(y)) { 205 | return ((calendar.lunarInfo[y - 1900] & 0x10000) ? 30 : 29); 206 | } 207 | return (0); 208 | }, 209 | 210 | /** 211 | * 返回农历y年m月(非闰月)的总天数,计算m为闰月时的天数请使用leapDays方法 212 | * @param lunar Year 213 | * @return Number (-1、29、30) 214 | * @eg:var MonthDay = calendar.monthDays(1987,9) ;//MonthDay=29 215 | */ 216 | monthDays: function (y, m) { 217 | if (m > 12 || m < 1) { 218 | return -1 219 | } //月份参数从1至12,参数错误返回-1 220 | return ((calendar.lunarInfo[y - 1900] & (0x10000 >> m)) ? 30 : 29); 221 | }, 222 | 223 | /** 224 | * 返回公历(!)y年m月的天数 225 | * @param solar Year 226 | * @return Number (-1、28、29、30、31) 227 | * @eg:var solarMonthDay = calendar.leapDays(1987) ;//solarMonthDay=30 228 | */ 229 | solarDays: function (y, m) { 230 | if (m > 12 || m < 1) { 231 | return -1 232 | } //若参数错误 返回-1 233 | var ms = m - 1; 234 | if (ms == 1) { //2月份的闰平规律测算后确认返回28或29 235 | return (((y % 4 == 0) && (y % 100 != 0) || (y % 400 == 0)) ? 29 : 28); 236 | } else { 237 | return (calendar.solarMonth[ms]); 238 | } 239 | }, 240 | 241 | /** 242 | * 农历年份转换为干支纪年 243 | * @param lYear 农历年的年份数 244 | * @return Cn string 245 | */ 246 | toGanZhiYear: function (lYear) { 247 | var ganKey = (lYear - 3) % 10; 248 | var zhiKey = (lYear - 3) % 12; 249 | if (ganKey == 0) ganKey = 10; //如果余数为0则为最后一个天干 250 | if (zhiKey == 0) zhiKey = 12; //如果余数为0则为最后一个地支 251 | return calendar.Gan[ganKey - 1] + calendar.Zhi[zhiKey - 1]; 252 | 253 | }, 254 | 255 | /** 256 | * 公历月、日判断所属星座 257 | * @param cMonth [description] 258 | * @param cDay [description] 259 | * @return Cn string 260 | */ 261 | toAstro: function (cMonth, cDay) { 262 | var s = "\u9b54\u7faf\u6c34\u74f6\u53cc\u9c7c\u767d\u7f8a\u91d1\u725b\u53cc\u5b50\u5de8\u87f9\u72ee\u5b50\u5904\u5973\u5929\u79e4\u5929\u874e\u5c04\u624b\u9b54\u7faf"; 263 | var arr = [20, 19, 21, 21, 21, 22, 23, 23, 23, 23, 22, 22]; 264 | return s.substr(cMonth * 2 - (cDay < arr[cMonth - 1] ? 2 : 0), 2) + "\u5ea7"; //座 265 | }, 266 | 267 | /** 268 | * 传入offset偏移量返回干支 269 | * @param offset 相对甲子的偏移量 270 | * @return Cn string 271 | */ 272 | toGanZhi: function (offset) { 273 | return calendar.Gan[offset % 10] + calendar.Zhi[offset % 12]; 274 | }, 275 | 276 | /** 277 | * 传入公历(!)y年获得该年第n个节气的公历日期 278 | * @param y公历年(1900-2100);n二十四节气中的第几个节气(1~24);从n=1(小寒)算起 279 | * @return day Number 280 | * @eg:var _24 = calendar.getTerm(1987,3) ;//_24=4;意即1987年2月4日立春 281 | */ 282 | getTerm: function (y, n) { 283 | if (y < 1900 || y > 2100) { 284 | return -1; 285 | } 286 | if (n < 1 || n > 24) { 287 | return -1; 288 | } 289 | var _table = calendar.sTermInfo[y - 1900]; 290 | var _info = [ 291 | parseInt('0x' + _table.substr(0, 5)).toString(), 292 | parseInt('0x' + _table.substr(5, 5)).toString(), 293 | parseInt('0x' + _table.substr(10, 5)).toString(), 294 | parseInt('0x' + _table.substr(15, 5)).toString(), 295 | parseInt('0x' + _table.substr(20, 5)).toString(), 296 | parseInt('0x' + _table.substr(25, 5)).toString() 297 | ]; 298 | var _calday = [ 299 | _info[0].substr(0, 1), 300 | _info[0].substr(1, 2), 301 | _info[0].substr(3, 1), 302 | _info[0].substr(4, 2), 303 | 304 | _info[1].substr(0, 1), 305 | _info[1].substr(1, 2), 306 | _info[1].substr(3, 1), 307 | _info[1].substr(4, 2), 308 | 309 | _info[2].substr(0, 1), 310 | _info[2].substr(1, 2), 311 | _info[2].substr(3, 1), 312 | _info[2].substr(4, 2), 313 | 314 | _info[3].substr(0, 1), 315 | _info[3].substr(1, 2), 316 | _info[3].substr(3, 1), 317 | _info[3].substr(4, 2), 318 | 319 | _info[4].substr(0, 1), 320 | _info[4].substr(1, 2), 321 | _info[4].substr(3, 1), 322 | _info[4].substr(4, 2), 323 | 324 | _info[5].substr(0, 1), 325 | _info[5].substr(1, 2), 326 | _info[5].substr(3, 1), 327 | _info[5].substr(4, 2), 328 | ]; 329 | return parseInt(_calday[n - 1]); 330 | }, 331 | 332 | /** 333 | * 传入农历数字月份返回汉语通俗表示法 334 | * @param lunar month 335 | * @return Cn string 336 | * @eg:var cnMonth = calendar.toChinaMonth(12) ;//cnMonth='腊月' 337 | */ 338 | toChinaMonth: function (m) { // 月 => \u6708 339 | if (m > 12 || m < 1) { 340 | return -1 341 | } //若参数错误 返回-1 342 | var s = calendar.nStr3[m - 1]; 343 | s += "\u6708"; //加上月字 344 | return s; 345 | }, 346 | 347 | /** 348 | * 传入年份月份返回第n个星期日的日期数字 349 | * @param y 年份 350 | * @param m 月份 351 | * @param n 第几个星期日 ( 5>n>0的数字 一个月一般就4个星期日,最多5个) 352 | * @return 日期数字;3 = getSunday(2017,9,1); 九月的第一个星期日是3号;超出返回-1 353 | */ 354 | getSunday(y, m, n) { 355 | var d = new Date(y + '-' + m + '-1'); 356 | var d2 = new Date(y + '-' + (m + 1) + '-1'); 357 | d2.setDate(0); 358 | var maxDay = d2.getDate(); //传入月份的最后一天 359 | 360 | var week = d.getDay(); 361 | var first = 1; 362 | if (week > 0) first = d.getDate() + (7 - week); 363 | var result = (n - 1) * 7 + first; 364 | if (result > maxDay) return -1; 365 | return result; 366 | }, 367 | /** 368 | * 传入农历日期数字返回汉字表示法 369 | * @param lunar day 370 | * @return Cn string 371 | * @eg:var cnDay = calendar.toChinaDay(21) ;//cnMonth='廿一' 372 | */ 373 | toChinaDay: function (d) { //日 => \u65e5 374 | var s; 375 | switch (d) { 376 | case 10: 377 | s = '\u521d\u5341'; 378 | break; 379 | case 20: 380 | s = '\u4e8c\u5341'; 381 | break; 382 | break; 383 | case 30: 384 | s = '\u4e09\u5341'; 385 | break; 386 | break; 387 | default: 388 | s = calendar.nStr2[Math.floor(d / 10)]; 389 | s += calendar.nStr1[d % 10]; 390 | } 391 | return (s); 392 | }, 393 | 394 | /** 395 | * 年份转生肖[!仅能大致转换] => 精确划分生肖分界线是“立春” 396 | * @param y year 397 | * @return Cn string 398 | * @eg:var animal = calendar.getAnimal(1987) ;//animal='兔' 399 | */ 400 | getAnimal: function (y) { 401 | return calendar.Animals[(y - 4) % 12] 402 | }, 403 | 404 | /** 405 | * 传入阳历年月日获得详细的公历、农历object信息 <=>JSON 406 | * @param y solar year 407 | * @param m solar month 408 | * @param d solar day 409 | * @return JSON object 410 | * @eg:console.log(calendar.solar2lunar(1987,11,01)); 411 | */ 412 | solar2lunar: function (y, m, d) { //参数区间1900.1.31~2100.12.31 413 | //年份限定、上限 414 | if (y < 1900 || y > 2100) { 415 | return -1; // undefined转换为数字变为NaN 416 | } 417 | //公历传参最下限 418 | if (y == 1900 && m == 1 && d < 31) { 419 | return -1; 420 | } 421 | //未传参 获得当天 422 | if (!y) { 423 | var objDate = new Date(); 424 | } else { 425 | var objDate = new Date(y, parseInt(m) - 1, d) 426 | } 427 | var i, leap = 0, 428 | temp = 0; 429 | //修正ymd参数 430 | var y = objDate.getFullYear(), 431 | m = objDate.getMonth() + 1, 432 | d = objDate.getDate(); 433 | var offset = (Date.UTC(objDate.getFullYear(), objDate.getMonth(), objDate.getDate()) - Date.UTC(1900, 0, 31)) / 86400000; 434 | for (i = 1900; i < 2101 && offset > 0; i++) { 435 | temp = calendar.lYearDays(i); 436 | offset -= temp; 437 | } 438 | if (offset < 0) { 439 | offset += temp; 440 | i--; 441 | } 442 | 443 | //是否今天 444 | var isTodayObj = new Date(), 445 | isToday = false; 446 | if (isTodayObj.getFullYear() == y && isTodayObj.getMonth() + 1 == m && isTodayObj.getDate() == d) { 447 | isToday = true; 448 | } 449 | //星期几 450 | var nWeek = objDate.getDay(), 451 | cWeek = calendar.nStr1[nWeek]; 452 | //数字表示周几顺应天朝周一开始的惯例 453 | if (nWeek == 0) { 454 | nWeek = 7; 455 | } 456 | //农历年 457 | var year = i; 458 | var leap = calendar.leapMonth(i); //闰哪个月 459 | var isLeap = false; 460 | 461 | //效验闰月 462 | for (i = 1; i < 13 && offset > 0; i++) { 463 | //闰月 464 | if (leap > 0 && i == (leap + 1) && isLeap == false) { 465 | --i; 466 | isLeap = true; 467 | temp = calendar.leapDays(year); //计算农历闰月天数 468 | } else { 469 | temp = calendar.monthDays(year, i); //计算农历普通月天数 470 | } 471 | //解除闰月 472 | if (isLeap == true && i == (leap + 1)) { 473 | isLeap = false; 474 | } 475 | offset -= temp; 476 | } 477 | // 闰月导致数组下标重叠取反 478 | if (offset == 0 && leap > 0 && i == leap + 1) { 479 | if (isLeap) { 480 | isLeap = false; 481 | } else { 482 | isLeap = true; 483 | --i; 484 | } 485 | } 486 | if (offset < 0) { 487 | offset += temp; 488 | --i; 489 | } 490 | //农历月 491 | var month = i; 492 | //农历日 493 | var day = offset + 1; 494 | //天干地支处理 495 | var sm = m - 1; 496 | var gzY = calendar.toGanZhiYear(year); 497 | 498 | // 当月的两个节气 499 | // bugfix-2017-7-24 11:03:38 use lunar Year Param `y` Not `year` 500 | var firstNode = calendar.getTerm(y, (m * 2 - 1)); //返回当月「节」为几日开始 501 | var secondNode = calendar.getTerm(y, (m * 2)); //返回当月「节」为几日开始 502 | 503 | // 依据12节气修正干支月 504 | var gzM = calendar.toGanZhi((y - 1900) * 12 + m + 11); 505 | if (d >= firstNode) { 506 | gzM = calendar.toGanZhi((y - 1900) * 12 + m + 12); 507 | } 508 | 509 | //传入的日期的节气与否 510 | var isTerm = false; 511 | var Term = null; 512 | if (firstNode == d) { 513 | isTerm = true; 514 | Term = calendar.solarTerm[m * 2 - 2]; 515 | } 516 | if (secondNode == d) { 517 | isTerm = true; 518 | Term = calendar.solarTerm[m * 2 - 1]; 519 | } 520 | //日柱 当月一日与 1900/1/1 相差天数 521 | var dayCyclical = Date.UTC(y, sm, 1, 0, 0, 0, 0) / 86400000 + 25567 + 10; 522 | var gzD = calendar.toGanZhi(dayCyclical + d - 1); 523 | //该日期所属的星座 524 | var astro = calendar.toAstro(m, d); 525 | //该日期所有的节日 526 | var festival = []; 527 | //农历传统节日 528 | if (month == 1 && day == 1) { 529 | festival.push('春节'); 530 | } else if (month == 1 && day == 15) { 531 | festival.push('上元节'); 532 | } else if (month == 2 && day == 2) { 533 | festival.push('龙抬头'); 534 | } else if (month == 5 && day == 5) { 535 | festival.push('端午'); 536 | } else if (month == 7) { 537 | if (day == 7) festival.push('七夕'); 538 | if (day == 15) festival.push('中元节'); 539 | } else if (month == 8 && day == 15) { 540 | festival.push('中秋'); 541 | } else if (month == 9 && day == 9) { 542 | festival.push('重阳'); 543 | } else if (month == 10 && day == 15) { 544 | festival.push('下元节'); 545 | } else if (month == 12) { 546 | if (day == 8) festival.push('腊八'); 547 | if (day == 23) festival.push('小年'); 548 | if (isLeap ? day == calendar.leapDays(year) : calendar.monthDays(month - 1) == 29 ? day == 30 : day == 29) festival.push('除夕'); 549 | } 550 | //公历节日 551 | if (m == 1 && d == 1) { 552 | festival.splice(0, 0, '元旦'); 553 | } else if (m == 2 && d == 14) { 554 | festival.push('情人节'); 555 | } else if (m == 3) { 556 | if (d == 8) festival.push('妇女节'); 557 | if (d == 12) festival.push('植树节'); 558 | } else if (m == 4 && d == 1) { 559 | festival.push('愚人节'); 560 | } else if (m == 5) { 561 | if (d == 1) festival.push('劳动节'); 562 | if (d == 4) festival.push('青年节'); 563 | if (d == calendar.getSunday(y, m, 2)) festival.push('母亲节'); 564 | } else if (m == 6) { 565 | if (d == 1) festival.push('儿童节'); 566 | if (d == 4) festival.push('青年节'); 567 | if (d == calendar.getSunday(y, m, 3)) festival.push('父亲节'); 568 | } else if (m == 7 && d == 1) { 569 | festival.push('建党节'); 570 | } else if (m == 8 && d == 1) { 571 | festival.push('建军节'); 572 | } else if (m == 9 && d == 10) { 573 | festival.push('教师节'); 574 | } else if (m == 10 && d == 1) { 575 | festival.push('国庆节'); 576 | } else if (m == 11 && d == 1) { 577 | festival.push('万圣节'); 578 | } else if (m == 12) { 579 | if (d == 24) festival.push('平安夜'); 580 | if (d == 25) festival.push('圣诞节'); 581 | } 582 | return { 583 | 'lYear': year, 584 | 'lMonth': month, 585 | 'lDay': day, 586 | 'isFestival': festival.length > 0, 587 | 'festival': festival, 588 | 'Animal': calendar.getAnimal(year), 589 | 'IMonthCn': (isLeap ? "\u95f0" : '') + calendar.toChinaMonth(month), 590 | 'IDayCn': calendar.toChinaDay(day), 591 | 'cYear': y, 592 | 'cMonth': m, 593 | 'cDay': d, 594 | 'gzYear': gzY, 595 | 'gzMonth': gzM, 596 | 'gzDay': gzD, 597 | 'isToday': isToday, 598 | 'isLeap': isLeap, 599 | 'nWeek': nWeek, 600 | 'ncWeek': "\u661f\u671f" + cWeek, 601 | 'isTerm': isTerm, 602 | 'Term': Term, 603 | 'astro': astro 604 | }; 605 | }, 606 | 607 | getLunar: function (date) { 608 | var D; 609 | if (date == undefined) { 610 | D = new Date(); 611 | } else { 612 | D = new Date(date); 613 | } 614 | D.setHours(D.getHours() + 8) //根据国际UTC标准,中国时区应为:UTC+8 615 | var cY = D.getUTCFullYear(); 616 | var cM = D.getUTCMonth() + 1; 617 | var cD = D.getUTCDate(); 618 | //console.log('getLunar:月'+cM+'--'+cD+'日') 619 | return calendar.solar2lunar(cY, cM, cD); 620 | }, 621 | 622 | /** 623 | * 传入农历年月日以及传入的月份是否闰月获得详细的公历、农历object信息 <=>JSON 624 | * @param y lunar year 625 | * @param m lunar month 626 | * @param d lunar day 627 | * @param isLeapMonth lunar month is leap or not.[如果是农历闰月第四个参数赋值true即可] 628 | * @return JSON object 629 | * @eg:console.log(calendar.lunar2solar(1987,9,10)); 630 | */ 631 | lunar2solar: function (y, m, d, isLeapMonth) { //参数区间1900.1.31~2100.12.1 632 | var isLeapMonth = !!isLeapMonth; 633 | var leapOffset = 0; 634 | var leapMonth = calendar.leapMonth(y); 635 | var leapDay = calendar.leapDays(y); 636 | if (isLeapMonth && (leapMonth != m)) { 637 | return -1; 638 | } //传参要求计算该闰月公历 但该年得出的闰月与传参的月份并不同 639 | if (y == 2100 && m == 12 && d > 1 || y == 1900 && m == 1 && d < 31) { 640 | return -1; 641 | } //超出了最大极限值 642 | var day = calendar.monthDays(y, m); 643 | var _day = day; 644 | //bugFix 2016-9-25 645 | //if month is leap, _day use leapDays method 646 | if (isLeapMonth) { 647 | _day = calendar.leapDays(y, m); 648 | } 649 | if (y < 1900 || y > 2100 || d > _day) { 650 | return -1; 651 | } //参数合法性效验 652 | 653 | //计算农历的时间差 654 | var offset = 0; 655 | for (var i = 1900; i < y; i++) { 656 | offset += calendar.lYearDays(i); 657 | } 658 | var leap = 0, 659 | isAdd = false; 660 | for (var i = 1; i < m; i++) { 661 | leap = calendar.leapMonth(y); 662 | if (!isAdd) { //处理闰月 663 | if (leap <= i && leap > 0) { 664 | offset += calendar.leapDays(y); 665 | isAdd = true; 666 | } 667 | } 668 | offset += calendar.monthDays(y, i); 669 | } 670 | //转换闰月农历 需补充该年闰月的前一个月的时差 671 | if (isLeapMonth) { 672 | offset += day; 673 | } 674 | //1900年农历正月一日的公历时间为1900年1月30日0时0分0秒(该时间也是本农历的最开始起始点) 675 | var stmap = Date.UTC(1900, 1, 30, 0, 0, 0); 676 | var calObj = new Date((offset + d - 31) * 86400000 + stmap); 677 | var cY = calObj.getUTCFullYear(); 678 | var cM = calObj.getUTCMonth() + 1; 679 | var cD = calObj.getUTCDate(); 680 | 681 | return calendar.solar2lunar(cY, cM, cD); 682 | }, 683 | /** 684 | * 传入农历日期 685 | * @param date 类型String,格式:L2017-01-02;闰月:LR2017-06-03 686 | * @returns {*|JSON} 687 | */ 688 | getSolar(date) { 689 | if (date == undefined || date == null || date == '' || date.indexOf('L') == -1) return null; 690 | var isLeapMonth = date.indexOf('R') > -1; 691 | var D = date.replace(/L/, '').replace(/R/, '').split('-'); 692 | var cY = parseInt(D[0]); 693 | var cM = parseInt(D[1]); 694 | var cD = parseInt(D[2]); 695 | return calendar.lunar2solar(cY, cM, cD, isLeapMonth); 696 | }, 697 | }; 698 | 699 | const Calendar = calendar; 700 | export default Calendar; 701 | --------------------------------------------------------------------------------