commit b0d3902e8d891f82161f5efad4310b11d8451f79 Author: dengtongyu Date: Tue Aug 24 19:33:17 2021 +0800 feat:初始化项目 diff --git a/.browserslistrc b/.browserslistrc new file mode 100644 index 0000000..214388f --- /dev/null +++ b/.browserslistrc @@ -0,0 +1,3 @@ +> 1% +last 2 versions +not dead diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..5592b18 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,14 @@ +module.exports = { + root: true, + env: { + node: true + }, + extends: ["plugin:vue/essential", "eslint:recommended", "@vue/prettier"], + parserOptions: { + parser: "babel-eslint" + }, + rules: { + "no-console": process.env.NODE_ENV === "production" ? "warn" : "off", + "no-debugger": process.env.NODE_ENV === "production" ? "warn" : "off" + } +}; diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6238331 --- /dev/null +++ b/.gitignore @@ -0,0 +1,22 @@ +.DS_Store +node_modules +/dist +package-lock.json + +# local env files +.env.local +.env.*.local + +# Log files +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Editor directories and files +.idea +.vscode +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/README.md b/README.md new file mode 100644 index 0000000..dd6cc6a --- /dev/null +++ b/README.md @@ -0,0 +1,24 @@ +# template-h5 + +## Project setup +``` +npm install +``` + +### Compiles and hot-reloads for development +``` +npm run serve +``` + +### Compiles and minifies for production +``` +npm run build +``` + +### Lints and fixes files +``` +npm run lint +``` + +### Customize configuration +See [Configuration Reference](https://cli.vuejs.org/config/). diff --git a/babel.config.js b/babel.config.js new file mode 100644 index 0000000..397abca --- /dev/null +++ b/babel.config.js @@ -0,0 +1,3 @@ +module.exports = { + presets: ["@vue/cli-plugin-babel/preset"] +}; diff --git a/package.json b/package.json new file mode 100644 index 0000000..7b92a35 --- /dev/null +++ b/package.json @@ -0,0 +1,38 @@ +{ + "name": "luckyrun", + "version": "0.1.0", + "private": true, + "scripts": { + "serve:test": "cross-env VUE_APP_PROXY=1 vue-cli-service serve", + "serve:prod": "cross-env VUE_APP_PROXY=2 vue-cli-service serve", + "build": "vue-cli-service build", + "lint": "vue-cli-service lint --fix" + }, + "dependencies": { + "axios": "^0.19.2", + "core-js": "^3.6.4", + "vue": "^2.6.11", + "vue-router": "^3.1.6", + "vuex": "^3.1.3" + }, + "devDependencies": { + "@vue/cli-plugin-babel": "~4.3.0", + "@vue/cli-plugin-eslint": "~4.3.0", + "@vue/cli-plugin-router": "~4.3.0", + "@vue/cli-plugin-vuex": "~4.3.0", + "@vue/cli-service": "~4.3.0", + "@vue/eslint-config-prettier": "^6.0.0", + "babel-eslint": "^10.1.0", + "cross-env": "^7.0.2", + "eslint": "^6.7.2", + "eslint-plugin-prettier": "^3.1.1", + "eslint-plugin-vue": "^6.2.2", + "postcss-design-convert": "^1.1.3", + "postcss-px-to-viewport": "^1.1.1", + "postcss-write-svg": "^3.0.1", + "prettier": "^1.19.1", + "sass": "^1.26.3", + "sass-loader": "^8.0.2", + "vue-template-compiler": "^2.6.11" + } +} diff --git a/postcss.config.js b/postcss.config.js new file mode 100644 index 0000000..59b442a --- /dev/null +++ b/postcss.config.js @@ -0,0 +1,21 @@ +module.exports = { + plugins: { + "postcss-px-to-viewport": { + viewportWidth: 750, // 视窗的宽度,对应的是我们设计稿的宽度,一般是750 + viewportHeight: 1334, // 视窗的高度,根据750设备的宽度来指定,一般指定1334,也可以不配置 + unitPrecision: 3, // 指定`px`转换为视窗单位值的小数位数(很多时候无法整除) + viewportUnit: "vw", // 指定需要转换成的视窗单位,建议使用vw + selectorBlackList: [".ignore", ".hairlines", "dgd", "dgdui"], // 指定不转换为视窗单位的类,可以自定义,可以无限添加,建议定义一至两个通用的类名 + minPixelValue: 1, // 小于或等于`1px`不转换为视窗单位,你也可以设置为你想要的值 + mediaQuery: false // 允许在媒体查询中转换`px` + }, + "postcss-design-convert": { + multiple: 2, + units: ["vw"], + selector: /^\.yzy-/ + }, + "postcss-write-svg": { + utf8: false + } + } +}; diff --git a/proxy.config.js b/proxy.config.js new file mode 100644 index 0000000..68dfb22 --- /dev/null +++ b/proxy.config.js @@ -0,0 +1,42 @@ +// 代理环境,1测试环境,2生产环境 +const VUE_APP_PROXY = process.env.VUE_APP_PROXY + ? parseInt(process.env.VUE_APP_PROXY) + : 1; + +let target = ""; + +switch (VUE_APP_PROXY) { + case 1: + target = "http://test.haloapp.vip"; + break; + case 2: + target = "http://haloapp.vip"; + break; + default: + target = "http://test.haloapp.vip"; +} + +let proxyTable = { + "/zuul": { + target: target, + changeOrigin: true, + secure: false + }, + "/sjht": { + target: target, + changeOrigin: true, + secure: false + }, + "/media/": { + target: target, + changeOrigin: true, + secure: false + }, + "/bzdb": { + target: target, + changeOrigin: true, + secure: false + } +}; + +module.exports = proxyTable; diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000..df36fcf Binary files /dev/null and b/public/favicon.ico differ diff --git a/public/index.html b/public/index.html new file mode 100644 index 0000000..91c6ed6 --- /dev/null +++ b/public/index.html @@ -0,0 +1,17 @@ + + + + + + + + <%= htmlWebpackPlugin.options.title %> + + + +
+ + + diff --git a/src/App.vue b/src/App.vue new file mode 100644 index 0000000..cc7283a --- /dev/null +++ b/src/App.vue @@ -0,0 +1,26 @@ + + + diff --git a/src/api/index.js b/src/api/index.js new file mode 100644 index 0000000..200f667 --- /dev/null +++ b/src/api/index.js @@ -0,0 +1,12 @@ +import ajax from "@/lib/ajax"; +import config from "@/config"; + +// host +const HOST = config.host("/zuul", "/mrxf"); + +// 来访总量统计列表 +const petitionReportTotal = param => { + return ajax.post(`${HOST}/petitionReport/total`, param); +}; + +export { petitionReportTotal }; diff --git a/src/assets/logo.png b/src/assets/logo.png new file mode 100644 index 0000000..f3d2503 Binary files /dev/null and b/src/assets/logo.png differ diff --git a/src/components/HelloWorld.vue b/src/components/HelloWorld.vue new file mode 100644 index 0000000..74d0c05 --- /dev/null +++ b/src/components/HelloWorld.vue @@ -0,0 +1,130 @@ + + + + + + diff --git a/src/config/index.js b/src/config/index.js new file mode 100644 index 0000000..4416f50 --- /dev/null +++ b/src/config/index.js @@ -0,0 +1,24 @@ +// 应用的名称 +const appName = "每日信访动态报送"; + +// 是否启用YApi +const YApi = false; + +// 代理环境,1测试环境,2生产环境 +const VUE_APP_PROXY = process.env.VUE_APP_PROXY + ? parseInt(process.env.VUE_APP_PROXY) + : 1; + +const host = (PASSID, GATEWAY) => { + // host + const HOST = YApi ? `/mock/73/${GATEWAY}` : `${PASSID}${GATEWAY}`; + + return HOST; +}; + +module.exports = { + appName, + YApi, + VUE_APP_PROXY, + host +}; diff --git a/src/lib/ajax.js b/src/lib/ajax.js new file mode 100755 index 0000000..06e0130 --- /dev/null +++ b/src/lib/ajax.js @@ -0,0 +1,55 @@ +import axios from "axios"; + +// 添加公共请求头 +const getHeader = function(options) { + if (options === "form") { + return Object.assign({ + "content-type": "application/x-www-form-urlencoded" + }); + } else if (options === "file") { + return Object.assign({ "content-type": "multipart/form-data" }); + } +}; + +const request = function(method, url, params, options) { + return new Promise(function(resolve, reject) { + axios + .request({ + headers: getHeader(options), + url: url, + method: method, + withCredentials: true, + data: method === "post" ? params : {}, + params: method === "get" ? params : {}, + timeout: 120000, + responseType: "json" + }) + .then(function(response) { + let data = response.data || JSON.parse(response.request.responseText); + resolve(data); + }) + .catch(function(error) { + if (typeof error.response === "undefined") { + if ( + location.hostname == "127.0.0.1" || + location.hostname == "localhost" + ) { + reject(error); + } else { + location.reload(); + } + } else { + reject(error); + } + }); + }); +}; + +export default { + get: function(url, params, options) { + return request("get", url, params, options); + }, + post: function(url, params, options) { + return request("post", url, params, options); + } +}; diff --git a/src/lib/excel.js b/src/lib/excel.js new file mode 100755 index 0000000..0a22803 --- /dev/null +++ b/src/lib/excel.js @@ -0,0 +1,118 @@ +/* eslint-disable */ +import XLSX from 'xlsx'; + +function auto_width(ws, data){ + /*set worksheet max width per col*/ + const colWidth = data.map(row => row.map(val => { + /*if null/undefined*/ + if (val == null) { + return {'wch': 10}; + } + /*if chinese*/ + else if (val.toString().charCodeAt(0) > 255) { + return {'wch': val.toString().length * 2}; + } else { + return {'wch': val.toString().length}; + } + })) + /*start in the first row*/ + let result = colWidth[0]; + for (let i = 1; i < colWidth.length; i++) { + for (let j = 0; j < colWidth[i].length; j++) { + if (result[j]['wch'] < colWidth[i][j]['wch']) { + result[j]['wch'] = colWidth[i][j]['wch']; + } + } + } + ws['!cols'] = result; +} + +function json_to_array(key, jsonData){ + return jsonData.map(v => key.map(j => { return v[j] })); +} + +// fix data,return string +function fixdata(data) { + let o = '' + let l = 0 + const w = 10240 + for (; l < data.byteLength / w; ++l) o += String.fromCharCode.apply(null, new Uint8Array(data.slice(l * w, l * w + w))) + o += String.fromCharCode.apply(null, new Uint8Array(data.slice(l * w))) + return o +} + +// get head from excel file,return array +function get_header_row(sheet) { + const headers = [] + const range = XLSX.utils.decode_range(sheet['!ref']) + let C + const R = range.s.r /* start in the first row */ + for (C = range.s.c; C <= range.e.c; ++C) { /* walk every column in the range */ + var cell = sheet[XLSX.utils.encode_cell({ c: C, r: R })] /* find the cell in the first row */ + var hdr = 'UNKNOWN ' + C // <-- replace with your desired default + if (cell && cell.t) hdr = XLSX.utils.format_cell(cell) + headers.push(hdr) + } + return headers +} + +// export const export_table_to_excel= (id, filename) => { +// const table = document.getElementById(id); +// const wb = XLSX.utils.table_to_book(table); +// XLSX.writeFile(wb, filename); + +// /* the second way */ +// // const table = document.getElementById(id); +// // const wb = XLSX.utils.book_new(); +// // const ws = XLSX.utils.table_to_sheet(table); +// // XLSX.utils.book_append_sheet(wb, ws, filename); +// // XLSX.writeFile(wb, filename); +// } +export const export_table_to_excel= (table, filename) => { + if(!table) return; + const wb = XLSX.utils.table_to_book(table); + XLSX.writeFile(wb, filename) +} + +export const export_json_to_excel = ({data, key, title, filename, autoWidth}) => { + const wb = XLSX.utils.book_new(); + data.unshift(title); + const ws = XLSX.utils.json_to_sheet(data, {header: key, skipHeader: true}); + if(autoWidth){ + const arr = json_to_array(key, data); + auto_width(ws, arr); + } + XLSX.utils.book_append_sheet(wb, ws, filename); + XLSX.writeFile(wb, filename + '.xlsx'); +} + +export const export_array_to_excel = ({key, data, title, filename, autoWidth}) => { + const wb = XLSX.utils.book_new(); + const arr = json_to_array(key, data); + arr.unshift(title); + const ws = XLSX.utils.aoa_to_sheet(arr); + if(autoWidth){ + auto_width(ws, arr); + } + XLSX.utils.book_append_sheet(wb, ws, filename); + XLSX.writeFile(wb, filename + '.xlsx'); +} + +export const read = (data, type) => { + /* if type == 'base64' must fix data first */ + // const fixedData = fixdata(data) + // const workbook = XLSX.read(btoa(fixedData), { type: 'base64' }) + const workbook = XLSX.read(data, { type: type }); + const firstSheetName = workbook.SheetNames[0]; + const worksheet = workbook.Sheets[firstSheetName]; + const header = get_header_row(worksheet); + const results = XLSX.utils.sheet_to_json(worksheet); + return {header, results}; +} + +export default { + export_table_to_excel, + export_array_to_excel, + export_json_to_excel, + read +} diff --git a/src/lib/tool.js b/src/lib/tool.js new file mode 100644 index 0000000..151effd --- /dev/null +++ b/src/lib/tool.js @@ -0,0 +1,121 @@ +import { CookieStorage } from "cookie-storage"; +import config from "@/config"; + +const cookieStorage = new CookieStorage(); + +const systemCode = config.systemCode; + +// 随机长度字符串 +const randomString = len => { + len = len || 10; + var chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; + var maxPos = chars.length; + var str = ""; + for (let i = 0; i < len; i++) { + str += chars.charAt(Math.floor(Math.random() * maxPos)); + } + return str; +}; + +// 设置localStorage +const _setItem = (key, data) => { + localStorage.setItem(key, JSON.stringify(data)); +}; + +// 获取localStorage +const _getItem = key => { + let data = localStorage.getItem(key); + if (data) data = JSON.parse(data); + return data; +}; + +// 删除localStorage +const _removeItem = key => { + localStorage.removeItem(key); +}; + +// 缓存用户信息 +const setUserInfoCache = info => { + let data = { + account: info.account, + avatar: info.avatar, + userId: info.userId, + userName: info.userName + }; + _setItem("__UserInfo__", data); +}; + +// 获取缓存的用户信息 +const getUserInfoCache = () => { + let data = _getItem("__UserInfo__"); + return data; +}; + +// 删除用户信息 +const removeUserInfoCache = () => { + _removeItem("__UserInfo__"); +}; + +// 缓存token +const setToken = value => { + let curDate = new Date(); + let nextDate = new Date(curDate.getTime() + 24 * 60 * 60 * 1000); + + cookieStorage.setItem("Authorization", value, { + domain: document.domain, + expires: nextDate + }); +}; + +// 获取token +const getToken = () => { + return cookieStorage.getItem("Authorization"); +}; + +// 删除token +const removeToken = () => { + cookieStorage.removeItem("Authorization"); +}; + +// 缓存用户权限 +const setUserPowerCache = arr => { + let map = {}; + for (let i = 0; i < arr.length; i++) { + let k = arr[i].powerCode; + map[k] = arr[i]; + } + _setItem(`__UserPower_${systemCode}__`, map); +}; + +// 获取缓存的用户权限 +const getUserPowerCache = () => { + let data = _getItem(`__UserPower_${systemCode}__`); + return data; +}; + +// 获取指定的用户权限 +const getUserSomeonePowerCache = code => { + let data = getUserPowerCache(); + let item = null; + if (data) item = data[code]; + return item; +}; + +// 删除用户权限 +const removeUserPowerCache = () => { + _removeItem(`__UserPower_${systemCode}__`); +}; + +export { + randomString, + setUserInfoCache, + getUserInfoCache, + removeUserInfoCache, + setToken, + getToken, + removeToken, + setUserPowerCache, + getUserPowerCache, + removeUserPowerCache, + getUserSomeonePowerCache +}; diff --git a/src/main.js b/src/main.js new file mode 100644 index 0000000..3a47006 --- /dev/null +++ b/src/main.js @@ -0,0 +1,12 @@ +import Vue from "vue"; +import App from "./App.vue"; +import router from "./router"; +import store from "./store"; + +Vue.config.productionTip = false; + +new Vue({ + router, + store, + render: h => h(App) +}).$mount("#app"); diff --git a/src/router/index.js b/src/router/index.js new file mode 100644 index 0000000..daa6cee --- /dev/null +++ b/src/router/index.js @@ -0,0 +1,28 @@ +import Vue from "vue"; +import VueRouter from "vue-router"; +import Home from "../views/Home.vue"; + +Vue.use(VueRouter); + +const routes = [ + { + path: "/", + name: "Home", + component: Home + }, + { + path: "/about", + name: "About", + // route level code-splitting + // this generates a separate chunk (about.[hash].js) for this route + // which is lazy-loaded when the route is visited. + component: () => + import(/* webpackChunkName: "about" */ "../views/About.vue") + } +]; + +const router = new VueRouter({ + routes +}); + +export default router; diff --git a/src/store/index.js b/src/store/index.js new file mode 100644 index 0000000..fb6015f --- /dev/null +++ b/src/store/index.js @@ -0,0 +1,11 @@ +import Vue from "vue"; +import Vuex from "vuex"; + +Vue.use(Vuex); + +export default new Vuex.Store({ + state: {}, + mutations: {}, + actions: {}, + modules: {} +}); diff --git a/src/styles/global.scss b/src/styles/global.scss new file mode 100644 index 0000000..f8b3326 --- /dev/null +++ b/src/styles/global.scss @@ -0,0 +1,29 @@ +html,body,#app { + width: 100%; + height: 100%; + margin: 0; +} +h1,h2,h3,h4,h5,p,dl,dt,dd,ol,ul,li { + padding: 0; + margin: 0 +} +#app { + font-family: "Helvetica","Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", SimSun, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + color: #2c3e50; + font-size: 14px; +} + +@svg 1px-border { + height: 2px; + @rect { + fill: var(--color, black); + width: 100%; + height: 50%; + } +} +.border-1px { + border: 1px solid transparent; + border-image: svg(1px-border param(--color #00b1ff)) 2 2 stretch; +} diff --git a/src/styles/index.scss b/src/styles/index.scss new file mode 100644 index 0000000..8063ce3 --- /dev/null +++ b/src/styles/index.scss @@ -0,0 +1,2 @@ + +@import "./global.scss"; \ No newline at end of file diff --git a/src/views/About.vue b/src/views/About.vue new file mode 100644 index 0000000..3fa2807 --- /dev/null +++ b/src/views/About.vue @@ -0,0 +1,5 @@ + diff --git a/src/views/Home.vue b/src/views/Home.vue new file mode 100644 index 0000000..191049e --- /dev/null +++ b/src/views/Home.vue @@ -0,0 +1,18 @@ + + + diff --git a/vue.config.js b/vue.config.js new file mode 100644 index 0000000..2e3e024 --- /dev/null +++ b/vue.config.js @@ -0,0 +1,32 @@ +const config = require("./src/config"); +const proxy = require("./proxy.config"); +module.exports = { + publicPath: "./", + outputDir: "dist", + assetsDir: "static", + indexPath: "index.html", + pages: { + index: { + // page 的入口 + entry: "src/main.js", + // 模板来源 + template: "public/index.html", + // 在 dist/index.html 的输出 + filename: "index.html", + // 当使用 title 选项时, + // template 中的 title 标签需要是 <%= htmlWebpackPlugin.options.title %> + title: config.appName, + // 在这个页面中包含的块,默认情况下会包含 + // 提取出来的通用 chunk 和 vendor chunk。 + chunks: ["chunk-vendors", "chunk-common", "index"] + } + }, + devServer: { + proxy: proxy + }, + css: { + loaderOptions: { + postcss: {} + } + } +};