├── config
├── dev.config.js
├── prod.config.js
├── webpack.dev.js
├── webpack.prod.js
└── webpack.common.js
├── src
├── script
│ ├── testEntryCheck.js
│ ├── index.js
│ ├── stylus.js
│ ├── demoPage
│ │ └── display.js
│ ├── date-manager.js
│ └── demo.js
├── static
│ ├── img
│ │ ├── bg-1.jpg
│ │ ├── calc.png
│ │ ├── logo.png
│ │ ├── src.png
│ │ ├── host-set.png
│ │ ├── proxy-set.png
│ │ ├── select-html.png
│ │ ├── global-import.png
│ │ └── import-select.png
│ ├── iconfont
│ │ ├── iconfont.eot
│ │ ├── iconfont.ttf
│ │ ├── iconfont.woff
│ │ ├── iconfont.woff2
│ │ ├── iconfont.json
│ │ ├── iconfont.css
│ │ ├── iconfont.svg
│ │ ├── iconfont.js
│ │ ├── demo.css
│ │ └── demo_index.html
│ └── data
│ │ └── data.json
├── style
│ ├── stylus.styl
│ ├── demo.sass
│ └── index.sass
├── plugin
│ ├── el-select
│ │ ├── chevron-down.svg
│ │ ├── select.sass
│ │ └── index.js
│ ├── arithmetic
│ │ ├── stack.js
│ │ └── index.js
│ └── date-manager.js
└── view
│ ├── stylus.html
│ ├── index.html
│ └── demo.html
├── static
├── logo.png
└── index-page.png
├── .babelrc
├── modules
├── create-define-plugin.js
├── style-file-loader-config.js
└── html-webpack-config.js
├── README.md
├── server.js
├── package.json
└── .gitignore
/config/dev.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | API: './',
3 | };
4 |
--------------------------------------------------------------------------------
/config/prod.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | API: '../',
3 | };
4 |
--------------------------------------------------------------------------------
/src/script/testEntryCheck.js:
--------------------------------------------------------------------------------
1 | /* 该文件在这里只是用来测试入口文件与html的匹配情况,无其他作用 */
2 |
--------------------------------------------------------------------------------
/static/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robustNan/jQuery-development-environment/HEAD/static/logo.png
--------------------------------------------------------------------------------
/static/index-page.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robustNan/jQuery-development-environment/HEAD/static/index-page.png
--------------------------------------------------------------------------------
/src/static/img/bg-1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robustNan/jQuery-development-environment/HEAD/src/static/img/bg-1.jpg
--------------------------------------------------------------------------------
/src/static/img/calc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robustNan/jQuery-development-environment/HEAD/src/static/img/calc.png
--------------------------------------------------------------------------------
/src/static/img/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robustNan/jQuery-development-environment/HEAD/src/static/img/logo.png
--------------------------------------------------------------------------------
/src/static/img/src.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robustNan/jQuery-development-environment/HEAD/src/static/img/src.png
--------------------------------------------------------------------------------
/src/style/stylus.styl:
--------------------------------------------------------------------------------
1 | #test
2 | height 100px
3 | width 100px
4 | background radial-gradient(#007aff 20%, #5856d6 80%)
--------------------------------------------------------------------------------
/src/static/img/host-set.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robustNan/jQuery-development-environment/HEAD/src/static/img/host-set.png
--------------------------------------------------------------------------------
/src/static/img/proxy-set.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robustNan/jQuery-development-environment/HEAD/src/static/img/proxy-set.png
--------------------------------------------------------------------------------
/src/static/img/select-html.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robustNan/jQuery-development-environment/HEAD/src/static/img/select-html.png
--------------------------------------------------------------------------------
/src/static/iconfont/iconfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robustNan/jQuery-development-environment/HEAD/src/static/iconfont/iconfont.eot
--------------------------------------------------------------------------------
/src/static/iconfont/iconfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robustNan/jQuery-development-environment/HEAD/src/static/iconfont/iconfont.ttf
--------------------------------------------------------------------------------
/src/static/iconfont/iconfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robustNan/jQuery-development-environment/HEAD/src/static/iconfont/iconfont.woff
--------------------------------------------------------------------------------
/src/static/img/global-import.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robustNan/jQuery-development-environment/HEAD/src/static/img/global-import.png
--------------------------------------------------------------------------------
/src/static/img/import-select.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robustNan/jQuery-development-environment/HEAD/src/static/img/import-select.png
--------------------------------------------------------------------------------
/src/static/iconfont/iconfont.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robustNan/jQuery-development-environment/HEAD/src/static/iconfont/iconfont.woff2
--------------------------------------------------------------------------------
/src/style/demo.sass:
--------------------------------------------------------------------------------
1 | @import '../static/iconfont/iconfont.css'
2 |
3 | body
4 | padding-bottom: 150px
5 |
6 | .pricing-card-title
7 | color: orange
8 |
9 | #css-bg
10 | background: url(../static/img/bg-1.jpg) no-repeat
11 | background-size: 100%
--------------------------------------------------------------------------------
/src/script/index.js:
--------------------------------------------------------------------------------
1 | import 'bootstrap';
2 |
3 | import 'bootstrap/scss/bootstrap.scss';
4 | import '../style/index.sass';
5 | import displayState from './demoPage/display';
6 |
7 | console.warn(`mode is: ${process.env.NODE_ENV}`);
8 | console.warn(displayState); //引入并打印是为了测试共同引用模块的打包
9 |
--------------------------------------------------------------------------------
/src/plugin/el-select/chevron-down.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | [
4 | "@babel/env",
5 | {
6 | "targets": {
7 | "edge": "17",
8 | "firefox": "60",
9 | "chrome": "67",
10 | "safari": "11.1",
11 | "ie": "11"
12 | },
13 | "corejs": "3",
14 | "useBuiltIns": "usage"
15 | }
16 | ]
17 | ]
18 | }
--------------------------------------------------------------------------------
/src/style/index.sass:
--------------------------------------------------------------------------------
1 | $theme: #03a9f4
2 |
3 | body
4 | // background: tomato
5 |
6 | h1
7 | color: $theme
8 | margin-bottom: 50px
9 | margin-top: 150px
10 | text-align: center
11 |
12 | .container
13 |
14 | #des
15 | text-indent: 15px
16 |
17 | #link
18 | text-align: right
19 |
20 | .row:last-of-type
21 | margin-top: 50px
--------------------------------------------------------------------------------
/src/script/stylus.js:
--------------------------------------------------------------------------------
1 | import 'bootstrap';
2 | import 'bootstrap/scss/bootstrap.scss';
3 |
4 | // import '../plugin/date-picker';
5 |
6 | import '../style/stylus.styl';
7 |
8 | /* $(function () {
9 | $('#date').datePicker({ isEn: true });
10 | $('#date-range').datePicker({
11 | default: {
12 | start: '2020-09-07',
13 | end: '2020-09-07',
14 | },
15 | range: true,
16 | });
17 | }); */
18 |
--------------------------------------------------------------------------------
/config/webpack.dev.js:
--------------------------------------------------------------------------------
1 | const webpack = require('webpack');
2 | const MiniCssExtractPlugin = require('mini-css-extract-plugin');
3 |
4 | module.exports = {
5 | mode: 'development',
6 | devtool: 'cheap-module-eval-source-map', //inline-source-map
7 | plugins: [
8 | new webpack.HotModuleReplacementPlugin(),
9 | new MiniCssExtractPlugin({
10 | filename: 'css/[name].css',
11 | }),
12 | ],
13 | };
14 |
--------------------------------------------------------------------------------
/modules/create-define-plugin.js:
--------------------------------------------------------------------------------
1 | const webpack = require('webpack');
2 |
3 | /**
4 | * @author cooper
5 | * @description 根据dev.config.js或prod.config.js设定的值创建DefinePlugin,前端页面可全局调用这些值
6 | * @param {Object} | options
7 | * @returns {webpack.DefinePlugin}
8 | */
9 | module.exports = (options) => {
10 | const obj = {};
11 | for (const key in options) {
12 | const value = options[key];
13 | obj[key] = JSON.stringify(value);
14 | }
15 | return new webpack.DefinePlugin(obj);
16 | };
17 |
--------------------------------------------------------------------------------
/src/plugin/arithmetic/stack.js:
--------------------------------------------------------------------------------
1 | export default class {
2 | constructor() {
3 | this.stack = [];
4 | }
5 |
6 | getLength() {
7 | return this.stack.length;
8 | }
9 |
10 | peek() {
11 | const len = this.getLength();
12 | return len ? this.stack[len - 1] : undefined;
13 | }
14 |
15 | pop() {
16 | return this.stack.pop();
17 | }
18 |
19 | push(num) {
20 | this.stack.push(num);
21 | return undefined;
22 | }
23 |
24 | reset() {
25 | this.stack = [];
26 | return undefined;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/view/stylus.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | date-picker
7 |
8 |
9 | stylus
10 |
11 |
12 |
13 |
14 |
15 |
16 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 | 
4 |
5 | # JQDE
6 |
7 | 基于 Webpack 搭建的 jQuery 项目开发环境(jQuery development environment),使 jQuery 项目能够以前后端分离模式进行开发,这是一种有效提高开发效率的先进模式。利用此环境前端开发人员无需搭建后台环境,只需要配置相应的代理地址即可实现前后端的数据流通。并且此环境配置了对 Sass 和 Stylus 两种 CSS 样式预编译语言的配置,可以直接使用这些语言高效快速的编写界面样式。
8 |
9 | 附加仿Element样式Select插件
10 |
11 | **安装依赖**
12 |
13 | `* 推荐使用cnpm安装,避免npm安装导致部分依赖安装失败`
14 |
15 | ```shell
16 | $ cnpm install
17 | $ cnpm i
18 | $ npm install
19 | $ npm i
20 | ```
21 |
22 | **启动环境**
23 |
24 | ```shell
25 | $ npm start
26 | ```
27 |
28 | **打包输出**
29 |
30 | ```shell
31 | $ npm run build
32 | ```
33 |
34 | **node-sass升级**
35 |
36 | `* 已针对node14版本进行修改,如果使用的node版本不同,需要替换对应版本的node-sass`
37 | https://www.npmjs.com/package/node-sass
38 |
--------------------------------------------------------------------------------
/src/script/demoPage/display.js:
--------------------------------------------------------------------------------
1 | export default function displayState(data) {
2 | const currentData = [
3 | {
4 | /* 全球确诊 */
5 | id: 'global',
6 | count: data.globalStatistics.confirmedCount,
7 | add: data.globalStatistics.confirmedIncr,
8 | },
9 | {
10 | /* 国外确诊 */
11 | id: 'foreign',
12 | count: data.foreignStatistics.confirmedCount,
13 | add: data.foreignStatistics.confirmedIncr,
14 | },
15 | {
16 | /* 国内确诊 */
17 | id: 'demostic',
18 | count: data.confirmedCount,
19 | add: data.confirmedIncr,
20 | },
21 | ];
22 |
23 | for (const iterator of currentData) {
24 | $(`#${iterator.id}`)
25 | .children('h1')
26 | .html(`${iterator.count} / 例`)
27 | .next()
28 | .children()
29 | .text(iterator.add > 0 ? `+${iterator.add}` : iterator.add);
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/view/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | JQDE
7 |
8 |
9 |
10 |
11 |

12 |
Hello, JQDE!
13 |
14 | 基于Webpack搭建的用于jQuery多页面项目的开发环境,融入了jQuery,Lodash,Echarts和Bootstrap4库。借助Webpack,让jQuery项目开发前后端分离。
15 |
16 |
17 |
18 | 在使用本环境进行开发前请先对
19 | Webpack
20 | 有所了解
21 |
22 |
Learn more
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/modules/style-file-loader-config.js:
--------------------------------------------------------------------------------
1 | const MiniCssExtractPlugin = require('mini-css-extract-plugin');
2 |
3 | /**
4 | * @author cooper
5 | * @description 根据入参判定是否启用热重载
6 | * @param {Boolean} | isOn
7 | * @returns {Array}
8 | */
9 | module.exports = (isOn) => {
10 | const baseLoader = [
11 | {
12 | loader: MiniCssExtractPlugin.loader,
13 | options: {
14 | publicPath: '../',
15 | hmr: isOn, //热重载相关
16 | reloadAll: isOn, //热重载相关
17 | },
18 | },
19 | 'css-loader',
20 | ];
21 |
22 | return [
23 | {
24 | test: /\.styl$/,
25 | use: [...baseLoader, 'stylus-loader'],
26 | },
27 | {
28 | test: /\.(sa|sc)ss$/,
29 | use: [
30 | ...baseLoader,
31 | {
32 | loader: 'postcss-loader', // Run postcss actions
33 | options: {
34 | plugins: function () {
35 | // postcss plugins, can be exported to postcss.config.js
36 | return [require('autoprefixer')];
37 | },
38 | },
39 | },
40 | 'sass-loader',
41 | ],
42 | },
43 | {
44 | test: /\.css$/,
45 | use: baseLoader,
46 | },
47 | ];
48 | };
49 |
--------------------------------------------------------------------------------
/server.js:
--------------------------------------------------------------------------------
1 | const merge = require('webpack-merge');
2 | const path = require('path');
3 | const webpackDevServer = require('webpack-dev-server');
4 | const webpack = require('webpack');
5 |
6 | const commonConfig = require('./config/webpack.common');
7 | const devConfig = require('./config/webpack.dev');
8 | const getStyleRules = require('./modules/style-file-loader-config');
9 |
10 | const dotenv = require('dotenv');
11 | dotenv.config('./env');
12 |
13 | const NODE_ENV = process.env.NODE_ENV;
14 | const config = merge(commonConfig, devConfig, {
15 | module: {
16 | rules: getStyleRules(NODE_ENV === 'development'),
17 | },
18 | });
19 |
20 | const devServerOptions = {
21 | contentBase: path.join(__dirname, './dist'),
22 | host: process.env.HOST,
23 | hot: true,
24 | open: true,
25 | proxy: {
26 | '/txapi': {
27 | target: 'http://api.tianapi.com',
28 | changeOrigin: true,
29 | },
30 | },
31 | overlay: {
32 | errors: true, // 编译出现错误时,错误直接贴到页面上
33 | },
34 | };
35 |
36 | webpackDevServer.addDevServerEntrypoints(config, devServerOptions);
37 | const compiler = webpack(config);
38 | const server = new webpackDevServer(compiler, devServerOptions);
39 |
40 | server.listen(process.env.PORT, 'localhost', () => {
41 | console.log(`dev server listening on port ${process.env.PORT}`);
42 | });
43 |
--------------------------------------------------------------------------------
/src/static/iconfont/iconfont.json:
--------------------------------------------------------------------------------
1 | {
2 | "id": "1689502",
3 | "name": "chanyedashuju",
4 | "font_family": "iconfont",
5 | "css_prefix_text": "icon-",
6 | "description": "",
7 | "glyphs": [
8 | {
9 | "icon_id": "5387588",
10 | "name": "箭头_向下",
11 | "font_class": "jiantou_xiangxia",
12 | "unicode": "eb0a",
13 | "unicode_decimal": 60170
14 | },
15 | {
16 | "icon_id": "5387589",
17 | "name": "箭头_向上",
18 | "font_class": "jiantou_xiangshang",
19 | "unicode": "eb0b",
20 | "unicode_decimal": 60171
21 | },
22 | {
23 | "icon_id": "11488026",
24 | "name": "double-arro- right",
25 | "font_class": "double-arro-right",
26 | "unicode": "e74c",
27 | "unicode_decimal": 59212
28 | },
29 | {
30 | "icon_id": "1368661",
31 | "name": "3d",
32 | "font_class": "d",
33 | "unicode": "e625",
34 | "unicode_decimal": 58917
35 | },
36 | {
37 | "icon_id": "7685206",
38 | "name": "power",
39 | "font_class": "power",
40 | "unicode": "e71d",
41 | "unicode_decimal": 59165
42 | },
43 | {
44 | "icon_id": "11758144",
45 | "name": "柱状图",
46 | "font_class": "zhuzhuangtu",
47 | "unicode": "e748",
48 | "unicode_decimal": 59208
49 | }
50 | ]
51 | }
52 |
--------------------------------------------------------------------------------
/config/webpack.prod.js:
--------------------------------------------------------------------------------
1 | const MiniCssExtractPlugin = require('mini-css-extract-plugin');
2 | const WebpackProgressOraPlugin = require('webpack-progress-ora-plugin');
3 |
4 | module.exports = {
5 | mode: 'production',
6 | devtool: 'source-map', //source-map
7 | optimization: {
8 | splitChunks: {
9 | chunks: 'all',
10 | minSize: 30000, //表示在压缩前的最小模块大小,默认值是30kb
11 | minChunks: 1, // 表示被引用次数,默认为1;
12 | maxAsyncRequests: 6, //所有异步请求不得超过6个
13 | maxInitialRequests: 4, //初始话并行请求不得超过4个
14 | automaticNameDelimiter: '~', //名称分隔符
15 | name: true, //打包后的名称,默认是chunk的名字通过分隔符(默认是~)分隔
16 | /* 设置缓存组用来抽取满足不同规则的chunk */
17 | cacheGroups: {
18 | utilCommon: {
19 | // 抽离自定义工具库
20 | name: 'common',
21 | minSize: 0, // 将引用模块分离成新代码文件的最小体积
22 | minChunks: 2, // 表示将引用模块如不同文件引用了多少次,才能分离生成新chunk
23 | priority: -20,
24 | },
25 | vendors: {
26 | // 抽离第三方插件
27 | test: /[\\/]node_modules[\\/]/, // 指定是node_modules下的第三方包
28 | name: 'vendors',
29 | priority: -10, // 抽取优先级
30 | },
31 | },
32 | },
33 | },
34 | plugins: [
35 | new MiniCssExtractPlugin({
36 | filename: 'css/[name]-[hash].css',
37 | }),
38 | new WebpackProgressOraPlugin({
39 | stderr_check: true,
40 | interval: 300,
41 | }),
42 | ],
43 | };
44 |
--------------------------------------------------------------------------------
/modules/html-webpack-config.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | const glob = require('glob');
3 | const HtmlWebpackPlugin = require('html-webpack-plugin');
4 |
5 | /**
6 | * @cooper
7 | * @description 根据/src/script下的js文件名称动态生成入口配置对象
8 | * @returns {Object}
9 | */
10 | function getEntry() {
11 | const entry = {};
12 | const list = glob.sync('./src/script/*.js');
13 | list.forEach(function (path) {
14 | const [flag, suffix] = ['script/', '.js'];
15 | const start = path.indexOf(flag) + flag.length;
16 | const end = path.length - suffix.length;
17 | const name = path.slice(start, end);
18 | if (fs.existsSync(`./src/view/${name}.html`)) entry[name] = path; //判定入口文件是否存在对应的html
19 | });
20 | return entry;
21 | }
22 |
23 | /**
24 | * @cooper
25 | * @description 根据传入的入口文件名称返回HtmlWebpackPlugin所需配置对象
26 | * @param {String} | name
27 | * @returns {Object}
28 | */
29 | function getHtmlConfig(name) {
30 | return {
31 | chunks: [name],
32 | template: `./src/view/${name}.html`,
33 | filename: `${name}.html`,
34 | favicon: './static/logo.png', //该配置回导致在html同级目录下多出一个logo.png文件
35 | hash: true,
36 | inject: 'body',
37 | };
38 | }
39 |
40 | /**
41 | * @cooper
42 | * @description 根据getEntry返回的入口配置对象分别创建HtmlWebpackPlugin
43 | * @param {Object} | entries
44 | * @returns {Array}
45 | */
46 | function createHtmlWebpackPlugin(entries) {
47 | const pluginArr = [];
48 | for (const key in entries) {
49 | if (entries.hasOwnProperty(key)) {
50 | const configOptions = getHtmlConfig(key);
51 | pluginArr.push(new HtmlWebpackPlugin(configOptions));
52 | }
53 | }
54 | return pluginArr;
55 | }
56 |
57 | module.exports = { getEntry, createHtmlWebpackPlugin };
58 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "jqde",
3 | "version": "1.0.0",
4 | "description": "jQuery development environment",
5 | "scripts": {
6 | "build": "cross-env NODE_ENV=production node build.js",
7 | "start": "cross-env NODE_ENV=development node server.js"
8 | },
9 | "keywords": [
10 | "jquery"
11 | ],
12 | "repository": {
13 | "type": "git",
14 | "url": "git+https://github.com/robustNan/jQuery-development-environment"
15 | },
16 | "homepage": "https://github.com/robustNan/jQuery-development-environment#readme",
17 | "author": "Cooper",
18 | "license": "ISC",
19 | "devDependencies": {
20 | "@babel/cli": "^7.8.4",
21 | "@babel/core": "^7.9.0",
22 | "@babel/preset-env": "^7.9.0",
23 | "autoprefixer": "^9.7.5",
24 | "babel-loader": "^8.1.0",
25 | "clean-webpack-plugin": "^3.0.0",
26 | "cross-env": "^7.0.2",
27 | "css-loader": "^3.4.2",
28 | "dotenv": "^8.2.0",
29 | "file-loader": "^6.0.0",
30 | "glob": "^7.1.6",
31 | "html-loader": "^1.0.0",
32 | "html-webpack-plugin": "^4.0.1",
33 | "mini-css-extract-plugin": "^0.9.0",
34 | "mkdirp": "^1.0.3",
35 | "node-sass": "^4.14.1",
36 | "postcss-loader": "^3.0.0",
37 | "sass-loader": "^8.0.2",
38 | "single-line-log": "^1.1.2",
39 | "stylus": "^0.54.7",
40 | "stylus-loader": "^3.0.2",
41 | "true-case-path": "^2.2.1",
42 | "webpack": "^4.42.1",
43 | "webpack-cli": "^3.3.11",
44 | "webpack-dev-server": "^3.11.2",
45 | "webpack-merge": "^4.2.2",
46 | "webpack-progress-ora-plugin": "^1.2.2"
47 | },
48 | "dependencies": {
49 | "@babel/polyfill": "^7.8.7",
50 | "bootstrap": "^4.4.1",
51 | "core-js": "^3.6.4",
52 | "daterangepicker": "^3.1.0",
53 | "echarts": "^4.7.0",
54 | "jquery": "^3.6.0",
55 | "lodash": "^4.17.21",
56 | "moment": "^2.27.0",
57 | "popper.js": "^1.16.1"
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/src/plugin/date-manager.js:
--------------------------------------------------------------------------------
1 | export default {
2 | /**
3 | * @author jiaojiannan
4 | * @description 获取十二个月分
5 | */
6 | allMonths() {
7 | const months = [];
8 | for (let i = 1; i < 13; i++) months.push({ value: i, text: i + ' 月' });
9 | return months;
10 | },
11 |
12 | /**
13 | * @author jiaojiannan
14 | * @description 根据年份、月分获取当月天数的数据
15 | * @param {Number} year
16 | * @param {Number} month 1-12
17 | */
18 | daysInMonth(year, month) {
19 | const [days, leng] = [[], this.getMonthLength(year, month)];
20 | for (let i = 1; i <= leng; i++) days.push({ value: i, text: i + ' 日' });
21 | return days;
22 | },
23 |
24 | /**
25 | * @author jiaojiannan
26 | * @description 根据年份、月分获取当月总计天数
27 | * @param {Number} year
28 | * @param {Number} month 1-12
29 | */
30 | getMonthLength(year, month) {
31 | const [datumYear, datumMonth] = [
32 | 12 === month ? year + 1 : year,
33 | 12 === month ? 1 : month + 1,
34 | ]; //需要将月分向后推一个月
35 | const datum = new Date(datumYear + '-' + datumMonth);
36 | datum.setDate(0); //设置到指定月份最后一天
37 | return datum.getDate();
38 | },
39 |
40 | /**
41 | * @author jiaojiannan
42 | * @description 根据传入参数获取近几年,默认六年
43 | * @param {Number} range
44 | * @param {Number} maxYear
45 | */
46 | nearlyYears(range = 6, maxYear) {
47 | const years = [];
48 | let max = maxYear ? maxYear : new Date().getFullYear();
49 | for (let i = 0; i < range; i++) {
50 | const year = max - i;
51 | years.push({ value: year, text: year + ' 年' });
52 | }
53 | return years;
54 | },
55 |
56 | /**
57 | * @author jiaojiannan
58 | * @description 根据传入时间对象及分隔符输出日期字符串
59 | * @param {Date} date
60 | * @param {String} symbol
61 | */
62 | formatterDate(date, symbol) {
63 | return (
64 | date.getFullYear() +
65 | symbol +
66 | (date.getMonth() + 1) +
67 | symbol +
68 | date.getDate()
69 | );
70 | },
71 | };
72 |
--------------------------------------------------------------------------------
/src/script/date-manager.js:
--------------------------------------------------------------------------------
1 | export default {
2 | /**
3 | * @author jiaojiannan
4 | * @description 获取十二个月分
5 | */
6 | allMonths() {
7 | const months = [];
8 | for (let i = 1; i < 13; i++) months.push({ value: i, text: i + ' 月' });
9 | return months;
10 | },
11 |
12 | /**
13 | * @author jiaojiannan
14 | * @description 根据年份、月分获取当月天数的数据
15 | * @param {Number} year
16 | * @param {Number} month 1-12
17 | */
18 | daysInMonth(year, month) {
19 | const [days, leng] = [[], this.getMonthLength(year, month)];
20 | for (let i = 1; i <= leng; i++) days.push({ value: i, text: i + ' 日' });
21 | return days;
22 | },
23 |
24 | /**
25 | * @author jiaojiannan
26 | * @description 根据年份、月分获取当月总计天数
27 | * @param {Number} year
28 | * @param {Number} month 1-12
29 | */
30 | getMonthLength(year, month) {
31 | const [datumYear, datumMonth] = [
32 | 12 === month ? year + 1 : year,
33 | 12 === month ? 1 : month + 1,
34 | ]; //需要将月分向后推一个月
35 | const datum = new Date(datumYear + '-' + datumMonth);
36 | datum.setDate(0); //设置到指定月份最后一天
37 | return datum.getDate();
38 | },
39 |
40 | /**
41 | * @author jiaojiannan
42 | * @description 根据传入参数获取近几年,默认六年
43 | * @param {Number} range
44 | * @param {Number} maxYear
45 | */
46 | nearlyYears(range = 6, maxYear) {
47 | const years = [];
48 | let max = maxYear ? maxYear : new Date().getFullYear();
49 | for (let i = 0; i < range; i++) {
50 | const year = max - i;
51 | years.push({ value: year, text: year + ' 年' });
52 | }
53 | return years;
54 | },
55 |
56 | /**
57 | * @author jiaojiannan
58 | * @description 根据传入时间对象及分隔符输出日期字符串
59 | * @param {Date} date
60 | * @param {String} symbol
61 | */
62 | formatterDate(date, symbol) {
63 | return (
64 | date.getFullYear() +
65 | symbol +
66 | (date.getMonth() + 1) +
67 | symbol +
68 | date.getDate()
69 | );
70 | },
71 | };
72 |
--------------------------------------------------------------------------------
/config/webpack.common.js:
--------------------------------------------------------------------------------
1 | const { CleanWebpackPlugin } = require('clean-webpack-plugin');
2 | const path = require('path');
3 | const webpack = require('webpack');
4 |
5 | const getDefinePlugin = require('../modules/create-define-plugin');
6 | const {
7 | getEntry,
8 | createHtmlWebpackPlugin,
9 | } = require('../modules/html-webpack-config');
10 | const entries = getEntry(); //获取到所有入口文件
11 |
12 | /* 根据 process.env.NODE_ENV 生成对应 DefinePlugin */
13 | const DefinePlugin =
14 | process.env.NODE_ENV === 'development'
15 | ? getDefinePlugin(require('./dev.config'))
16 | : getDefinePlugin(require('./prod.config'));
17 |
18 | module.exports = {
19 | entry: entries,
20 | output: {
21 | filename: 'js/[name]-[hash].js',
22 | path: path.resolve(__dirname, '../dist'),
23 | },
24 | module: {
25 | rules: [
26 | {
27 | test: /\.(woff|woff2|eot|ttf|otf)$/,
28 | use: {
29 | loader: 'file-loader',
30 | options: {
31 | name: '[name]-[hash].[ext]',
32 | outputPath: 'font',
33 | },
34 | },
35 | },
36 | {
37 | test: /\.(png|svg|jpg|gif)$/,
38 | use: [
39 | {
40 | loader: 'file-loader',
41 | options: {
42 | name: '[name]-[hash].[ext]',
43 | outputPath: 'img',
44 | },
45 | },
46 | ],
47 | },
48 | {
49 | test: /\.js$/,
50 | exclude: /[\\/]node_modules[\\/]/,
51 | loader: 'babel-loader',
52 | },
53 | {
54 | test: /\.html$/,
55 | use: [
56 | {
57 | loader: 'html-loader',
58 | options: {
59 | attributes: true,
60 | },
61 | },
62 | ],
63 | },
64 | ],
65 | },
66 | plugins: [
67 | new CleanWebpackPlugin(),
68 | /* 全局引入jquery、lodash、echarts */
69 | new webpack.ProvidePlugin({
70 | $: 'jquery',
71 | jQuery: 'jquery',
72 | jquery: 'jquery',
73 | _: 'lodash',
74 | echarts: 'echarts',
75 | moment: 'moment',
76 | Popper: ['popper.js', 'default'],
77 | }),
78 | DefinePlugin,
79 | ...createHtmlWebpackPlugin(entries),
80 | ],
81 | };
82 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | lerna-debug.log*
8 |
9 | # Diagnostic reports (https://nodejs.org/api/report.html)
10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
11 |
12 | # Runtime data
13 | pids
14 | *.pid
15 | *.seed
16 | *.pid.lock
17 |
18 | # Directory for instrumented libs generated by jscoverage/JSCover
19 | lib-cov
20 |
21 | # Coverage directory used by tools like istanbul
22 | coverage
23 | *.lcov
24 |
25 | # nyc test coverage
26 | .nyc_output
27 |
28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
29 | .grunt
30 |
31 | # Bower dependency directory (https://bower.io/)
32 | bower_components
33 |
34 | # node-waf configuration
35 | .lock-wscript
36 |
37 | # Compiled binary addons (https://nodejs.org/api/addons.html)
38 | build/Release
39 |
40 | # Dependency directories
41 | node_modules/
42 | jspm_packages/
43 |
44 | # TypeScript v1 declaration files
45 | typings/
46 |
47 | # TypeScript cache
48 | *.tsbuildinfo
49 |
50 | # Optional npm cache directory
51 | .npm
52 |
53 | # Optional eslint cache
54 | .eslintcache
55 |
56 | # Microbundle cache
57 | .rpt2_cache/
58 | .rts2_cache_cjs/
59 | .rts2_cache_es/
60 | .rts2_cache_umd/
61 |
62 | # Optional REPL history
63 | .node_repl_history
64 |
65 | # Output of 'npm pack'
66 | *.tgz
67 |
68 | # Yarn Integrity file
69 | .yarn-integrity
70 |
71 | # dotenv environment variables file
72 | .env
73 | .env.test
74 |
75 | # parcel-bundler cache (https://parceljs.org/)
76 | .cache
77 |
78 | # Next.js build output
79 | .next
80 |
81 | # Nuxt.js build / generate output
82 | .nuxt
83 | dist
84 |
85 | # Gatsby files
86 | .cache/
87 | # Comment in the public line in if your project uses Gatsby and *not* Next.js
88 | # https://nextjs.org/blog/next-9-1#public-directory-support
89 | # public
90 |
91 | # vuepress build output
92 | .vuepress/dist
93 |
94 | # Serverless directories
95 | .serverless/
96 |
97 | # FuseBox cache
98 | .fusebox/
99 |
100 | # DynamoDB Local files
101 | .dynamodb/
102 |
103 | # TernJS port file
104 | .tern-port
105 |
106 | # Vscode config file
107 | .vscode
108 | /package-lock.json
109 |
--------------------------------------------------------------------------------
/src/static/iconfont/iconfont.css:
--------------------------------------------------------------------------------
1 | @font-face {font-family: "iconfont";
2 | src: url('iconfont.eot?t=1584330793137'); /* IE9 */
3 | src: url('iconfont.eot?t=1584330793137#iefix') format('embedded-opentype'), /* IE6-IE8 */
4 | url('data:application/x-font-woff2;charset=utf-8;base64,d09GMgABAAAAAAQYAAsAAAAACNQAAAPLAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHEIGVgCDVgqEDINIATYCJAMcCxAABCAFhG0HfRu1BxEVnFPJfiTGMSnrzPIqmmg3EzxfOfV97QqyChSYTwBslwCcAjApjadHujkA9l17P8I2oSLMofx25NEepnCUvjQd/fwx00XaBpbPvs0lKykScFZAA9pFNsgBlsiB+D3Asxr8T8DlEMCQixJI7bqNW+Oh0bcTQAb269MNL2FEV1QKHoJTcKhGFmPjWXOs+8Ai7/clSjnxwMJW6Ls2712nJ9V/Foz6KhKL0NHBIBrODvBHgQJKABpkcqFzLCpIlkBh1JdoGgPxeFjonwWDnEH9oHHUj8USOCPVvUK8UQwaG2fAfzwLxIHK4wFoi3qHIxRZCBqCnAg2BPURHAgaIyiIGgSBqH8EFgAuAImQng3cR2IFpVyCQlNOXJzjZNE6vVAaffEhttGh5m3CLcdoY7duGW7TfEyvnlXDoZBz2wndV87N0HX5bqzInozdVszL3GPVPlHJe7t369q9TDeL21X1sMas3A6RNRlfvGj9/Lm58mXo1avwqnUiyTszJGVtCnhk+xZ+iaHkvZlMLyt8f94+GaN9uy+dwXT0XTPWV6bYyc6hdtOmXUrVE+coNrxdwnYu9ZfBQ3uGlZkY6oMU3/mSGTMR7cOvlFoqpRtT7dL//Cl2zuv4tLPSxvu+00G+AJUpicDgJXn2G7VB7v0dcu/osqOD94m6sz1YZkwjf8v0piVCW03PhEGrVg9JWOLfOqEWEm69sG7R6Vv8RsYsi1RclmpWJK198mpdhtuJ6f7bN2T24mdfp8dzuPJh4puBPr6ydQq+NJg7Z27jOXPSzbmWdnZkdnwtSDWczWT0KSuqMtGaqoS1CmKXVURVh+RadVS1S2IH/IUAAhvq/3e7JFX+4/kagLcrshbFQGytprnwS6pQRZ9c1HBIaxLd5Gqls9WCAC6VYl/BAgwG+NTedHwcTp2xcTkIHhkjsHDJCQqPAlhNLAE2PhXAwaMaGIpT72if9AxHIToOKMYMACENh8AikUugSMMDrCZ+AJtM/AaHNKLAEJL0p/QpJDp7eGSsBFuo/8A2NCnTIge/8g11GCqOSzzGF7K3EcjiNJ15xQl5iD38t85FFCimEV7gajgMBI6pw0ZiI+JuSaKKPihuaJwdeGSsBFug/gNsQ5NyJssh8/NvqMNQcUVblfsL2dvlgYyYtAH2VTk1aruUp/hvnSOiAMU0Ai9gx8FIEuCKN+qwkRjTIe5uJDRONVXG06vH+7wAGPQ7uGKJEi22OOKKx11/W01Cofj15NoefUjpvcE73rcU6gGjipkittrIvF07+kE+/ptg8qsDEmYzAA==') format('woff2'),
5 | url('iconfont.woff?t=1584330793137') format('woff'),
6 | url('iconfont.ttf?t=1584330793137') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */
7 | url('iconfont.svg?t=1584330793137#iconfont') format('svg'); /* iOS 4.1- */
8 | }
9 |
10 | .iconfont {
11 | font-family: "iconfont" !important;
12 | font-size: 16px;
13 | font-style: normal;
14 | -webkit-font-smoothing: antialiased;
15 | -moz-osx-font-smoothing: grayscale;
16 | }
17 |
18 | .icon-jiantou_xiangxia:before {
19 | content: "\eb0a";
20 | }
21 |
22 | .icon-jiantou_xiangshang:before {
23 | content: "\eb0b";
24 | }
25 |
26 | .icon-double-arro-right:before {
27 | content: "\e74c";
28 | }
29 |
30 | .icon-d:before {
31 | content: "\e625";
32 | }
33 |
34 | .icon-power:before {
35 | content: "\e71d";
36 | }
37 |
38 | .icon-zhuzhuangtu:before {
39 | content: "\e748";
40 | }
41 |
42 |
--------------------------------------------------------------------------------
/src/plugin/el-select/select.sass:
--------------------------------------------------------------------------------
1 | $bg-color: #fff //背景色
2 | $border-color: #dcdfe6 //边框颜色
3 | $font-color: #606266 //文字颜色
4 | $hover-color: #f5f7fa //下拉选项鼠标经过颜色
5 | $border-hover: #c0c4cc //Select框鼠标移入颜色
6 | $triangle-color: #c0c4cc //Select框箭头颜色
7 |
8 | .selector
9 | cursor: default
10 | display: inline-block
11 | position: relative
12 | // height: 32px
13 | width: 160px
14 | vertical-align: top
15 |
16 | .form-control[readonly]
17 | cursor: default
18 | font-size: 14px
19 | padding: 5px 31px 5px 10px
20 | background: $bg-color
21 | border: 1px solid $border-color
22 | border-radius: 2px
23 | color: $font-color
24 |
25 | &:hover
26 | border-color: $border-hover
27 |
28 | // &:focus
29 | // border-color: $border-focus
30 |
31 | /** i.glyphicon-triangle-bottom
32 | border: 5px solid $triangle-color
33 | border-top: 5px solid transparent
34 | border-left: 5px solid transparent
35 | display: block
36 | height: 10px
37 | width: 10px
38 | position: absolute
39 | right: 10px
40 | top: 50%
41 | transform: translateY(-50%) rotate(45deg)
42 | z-index: 100 **/
43 |
44 | .glyphicon-triangle-bottom
45 | display: block
46 | position: absolute
47 | right: 10px
48 | top: 50%
49 | transform: translateY(-50%) rotate(0)
50 | z-index: 100
51 |
52 | ul.list-group
53 | border-radius: 5px
54 | display: none
55 | margin: 0
56 | max-height: 310px
57 | padding: 6px 0
58 | position: absolute
59 | top: 45px
60 | left: 0
61 | z-index: 999
62 | background: $bg-color
63 | border: 1px solid $border-color
64 | box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1)
65 | color: $font-color
66 |
67 | li
68 | height: 30px
69 | line-height: 30px
70 | padding: 0 10px
71 | text-overflow: ellipsis
72 | overflow: hidden
73 | white-space: normal
74 |
75 | &:hover
76 | background-color: $hover-color
77 |
78 | div.select-arrow
79 | border: 6px solid $bg-color
80 | border-right: 6px solid transparent !important
81 | border-bottom: 6px solid transparent !important
82 | display: none
83 | height: 10px
84 | position: absolute
85 | left: 30%
86 | top: 40.5px
87 | transform: rotate(45deg)
88 | width: 10px
89 | z-index: 1000
90 |
91 | &::after
92 | border: 1px solid $border-color
93 | border-right: none !important
94 | border-bottom: none !important
95 | content: ''
96 | display: block
97 | height: 11px
98 | width: 11px
99 | transform: translate(-6px, -6px)
100 |
--------------------------------------------------------------------------------
/src/static/iconfont/iconfont.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
45 |
--------------------------------------------------------------------------------
/src/script/demo.js:
--------------------------------------------------------------------------------
1 | import 'bootstrap';
2 |
3 | import 'bootstrap/scss/bootstrap.scss';
4 | import '../style/demo.sass';
5 |
6 | /* 引入日期范围选择器 */
7 | import 'daterangepicker/daterangepicker.js';
8 | import 'daterangepicker/daterangepicker.css';
9 |
10 | import '../plugin/el-select'; //引入select插件
11 | import displayState from './demoPage/display';
12 |
13 | /* import引入图片 */
14 | import bg from '../static/img/bg-1.jpg';
15 |
16 | import dateM from '../plugin/date-manager';
17 | import Arithmetic from '../plugin/arithmetic';
18 |
19 | /**
20 | * @description 日期范围选择插件配置
21 | * @type {Object}
22 | */
23 | const locale = {
24 | format: 'YYYY/MM/DD',
25 | separator: ' - ',
26 | applyLabel: '确定',
27 | cancelLabel: '取消',
28 | fromLabel: 'From',
29 | toLabel: 'To',
30 | customRangeLabel: 'Custom',
31 | weekLabel: 'W',
32 | daysOfWeek: ['日', '一', '二', '三', '四', '五', '六'],
33 | monthNames: [
34 | '一月',
35 | '二月',
36 | '三月',
37 | '四月',
38 | '五月',
39 | '六月',
40 | '七月',
41 | '八月',
42 | '九月',
43 | '十一月',
44 | '十二月',
45 | ],
46 | firstDay: 1,
47 | };
48 |
49 | $(function () {
50 | console.warn('全局引入jQuery', $);
51 | console.warn('全局引入Lodash', _);
52 | console.warn('全局引入Echarts', echarts);
53 |
54 | console.warn(`current 'API' value: '${API}'`);
55 |
56 | const $btn = $('.btn');
57 | $btn.on('click', function (e) {
58 | $btn
59 | .removeClass('btn-primary, btn-outline-primary')
60 | .addClass('btn-primary');
61 | $(e.target).removeClass('btn-primary').addClass('btn-outline-primary');
62 | });
63 |
64 | if (process.env.NODE_ENV === 'development') {
65 | const key = 'a63b0782ec22dfd190771f7f57cf579d';
66 | $.post('/txapi/ncov/index', { key }, function (response) {
67 | if (response.code === 200) {
68 | const desc = response.newslist[0].desc;
69 | displayState(desc);
70 | }
71 | });
72 | } else {
73 | const data = require('../static/data/data.json');
74 | displayState(data.newslist[0].desc);
75 | }
76 |
77 | document.querySelector('#script-import').src = bg;
78 |
79 | const years = $('#years').elSelect(
80 | [{ value: '2019', text: '2019年' }], //初始设置的数据
81 | (value, text) => {
82 | alert(
83 | `value: ${value}, text: ${text}\n提示:调用setValue方法也会设置value也会触发回调`
84 | );
85 | }
86 | );
87 | years.setData(dateM.nearlyYears()); //再次设置可选择数据
88 | // years.setValue('2015'); //设置指定值
89 |
90 | console.log($('#date-range').daterangepicker);
91 |
92 | $('#date').daterangepicker(
93 | {
94 | locale,
95 | // autoApply: true,
96 | drops: 'up',
97 | startDate: '2020/09/09',
98 | singleDatePicker: true,
99 | },
100 | function (start, end, label) {
101 | console.log(
102 | '选择了一个新的日期: ' +
103 | start.format('YYYY-MM-DD') +
104 | ' to ' +
105 | end.format('YYYY-MM-DD')
106 | );
107 | }
108 | );
109 |
110 | $('#date-range').daterangepicker(
111 | {
112 | locale,
113 | // autoApply: true,
114 | drops: 'up',
115 | opens: 'left',
116 | startDate: '2020/09/03',
117 | endDate: '2020/09/09',
118 | },
119 | function (start, end, label) {
120 | console.log(
121 | '选择了一个新的日期: ' +
122 | start.format('YYYY-MM-DD') +
123 | ' to ' +
124 | end.format('YYYY-MM-DD')
125 | );
126 | }
127 | );
128 |
129 | const arith = new Arithmetic(); //初始化计算对象
130 | $('#calc').on('click', () => {
131 | const expression = $('#calc-input').val();
132 | const result = arith.calculate(expression); //传入表达式开始计算
133 | alert(result);
134 | });
135 | });
136 |
--------------------------------------------------------------------------------
/src/static/iconfont/iconfont.js:
--------------------------------------------------------------------------------
1 | !function(c){var e,a='',t=(e=document.getElementsByTagName("script"))[e.length-1].getAttribute("data-injectcss");if(t&&!c.__iconfont__svg__cssinject__){c.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(e){console&&console.log(e)}}!function(e){if(document.addEventListener)if(~["complete","loaded","interactive"].indexOf(document.readyState))setTimeout(e,0);else{var t=function(){document.removeEventListener("DOMContentLoaded",t,!1),e()};document.addEventListener("DOMContentLoaded",t,!1)}else document.attachEvent&&(o=e,i=c.document,l=!1,(a=function(){try{i.documentElement.doScroll("left")}catch(e){return void setTimeout(a,50)}n()})(),i.onreadystatechange=function(){"complete"==i.readyState&&(i.onreadystatechange=null,n())});function n(){l||(l=!0,o())}var o,i,l,a}(function(){var e,t,n,o,i,l;(e=document.createElement("div")).innerHTML=a,a=null,(t=e.getElementsByTagName("svg")[0])&&(t.setAttribute("aria-hidden","true"),t.style.position="absolute",t.style.width=0,t.style.height=0,t.style.overflow="hidden",n=t,(o=document.body).firstChild?(i=n,(l=o.firstChild).parentNode.insertBefore(i,l)):o.appendChild(n))})}(window);
--------------------------------------------------------------------------------
/src/plugin/el-select/index.js:
--------------------------------------------------------------------------------
1 | import '../../lib/jquery.nicescroll';
2 | import './select.sass';
3 |
4 | const down = require('./chevron-down.svg');
5 | console.log(down);
6 | $.fn.extend({
7 | elSelect: function (data, callback) {
8 | const _this = this;
9 | const $input = _this.children('input');
10 | /* webpack打包好的代码中回自动去掉 type="text" */
11 | // const $input = _this.children('input[type="text"]');
12 | const $glyphicon = $(
13 | ``
16 | // ``
17 | );
18 | const $ul = $(
19 | ''
22 | );
23 | const $arrow = $('');
24 |
25 | let _data = null;
26 | let _callback = callback;
27 | let displayFlag = false;
28 |
29 | _this.append($glyphicon).append($arrow).append($ul);
30 |
31 | $input
32 | .on('click', function () {
33 | if (displayFlag) setListVisible(false);
34 | else setListVisible(true);
35 | if (_this.get(0).offsetWidth != $ul[0].offsetWidth) {
36 | $ul.css({ width: _this.get(0).offsetWidth + 'px' });
37 | }
38 | })
39 | .prop('readonly', true)
40 | .attr('placeholder', '请选择');
41 |
42 | $glyphicon.on('click', function () {
43 | if (displayFlag) setListVisible(false);
44 | else setListVisible(true);
45 | });
46 |
47 | if (typeof data == 'object' && data instanceof Array) setData(data);
48 |
49 | $ul
50 | .on('click', function (e) {
51 | const $target = $(e.target);
52 | const value = $target.attr('data-value');
53 | const text = $target.text();
54 | $input.val(text).attr('title', text).data('value', value);
55 | if (typeof _callback == 'function') _callback(value, text);
56 | })
57 | .niceScroll({
58 | cursorcolor: '#c0c4cc',
59 | });
60 |
61 | $(document).on('click', function (e) {
62 | if (
63 | e.target !== _this.get(0) &&
64 | e.target !== $input.get(0) &&
65 | e.target !== $ul.get(0) &&
66 | e.target !== $glyphicon.get(0)
67 | )
68 | setListVisible(false);
69 | });
70 |
71 | function setListVisible(visible) {
72 | if (visible) {
73 | $arrow.show();
74 | $ul.show();
75 | $glyphicon.css('transform', 'translateY(-50%) rotate(180deg)');
76 | } else {
77 | $arrow.hide();
78 | $ul.hide().getNiceScroll(0).doScrollLeft(0);
79 | $glyphicon.css('transform', 'translateY(-50%) rotate(0)');
80 | }
81 | displayFlag = visible;
82 | }
83 |
84 | function setData(data) {
85 | _data = data;
86 | $ul.empty();
87 | for (let i = 0, len = _data.length; i < len; i++) {
88 | $ul.append(
89 | '' +
94 | _data[i].text +
95 | ''
96 | );
97 | }
98 | $ul.getNiceScroll().resize();
99 | return _this;
100 | }
101 |
102 | _this.setData = setData;
103 |
104 | _this.setCallback = function (callback) {
105 | if (typeof callback == 'function') _callback = callback;
106 | };
107 |
108 | _this.setValue = function (value) {
109 | if (typeof _data == 'object' && _data instanceof Array && _data.length)
110 | for (let i = 0, len = _data.length; i < len; i++) {
111 | if (value == _data[i].value) {
112 | $input
113 | .val(_data[i].text)
114 | .attr('title', _data[i].text)
115 | .data('value', value);
116 | if (typeof _callback == 'function')
117 | _callback(_data[i].value, _data[i].text);
118 | return _this;
119 | }
120 | }
121 | return _this;
122 | };
123 |
124 | _this.value = function () {
125 | return $input.data('value');
126 | };
127 |
128 | return _this;
129 | },
130 | });
131 |
--------------------------------------------------------------------------------
/src/static/data/data.json:
--------------------------------------------------------------------------------
1 | {
2 | "code": 200,
3 | "msg": "success",
4 | "newslist": [
5 | {
6 | "news": [
7 | {
8 | "id": 12991,
9 | "pubDate": 1584938403000,
10 | "pubDateStr": "1小时前",
11 | "title": "哥伦比亚监狱暴动致23死90伤:囚犯不满卫生条件差发起抗议",
12 | "summary": "3月22日,哥伦比亚首都波哥大的一座监狱发生暴动,造成至少23人死亡,十多人受伤。据称囚犯因不满新冠疫情下的监狱卫生条件发起抗议,而司法部长称暴乱只是一场大规模的越狱意图。",
13 | "infoSource": "人民日报海外版",
14 | "sourceUrl": "http:\/\/m.weibo.cn\/3057540037\/4485619134236654",
15 | "provinceId": "1",
16 | "createTime": 1584939378000,
17 | "modifyTime": 1584939378000,
18 | "entryWay": 1,
19 | "adoptType": 1,
20 | "infoType": 1,
21 | "dataInfoState": 0,
22 | "dataInfoOperator": "",
23 | "dataInfoTime": 1584939378000
24 | },
25 | {
26 | "id": 12985,
27 | "pubDate": 1584937444000,
28 | "pubDateStr": "1小时前",
29 | "title": "新西兰宣布将全面停工停课",
30 | "summary": "新西兰总理阿德恩23日表示,48小时后将把新冠肺炎疫情警报等级提高到最高级。届时,新西兰全国将全面停工停课,仅保留超市、医疗机构等必要机构运行。该警报等级将至少持续四周。\n",
31 | "infoSource": "央视新闻",
32 | "sourceUrl": "http:\/\/m.weibo.cn\/2656274875\/4485615112315259",
33 | "provinceId": "1",
34 | "createTime": 1584938417000,
35 | "modifyTime": 1584938417000,
36 | "entryWay": 1,
37 | "adoptType": 1,
38 | "infoType": 2,
39 | "dataInfoState": 0,
40 | "dataInfoOperator": "",
41 | "dataInfoTime": 1584938417000
42 | },
43 | {
44 | "id": 12975,
45 | "pubDate": 1584934983000,
46 | "pubDateStr": "2小时前",
47 | "title": "天津新增4例境外输入病例",
48 | "summary": "3月22日18时至23日6时,天津无新增报告本地新冠肺炎确诊病例,新增报告4例境外输入确诊病例(中国籍3例、法国籍1例),累计报告境外输入确诊病例5例(中国籍4例、法国籍1例)。",
49 | "infoSource": "人民日报",
50 | "sourceUrl": "http:\/\/m.weibo.cn\/2803301701\/4485604790057843",
51 | "provinceId": "12",
52 | "provinceName": "天津市",
53 | "createTime": 1584935781000,
54 | "modifyTime": 1584935781000,
55 | "entryWay": 1,
56 | "adoptType": 1,
57 | "infoType": 2,
58 | "dataInfoState": 0,
59 | "dataInfoOperator": "",
60 | "dataInfoTime": 1584935781000
61 | },
62 | {
63 | "id": 12968,
64 | "pubDate": 1584933008000,
65 | "pubDateStr": "2小时前",
66 | "title": "澳大利亚无法集结参加今夏奥运会",
67 | "summary": "据今日俄罗斯网站23日报道,澳大利亚奥委会(AOC)表示,鉴于国内外(疫情)不断变化的情势,澳大利亚团队“无法集结”参与今夏奥运会,会为2021年准备。\n",
68 | "infoSource": "人民日报海外版",
69 | "sourceUrl": "http:\/\/m.weibo.cn\/3057540037\/4485596506899811",
70 | "provinceId": "1",
71 | "createTime": 1584933978000,
72 | "modifyTime": 1584933978000,
73 | "entryWay": 1,
74 | "adoptType": 1,
75 | "infoType": 2,
76 | "dataInfoState": 0,
77 | "dataInfoOperator": "",
78 | "dataInfoTime": 1584933978000
79 | },
80 | {
81 | "id": 12953,
82 | "pubDate": 1584930447000,
83 | "pubDateStr": "3小时前",
84 | "title": "上海应急响应级别调整为二级",
85 | "summary": "上海市自3月3日起已无新增本地确诊病例,上海市政府决定,自24日零时起,将上海市重大突发公共卫生事件应急响应级别由一级响应调整为二级响应。上海市将继续高度重视疫情防控工作,特别是以严防境外疫情输入为重点,做好口岸防控和社区防控。\n",
86 | "infoSource": "央视新闻",
87 | "sourceUrl": "http:\/\/m.weibo.cn\/2656274875\/4485585765178598",
88 | "provinceId": "31",
89 | "provinceName": "上海市",
90 | "createTime": 1584931217000,
91 | "modifyTime": 1584931217000,
92 | "entryWay": 1,
93 | "adoptType": 1,
94 | "infoType": 2,
95 | "dataInfoState": 0,
96 | "dataInfoOperator": "",
97 | "dataInfoTime": 1584931217000
98 | }
99 | ],
100 | "desc": {
101 | "id": 1,
102 | "createTime": 1579537899000,
103 | "modifyTime": 1584941547000,
104 | "summary": "",
105 | "deleted": false,
106 | "countRemark": "",
107 | "currentConfirmedCount": 5486,
108 | "confirmedCount": 81608,
109 | "suspectedCount": 354,
110 | "curedCount": 72846,
111 | "deadCount": 3276,
112 | "seriousCount": 1749,
113 | "suspectedIncr": 40,
114 | "currentConfirmedIncr": -363,
115 | "confirmedIncr": 110,
116 | "curedIncr": 464,
117 | "deadIncr": 9,
118 | "seriousIncr": -96,
119 | "remark1": "易感人群:人群普遍易感。老年人及有基础疾病者感染后病情较重,儿童及婴幼儿也有发病",
120 | "remark2": "潜伏期:一般为 3~7 天,最长不超过 14 天,潜伏期内可能存在传染性,其中无症状病例传染性非常罕见",
121 | "remark3": "宿主:野生动物,可能为中华菊头蝠",
122 | "remark4": "",
123 | "remark5": "",
124 | "note1": "病毒:SARS-CoV-2,其导致疾病命名 COVID-19",
125 | "note2": "传染源:新冠肺炎的患者。无症状感染者也可能成为传染源。",
126 | "note3": "传播途径:经呼吸道飞沫、接触传播是主要的传播途径。气溶胶传播和消化道等传播途径尚待明确。",
127 | "generalRemark": "1. 3 月 12 日国家卫健委确诊补订遗漏 12 例确诊病例(非 12 日新增),暂无具体省份信息。 2. 浙江省 12 例外省治愈暂无具体省份信息。",
128 | "abroadRemark": "",
129 | "foreignStatistics": {
130 | "currentConfirmedCount": 220144,
131 | "confirmedCount": 256234,
132 | "suspectedCount": 4,
133 | "curedCount": 24813,
134 | "deadCount": 11277,
135 | "suspectedIncr": 0,
136 | "currentConfirmedIncr": 2905,
137 | "confirmedIncr": 3140,
138 | "curedIncr": 208,
139 | "deadIncr": 27
140 | },
141 | "globalStatistics": {
142 | "currentConfirmedCount": 225630,
143 | "confirmedCount": 337842,
144 | "curedCount": 97659,
145 | "deadCount": 14553,
146 | "currentConfirmedIncr": 2542,
147 | "confirmedIncr": 3250,
148 | "curedIncr": 672,
149 | "deadIncr": 36
150 | }
151 | }
152 | }
153 | ]
154 | }
--------------------------------------------------------------------------------
/src/plugin/arithmetic/index.js:
--------------------------------------------------------------------------------
1 | import Stack from './stack';
2 |
3 | export default class Arithmetic {
4 | constructor() {
5 | this.operand = new Stack();
6 | this.operator = new Stack();
7 | this.tempNum = '';
8 | this.tempSym = '';
9 | }
10 | /**
11 | * @description 递归表达式,优先计算括号中的内容并进行替换
12 | * @param {String}
13 | */
14 | matchInBrackets(expression) {
15 | const regInBrackets = /\([\+|\-|\*|\/|\.|\d]+?\)/g;
16 | let expInBrackets = expression.match(regInBrackets);
17 | if (expInBrackets) {
18 | expInBrackets.forEach((element) => {
19 | const tempResualt = this.calculate(element.replace(/[\(|\)]/g, ''));
20 | expression = expression.replace(element, tempResualt);
21 | });
22 | }
23 | expInBrackets = expression.match(regInBrackets);
24 | return expInBrackets ? this.matchInBrackets(expression) : expression;
25 | }
26 | /**
27 | * @description 初步处理计算表达式,将优先级高的乘除运算和括号内的运算先计算出结果
28 | * @param {String}
29 | */
30 | calculate(expression) {
31 | // 先判断表达式中是否存在括号运算,如果有则递归计算出其中的值并替换表达式中的括号
32 | expression = this.matchInBrackets(expression);
33 | for (let i = expression.length - 1; 0 <= i; i--) {
34 | const numReg = /[\d|\.]/;
35 | let char = expression[i];
36 | if (numReg.test(char)) {
37 | this.tempNum = char + this.tempNum;
38 | if (0 == i) {
39 | if (this.tempSym) {
40 | this.calculateMultiOrDivis(this.tempSym);
41 | this.tempSym = '';
42 | }
43 | if (this.tempNum) this.operand.push(this.tempNum);
44 | break;
45 | }
46 | } else {
47 | if (0 == i) {
48 | if (this.tempSym) {
49 | this.calculateMultiOrDivis(this.tempSym);
50 | this.tempSym = '';
51 | }
52 | if (this.tempNum) this.operand.push(this.tempNum);
53 | this.operator.push(char);
54 | break;
55 | }
56 | if (this.tempSym) {
57 | this.calculateMultiOrDivis(this.tempSym);
58 | this.tempSym = '';
59 | }
60 | let peekSym = this.operator.peek();
61 | const nextChar = expression[i - 1];
62 | const isSymbol = /[\+|\-|\*|\/]/;
63 | if (peekSym) {
64 | if (this.tempNum) {
65 | if (isSymbol.test(nextChar) && '-' == char) {
66 | this.operand.push(char + this.tempNum);
67 | char = '';
68 | } else {
69 | this.operand.push(this.tempNum);
70 | }
71 | this.tempNum = '';
72 | }
73 | switch (Arithmetic.priorityCompare(peekSym, char)) {
74 | case 2:
75 | this.tempSym = this.operator.pop();
76 | break;
77 | case 1:
78 | this.calculateMultiOrDivis(this.operator.pop());
79 | break;
80 | default:
81 | break;
82 | }
83 | } else if (!peekSym && this.tempNum) {
84 | if (isSymbol.test(nextChar) && '-' == char) {
85 | this.operand.push(char + this.tempNum);
86 | char = '';
87 | } else {
88 | this.operand.push(this.tempNum);
89 | }
90 | this.tempNum = '';
91 | }
92 | if (char) this.operator.push(char);
93 | }
94 | }
95 | return this.calculateReversePoland();
96 | }
97 | /**
98 | * @description 计算最终的逆波兰表达式
99 | */
100 | calculateReversePoland() {
101 | let resualt = 0;
102 | while (0 < this.operand.getLength()) {
103 | if (this.operator.getLength() == this.operand.getLength()) {
104 | const symL = resualt;
105 | const symR = this.operand.pop();
106 | const cacheSym = this.operator.pop();
107 | resualt =
108 | '+' == cacheSym
109 | ? Arithmetic.addition(symL, symR)
110 | : Arithmetic.subtraction(symL, symR);
111 | } else {
112 | if (1 == this.operand.getLength()) {
113 | resualt = parseFloat(this.operand.pop());
114 | break;
115 | }
116 | const symL = this.operand.pop();
117 | const symR = this.operand.pop();
118 | const cacheSym = this.operator.pop();
119 | resualt = Arithmetic.selectCalculationRule(symL, symR, cacheSym);
120 | }
121 | this.operand.push(resualt);
122 | }
123 | this.operand.reset();
124 | this.operator.reset();
125 | this.tempNum = '';
126 | this.tempSym = '';
127 | return resualt;
128 | }
129 | /**
130 | * @description 只计算乘法或者除法
131 | * @param {String} sym
132 | */
133 | calculateMultiOrDivis(sym) {
134 | const symL = this.operand.pop();
135 | const symR = this.operand.pop();
136 | this.operand.push(Arithmetic.selectCalculationRule(symL, symR, sym));
137 | return undefined;
138 | }
139 | /**
140 | * @description 判断两个数字间的运算法则
141 | * @param {String || Number} symL
142 | * @param {String || Number} symR
143 | * @param {String} sym
144 | */
145 | static selectCalculationRule(symL, symR, sym) {
146 | switch (sym) {
147 | case '*':
148 | return Arithmetic.multiplication(symL, symR);
149 | case '/':
150 | return Arithmetic.division(symL, symR);
151 | case '+':
152 | return Arithmetic.addition(symL, symR);
153 | default:
154 | return Arithmetic.subtraction(symL, symR);
155 | }
156 | }
157 | /**
158 | * @description 加法
159 | * @param {String || Number}
160 | */
161 | static addition(...num) {
162 | const symL = parseFloat(num[0]);
163 | const symR = parseFloat(num[1]);
164 | return symL + symR;
165 | }
166 | /**
167 | * @description 除法
168 | * @param {String || Number}
169 | */
170 | static division(...num) {
171 | const symL = parseFloat(num[0]);
172 | const symR = parseFloat(num[1]);
173 | return symL / symR;
174 | }
175 | /**
176 | * @description 乘法
177 | * @param {String || Number}
178 | */
179 | static multiplication(...num) {
180 | const symL = parseFloat(num[0]);
181 | const symR = parseFloat(num[1]);
182 | return symL * symR;
183 | }
184 | /**
185 | * @description 减法
186 | * @param {String || Number}
187 | */
188 | static subtraction(...num) {
189 | const symL = parseFloat(num[0]);
190 | const symR = parseFloat(num[1]);
191 | return symL - symR;
192 | }
193 | /**
194 | * @description 判断两个运算符的优先级
195 | * @param {String}
196 | */
197 | static priorityCompare(symA, symB) {
198 | const high = /[\*\/]/;
199 | if (high.test(symA) && !high.test(symB)) {
200 | return 2;
201 | } else if (high.test(symA) && high.test(symB)) {
202 | return 1;
203 | } else {
204 | return 0;
205 | }
206 | }
207 | }
208 |
--------------------------------------------------------------------------------
/src/view/demo.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | 上手使用
7 |
8 |
9 |
10 |
11 |
什么是JQDE?
12 |
13 | 是一套基于Webpack搭建的jQuery项目开发环境(jQuery development
14 | environment),使jQuery项目能够以前后端分离模式进行开发,这是一种有效提高开发效率的先进模式。利用此环境前端开发人员无需搭建后台环境,只需要配置相应的代理地址即可实现前后端的数据流通。并且此环境配置了对Sass和Stylus两种CSS样式预编译语言的配置,可以直接使用这些语言高效快速的编写界面样式。
17 |
18 |
19 |
开始使用
20 |
21 | 对于多页面的jQuery项目,每个页面需要一个入口文件,入口文件的名称需要与页面名称严格对应,并且分别放置在src目录下的script和view目录中,这两个目录名称及位置不允许被改变。例如当前页面为view中的demo.html,对应的脚本入口文件为script中的demo.js,这是该页面的主入口文件。这样Webpack会将两个文件建立联系,而样式文件及其他脚本或库的引入都可以在主入口文件中通过import或者require引入。
24 |
25 |
26 |
27 |
28 |
29 |
配置代理
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
41 |
42 |
43 | ---- / 例
44 |
45 |
较昨日新增 ----
46 |
49 |
50 |
51 |
52 |
55 |
56 |
57 | ---- / 例
58 |
59 |
较昨日新增 ----
60 |
63 |
64 |
65 |
66 |
69 |
70 |
71 | ---- / 例
72 |
73 |
较昨日新增 ----
74 |
77 |
78 |
79 |
80 |
81 |
82 | 数据来源
83 | 天行数据
89 |
90 |
91 |
92 |
93 |
94 |
95 | 上面的显示的信息是对于Webpack请求代理配置的自验和功能展示,千万不要以为是广告植入。这里去请求了一个第三方的接口地址,如果你目前是通过npm
96 | start启动的项目,那么这些数据是动态获取的,如果你是从dist中直接打开的本地页面,那么这些数据从有页面引入的json中获取。代理接口地址的修改在server.js中可以看到proxy属性,请根据自己项目情况自行设定。另外,开发环境端口后的配置也在此文件中。
99 |
100 |

101 |
102 |
域名及端口的设置
103 |
104 | 通过在server.js中引入dotenv,我们可以方便的在根目录下的.env文件中对域名和端口号进行设置。
105 |
106 |

107 |
108 |
全局变量的配置
109 |
110 | 通过Webpack的DefinePlugin,我们可以获取到指定变量在不同开发环境下的取值,这些配置在config目录下的dev.config.js和prod.config.js两个文件中。现在你可以打开控制台查看当前对API变量的取值情况。
112 |
113 |
114 |
全局引入jQuery、Lodash、Echarts
115 |
116 | 在配置webpack时已将jQuery、Lodash、Echarts这三个常用库全局引入,各个模块中可直接调用。就像本页面在demo.js中将他们直接打印出来,但没有在文件顶部引入,你可以去控制台查看打印结果。
117 |
118 |
119 |
123 |
124 |
125 |
图片的引入
126 |
127 |
128 |
129 |
130 |
134 | img标签src引入
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 | script脚本import引入
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |

157 |
158 |
159 | css样式background引入
160 |
161 |
162 |
163 |
164 |
165 |
166 |
字体图标的引入
167 |
168 | 只需在主入口文件或页面对应的css文件中引入相应的字体css文件即可,示例图标:
171 |
172 |
173 | 你还可以尝试Bootstrap Icons
179 |
180 |
181 | 同时了解下Bootstrap4
187 |
188 |
189 |
关于HTML文件没有热重载
190 |
191 | 由于为了满足img标签通过src属性链接图片而采用了html-loader,目前不能实现Html文件变更的响应。
192 |
193 |
194 |
模拟Element的Select选择器
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 | Select选择器基于jQuery和jQuery.niceScroll(存放在lib目录下)及Bootstrap编写,存放在plugin目录下,使用时先引入该插件后$('')选择元素调用.elSelect方法,接收数据数组和回调两个参数。提供setData、setValue、setCallback和value四个接口,分别用来初始化后更新数据、设值、添加或修改回调、取值。select.sass文件顶部定义有颜色变量可修改。
204 |
205 |
206 |
210 |
214 |
215 |
216 |
Arithmetic 类
217 |
218 | 一个用于前端解析计算公式并输出结果的小工具,原生JS实现不依赖任何第三方库,可以实现简单的四则运算。使用时只需new出实例对象,每次需要计算时调用calculate方法并传入计算式即可。
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
234 |
235 |
236 |
237 | 跳转
238 | GitHub仓
244 |
245 |
246 |
推荐的日期选择插件Date Range Picker
247 |
248 |
256 |
257 |
258 | Date Range Picker文档
264 |
265 |
266 |
267 |
Back to index
270 |
271 |
272 |
273 |
--------------------------------------------------------------------------------
/src/static/iconfont/demo.css:
--------------------------------------------------------------------------------
1 | /* Logo 字体 */
2 | @font-face {
3 | font-family: "iconfont logo";
4 | src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834');
5 | src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834#iefix') format('embedded-opentype'),
6 | url('https://at.alicdn.com/t/font_985780_km7mi63cihi.woff?t=1545807318834') format('woff'),
7 | url('https://at.alicdn.com/t/font_985780_km7mi63cihi.ttf?t=1545807318834') format('truetype'),
8 | url('https://at.alicdn.com/t/font_985780_km7mi63cihi.svg?t=1545807318834#iconfont') format('svg');
9 | }
10 |
11 | .logo {
12 | font-family: "iconfont logo";
13 | font-size: 160px;
14 | font-style: normal;
15 | -webkit-font-smoothing: antialiased;
16 | -moz-osx-font-smoothing: grayscale;
17 | }
18 |
19 | /* tabs */
20 | .nav-tabs {
21 | position: relative;
22 | }
23 |
24 | .nav-tabs .nav-more {
25 | position: absolute;
26 | right: 0;
27 | bottom: 0;
28 | height: 42px;
29 | line-height: 42px;
30 | color: #666;
31 | }
32 |
33 | #tabs {
34 | border-bottom: 1px solid #eee;
35 | }
36 |
37 | #tabs li {
38 | cursor: pointer;
39 | width: 100px;
40 | height: 40px;
41 | line-height: 40px;
42 | text-align: center;
43 | font-size: 16px;
44 | border-bottom: 2px solid transparent;
45 | position: relative;
46 | z-index: 1;
47 | margin-bottom: -1px;
48 | color: #666;
49 | }
50 |
51 |
52 | #tabs .active {
53 | border-bottom-color: #f00;
54 | color: #222;
55 | }
56 |
57 | .tab-container .content {
58 | display: none;
59 | }
60 |
61 | /* 页面布局 */
62 | .main {
63 | padding: 30px 100px;
64 | width: 960px;
65 | margin: 0 auto;
66 | }
67 |
68 | .main .logo {
69 | color: #333;
70 | text-align: left;
71 | margin-bottom: 30px;
72 | line-height: 1;
73 | height: 110px;
74 | margin-top: -50px;
75 | overflow: hidden;
76 | *zoom: 1;
77 | }
78 |
79 | .main .logo a {
80 | font-size: 160px;
81 | color: #333;
82 | }
83 |
84 | .helps {
85 | margin-top: 40px;
86 | }
87 |
88 | .helps pre {
89 | padding: 20px;
90 | margin: 10px 0;
91 | border: solid 1px #e7e1cd;
92 | background-color: #fffdef;
93 | overflow: auto;
94 | }
95 |
96 | .icon_lists {
97 | width: 100% !important;
98 | overflow: hidden;
99 | *zoom: 1;
100 | }
101 |
102 | .icon_lists li {
103 | width: 100px;
104 | margin-bottom: 10px;
105 | margin-right: 20px;
106 | text-align: center;
107 | list-style: none !important;
108 | cursor: default;
109 | }
110 |
111 | .icon_lists li .code-name {
112 | line-height: 1.2;
113 | }
114 |
115 | .icon_lists .icon {
116 | display: block;
117 | height: 100px;
118 | line-height: 100px;
119 | font-size: 42px;
120 | margin: 10px auto;
121 | color: #333;
122 | -webkit-transition: font-size 0.25s linear, width 0.25s linear;
123 | -moz-transition: font-size 0.25s linear, width 0.25s linear;
124 | transition: font-size 0.25s linear, width 0.25s linear;
125 | }
126 |
127 | .icon_lists .icon:hover {
128 | font-size: 100px;
129 | }
130 |
131 | .icon_lists .svg-icon {
132 | /* 通过设置 font-size 来改变图标大小 */
133 | width: 1em;
134 | /* 图标和文字相邻时,垂直对齐 */
135 | vertical-align: -0.15em;
136 | /* 通过设置 color 来改变 SVG 的颜色/fill */
137 | fill: currentColor;
138 | /* path 和 stroke 溢出 viewBox 部分在 IE 下会显示
139 | normalize.css 中也包含这行 */
140 | overflow: hidden;
141 | }
142 |
143 | .icon_lists li .name,
144 | .icon_lists li .code-name {
145 | color: #666;
146 | }
147 |
148 | /* markdown 样式 */
149 | .markdown {
150 | color: #666;
151 | font-size: 14px;
152 | line-height: 1.8;
153 | }
154 |
155 | .highlight {
156 | line-height: 1.5;
157 | }
158 |
159 | .markdown img {
160 | vertical-align: middle;
161 | max-width: 100%;
162 | }
163 |
164 | .markdown h1 {
165 | color: #404040;
166 | font-weight: 500;
167 | line-height: 40px;
168 | margin-bottom: 24px;
169 | }
170 |
171 | .markdown h2,
172 | .markdown h3,
173 | .markdown h4,
174 | .markdown h5,
175 | .markdown h6 {
176 | color: #404040;
177 | margin: 1.6em 0 0.6em 0;
178 | font-weight: 500;
179 | clear: both;
180 | }
181 |
182 | .markdown h1 {
183 | font-size: 28px;
184 | }
185 |
186 | .markdown h2 {
187 | font-size: 22px;
188 | }
189 |
190 | .markdown h3 {
191 | font-size: 16px;
192 | }
193 |
194 | .markdown h4 {
195 | font-size: 14px;
196 | }
197 |
198 | .markdown h5 {
199 | font-size: 12px;
200 | }
201 |
202 | .markdown h6 {
203 | font-size: 12px;
204 | }
205 |
206 | .markdown hr {
207 | height: 1px;
208 | border: 0;
209 | background: #e9e9e9;
210 | margin: 16px 0;
211 | clear: both;
212 | }
213 |
214 | .markdown p {
215 | margin: 1em 0;
216 | }
217 |
218 | .markdown>p,
219 | .markdown>blockquote,
220 | .markdown>.highlight,
221 | .markdown>ol,
222 | .markdown>ul {
223 | width: 80%;
224 | }
225 |
226 | .markdown ul>li {
227 | list-style: circle;
228 | }
229 |
230 | .markdown>ul li,
231 | .markdown blockquote ul>li {
232 | margin-left: 20px;
233 | padding-left: 4px;
234 | }
235 |
236 | .markdown>ul li p,
237 | .markdown>ol li p {
238 | margin: 0.6em 0;
239 | }
240 |
241 | .markdown ol>li {
242 | list-style: decimal;
243 | }
244 |
245 | .markdown>ol li,
246 | .markdown blockquote ol>li {
247 | margin-left: 20px;
248 | padding-left: 4px;
249 | }
250 |
251 | .markdown code {
252 | margin: 0 3px;
253 | padding: 0 5px;
254 | background: #eee;
255 | border-radius: 3px;
256 | }
257 |
258 | .markdown strong,
259 | .markdown b {
260 | font-weight: 600;
261 | }
262 |
263 | .markdown>table {
264 | border-collapse: collapse;
265 | border-spacing: 0px;
266 | empty-cells: show;
267 | border: 1px solid #e9e9e9;
268 | width: 95%;
269 | margin-bottom: 24px;
270 | }
271 |
272 | .markdown>table th {
273 | white-space: nowrap;
274 | color: #333;
275 | font-weight: 600;
276 | }
277 |
278 | .markdown>table th,
279 | .markdown>table td {
280 | border: 1px solid #e9e9e9;
281 | padding: 8px 16px;
282 | text-align: left;
283 | }
284 |
285 | .markdown>table th {
286 | background: #F7F7F7;
287 | }
288 |
289 | .markdown blockquote {
290 | font-size: 90%;
291 | color: #999;
292 | border-left: 4px solid #e9e9e9;
293 | padding-left: 0.8em;
294 | margin: 1em 0;
295 | }
296 |
297 | .markdown blockquote p {
298 | margin: 0;
299 | }
300 |
301 | .markdown .anchor {
302 | opacity: 0;
303 | transition: opacity 0.3s ease;
304 | margin-left: 8px;
305 | }
306 |
307 | .markdown .waiting {
308 | color: #ccc;
309 | }
310 |
311 | .markdown h1:hover .anchor,
312 | .markdown h2:hover .anchor,
313 | .markdown h3:hover .anchor,
314 | .markdown h4:hover .anchor,
315 | .markdown h5:hover .anchor,
316 | .markdown h6:hover .anchor {
317 | opacity: 1;
318 | display: inline-block;
319 | }
320 |
321 | .markdown>br,
322 | .markdown>p>br {
323 | clear: both;
324 | }
325 |
326 |
327 | .hljs {
328 | display: block;
329 | background: white;
330 | padding: 0.5em;
331 | color: #333333;
332 | overflow-x: auto;
333 | }
334 |
335 | .hljs-comment,
336 | .hljs-meta {
337 | color: #969896;
338 | }
339 |
340 | .hljs-string,
341 | .hljs-variable,
342 | .hljs-template-variable,
343 | .hljs-strong,
344 | .hljs-emphasis,
345 | .hljs-quote {
346 | color: #df5000;
347 | }
348 |
349 | .hljs-keyword,
350 | .hljs-selector-tag,
351 | .hljs-type {
352 | color: #a71d5d;
353 | }
354 |
355 | .hljs-literal,
356 | .hljs-symbol,
357 | .hljs-bullet,
358 | .hljs-attribute {
359 | color: #0086b3;
360 | }
361 |
362 | .hljs-section,
363 | .hljs-name {
364 | color: #63a35c;
365 | }
366 |
367 | .hljs-tag {
368 | color: #333333;
369 | }
370 |
371 | .hljs-title,
372 | .hljs-attr,
373 | .hljs-selector-id,
374 | .hljs-selector-class,
375 | .hljs-selector-attr,
376 | .hljs-selector-pseudo {
377 | color: #795da3;
378 | }
379 |
380 | .hljs-addition {
381 | color: #55a532;
382 | background-color: #eaffea;
383 | }
384 |
385 | .hljs-deletion {
386 | color: #bd2c00;
387 | background-color: #ffecec;
388 | }
389 |
390 | .hljs-link {
391 | text-decoration: underline;
392 | }
393 |
394 | /* 代码高亮 */
395 | /* PrismJS 1.15.0
396 | https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript */
397 | /**
398 | * prism.js default theme for JavaScript, CSS and HTML
399 | * Based on dabblet (http://dabblet.com)
400 | * @author Lea Verou
401 | */
402 | code[class*="language-"],
403 | pre[class*="language-"] {
404 | color: black;
405 | background: none;
406 | text-shadow: 0 1px white;
407 | font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
408 | text-align: left;
409 | white-space: pre;
410 | word-spacing: normal;
411 | word-break: normal;
412 | word-wrap: normal;
413 | line-height: 1.5;
414 |
415 | -moz-tab-size: 4;
416 | -o-tab-size: 4;
417 | tab-size: 4;
418 |
419 | -webkit-hyphens: none;
420 | -moz-hyphens: none;
421 | -ms-hyphens: none;
422 | hyphens: none;
423 | }
424 |
425 | pre[class*="language-"]::-moz-selection,
426 | pre[class*="language-"] ::-moz-selection,
427 | code[class*="language-"]::-moz-selection,
428 | code[class*="language-"] ::-moz-selection {
429 | text-shadow: none;
430 | background: #b3d4fc;
431 | }
432 |
433 | pre[class*="language-"]::selection,
434 | pre[class*="language-"] ::selection,
435 | code[class*="language-"]::selection,
436 | code[class*="language-"] ::selection {
437 | text-shadow: none;
438 | background: #b3d4fc;
439 | }
440 |
441 | @media print {
442 |
443 | code[class*="language-"],
444 | pre[class*="language-"] {
445 | text-shadow: none;
446 | }
447 | }
448 |
449 | /* Code blocks */
450 | pre[class*="language-"] {
451 | padding: 1em;
452 | margin: .5em 0;
453 | overflow: auto;
454 | }
455 |
456 | :not(pre)>code[class*="language-"],
457 | pre[class*="language-"] {
458 | background: #f5f2f0;
459 | }
460 |
461 | /* Inline code */
462 | :not(pre)>code[class*="language-"] {
463 | padding: .1em;
464 | border-radius: .3em;
465 | white-space: normal;
466 | }
467 |
468 | .token.comment,
469 | .token.prolog,
470 | .token.doctype,
471 | .token.cdata {
472 | color: slategray;
473 | }
474 |
475 | .token.punctuation {
476 | color: #999;
477 | }
478 |
479 | .namespace {
480 | opacity: .7;
481 | }
482 |
483 | .token.property,
484 | .token.tag,
485 | .token.boolean,
486 | .token.number,
487 | .token.constant,
488 | .token.symbol,
489 | .token.deleted {
490 | color: #905;
491 | }
492 |
493 | .token.selector,
494 | .token.attr-name,
495 | .token.string,
496 | .token.char,
497 | .token.builtin,
498 | .token.inserted {
499 | color: #690;
500 | }
501 |
502 | .token.operator,
503 | .token.entity,
504 | .token.url,
505 | .language-css .token.string,
506 | .style .token.string {
507 | color: #9a6e3a;
508 | background: hsla(0, 0%, 100%, .5);
509 | }
510 |
511 | .token.atrule,
512 | .token.attr-value,
513 | .token.keyword {
514 | color: #07a;
515 | }
516 |
517 | .token.function,
518 | .token.class-name {
519 | color: #DD4A68;
520 | }
521 |
522 | .token.regex,
523 | .token.important,
524 | .token.variable {
525 | color: #e90;
526 | }
527 |
528 | .token.important,
529 | .token.bold {
530 | font-weight: bold;
531 | }
532 |
533 | .token.italic {
534 | font-style: italic;
535 | }
536 |
537 | .token.entity {
538 | cursor: help;
539 | }
540 |
--------------------------------------------------------------------------------
/src/static/iconfont/demo_index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IconFont Demo
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 | - Unicode
22 | - Font class
23 | - Symbol
24 |
25 |
26 |
查看项目
27 |
28 |
29 |
30 |
31 |
32 |
33 | -
34 |
35 |
箭头_向下
36 | 
37 |
38 |
39 | -
40 |
41 |
箭头_向上
42 | 
43 |
44 |
45 | -
46 |
47 |
double-arro- right
48 | 
49 |
50 |
51 | -
52 |
53 |
3d
54 | 
55 |
56 |
57 | -
58 |
59 |
power
60 | 
61 |
62 |
63 | -
64 |
65 |
柱状图
66 | 
67 |
68 |
69 |
70 |
71 |
Unicode 引用
72 |
73 |
74 |
Unicode 是字体在网页端最原始的应用方式,特点是:
75 |
76 | - 兼容性最好,支持 IE6+,及所有现代浏览器。
77 | - 支持按字体的方式去动态调整图标大小,颜色等等。
78 | - 但是因为是字体,所以不支持多色。只能使用平台里单色的图标,就算项目里有多色图标也会自动去色。
79 |
80 |
81 | 注意:新版 iconfont 支持多色图标,这些多色图标在 Unicode 模式下将不能使用,如果有需求建议使用symbol 的引用方式
82 |
83 |
Unicode 使用步骤如下:
84 |
第一步:拷贝项目下面生成的 @font-face
85 |
@font-face {
87 | font-family: 'iconfont';
88 | src: url('iconfont.eot');
89 | src: url('iconfont.eot?#iefix') format('embedded-opentype'),
90 | url('iconfont.woff2') format('woff2'),
91 | url('iconfont.woff') format('woff'),
92 | url('iconfont.ttf') format('truetype'),
93 | url('iconfont.svg#iconfont') format('svg');
94 | }
95 |
96 |
第二步:定义使用 iconfont 的样式
97 |
.iconfont {
99 | font-family: "iconfont" !important;
100 | font-size: 16px;
101 | font-style: normal;
102 | -webkit-font-smoothing: antialiased;
103 | -moz-osx-font-smoothing: grayscale;
104 | }
105 |
106 |
第三步:挑选相应图标并获取字体编码,应用于页面
107 |
108 | <span class="iconfont">3</span>
110 |
111 |
112 | "iconfont" 是你项目下的 font-family。可以通过编辑项目查看,默认是 "iconfont"。
113 |
114 |
115 |
116 |
117 |
118 |
119 | -
120 |
121 |
122 | 箭头_向下
123 |
124 | .icon-jiantou_xiangxia
125 |
126 |
127 |
128 | -
129 |
130 |
131 | 箭头_向上
132 |
133 | .icon-jiantou_xiangshang
134 |
135 |
136 |
137 | -
138 |
139 |
140 | double-arro- right
141 |
142 | .icon-double-arro-right
143 |
144 |
145 |
146 | -
147 |
148 |
149 | 3d
150 |
151 | .icon-d
152 |
153 |
154 |
155 | -
156 |
157 |
158 | power
159 |
160 | .icon-power
161 |
162 |
163 |
164 | -
165 |
166 |
167 | 柱状图
168 |
169 | .icon-zhuzhuangtu
170 |
171 |
172 |
173 |
174 |
175 |
font-class 引用
176 |
177 |
178 |
font-class 是 Unicode 使用方式的一种变种,主要是解决 Unicode 书写不直观,语意不明确的问题。
179 |
与 Unicode 使用方式相比,具有如下特点:
180 |
181 | - 兼容性良好,支持 IE8+,及所有现代浏览器。
182 | - 相比于 Unicode 语意明确,书写更直观。可以很容易分辨这个 icon 是什么。
183 | - 因为使用 class 来定义图标,所以当要替换图标时,只需要修改 class 里面的 Unicode 引用。
184 | - 不过因为本质上还是使用的字体,所以多色图标还是不支持的。
185 |
186 |
使用步骤如下:
187 |
第一步:引入项目下面生成的 fontclass 代码:
188 |
<link rel="stylesheet" href="./iconfont.css">
189 |
190 |
第二步:挑选相应图标并获取类名,应用于页面:
191 |
<span class="iconfont icon-xxx"></span>
192 |
193 |
194 | "
195 | iconfont" 是你项目下的 font-family。可以通过编辑项目查看,默认是 "iconfont"。
196 |
197 |
198 |
199 |
200 |
201 |
202 | -
203 |
206 |
箭头_向下
207 | #icon-jiantou_xiangxia
208 |
209 |
210 | -
211 |
214 |
箭头_向上
215 | #icon-jiantou_xiangshang
216 |
217 |
218 | -
219 |
222 |
double-arro- right
223 | #icon-double-arro-right
224 |
225 |
226 | -
227 |
230 |
3d
231 | #icon-d
232 |
233 |
234 | -
235 |
238 |
power
239 | #icon-power
240 |
241 |
242 | -
243 |
246 |
柱状图
247 | #icon-zhuzhuangtu
248 |
249 |
250 |
251 |
252 |
Symbol 引用
253 |
254 |
255 |
这是一种全新的使用方式,应该说这才是未来的主流,也是平台目前推荐的用法。相关介绍可以参考这篇文章
256 | 这种用法其实是做了一个 SVG 的集合,与另外两种相比具有如下特点:
257 |
258 | - 支持多色图标了,不再受单色限制。
259 | - 通过一些技巧,支持像字体那样,通过
font-size, color 来调整样式。
260 | - 兼容性较差,支持 IE9+,及现代浏览器。
261 | - 浏览器渲染 SVG 的性能一般,还不如 png。
262 |
263 |
使用步骤如下:
264 |
第一步:引入项目下面生成的 symbol 代码:
265 |
<script src="./iconfont.js"></script>
266 |
267 |
第二步:加入通用 CSS 代码(引入一次就行):
268 |
<style>
269 | .icon {
270 | width: 1em;
271 | height: 1em;
272 | vertical-align: -0.15em;
273 | fill: currentColor;
274 | overflow: hidden;
275 | }
276 | </style>
277 |
278 |
第三步:挑选相应图标并获取类名,应用于页面:
279 |
<svg class="icon" aria-hidden="true">
280 | <use xlink:href="#icon-xxx"></use>
281 | </svg>
282 |
283 |
284 |
285 |
286 |
287 |
288 |
307 |
308 |
309 |
--------------------------------------------------------------------------------