├── .babelrc ├── .editorconfig ├── .eslintignore ├── .eslintrc.js ├── .gitignore ├── .postcssrc.js ├── .travis.yml ├── LICENSE ├── README.md ├── build ├── build.js ├── check-versions.js ├── cooking.conf.js ├── utils.js ├── vue-loader.conf.js ├── webpack.base.conf.js ├── webpack.components.conf.js ├── webpack.dev.conf.js └── webpack.prod.conf.js ├── components ├── LunarFullCalendar │ ├── LunarFullCalendar.vue │ ├── fullcalendar.css │ └── fullcalendar.js └── index.js ├── config ├── dev.env.js ├── index.js └── prod.env.js ├── docs ├── index.html └── static │ ├── img │ └── lunar.b0e3d9b.png │ └── js │ ├── 1.971963f2ecee05637c92.js │ ├── 1.971963f2ecee05637c92.js.map │ ├── 2.69462526e73edaa36ba8.js │ ├── 2.69462526e73edaa36ba8.js.map │ ├── 3.6d227b05e837433b3d45.js │ ├── 3.6d227b05e837433b3d45.js.map │ ├── 4.22a5aaaa784121c40a27.js │ ├── 4.22a5aaaa784121c40a27.js.map │ ├── app.c9dd13ceee3bb04b520a.js │ └── app.c9dd13ceee3bb04b520a.js.map ├── index.html ├── lib ├── LunarFullCalendar.min.js └── LunarFullCalendar.min.js.LICENSE ├── package-lock.json ├── package.json ├── src ├── App.vue ├── assets │ ├── css │ │ └── reset.scss │ └── img │ │ ├── lunar.png │ │ └── window.lunar.png ├── main.js ├── router │ └── index.js └── view │ ├── explain.vue │ └── lunarFullCalendar.vue ├── static └── .gitkeep └── yarn.lock /.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 | "es2015" 11 | ], 12 | "plugins": ["transform-vue-jsx", "transform-runtime"], 13 | "compact": false // 文件超过500m提示 14 | } 15 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | /build/ 2 | /config/ 3 | /dist/ 4 | /*.js 5 | -------------------------------------------------------------------------------- /.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 | 'prefer-promise-reject-errors': 'off', 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | /dist/ 4 | /docs/ 5 | npm-debug.log* 6 | yarn-debug.log* 7 | yarn-error.log* 8 | 9 | # Editor directories and files 10 | .idea 11 | .vscode 12 | *.suo 13 | *.ntvs* 14 | *.njsproj 15 | *.sln 16 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "node" 4 | before_install: 5 | - curl -o- -L https://yarnpkg.com/install.sh | bash -s -- --version 0.27.5 6 | - export PATH="$HOME/.yarn/bin:$PATH" 7 | cache: yarn -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 hj 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## [vue-lunar-full-calendar](https://hjdev.github.io/vue-lunar-fullcalendar) 2 | 3 | [](https://www.npmjs.com/package/vue-lunar-full-calendar) 4 | [](https://www.npmjs.com/package/vue-lunar-full-calendar) 5 | 6 | ## Image and demo 7 | 8 | ``` 9 | a vue component for lunar fullcalendar. Uses Moment.js for date operations. 10 | Increase the functions of Chinese lunar calendar, 24 solar terms and holidays 11 | ``` 12 | 13 | [Simple Live Demo](https://hjdev.github.io/vue-lunar-fullcalendar) 14 |  15 | 16 | ## Installation 17 | 18 | ``` 19 | npm install --save vue-lunar-full-calendar 20 | ``` 21 | 22 | ```js 23 | //main.js 24 | import LunarFullCalendar from "vue-lunar-full-calendar"; 25 | Vue.use(LunarFullCalendar); 26 | ``` 27 | 28 | But you can also import the standalone component to add locally or for more complex installations. 29 | 30 | ```js 31 | // index.vue 32 | import { LunarFullCalendar } from "vue-lunar-full-calendar"; 33 | export default { 34 | components: { 35 | LunarFullCalendar 36 | } 37 | }; 38 | ``` 39 | 40 | ## Important function 41 | 42 | 1、window.lunar(date) 43 | 44 | Use vue-lunar-full-calendar , You can use one function to get the date of a certain day. 45 | 46 | 2、lunarCalendar (default: true) 47 | 48 | You can pass any custom options through to fullcalendar by using the `config` prop. 49 | Control whether the Chinese calendar shows true. 50 | 51 | ```html 52 | 53 | ... 54 | 68 | ``` 69 | 70 |  71 | 72 | ## API document 73 | 74 | [Fullcalendar 文档(Fullcalendar docs)](https://fullcalendar.io/docs/) 75 | 76 | ## Example App 77 | 78 | I have created a simple Vue 2 webpack application as an example/playground 79 | https://github.com/hjdev/vue-lunar-fullcalendar 80 | 81 | ## Basic Usage 82 | 83 | You can pass an array of fullclendar objects through the props 84 | 85 | ```html 86 | ... 87 | 111 | ``` 112 | 113 | More event options can be found at http://fullcalendar.io/docs/event_data/Event_Object/ 114 | 115 | ## Using a JSON Feed 116 | 117 | ```html 118 | ... 119 | 146 | ``` 147 | 148 | ## Custom Config 149 | 150 | You can pass any custom [options](https://fullcalendar.io/docs/) through to fullcalendar by using the `config` prop, this includes extra event handlers. 151 | 152 | ```html 153 | ... 154 | 169 | ``` 170 | 171 | ## Further Props 172 | 173 | You can edit the look and feel of fullcalendar by passing through extra props. These all have sensible defaults 174 | 175 | - **header** - [obj] - [docs](http://fullcalendar.io/docs/display/header/) 176 | - **defaultView** - ['agendaWeek'] - [docs](http://fullcalendar.io/docs/views/defaultView/) 177 | - **editable** - [true] - [docs](http://fullcalendar.io/docs/event_ui/editable/) 178 | - **selectable** - [true] - [docs](http://fullcalendar.io/docs/selection/selectable/) 179 | - **selectHelper** - [true] - [docs](http://fullcalendar.io/docs/selection/selectHelper/) 180 | - **config** - [true] - Pass your own custom config straight through to fullcalendar 181 | 182 | ## Methods 183 | 184 | Sometimes you may need to manipulate the Calendar from your parent component, you can use `fireMethod` for this. This works with anything in the [Fullcalendar docs](https://fullcalendar.io/docs/) suffixed with `(method)` and it will dynamically handle as many arguments as needed. 185 | 186 | ```html 187 | ... 188 | 206 | ``` 207 | 208 | ## Events and Hooks 209 | 210 | ### Emitted 211 | 212 | - **event-selected(event, jsEvent, view)** - Triggered on eventClick() 213 | - **event-drop(event)** - Triggered on eventDrop() 214 | - **event-resize(event)** - Triggered on eventResize() 215 | - **event-created(event)** - Triggered on select() 216 | - **event-receive(event)** - Triggered on eventReceive() 217 | - **event-render(event)** - Triggered on eventRender() 218 | - **day-click(date, jsEvent, view)** - Triggered on dayClick() 219 | 220 | You can listen for these events using the following markup 221 | 222 | ```html 223 | 227 | ``` 228 | 229 | ### Listens on 230 | 231 | - **render-event(event)** - Adds a new event to calendar 232 | - **remove-event(event)** - Removes event from calendar 233 | - **rerender-events()** - Rerenders events to reflect local changes 234 | - **refetch-events()** - Makes another JSON call to event sources 235 | - **reload-events()** - Removes all events and adds all events in this.events 236 | 237 | You can trigger these events in the parent component like so... 238 | 239 | ```html 240 | 244 | ... 245 | 254 | ``` 255 | -------------------------------------------------------------------------------- /build/build.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | require('./check-versions')() 3 | 4 | process.env.NODE_ENV = process.env.NODE_ENV || 'production' 5 | console.log('NODE_ENV', process.env.NODE_ENV) 6 | const ora = require('ora') 7 | const rm = require('rimraf') 8 | const path = require('path') 9 | const chalk = require('chalk') 10 | const webpack = require('webpack') 11 | const config = require('../config') 12 | const webpackConfig = require('./webpack.prod.conf') 13 | 14 | const spinner = ora('building for production...') 15 | spinner.start() 16 | 17 | rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => { 18 | if (err) throw err 19 | webpack(webpackConfig, (err, stats) => { 20 | spinner.stop() 21 | if (err) throw err 22 | process.stdout.write(stats.toString({ 23 | colors: true, 24 | modules: false, 25 | children: false, // If you are using ts-loader, setting this to true will make TypeScript errors show up during build. 26 | chunks: false, 27 | chunkModules: false 28 | }) + '\n\n') 29 | 30 | if (stats.hasErrors()) { 31 | console.log(chalk.red(' Build failed with errors.\n')) 32 | process.exit(1) 33 | } 34 | 35 | console.log(chalk.cyan(' Build complete.\n')) 36 | console.log(chalk.yellow( 37 | ' Tip: built files are meant to be served over an HTTP server.\n' + 38 | ' Opening index.html over file:// won\'t work.\n' 39 | )) 40 | }) 41 | }) 42 | -------------------------------------------------------------------------------- /build/check-versions.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const chalk = require('chalk') 3 | const semver = require('semver') 4 | const packageConfig = require('../package.json') 5 | const shell = require('shelljs') 6 | 7 | function exec (cmd) { 8 | return require('child_process').execSync(cmd).toString().trim() 9 | } 10 | 11 | const versionRequirements = [ 12 | { 13 | name: 'node', 14 | currentVersion: semver.clean(process.version), 15 | versionRequirement: packageConfig.engines.node 16 | } 17 | ] 18 | 19 | if (shell.which('npm')) { 20 | versionRequirements.push({ 21 | name: 'npm', 22 | currentVersion: exec('npm --version'), 23 | versionRequirement: packageConfig.engines.npm 24 | }) 25 | } 26 | 27 | module.exports = function () { 28 | const warnings = [] 29 | 30 | for (let i = 0; i < versionRequirements.length; i++) { 31 | const mod = versionRequirements[i] 32 | 33 | if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) { 34 | warnings.push(mod.name + ': ' + 35 | chalk.red(mod.currentVersion) + ' should be ' + 36 | chalk.green(mod.versionRequirement) 37 | ) 38 | } 39 | } 40 | 41 | if (warnings.length) { 42 | console.log('') 43 | console.log(chalk.yellow('To use this template, you must update following to modules:')) 44 | console.log() 45 | 46 | for (let i = 0; i < warnings.length; i++) { 47 | const warning = warnings[i] 48 | console.log(' ' + warning) 49 | } 50 | 51 | console.log() 52 | process.exit(1) 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /build/cooking.conf.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var cooking = require('cooking') 3 | var config = require('./webpack.base.conf') 4 | 5 | cooking.set({ 6 | // use: 'vue', 7 | entry: { 8 | 'LunarFullCalendar.min': './components/index.js' 9 | }, 10 | dist: './lib', 11 | 12 | minimize: true, 13 | clean: true, 14 | // sourceMap: true, 15 | // extractCSS: true, 16 | publicPath: '/lib/', 17 | // assetsPath: 'static', 18 | format: 'cjs', 19 | extends: ['vue'], 20 | alias: config.resolve.alias, 21 | externals: { 22 | 'vue': 'vue' 23 | } 24 | }) 25 | // cooking.add('loader.js.exclude', '/node_modules/'); 26 | // cooking.add('loader.scss', { 27 | // test: /\.scss$/, 28 | // loaders: ['style-loader', 'css-loader', 'sass-loader'] 29 | // }); 30 | // cooking.add('vue.preserveWhitespace', false); 31 | 32 | module.exports = cooking.resolve() 33 | -------------------------------------------------------------------------------- /build/utils.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const path = require('path') 3 | const config = require('../config') 4 | // const ExtractTextPlugin = require('extract-text-webpack-plugin') 5 | const MiniCssExtractPlugin = require('mini-css-extract-plugin') 6 | const packageConfig = require('../package.json') 7 | 8 | exports.assetsPath = function (_path) { 9 | const assetsSubDirectory = process.env.NODE_ENV === 'production' ? 10 | config.build.assetsSubDirectory : 11 | config.dev.assetsSubDirectory 12 | 13 | return path.posix.join(assetsSubDirectory, _path) 14 | } 15 | 16 | exports.cssLoaders = function (options) { 17 | options = options || {} 18 | 19 | const cssLoader = { 20 | loader: 'css-loader', 21 | options: { 22 | sourceMap: options.sourceMap 23 | } 24 | } 25 | 26 | const postcssLoader = { 27 | loader: 'postcss-loader', 28 | options: { 29 | sourceMap: options.sourceMap 30 | } 31 | } 32 | 33 | // generate loader string to be used with extract text plugin 34 | function generateLoaders(loader, loaderOptions) { 35 | const loaders = options.usePostCSS ? [cssLoader, postcssLoader] : [cssLoader] 36 | 37 | if (loader) { 38 | loaders.push({ 39 | loader: loader + '-loader', 40 | options: Object.assign({}, loaderOptions, { 41 | sourceMap: options.sourceMap 42 | }) 43 | }) 44 | } 45 | 46 | // Extract CSS when that option is specified 47 | // (which is the case during production build) 48 | if (options.extract) { 49 | loaders.push(MiniCssExtractPlugin.loader) 50 | // return ExtractTextPlugin.extract({ 51 | // use: loaders, 52 | // fallback: 'vue-style-loader' 53 | // }) 54 | } else { 55 | loaders.push('vue-style-loader') 56 | // return ['vue-style-loader'].concat(loaders) 57 | } 58 | } 59 | 60 | // https://vue-loader.vuejs.org/en/configurations/extract-css.html 61 | return { 62 | css: generateLoaders(), 63 | postcss: generateLoaders(), 64 | less: generateLoaders('less'), 65 | sass: generateLoaders('sass', { 66 | indentedSyntax: true 67 | }), 68 | scss: generateLoaders('sass'), 69 | stylus: generateLoaders('stylus'), 70 | styl: generateLoaders('stylus') 71 | } 72 | } 73 | 74 | // Generate loaders for standalone style files (outside of .vue) 75 | exports.styleLoaders = function (options) { 76 | const output = [] 77 | const loaders = exports.cssLoaders(options) 78 | 79 | for (const extension in loaders) { 80 | const loader = loaders[extension] 81 | output.push({ 82 | test: new RegExp('\\.' + extension + '$'), 83 | use: loader 84 | }) 85 | } 86 | 87 | return output 88 | } 89 | 90 | exports.createNotifierCallback = () => { 91 | const notifier = require('node-notifier') 92 | 93 | return (severity, errors) => { 94 | if (severity !== 'error') return 95 | 96 | const error = errors[0] 97 | const filename = error.file && error.file.split('!').pop() 98 | 99 | notifier.notify({ 100 | title: packageConfig.name, 101 | message: severity + ': ' + error.name, 102 | subtitle: filename || '', 103 | icon: path.join(__dirname, 'logo.png') 104 | }) 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /build/vue-loader.conf.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const utils = require('./utils') 3 | const config = require('../config') 4 | const isProduction = process.env.NODE_ENV === 'production' 5 | const sourceMapEnabled = isProduction 6 | ? config.build.productionSourceMap 7 | : config.dev.cssSourceMap 8 | 9 | module.exports = { 10 | loaders: utils.cssLoaders({ 11 | sourceMap: sourceMapEnabled, 12 | extract: isProduction 13 | }), 14 | cssSourceMap: sourceMapEnabled, 15 | cacheBusting: config.dev.cacheBusting, 16 | transformToRequire: { 17 | video: ['src', 'poster'], 18 | source: 'src', 19 | img: 'src', 20 | image: 'xlink:href' 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /build/webpack.base.conf.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const path = require('path') 3 | const utils = require('./utils') 4 | const config = require('../config') 5 | const vueLoaderConfig = require('./vue-loader.conf') 6 | const VueLoaderPlugin = require('vue-loader/lib/plugin') 7 | 8 | function resolve(dir) { 9 | return path.join(__dirname, '..', dir) 10 | } 11 | 12 | const createLintingRule = () => ({ 13 | test: /\.(js|vue)$/, 14 | loader: 'eslint-loader', 15 | enforce: 'pre', 16 | include: [resolve('src'), resolve('test')], 17 | options: { 18 | formatter: require('eslint-friendly-formatter'), 19 | emitWarning: !config.dev.showEslintErrorsInOverlay 20 | } 21 | }) 22 | 23 | module.exports = { 24 | mode: 'development', 25 | context: path.resolve(__dirname, '../'), 26 | entry: { 27 | app: ['babel-polyfill', './src/main.js'] 28 | }, 29 | output: { 30 | path: config.build.assetsRoot, 31 | filename: '[name].[hash].js', 32 | publicPath: process.env.NODE_ENV === 'production' ? 33 | config.build.assetsPublicPath : config.dev.assetsPublicPath 34 | }, 35 | performance: { 36 | hints: false 37 | }, 38 | // performance: { 39 | // hints: 'warning', 40 | // //入口起点的最大体积 41 | // maxEntrypointSize: 50000000, 42 | // //生成文件的最大体积 43 | // maxAssetSize: 30000000, 44 | // //只给出 js 文件的性能提示 45 | // assetFilter: function (assetFilename) { 46 | // return assetFilename.endsWith('.js'); 47 | // } 48 | // }, 49 | resolve: { 50 | extensions: ['.js', '.vue', '.json'], 51 | alias: { 52 | 'vue$': 'vue/dist/vue.esm.js', 53 | '@': resolve('src'), 54 | } 55 | }, 56 | module: { 57 | rules: [ 58 | ...(config.dev.useEslint ? [createLintingRule()] : []), 59 | { 60 | test: /\.vue$/, 61 | loader: 'vue-loader', 62 | options: vueLoaderConfig 63 | }, 64 | { 65 | test: /\.(css|scss)$/, 66 | use: ['style-loader', 'css-loader', 'sass-loader'] 67 | }, 68 | { 69 | test: /\.js$/, 70 | loader: 'babel-loader', 71 | exclude: [resolve('lib')], 72 | include: [resolve('src'), resolve('components'), resolve('node_modules/webpack-dev-server/client')] 73 | }, 74 | { 75 | test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, 76 | loader: 'url-loader', 77 | options: { 78 | limit: 10000, 79 | name: utils.assetsPath('img/[name].[hash:7].[ext]') 80 | } 81 | }, 82 | { 83 | test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/, 84 | loader: 'url-loader', 85 | options: { 86 | limit: 10000, 87 | name: utils.assetsPath('media/[name].[hash:7].[ext]') 88 | } 89 | }, 90 | { 91 | test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, 92 | loader: 'url-loader', 93 | options: { 94 | limit: 10000, 95 | name: utils.assetsPath('fonts/[name].[hash:7].[ext]') 96 | } 97 | } 98 | ] 99 | }, 100 | node: { 101 | // prevent webpack from injecting useless setImmediate polyfill because Vue 102 | // source contains it (although only uses it if it's native). 103 | setImmediate: false, 104 | // prevent webpack from injecting mocks to Node native modules 105 | // that does not make sense for the client 106 | dgram: 'empty', 107 | fs: 'empty', 108 | net: 'empty', 109 | tls: 'empty', 110 | child_process: 'empty' 111 | }, 112 | plugins: [ 113 | new VueLoaderPlugin() 114 | ] 115 | } 116 | -------------------------------------------------------------------------------- /build/webpack.components.conf.js: -------------------------------------------------------------------------------- 1 | const webpack = require('webpack') 2 | const path = require('path'); 3 | const ProgressBarPlugin = require('progress-bar-webpack-plugin'); 4 | const VueLoaderPlugin = require('vue-loader/lib/plugin'); 5 | const nodeExternals = require('webpack-node-externals'); 6 | const TerserPlugin = require('terser-webpack-plugin'); 7 | const { 8 | CleanWebpackPlugin 9 | } = require('clean-webpack-plugin') 10 | const version = process.env.VERSION || require('../package.json').version 11 | 12 | let banner = 13 | 'vue-lunar-fullcalendar v' + version + '\n' + 14 | '(c) ' + new Date().getFullYear() + ' h j \n' + 15 | '@license MIT' 16 | 17 | module.exports = { 18 | mode: 'production', 19 | entry: { 20 | app: ['./components/index.js'] 21 | }, 22 | output: { 23 | path: path.resolve(__dirname, '../lib'), 24 | publicPath: '/', 25 | filename: 'LunarFullCalendar.min.js', 26 | chunkFilename: '[id].js', 27 | libraryExport: 'default', 28 | library: 'LunarFullCalendar', 29 | libraryTarget: 'umd', 30 | umdNamedDefine: true, 31 | globalObject: 'typeof self !== \'undefined\' ? self : this' 32 | }, 33 | resolve: { 34 | extensions: ['.js', '.vue', '.json'], 35 | alias: { 36 | 'vue$': 'vue/dist/vue.esm.js' 37 | }, 38 | modules: ['node_modules'] 39 | }, 40 | externals: [{ 41 | vue: { 42 | root: 'Vue', 43 | commonjs: 'vue', 44 | commonjs2: 'vue', 45 | amd: 'vue' 46 | } 47 | }, nodeExternals()], 48 | performance: { 49 | hints: false 50 | }, 51 | // stats: { 52 | // children: false 53 | // }, 54 | optimization: { 55 | minimizer: [ 56 | new TerserPlugin({ 57 | terserOptions: { 58 | output: { 59 | comments: false 60 | } 61 | } 62 | }) 63 | ] 64 | }, 65 | module: { 66 | rules: [{ 67 | test: /\.(jsx?|babel|es6)$/, 68 | include: process.cwd(), 69 | exclude: /node_modules|utils\/popper\.js|utils\/date\.js/, 70 | loader: 'babel-loader' 71 | }, 72 | { 73 | test: /\.vue$/, 74 | loader: 'vue-loader', 75 | options: { 76 | compilerOptions: { 77 | preserveWhitespace: false 78 | } 79 | } 80 | }, 81 | { 82 | test: /\.css$/, 83 | loaders: ['style-loader', 'css-loader'] 84 | }, 85 | { 86 | test: /\.(svg|otf|ttf|woff2?|eot|gif|png|jpe?g)(\?\S*)?$/, 87 | loader: 'url-loader', 88 | query: { 89 | limit: 10000, 90 | name: path.posix.join('static', '[name].[hash:7].[ext]') 91 | } 92 | } 93 | ] 94 | }, 95 | plugins: [ 96 | new ProgressBarPlugin(), 97 | new VueLoaderPlugin(), 98 | new CleanWebpackPlugin(), 99 | new webpack.BannerPlugin({ 100 | banner 101 | }) 102 | ] 103 | } 104 | -------------------------------------------------------------------------------- /build/webpack.dev.conf.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const utils = require('./utils') 3 | const webpack = require('webpack') 4 | const config = require('../config') 5 | const merge = require('webpack-merge') 6 | const path = require('path') 7 | const baseWebpackConfig = require('./webpack.base.conf') 8 | const CopyWebpackPlugin = require('copy-webpack-plugin') 9 | const HtmlWebpackPlugin = require('html-webpack-plugin') 10 | const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin') 11 | const portfinder = require('portfinder') 12 | 13 | const HOST = process.env.HOST 14 | const PORT = process.env.PORT && Number(process.env.PORT) 15 | 16 | const devWebpackConfig = merge(baseWebpackConfig, { 17 | module: { 18 | rules: utils.styleLoaders({ 19 | sourceMap: config.dev.cssSourceMap, 20 | usePostCSS: true 21 | }) 22 | }, 23 | // cheap-module-eval-source-map is faster for development 24 | devtool: config.dev.devtool, 25 | 26 | // these devServer options should be customized in /config/index.js 27 | devServer: { 28 | clientLogLevel: 'warning', 29 | historyApiFallback: { 30 | rewrites: [{ 31 | from: /.*/, 32 | to: path.posix.join(config.dev.assetsPublicPath, 'index.html') 33 | }, ], 34 | }, 35 | hot: true, 36 | contentBase: false, // since we use CopyWebpackPlugin. 37 | compress: true, 38 | host: HOST || config.dev.host, 39 | port: PORT || config.dev.port, 40 | open: config.dev.autoOpenBrowser, 41 | overlay: config.dev.errorOverlay ? 42 | { 43 | warnings: false, 44 | errors: true 45 | } : 46 | false, 47 | publicPath: config.dev.assetsPublicPath, 48 | proxy: config.dev.proxyTable, 49 | quiet: true, // necessary for FriendlyErrorsPlugin 50 | watchOptions: { 51 | poll: config.dev.poll, 52 | } 53 | }, 54 | plugins: [ 55 | new webpack.DefinePlugin({ 56 | 'process.env': require('../config/dev.env') 57 | }), 58 | new webpack.HotModuleReplacementPlugin(), 59 | new webpack.NamedModulesPlugin(), // HMR shows correct file names in console on update. 60 | new webpack.NoEmitOnErrorsPlugin(), 61 | // https://github.com/ampedandwired/html-webpack-plugin 62 | new HtmlWebpackPlugin({ 63 | filename: 'index.html', 64 | template: 'index.html', 65 | inject: true 66 | }), 67 | // copy custom static assets 68 | new CopyWebpackPlugin([{ 69 | from: path.resolve(__dirname, '../static'), 70 | to: config.dev.assetsSubDirectory, 71 | ignore: ['.*'] 72 | }]) 73 | ] 74 | }) 75 | 76 | module.exports = new Promise((resolve, reject) => { 77 | portfinder.basePort = process.env.PORT || config.dev.port 78 | portfinder.getPort((err, port) => { 79 | if (err) { 80 | reject(err) 81 | } else { 82 | // publish the new Port, necessary for e2e tests 83 | process.env.PORT = port 84 | // add port to devServer config 85 | devWebpackConfig.devServer.port = port 86 | 87 | // Add FriendlyErrorsPlugin 88 | devWebpackConfig.plugins.push(new FriendlyErrorsPlugin({ 89 | compilationSuccessInfo: { 90 | messages: [`Your application is running here: http://${devWebpackConfig.devServer.host}:${port}`], 91 | }, 92 | onErrors: config.dev.notifyOnErrors ? 93 | utils.createNotifierCallback() : 94 | undefined 95 | })) 96 | 97 | resolve(devWebpackConfig) 98 | } 99 | }) 100 | }) 101 | -------------------------------------------------------------------------------- /build/webpack.prod.conf.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const path = require('path') 3 | const utils = require('./utils') 4 | const webpack = require('webpack') 5 | const config = require('../config') 6 | const merge = require('webpack-merge') 7 | const baseWebpackConfig = require('./webpack.base.conf') 8 | const CopyWebpackPlugin = require('copy-webpack-plugin') 9 | const HtmlWebpackPlugin = require('html-webpack-plugin') 10 | // const ExtractTextPlugin = require('extract-text-webpack-plugin') 11 | const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin') 12 | // const UglifyJsPlugin = require('uglifyjs-webpack-plugin') 13 | const TerserPlugin = require('terser-webpack-plugin') // 代替 uglifyjs-webpack-plugin 14 | const MiniCssExtractPlugin = require('mini-css-extract-plugin') //代替 extract-text-webpack-plugin 15 | 16 | const env = require('../config/prod.env') 17 | 18 | const webpackConfig = merge(baseWebpackConfig, { 19 | mode: 'production', 20 | module: { 21 | rules: utils.styleLoaders({ 22 | sourceMap: config.build.productionSourceMap, 23 | extract: true, 24 | usePostCSS: true 25 | }) 26 | }, 27 | devtool: config.build.productionSourceMap ? config.build.devtool : false, 28 | output: { 29 | path: config.build.assetsRoot, 30 | filename: utils.assetsPath('js/[name].[chunkhash].js'), 31 | chunkFilename: utils.assetsPath('js/[id].[chunkhash].js') 32 | }, 33 | optimization: { 34 | splitChunks: { 35 | chunks: 'all', 36 | minSize: 30000, 37 | maxAsyncRequests: 5, 38 | maxInitialRequests: 3, 39 | automaticNameDelimiter: '~', 40 | name: true 41 | // cacheGroups: { 42 | // styles: { 43 | // name: 'styles', 44 | // test: /\.css$/, 45 | // chunks: 'all', 46 | // enforce: true, 47 | // } 48 | // } 49 | }, 50 | minimizer: [ 51 | new TerserPlugin({ 52 | cache: true, 53 | parallel: true, 54 | // warnings: false, 55 | sourceMap: true, // Must be set to true if using source-maps in production 56 | terserOptions: { 57 | // https://github.com/webpack-contrib/terser-webpack-plugin#terseroptions 58 | } 59 | }), 60 | new MiniCssExtractPlugin({ 61 | filename: utils.assetsPath('css/[name].[contenthash].css'), 62 | allChunks: true 63 | }), 64 | // http://vuejs.github.io/vue-loader/en/workflow/production.html 65 | new webpack.DefinePlugin({ 66 | 'process.env': env 67 | }), 68 | // new UglifyJsPlugin({ 69 | // uglifyOptions: { 70 | // compress: { 71 | // warnings: false 72 | // } 73 | // }, 74 | // sourceMap: config.build.productionSourceMap, 75 | // parallel: true 76 | // }), 77 | // extract css into its own file 78 | // new ExtractTextPlugin({ 79 | // filename: utils.assetsPath('css/[name].[contenthash].css'), 80 | // // Setting the following option to `false` will not extract CSS from codesplit chunks. 81 | // // Their CSS will instead be inserted dynamically with style-loader when the codesplit chunk has been loaded by webpack. 82 | // // It's currently set to `true` because we are seeing that sourcemaps are included in the codesplit bundle as well when it's `false`, 83 | // // increasing file size: https://github.com/vuejs-templates/webpack/issues/1110 84 | // allChunks: true, 85 | // }), 86 | // Compress extracted CSS. We are using this plugin so that possible 87 | // duplicated CSS from different components can be deduped. 88 | new OptimizeCSSPlugin({ 89 | cssProcessorOptions: config.build.productionSourceMap ? { 90 | safe: true, 91 | map: { 92 | inline: false 93 | } 94 | } : { 95 | safe: true 96 | } 97 | }), 98 | // generate dist index.html with correct asset hash for caching. 99 | // you can customize output by editing /index.html 100 | // see https://github.com/ampedandwired/html-webpack-plugin 101 | new HtmlWebpackPlugin({ 102 | filename: config.build.index, 103 | template: 'index.html', 104 | inject: true, 105 | minify: { 106 | removeComments: true, 107 | collapseWhitespace: true, 108 | removeAttributeQuotes: true 109 | // more options: 110 | // https://github.com/kangax/html-minifier#options-quick-reference 111 | }, 112 | // necessary to consistently work with multiple chunks via CommonsChunkPlugin 113 | chunksSortMode: 'dependency' 114 | }), 115 | // keep module.id stable when vendor modules does not change 116 | new webpack.HashedModuleIdsPlugin(), 117 | // enable scope hoisting 118 | new webpack.optimize.ModuleConcatenationPlugin(), 119 | // split vendor js into its own file 120 | // new webpack.optimize.CommonsChunkPlugin({ 121 | // name: 'vendor', 122 | // minChunks(module) { 123 | // // any required modules inside node_modules are extracted to vendor 124 | // return ( 125 | // module.resource && 126 | // /\.js$/.test(module.resource) && 127 | // module.resource.indexOf( 128 | // path.join(__dirname, '../node_modules') 129 | // ) === 0 130 | // ) 131 | // } 132 | // }), 133 | // // extract webpack runtime and module manifest to its own file in order to 134 | // // prevent vendor hash from being updated whenever app bundle is updated 135 | // new webpack.optimize.CommonsChunkPlugin({ 136 | // name: 'manifest', 137 | // minChunks: Infinity 138 | // }), 139 | // // This instance extracts shared chunks from code splitted chunks and bundles them 140 | // // in a separate chunk, similar to the vendor chunk 141 | // // see: https://webpack.js.org/plugins/commons-chunk-plugin/#extra-async-commons-chunk 142 | // new webpack.optimize.CommonsChunkPlugin({ 143 | // name: 'app', 144 | // async: 'vendor-async', 145 | // children: true, 146 | // minChunks: 3 147 | // }), 148 | 149 | // copy custom static assets 150 | new CopyWebpackPlugin([{ 151 | from: path.resolve(__dirname, '../static'), 152 | to: config.build.assetsSubDirectory, 153 | ignore: ['.*'] 154 | }]) 155 | ] 156 | } 157 | }) 158 | 159 | if (config.build.productionGzip) { 160 | const CompressionWebpackPlugin = require('compression-webpack-plugin') 161 | 162 | webpackConfig.plugins.push( 163 | new CompressionWebpackPlugin({ 164 | asset: '[path].gz[query]', 165 | algorithm: 'gzip', 166 | test: new RegExp( 167 | '\\.(' + 168 | config.build.productionGzipExtensions.join('|') + 169 | ')$' 170 | ), 171 | threshold: 10240, 172 | minRatio: 0.8 173 | }) 174 | ) 175 | } 176 | 177 | if (config.build.bundleAnalyzerReport) { 178 | const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin 179 | webpackConfig.plugins.push(new BundleAnalyzerPlugin()) 180 | } 181 | 182 | module.exports = webpackConfig 183 | -------------------------------------------------------------------------------- /components/LunarFullCalendar/LunarFullCalendar.vue: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 207 | 210 | -------------------------------------------------------------------------------- /components/LunarFullCalendar/fullcalendar.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * FullCalendar v3.9.0 3 | */ 4 | .fc { 5 | direction: ltr; 6 | text-align: left; 7 | } 8 | 9 | .fc-rtl { 10 | text-align: right; 11 | } 12 | 13 | body .fc { 14 | /* extra precedence to overcome jqui */ 15 | font-size: 1em; 16 | } 17 | 18 | /* Colors 19 | --------------------------------------------------------------------------------------------------*/ 20 | .fc-highlight { 21 | /* when user is selecting cells */ 22 | background: #bce8f1; 23 | opacity: .3; 24 | } 25 | 26 | .fc-bgevent { 27 | /* default look for background events */ 28 | background: #8fdf82; 29 | opacity: .3; 30 | } 31 | 32 | .fc-nonbusiness { 33 | /* default look for non-business-hours areas */ 34 | /* will inherit .fc-bgevent's styles */ 35 | background: #d7d7d7; 36 | } 37 | 38 | /* Buttons (styled tags, normalized to work cross-browser) 39 | --------------------------------------------------------------------------------------------------*/ 40 | .fc button { 41 | /* force height to include the border and padding */ 42 | -moz-box-sizing: border-box; 43 | -webkit-box-sizing: border-box; 44 | box-sizing: border-box; 45 | /* dimensions */ 46 | margin: 0; 47 | height: 2.1em; 48 | padding: 0 .6em; 49 | /* text & cursor */ 50 | font-size: 1em; 51 | /* normalize */ 52 | white-space: nowrap; 53 | cursor: pointer; 54 | } 55 | 56 | /* Firefox has an annoying inner border */ 57 | .fc button::-moz-focus-inner { 58 | margin: 0; 59 | padding: 0; 60 | } 61 | 62 | .fc-state-default { 63 | /* non-theme */ 64 | border: 1px solid; 65 | } 66 | 67 | .fc-state-default.fc-corner-left { 68 | /* non-theme */ 69 | border-top-left-radius: 4px; 70 | border-bottom-left-radius: 4px; 71 | } 72 | 73 | .fc-state-default.fc-corner-right { 74 | /* non-theme */ 75 | border-top-right-radius: 4px; 76 | border-bottom-right-radius: 4px; 77 | } 78 | 79 | /* icons in buttons */ 80 | .fc button .fc-icon { 81 | /* non-theme */ 82 | position: relative; 83 | top: -0.05em; 84 | /* seems to be a good adjustment across browsers */ 85 | margin: 0 .2em; 86 | vertical-align: middle; 87 | } 88 | 89 | /* 90 | button states 91 | borrowed from twitter bootstrap (http://twitter.github.com/bootstrap/) 92 | */ 93 | .fc-state-default { 94 | background-color: #f5f5f5; 95 | background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6); 96 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6)); 97 | background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6); 98 | background-image: -o-linear-gradient(top, #ffffff, #e6e6e6); 99 | background-image: linear-gradient(to bottom, #ffffff, #e6e6e6); 100 | background-repeat: repeat-x; 101 | border-color: #e6e6e6 #e6e6e6 #bfbfbf; 102 | border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); 103 | color: #333; 104 | text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75); 105 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); 106 | } 107 | 108 | .fc-state-hover, 109 | .fc-state-down, 110 | .fc-state-active, 111 | .fc-state-disabled { 112 | color: #333333; 113 | background-color: #e6e6e6; 114 | } 115 | 116 | .fc-state-hover { 117 | color: #333333; 118 | text-decoration: none; 119 | background-position: 0 -15px; 120 | -webkit-transition: background-position 0.1s linear; 121 | -moz-transition: background-position 0.1s linear; 122 | -o-transition: background-position 0.1s linear; 123 | transition: background-position 0.1s linear; 124 | } 125 | 126 | .fc-state-down, 127 | .fc-state-active { 128 | background-color: #cccccc; 129 | background-image: none; 130 | box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); 131 | } 132 | 133 | .fc-state-disabled { 134 | cursor: default; 135 | background-image: none; 136 | opacity: 0.65; 137 | box-shadow: none; 138 | } 139 | 140 | /* Buttons Groups 141 | --------------------------------------------------------------------------------------------------*/ 142 | .fc-button-group { 143 | display: inline-block; 144 | } 145 | 146 | /* 147 | every button that is not first in a button group should scootch over one pixel and cover the 148 | previous button's border... 149 | */ 150 | .fc .fc-button-group>* { 151 | /* extra precedence b/c buttons have margin set to zero */ 152 | float: left; 153 | margin: 0 0 0 -1px; 154 | } 155 | 156 | .fc .fc-button-group> :first-child { 157 | /* same */ 158 | margin-left: 0; 159 | } 160 | 161 | /* Popover 162 | --------------------------------------------------------------------------------------------------*/ 163 | .fc-popover { 164 | position: absolute; 165 | box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15); 166 | } 167 | 168 | .fc-popover .fc-header { 169 | /* TODO: be more consistent with fc-head/fc-body */ 170 | padding: 2px 4px; 171 | } 172 | 173 | .fc-popover .fc-header .fc-title { 174 | margin: 0 2px; 175 | } 176 | 177 | .fc-popover .fc-header .fc-close { 178 | cursor: pointer; 179 | } 180 | 181 | .fc-ltr .fc-popover .fc-header .fc-title, 182 | .fc-rtl .fc-popover .fc-header .fc-close { 183 | float: left; 184 | } 185 | 186 | .fc-rtl .fc-popover .fc-header .fc-title, 187 | .fc-ltr .fc-popover .fc-header .fc-close { 188 | float: right; 189 | } 190 | 191 | /* Misc Reusable Components 192 | --------------------------------------------------------------------------------------------------*/ 193 | .fc-divider { 194 | border-style: solid; 195 | border-width: 1px; 196 | } 197 | 198 | hr.fc-divider { 199 | height: 0; 200 | margin: 0; 201 | padding: 0 0 2px; 202 | /* height is unreliable across browsers, so use padding */ 203 | border-width: 1px 0; 204 | } 205 | 206 | .fc-clear { 207 | clear: both; 208 | } 209 | 210 | .fc-bg, 211 | .fc-bgevent-skeleton, 212 | .fc-highlight-skeleton, 213 | .fc-helper-skeleton { 214 | /* these element should always cling to top-left/right corners */ 215 | position: absolute; 216 | top: 0; 217 | left: 0; 218 | right: 0; 219 | } 220 | 221 | .fc-bg { 222 | bottom: 0; 223 | /* strech bg to bottom edge */ 224 | } 225 | 226 | .fc-bg table { 227 | height: 100%; 228 | /* strech bg to bottom edge */ 229 | } 230 | 231 | /* Tables 232 | --------------------------------------------------------------------------------------------------*/ 233 | .fc table { 234 | width: 100%; 235 | box-sizing: border-box; 236 | /* fix scrollbar issue in firefox */ 237 | table-layout: fixed; 238 | border-collapse: collapse; 239 | border-spacing: 0; 240 | font-size: 1em; 241 | /* normalize cross-browser */ 242 | } 243 | 244 | .fc th { 245 | text-align: center; 246 | } 247 | 248 | .fc th, 249 | .fc td { 250 | border-style: solid; 251 | border-width: 1px; 252 | padding: 0; 253 | vertical-align: top; 254 | } 255 | 256 | .fc td.fc-today { 257 | border-style: double; 258 | /* overcome neighboring borders */ 259 | } 260 | 261 | /* Internal Nav Links 262 | --------------------------------------------------------------------------------------------------*/ 263 | a[data-goto] { 264 | cursor: pointer; 265 | } 266 | 267 | a[data-goto]:hover { 268 | text-decoration: underline; 269 | } 270 | 271 | /* Fake Table Rows 272 | --------------------------------------------------------------------------------------------------*/ 273 | .fc .fc-row { 274 | /* extra precedence to overcome themes w/ .ui-widget-content forcing a 1px border */ 275 | /* no visible border by default. but make available if need be (scrollbar width compensation) */ 276 | border-style: solid; 277 | border-width: 0; 278 | } 279 | 280 | .fc-row table { 281 | /* don't put left/right border on anything within a fake row. 282 | the outer tbody will worry about this */ 283 | border-left: 0 hidden transparent; 284 | border-right: 0 hidden transparent; 285 | /* no bottom borders on rows */ 286 | border-bottom: 0 hidden transparent; 287 | } 288 | 289 | .fc-row:first-child table { 290 | border-top: 0 hidden transparent; 291 | /* no top border on first row */ 292 | } 293 | 294 | /* Day Row (used within the header and the DayGrid) 295 | --------------------------------------------------------------------------------------------------*/ 296 | .fc-row { 297 | position: relative; 298 | } 299 | 300 | .fc-row .fc-bg { 301 | z-index: 1; 302 | } 303 | 304 | /* highlighting cells & background event skeleton */ 305 | .fc-row .fc-bgevent-skeleton, 306 | .fc-row .fc-highlight-skeleton { 307 | bottom: 0; 308 | /* stretch skeleton to bottom of row */ 309 | } 310 | 311 | .fc-row .fc-bgevent-skeleton table, 312 | .fc-row .fc-highlight-skeleton table { 313 | height: 100%; 314 | /* stretch skeleton to bottom of row */ 315 | } 316 | 317 | .fc-row .fc-highlight-skeleton td, 318 | .fc-row .fc-bgevent-skeleton td { 319 | border-color: transparent; 320 | } 321 | 322 | .fc-row .fc-bgevent-skeleton { 323 | z-index: 2; 324 | } 325 | 326 | .fc-row .fc-highlight-skeleton { 327 | z-index: 3; 328 | } 329 | 330 | /* 331 | row content (which contains day/week numbers and events) as well as "helper" (which contains 332 | temporary rendered events). 333 | */ 334 | .fc-row .fc-content-skeleton { 335 | position: relative; 336 | z-index: 4; 337 | padding-bottom: 2px; 338 | /* matches the space above the events */ 339 | } 340 | 341 | .fc-row .fc-helper-skeleton { 342 | z-index: 5; 343 | } 344 | 345 | .fc .fc-row .fc-content-skeleton table, 346 | .fc .fc-row .fc-content-skeleton td, 347 | .fc .fc-row .fc-helper-skeleton td { 348 | /* see-through to the background below */ 349 | /* extra precedence to prevent theme-provided backgrounds */ 350 | background: none; 351 | /* in case s are globally styled */ 352 | border-color: transparent; 353 | } 354 | 355 | .fc-row .fc-content-skeleton td, 356 | .fc-row .fc-helper-skeleton td { 357 | /* don't put a border between events and/or the day number */ 358 | border-bottom: 0; 359 | } 360 | 361 | .fc-row .fc-content-skeleton tbody td, 362 | .fc-row .fc-helper-skeleton tbody td { 363 | /* don't put a border between event cells */ 364 | border-top: 0; 365 | } 366 | 367 | /* Scrolling Container 368 | --------------------------------------------------------------------------------------------------*/ 369 | .fc-scroller { 370 | -webkit-overflow-scrolling: touch; 371 | } 372 | 373 | /* TODO: move to agenda/basic */ 374 | .fc-scroller>.fc-day-grid, 375 | .fc-scroller>.fc-time-grid { 376 | position: relative; 377 | /* re-scope all positions */ 378 | width: 100%; 379 | /* hack to force re-sizing this inner element when scrollbars appear/disappear */ 380 | } 381 | 382 | /* Global Event Styles 383 | --------------------------------------------------------------------------------------------------*/ 384 | .fc-event { 385 | position: relative; 386 | /* for resize handle and other inner positioning */ 387 | display: block; 388 | /* make the tag block */ 389 | font-size: .85em; 390 | line-height: 1.3; 391 | border-radius: 3px; 392 | border: 1px solid #3a87ad; 393 | /* default BORDER color */ 394 | } 395 | 396 | .fc-event, 397 | .fc-event-dot { 398 | background-color: #3a87ad; 399 | /* default BACKGROUND color */ 400 | } 401 | 402 | .fc-event, 403 | .fc-event:hover { 404 | color: #fff; 405 | /* default TEXT color */ 406 | text-decoration: none; 407 | /* if has an href */ 408 | } 409 | 410 | .fc-event[href], 411 | .fc-event.fc-draggable { 412 | cursor: pointer; 413 | /* give events with links and draggable events a hand mouse pointer */ 414 | } 415 | 416 | .fc-not-allowed, 417 | .fc-not-allowed .fc-event { 418 | /* to override an event's custom cursor */ 419 | cursor: not-allowed; 420 | } 421 | 422 | .fc-event .fc-bg { 423 | /* the generic .fc-bg already does position */ 424 | z-index: 1; 425 | background: #fff; 426 | opacity: .25; 427 | } 428 | 429 | .fc-event .fc-content { 430 | position: relative; 431 | z-index: 2; 432 | } 433 | 434 | /* resizer (cursor AND touch devices) */ 435 | .fc-event .fc-resizer { 436 | position: absolute; 437 | z-index: 4; 438 | } 439 | 440 | /* resizer (touch devices) */ 441 | .fc-event .fc-resizer { 442 | display: none; 443 | } 444 | 445 | .fc-event.fc-allow-mouse-resize .fc-resizer, 446 | .fc-event.fc-selected .fc-resizer { 447 | /* only show when hovering or selected (with touch) */ 448 | display: block; 449 | } 450 | 451 | /* hit area */ 452 | .fc-event.fc-selected .fc-resizer:before { 453 | /* 40x40 touch area */ 454 | content: ""; 455 | position: absolute; 456 | z-index: 9999; 457 | /* user of this util can scope within a lower z-index */ 458 | top: 50%; 459 | left: 50%; 460 | width: 40px; 461 | height: 40px; 462 | margin-left: -20px; 463 | margin-top: -20px; 464 | } 465 | 466 | /* Event Selection (only for touch devices) 467 | --------------------------------------------------------------------------------------------------*/ 468 | .fc-event.fc-selected { 469 | z-index: 9999 !important; 470 | /* overcomes inline z-index */ 471 | box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2); 472 | } 473 | 474 | .fc-event.fc-selected.fc-dragging { 475 | box-shadow: 0 2px 7px rgba(0, 0, 0, 0.3); 476 | } 477 | 478 | /* Horizontal Events 479 | --------------------------------------------------------------------------------------------------*/ 480 | /* bigger touch area when selected */ 481 | .fc-h-event.fc-selected:before { 482 | content: ""; 483 | position: absolute; 484 | z-index: 3; 485 | /* below resizers */ 486 | top: -10px; 487 | bottom: -10px; 488 | left: 0; 489 | right: 0; 490 | } 491 | 492 | /* events that are continuing to/from another week. kill rounded corners and butt up against edge */ 493 | .fc-ltr .fc-h-event.fc-not-start, 494 | .fc-rtl .fc-h-event.fc-not-end { 495 | margin-left: 0; 496 | border-left-width: 0; 497 | padding-left: 1px; 498 | /* replace the border with padding */ 499 | border-top-left-radius: 0; 500 | border-bottom-left-radius: 0; 501 | } 502 | 503 | .fc-ltr .fc-h-event.fc-not-end, 504 | .fc-rtl .fc-h-event.fc-not-start { 505 | margin-right: 0; 506 | border-right-width: 0; 507 | padding-right: 1px; 508 | /* replace the border with padding */ 509 | border-top-right-radius: 0; 510 | border-bottom-right-radius: 0; 511 | } 512 | 513 | /* resizer (cursor AND touch devices) */ 514 | /* left resizer */ 515 | .fc-ltr .fc-h-event .fc-start-resizer, 516 | .fc-rtl .fc-h-event .fc-end-resizer { 517 | cursor: w-resize; 518 | left: -1px; 519 | /* overcome border */ 520 | } 521 | 522 | /* right resizer */ 523 | .fc-ltr .fc-h-event .fc-end-resizer, 524 | .fc-rtl .fc-h-event .fc-start-resizer { 525 | cursor: e-resize; 526 | right: -1px; 527 | /* overcome border */ 528 | } 529 | 530 | /* resizer (mouse devices) */ 531 | .fc-h-event.fc-allow-mouse-resize .fc-resizer { 532 | width: 7px; 533 | top: -1px; 534 | /* overcome top border */ 535 | bottom: -1px; 536 | /* overcome bottom border */ 537 | } 538 | 539 | /* resizer (touch devices) */ 540 | .fc-h-event.fc-selected .fc-resizer { 541 | /* 8x8 little dot */ 542 | border-radius: 4px; 543 | border-width: 1px; 544 | width: 6px; 545 | height: 6px; 546 | border-style: solid; 547 | border-color: inherit; 548 | background: #fff; 549 | /* vertically center */ 550 | top: 50%; 551 | margin-top: -4px; 552 | } 553 | 554 | /* left resizer */ 555 | .fc-ltr .fc-h-event.fc-selected .fc-start-resizer, 556 | .fc-rtl .fc-h-event.fc-selected .fc-end-resizer { 557 | margin-left: -4px; 558 | /* centers the 8x8 dot on the left edge */ 559 | } 560 | 561 | /* right resizer */ 562 | .fc-ltr .fc-h-event.fc-selected .fc-end-resizer, 563 | .fc-rtl .fc-h-event.fc-selected .fc-start-resizer { 564 | margin-right: -4px; 565 | /* centers the 8x8 dot on the right edge */ 566 | } 567 | 568 | /* DayGrid events 569 | ---------------------------------------------------------------------------------------------------- 570 | We use the full "fc-day-grid-event" class instead of using descendants because the event won't 571 | be a descendant of the grid when it is being dragged. 572 | */ 573 | .fc-day-grid-event { 574 | margin: 1px 2px 0; 575 | /* spacing between events and edges */ 576 | padding: 0 1px; 577 | } 578 | 579 | tr:first-child>td>.fc-day-grid-event { 580 | margin-top: 2px; 581 | /* a little bit more space before the first event */ 582 | } 583 | 584 | .fc-day-grid-event.fc-selected:after { 585 | content: ""; 586 | position: absolute; 587 | z-index: 1; 588 | /* same z-index as fc-bg, behind text */ 589 | /* overcome the borders */ 590 | top: -1px; 591 | right: -1px; 592 | bottom: -1px; 593 | left: -1px; 594 | /* darkening effect */ 595 | background: #000; 596 | opacity: .25; 597 | } 598 | 599 | .fc-day-grid-event .fc-content { 600 | /* force events to be one-line tall */ 601 | white-space: nowrap; 602 | overflow: hidden; 603 | } 604 | 605 | .fc-day-grid-event .fc-time { 606 | font-weight: bold; 607 | } 608 | 609 | /* resizer (cursor devices) */ 610 | /* left resizer */ 611 | .fc-ltr .fc-day-grid-event.fc-allow-mouse-resize .fc-start-resizer, 612 | .fc-rtl .fc-day-grid-event.fc-allow-mouse-resize .fc-end-resizer { 613 | margin-left: -2px; 614 | /* to the day cell's edge */ 615 | } 616 | 617 | /* right resizer */ 618 | .fc-ltr .fc-day-grid-event.fc-allow-mouse-resize .fc-end-resizer, 619 | .fc-rtl .fc-day-grid-event.fc-allow-mouse-resize .fc-start-resizer { 620 | margin-right: -2px; 621 | /* to the day cell's edge */ 622 | } 623 | 624 | /* Event Limiting 625 | --------------------------------------------------------------------------------------------------*/ 626 | /* "more" link that represents hidden events */ 627 | a.fc-more { 628 | margin: 1px 3px; 629 | font-size: .85em; 630 | cursor: pointer; 631 | text-decoration: none; 632 | } 633 | 634 | a.fc-more:hover { 635 | text-decoration: underline; 636 | } 637 | 638 | .fc-limited { 639 | /* rows and cells that are hidden because of a "more" link */ 640 | display: none; 641 | } 642 | 643 | /* popover that appears when "more" link is clicked */ 644 | .fc-day-grid .fc-row { 645 | z-index: 1; 646 | /* make the "more" popover one higher than this */ 647 | } 648 | 649 | .fc-more-popover { 650 | z-index: 2; 651 | width: 220px; 652 | } 653 | 654 | .fc-more-popover .fc-event-container { 655 | padding: 10px; 656 | } 657 | 658 | /* Now Indicator 659 | --------------------------------------------------------------------------------------------------*/ 660 | .fc-now-indicator { 661 | position: absolute; 662 | border: 0 solid red; 663 | } 664 | 665 | /* Utilities 666 | --------------------------------------------------------------------------------------------------*/ 667 | .fc-unselectable { 668 | -webkit-user-select: none; 669 | -khtml-user-select: none; 670 | -moz-user-select: none; 671 | -ms-user-select: none; 672 | user-select: none; 673 | -webkit-touch-callout: none; 674 | -webkit-tap-highlight-color: transparent; 675 | } 676 | 677 | /* 678 | TODO: more distinction between this file and common.css 679 | */ 680 | /* Colors 681 | --------------------------------------------------------------------------------------------------*/ 682 | .fc-unthemed th, 683 | .fc-unthemed td, 684 | .fc-unthemed thead, 685 | .fc-unthemed tbody, 686 | .fc-unthemed .fc-divider, 687 | .fc-unthemed .fc-row, 688 | .fc-unthemed .fc-content, 689 | .fc-unthemed .fc-popover, 690 | .fc-unthemed .fc-list-view, 691 | .fc-unthemed .fc-list-heading td { 692 | border-color: #ddd; 693 | } 694 | 695 | .fc-unthemed .fc-popover { 696 | background-color: #fff; 697 | } 698 | 699 | .fc-unthemed .fc-divider, 700 | .fc-unthemed .fc-popover .fc-header, 701 | .fc-unthemed .fc-list-heading td { 702 | background: #eee; 703 | } 704 | 705 | .fc-unthemed .fc-popover .fc-header .fc-close { 706 | color: #666; 707 | } 708 | 709 | .fc-unthemed td.fc-today { 710 | background: #fcf8e3; 711 | } 712 | 713 | .fc-unthemed .fc-disabled-day { 714 | background: #d7d7d7; 715 | opacity: .3; 716 | } 717 | 718 | /* Icons (inline elements with styled text that mock arrow icons) 719 | --------------------------------------------------------------------------------------------------*/ 720 | .fc-icon { 721 | display: inline-block; 722 | height: 1em; 723 | line-height: 1em; 724 | font-size: 1em; 725 | text-align: center; 726 | overflow: hidden; 727 | font-family: "Courier New", Courier, monospace; 728 | /* don't allow browser text-selection */ 729 | -webkit-touch-callout: none; 730 | -webkit-user-select: none; 731 | -khtml-user-select: none; 732 | -moz-user-select: none; 733 | -ms-user-select: none; 734 | user-select: none; 735 | } 736 | 737 | /* 738 | Acceptable font-family overrides for individual icons: 739 | "Arial", sans-serif 740 | "Times New Roman", serif 741 | NOTE: use percentage font sizes or else old IE chokes 742 | */ 743 | .fc-icon:after { 744 | position: relative; 745 | } 746 | 747 | .fc-icon-left-single-arrow:after { 748 | content: "\2039"; 749 | font-weight: bold; 750 | font-size: 200%; 751 | top: -7%; 752 | } 753 | 754 | .fc-icon-right-single-arrow:after { 755 | content: "\203A"; 756 | font-weight: bold; 757 | font-size: 200%; 758 | top: -7%; 759 | } 760 | 761 | .fc-icon-left-double-arrow:after { 762 | content: "\AB"; 763 | font-size: 160%; 764 | top: -7%; 765 | } 766 | 767 | .fc-icon-right-double-arrow:after { 768 | content: "\BB"; 769 | font-size: 160%; 770 | top: -7%; 771 | } 772 | 773 | .fc-icon-left-triangle:after { 774 | content: "\25C4"; 775 | font-size: 125%; 776 | top: 3%; 777 | } 778 | 779 | .fc-icon-right-triangle:after { 780 | content: "\25BA"; 781 | font-size: 125%; 782 | top: 3%; 783 | } 784 | 785 | .fc-icon-down-triangle:after { 786 | content: "\25BC"; 787 | font-size: 125%; 788 | top: 2%; 789 | } 790 | 791 | .fc-icon-x:after { 792 | content: "\D7"; 793 | font-size: 200%; 794 | top: 6%; 795 | } 796 | 797 | /* Popover 798 | --------------------------------------------------------------------------------------------------*/ 799 | .fc-unthemed .fc-popover { 800 | border-width: 1px; 801 | border-style: solid; 802 | } 803 | 804 | .fc-unthemed .fc-popover .fc-header .fc-close { 805 | font-size: .9em; 806 | margin-top: 2px; 807 | } 808 | 809 | /* List View 810 | --------------------------------------------------------------------------------------------------*/ 811 | .fc-unthemed .fc-list-item:hover td { 812 | background-color: #f5f5f5; 813 | } 814 | 815 | /* Colors 816 | --------------------------------------------------------------------------------------------------*/ 817 | .ui-widget .fc-disabled-day { 818 | background-image: none; 819 | } 820 | 821 | /* Popover 822 | --------------------------------------------------------------------------------------------------*/ 823 | .fc-popover>.ui-widget-header+.ui-widget-content { 824 | border-top: 0; 825 | /* where they meet, let the header have the border */ 826 | } 827 | 828 | /* Global Event Styles 829 | --------------------------------------------------------------------------------------------------*/ 830 | .ui-widget .fc-event { 831 | /* overpower jqui's styles on tags. TODO: more DRY */ 832 | color: #fff; 833 | /* default TEXT color */ 834 | text-decoration: none; 835 | /* if has an href */ 836 | /* undo ui-widget-header bold */ 837 | font-weight: normal; 838 | } 839 | 840 | /* TimeGrid axis running down the side (for both the all-day area and the slot area) 841 | --------------------------------------------------------------------------------------------------*/ 842 | .ui-widget td.fc-axis { 843 | font-weight: normal; 844 | /* overcome bold */ 845 | } 846 | 847 | /* TimeGrid Slats (lines that run horizontally) 848 | --------------------------------------------------------------------------------------------------*/ 849 | .fc-time-grid .fc-slats .ui-widget-content { 850 | background: none; 851 | /* see through to fc-bg */ 852 | } 853 | 854 | .fc.fc-bootstrap3 a { 855 | text-decoration: none; 856 | } 857 | 858 | .fc.fc-bootstrap3 a[data-goto]:hover { 859 | text-decoration: underline; 860 | } 861 | 862 | .fc-bootstrap3 hr.fc-divider { 863 | border-color: inherit; 864 | } 865 | 866 | .fc-bootstrap3 .fc-today.alert { 867 | border-radius: 0; 868 | } 869 | 870 | /* Popover 871 | --------------------------------------------------------------------------------------------------*/ 872 | .fc-bootstrap3 .fc-popover .panel-body { 873 | padding: 0; 874 | } 875 | 876 | /* TimeGrid Slats (lines that run horizontally) 877 | --------------------------------------------------------------------------------------------------*/ 878 | .fc-bootstrap3 .fc-time-grid .fc-slats table { 879 | /* some themes have background color. see through to slats */ 880 | background: none; 881 | } 882 | 883 | .fc.fc-bootstrap4 a { 884 | text-decoration: none; 885 | } 886 | 887 | .fc.fc-bootstrap4 a[data-goto]:hover { 888 | text-decoration: underline; 889 | } 890 | 891 | .fc-bootstrap4 hr.fc-divider { 892 | border-color: inherit; 893 | } 894 | 895 | .fc-bootstrap4 .fc-today.alert { 896 | border-radius: 0; 897 | } 898 | 899 | .fc-bootstrap4 a.fc-event:not([href]):not([tabindex]) { 900 | color: #fff; 901 | } 902 | 903 | .fc-bootstrap4 .fc-popover.card { 904 | position: absolute; 905 | } 906 | 907 | /* Popover 908 | --------------------------------------------------------------------------------------------------*/ 909 | .fc-bootstrap4 .fc-popover .card-body { 910 | padding: 0; 911 | } 912 | 913 | /* TimeGrid Slats (lines that run horizontally) 914 | --------------------------------------------------------------------------------------------------*/ 915 | .fc-bootstrap4 .fc-time-grid .fc-slats table { 916 | /* some themes have background color. see through to slats */ 917 | background: none; 918 | } 919 | 920 | /* Toolbar 921 | --------------------------------------------------------------------------------------------------*/ 922 | .fc-toolbar { 923 | text-align: center; 924 | } 925 | 926 | .fc-toolbar.fc-header-toolbar { 927 | margin-bottom: 1em; 928 | } 929 | 930 | .fc-toolbar.fc-footer-toolbar { 931 | margin-top: 1em; 932 | } 933 | 934 | .fc-toolbar .fc-left { 935 | float: left; 936 | } 937 | 938 | .fc-toolbar .fc-right { 939 | float: right; 940 | } 941 | 942 | .fc-toolbar .fc-center { 943 | display: inline-block; 944 | } 945 | 946 | /* the things within each left/right/center section */ 947 | .fc .fc-toolbar>*>* { 948 | /* extra precedence to override button border margins */ 949 | float: left; 950 | margin-left: .75em; 951 | } 952 | 953 | /* the first thing within each left/center/right section */ 954 | .fc .fc-toolbar>*> :first-child { 955 | /* extra precedence to override button border margins */ 956 | margin-left: 0; 957 | } 958 | 959 | /* title text */ 960 | .fc-toolbar h2 { 961 | margin: 0; 962 | } 963 | 964 | /* button layering (for border precedence) */ 965 | .fc-toolbar button { 966 | position: relative; 967 | } 968 | 969 | .fc-toolbar .fc-state-hover, 970 | .fc-toolbar .ui-state-hover { 971 | z-index: 2; 972 | } 973 | 974 | .fc-toolbar .fc-state-down { 975 | z-index: 3; 976 | } 977 | 978 | .fc-toolbar .fc-state-active, 979 | .fc-toolbar .ui-state-active { 980 | z-index: 4; 981 | } 982 | 983 | .fc-toolbar button:focus { 984 | z-index: 5; 985 | } 986 | 987 | /* View Structure 988 | --------------------------------------------------------------------------------------------------*/ 989 | /* undo twitter bootstrap's box-sizing rules. normalizes positioning techniques */ 990 | /* don't do this for the toolbar because we'll want bootstrap to style those buttons as some pt */ 991 | .fc-view-container *, 992 | .fc-view-container *:before, 993 | .fc-view-container *:after { 994 | -webkit-box-sizing: content-box; 995 | -moz-box-sizing: content-box; 996 | box-sizing: content-box; 997 | } 998 | 999 | .fc-view, 1000 | .fc-view>table { 1001 | /* so dragged elements can be above the view's main element */ 1002 | position: relative; 1003 | z-index: 1; 1004 | } 1005 | 1006 | /* BasicView 1007 | --------------------------------------------------------------------------------------------------*/ 1008 | /* day row structure */ 1009 | .fc-basicWeek-view .fc-content-skeleton, 1010 | .fc-basicDay-view .fc-content-skeleton { 1011 | /* there may be week numbers in these views, so no padding-top */ 1012 | padding-bottom: 1em; 1013 | /* ensure a space at bottom of cell for user selecting/clicking */ 1014 | } 1015 | 1016 | .fc-basic-view .fc-body .fc-row { 1017 | min-height: 4em; 1018 | /* ensure that all rows are at least this tall */ 1019 | } 1020 | 1021 | /* a "rigid" row will take up a constant amount of height because content-skeleton is absolute */ 1022 | .fc-row.fc-rigid { 1023 | overflow: hidden; 1024 | } 1025 | 1026 | .fc-row.fc-rigid .fc-content-skeleton { 1027 | position: absolute; 1028 | top: 0; 1029 | left: 0; 1030 | right: 0; 1031 | } 1032 | 1033 | /* week and day number styling */ 1034 | .fc-day-top.fc-other-month { 1035 | opacity: 0.3; 1036 | } 1037 | 1038 | .fc-basic-view .fc-week-number, 1039 | .fc-basic-view .fc-day-number { 1040 | padding: 2px; 1041 | } 1042 | 1043 | .fc-basic-view th.fc-week-number, 1044 | .fc-basic-view th.fc-day-number { 1045 | padding: 0 2px; 1046 | /* column headers can't have as much v space */ 1047 | } 1048 | 1049 | .fc-ltr .fc-basic-view .fc-day-top .fc-day-number { 1050 | float: right; 1051 | } 1052 | 1053 | .fc-rtl .fc-basic-view .fc-day-top .fc-day-number { 1054 | float: left; 1055 | } 1056 | 1057 | .fc-ltr .fc-basic-view .fc-day-top .fc-week-number { 1058 | float: left; 1059 | border-radius: 0 0 3px 0; 1060 | } 1061 | 1062 | .fc-rtl .fc-basic-view .fc-day-top .fc-week-number { 1063 | float: right; 1064 | border-radius: 0 0 0 3px; 1065 | } 1066 | 1067 | .fc-basic-view .fc-day-top .fc-week-number { 1068 | min-width: 1.5em; 1069 | text-align: center; 1070 | background-color: #f2f2f2; 1071 | color: #808080; 1072 | } 1073 | 1074 | /* when week/day number have own column */ 1075 | .fc-basic-view td.fc-week-number { 1076 | text-align: center; 1077 | } 1078 | 1079 | .fc-basic-view td.fc-week-number>* { 1080 | /* work around the way we do column resizing and ensure a minimum width */ 1081 | display: inline-block; 1082 | min-width: 1.25em; 1083 | } 1084 | 1085 | /* AgendaView all-day area 1086 | --------------------------------------------------------------------------------------------------*/ 1087 | .fc-agenda-view .fc-day-grid { 1088 | position: relative; 1089 | z-index: 2; 1090 | /* so the "more.." popover will be over the time grid */ 1091 | } 1092 | 1093 | .fc-agenda-view .fc-day-grid .fc-row { 1094 | min-height: 3em; 1095 | /* all-day section will never get shorter than this */ 1096 | } 1097 | 1098 | .fc-agenda-view .fc-day-grid .fc-row .fc-content-skeleton { 1099 | padding-bottom: 1em; 1100 | /* give space underneath events for clicking/selecting days */ 1101 | } 1102 | 1103 | /* TimeGrid axis running down the side (for both the all-day area and the slot area) 1104 | --------------------------------------------------------------------------------------------------*/ 1105 | .fc .fc-axis { 1106 | /* .fc to overcome default cell styles */ 1107 | vertical-align: middle; 1108 | padding: 0 4px; 1109 | white-space: nowrap; 1110 | } 1111 | 1112 | .fc-ltr .fc-axis { 1113 | text-align: right; 1114 | } 1115 | 1116 | .fc-rtl .fc-axis { 1117 | text-align: left; 1118 | } 1119 | 1120 | /* TimeGrid Structure 1121 | --------------------------------------------------------------------------------------------------*/ 1122 | .fc-time-grid-container, 1123 | .fc-time-grid { 1124 | /* so slats/bg/content/etc positions get scoped within here */ 1125 | position: relative; 1126 | z-index: 1; 1127 | } 1128 | 1129 | .fc-time-grid { 1130 | min-height: 100%; 1131 | /* so if height setting is 'auto', .fc-bg stretches to fill height */ 1132 | } 1133 | 1134 | .fc-time-grid table { 1135 | /* don't put outer borders on slats/bg/content/etc */ 1136 | border: 0 hidden transparent; 1137 | } 1138 | 1139 | .fc-time-grid>.fc-bg { 1140 | z-index: 1; 1141 | } 1142 | 1143 | .fc-time-grid .fc-slats, 1144 | .fc-time-grid>hr { 1145 | /* the AgendaView injects when grid is shorter than scroller */ 1146 | position: relative; 1147 | z-index: 2; 1148 | } 1149 | 1150 | .fc-time-grid .fc-content-col { 1151 | position: relative; 1152 | /* because now-indicator lives directly inside */ 1153 | } 1154 | 1155 | .fc-time-grid .fc-content-skeleton { 1156 | position: absolute; 1157 | z-index: 3; 1158 | top: 0; 1159 | left: 0; 1160 | right: 0; 1161 | } 1162 | 1163 | /* divs within a cell within the fc-content-skeleton */ 1164 | .fc-time-grid .fc-business-container { 1165 | position: relative; 1166 | z-index: 1; 1167 | } 1168 | 1169 | .fc-time-grid .fc-bgevent-container { 1170 | position: relative; 1171 | z-index: 2; 1172 | } 1173 | 1174 | .fc-time-grid .fc-highlight-container { 1175 | position: relative; 1176 | z-index: 3; 1177 | } 1178 | 1179 | .fc-time-grid .fc-event-container { 1180 | position: relative; 1181 | z-index: 4; 1182 | } 1183 | 1184 | .fc-time-grid .fc-now-indicator-line { 1185 | z-index: 5; 1186 | } 1187 | 1188 | .fc-time-grid .fc-helper-container { 1189 | /* also is fc-event-container */ 1190 | position: relative; 1191 | z-index: 6; 1192 | } 1193 | 1194 | /* TimeGrid Slats (lines that run horizontally) 1195 | --------------------------------------------------------------------------------------------------*/ 1196 | .fc-time-grid .fc-slats td { 1197 | height: 1.5em; 1198 | border-bottom: 0; 1199 | /* each cell is responsible for its top border */ 1200 | } 1201 | 1202 | .fc-time-grid .fc-slats .fc-minor td { 1203 | border-top-style: dotted; 1204 | } 1205 | 1206 | /* TimeGrid Highlighting Slots 1207 | --------------------------------------------------------------------------------------------------*/ 1208 | .fc-time-grid .fc-highlight-container { 1209 | /* a div within a cell within the fc-highlight-skeleton */ 1210 | position: relative; 1211 | /* scopes the left/right of the fc-highlight to be in the column */ 1212 | } 1213 | 1214 | .fc-time-grid .fc-highlight { 1215 | position: absolute; 1216 | left: 0; 1217 | right: 0; 1218 | /* top and bottom will be in by JS */ 1219 | } 1220 | 1221 | /* TimeGrid Event Containment 1222 | --------------------------------------------------------------------------------------------------*/ 1223 | .fc-ltr .fc-time-grid .fc-event-container { 1224 | /* space on the sides of events for LTR (default) */ 1225 | margin: 0 2.5% 0 2px; 1226 | } 1227 | 1228 | .fc-rtl .fc-time-grid .fc-event-container { 1229 | /* space on the sides of events for RTL */ 1230 | margin: 0 2px 0 2.5%; 1231 | } 1232 | 1233 | .fc-time-grid .fc-event, 1234 | .fc-time-grid .fc-bgevent { 1235 | position: absolute; 1236 | z-index: 1; 1237 | /* scope inner z-index's */ 1238 | } 1239 | 1240 | .fc-time-grid .fc-bgevent { 1241 | /* background events always span full width */ 1242 | left: 0; 1243 | right: 0; 1244 | } 1245 | 1246 | /* Generic Vertical Event 1247 | --------------------------------------------------------------------------------------------------*/ 1248 | .fc-v-event.fc-not-start { 1249 | /* events that are continuing from another day */ 1250 | /* replace space made by the top border with padding */ 1251 | border-top-width: 0; 1252 | padding-top: 1px; 1253 | /* remove top rounded corners */ 1254 | border-top-left-radius: 0; 1255 | border-top-right-radius: 0; 1256 | } 1257 | 1258 | .fc-v-event.fc-not-end { 1259 | /* replace space made by the top border with padding */ 1260 | border-bottom-width: 0; 1261 | padding-bottom: 1px; 1262 | /* remove bottom rounded corners */ 1263 | border-bottom-left-radius: 0; 1264 | border-bottom-right-radius: 0; 1265 | } 1266 | 1267 | /* TimeGrid Event Styling 1268 | ---------------------------------------------------------------------------------------------------- 1269 | We use the full "fc-time-grid-event" class instead of using descendants because the event won't 1270 | be a descendant of the grid when it is being dragged. 1271 | */ 1272 | .fc-time-grid-event { 1273 | overflow: hidden; 1274 | /* don't let the bg flow over rounded corners */ 1275 | } 1276 | 1277 | .fc-time-grid-event.fc-selected { 1278 | /* need to allow touch resizers to extend outside event's bounding box */ 1279 | /* common fc-selected styles hide the fc-bg, so don't need this anyway */ 1280 | overflow: visible; 1281 | } 1282 | 1283 | .fc-time-grid-event.fc-selected .fc-bg { 1284 | display: none; 1285 | /* hide semi-white background, to appear darker */ 1286 | } 1287 | 1288 | .fc-time-grid-event .fc-content { 1289 | overflow: hidden; 1290 | /* for when .fc-selected */ 1291 | } 1292 | 1293 | .fc-time-grid-event .fc-time, 1294 | .fc-time-grid-event .fc-title { 1295 | padding: 0 1px; 1296 | } 1297 | 1298 | .fc-time-grid-event .fc-time { 1299 | font-size: .85em; 1300 | white-space: nowrap; 1301 | } 1302 | 1303 | /* short mode, where time and title are on the same line */ 1304 | .fc-time-grid-event.fc-short .fc-content { 1305 | /* don't wrap to second line (now that contents will be inline) */ 1306 | white-space: nowrap; 1307 | } 1308 | 1309 | .fc-time-grid-event.fc-short .fc-time, 1310 | .fc-time-grid-event.fc-short .fc-title { 1311 | /* put the time and title on the same line */ 1312 | display: inline-block; 1313 | vertical-align: top; 1314 | } 1315 | 1316 | .fc-time-grid-event.fc-short .fc-time span { 1317 | display: none; 1318 | /* don't display the full time text... */ 1319 | } 1320 | 1321 | .fc-time-grid-event.fc-short .fc-time:before { 1322 | content: attr(data-start); 1323 | /* ...instead, display only the start time */ 1324 | } 1325 | 1326 | .fc-time-grid-event.fc-short .fc-time:after { 1327 | content: "\A0-\A0"; 1328 | /* seperate with a dash, wrapped in nbsp's */ 1329 | } 1330 | 1331 | .fc-time-grid-event.fc-short .fc-title { 1332 | font-size: .85em; 1333 | /* make the title text the same size as the time */ 1334 | padding: 0; 1335 | /* undo padding from above */ 1336 | } 1337 | 1338 | /* resizer (cursor device) */ 1339 | .fc-time-grid-event.fc-allow-mouse-resize .fc-resizer { 1340 | left: 0; 1341 | right: 0; 1342 | bottom: 0; 1343 | height: 8px; 1344 | overflow: hidden; 1345 | line-height: 8px; 1346 | font-size: 11px; 1347 | font-family: monospace; 1348 | text-align: center; 1349 | cursor: s-resize; 1350 | } 1351 | 1352 | .fc-time-grid-event.fc-allow-mouse-resize .fc-resizer:after { 1353 | content: "="; 1354 | } 1355 | 1356 | /* resizer (touch device) */ 1357 | .fc-time-grid-event.fc-selected .fc-resizer { 1358 | /* 10x10 dot */ 1359 | border-radius: 5px; 1360 | border-width: 1px; 1361 | width: 8px; 1362 | height: 8px; 1363 | border-style: solid; 1364 | border-color: inherit; 1365 | background: #fff; 1366 | /* horizontally center */ 1367 | left: 50%; 1368 | margin-left: -5px; 1369 | /* center on the bottom edge */ 1370 | bottom: -5px; 1371 | } 1372 | 1373 | /* Now Indicator 1374 | --------------------------------------------------------------------------------------------------*/ 1375 | .fc-time-grid .fc-now-indicator-line { 1376 | border-top-width: 1px; 1377 | left: 0; 1378 | right: 0; 1379 | } 1380 | 1381 | /* arrow on axis */ 1382 | .fc-time-grid .fc-now-indicator-arrow { 1383 | margin-top: -5px; 1384 | /* vertically center on top coordinate */ 1385 | } 1386 | 1387 | .fc-ltr .fc-time-grid .fc-now-indicator-arrow { 1388 | left: 0; 1389 | /* triangle pointing right... */ 1390 | border-width: 5px 0 5px 6px; 1391 | border-top-color: transparent; 1392 | border-bottom-color: transparent; 1393 | } 1394 | 1395 | .fc-rtl .fc-time-grid .fc-now-indicator-arrow { 1396 | right: 0; 1397 | /* triangle pointing left... */ 1398 | border-width: 5px 6px 5px 0; 1399 | border-top-color: transparent; 1400 | border-bottom-color: transparent; 1401 | } 1402 | 1403 | /* List View 1404 | --------------------------------------------------------------------------------------------------*/ 1405 | /* possibly reusable */ 1406 | .fc-event-dot { 1407 | display: inline-block; 1408 | width: 10px; 1409 | height: 10px; 1410 | border-radius: 5px; 1411 | } 1412 | 1413 | /* view wrapper */ 1414 | .fc-rtl .fc-list-view { 1415 | direction: rtl; 1416 | /* unlike core views, leverage browser RTL */ 1417 | } 1418 | 1419 | .fc-list-view { 1420 | border-width: 1px; 1421 | border-style: solid; 1422 | } 1423 | 1424 | /* table resets */ 1425 | .fc .fc-list-table { 1426 | table-layout: auto; 1427 | /* for shrinkwrapping cell content */ 1428 | } 1429 | 1430 | .fc-list-table td { 1431 | border-width: 1px 0 0; 1432 | padding: 8px 14px; 1433 | } 1434 | 1435 | .fc-list-table tr:first-child td { 1436 | border-top-width: 0; 1437 | } 1438 | 1439 | /* day headings with the list */ 1440 | .fc-list-heading { 1441 | border-bottom-width: 1px; 1442 | } 1443 | 1444 | .fc-list-heading td { 1445 | font-weight: bold; 1446 | } 1447 | 1448 | .fc-ltr .fc-list-heading-main { 1449 | float: left; 1450 | } 1451 | 1452 | .fc-ltr .fc-list-heading-alt { 1453 | float: right; 1454 | } 1455 | 1456 | .fc-rtl .fc-list-heading-main { 1457 | float: right; 1458 | } 1459 | 1460 | .fc-rtl .fc-list-heading-alt { 1461 | float: left; 1462 | } 1463 | 1464 | /* event list items */ 1465 | .fc-list-item.fc-has-url { 1466 | cursor: pointer; 1467 | /* whole row will be clickable */ 1468 | } 1469 | 1470 | .fc-list-item-marker, 1471 | .fc-list-item-time { 1472 | white-space: nowrap; 1473 | width: 1px; 1474 | } 1475 | 1476 | /* make the dot closer to the event title */ 1477 | .fc-ltr .fc-list-item-marker { 1478 | padding-right: 0; 1479 | } 1480 | 1481 | .fc-rtl .fc-list-item-marker { 1482 | padding-left: 0; 1483 | } 1484 | 1485 | .fc-list-item-title a { 1486 | /* every event title cell has an tag */ 1487 | text-decoration: none; 1488 | color: inherit; 1489 | } 1490 | 1491 | .fc-list-item-title a[href]:hover { 1492 | /* hover effect only on titles with hrefs */ 1493 | text-decoration: underline; 1494 | } 1495 | 1496 | /* message when no events */ 1497 | .fc-list-empty-wrap2 { 1498 | position: absolute; 1499 | top: 0; 1500 | left: 0; 1501 | right: 0; 1502 | bottom: 0; 1503 | } 1504 | 1505 | .fc-list-empty-wrap1 { 1506 | width: 100%; 1507 | height: 100%; 1508 | display: table; 1509 | } 1510 | 1511 | .fc-list-empty { 1512 | display: table-cell; 1513 | vertical-align: middle; 1514 | text-align: center; 1515 | } 1516 | 1517 | .fc-unthemed .fc-list-empty { 1518 | /* theme will provide own background */ 1519 | background-color: #eee; 1520 | } 1521 | -------------------------------------------------------------------------------- /components/index.js: -------------------------------------------------------------------------------- 1 | import LunarFullCalendar from './LunarFullCalendar/LunarFullCalendar.vue' 2 | 3 | const install = (Vue) => { 4 | Vue.component('lunar-full-calendar', LunarFullCalendar) 5 | } 6 | module.exports = { 7 | install, 8 | LunarFullCalendar 9 | } 10 | module.exports.default = module.exports 11 | // export default { 12 | // install, 13 | // LunarFullCalendar 14 | // } 15 | 16 | // export { 17 | // install, 18 | // LunarFullCalendar 19 | // } 20 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | // assetsPublicPath: '/vue-lunar-fullcalendar/', 55 | 56 | /** 57 | * Source Maps 58 | */ 59 | 60 | productionSourceMap: true, 61 | // https://webpack.js.org/configuration/devtool/#production 62 | devtool: '#source-map', 63 | 64 | // Gzip off by default as many popular static hosts such as 65 | // Surge or Netlify already gzip all static assets for you. 66 | // Before setting to `true`, make sure to: 67 | // npm install --save-dev compression-webpack-plugin 68 | productionGzip: false, 69 | productionGzipExtensions: ['js', 'css'], 70 | 71 | // Run the build command with an extra argument to 72 | // View the bundle analyzer report after build finishes: 73 | // `npm run build --report` 74 | // Set to `true` or `false` to always turn it on or off 75 | bundleAnalyzerReport: process.env.npm_config_report 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /config/prod.env.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | module.exports = { 3 | NODE_ENV: '"production"' 4 | } 5 | -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 中国节假日和农历日程控件 -------------------------------------------------------------------------------- /docs/static/img/lunar.b0e3d9b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hjdev/vue-lunar-fullcalendar/319227b238f3df1461219b5823d2c1b43d405b9f/docs/static/img/lunar.b0e3d9b.png -------------------------------------------------------------------------------- /docs/static/js/4.22a5aaaa784121c40a27.js: -------------------------------------------------------------------------------- 1 | (window.webpackJsonp=window.webpackJsonp||[]).push([[4],{"8reR":function(t,a,n){"use strict";n.r(a);var e=n("IIpD"),r=n.n(e);for(var i in e)"default"!==i&&function(t){n.d(a,t,(function(){return e[t]}))}(i);a.default=r.a},A1T1:function(t,a,n){"use strict";var e=function(){var t=this.$createElement,a=this._self._c||t;return a("div",{staticClass:"explain"},[this._m(0),this._v(" "),a("img",{staticClass:"lunarImg",attrs:{src:n("gtPt"),alt:""}}),this._v(" "),a("div",[a("span",{staticClass:"back",on:{click:this.back}},[this._v("back")])])])},r=[function(){var t=this,a=t.$createElement,n=t._self._c||a;return n("div",{staticClass:"top"},[n("h2",[t._v("增加中国农历、24节气和节假日的功能")]),t._v(" "),n("h2",[t._v("npm install vue-lunar-full-calendar")]),t._v(" "),n("div",[t._v("A vue component for lunar fullcalendar. Uses Moment.js for date operations.(Increase the functions of Chinese lunar calendar, 24 solar terms and holidays)")]),t._v(" "),n("div",{staticClass:"red"},[t._v("window.lunar(date) 使用此依赖包可以使用这个功能获取农历的信息date是时间日期")]),t._v(" "),n("div",{staticClass:"red"},[t._v("config属性下新增了一个开启或者隐藏农历的功能字段lunarCalendar(lunarCalendar控制是否显示中国农历、显示的为true,隐藏为flase,默认为true)")]),t._v(" "),n("div",[t._v("其它功能可以参照"),n("a",{attrs:{href:"https://fullcalendar.io/docs",target:"_blank"}},[t._v("https://fullcalendar.io/docs")]),t._v(" 这个链接为官方的API文档去熟悉")])])}];n.d(a,"a",(function(){return e})),n.d(a,"b",(function(){return r}))},DVgg:function(t,a,n){var e=n("IYkF");"string"==typeof e&&(e=[[t.i,e,""]]);var r={insert:"head",singleton:!1};n("LboF")(e,r);e.locals&&(t.exports=e.locals)},IIpD:function(t,a,n){"use strict";Object.defineProperty(a,"__esModule",{value:!0}),a.default={methods:{back:function(){this.$router.push("/vue-lunar-fullCalendar")}}}},IYkF:function(t,a,n){(t.exports=n("I1BE")(!1)).push([t.i,".explain[data-v-533888f5]{font-size:14px;text-align:center}.explain h2[data-v-533888f5]{text-align:center}.explain div[data-v-533888f5]{text-indent:20px}.explain a[data-v-533888f5]{color:#409eff}.explain .back[data-v-533888f5]{cursor:pointer;display:inline-block;margin-top:40px;color:#45b984;font-size:15px}.explain .lunarImg[data-v-533888f5]{height:380px}.explain .red[data-v-533888f5]{color:#ff0000}\n",""])},VAsf:function(t,a,n){"use strict";var e=n("DVgg");n.n(e).a},"WJ/M":function(t,a,n){"use strict";n.r(a);var e=n("A1T1"),r=n("8reR");for(var i in r)"default"!==i&&function(t){n.d(a,t,(function(){return r[t]}))}(i);n("VAsf");var s=n("KHd+"),l=Object(s.a)(r.default,e.a,e.b,!1,null,"533888f5",null);a.default=l.exports},gtPt:function(t,a,n){t.exports=n.p+"static/img/lunar.b0e3d9b.png"}}]); 2 | //# sourceMappingURL=4.22a5aaaa784121c40a27.js.map -------------------------------------------------------------------------------- /docs/static/js/4.22a5aaaa784121c40a27.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["webpack:///./src/view/explain.vue?ba08","webpack:///./src/view/explain.vue?393b","webpack:///./src/view/explain.vue?46c0","webpack:///./src/view/explain.vue?47b5","webpack:///src/view/explain.vue","webpack:///./src/view/explain.vue?7d2e","webpack:///./src/view/explain.vue?714c","webpack:///./src/view/explain.vue","webpack:///./src/assets/img/lunar.png"],"names":["render","_h","this","$createElement","_c","_self","staticClass","_m","_v","attrs","on","back","staticRenderFns","_vm","content","module","i","options","locals","exports","methods","$router","push","component"],"mappings":"6FAAA,iHAAuL,YAAG,G,kCCA1L,IAAIA,EAAS,WAAa,IAAiBC,EAATC,KAAgBC,eAAmBC,EAAnCF,KAA0CG,MAAMD,IAAIH,EAAG,OAAOG,EAAG,MAAM,CAACE,YAAY,WAAW,CAA/FJ,KAAoGK,GAAG,GAAvGL,KAA8GM,GAAG,KAAKJ,EAAG,MAAM,CAACE,YAAY,WAAWG,MAAM,CAAC,IAAM,EAAQ,QAA0B,IAAM,MAA5MP,KAAsNM,GAAG,KAAKJ,EAAG,MAAM,CAACA,EAAG,OAAO,CAACE,YAAY,OAAOI,GAAG,CAAC,MAA1QR,KAAsRS,OAAO,CAA7RT,KAAkSM,GAAG,eACnUI,EAAkB,CAAC,WAAa,IAAIC,EAAIX,KAASD,EAAGY,EAAIV,eAAmBC,EAAGS,EAAIR,MAAMD,IAAIH,EAAG,OAAOG,EAAG,MAAM,CAACE,YAAY,OAAO,CAACF,EAAG,KAAK,CAACS,EAAIL,GAAG,wBAAwBK,EAAIL,GAAG,KAAKJ,EAAG,KAAK,CAACS,EAAIL,GAAG,yCAAyCK,EAAIL,GAAG,KAAKJ,EAAG,MAAM,CAACS,EAAIL,GAAG,gKAAgKK,EAAIL,GAAG,KAAKJ,EAAG,MAAM,CAACE,YAAY,OAAO,CAACO,EAAIL,GAAG,uDAAuDK,EAAIL,GAAG,KAAKJ,EAAG,MAAM,CAACE,YAAY,OAAO,CAACO,EAAIL,GAAG,iGAAiGK,EAAIL,GAAG,KAAKJ,EAAG,MAAM,CAACS,EAAIL,GAAG,YAAYJ,EAAG,IAAI,CAACK,MAAM,CAAC,KAAO,+BAA+B,OAAS,WAAW,CAACI,EAAIL,GAAG,kCAAkCK,EAAIL,GAAG,2BCD/0B,qE,qBCAA,IAAIM,EAAU,EAAQ,QAEC,iBAAZA,IACTA,EAAU,CAAC,CAACC,EAAOC,EAAIF,EAAS,MAGlC,IAAIG,EAAU,CAEd,OAAiB,OACjB,WAAoB,GAEP,EAAQ,OAAR,CAAqFH,EAASG,GAEvGH,EAAQI,SACVH,EAAOI,QAAUL,EAAQI,S,6FCO3B,CACEE,QAAS,CACPT,KADJ,WAEMT,KAAKmB,QAAQC,KAAK,+B,sBCxBdP,EAAOI,QAAU,EAAQ,OAAR,EAAyD,IAK5EG,KAAK,CAACP,EAAOC,EAAI,uZAAwZ,M,kCCLjb,uBAA2W,G,oCCA3W,8IAQIO,EAAY,YACd,UACA,IACA,KACA,EACA,KACA,WACA,MAIa,UAAAA,E,8BCnBfR,EAAOI,QAAU,IAA0B","file":"static/js/4.22a5aaaa784121c40a27.js","sourcesContent":["import mod from \"-!../../node_modules/babel-loader/lib/index.js!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./explain.vue?vue&type=script&lang=js&\"; export default mod; export * from \"-!../../node_modules/babel-loader/lib/index.js!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./explain.vue?vue&type=script&lang=js&\"","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:\"explain\"},[_vm._m(0),_vm._v(\" \"),_c('img',{staticClass:\"lunarImg\",attrs:{\"src\":require(\"@/assets/img/lunar.png\"),\"alt\":\"\"}}),_vm._v(\" \"),_c('div',[_c('span',{staticClass:\"back\",on:{\"click\":_vm.back}},[_vm._v(\"back\")])])])}\nvar staticRenderFns = [function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:\"top\"},[_c('h2',[_vm._v(\"增加中国农历、24节气和节假日的功能\")]),_vm._v(\" \"),_c('h2',[_vm._v(\"npm install vue-lunar-full-calendar\")]),_vm._v(\" \"),_c('div',[_vm._v(\"A vue component for lunar fullcalendar. Uses Moment.js for date operations.(Increase the functions of Chinese lunar calendar, 24 solar terms and holidays)\")]),_vm._v(\" \"),_c('div',{staticClass:\"red\"},[_vm._v(\"window.lunar(date) 使用此依赖包可以使用这个功能获取农历的信息date是时间日期\")]),_vm._v(\" \"),_c('div',{staticClass:\"red\"},[_vm._v(\"config属性下新增了一个开启或者隐藏农历的功能字段lunarCalendar(lunarCalendar控制是否显示中国农历、显示的为true,隐藏为flase,默认为true)\")]),_vm._v(\" \"),_c('div',[_vm._v(\"其它功能可以参照\"),_c('a',{attrs:{\"href\":\"https://fullcalendar.io/docs\",\"target\":\"_blank\"}},[_vm._v(\"https://fullcalendar.io/docs\")]),_vm._v(\" 这个链接为官方的API文档去熟悉\")])])}]\n\nexport { render, staticRenderFns }","export * from \"-!../../node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./explain.vue?vue&type=template&id=533888f5&scoped=true&\"","var content = require(\"!!../../node_modules/css-loader/index.js!../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../node_modules/sass-loader/dist/cjs.js!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./explain.vue?vue&type=style&index=0&id=533888f5&scoped=true&lang=scss&\");\n\nif (typeof content === 'string') {\n content = [[module.id, content, '']];\n}\n\nvar options = {}\n\noptions.insert = \"head\";\noptions.singleton = false;\n\nvar update = require(\"!../../node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js\")(content, options);\n\nif (content.locals) {\n module.exports = content.locals;\n}\n","\r\n \r\n \r\n 增加中国农历、24节气和节假日的功能\r\n npm install vue-lunar-full-calendar\r\n A vue component for lunar fullcalendar. Uses Moment.js for date operations.(Increase the functions of Chinese lunar calendar, 24 solar terms and holidays)\r\n window.lunar(date) 使用此依赖包可以使用这个功能获取农历的信息date是时间日期\r\n config属性下新增了一个开启或者隐藏农历的功能字段lunarCalendar(lunarCalendar控制是否显示中国农历、显示的为true,隐藏为flase,默认为true)\r\n 其它功能可以参照https://fullcalendar.io/docs 这个链接为官方的API文档去熟悉\r\n \r\n \r\n \r\n back\r\n \r\n \r\n\r\n\r\n\r\n","exports = module.exports = require(\"../../node_modules/css-loader/lib/css-base.js\")(false);\n// imports\n\n\n// module\nexports.push([module.id, \".explain[data-v-533888f5]{font-size:14px;text-align:center}.explain h2[data-v-533888f5]{text-align:center}.explain div[data-v-533888f5]{text-indent:20px}.explain a[data-v-533888f5]{color:#409eff}.explain .back[data-v-533888f5]{cursor:pointer;display:inline-block;margin-top:40px;color:#45b984;font-size:15px}.explain .lunarImg[data-v-533888f5]{height:380px}.explain .red[data-v-533888f5]{color:#ff0000}\\n\", \"\"]);\n\n// exports\n","import mod from \"-!../../node_modules/style-loader/dist/index.js!../../node_modules/css-loader/index.js!../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../node_modules/sass-loader/dist/cjs.js!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./explain.vue?vue&type=style&index=0&id=533888f5&scoped=true&lang=scss&\"; export default mod; export * from \"-!../../node_modules/style-loader/dist/index.js!../../node_modules/css-loader/index.js!../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../node_modules/sass-loader/dist/cjs.js!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./explain.vue?vue&type=style&index=0&id=533888f5&scoped=true&lang=scss&\"","import { render, staticRenderFns } from \"./explain.vue?vue&type=template&id=533888f5&scoped=true&\"\nimport script from \"./explain.vue?vue&type=script&lang=js&\"\nexport * from \"./explain.vue?vue&type=script&lang=js&\"\nimport style0 from \"./explain.vue?vue&type=style&index=0&id=533888f5&scoped=true&lang=scss&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"533888f5\",\n null\n \n)\n\nexport default component.exports","module.exports = __webpack_public_path__ + \"static/img/lunar.b0e3d9b.png\";"],"sourceRoot":""} -------------------------------------------------------------------------------- /docs/static/js/app.c9dd13ceee3bb04b520a.js: -------------------------------------------------------------------------------- 1 | !function(e){function t(t){for(var r,i,u=t[0],l=t[1],c=t[2],p=0,s=[];p h(App)\r\n})\r\n","import Vue from 'vue'\r\nimport Router from 'vue-router'\r\n// 主页面结构\r\nconst lunarFullCalendar = () => import('@/view/lunarFullCalendar.vue')\r\n// 说明\r\nconst explain = () => import('@/view/explain.vue')\r\n\r\nVue.use(Router)\r\nconst routes = [\r\n {\r\n path: '*',\r\n redirect: '/vue-lunar-fullCalendar'\r\n },\r\n {\r\n path: '/vue-lunar-fullCalendar',\r\n name: 'fullCalendar',\r\n component: lunarFullCalendar\r\n },\r\n {\r\n path: '/explain',\r\n name: 'explain',\r\n component: explain\r\n }\r\n]\r\n\r\nconst router = new Router({\r\n // mode:'history',//default: hash ,history\r\n base: '/vue-lunar-fullcalendar',\r\n routes,\r\n linkActiveClass: 'my-active',\r\n scrollBehavior (to, from, savedPosition) {\r\n if (savedPosition) {\r\n return savedPosition\r\n } else {\r\n return {\r\n x: 0,\r\n y: 0\r\n }\r\n }\r\n }\r\n})\r\nexport default router\r\n"],"sourceRoot":""} -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 中国节假日和农历日程控件 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /lib/LunarFullCalendar.min.js.LICENSE: -------------------------------------------------------------------------------- 1 | /*! 2 | * vue-lunar-fullcalendar v1.3.2 3 | * (c) 2019 h j 4 | * @license MIT 5 | */ 6 | 7 | /*! 8 | * FullCalendar v3.9.0 9 | */ 10 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-lunar-full-calendar", 3 | "version": "1.3.2", 4 | "description": "vue-fulcalendar", 5 | "author": "hj", 6 | "main": "lib/LunarFullCalendar.min.js", 7 | "scripts": { 8 | "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js", 9 | "start": "npm run dev", 10 | "lint": "eslint --ext .js,.vue src", 11 | "build": "node build/build.js", 12 | "build:components": "webpack --config build/webpack.components.conf.js" 13 | }, 14 | "license": "ISC", 15 | "keywords": [ 16 | "lunar", 17 | "vue", 18 | "fullcalendar", 19 | "lunarfullcalendar", 20 | "vuelunarfullcalendar", 21 | "calendar", 22 | "holidays", 23 | "24 solar", 24 | "Chinese lunar calendar", 25 | "js", 26 | "中国农历", 27 | "中国节假日", 28 | "24节气" 29 | ], 30 | "dependencies": { 31 | "jquery": "^3.4.1", 32 | "lodash.defaultsdeep": "^4.6.1", 33 | "moment": "^2.22.2" 34 | }, 35 | "devDependencies": { 36 | "autoprefixer": "^7.1.2", 37 | "babel-core": "^6.26.3", 38 | "babel-eslint": "^8.2.1", 39 | "babel-helper-vue-jsx-merge-props": "^2.0.3", 40 | "babel-loader": "^7.1.5", 41 | "babel-plugin-syntax-jsx": "^6.18.0", 42 | "babel-plugin-transform-runtime": "^6.22.0", 43 | "babel-plugin-transform-vue-jsx": "^3.5.0", 44 | "babel-polyfill": "^6.26.0", 45 | "babel-preset-env": "^1.3.2", 46 | "babel-preset-es2015": "^6.24.1", 47 | "babel-preset-stage-2": "^6.22.0", 48 | "chalk": "^2.0.1", 49 | "clean-webpack-plugin": "^3.0.0", 50 | "copy-webpack-plugin": "^5.1.1", 51 | "cross-env": "^6.0.3", 52 | "css-loader": "^3.2.0", 53 | "eslint": "^6.7.1", 54 | "eslint-config-standard": "^10.2.1", 55 | "eslint-friendly-formatter": "^3.0.0", 56 | "eslint-loader": "^3.0.2", 57 | "eslint-plugin-import": "^2.7.0", 58 | "eslint-plugin-node": "^5.2.0", 59 | "eslint-plugin-promise": "^3.4.0", 60 | "eslint-plugin-standard": "^3.0.1", 61 | "eslint-plugin-vue": "^6.0.1", 62 | "file-loader": "^1.1.11", 63 | "friendly-errors-webpack-plugin": "^1.6.1", 64 | "html-loader": "^0.5.5", 65 | "html-webpack-plugin": "^3.2.0", 66 | "json-loader": "^0.5.7", 67 | "mini-css-extract-plugin": "^0.8.0", 68 | "node-notifier": "^5.1.2", 69 | "node-sass": "^4.13.0", 70 | "optimize-css-assets-webpack-plugin": "^3.2.0", 71 | "ora": "^1.2.0", 72 | "portfinder": "^1.0.25", 73 | "postcss": "^7.0.23", 74 | "postcss-import": "^11.0.0", 75 | "postcss-loader": "^2.1.6", 76 | "postcss-url": "^7.2.1", 77 | "progress-bar-webpack-plugin": "^1.12.1", 78 | "rimraf": "^2.6.0", 79 | "sass": "^1.23.7", 80 | "sass-loader": "^7.1.0", 81 | "semver": "^5.3.0", 82 | "shelljs": "^0.7.6", 83 | "style-loader": "^1.0.0", 84 | "terser-webpack-plugin": "^2.3.1", 85 | "url-loader": "^0.5.9", 86 | "vue": "^2.5.2", 87 | "vue-loader": "^15.7.2", 88 | "vue-router": "^3.0.1", 89 | "vue-style-loader": "^4.1.2", 90 | "vue-template-compiler": "^2.5.2", 91 | "webpack": "^4.41.2", 92 | "webpack-bundle-analyzer": "^3.6.0", 93 | "webpack-cli": "^3.3.10", 94 | "webpack-dev-server": "^3.9.0", 95 | "webpack-merge": "^4.1.0", 96 | "webpack-node-externals": "^1.7.2" 97 | }, 98 | "repository": { 99 | "type": "git", 100 | "url": "git+https://github.com/hjdev/vue-lunar-fullcalendar.git" 101 | }, 102 | "bugs": { 103 | "url": "https://github.com/hjdev/vue-lunar-fullcalendar/issues" 104 | }, 105 | "homepage": "https://github.com/hjdev/vue-lunar-fullcalendar#readme", 106 | "engines": { 107 | "node": ">= 6.0.0", 108 | "npm": ">= 3.0.0" 109 | }, 110 | "browserslist": [ 111 | "> 1%", 112 | "last 2 versions", 113 | "not ie <= 8" 114 | ] 115 | } 116 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/assets/css/reset.scss: -------------------------------------------------------------------------------- 1 | * { 2 | box-sizing: border-box; 3 | -moz-box-sizing: border-box; 4 | /* Firefox */ 5 | -webkit-box-sizing: border-box; 6 | /* Safari */ 7 | font-family: PingFangSC-Regular, "Source Han Sans"; 8 | } 9 | 10 | #app, 11 | html, 12 | body { 13 | width: 100%; 14 | height: 100%; 15 | margin: 0; 16 | padding: 0; 17 | } 18 | 19 | body { 20 | font-weight: 100; 21 | color: #1D262E; 22 | font-size: 14px; 23 | background: #F5F8FA; 24 | font-size: 0.14rem; 25 | } 26 | 27 | ul, 28 | li, 29 | p, 30 | h1, 31 | h2, 32 | h3, 33 | h4, 34 | h5, 35 | h6, 36 | dl, 37 | dt, 38 | dd { 39 | margin: 0; 40 | padding: 0; 41 | border: none; 42 | list-style: none; 43 | } 44 | 45 | a { 46 | text-decoration: none; 47 | color: #333; 48 | } 49 | 50 | a:hover, 51 | a:focus { 52 | text-decoration: none; 53 | } 54 | 55 | input, 56 | textarea, 57 | button { 58 | border: none; 59 | outline: none; 60 | font-size: 14px; 61 | } 62 | 63 | button { 64 | cursor: pointer; 65 | font-size: 14px; 66 | } 67 | 68 | input { 69 | text-indent: 5px; 70 | } 71 | 72 | img { 73 | border: none; 74 | height: auto; 75 | max-width: 100%; 76 | vertical-align: middle; 77 | } 78 | 79 | i, 80 | cite, 81 | em, 82 | var, 83 | address, 84 | dfn { 85 | font-style: normal; 86 | } 87 | 88 | p { 89 | line-height: 20px; 90 | } 91 | 92 | table { 93 | border-collapse: collapse; 94 | 95 | td, 96 | tr { 97 | padding: 0; 98 | margin: 0; 99 | } 100 | } 101 | 102 | input::-webkit-input-placeholder, 103 | input::-moz-placeholder, 104 | input:-moz-placeholder { 105 | color: #C7C7C7; 106 | font-size: 14px; 107 | } 108 | 109 | input::-webkit-outer-spin-button, 110 | input::-webkit-inner-spin-button { 111 | -webkit-appearance: none !important; 112 | margin: 0; 113 | } 114 | 115 | .cursor { 116 | cursor: pointer; 117 | } 118 | 119 | .clearfix:after { 120 | content: "."; 121 | display: block; 122 | height: 0; 123 | clear: both; 124 | visibility: hidden; 125 | } 126 | 127 | .clearfix { 128 | zoom: 1 129 | } 130 | 131 | .input[type="number"] { 132 | -moz-appearance: textfield; 133 | } 134 | -------------------------------------------------------------------------------- /src/assets/img/lunar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hjdev/vue-lunar-fullcalendar/319227b238f3df1461219b5823d2c1b43d405b9f/src/assets/img/lunar.png -------------------------------------------------------------------------------- /src/assets/img/window.lunar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hjdev/vue-lunar-fullcalendar/319227b238f3df1461219b5823d2c1b43d405b9f/src/assets/img/window.lunar.png -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import App from './App' 3 | import router from './router' 4 | 5 | // 重置样式 6 | import '@/assets/css/reset.scss' 7 | 8 | // import lunarFullCalendar from '../lib/LunarFullCalendar.min.js' 9 | // Vue.use(lunarFullCalendar) 10 | 11 | Vue.config.productionTip = false 12 | /* eslint-disable no-new */ 13 | new Vue({ 14 | el: '#app', 15 | router, 16 | render: (h) => h(App) 17 | }) 18 | -------------------------------------------------------------------------------- /src/router/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Router from 'vue-router' 3 | // 主页面结构 4 | const lunarFullCalendar = () => import('@/view/lunarFullCalendar.vue') 5 | // 说明 6 | const explain = () => import('@/view/explain.vue') 7 | 8 | Vue.use(Router) 9 | const routes = [{ 10 | path: '*', 11 | redirect: '/vue-lunar-fullCalendar' 12 | }, 13 | { 14 | path: '/vue-lunar-fullCalendar', 15 | name: 'fullCalendar', 16 | component: lunarFullCalendar 17 | }, 18 | { 19 | path: '/explain', 20 | name: 'explain', 21 | component: explain 22 | } 23 | ] 24 | 25 | const router = new Router({ 26 | // mode:'history',//default: hash ,history 27 | // base: '/vue-lunar-fullcalendar', 28 | routes, 29 | linkActiveClass: 'my-active', 30 | scrollBehavior (to, from, savedPosition) { 31 | if (savedPosition) { 32 | return savedPosition 33 | } else { 34 | return { 35 | x: 0, 36 | y: 0 37 | } 38 | } 39 | } 40 | }) 41 | export default router 42 | -------------------------------------------------------------------------------- /src/view/explain.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 增加中国农历、24节气和节假日的功能 5 | npm install vue-lunar-full-calendar 6 | A vue component for lunar fullcalendar. Uses Moment.js for date operations.(Increase the functions of Chinese lunar calendar, 24 solar terms and holidays) 7 | window.lunar(date) 使用此依赖包可以使用这个功能获取农历的信息date是时间日期 8 | config属性下新增了一个开启或者隐藏农历的功能字段lunarCalendar(lunarCalendar控制是否显示中国农历、显示的为true,隐藏为flase,默认为true) 9 | 其它功能可以参照https://fullcalendar.io/docs 这个链接为官方的API文档去熟悉 11 | 12 | 15 | 16 | back 18 | 19 | 20 | 21 | 30 | 58 | -------------------------------------------------------------------------------- /src/view/lunarFullCalendar.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | 详细请看说明(点击此处进入) 13 | 14 | 15 | 154 | 333 | -------------------------------------------------------------------------------- /static/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hjdev/vue-lunar-fullcalendar/319227b238f3df1461219b5823d2c1b43d405b9f/static/.gitkeep --------------------------------------------------------------------------------