feat: 初始化
39
.editorconfig
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
[*]
|
||||||
|
charset=utf-8
|
||||||
|
end_of_line=crlf
|
||||||
|
insert_final_newline=false
|
||||||
|
indent_style=space
|
||||||
|
indent_size=2
|
||||||
|
|
||||||
|
[{*.ng,*.sht,*.html,*.shtm,*.shtml,*.htm}]
|
||||||
|
indent_style=space
|
||||||
|
indent_size=2
|
||||||
|
|
||||||
|
[{*.jhm,*.xslt,*.xul,*.rng,*.xsl,*.xsd,*.ant,*.tld,*.fxml,*.jrxml,*.xml,*.jnlp,*.wsdl}]
|
||||||
|
indent_style=space
|
||||||
|
indent_size=2
|
||||||
|
|
||||||
|
[{.babelrc,.stylelintrc,jest.config,.eslintrc,.prettierrc,*.json,*.jsb3,*.jsb2,*.bowerrc}]
|
||||||
|
indent_style=space
|
||||||
|
indent_size=2
|
||||||
|
|
||||||
|
[*.svg]
|
||||||
|
indent_style=space
|
||||||
|
indent_size=2
|
||||||
|
|
||||||
|
[*.js.map]
|
||||||
|
indent_style=space
|
||||||
|
indent_size=2
|
||||||
|
|
||||||
|
[*.less]
|
||||||
|
indent_style=space
|
||||||
|
indent_size=2
|
||||||
|
|
||||||
|
[*.vue]
|
||||||
|
indent_style=space
|
||||||
|
indent_size=2
|
||||||
|
|
||||||
|
[{.analysis_options,*.yml,*.yaml}]
|
||||||
|
indent_style=space
|
||||||
|
indent_size=2
|
||||||
|
|
||||||
7
.env.development
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
# 本地环境
|
||||||
|
ENV = 'development'
|
||||||
|
|
||||||
|
# 接口地址
|
||||||
|
VUE_API_BASE_URL = http://127.0.0.1:9999/jshERP-boot
|
||||||
|
# 本地端口
|
||||||
|
VUE_PORT = 82
|
||||||
7
.env.production
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
# 生产环境
|
||||||
|
ENV = 'production'
|
||||||
|
|
||||||
|
# 接口地址
|
||||||
|
VUE_API_BASE_URL = https://www.byhah.com/jshERP-boot
|
||||||
|
# 本地端口
|
||||||
|
VUE_PORT = 82
|
||||||
1
.eslintignore
Normal file
@ -0,0 +1 @@
|
|||||||
|
/src
|
||||||
1
.gitattributes
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
public/* linguist-vendored
|
||||||
22
.gitignore
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
.DS_Store
|
||||||
|
node_modules
|
||||||
|
/dist
|
||||||
|
|
||||||
|
# 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*
|
||||||
|
/package-lock.json
|
||||||
5
.prettierrc
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"printWidth": 120,
|
||||||
|
"semi": false,
|
||||||
|
"singleQuote": true
|
||||||
|
}
|
||||||
104
README.md
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
jshERP-web Vue
|
||||||
|
====
|
||||||
|
|
||||||
|
|
||||||
|
Overview
|
||||||
|
----
|
||||||
|
|
||||||
|
|
||||||
|
#### 前端技术
|
||||||
|
|
||||||
|
- 基础框架:[ant-design-vue](https://github.com/vueComponent/ant-design-vue) - Ant Design Of Vue 实现
|
||||||
|
- JavaScript框架:Vue
|
||||||
|
- Jeecg-boot 的前段UI框架
|
||||||
|
- Webpack
|
||||||
|
- node
|
||||||
|
- yarn
|
||||||
|
- eslint
|
||||||
|
- @vue/cli 3.2.1
|
||||||
|
- [vue-cropper](https://github.com/xyxiao001/vue-cropper) - 头像裁剪组件
|
||||||
|
- [@antv/g2](https://antv.alipay.com/zh-cn/index.html) - Alipay AntV 数据可视化图表
|
||||||
|
- [Viser-vue](https://viserjs.github.io/docs.html#/viser/guide/installation) - antv/g2 封装实现
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
项目运行
|
||||||
|
----
|
||||||
|
|
||||||
|
- 安装nodeJS
|
||||||
|
```
|
||||||
|
建议安装node-v20.17.0-x64版本 教程参考 https://blog.csdn.net/Coin_Collecter/article/details/136484312
|
||||||
|
```
|
||||||
|
|
||||||
|
- 安装yarn
|
||||||
|
```
|
||||||
|
npm install -g yarn
|
||||||
|
```
|
||||||
|
|
||||||
|
- 配镜像源(速度快)
|
||||||
|
```
|
||||||
|
yarn config set registry https://registry.npmmirror.com
|
||||||
|
```
|
||||||
|
|
||||||
|
- 安装依赖
|
||||||
|
```
|
||||||
|
yarn install
|
||||||
|
```
|
||||||
|
|
||||||
|
- 开发模式运行
|
||||||
|
```
|
||||||
|
yarn serve
|
||||||
|
```
|
||||||
|
|
||||||
|
- 编译发布项目
|
||||||
|
```
|
||||||
|
yarn build
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
其他说明
|
||||||
|
----
|
||||||
|
|
||||||
|
- 项目使用的 [vue-cli3](https://cli.vuejs.org/guide/), 请更新您的 cli
|
||||||
|
|
||||||
|
- 关闭 Eslint (不推荐) 移除 `package.json` 中 `eslintConfig` 整个节点代码
|
||||||
|
|
||||||
|
- 修改 Ant Design 配色,在文件 `vue.config.js` 中,其他 less 变量覆盖参考 [ant design](https://ant.design/docs/react/customize-theme-cn) 官方说明
|
||||||
|
```ecmascript 6
|
||||||
|
css: {
|
||||||
|
loaderOptions: {
|
||||||
|
less: {
|
||||||
|
modifyVars: {
|
||||||
|
/* less 变量覆盖,用于自定义 ant design 主题 */
|
||||||
|
|
||||||
|
'primary-color': '#F5222D',
|
||||||
|
'link-color': '#F5222D',
|
||||||
|
'border-radius-base': '4px',
|
||||||
|
},
|
||||||
|
javascriptEnabled: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
附属文档
|
||||||
|
----
|
||||||
|
- [Ant Design Vue](https://vuecomponent.github.io/ant-design-vue/docs/vue/introduce-cn)
|
||||||
|
|
||||||
|
- [报表 viser-vue](https://viserjs.github.io/demo.html#/viser/bar/basic-bar)
|
||||||
|
|
||||||
|
- [Vue](https://cn.vuejs.org/v2/guide)
|
||||||
|
|
||||||
|
- [路由/菜单说明](https://github.com/zhangdaiscott/jeecg-boot/tree/master/ant-design-jeecg-vue/src/router/README.md)
|
||||||
|
|
||||||
|
- [ANTD 默认配置项](https://github.com/zhangdaiscott/jeecg-boot/tree/master/ant-design-jeecg-vue/src/defaultSettings.js)
|
||||||
|
|
||||||
|
- 其他待补充...
|
||||||
|
|
||||||
|
|
||||||
|
备注
|
||||||
|
----
|
||||||
|
|
||||||
|
> @vue/cli 升级后,eslint 规则更新了。由于影响到全部 .vue 文件,需要逐个验证。既暂时关闭部分原本不验证的规则,后期维护时,在逐步修正这些 rules
|
||||||
6
babel.config.js
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
module.exports = {
|
||||||
|
presets: [
|
||||||
|
['@vue/app',
|
||||||
|
{ useBuiltIns: 'entry' }]
|
||||||
|
]
|
||||||
|
}
|
||||||
24
idea.config.js
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
'use strict'
|
||||||
|
const path = require('path')
|
||||||
|
|
||||||
|
function resolve (dir) {
|
||||||
|
return path.join(__dirname, '.', dir)
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
context: path.resolve(__dirname, './'),
|
||||||
|
resolve: {
|
||||||
|
extensions: ['.js', '.vue', '.json'],
|
||||||
|
alias: {
|
||||||
|
'config': resolve('config'),
|
||||||
|
'@': resolve('src'),
|
||||||
|
'@views': resolve('src/views'),
|
||||||
|
'@comp': resolve('src/components'),
|
||||||
|
'@core': resolve('src/core'),
|
||||||
|
'@utils': resolve('src/utils'),
|
||||||
|
'@entry': resolve('src/entry'),
|
||||||
|
'@router': resolve('src/router'),
|
||||||
|
'@store': resolve('src/store')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
110
package.json
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
{
|
||||||
|
"name": "jsh-erp-web",
|
||||||
|
"version": "3.5.0",
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"serve": "vue-cli-service serve",
|
||||||
|
"build": "vue-cli-service build"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@antv/data-set": "^0.11.2",
|
||||||
|
"@tinymce/tinymce-vue": "^2.0.0",
|
||||||
|
"ant-design-vue": "1.5.2",
|
||||||
|
"area-data": "^5.0.6",
|
||||||
|
"axios": "^0.18.0",
|
||||||
|
"clipboard": "^2.0.4",
|
||||||
|
"codemirror": "^5.46.0",
|
||||||
|
"dayjs": "^1.8.0",
|
||||||
|
"enquire.js": "^2.1.6",
|
||||||
|
"intro.js": "^4.2.2",
|
||||||
|
"jquery": "^1.12.4",
|
||||||
|
"js-cookie": "^2.2.0",
|
||||||
|
"lodash.get": "^4.4.2",
|
||||||
|
"lodash.pick": "^4.4.0",
|
||||||
|
"md5": "^2.2.1",
|
||||||
|
"nprogress": "^0.2.0",
|
||||||
|
"viser-vue": "^2.4.4",
|
||||||
|
"vue": "^2.7.16",
|
||||||
|
"vue-area-linkage": "^5.1.0",
|
||||||
|
"vue-cropper": "^0.4.8",
|
||||||
|
"vue-draggable-resizable": "^2.3.0",
|
||||||
|
"vue-i18n": "^8.7.0",
|
||||||
|
"vue-loader": "^15.7.0",
|
||||||
|
"vue-ls": "^3.2.0",
|
||||||
|
"vue-photo-preview": "^1.1.3",
|
||||||
|
"vue-print-nb-jeecg": "^1.0.9",
|
||||||
|
"vue-router": "^3.0.1",
|
||||||
|
"vue-splitpane": "^1.0.4",
|
||||||
|
"vuedraggable": "^2.20.0",
|
||||||
|
"vuex": "^3.1.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@babel/polyfill": "^7.2.5",
|
||||||
|
"@vue/cli-plugin-babel": "^3.3.0",
|
||||||
|
"@vue/cli-plugin-eslint": "^3.3.0",
|
||||||
|
"@vue/cli-service": "^3.3.0",
|
||||||
|
"@vue/eslint-config-standard": "^4.0.0",
|
||||||
|
"babel-eslint": "^10.0.1",
|
||||||
|
"compression-webpack-plugin": "^3.1.0",
|
||||||
|
"eslint": "^5.16.0",
|
||||||
|
"eslint-plugin-vue": "^5.1.0",
|
||||||
|
"html-webpack-plugin": "^4.2.0",
|
||||||
|
"less": "^3.9.0",
|
||||||
|
"less-loader": "^4.1.0",
|
||||||
|
"mini-css-extract-plugin": "^2.9.4",
|
||||||
|
"vue-template-compiler": "^2.6.10"
|
||||||
|
},
|
||||||
|
"eslintConfig": {
|
||||||
|
"root": true,
|
||||||
|
"env": {
|
||||||
|
"node": true
|
||||||
|
},
|
||||||
|
"extends": [
|
||||||
|
"plugin:vue/strongly-recommended",
|
||||||
|
"@vue/standard"
|
||||||
|
],
|
||||||
|
"parserOptions": {
|
||||||
|
"parser": "babel-eslint"
|
||||||
|
},
|
||||||
|
"rules": {
|
||||||
|
"generator-star-spacing": "off",
|
||||||
|
"no-mixed-operators": 0,
|
||||||
|
"vue/max-attributes-per-line": [
|
||||||
|
2,
|
||||||
|
{
|
||||||
|
"singleline": 5,
|
||||||
|
"multiline": {
|
||||||
|
"max": 1,
|
||||||
|
"allowFirstLine": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"vue/attribute-hyphenation": 0,
|
||||||
|
"vue/html-self-closing": 0,
|
||||||
|
"vue/component-name-in-template-casing": 0,
|
||||||
|
"vue/html-closing-bracket-spacing": 0,
|
||||||
|
"vue/singleline-html-element-content-newline": 0,
|
||||||
|
"vue/no-unused-components": 0,
|
||||||
|
"vue/multiline-html-element-content-newline": 0,
|
||||||
|
"vue/no-use-v-if-with-v-for": 0,
|
||||||
|
"vue/html-closing-bracket-newline": 0,
|
||||||
|
"vue/no-parsing-error": 0,
|
||||||
|
"no-console": 0,
|
||||||
|
"no-tabs": 0,
|
||||||
|
"indent": [
|
||||||
|
1,
|
||||||
|
4
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"postcss": {
|
||||||
|
"plugins": {
|
||||||
|
"autoprefixer": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"browserslist": [
|
||||||
|
"> 1%",
|
||||||
|
"last 2 versions",
|
||||||
|
"not ie <= 10"
|
||||||
|
]
|
||||||
|
}
|
||||||
BIN
public/doc/apply_item_template.xls
Normal file
BIN
public/doc/buy_sale_item_template.xls
Normal file
BIN
public/doc/customer_template.xls
Normal file
BIN
public/doc/goods_template.xls
Normal file
BIN
public/doc/in_out_item_template.xls
Normal file
BIN
public/doc/member_template.xls
Normal file
BIN
public/doc/order_item_template.xls
Normal file
BIN
public/doc/vendor_template.xls
Normal file
319
public/index.html
vendored
Normal file
@ -0,0 +1,319 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-cmn-Hans">
|
||||||
|
<head>
|
||||||
|
<title></title>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||||
|
<meta name="description" content="基于SpringBoot框架,立志为中小企业提供开源好用的ERP软件,目前专注进销存+财务功能。主要模块有零售管理、采购管理、销售管理、仓库管理、财务管理、报表查询、基础数据、系统管理等。" />
|
||||||
|
<meta name="keywords" content="erp,erp系统,进销存,进销存系统" />
|
||||||
|
<link rel="icon" href="<%= BASE_URL %>static/favicon.ico">
|
||||||
|
<style>
|
||||||
|
html,
|
||||||
|
body,
|
||||||
|
#app {
|
||||||
|
height: 100%;
|
||||||
|
margin: 0px;
|
||||||
|
padding: 0px;
|
||||||
|
}
|
||||||
|
.chromeframe {
|
||||||
|
margin: 0.2em 0;
|
||||||
|
background: #ccc;
|
||||||
|
color: #999;
|
||||||
|
padding: 0.2em 0;
|
||||||
|
}
|
||||||
|
#loader-wrapper {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
z-index: 999999;
|
||||||
|
}
|
||||||
|
#loader {
|
||||||
|
display: block;
|
||||||
|
position: relative;
|
||||||
|
left: 50%;
|
||||||
|
top: 50%;
|
||||||
|
width: 120px;
|
||||||
|
height: 120px;
|
||||||
|
margin: -75px 0 0 -75px;
|
||||||
|
border-radius: 50%;
|
||||||
|
border: 3px solid transparent;
|
||||||
|
/* COLOR 1 */
|
||||||
|
border-top-color: #999;
|
||||||
|
-webkit-animation: spin 2s linear infinite;
|
||||||
|
/* Chrome, Opera 15+, Safari 5+ */
|
||||||
|
-ms-animation: spin 2s linear infinite;
|
||||||
|
/* Chrome, Opera 15+, Safari 5+ */
|
||||||
|
-moz-animation: spin 2s linear infinite;
|
||||||
|
/* Chrome, Opera 15+, Safari 5+ */
|
||||||
|
-o-animation: spin 2s linear infinite;
|
||||||
|
/* Chrome, Opera 15+, Safari 5+ */
|
||||||
|
animation: spin 2s linear infinite;
|
||||||
|
/* Chrome, Firefox 16+, IE 10+, Opera */
|
||||||
|
z-index: 1001;
|
||||||
|
}
|
||||||
|
#loader:before {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
top: 5px;
|
||||||
|
left: 5px;
|
||||||
|
right: 5px;
|
||||||
|
bottom: 5px;
|
||||||
|
border-radius: 50%;
|
||||||
|
border: 3px solid transparent;
|
||||||
|
/* COLOR 2 */
|
||||||
|
border-top-color: #999;
|
||||||
|
-webkit-animation: spin 3s linear infinite;
|
||||||
|
/* Chrome, Opera 15+, Safari 5+ */
|
||||||
|
-moz-animation: spin 3s linear infinite;
|
||||||
|
/* Chrome, Opera 15+, Safari 5+ */
|
||||||
|
-o-animation: spin 3s linear infinite;
|
||||||
|
/* Chrome, Opera 15+, Safari 5+ */
|
||||||
|
-ms-animation: spin 3s linear infinite;
|
||||||
|
/* Chrome, Opera 15+, Safari 5+ */
|
||||||
|
animation: spin 3s linear infinite;
|
||||||
|
/* Chrome, Firefox 16+, IE 10+, Opera */
|
||||||
|
}
|
||||||
|
#loader:after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
top: 15px;
|
||||||
|
left: 15px;
|
||||||
|
right: 15px;
|
||||||
|
bottom: 15px;
|
||||||
|
border-radius: 50%;
|
||||||
|
border: 3px solid transparent;
|
||||||
|
border-top-color: #999;
|
||||||
|
/* COLOR 3 */
|
||||||
|
-moz-animation: spin 1.5s linear infinite;
|
||||||
|
/* Chrome, Opera 15+, Safari 5+ */
|
||||||
|
-o-animation: spin 1.5s linear infinite;
|
||||||
|
/* Chrome, Opera 15+, Safari 5+ */
|
||||||
|
-ms-animation: spin 1.5s linear infinite;
|
||||||
|
/* Chrome, Opera 15+, Safari 5+ */
|
||||||
|
-webkit-animation: spin 1.5s linear infinite;
|
||||||
|
/* Chrome, Opera 15+, Safari 5+ */
|
||||||
|
animation: spin 1.5s linear infinite;
|
||||||
|
/* Chrome, Firefox 16+, IE 10+, Opera */
|
||||||
|
}
|
||||||
|
@-webkit-keyframes spin {
|
||||||
|
0% {
|
||||||
|
-webkit-transform: rotate(0deg);
|
||||||
|
/* Chrome, Opera 15+, Safari 3.1+ */
|
||||||
|
-ms-transform: rotate(0deg);
|
||||||
|
/* IE 9 */
|
||||||
|
transform: rotate(0deg);
|
||||||
|
/* Firefox 16+, IE 10+, Opera */
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
-webkit-transform: rotate(360deg);
|
||||||
|
/* Chrome, Opera 15+, Safari 3.1+ */
|
||||||
|
-ms-transform: rotate(360deg);
|
||||||
|
/* IE 9 */
|
||||||
|
transform: rotate(360deg);
|
||||||
|
/* Firefox 16+, IE 10+, Opera */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@keyframes spin {
|
||||||
|
0% {
|
||||||
|
-webkit-transform: rotate(0deg);
|
||||||
|
/* Chrome, Opera 15+, Safari 3.1+ */
|
||||||
|
-ms-transform: rotate(0deg);
|
||||||
|
/* IE 9 */
|
||||||
|
transform: rotate(0deg);
|
||||||
|
/* Firefox 16+, IE 10+, Opera */
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
-webkit-transform: rotate(360deg);
|
||||||
|
/* Chrome, Opera 15+, Safari 3.1+ */
|
||||||
|
-ms-transform: rotate(360deg);
|
||||||
|
/* IE 9 */
|
||||||
|
transform: rotate(360deg);
|
||||||
|
/* Firefox 16+, IE 10+, Opera */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#loader-wrapper .loader-section {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
width: 51%;
|
||||||
|
height: 100%;
|
||||||
|
background: #fff;
|
||||||
|
/* Old browsers */
|
||||||
|
z-index: 1000;
|
||||||
|
-webkit-transform: translateX(0);
|
||||||
|
/* Chrome, Opera 15+, Safari 3.1+ */
|
||||||
|
-ms-transform: translateX(0);
|
||||||
|
/* IE 9 */
|
||||||
|
transform: translateX(0);
|
||||||
|
/* Firefox 16+, IE 10+, Opera */
|
||||||
|
}
|
||||||
|
#loader-wrapper .loader-section.section-left {
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
#loader-wrapper .loader-section.section-right {
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
/* Loaded */
|
||||||
|
.loaded #loader-wrapper .loader-section.section-left {
|
||||||
|
-webkit-transform: translateX(-100%);
|
||||||
|
/* Chrome, Opera 15+, Safari 3.1+ */
|
||||||
|
-ms-transform: translateX(-100%);
|
||||||
|
/* IE 9 */
|
||||||
|
transform: translateX(-100%);
|
||||||
|
/* Firefox 16+, IE 10+, Opera */
|
||||||
|
-webkit-transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1.000);
|
||||||
|
transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1.000);
|
||||||
|
}
|
||||||
|
.loaded #loader-wrapper .loader-section.section-right {
|
||||||
|
-webkit-transform: translateX(100%);
|
||||||
|
/* Chrome, Opera 15+, Safari 3.1+ */
|
||||||
|
-ms-transform: translateX(100%);
|
||||||
|
/* IE 9 */
|
||||||
|
transform: translateX(100%);
|
||||||
|
/* Firefox 16+, IE 10+, Opera */
|
||||||
|
-webkit-transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1.000);
|
||||||
|
transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1.000);
|
||||||
|
}
|
||||||
|
.loaded #loader {
|
||||||
|
opacity: 0;
|
||||||
|
-webkit-transition: all 0.3s ease-out;
|
||||||
|
transition: all 0.3s ease-out;
|
||||||
|
}
|
||||||
|
.loaded #loader-wrapper {
|
||||||
|
visibility: hidden;
|
||||||
|
-webkit-transform: translateY(-100%);
|
||||||
|
/* Chrome, Opera 15+, Safari 3.1+ */
|
||||||
|
-ms-transform: translateY(-100%);
|
||||||
|
/* IE 9 */
|
||||||
|
transform: translateY(-100%);
|
||||||
|
/* Firefox 16+, IE 10+, Opera */
|
||||||
|
-webkit-transition: all 0.3s 1s ease-out;
|
||||||
|
transition: all 0.3s 1s ease-out;
|
||||||
|
}
|
||||||
|
/* JavaScript Turned Off */
|
||||||
|
.no-js #loader-wrapper {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.no-js h1 {
|
||||||
|
color: #222222;
|
||||||
|
}
|
||||||
|
#loader-wrapper .load_title {
|
||||||
|
font-family: 'Open Sans';
|
||||||
|
color: #999;
|
||||||
|
font-size: 14px;
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
z-index: 9999999999999;
|
||||||
|
position: absolute;
|
||||||
|
top: 60%;
|
||||||
|
opacity: 1;
|
||||||
|
line-height: 30px;
|
||||||
|
}
|
||||||
|
#loader-wrapper .load_title span {
|
||||||
|
font-weight: normal;
|
||||||
|
font-style: italic;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #999;
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
/* 滚动条优化 start */
|
||||||
|
::-webkit-scrollbar{
|
||||||
|
width:8px;
|
||||||
|
height:8px;
|
||||||
|
}
|
||||||
|
::-webkit-scrollbar-track{
|
||||||
|
background: #f6f6f6;
|
||||||
|
border-radius:2px;
|
||||||
|
}
|
||||||
|
::-webkit-scrollbar-thumb{
|
||||||
|
background: #cdcdcd;
|
||||||
|
border-radius:2px;
|
||||||
|
}
|
||||||
|
::-webkit-scrollbar-thumb:hover{
|
||||||
|
background: #747474;
|
||||||
|
}
|
||||||
|
::-webkit-scrollbar-corner {
|
||||||
|
background: #f6f6f6;
|
||||||
|
}
|
||||||
|
/* 滚动条优化 end */
|
||||||
|
</style>
|
||||||
|
<script>
|
||||||
|
function getPlatform(type) {
|
||||||
|
let res = '';
|
||||||
|
let ajax = new XMLHttpRequest();
|
||||||
|
let url = window._CONFIG['domianURL'] + '/platformConfig/getPlatform/' + type
|
||||||
|
ajax.onreadystatechange = function () {
|
||||||
|
if (ajax.readyState===4 &&ajax.status===200) {
|
||||||
|
res = ajax.responseText;
|
||||||
|
} else {
|
||||||
|
res = 'ERP系统';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ajax.open('get', url, false);
|
||||||
|
ajax.send(null);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
window._CONFIG = {};
|
||||||
|
window._CONFIG['domianURL'] = '/jshERP-boot';
|
||||||
|
let statisticsCode = '1cd9bcbaae133f03a6eb19da6579aaba'
|
||||||
|
window.SYS_TITLE = getPlatform("name");
|
||||||
|
window.SYS_URL = getPlatform("url");
|
||||||
|
window._statistics = 'https://hm.baidu.com/hm.js?' + statisticsCode
|
||||||
|
document.title = window.SYS_TITLE;
|
||||||
|
//statistics
|
||||||
|
var _hmt = _hmt || [];
|
||||||
|
(function() {
|
||||||
|
var hm = document.createElement("script");
|
||||||
|
hm.src = window._statistics;
|
||||||
|
var s = document.getElementsByTagName("script")[0];
|
||||||
|
s.parentNode.insertBefore(hm, s);
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<!-- built files will be auto injected -->
|
||||||
|
<div id="app">
|
||||||
|
<div id="loader-wrapper">
|
||||||
|
<div id="loader"></div>
|
||||||
|
<div class="loader-section section-left"></div>
|
||||||
|
<div class="loader-section section-right"></div>
|
||||||
|
<div class="load_title">
|
||||||
|
正在加载系统,请耐心等待
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
<!-- 全局配置-多语言切换-开始 -->
|
||||||
|
<script src="<%= BASE_URL %>static/translate.js"></script>
|
||||||
|
<script>
|
||||||
|
//设置本地语种(当前网页的语种)。如果不设置,默认就是 'chinese_simplified' 简体中文
|
||||||
|
translate.language.setLocal('chinese_simplified');
|
||||||
|
translate.service.use('client.edge');
|
||||||
|
//翻译自定义
|
||||||
|
translate.nomenclature.append('chinese_simplified','english',`
|
||||||
|
管伊佳ERP=GuanYiJia
|
||||||
|
`)
|
||||||
|
//开启html页面变化的监控,对变化部分会进行自动翻译
|
||||||
|
translate.listener.start();
|
||||||
|
//不显示语言选择标签
|
||||||
|
translate.selectLanguageTag.show = false;
|
||||||
|
//执行翻译初始化操作,显示出select语言选择
|
||||||
|
//translate.execute();
|
||||||
|
|
||||||
|
//VUE的渲染需要时间,所以留出一点点时间来进行翻译切换
|
||||||
|
document.addEventListener('DOMContentLoaded', function () {
|
||||||
|
//页面 DOM 已渲染完毕,当然最好是能监控到整个vue渲染完毕后触发最好
|
||||||
|
translate.execute();
|
||||||
|
//2秒后再一次,避免有遗漏
|
||||||
|
setTimeout(function(){
|
||||||
|
translate.execute();
|
||||||
|
},2000);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
<!-- 全局配置-多语言切换-结束 -->
|
||||||
|
|
||||||
|
</html>
|
||||||
BIN
public/static/Android.png
Normal file
|
After Width: | Height: | Size: 3.0 KiB |
BIN
public/static/android-code.png
Normal file
|
After Width: | Height: | Size: 21 KiB |
BIN
public/static/banner-home.jpg
Normal file
|
After Width: | Height: | Size: 37 KiB |
BIN
public/static/banner-small.jpg
Normal file
|
After Width: | Height: | Size: 39 KiB |
BIN
public/static/bgimg.png
Normal file
|
After Width: | Height: | Size: 233 KiB |
BIN
public/static/blue.png
Normal file
|
After Width: | Height: | Size: 42 KiB |
7701
public/static/color.less
Normal file
BIN
public/static/favicon.ico
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
public/static/iPhone.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
public/static/iphone-code.png
Normal file
|
After Width: | Height: | Size: 24 KiB |
18
public/static/less.min.js
vendored
Normal file
BIN
public/static/mini-program.png
Normal file
|
After Width: | Height: | Size: 6.7 KiB |
BIN
public/static/rightImg.png
Normal file
|
After Width: | Height: | Size: 258 KiB |
BIN
public/static/screenshot/1.jpg
Normal file
|
After Width: | Height: | Size: 157 KiB |
BIN
public/static/screenshot/10.jpg
Normal file
|
After Width: | Height: | Size: 101 KiB |
BIN
public/static/screenshot/2.jpg
Normal file
|
After Width: | Height: | Size: 168 KiB |
BIN
public/static/screenshot/3.jpg
Normal file
|
After Width: | Height: | Size: 185 KiB |
BIN
public/static/screenshot/4.jpg
Normal file
|
After Width: | Height: | Size: 185 KiB |
BIN
public/static/screenshot/5.jpg
Normal file
|
After Width: | Height: | Size: 142 KiB |
BIN
public/static/screenshot/6.jpg
Normal file
|
After Width: | Height: | Size: 151 KiB |
BIN
public/static/screenshot/7.jpg
Normal file
|
After Width: | Height: | Size: 148 KiB |
BIN
public/static/screenshot/8.jpg
Normal file
|
After Width: | Height: | Size: 149 KiB |
BIN
public/static/screenshot/9.jpg
Normal file
|
After Width: | Height: | Size: 131 KiB |
5822
public/static/translate.js
Normal file
BIN
public/static/weixin-code.png
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
public/static/weixin.jpg
Normal file
|
After Width: | Height: | Size: 58 KiB |
43
src/App.vue
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
<template>
|
||||||
|
<a-config-provider :locale="locale">
|
||||||
|
<div id="app">
|
||||||
|
<router-view/>
|
||||||
|
</div>
|
||||||
|
</a-config-provider>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import zhCN from 'ant-design-vue/lib/locale-provider/zh_CN'
|
||||||
|
import enquireScreen from '@/utils/device'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
locale: zhCN,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created () {
|
||||||
|
let that = this
|
||||||
|
enquireScreen(deviceType => {
|
||||||
|
// tablet
|
||||||
|
if (deviceType === 0) {
|
||||||
|
that.$store.commit('TOGGLE_DEVICE', 'mobile')
|
||||||
|
that.$store.dispatch('setSidebar', false)
|
||||||
|
}
|
||||||
|
// mobile
|
||||||
|
else if (deviceType === 1) {
|
||||||
|
that.$store.commit('TOGGLE_DEVICE', 'mobile')
|
||||||
|
that.$store.dispatch('setSidebar', false)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
that.$store.commit('TOGGLE_DEVICE', 'desktop')
|
||||||
|
that.$store.dispatch('setSidebar', true)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style>
|
||||||
|
#app {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
30
src/api/GroupRequest.js
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
import Vue from 'vue'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将一个请求分组
|
||||||
|
*
|
||||||
|
* @param getPromise 传入一个可以获取到Promise对象的方法
|
||||||
|
* @param groupId 分组ID,如果不传或者为空则不分组
|
||||||
|
* @param expire 过期时间,默认 半分钟
|
||||||
|
*/
|
||||||
|
export function httpGroupRequest(getPromise, groupId, expire = 1000 * 30) {
|
||||||
|
if (groupId == null || groupId === '') {
|
||||||
|
console.log("--------popup----------getFrom DB-------with---no--groupId ")
|
||||||
|
return getPromise()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Vue.ls.get(groupId)) {
|
||||||
|
console.log("---------popup--------getFrom Cache--------groupId = " + groupId)
|
||||||
|
return Promise.resolve(Vue.ls.get(groupId));
|
||||||
|
} else {
|
||||||
|
console.log("--------popup----------getFrom DB---------groupId = " + groupId)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 还没有发出请求,就发出第一次的请求
|
||||||
|
return getPromise().then(res => {
|
||||||
|
Vue.ls.set(groupId, res, expire);
|
||||||
|
return Promise.resolve(res);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
213
src/api/api.js
Normal file
@ -0,0 +1,213 @@
|
|||||||
|
import { getAction, deleteAction, putAction, postAction, httpAction } from '@/api/manage'
|
||||||
|
|
||||||
|
//首页统计
|
||||||
|
const getBuyAndSaleStatistics = (params)=>getAction("/depotHead/getBuyAndSaleStatistics",params);
|
||||||
|
const buyOrSalePrice = (params)=>getAction("/depotItem/buyOrSalePrice",params);
|
||||||
|
//租户管理
|
||||||
|
const checkTenant = (params)=>getAction("/tenant/checkIsNameExist",params);
|
||||||
|
const addTenant = (params)=>postAction("/tenant/add",params);
|
||||||
|
const editTenant = (params)=>putAction("/tenant/update",params);
|
||||||
|
//角色管理
|
||||||
|
const addRole = (params)=>postAction("/role/add",params);
|
||||||
|
const editRole = (params)=>putAction("/role/update",params);
|
||||||
|
const checkRole = (params)=>getAction("/role/checkIsNameExist",params);
|
||||||
|
const roleAllList = (params)=>getAction("/role/allList",params);
|
||||||
|
const getTenantRoleList = (params)=>getAction("/role/tenantRoleList",params);
|
||||||
|
//用户管理
|
||||||
|
const registerUser = (params)=>postAction("/user/registerUser",params);
|
||||||
|
const addUser = (params)=>postAction("/user/addUser",params);
|
||||||
|
const editUser = (params)=>putAction("/user/updateUser",params);
|
||||||
|
const getUserList = (params)=>getAction("/user/getUserList",params);
|
||||||
|
const getUserBtnByCurrentUser = (params)=>getAction("/user/getUserBtnByCurrentUser",params);
|
||||||
|
const queryPermissionsByUser = (params)=>postAction("/function/findMenuByPNumber",params);
|
||||||
|
//机构管理
|
||||||
|
const queryOrganizationTreeList = (params)=>getAction("/organization/getOrganizationTree",params);
|
||||||
|
const getAllOrganizationTreeByUser = (params)=>getAction("/organization/getAllOrganizationTreeByUser",params);
|
||||||
|
const queryOrganizationById = (params)=>getAction("/organization/findById",params);
|
||||||
|
const checkOrganization = (params)=>getAction("/organization/checkIsNameExist",params);
|
||||||
|
//经手人管理
|
||||||
|
const addPerson = (params)=>postAction("/person/add",params);
|
||||||
|
const editPerson = (params)=>putAction("/person/update",params);
|
||||||
|
const checkPerson = (params)=>getAction("/person/checkIsNameExist",params);
|
||||||
|
const getPersonByType = (params)=>getAction("/person/getPersonByType",params);
|
||||||
|
const getPersonByNumType = (params)=>getAction("/person/getPersonByNumType",params);
|
||||||
|
//账户管理
|
||||||
|
const addAccount = (params)=>postAction("/account/add",params);
|
||||||
|
const editAccount = (params)=>putAction("/account/update",params);
|
||||||
|
const checkAccount = (params)=>getAction("/account/checkIsNameExist",params);
|
||||||
|
const getAccount = (params)=>getAction("/account/getAccount",params);
|
||||||
|
//收支项目
|
||||||
|
const addInOutItem = (params)=>postAction("/inOutItem/add",params);
|
||||||
|
const editInOutItem = (params)=>putAction("/inOutItem/update",params);
|
||||||
|
const checkInOutItem = (params)=>getAction("/inOutItem/checkIsNameExist",params);
|
||||||
|
const findInOutItemByParam = (params)=>getAction("/inOutItem/findBySelect",params);
|
||||||
|
//仓库信息
|
||||||
|
const addDepot = (params)=>postAction("/depot/add",params);
|
||||||
|
const editDepot = (params)=>putAction("/depot/update",params);
|
||||||
|
const checkDepot = (params)=>getAction("/depot/checkIsNameExist",params);
|
||||||
|
//商品属性
|
||||||
|
const addOrUpdateMaterialProperty = (params)=>postAction("/materialProperty/addOrUpdate",params);
|
||||||
|
//商品类型
|
||||||
|
const queryMaterialCategoryTreeList = (params)=>getAction("/materialCategory/getMaterialCategoryTree",params);
|
||||||
|
const queryMaterialCategoryById = (params)=>getAction("/materialCategory/findById",params);
|
||||||
|
const checkMaterialCategory = (params)=>getAction("/materialCategory/checkIsNameExist",params);
|
||||||
|
//商品管理
|
||||||
|
const addMaterial = (params)=>postAction("/material/add",params);
|
||||||
|
const editMaterial = (params)=>putAction("/material/update",params);
|
||||||
|
const checkMaterial = (params)=>getAction("/material/checkIsExist",params);
|
||||||
|
const getMaterialBySelect = (params)=>getAction("/material/findBySelect",params);
|
||||||
|
const getSerialMaterialBySelect = (params)=>getAction("/material/getMaterialEnableSerialNumberList",params);
|
||||||
|
const getMaterialByParam = (params)=>getAction("/material/getMaterialByParam",params);
|
||||||
|
const getMaterialByBarCode = (params)=>getAction("/material/getMaterialByBarCode",params);
|
||||||
|
const getMaxBarCode = (params)=>getAction("/material/getMaxBarCode",params);
|
||||||
|
const checkMaterialBarCode = (params)=>getAction("/materialsExtend/checkIsBarCodeExist",params);
|
||||||
|
const batchUpdateMaterial = (params)=>postAction("/material/batchUpdate",params);
|
||||||
|
const changeNameToPinYin = (params)=>postAction("/material/changeNameToPinYin",params);
|
||||||
|
//序列号
|
||||||
|
const batAddSerialNumber = (params)=>postAction("/serialNumber/batAddSerialNumber",params);
|
||||||
|
const getEnableSerialNumberList = (params)=>postAction("/serialNumber/getEnableSerialNumberList",params);
|
||||||
|
//多属性
|
||||||
|
const addMaterialAttribute = (params)=>postAction("/materialAttribute/add",params);
|
||||||
|
const editMaterialAttribute = (params)=>putAction("/materialAttribute/update",params);
|
||||||
|
const checkMaterialAttribute = (params)=>getAction("/materialAttribute/checkIsNameExist",params);
|
||||||
|
const getMaterialAttributeNameList = (params)=>getAction("/materialAttribute/getNameList",params);
|
||||||
|
const getMaterialAttributeValueListById = (params)=>getAction("/materialAttribute/getValueListById",params);
|
||||||
|
//功能管理
|
||||||
|
const addFunction = (params)=>postAction("/function/add",params);
|
||||||
|
const editFunction = (params)=>putAction("/function/update",params);
|
||||||
|
const checkFunction = (params)=>getAction("/function/checkIsNameExist",params);
|
||||||
|
const checkNumber = (params)=>getAction("/function/checkIsNumberExist",params);
|
||||||
|
//系统配置
|
||||||
|
const addSystemConfig = (params)=>postAction("/systemConfig/add",params);
|
||||||
|
const editSystemConfig = (params)=>putAction("/systemConfig/update",params);
|
||||||
|
const checkSystemConfig = (params)=>getAction("/systemConfig/checkIsNameExist",params);
|
||||||
|
const getCurrentSystemConfig = (params)=>getAction("/systemConfig/getCurrentInfo",params);
|
||||||
|
const fileSizeLimit = (params)=>getAction("/systemConfig/fileSizeLimit",params);
|
||||||
|
//平台参数
|
||||||
|
const addPlatformConfig = (params)=>postAction("/platformConfig/add",params);
|
||||||
|
const editPlatformConfig = (params)=>putAction("/platformConfig/update",params);
|
||||||
|
const getPlatformConfigByKey = (params)=>getAction("/platformConfig/getInfoByKey",params);
|
||||||
|
//用户|角色|模块关系
|
||||||
|
const addUserBusiness = (params)=>postAction("/userBusiness/add",params);
|
||||||
|
const editUserBusiness = (params)=>putAction("/userBusiness/update",params);
|
||||||
|
const checkUserBusiness = (params)=>getAction("/userBusiness/checkIsValueExist",params);
|
||||||
|
const updateBtnStrByRoleId = (params)=>postAction("/userBusiness/updateBtnStr",params);
|
||||||
|
const updateOneValueByKeyIdAndType = (params)=>postAction("/userBusiness/updateOneValueByKeyIdAndType",params);
|
||||||
|
//多单位
|
||||||
|
const addUnit = (params)=>postAction("/unit/add",params);
|
||||||
|
const editUnit = (params)=>putAction("/unit/update",params);
|
||||||
|
const checkUnit = (params)=>getAction("/unit/checkIsNameExist",params);
|
||||||
|
//供应商|客户|会员
|
||||||
|
const addSupplier = (params)=>postAction("/supplier/add",params);
|
||||||
|
const editSupplier = (params)=>putAction("/supplier/update",params);
|
||||||
|
const checkSupplier = (params)=>getAction("/supplier/checkIsNameAndTypeExist",params);
|
||||||
|
const findBySelectSup = (params)=>postAction("/supplier/findBySelect_sup",params);
|
||||||
|
const findBySelectCus = (params)=>postAction("/supplier/findBySelect_cus",params);
|
||||||
|
const findBySelectRetail = (params)=>postAction("/supplier/findBySelect_retail",params);
|
||||||
|
const findBySelectOrgan = (params)=>postAction("/supplier/findBySelect_organ",params);
|
||||||
|
//单据相关
|
||||||
|
const findBillDetailByNumber = (params)=>getAction("/depotHead/getDetailByNumber",params);
|
||||||
|
const waitBillCount = (params)=>getAction("/depotHead/waitBillCount",params);
|
||||||
|
const getNeedCount = (params)=>getAction("/depotHead/getNeedCount",params);
|
||||||
|
const batchAddDepotHeadAndDetail = (params)=>postAction("/depotHead/batchAddDepotHeadAndDetail",params);
|
||||||
|
const findStockByDepotAndBarCode = (params)=>getAction("/depotItem/findStockByDepotAndBarCode",params);
|
||||||
|
const getBatchNumberList = (params)=>getAction("/depotItem/getBatchNumberList",params);
|
||||||
|
const findFinancialDetailByNumber = (params)=>getAction("/accountHead/getDetailByNumber",params);
|
||||||
|
|
||||||
|
export {
|
||||||
|
getBuyAndSaleStatistics,
|
||||||
|
buyOrSalePrice,
|
||||||
|
checkTenant,
|
||||||
|
addTenant,
|
||||||
|
editTenant,
|
||||||
|
addRole,
|
||||||
|
editRole,
|
||||||
|
checkRole,
|
||||||
|
roleAllList,
|
||||||
|
getTenantRoleList,
|
||||||
|
registerUser,
|
||||||
|
addUser,
|
||||||
|
editUser,
|
||||||
|
getUserList,
|
||||||
|
getUserBtnByCurrentUser,
|
||||||
|
queryPermissionsByUser,
|
||||||
|
queryOrganizationTreeList,
|
||||||
|
getAllOrganizationTreeByUser,
|
||||||
|
queryOrganizationById,
|
||||||
|
checkOrganization,
|
||||||
|
addPerson,
|
||||||
|
editPerson,
|
||||||
|
checkPerson,
|
||||||
|
getPersonByType,
|
||||||
|
getPersonByNumType,
|
||||||
|
addAccount,
|
||||||
|
editAccount,
|
||||||
|
checkAccount,
|
||||||
|
getAccount,
|
||||||
|
addInOutItem,
|
||||||
|
editInOutItem,
|
||||||
|
checkInOutItem,
|
||||||
|
findInOutItemByParam,
|
||||||
|
addDepot,
|
||||||
|
editDepot,
|
||||||
|
checkDepot,
|
||||||
|
addOrUpdateMaterialProperty,
|
||||||
|
queryMaterialCategoryTreeList,
|
||||||
|
queryMaterialCategoryById,
|
||||||
|
checkMaterialCategory,
|
||||||
|
addMaterial,
|
||||||
|
editMaterial,
|
||||||
|
checkMaterial,
|
||||||
|
getMaterialBySelect,
|
||||||
|
getSerialMaterialBySelect,
|
||||||
|
getMaterialByParam,
|
||||||
|
getMaterialByBarCode,
|
||||||
|
getMaxBarCode,
|
||||||
|
checkMaterialBarCode,
|
||||||
|
batchUpdateMaterial,
|
||||||
|
changeNameToPinYin,
|
||||||
|
batAddSerialNumber,
|
||||||
|
getEnableSerialNumberList,
|
||||||
|
addMaterialAttribute,
|
||||||
|
editMaterialAttribute,
|
||||||
|
checkMaterialAttribute,
|
||||||
|
getMaterialAttributeNameList,
|
||||||
|
getMaterialAttributeValueListById,
|
||||||
|
addFunction,
|
||||||
|
editFunction,
|
||||||
|
checkFunction,
|
||||||
|
checkNumber,
|
||||||
|
addSystemConfig,
|
||||||
|
editSystemConfig,
|
||||||
|
checkSystemConfig,
|
||||||
|
getCurrentSystemConfig,
|
||||||
|
fileSizeLimit,
|
||||||
|
addPlatformConfig,
|
||||||
|
editPlatformConfig,
|
||||||
|
getPlatformConfigByKey,
|
||||||
|
addUserBusiness,
|
||||||
|
editUserBusiness,
|
||||||
|
checkUserBusiness,
|
||||||
|
updateBtnStrByRoleId,
|
||||||
|
updateOneValueByKeyIdAndType,
|
||||||
|
addUnit,
|
||||||
|
editUnit,
|
||||||
|
checkUnit,
|
||||||
|
addSupplier,
|
||||||
|
editSupplier,
|
||||||
|
checkSupplier,
|
||||||
|
findBySelectSup,
|
||||||
|
findBySelectCus,
|
||||||
|
findBySelectRetail,
|
||||||
|
findBySelectOrgan,
|
||||||
|
findBillDetailByNumber,
|
||||||
|
waitBillCount,
|
||||||
|
getNeedCount,
|
||||||
|
batchAddDepotHeadAndDetail,
|
||||||
|
findStockByDepotAndBarCode,
|
||||||
|
getBatchNumberList,
|
||||||
|
findFinancialDetailByNumber
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
10
src/api/index.js
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
const api = {
|
||||||
|
Login: '/user/login',
|
||||||
|
Logout: '/sys/logout',
|
||||||
|
ForgePassword: '/auth/forge-password',
|
||||||
|
Register: '/auth/register',
|
||||||
|
SendSms: '/account/sms',
|
||||||
|
// get my info
|
||||||
|
UserInfo: '/user/info'
|
||||||
|
}
|
||||||
|
export default api
|
||||||
28
src/api/login.js
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import api from './index'
|
||||||
|
import { axios } from '@/utils/request'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* login func
|
||||||
|
* parameter: {
|
||||||
|
* username: '',
|
||||||
|
* password: '',
|
||||||
|
* remember_me: true,
|
||||||
|
* captcha: '12345'
|
||||||
|
* }
|
||||||
|
* @param parameter
|
||||||
|
* @returns {*}
|
||||||
|
*/
|
||||||
|
export function login(parameter) {
|
||||||
|
return axios({
|
||||||
|
url: '/user/login',
|
||||||
|
method: 'post',
|
||||||
|
data: parameter
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function logout() {
|
||||||
|
return axios({
|
||||||
|
url: '/user/logout',
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
164
src/api/manage.js
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
import Vue from 'vue'
|
||||||
|
import { axios } from '@/utils/request'
|
||||||
|
|
||||||
|
const api = {
|
||||||
|
user: '/api/user',
|
||||||
|
role: '/api/role',
|
||||||
|
service: '/api/service',
|
||||||
|
permission: '/api/permission',
|
||||||
|
permissionNoPager: '/api/permission/no-pager',
|
||||||
|
exportExcelByParam: '/systemConfig/exportExcelByParam'
|
||||||
|
}
|
||||||
|
|
||||||
|
export default api
|
||||||
|
|
||||||
|
//post
|
||||||
|
export function postAction(url,parameter) {
|
||||||
|
return axios({
|
||||||
|
url: url,
|
||||||
|
method:'post' ,
|
||||||
|
data: parameter
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
//post method= {post | put}
|
||||||
|
export function httpAction(url,parameter,method) {
|
||||||
|
return axios({
|
||||||
|
url: url,
|
||||||
|
method:method ,
|
||||||
|
data: parameter
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
//put
|
||||||
|
export function putAction(url,parameter) {
|
||||||
|
return axios({
|
||||||
|
url: url,
|
||||||
|
method:'put',
|
||||||
|
data: parameter
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
//get
|
||||||
|
export function getAction(url,parameter) {
|
||||||
|
return axios({
|
||||||
|
url: url,
|
||||||
|
method: 'get',
|
||||||
|
params: parameter
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
//deleteAction
|
||||||
|
export function deleteAction(url,parameter) {
|
||||||
|
return axios({
|
||||||
|
url: url,
|
||||||
|
method: 'delete',
|
||||||
|
params: parameter
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getUserList(parameter) {
|
||||||
|
return axios({
|
||||||
|
url: api.user,
|
||||||
|
method: 'get',
|
||||||
|
params: parameter
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getRoleList(parameter) {
|
||||||
|
return axios({
|
||||||
|
url: api.role,
|
||||||
|
method: 'get',
|
||||||
|
params: parameter
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getServiceList(parameter) {
|
||||||
|
return axios({
|
||||||
|
url: api.service,
|
||||||
|
method: 'get',
|
||||||
|
params: parameter
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getPermissions(parameter) {
|
||||||
|
return axios({
|
||||||
|
url: api.permissionNoPager,
|
||||||
|
method: 'get',
|
||||||
|
params: parameter
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// id == 0 add post
|
||||||
|
// id != 0 update put
|
||||||
|
export function saveService(parameter) {
|
||||||
|
return axios({
|
||||||
|
url: api.service,
|
||||||
|
method: parameter.id == 0 ? 'post' : 'put',
|
||||||
|
data: parameter
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 下载文件 用于excel导出
|
||||||
|
* @param url
|
||||||
|
* @param parameter
|
||||||
|
* @returns {*}
|
||||||
|
*/
|
||||||
|
export function downFile(url,parameter){
|
||||||
|
return axios({
|
||||||
|
url: url,
|
||||||
|
params: parameter,
|
||||||
|
method: 'get',
|
||||||
|
responseType: 'blob'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 下载文件 用于excel导出
|
||||||
|
* @param url
|
||||||
|
* @param parameter
|
||||||
|
* @returns {*}
|
||||||
|
*/
|
||||||
|
export function downFilePost(parameter){
|
||||||
|
return axios({
|
||||||
|
url: api.exportExcelByParam,
|
||||||
|
data: parameter,
|
||||||
|
method: 'post',
|
||||||
|
responseType: 'blob'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件上传 用于富文本上传图片
|
||||||
|
* @param url
|
||||||
|
* @param parameter
|
||||||
|
* @returns {*}
|
||||||
|
*/
|
||||||
|
export function uploadAction(url,parameter){
|
||||||
|
return axios({
|
||||||
|
url: url,
|
||||||
|
data: parameter,
|
||||||
|
method:'post' ,
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'multipart/form-data', // 文件上传
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取文件服务访问路径
|
||||||
|
* @param avatar
|
||||||
|
* @param subStr
|
||||||
|
* @returns {*}
|
||||||
|
*/
|
||||||
|
export function getFileAccessHttpUrl(avatar,subStr) {
|
||||||
|
if(!subStr) subStr = 'http'
|
||||||
|
if(avatar && avatar.startsWith(subStr)){
|
||||||
|
return avatar;
|
||||||
|
}else{
|
||||||
|
if(avatar && avatar.length>0 && avatar.indexOf('[')==-1){
|
||||||
|
return window._CONFIG['domianURL'] + "/" + avatar;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
src/assets/checkcode.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
40
src/assets/dark.svg
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<svg width="52px" height="45px" viewBox="0 0 52 45" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<!-- Generator: Sketch 50.2 (55047) - http://www.bohemiancoding.com/sketch -->
|
||||||
|
<title>Group 5 Copy 5</title>
|
||||||
|
<desc>Created with Sketch.</desc>
|
||||||
|
<defs>
|
||||||
|
<filter x="-9.4%" y="-6.2%" width="118.8%" height="122.5%" filterUnits="objectBoundingBox" id="filter-1">
|
||||||
|
<feOffset dx="0" dy="1" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset>
|
||||||
|
<feGaussianBlur stdDeviation="1" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur>
|
||||||
|
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0" type="matrix" in="shadowBlurOuter1" result="shadowMatrixOuter1"></feColorMatrix>
|
||||||
|
<feMerge>
|
||||||
|
<feMergeNode in="shadowMatrixOuter1"></feMergeNode>
|
||||||
|
<feMergeNode in="SourceGraphic"></feMergeNode>
|
||||||
|
</feMerge>
|
||||||
|
</filter>
|
||||||
|
<rect id="path-2" x="0" y="0" width="48" height="40" rx="4"></rect>
|
||||||
|
<filter x="-4.2%" y="-2.5%" width="108.3%" height="110.0%" filterUnits="objectBoundingBox" id="filter-4">
|
||||||
|
<feOffset dx="0" dy="1" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset>
|
||||||
|
<feGaussianBlur stdDeviation="0.5" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur>
|
||||||
|
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0" type="matrix" in="shadowBlurOuter1"></feColorMatrix>
|
||||||
|
</filter>
|
||||||
|
</defs>
|
||||||
|
<g id="配置面板" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||||
|
<g id="setting-copy-2" transform="translate(-1190.000000, -136.000000)">
|
||||||
|
<g id="Group-8" transform="translate(1167.000000, 0.000000)">
|
||||||
|
<g id="Group-5-Copy-5" filter="url(#filter-1)" transform="translate(25.000000, 137.000000)">
|
||||||
|
<mask id="mask-3" fill="white">
|
||||||
|
<use xlink:href="#path-2"></use>
|
||||||
|
</mask>
|
||||||
|
<g id="Rectangle-18">
|
||||||
|
<use fill="black" fill-opacity="1" filter="url(#filter-4)" xlink:href="#path-2"></use>
|
||||||
|
<use fill="#F0F2F5" fill-rule="evenodd" xlink:href="#path-2"></use>
|
||||||
|
</g>
|
||||||
|
<rect id="Rectangle-11" fill="#FFFFFF" mask="url(#mask-3)" x="-1" y="0" width="49" height="10"></rect>
|
||||||
|
<rect id="Rectangle-18" fill="#303648" mask="url(#mask-3)" x="0" y="0" width="16" height="44"></rect>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 2.6 KiB |
259
src/assets/less/JAreaLinkage.less
Normal file
@ -0,0 +1,259 @@
|
|||||||
|
.area-zoom-in-top-enter-active,
|
||||||
|
.area-zoom-in-top-leave-active {
|
||||||
|
opacity: 1;
|
||||||
|
transform: scaleY(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.area-zoom-in-top-enter,
|
||||||
|
.area-zoom-in-top-leave-active {
|
||||||
|
opacity: 0;
|
||||||
|
transform: scaleY(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.area-select {
|
||||||
|
box-sizing: border-box;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
color: rgba(0, 0, 0, 0.65);
|
||||||
|
font-size: 14px;
|
||||||
|
font-variant: tabular-nums;
|
||||||
|
line-height: 1.5;
|
||||||
|
list-style: none;
|
||||||
|
font-feature-settings: 'tnum';
|
||||||
|
position: relative;
|
||||||
|
outline: 0;
|
||||||
|
display: block;
|
||||||
|
background-color: #fff;
|
||||||
|
border: 1px solid #d9d9d9;
|
||||||
|
border-top-width: 1.02px;
|
||||||
|
border-radius: 4px;
|
||||||
|
outline: none;
|
||||||
|
transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-ms-user-select: none;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.area-select-wrap .area-select {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.area-select * {
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.area-select:hover {
|
||||||
|
border-color: #40a9ff;
|
||||||
|
border-right-width: 1px !important;
|
||||||
|
outline: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.area-select:active {
|
||||||
|
box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.area-select.small {
|
||||||
|
width: 126px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.area-select.medium {
|
||||||
|
width: 160px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.area-select.large {
|
||||||
|
width: 194px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.area-select.is-disabled {
|
||||||
|
background: #eceff5;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
.area-select.is-disabled:hover {
|
||||||
|
border-color: #e1e2e6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.area-select.is-disabled .area-selected-trigger {
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
.area-select .area-selected-trigger {
|
||||||
|
position: relative;
|
||||||
|
display: block;
|
||||||
|
font-size: 14px;
|
||||||
|
cursor: pointer;
|
||||||
|
margin: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
height: 100%;
|
||||||
|
padding: 8px 20px 7px 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.area-select .area-select-icon {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
margin-top: -2px;
|
||||||
|
right: 6px;
|
||||||
|
content: "";
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
border: 6px solid transparent;
|
||||||
|
border-top-color: rgba(0, 0, 0, 0.25);
|
||||||
|
transition: all .3s linear;
|
||||||
|
transform-origin: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.area-select .area-select-icon.active {
|
||||||
|
margin-top: -8px;
|
||||||
|
transform: rotate(180deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.area-selectable-list-wrap {
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
max-height: 275px;
|
||||||
|
z-index: 15000;
|
||||||
|
background-color: #fff;
|
||||||
|
box-sizing: border-box;
|
||||||
|
overflow-x: auto;
|
||||||
|
margin: 2px 0;
|
||||||
|
border-radius: 4px;
|
||||||
|
outline: none;
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
|
||||||
|
|
||||||
|
transition: opacity 0.15s, transform 0.3s !important;
|
||||||
|
transform-origin: center top !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.area-selectable-list {
|
||||||
|
position: relative;
|
||||||
|
margin: 0;
|
||||||
|
padding: 6px 0;
|
||||||
|
width: 100%;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #565656;
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.area-selectable-list .area-select-option {
|
||||||
|
position: relative;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 0 15px 0 10px;
|
||||||
|
height: 32px;
|
||||||
|
line-height: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.area-selectable-list .area-select-option.hover {
|
||||||
|
background-color: #e6f7ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.area-selectable-list .area-select-option.selected {
|
||||||
|
color: rgba(0, 0, 0, 0.65);
|
||||||
|
font-weight: 600;
|
||||||
|
background-color: #efefef;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cascader-menu-list-wrap {
|
||||||
|
position: absolute;
|
||||||
|
white-space: nowrap;
|
||||||
|
z-index: 15000;
|
||||||
|
background-color: #fff;
|
||||||
|
box-sizing: border-box;
|
||||||
|
overflow: hidden;
|
||||||
|
font-size: 0;
|
||||||
|
margin: 2px 0;
|
||||||
|
border-radius: 4px;
|
||||||
|
outline: none;
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
|
||||||
|
|
||||||
|
transition: opacity 0.15s, transform 0.3s !important;
|
||||||
|
transform-origin: center top !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cascader-menu-list {
|
||||||
|
position: relative;
|
||||||
|
margin: 0;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #565656;
|
||||||
|
padding: 6px 0;
|
||||||
|
list-style: none;
|
||||||
|
display: inline-block;
|
||||||
|
height: 204px;
|
||||||
|
overflow-x: hidden;
|
||||||
|
overflow-y: auto;
|
||||||
|
min-width: 160px;
|
||||||
|
vertical-align: top;
|
||||||
|
background-color: #fff;
|
||||||
|
border-right: 1px solid #e4e7ed;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cascader-menu-list:last-child {
|
||||||
|
border-right: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cascader-menu-list .cascader-menu-option {
|
||||||
|
position: relative;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 0 15px 0 10px;
|
||||||
|
height: 32px;
|
||||||
|
line-height: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cascader-menu-list .cascader-menu-option.hover,
|
||||||
|
.cascader-menu-list .cascader-menu-option:hover {
|
||||||
|
background-color: #e6f7ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cascader-menu-list .cascader-menu-option.selected {
|
||||||
|
color: rgba(0, 0, 0, 0.65);
|
||||||
|
font-weight: 600;
|
||||||
|
background-color: #efefef;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cascader-menu-list .cascader-menu-option.cascader-menu-extensible:after {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
margin-top: -4px;
|
||||||
|
right: 5px;
|
||||||
|
content: "";
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
border: 4px solid transparent;
|
||||||
|
border-left-color: #a1a4ad;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cascader-menu-list::-webkit-scrollbar,
|
||||||
|
.area-selectable-list-wrap::-webkit-scrollbar {
|
||||||
|
width: 8px;
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.area-selectable-list-wrap::-webkit-scrollbar-button:vertical:decremen,
|
||||||
|
.area-selectable-list-wrap::-webkit-scrollbar-button:vertical:end:decrement,
|
||||||
|
.area-selectable-list-wrap::-webkit-scrollbar-button:vertical:increment,
|
||||||
|
.area-selectable-list-wrap::-webkit-scrollbar-button:vertical:start:increment,
|
||||||
|
.cascader-menu-list::-webkit-scrollbar-button:vertical:decremen,
|
||||||
|
.cascader-menu-list::-webkit-scrollbar-button:vertical:end:decrement,
|
||||||
|
.cascader-menu-list::-webkit-scrollbar-button:vertical:increment,
|
||||||
|
.cascader-menu-list::-webkit-scrollbar-button:vertical:start:increment {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cascader-menu-list::-webkit-scrollbar-thumb:vertical,
|
||||||
|
.area-selectable-list-wrap::-webkit-scrollbar-thumb:vertical {
|
||||||
|
background-color: #b8b8b8;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cascader-menu-list::-webkit-scrollbar-thumb:vertical:hover,
|
||||||
|
.area-selectable-list-wrap::-webkit-scrollbar-thumb:vertical:hover {
|
||||||
|
background-color: #777;
|
||||||
|
}
|
||||||
15
src/assets/less/TableExpand.less
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
/** [表格主题样式一] 表格强制列不换行 */
|
||||||
|
.j-table-force-nowrap {
|
||||||
|
td, th {
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-table-selection-column {
|
||||||
|
padding: 12px 22px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 列自适应,弊端会导致列宽失效 */
|
||||||
|
&.ant-table-wrapper .ant-table-content {
|
||||||
|
overflow-x: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
96
src/assets/less/common.less
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
/*列表上方操作按钮区域*/
|
||||||
|
.ant-card-body .table-operator {
|
||||||
|
margin-bottom: 0px;
|
||||||
|
}
|
||||||
|
/** Button按钮间距 */
|
||||||
|
.table-operator .ant-btn {
|
||||||
|
margin: 0 8px 8px 0;
|
||||||
|
}
|
||||||
|
.table-operator .ant-btn-group .ant-btn {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
.table-operator .ant-btn-group .ant-btn:last-child {
|
||||||
|
margin: 0 8px 8px 0;
|
||||||
|
}
|
||||||
|
/*列表td的padding设置 可以控制列表大小*/
|
||||||
|
.ant-table-tbody .ant-table-row td {
|
||||||
|
padding-top: 15px;
|
||||||
|
padding-bottom: 15px;
|
||||||
|
}
|
||||||
|
.depot-mask {
|
||||||
|
margin-top: 93px;
|
||||||
|
margin-left: 154px;
|
||||||
|
}
|
||||||
|
/*列表页面弹出modal*/
|
||||||
|
.ant-modal-cust-warp {
|
||||||
|
height: 100%
|
||||||
|
}
|
||||||
|
/*弹出modal Y轴滚动条*/
|
||||||
|
.ant-modal-cust-warp .ant-modal-body {
|
||||||
|
padding: 24px 24px 12px 24px;
|
||||||
|
height: calc(100% - 110px) !important;
|
||||||
|
overflow-y: auto
|
||||||
|
}
|
||||||
|
/*弹出modal 先有content后有body 故滚动条控制在body上*/
|
||||||
|
.ant-modal-cust-warp .ant-modal-content {
|
||||||
|
height: 90%;
|
||||||
|
overflow-y: hidden
|
||||||
|
}
|
||||||
|
/*文本框样式*/
|
||||||
|
.ant-modal-cust-warp .ant-form-item {
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
/*全屏模式*/
|
||||||
|
.ant-modal-cust-warp .fullscreen >.ant-modal-content {
|
||||||
|
height: 100vh;
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
/*全屏模式*/
|
||||||
|
.ant-modal-cust-warp .fullscreen >.ant-modal-content >.ant-modal-body {
|
||||||
|
padding: 24px 24px 12px 24px;
|
||||||
|
height: calc(100% - 200px) !important;
|
||||||
|
overflow-y: auto
|
||||||
|
}
|
||||||
|
/*列表中有图片的加这个样式 参考用户管理*/
|
||||||
|
.anty-img-wrap {
|
||||||
|
height: 25px;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
.anty-img-wrap > img {
|
||||||
|
max-height: 100%;
|
||||||
|
}
|
||||||
|
/*列表中范围查询样式*/
|
||||||
|
.query-group-cust{width: calc(50% - 10px)}
|
||||||
|
.query-group-split-cust:before{content:"~";width: 20px;display: inline-block;text-align: center}
|
||||||
|
/*erp风格子表外框padding设置*/
|
||||||
|
.ant-card-wider-padding.cust-erp-sub-tab>.ant-card-body{padding:5px 12px}
|
||||||
|
/* 内嵌子表背景颜色 */
|
||||||
|
.j-inner-table-wrapper /deep/ .ant-table-expanded-row .ant-table-wrapper .ant-table-tbody .ant-table-row {
|
||||||
|
background-color: #FFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-modal-mask {
|
||||||
|
background-color: rgba(0, 0, 0, 0.1) !important;
|
||||||
|
}
|
||||||
|
/* 拖拽 */
|
||||||
|
.table-draggable-handle {
|
||||||
|
/* width: 10px !important; */
|
||||||
|
height: 100% !important;
|
||||||
|
left: auto !important;
|
||||||
|
right: -5px;
|
||||||
|
cursor: col-resize;
|
||||||
|
touch-action: none;
|
||||||
|
border: none;
|
||||||
|
position: absolute;
|
||||||
|
transform: none !important;
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
|
.resize-table-th {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
/* 单据下拉框-按钮 */
|
||||||
|
.dropdown-btn {
|
||||||
|
float:left;
|
||||||
|
padding: 4px 8px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
28
src/assets/less/index.less
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
/**
|
||||||
|
* 列表查询通用样式,移动端自适应
|
||||||
|
*/
|
||||||
|
.search{
|
||||||
|
margin-bottom: 54px;
|
||||||
|
}
|
||||||
|
.fold{
|
||||||
|
width: calc(100% - 216px);
|
||||||
|
display: inline-block
|
||||||
|
}
|
||||||
|
.operator{
|
||||||
|
margin-bottom: 18px;
|
||||||
|
}
|
||||||
|
@media screen and (max-width: 900px) {
|
||||||
|
.fold {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.operator button {
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
i {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.trcolor{
|
||||||
|
background-color: rgba(255, 192, 203, 0.31);
|
||||||
|
color:red;
|
||||||
|
}
|
||||||
40
src/assets/light.svg
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<svg width="52px" height="45px" viewBox="0 0 52 45" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<!-- Generator: Sketch 50.2 (55047) - http://www.bohemiancoding.com/sketch -->
|
||||||
|
<title>Group 5</title>
|
||||||
|
<desc>Created with Sketch.</desc>
|
||||||
|
<defs>
|
||||||
|
<filter x="-9.4%" y="-6.2%" width="118.8%" height="122.5%" filterUnits="objectBoundingBox" id="filter-1">
|
||||||
|
<feOffset dx="0" dy="1" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset>
|
||||||
|
<feGaussianBlur stdDeviation="1" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur>
|
||||||
|
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0" type="matrix" in="shadowBlurOuter1" result="shadowMatrixOuter1"></feColorMatrix>
|
||||||
|
<feMerge>
|
||||||
|
<feMergeNode in="shadowMatrixOuter1"></feMergeNode>
|
||||||
|
<feMergeNode in="SourceGraphic"></feMergeNode>
|
||||||
|
</feMerge>
|
||||||
|
</filter>
|
||||||
|
<rect id="path-2" x="0" y="0" width="48" height="40" rx="4"></rect>
|
||||||
|
<filter x="-4.2%" y="-2.5%" width="108.3%" height="110.0%" filterUnits="objectBoundingBox" id="filter-4">
|
||||||
|
<feOffset dx="0" dy="1" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset>
|
||||||
|
<feGaussianBlur stdDeviation="0.5" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur>
|
||||||
|
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0" type="matrix" in="shadowBlurOuter1"></feColorMatrix>
|
||||||
|
</filter>
|
||||||
|
</defs>
|
||||||
|
<g id="配置面板" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||||
|
<g id="setting-copy-2" transform="translate(-1254.000000, -136.000000)">
|
||||||
|
<g id="Group-8" transform="translate(1167.000000, 0.000000)">
|
||||||
|
<g id="Group-5" filter="url(#filter-1)" transform="translate(89.000000, 137.000000)">
|
||||||
|
<mask id="mask-3" fill="white">
|
||||||
|
<use xlink:href="#path-2"></use>
|
||||||
|
</mask>
|
||||||
|
<g id="Rectangle-18">
|
||||||
|
<use fill="black" fill-opacity="1" filter="url(#filter-4)" xlink:href="#path-2"></use>
|
||||||
|
<use fill="#F0F2F5" fill-rule="evenodd" xlink:href="#path-2"></use>
|
||||||
|
</g>
|
||||||
|
<rect id="Rectangle-18" fill="#FFFFFF" mask="url(#mask-3)" x="0" y="0" width="16" height="44"></rect>
|
||||||
|
<rect id="Rectangle-11" fill="#FFFFFF" mask="url(#mask-3)" x="-1" y="0" width="49" height="10"></rect>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 2.6 KiB |
46
src/components/AvatarList/Item.vue
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
<template>
|
||||||
|
<tooltip v-if="tips !== ''">
|
||||||
|
<template slot="title">{{ tips }}</template>
|
||||||
|
<avatar :size="avatarSize" :src="src" />
|
||||||
|
</tooltip>
|
||||||
|
<avatar v-else :size="avatarSize" :src="src" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import Avatar from 'ant-design-vue/es/avatar'
|
||||||
|
import Tooltip from 'ant-design-vue/es/tooltip'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "AvatarItem",
|
||||||
|
components: {
|
||||||
|
Avatar,
|
||||||
|
Tooltip
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
tips: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
required: false
|
||||||
|
},
|
||||||
|
src: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
size: this.$parent.size
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
avatarSize () {
|
||||||
|
return this.size !== 'mini' && this.size || 20
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
'$parent.size' (val) {
|
||||||
|
this.size = val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
91
src/components/AvatarList/List.vue
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
<!--
|
||||||
|
<template>
|
||||||
|
<div :class="[prefixCls]">
|
||||||
|
<ul>
|
||||||
|
<slot></slot>
|
||||||
|
<template v-for="item in filterEmpty($slots.default).slice(0, 3)"></template>
|
||||||
|
|
||||||
|
|
||||||
|
<template v-if="maxLength > 0 && filterEmpty($slots.default).length > maxLength">
|
||||||
|
<avatar-item :size="size">
|
||||||
|
<avatar :size="size !== 'mini' && size || 20" :style="excessItemsStyle">{{ `+${maxLength}` }}</avatar>
|
||||||
|
</avatar-item>
|
||||||
|
</template>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
-->
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import Avatar from 'ant-design-vue/es/avatar'
|
||||||
|
import AvatarItem from './Item'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
AvatarItem,
|
||||||
|
name: "AvatarList",
|
||||||
|
components: {
|
||||||
|
Avatar,
|
||||||
|
AvatarItem
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
prefixCls: {
|
||||||
|
type: String,
|
||||||
|
default: 'ant-pro-avatar-list'
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 头像大小 类型: large、small 、mini, default
|
||||||
|
* 默认值: default
|
||||||
|
*/
|
||||||
|
size: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: 'default'
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 要显示的最大项目
|
||||||
|
*/
|
||||||
|
maxLength: {
|
||||||
|
type: Number,
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 多余的项目风格
|
||||||
|
*/
|
||||||
|
excessItemsStyle: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {
|
||||||
|
return {
|
||||||
|
color: '#f56a00',
|
||||||
|
backgroundColor: '#fde3cf'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data () {
|
||||||
|
return {}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
getItems(items) {
|
||||||
|
const classString = {
|
||||||
|
[`${this.prefixCls}-item`]: true,
|
||||||
|
[`${this.size}`]: true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.maxLength > 0) {
|
||||||
|
items = items.slice(0, this.maxLength)
|
||||||
|
items.push((<Avatar size={ this.size } style={ this.excessItemsStyle }>{`+${this.maxLength}`}</Avatar>))
|
||||||
|
}
|
||||||
|
const itemList = items.map((item) => (
|
||||||
|
<li class={ classString }>{ item }</li>
|
||||||
|
))
|
||||||
|
return itemList
|
||||||
|
}
|
||||||
|
},
|
||||||
|
render () {
|
||||||
|
const { prefixCls, size } = this.$props
|
||||||
|
const classString = {
|
||||||
|
[`${prefixCls}`]: true,
|
||||||
|
[`${size}`]: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
4
src/components/AvatarList/index.js
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
import AvatarList from './List'
|
||||||
|
import "./index.less"
|
||||||
|
|
||||||
|
export default AvatarList
|
||||||
60
src/components/AvatarList/index.less
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
@import "../index";
|
||||||
|
|
||||||
|
@avatar-list-prefix-cls: ~"@{ant-pro-prefix}-avatar-list";
|
||||||
|
@avatar-list-item-prefix-cls: ~"@{ant-pro-prefix}-avatar-list-item";
|
||||||
|
|
||||||
|
.@{avatar-list-prefix-cls} {
|
||||||
|
display: inline-block;
|
||||||
|
|
||||||
|
ul {
|
||||||
|
list-style: none;
|
||||||
|
display: inline-block;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0 0 0 8px;
|
||||||
|
font-size: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.@{avatar-list-item-prefix-cls} {
|
||||||
|
display: inline-block;
|
||||||
|
font-size: @font-size-base;
|
||||||
|
margin-left: -8px;
|
||||||
|
width: @avatar-size-base;
|
||||||
|
height: @avatar-size-base;
|
||||||
|
|
||||||
|
:global {
|
||||||
|
.ant-avatar {
|
||||||
|
border: 1px solid #fff;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.large {
|
||||||
|
width: @avatar-size-lg;
|
||||||
|
height: @avatar-size-lg;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.small {
|
||||||
|
width: @avatar-size-sm;
|
||||||
|
height: @avatar-size-sm;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.mini {
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
|
||||||
|
:global {
|
||||||
|
.ant-avatar {
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
line-height: 20px;
|
||||||
|
|
||||||
|
.ant-avatar-string {
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 18px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
105
src/components/ChartCard.vue
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
<template>
|
||||||
|
<a-card :loading="loading" :body-style="{ padding: '20px 24px 8px' }" :bordered="false">
|
||||||
|
<div class="chart-card-header">
|
||||||
|
<div class="meta">
|
||||||
|
<span class="chart-card-title">{{ title }}</span>
|
||||||
|
<span class="chart-card-action">
|
||||||
|
<slot name="action"></slot>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="chart-card-content">
|
||||||
|
<div class="content-fix">
|
||||||
|
<slot></slot>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</a-card>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: "ChartCard",
|
||||||
|
props: {
|
||||||
|
title: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
total: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
loading: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.chart-card-header {
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
.meta {
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
width: 100%;
|
||||||
|
color: rgba(0, 0, 0, .45);
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 22px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart-card-action {
|
||||||
|
cursor: pointer;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart-card-footer {
|
||||||
|
border-top: 1px solid #e8e8e8;
|
||||||
|
padding-top: 9px;
|
||||||
|
margin-top: 8px;
|
||||||
|
|
||||||
|
> * {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.field {
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart-card-content {
|
||||||
|
margin-bottom: 12px;
|
||||||
|
position: relative;
|
||||||
|
height: 46px;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
.content-fix {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
bottom: 0;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.total {
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
word-break: break-all;
|
||||||
|
white-space: nowrap;
|
||||||
|
color: #000;
|
||||||
|
margin-top: 4px;
|
||||||
|
margin-bottom: 0;
|
||||||
|
font-size: 30px;
|
||||||
|
line-height: 38px;
|
||||||
|
height: 38px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
103
src/components/CountDown/CountDown.vue
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
<template>
|
||||||
|
<span>
|
||||||
|
{{ lastTime | format }}
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
function fixedZero(val) {
|
||||||
|
return val * 1 < 10 ? `0${val}` : val;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "CountDown",
|
||||||
|
props: {
|
||||||
|
format: {
|
||||||
|
type: Function,
|
||||||
|
default: undefined
|
||||||
|
},
|
||||||
|
target: {
|
||||||
|
type: [Date, Number],
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
onEnd: {
|
||||||
|
type: Function,
|
||||||
|
default: () => {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
dateTime: '0',
|
||||||
|
originTargetTime: 0,
|
||||||
|
lastTime: 0,
|
||||||
|
timer: 0,
|
||||||
|
interval: 1000
|
||||||
|
}
|
||||||
|
},
|
||||||
|
filters: {
|
||||||
|
format(time) {
|
||||||
|
const hours = 60 * 60 * 1000;
|
||||||
|
const minutes = 60 * 1000;
|
||||||
|
|
||||||
|
const h = Math.floor(time / hours);
|
||||||
|
const m = Math.floor((time - h * hours) / minutes);
|
||||||
|
const s = Math.floor((time - h * hours - m * minutes) / 1000);
|
||||||
|
return `${fixedZero(h)}:${fixedZero(m)}:${fixedZero(s)}`
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.initTime()
|
||||||
|
this.tick()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
initTime() {
|
||||||
|
let lastTime = 0;
|
||||||
|
let targetTime = 0;
|
||||||
|
this.originTargetTime = this.target
|
||||||
|
try {
|
||||||
|
if (Object.prototype.toString.call(this.target) === '[object Date]') {
|
||||||
|
targetTime = this.target
|
||||||
|
} else {
|
||||||
|
targetTime = new Date(this.target).getTime()
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
throw new Error('invalid target prop')
|
||||||
|
}
|
||||||
|
|
||||||
|
lastTime = targetTime - new Date().getTime();
|
||||||
|
|
||||||
|
this.lastTime = lastTime < 0 ? 0 : lastTime
|
||||||
|
},
|
||||||
|
tick() {
|
||||||
|
const {onEnd} = this
|
||||||
|
|
||||||
|
this.timer = setTimeout(() => {
|
||||||
|
if (this.lastTime < this.interval) {
|
||||||
|
clearTimeout(this.timer)
|
||||||
|
this.lastTime = 0
|
||||||
|
if (typeof onEnd === 'function') {
|
||||||
|
onEnd();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.lastTime -= this.interval
|
||||||
|
this.tick()
|
||||||
|
}
|
||||||
|
}, this.interval)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
beforeUpdate () {
|
||||||
|
if (this.originTargetTime !== this.target) {
|
||||||
|
this.initTime()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
clearTimeout(this.timer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
||||||
3
src/components/CountDown/index.js
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import CountDown from './CountDown'
|
||||||
|
|
||||||
|
export default CountDown
|
||||||
36
src/components/Ellipsis/Ellipsis.vue
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'Ellipsis',
|
||||||
|
props: {
|
||||||
|
prefixCls: {
|
||||||
|
type: String,
|
||||||
|
default: 'ant-pro-ellipsis'
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
length: {
|
||||||
|
type: Number,
|
||||||
|
default: 25,
|
||||||
|
},
|
||||||
|
lines: {
|
||||||
|
type: Number,
|
||||||
|
default: 1
|
||||||
|
},
|
||||||
|
fullWidthRecognition: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {},
|
||||||
|
render() {
|
||||||
|
const { tooltip, length } = this.$props
|
||||||
|
let text = ''
|
||||||
|
// 处理没有default插槽时的特殊情况
|
||||||
|
if (this.$slots.default) {
|
||||||
|
text = this.$slots.default.map(vNode => vNode.text).join('')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
3
src/components/Ellipsis/index.js
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import Ellipsis from './Ellipsis'
|
||||||
|
|
||||||
|
export default Ellipsis
|
||||||
54
src/components/NumberInfo/NumberInfo.vue
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
<template>
|
||||||
|
<div :class="[prefixCls]">
|
||||||
|
<slot name="subtitle">
|
||||||
|
<div :class="[`${prefixCls}-subtitle`]">{{ typeof subTitle === 'string' ? subTitle : subTitle() }}</div>
|
||||||
|
</slot>
|
||||||
|
<div class="number-info-value">
|
||||||
|
<span>{{ total }}</span>
|
||||||
|
<span class="sub-total">
|
||||||
|
{{ subTotal }}
|
||||||
|
<icon :type="`caret-${status}`" />
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import Icon from 'ant-design-vue/es/icon'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'NumberInfo',
|
||||||
|
props: {
|
||||||
|
prefixCls: {
|
||||||
|
type: String,
|
||||||
|
default: 'ant-pro-number-info'
|
||||||
|
},
|
||||||
|
total: {
|
||||||
|
type: Number,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
subTotal: {
|
||||||
|
type: Number,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
subTitle: {
|
||||||
|
type: [String, Function],
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
status: {
|
||||||
|
type: String,
|
||||||
|
default: 'up'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
Icon
|
||||||
|
},
|
||||||
|
data () {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
/*@import "index";*/
|
||||||
|
</style>
|
||||||
3
src/components/NumberInfo/index.js
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import NumberInfo from './NumberInfo'
|
||||||
|
|
||||||
|
export default NumberInfo
|
||||||
55
src/components/NumberInfo/index.less
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
@import "../index";
|
||||||
|
|
||||||
|
@numberInfo-prefix-cls: ~"@{ant-pro-prefix}-number-info";
|
||||||
|
|
||||||
|
.@{numberInfo-prefix-cls} {
|
||||||
|
|
||||||
|
.ant-pro-number-info-subtitle {
|
||||||
|
color: @text-color-secondary;
|
||||||
|
font-size: @font-size-base;
|
||||||
|
height: 22px;
|
||||||
|
line-height: 22px;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
word-break: break-all;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.number-info-value {
|
||||||
|
margin-top: 4px;
|
||||||
|
font-size: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
word-break: break-all;
|
||||||
|
white-space: nowrap;
|
||||||
|
|
||||||
|
& > span {
|
||||||
|
color: @heading-color;
|
||||||
|
display: inline-block;
|
||||||
|
line-height: 32px;
|
||||||
|
height: 32px;
|
||||||
|
font-size: 24px;
|
||||||
|
margin-right: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sub-total {
|
||||||
|
color: @text-color-secondary;
|
||||||
|
font-size: @font-size-lg;
|
||||||
|
vertical-align: top;
|
||||||
|
margin-right: 0;
|
||||||
|
i {
|
||||||
|
font-size: 12px;
|
||||||
|
transform: scale(0.82);
|
||||||
|
margin-left: 4px;
|
||||||
|
}
|
||||||
|
:global {
|
||||||
|
.anticon-caret-up {
|
||||||
|
color: @red-6;
|
||||||
|
}
|
||||||
|
.anticon-caret-down {
|
||||||
|
color: @green-6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
41
src/components/Trend/Trend.vue
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
<template>
|
||||||
|
<div :class="[prefixCls, reverseColor && 'reverse-color' ]">
|
||||||
|
<span>
|
||||||
|
<slot name="term"></slot>
|
||||||
|
<span class="item-text">
|
||||||
|
<slot></slot>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
<span :class="[flag]"><a-icon :type="`caret-${flag}`"/></span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: "Trend",
|
||||||
|
props: {
|
||||||
|
prefixCls: {
|
||||||
|
type: String,
|
||||||
|
default: 'ant-pro-trend'
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 上升下降标识:up|down
|
||||||
|
*/
|
||||||
|
flag: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 颜色反转
|
||||||
|
*/
|
||||||
|
reverseColor: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
@import "index";
|
||||||
|
</style>
|
||||||
3
src/components/Trend/index.js
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import Trend from './Trend.vue'
|
||||||
|
|
||||||
|
export default Trend
|
||||||
42
src/components/Trend/index.less
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
@import "../index";
|
||||||
|
|
||||||
|
@trend-prefix-cls: ~"@{ant-pro-prefix}-trend";
|
||||||
|
|
||||||
|
.@{trend-prefix-cls} {
|
||||||
|
display: inline-block;
|
||||||
|
font-size: @font-size-base;
|
||||||
|
line-height: 22px;
|
||||||
|
|
||||||
|
.up,
|
||||||
|
.down {
|
||||||
|
margin-left: 4px;
|
||||||
|
position: relative;
|
||||||
|
top: 1px;
|
||||||
|
|
||||||
|
i {
|
||||||
|
font-size: 12px;
|
||||||
|
transform: scale(0.83);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-text {
|
||||||
|
display: inline-block;
|
||||||
|
margin-left: 8px;
|
||||||
|
color: rgba(0,0,0,.85);
|
||||||
|
}
|
||||||
|
|
||||||
|
.up {
|
||||||
|
color: @red-6;
|
||||||
|
}
|
||||||
|
.down {
|
||||||
|
color: @green-6;
|
||||||
|
top: -1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.reverse-color .up {
|
||||||
|
color: @green-6;
|
||||||
|
}
|
||||||
|
&.reverse-color .down {
|
||||||
|
color: @red-6;
|
||||||
|
}
|
||||||
|
}
|
||||||
88
src/components/chart/AreaChartTy.vue
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
<template>
|
||||||
|
<div :style="{ padding: '0' }">
|
||||||
|
<h4 :style="{ marginBottom: '20px' }">{{ title }}</h4>
|
||||||
|
|
||||||
|
<v-chart ref="chart" :forceFit="true" :height="height" :data="dataSource" :scale="scale">
|
||||||
|
<v-tooltip :shared="false"/>
|
||||||
|
<v-axis/>
|
||||||
|
<v-line position="x*y" :size="lineSize" :color="lineColor"/>
|
||||||
|
<v-area position="x*y" :color="color"/>
|
||||||
|
</v-chart>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { triggerWindowResizeEvent } from '@/utils/util'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'AreaChartTy',
|
||||||
|
props: {
|
||||||
|
// 图表数据
|
||||||
|
dataSource: {
|
||||||
|
type: Array,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
// 图表标题
|
||||||
|
title: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
// x 轴别名
|
||||||
|
x: {
|
||||||
|
type: String,
|
||||||
|
default: 'x'
|
||||||
|
},
|
||||||
|
// y 轴别名
|
||||||
|
y: {
|
||||||
|
type: String,
|
||||||
|
default: 'y'
|
||||||
|
},
|
||||||
|
// Y轴最小值
|
||||||
|
min: {
|
||||||
|
type: Number,
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
// Y轴最大值
|
||||||
|
max: {
|
||||||
|
type: Number,
|
||||||
|
default: null
|
||||||
|
},
|
||||||
|
// 图表高度
|
||||||
|
height: {
|
||||||
|
type: Number,
|
||||||
|
default: 254
|
||||||
|
},
|
||||||
|
// 线的粗细
|
||||||
|
lineSize: {
|
||||||
|
type: Number,
|
||||||
|
default: 2
|
||||||
|
},
|
||||||
|
// 面积的颜色
|
||||||
|
color: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
// 线的颜色
|
||||||
|
lineColor: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
scale() {
|
||||||
|
return [
|
||||||
|
{ dataKey: 'x', title: this.x, alias: this.x },
|
||||||
|
{ dataKey: 'y', title: this.y, alias: this.y, min: this.min, max: this.max }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
triggerWindowResizeEvent()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
@import "chart";
|
||||||
|
</style>
|
||||||
55
src/components/chart/Bar.vue
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
<template>
|
||||||
|
<div :style="{ padding: '0 0 32px 32px' }">
|
||||||
|
<h3 :style="{ marginBottom: '20px' }">{{ title }}</h3>
|
||||||
|
<v-chart :forceFit="true" :height="height" :data="dataSource" :scale="scale" :padding="padding">
|
||||||
|
<v-tooltip/>
|
||||||
|
<v-axis/>
|
||||||
|
<v-bar position="x*y" :color="color"/>
|
||||||
|
</v-chart>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { triggerWindowResizeEvent } from '@/utils/util'
|
||||||
|
import { DEFAULT_COLOR } from "@/store/mutation-types"
|
||||||
|
import Vue from 'vue'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'Bar',
|
||||||
|
props: {
|
||||||
|
dataSource: {
|
||||||
|
type: Array,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
yaxisText: {
|
||||||
|
type: String,
|
||||||
|
default: 'y'
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
height: {
|
||||||
|
type: Number,
|
||||||
|
default: 254
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
padding: ['auto', 'auto', '40', '50'],
|
||||||
|
color: Vue.ls.get(DEFAULT_COLOR)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
scale() {
|
||||||
|
return [{
|
||||||
|
dataKey: 'y',
|
||||||
|
alias: this.yaxisText
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
triggerWindowResizeEvent()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
60
src/components/chart/BarAndLine.vue
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
<template>
|
||||||
|
<div :style="{ padding: '0 50px 32px 0' }">
|
||||||
|
<h4 :style="{ marginBottom: '20px' }">{{ title }}</h4>
|
||||||
|
<v-chart :forceFit="true" :height="height" :data="data" :scale="scale" :padding=" padding" :onClick="handleClick">
|
||||||
|
<v-tooltip/>
|
||||||
|
<v-legend/>
|
||||||
|
<v-axis/>
|
||||||
|
<v-bar position="type*bar"/>
|
||||||
|
<v-line position="type*line" color="#2fc25b" :size="3"/>
|
||||||
|
</v-chart>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { ChartEventMixins } from './mixins/ChartMixins'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'BarAndLine',
|
||||||
|
mixins: [ChartEventMixins],
|
||||||
|
props: {
|
||||||
|
title: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
dataSource: {
|
||||||
|
type: Array,
|
||||||
|
default: () => [
|
||||||
|
{ type: '10:10', bar: 200, line: 1000 },
|
||||||
|
{ type: '10:15', bar: 600, line: 1000},
|
||||||
|
{ type: '10:20', bar: 200, line: 1000},
|
||||||
|
{ type: '10:25', bar: 900, line: 1000},
|
||||||
|
{ type: '10:30', bar: 200, line: 1000},
|
||||||
|
{ type: '10:35', bar: 200, line: 1000},
|
||||||
|
{ type: '10:40', bar: 100, line: 1000}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
height: {
|
||||||
|
type: Number,
|
||||||
|
default: 400
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
padding: { top:50, right:50, bottom:100, left:50 },
|
||||||
|
scale: [{
|
||||||
|
dataKey: 'bar',
|
||||||
|
min: 0
|
||||||
|
}, {
|
||||||
|
dataKey: 'line',
|
||||||
|
min: 0
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
data() {
|
||||||
|
return this.dataSource
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
88
src/components/chart/BarMultid.vue
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
<template>
|
||||||
|
<div :style="{ padding: '0 0 32px 32px' }">
|
||||||
|
<h4 :style="{ marginBottom: '20px' }">{{ title }}</h4>
|
||||||
|
<v-chart :data="data" :height="height" :force-fit="true" :onClick="handleClick">
|
||||||
|
<v-tooltip/>
|
||||||
|
<v-axis/>
|
||||||
|
<v-legend/>
|
||||||
|
<v-bar position="x*y" color="type" :adjust="adjust"/>
|
||||||
|
</v-chart>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { DataSet } from '@antv/data-set'
|
||||||
|
import { ChartEventMixins } from './mixins/ChartMixins'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'BarMultid',
|
||||||
|
mixins: [ChartEventMixins],
|
||||||
|
props: {
|
||||||
|
title: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
dataSource: {
|
||||||
|
type: Array,
|
||||||
|
default: () => [
|
||||||
|
{ type: 'Jeecg', 'Jan.': 18.9, 'Feb.': 28.8, 'Mar.': 39.3, 'Apr.': 81.4, 'May': 47, 'Jun.': 20.3, 'Jul.': 24, 'Aug.': 35.6 },
|
||||||
|
{ type: 'Jeebt', 'Jan.': 12.4, 'Feb.': 23.2, 'Mar.': 34.5, 'Apr.': 99.7, 'May': 52.6, 'Jun.': 35.5, 'Jul.': 37.4, 'Aug.': 42.4 }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
fields: {
|
||||||
|
type: Array,
|
||||||
|
default: () => ['Jan.', 'Feb.', 'Mar.', 'Apr.', 'May', 'Jun.', 'Jul.', 'Aug.']
|
||||||
|
},
|
||||||
|
// 别名,需要的格式:[{field:'name',alias:'姓名'}, {field:'sex',alias:'性别'}]
|
||||||
|
aliases: {
|
||||||
|
type: Array,
|
||||||
|
default: () => []
|
||||||
|
},
|
||||||
|
height: {
|
||||||
|
type: Number,
|
||||||
|
default: 254
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
adjust: [{
|
||||||
|
type: 'dodge',
|
||||||
|
marginRatio: 1 / 32
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
data() {
|
||||||
|
const dv = new DataSet.View().source(this.dataSource)
|
||||||
|
dv.transform({
|
||||||
|
type: 'fold',
|
||||||
|
fields: this.fields,
|
||||||
|
key: 'x',
|
||||||
|
value: 'y'
|
||||||
|
})
|
||||||
|
|
||||||
|
// bar 使用不了 - 和 / 所以替换下
|
||||||
|
let rows = dv.rows.map(row => {
|
||||||
|
if (typeof row.x === 'string') {
|
||||||
|
row.x = row.x.replace(/[-/]/g, '_')
|
||||||
|
}
|
||||||
|
return row
|
||||||
|
})
|
||||||
|
// 替换别名
|
||||||
|
rows.forEach(row => {
|
||||||
|
for (let item of this.aliases) {
|
||||||
|
if (item.field === row.type) {
|
||||||
|
row.type = item.alias
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return rows
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
||||||
187
src/components/chart/DashChartDemo.vue
Normal file
@ -0,0 +1,187 @@
|
|||||||
|
<template>
|
||||||
|
<div :style="{ padding: '0 0 32px 32px' }">
|
||||||
|
<v-chart :forceFit="true" :height="300" :data="chartData" :scale="scale">
|
||||||
|
<v-coord type="polar" :startAngle="-202.5" :endAngle="22.5" :radius="0.75"></v-coord>
|
||||||
|
<v-axis
|
||||||
|
dataKey="value"
|
||||||
|
:zIndex="2"
|
||||||
|
:line="null"
|
||||||
|
:label="axisLabel"
|
||||||
|
:subTickCount="4"
|
||||||
|
:subTickLine="axisSubTickLine"
|
||||||
|
:tickLine="axisTickLine"
|
||||||
|
:grid="null"
|
||||||
|
></v-axis>
|
||||||
|
<v-axis dataKey="1" :show="false"></v-axis>
|
||||||
|
<v-series
|
||||||
|
gemo="point"
|
||||||
|
position="value*1"
|
||||||
|
shape="pointer"
|
||||||
|
color="#1890FF"
|
||||||
|
:active="false"
|
||||||
|
></v-series>
|
||||||
|
<v-guide
|
||||||
|
type="arc"
|
||||||
|
:zIndex="0"
|
||||||
|
:top="false"
|
||||||
|
:start="arcGuide1Start"
|
||||||
|
:end="arcGuide1End"
|
||||||
|
:vStyle="arcGuide1Style"
|
||||||
|
></v-guide>
|
||||||
|
<v-guide
|
||||||
|
type="arc"
|
||||||
|
:zIndex="1"
|
||||||
|
:start="arcGuide2Start"
|
||||||
|
:end="getArcGuide2End"
|
||||||
|
:vStyle="arcGuide2Style"
|
||||||
|
></v-guide>
|
||||||
|
<v-guide
|
||||||
|
type="html"
|
||||||
|
:position="htmlGuidePosition"
|
||||||
|
:html="getHtmlGuideHtml()"
|
||||||
|
></v-guide>
|
||||||
|
</v-chart>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { registerShape } from 'viser-vue';
|
||||||
|
|
||||||
|
registerShape('point', 'pointer', {
|
||||||
|
draw(cfg, container) {
|
||||||
|
let point = cfg.points[0];
|
||||||
|
point = this.parsePoint(point);
|
||||||
|
const center = this.parsePoint({
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
});
|
||||||
|
container.addShape('line', {
|
||||||
|
attrs: {
|
||||||
|
x1: center.x,
|
||||||
|
y1: center.y,
|
||||||
|
x2: point.x,
|
||||||
|
y2: point.y + 15,
|
||||||
|
stroke: cfg.color,
|
||||||
|
lineWidth: 5,
|
||||||
|
lineCap: 'round',
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return container.addShape('circle', {
|
||||||
|
attrs: {
|
||||||
|
x: center.x,
|
||||||
|
y: center.y,
|
||||||
|
r: 9.75,
|
||||||
|
stroke: cfg.color,
|
||||||
|
lineWidth: 4.5,
|
||||||
|
fill: '#fff',
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const scale = [{
|
||||||
|
dataKey: 'value',
|
||||||
|
min: 0,
|
||||||
|
max: 9,
|
||||||
|
tickInterval: 1,
|
||||||
|
nice: false,
|
||||||
|
}];
|
||||||
|
|
||||||
|
const data = [
|
||||||
|
{ value: 7.0 },
|
||||||
|
];
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name:"DashChartDemo",
|
||||||
|
props:{
|
||||||
|
datasource:{
|
||||||
|
type: Number,
|
||||||
|
default:7
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created(){
|
||||||
|
if(!this.datasource){
|
||||||
|
this.chartData = data;
|
||||||
|
}else{
|
||||||
|
this.chartData = [
|
||||||
|
{ value: this.datasource },
|
||||||
|
];
|
||||||
|
}
|
||||||
|
this.getChartData()
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
'datasource': function (val) {
|
||||||
|
this.chartData = [
|
||||||
|
{ value: val},
|
||||||
|
];
|
||||||
|
this.getChartData();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods:{
|
||||||
|
getChartData(){
|
||||||
|
if(this.chartData && this.chartData.length>0){
|
||||||
|
this.abcd = this.chartData[0].value * 10
|
||||||
|
}else{
|
||||||
|
this.abcd = 70
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getHtmlGuideHtml(){
|
||||||
|
return '<div style="width: 300px;text-align: center;">\n' +
|
||||||
|
'<p style="font-size: 14px;color: #545454;margin: 0;">'+this.title+'</p>\n' +
|
||||||
|
'<p style="font-size: 36px;color: #545454;margin: 0;">'+this.abcd+'%</p>\n' +
|
||||||
|
'</div>'
|
||||||
|
},
|
||||||
|
getArcGuide2End(){
|
||||||
|
return [this.chartData[0].value, 0.945]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
chartData:[],
|
||||||
|
height: 400,
|
||||||
|
scale: scale,
|
||||||
|
abcd:70,
|
||||||
|
axisLabel: {
|
||||||
|
offset: -16,
|
||||||
|
textStyle: {
|
||||||
|
fontSize: 18,
|
||||||
|
textAlign: 'center',
|
||||||
|
textBaseline: 'middle'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
axisSubTickLine: {
|
||||||
|
length: -8,
|
||||||
|
stroke: '#fff',
|
||||||
|
strokeOpacity: 1,
|
||||||
|
},
|
||||||
|
axisTickLine: {
|
||||||
|
length: -17,
|
||||||
|
stroke: '#fff',
|
||||||
|
strokeOpacity: 1,
|
||||||
|
},
|
||||||
|
arcGuide1Start: [0, 0.945],
|
||||||
|
arcGuide1End: [9, 0.945],
|
||||||
|
arcGuide1Style: {
|
||||||
|
stroke: '#CBCBCB',
|
||||||
|
lineWidth: 18,
|
||||||
|
},
|
||||||
|
arcGuide2Start: [0, 0.945],
|
||||||
|
arcGuide2Style: {
|
||||||
|
stroke: '#1890FF',
|
||||||
|
lineWidth: 18,
|
||||||
|
},
|
||||||
|
htmlGuidePosition: ['50%', '100%'],
|
||||||
|
htmlGuideHtml: `
|
||||||
|
<div style="width: 300px;text-align: center;">
|
||||||
|
<p style="font-size: 14px;color: #545454;margin: 0;">${this.title}</p>
|
||||||
|
<p style="font-size: 36px;color: #545454;margin: 0;">${this.abcd}%</p>
|
||||||
|
</div>
|
||||||
|
`,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
61
src/components/chart/IndexBar.vue
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
<template>
|
||||||
|
<div :style="{ padding: '0 0 32px 32px' }">
|
||||||
|
<h4 :style="{ marginBottom: '20px' }">{{ title }}</h4>
|
||||||
|
<v-chart
|
||||||
|
height="254"
|
||||||
|
:data="datasource"
|
||||||
|
:forceFit="true"
|
||||||
|
:padding="['auto', 'auto', '40', '50']">
|
||||||
|
<v-tooltip />
|
||||||
|
<v-axis />
|
||||||
|
<v-bar position="x*y"/>
|
||||||
|
</v-chart>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
const data = []
|
||||||
|
for (let i = 0; i < 12; i += 1) {
|
||||||
|
data.push({
|
||||||
|
x: `${i + 1}月`,
|
||||||
|
y: Math.floor(Math.random() * 1000) + 200
|
||||||
|
})
|
||||||
|
}
|
||||||
|
const tooltip = [
|
||||||
|
'x*y',
|
||||||
|
(x, y) => ({
|
||||||
|
name: x,
|
||||||
|
value: y
|
||||||
|
})
|
||||||
|
]
|
||||||
|
const scale = [{
|
||||||
|
dataKey: 'x',
|
||||||
|
min: 2
|
||||||
|
}, {
|
||||||
|
dataKey: 'y',
|
||||||
|
title: '时间',
|
||||||
|
min: 1,
|
||||||
|
max: 22
|
||||||
|
}]
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "Bar",
|
||||||
|
props: {
|
||||||
|
title: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted(){
|
||||||
|
this.datasource = data
|
||||||
|
},
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
datasource:[],
|
||||||
|
scale,
|
||||||
|
tooltip
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
94
src/components/chart/LineChartMultid.vue
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
<template>
|
||||||
|
<div :style="{ padding: '0 0 32px 32px' }">
|
||||||
|
<h4 :style="{ marginBottom: '20px' }">{{ title }}</h4>
|
||||||
|
<v-chart :force-fit="true" :height="height" :data="data" :scale="scale" :onClick="handleClick">
|
||||||
|
<v-tooltip/>
|
||||||
|
<v-axis/>
|
||||||
|
<v-legend/>
|
||||||
|
<v-line position="type*y" color="x"/>
|
||||||
|
<v-point position="type*y" color="x" :size="4" :v-style="style" :shape="'circle'"/>
|
||||||
|
</v-chart>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { DataSet } from '@antv/data-set'
|
||||||
|
import { ChartEventMixins } from './mixins/ChartMixins'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'LineChartMultid',
|
||||||
|
mixins: [ChartEventMixins],
|
||||||
|
props: {
|
||||||
|
title: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
dataSource: {
|
||||||
|
type: Array,
|
||||||
|
default: () => [
|
||||||
|
{ type: 'Jan', jeecg: 7.0, jeebt: 3.9 },
|
||||||
|
{ type: 'Feb', jeecg: 6.9, jeebt: 4.2 },
|
||||||
|
{ type: 'Mar', jeecg: 9.5, jeebt: 5.7 },
|
||||||
|
{ type: 'Apr', jeecg: 14.5, jeebt: 8.5 },
|
||||||
|
{ type: 'May', jeecg: 18.4, jeebt: 11.9 },
|
||||||
|
{ type: 'Jun', jeecg: 21.5, jeebt: 15.2 },
|
||||||
|
{ type: 'Jul', jeecg: 25.2, jeebt: 17.0 },
|
||||||
|
{ type: 'Aug', jeecg: 26.5, jeebt: 16.6 },
|
||||||
|
{ type: 'Sep', jeecg: 23.3, jeebt: 14.2 },
|
||||||
|
{ type: 'Oct', jeecg: 18.3, jeebt: 10.3 },
|
||||||
|
{ type: 'Nov', jeecg: 13.9, jeebt: 6.6 },
|
||||||
|
{ type: 'Dec', jeecg: 9.6, jeebt: 4.8 }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
fields: {
|
||||||
|
type: Array,
|
||||||
|
default: () => ['jeecg', 'jeebt']
|
||||||
|
},
|
||||||
|
// 别名,需要的格式:[{field:'name',alias:'姓名'}, {field:'sex',alias:'性别'}]
|
||||||
|
aliases:{
|
||||||
|
type: Array,
|
||||||
|
default: () => []
|
||||||
|
},
|
||||||
|
height: {
|
||||||
|
type: Number,
|
||||||
|
default: 254
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
scale: [{
|
||||||
|
dataKey: 'x',
|
||||||
|
min: 0,
|
||||||
|
max: 1
|
||||||
|
}],
|
||||||
|
style: { stroke: '#fff', lineWidth: 1 }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
data() {
|
||||||
|
const dv = new DataSet.View().source(this.dataSource)
|
||||||
|
dv.transform({
|
||||||
|
type: 'fold',
|
||||||
|
fields: this.fields,
|
||||||
|
key: 'x',
|
||||||
|
value: 'y'
|
||||||
|
})
|
||||||
|
let rows = dv.rows
|
||||||
|
// 替换别名
|
||||||
|
rows.forEach(row => {
|
||||||
|
for (let item of this.aliases) {
|
||||||
|
if (item.field === row.x) {
|
||||||
|
row.x = item.alias
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return rows
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
||||||
80
src/components/chart/Liquid.vue
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<v-chart
|
||||||
|
:forceFit="true"
|
||||||
|
:height="height"
|
||||||
|
:width="width"
|
||||||
|
:data="data"
|
||||||
|
:scale="scale"
|
||||||
|
:padding="0">
|
||||||
|
<v-tooltip/>
|
||||||
|
<v-interval
|
||||||
|
:shape="['liquid-fill-gauge']"
|
||||||
|
position="transfer*value"
|
||||||
|
color=""
|
||||||
|
:v-style="{
|
||||||
|
lineWidth: 8,
|
||||||
|
opacity: 0.75
|
||||||
|
}"
|
||||||
|
:tooltip="[
|
||||||
|
'transfer*value',
|
||||||
|
(transfer, value) => {
|
||||||
|
return {
|
||||||
|
name: transfer,
|
||||||
|
value,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
></v-interval>
|
||||||
|
<v-guide
|
||||||
|
v-for="(row, index) in data"
|
||||||
|
:key="index"
|
||||||
|
type="text"
|
||||||
|
:top="true"
|
||||||
|
:position="{
|
||||||
|
gender: row.transfer,
|
||||||
|
value: 45
|
||||||
|
}"
|
||||||
|
:content="row.value + '%'"
|
||||||
|
:v-style="{
|
||||||
|
fontSize: 100,
|
||||||
|
textAlign: 'center',
|
||||||
|
opacity: 0.75,
|
||||||
|
}"
|
||||||
|
/>
|
||||||
|
</v-chart>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
const sourceDataConst = [
|
||||||
|
{ transfer: '一月', value: 813 },
|
||||||
|
{ transfer: '二月', value: 233 },
|
||||||
|
{ transfer: '三月', value: 561 }
|
||||||
|
]
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'Liquid',
|
||||||
|
props: {
|
||||||
|
height: {
|
||||||
|
type: Number,
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
width: {
|
||||||
|
type: Number,
|
||||||
|
default: 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
data: sourceDataConst,
|
||||||
|
scale: []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
||||||
69
src/components/chart/MiniArea.vue
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
<template>
|
||||||
|
<div class="antv-chart-mini">
|
||||||
|
<div class="chart-wrapper" :style="{ height: 46 }">
|
||||||
|
<v-chart :force-fit="true" :height="height" :data="data" :scale="scale" :padding="[36, 0, 18, 0]">
|
||||||
|
<v-tooltip/>
|
||||||
|
<v-smooth-area position="x*y"/>
|
||||||
|
</v-chart>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import moment from 'dayjs'
|
||||||
|
|
||||||
|
const sourceData = []
|
||||||
|
const beginDay = new Date().getTime()
|
||||||
|
|
||||||
|
for (let i = 0; i < 10; i++) {
|
||||||
|
sourceData.push({
|
||||||
|
x: moment(new Date(beginDay + 1000 * 60 * 60 * 24 * i)).format('YYYY-MM-DD'),
|
||||||
|
y: Math.round(Math.random() * 10)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'MiniArea',
|
||||||
|
props: {
|
||||||
|
dataSource: {
|
||||||
|
type: Array,
|
||||||
|
default: () => []
|
||||||
|
},
|
||||||
|
// x 轴别名
|
||||||
|
x: {
|
||||||
|
type: String,
|
||||||
|
default: 'x'
|
||||||
|
},
|
||||||
|
// y 轴别名
|
||||||
|
y: {
|
||||||
|
type: String,
|
||||||
|
default: 'y'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
data: [],
|
||||||
|
height: 100
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
scale() {
|
||||||
|
return [
|
||||||
|
{ dataKey: 'x', title: this.x, alias: this.x },
|
||||||
|
{ dataKey: 'y', title: this.y, alias: this.y }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
if (this.dataSource.length === 0) {
|
||||||
|
this.data = sourceData
|
||||||
|
} else {
|
||||||
|
this.data = this.dataSource
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
@import "chart";
|
||||||
|
</style>
|
||||||
76
src/components/chart/MiniBar.vue
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
<template>
|
||||||
|
<div :style="{'width':width==null?'auto':width+'px'}">
|
||||||
|
<v-chart :forceFit="width==null" :height="height" :data="data" padding="0">
|
||||||
|
<v-tooltip/>
|
||||||
|
<v-bar position="x*y"/>
|
||||||
|
</v-chart>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import moment from 'dayjs'
|
||||||
|
|
||||||
|
const sourceData = []
|
||||||
|
const beginDay = new Date().getTime()
|
||||||
|
|
||||||
|
for (let i = 0; i < 10; i++) {
|
||||||
|
sourceData.push({
|
||||||
|
x: moment(new Date(beginDay + 1000 * 60 * 60 * 24 * i)).format('YYYY-MM-DD'),
|
||||||
|
y: Math.round(Math.random() * 10)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const tooltip = [
|
||||||
|
'x*y',
|
||||||
|
(x, y) => ({
|
||||||
|
name: x,
|
||||||
|
value: y
|
||||||
|
})
|
||||||
|
]
|
||||||
|
|
||||||
|
const scale = [{
|
||||||
|
dataKey: 'x',
|
||||||
|
min: 2
|
||||||
|
}, {
|
||||||
|
dataKey: 'y',
|
||||||
|
title: '时间',
|
||||||
|
min: 1,
|
||||||
|
max: 30
|
||||||
|
}]
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'MiniBar',
|
||||||
|
props: {
|
||||||
|
dataSource: {
|
||||||
|
type: Array,
|
||||||
|
default: () => []
|
||||||
|
},
|
||||||
|
width: {
|
||||||
|
type: Number,
|
||||||
|
default: null
|
||||||
|
},
|
||||||
|
height: {
|
||||||
|
type: Number,
|
||||||
|
default: 200
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
if (this.dataSource.length === 0) {
|
||||||
|
this.data = sourceData
|
||||||
|
} else {
|
||||||
|
this.data = this.dataSource
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
tooltip,
|
||||||
|
data: [],
|
||||||
|
scale
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
@import "chart";
|
||||||
|
</style>
|
||||||
75
src/components/chart/MiniProgress.vue
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
<template>
|
||||||
|
<div class="chart-mini-progress">
|
||||||
|
<div class="target" :style="{ left: target + '%'}">
|
||||||
|
<span :style="{ backgroundColor: color }"/>
|
||||||
|
<span :style="{ backgroundColor: color }"/>
|
||||||
|
</div>
|
||||||
|
<div class="progress-wrapper">
|
||||||
|
<div class="progress" :style="{ backgroundColor: color, width: percentage + '%', height: height+'px' }"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'MiniProgress',
|
||||||
|
props: {
|
||||||
|
target: {
|
||||||
|
type: Number,
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
height: {
|
||||||
|
type: Number,
|
||||||
|
default: 10
|
||||||
|
},
|
||||||
|
color: {
|
||||||
|
type: String,
|
||||||
|
default: '#13C2C2'
|
||||||
|
},
|
||||||
|
percentage: {
|
||||||
|
type: Number,
|
||||||
|
default: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.chart-mini-progress {
|
||||||
|
padding: 5px 0;
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
.target {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
|
||||||
|
span {
|
||||||
|
border-radius: 100px;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
height: 4px;
|
||||||
|
width: 2px;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
top: auto;
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.progress-wrapper {
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.progress {
|
||||||
|
transition: all .4s cubic-bezier(.08, .82, .17, 1) 0s;
|
||||||
|
border-radius: 1px 0 0 1px;
|
||||||
|
background-color: #1890ff;
|
||||||
|
width: 0;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
70
src/components/chart/Pie.vue
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
<template>
|
||||||
|
<v-chart :forceFit="true" :height="height" :data="data" :scale="scale" :onClick="handleClick">
|
||||||
|
<v-tooltip :showTitle="false" dataKey="item*percent"/>
|
||||||
|
<v-axis/>
|
||||||
|
<v-legend dataKey="item"/>
|
||||||
|
<v-pie position="percent" color="item" :v-style="pieStyle" :label="labelConfig"/>
|
||||||
|
<v-coord type="theta"/>
|
||||||
|
</v-chart>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const DataSet = require('@antv/data-set')
|
||||||
|
import { ChartEventMixins } from './mixins/ChartMixins'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'Pie',
|
||||||
|
mixins: [ChartEventMixins],
|
||||||
|
props: {
|
||||||
|
title: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
height: {
|
||||||
|
type: Number,
|
||||||
|
default: 254
|
||||||
|
},
|
||||||
|
dataSource: {
|
||||||
|
type: Array,
|
||||||
|
default: () => [
|
||||||
|
{ item: '示例一', count: 40 },
|
||||||
|
{ item: '示例二', count: 21 },
|
||||||
|
{ item: '示例三', count: 17 },
|
||||||
|
{ item: '示例四', count: 13 },
|
||||||
|
{ item: '示例五', count: 9 }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
scale: [{
|
||||||
|
dataKey: 'percent',
|
||||||
|
min: 0,
|
||||||
|
formatter: '.0%'
|
||||||
|
}],
|
||||||
|
pieStyle: {
|
||||||
|
stroke: '#fff',
|
||||||
|
lineWidth: 1
|
||||||
|
},
|
||||||
|
labelConfig: ['percent', {
|
||||||
|
formatter: (val, item) => {
|
||||||
|
return item.point.item + ': ' + val
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
data() {
|
||||||
|
let dv = new DataSet.View().source(this.dataSource)
|
||||||
|
// 计算数据百分比
|
||||||
|
dv.transform({
|
||||||
|
type: 'percent',
|
||||||
|
field: 'count',
|
||||||
|
dimension: 'item',
|
||||||
|
as: 'percent'
|
||||||
|
})
|
||||||
|
return dv.rows
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
90
src/components/chart/Radar.vue
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
<template>
|
||||||
|
<v-chart :forceFit="true" :height="height" :data="data" :padding="[20, 20, 95, 20]" :scale="scale">
|
||||||
|
<v-tooltip></v-tooltip>
|
||||||
|
<v-axis :dataKey="axis1Opts.dataKey" :line="axis1Opts.line" :tickLine="axis1Opts.tickLine" :grid="axis1Opts.grid"/>
|
||||||
|
<v-axis :dataKey="axis2Opts.dataKey" :line="axis2Opts.line" :tickLine="axis2Opts.tickLine" :grid="axis2Opts.grid"/>
|
||||||
|
<v-legend dataKey="user" marker="circle" :offset="30"/>
|
||||||
|
<v-coord type="polar" radius="0.8"/>
|
||||||
|
<v-line position="item*score" color="user" :size="2"/>
|
||||||
|
<v-point position="item*score" color="user" :size="4" shape="circle"/>
|
||||||
|
</v-chart>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const axis1Opts = {
|
||||||
|
dataKey: 'item',
|
||||||
|
line: null,
|
||||||
|
tickLine: null,
|
||||||
|
grid: {
|
||||||
|
lineStyle: {
|
||||||
|
lineDash: null
|
||||||
|
},
|
||||||
|
hideFirstLine: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const axis2Opts = {
|
||||||
|
dataKey: 'score',
|
||||||
|
line: null,
|
||||||
|
tickLine: null,
|
||||||
|
grid: {
|
||||||
|
type: 'polygon',
|
||||||
|
lineStyle: {
|
||||||
|
lineDash: null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const scale = [
|
||||||
|
{
|
||||||
|
dataKey: 'score',
|
||||||
|
min: 0,
|
||||||
|
max: 100
|
||||||
|
}, {
|
||||||
|
dataKey: 'user',
|
||||||
|
alias: '类型'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
const sourceData = [
|
||||||
|
{ item: '示例一', score: 40 },
|
||||||
|
{ item: '示例二', score: 20 },
|
||||||
|
{ item: '示例三', score: 67 },
|
||||||
|
{ item: '示例四', score: 43 },
|
||||||
|
{ item: '示例五', score: 90 }
|
||||||
|
]
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'Radar',
|
||||||
|
props: {
|
||||||
|
height: {
|
||||||
|
type: Number,
|
||||||
|
default: 254
|
||||||
|
},
|
||||||
|
dataSource: {
|
||||||
|
type: Array,
|
||||||
|
default: () => []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
axis1Opts,
|
||||||
|
axis2Opts,
|
||||||
|
scale,
|
||||||
|
data: sourceData
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
dataSource(newVal) {
|
||||||
|
if (newVal.length === 0) {
|
||||||
|
this.data = sourceData
|
||||||
|
} else {
|
||||||
|
this.data = newVal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
||||||
81
src/components/chart/RankList.vue
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
<template>
|
||||||
|
<div class="rank">
|
||||||
|
<h4 class="title">{{ title }}</h4>
|
||||||
|
<ul class="list" :style="{height:height?`${height}px`:'auto',overflow:'auto'}">
|
||||||
|
<li :key="index" v-for="(item, index) in list">
|
||||||
|
<span :class="index < 3 ? 'active' : null">{{ index + 1 }}</span>
|
||||||
|
<span>{{ item.name }}</span>
|
||||||
|
<span>{{ item.total }}</span>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: "RankList",
|
||||||
|
// ['title', 'list']
|
||||||
|
props: {
|
||||||
|
title: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
list: {
|
||||||
|
type: Array,
|
||||||
|
default: null
|
||||||
|
},
|
||||||
|
height: {
|
||||||
|
type: Number,
|
||||||
|
default: null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
|
||||||
|
.rank {
|
||||||
|
padding: 0 32px 32px 72px;
|
||||||
|
|
||||||
|
.list {
|
||||||
|
margin: 25px 0 0;
|
||||||
|
padding: 0;
|
||||||
|
list-style: none;
|
||||||
|
|
||||||
|
li {
|
||||||
|
margin-top: 16px;
|
||||||
|
|
||||||
|
span {
|
||||||
|
color: rgba(0, 0, 0, .65);
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 22px;
|
||||||
|
|
||||||
|
&:first-child {
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
border-radius: 20px;
|
||||||
|
display: inline-block;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 600;
|
||||||
|
margin-right: 24px;
|
||||||
|
height: 20px;
|
||||||
|
line-height: 20px;
|
||||||
|
width: 20px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
&.active {
|
||||||
|
background-color: #314659;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
&:last-child {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobile .rank {
|
||||||
|
padding: 0 32px 32px 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
54
src/components/chart/StackBar.vue
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<v-chart :forceFit="true" :height="height" :data="data">
|
||||||
|
<v-coord type="rect" direction="LB" />
|
||||||
|
<v-tooltip />
|
||||||
|
<v-legend />
|
||||||
|
<v-axis dataKey="State" :label="label" />
|
||||||
|
<v-stack-bar position="State*流程数量" color="流程状态" />
|
||||||
|
</v-chart>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const DataSet = require('@antv/data-set');
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'StackBar',
|
||||||
|
props: {
|
||||||
|
dataSource: {
|
||||||
|
type: Array,
|
||||||
|
required: true,
|
||||||
|
default: () => [
|
||||||
|
{ 'State': '请假', '流转中': 25, '已归档': 18 },
|
||||||
|
{ 'State': '出差', '流转中': 30, '已归档': 20 },
|
||||||
|
{ 'State': '加班', '流转中': 38, '已归档': 42},
|
||||||
|
{ 'State': '用车', '流转中': 51, '已归档': 67}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
height: {
|
||||||
|
type: Number,
|
||||||
|
default: 254
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
label: { offset: 12 }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
data() {
|
||||||
|
const dv = new DataSet.View().source(this.dataSource);
|
||||||
|
dv.transform({
|
||||||
|
type: 'fold',
|
||||||
|
fields: ['流转中', '已归档'],
|
||||||
|
key: '流程状态',
|
||||||
|
value: '流程数量',
|
||||||
|
retains: ['State'],
|
||||||
|
});
|
||||||
|
return dv.rows;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
66
src/components/chart/TransferBar.vue
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
<template>
|
||||||
|
<div :style="{ padding: '0 0 32px 32px' }">
|
||||||
|
<h4 :style="{ marginBottom: '20px' }">{{ title }}</h4>
|
||||||
|
<v-chart
|
||||||
|
:height="height"
|
||||||
|
:data="data"
|
||||||
|
:scale="scale"
|
||||||
|
:forceFit="true"
|
||||||
|
:padding="['auto', 'auto', '40', '50']">
|
||||||
|
<v-tooltip/>
|
||||||
|
<v-axis/>
|
||||||
|
<v-bar position="x*y"/>
|
||||||
|
</v-chart>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'Bar',
|
||||||
|
props: {
|
||||||
|
title: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
x: {
|
||||||
|
type: String,
|
||||||
|
default: 'x'
|
||||||
|
},
|
||||||
|
y: {
|
||||||
|
type: String,
|
||||||
|
default: 'y'
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
type: Array,
|
||||||
|
default: () => []
|
||||||
|
},
|
||||||
|
height: {
|
||||||
|
type: Number,
|
||||||
|
default: 254
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
scale() {
|
||||||
|
return [
|
||||||
|
{ dataKey: 'x', title: this.x, alias: this.x },
|
||||||
|
{ dataKey: 'y', title: this.y, alias: this.y }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
// this.getMonthBar()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
// getMonthBar() {
|
||||||
|
// this.$http.get('/analysis/month-bar')
|
||||||
|
// .then(res => {
|
||||||
|
// this.data = res.result
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
84
src/components/chart/Trend.vue
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
<template>
|
||||||
|
<div class="chart-trend">
|
||||||
|
{{ term }}
|
||||||
|
<span>{{ rate }}%</span>
|
||||||
|
<span :class="['trend-icon', trend]"><a-icon :type="'caret-' + trend"/></span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: "Trend",
|
||||||
|
props: {
|
||||||
|
// 同title
|
||||||
|
term: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
// 百分比
|
||||||
|
percentage: {
|
||||||
|
type: Number,
|
||||||
|
default: null
|
||||||
|
},
|
||||||
|
type: {
|
||||||
|
type: Boolean,
|
||||||
|
default: null
|
||||||
|
},
|
||||||
|
target: {
|
||||||
|
type: Number,
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
type: Number,
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
fixed: {
|
||||||
|
type: Number,
|
||||||
|
default: 2
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
trend: this.type && 'up' || 'down',
|
||||||
|
rate: this.percentage
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created () {
|
||||||
|
let type = this.type === null ? this.value >= this.target : this.type
|
||||||
|
this.trend = type ? 'up' : 'down';
|
||||||
|
this.rate = (this.percentage === null ? Math.abs(this.value - this.target) * 100 / this.target : this.percentage).toFixed(this.fixed)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.chart-trend {
|
||||||
|
display: inline-block;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 22px;
|
||||||
|
|
||||||
|
.trend-icon {
|
||||||
|
font-size: 12px;
|
||||||
|
|
||||||
|
&.up, &.down {
|
||||||
|
margin-left: 4px;
|
||||||
|
position: relative;
|
||||||
|
top: 1px;
|
||||||
|
|
||||||
|
i {
|
||||||
|
font-size: 12px;
|
||||||
|
transform: scale(.83);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.up {
|
||||||
|
color: #f5222d;
|
||||||
|
}
|
||||||
|
&.down {
|
||||||
|
color: #52c41a;
|
||||||
|
top: -1px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
13
src/components/chart/chart.less
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
.antv-chart-mini {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
.chart-wrapper {
|
||||||
|
position: absolute;
|
||||||
|
bottom: -28px;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
/* margin: 0 -5px;
|
||||||
|
overflow: hidden;*/
|
||||||
|
}
|
||||||
|
}
|
||||||
13
src/components/chart/chart.scss
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
.antv-chart-mini {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
.chart-wrapper {
|
||||||
|
position: absolute;
|
||||||
|
bottom: -28px;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
/* margin: 0 -5px;
|
||||||
|
overflow: hidden;*/
|
||||||
|
}
|
||||||
|
}
|
||||||
10
src/components/chart/mixins/ChartMixins.js
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
export const ChartEventMixins = {
|
||||||
|
methods: {
|
||||||
|
handleClick(event, chart) {
|
||||||
|
this.handleEvent('click', event, chart)
|
||||||
|
},
|
||||||
|
handleEvent(eventName, event, chart) {
|
||||||
|
this.$emit(eventName, event, chart)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
4
src/components/index.less
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
@import "~ant-design-vue/lib/style/index";
|
||||||
|
|
||||||
|
// The prefix to use on all css classes from ant-pro.
|
||||||
|
@ant-pro-prefix : ant-pro;
|
||||||
155
src/components/jeecg/JAreaLinkage.vue
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
<template>
|
||||||
|
<div v-if="!reloading" class="j-area-linkage">
|
||||||
|
<area-cascader
|
||||||
|
v-if="_type === enums.type[0]"
|
||||||
|
:value="innerValue"
|
||||||
|
:data="pcaa"
|
||||||
|
:level="1"
|
||||||
|
:style="{width}"
|
||||||
|
v-bind="$attrs"
|
||||||
|
v-on="_listeners"
|
||||||
|
@change="handleChange"
|
||||||
|
/>
|
||||||
|
<area-select
|
||||||
|
v-else-if="_type === enums.type[1]"
|
||||||
|
:value="innerValue"
|
||||||
|
:data="pcaa"
|
||||||
|
:level="2"
|
||||||
|
v-bind="$attrs"
|
||||||
|
v-on="_listeners"
|
||||||
|
@change="handleChange"
|
||||||
|
/>
|
||||||
|
<div v-else>
|
||||||
|
<span style="color:red;"> Bad type value: {{_type}}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { pcaa } from 'area-data'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'JAreaLinkage',
|
||||||
|
props: {
|
||||||
|
value: {
|
||||||
|
type: String,
|
||||||
|
required:false
|
||||||
|
},
|
||||||
|
// 组件的类型,可选值:
|
||||||
|
// select 下拉样式
|
||||||
|
// cascader 级联样式(默认)
|
||||||
|
type: {
|
||||||
|
type: String,
|
||||||
|
default: 'cascader'
|
||||||
|
},
|
||||||
|
width: {
|
||||||
|
type: String,
|
||||||
|
default: '100%'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
pcaa,
|
||||||
|
innerValue: [],
|
||||||
|
usedListeners: ['change'],
|
||||||
|
enums: {
|
||||||
|
type: ['cascader', 'select']
|
||||||
|
},
|
||||||
|
reloading: false,
|
||||||
|
areaData:''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
_listeners() {
|
||||||
|
let listeners = { ...this.$listeners }
|
||||||
|
// 去掉已使用的事件,防止冲突
|
||||||
|
this.usedListeners.forEach(key => {
|
||||||
|
delete listeners[key]
|
||||||
|
})
|
||||||
|
return listeners
|
||||||
|
},
|
||||||
|
_type() {
|
||||||
|
if (this.enums.type.includes(this.type)) {
|
||||||
|
return this.type
|
||||||
|
} else {
|
||||||
|
console.error(`JAreaLinkage的type属性只能接收指定的值(${this.enums.type.join('|')})`)
|
||||||
|
return this.enums.type[0]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
value: {
|
||||||
|
immediate: true,
|
||||||
|
handler() {
|
||||||
|
this.loadDataByValue(this.value)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.initAreaData();
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
/** 通过 value 反推 options */
|
||||||
|
loadDataByValue(value) {
|
||||||
|
if(!value || value.length==0){
|
||||||
|
this.innerValue = []
|
||||||
|
this.reloading = true;
|
||||||
|
setTimeout(()=>{
|
||||||
|
this.reloading = false
|
||||||
|
},100)
|
||||||
|
}else{
|
||||||
|
this.initAreaData();
|
||||||
|
let arr = this.areaData.getRealCode(value);
|
||||||
|
this.innerValue = arr
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/** 通过地区code获取子级 */
|
||||||
|
loadDataByCode(value) {
|
||||||
|
let options = []
|
||||||
|
let data = pcaa[value]
|
||||||
|
if (data) {
|
||||||
|
for (let key in data) {
|
||||||
|
if (data.hasOwnProperty(key)) {
|
||||||
|
options.push({ value: key, label: data[key], })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return options
|
||||||
|
} else {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/** 判断是否有子节点 */
|
||||||
|
hasChildren(options) {
|
||||||
|
options.forEach(option => {
|
||||||
|
let data = this.loadDataByCode(option.value)
|
||||||
|
option.isLeaf = data.length === 0
|
||||||
|
})
|
||||||
|
},
|
||||||
|
handleChange(values) {
|
||||||
|
let value = values[values.length - 1]
|
||||||
|
this.$emit('change', value)
|
||||||
|
},
|
||||||
|
initAreaData(){
|
||||||
|
if(!this.areaData){
|
||||||
|
this.areaData = new Area();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
},
|
||||||
|
model: { prop: 'value', event: 'change' },
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.j-area-linkage {
|
||||||
|
height:40px;
|
||||||
|
/deep/ .area-cascader-wrap .area-select {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/deep/ .area-select .area-selected-trigger {
|
||||||
|
line-height: 1.15;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
238
src/components/jeecg/JCategorySelect.vue
Normal file
@ -0,0 +1,238 @@
|
|||||||
|
<template>
|
||||||
|
<a-tree-select
|
||||||
|
allowClear
|
||||||
|
labelInValue
|
||||||
|
style="width: 100%"
|
||||||
|
:disabled="disabled"
|
||||||
|
:dropdownStyle="{ maxHeight: '400px', overflow: 'auto' }"
|
||||||
|
:placeholder="placeholder"
|
||||||
|
:loadData="asyncLoadTreeData"
|
||||||
|
:value="treeValue"
|
||||||
|
:treeData="treeData"
|
||||||
|
:multiple="multiple"
|
||||||
|
@change="onChange">
|
||||||
|
</a-tree-select>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
|
||||||
|
import { getAction } from '@/api/manage'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'JCategorySelect',
|
||||||
|
props: {
|
||||||
|
value:{
|
||||||
|
type: String,
|
||||||
|
required: false
|
||||||
|
},
|
||||||
|
placeholder:{
|
||||||
|
type: String,
|
||||||
|
default: '请选择',
|
||||||
|
required: false
|
||||||
|
},
|
||||||
|
disabled:{
|
||||||
|
type:Boolean,
|
||||||
|
default:false,
|
||||||
|
required:false
|
||||||
|
},
|
||||||
|
condition:{
|
||||||
|
type:String,
|
||||||
|
default:'',
|
||||||
|
required:false
|
||||||
|
},
|
||||||
|
// 是否支持多选
|
||||||
|
multiple: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
loadTriggleChange:{
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
required:false
|
||||||
|
},
|
||||||
|
pid:{
|
||||||
|
type:String,
|
||||||
|
default:'',
|
||||||
|
required:false
|
||||||
|
},
|
||||||
|
pcode:{
|
||||||
|
type:String,
|
||||||
|
default:'',
|
||||||
|
required:false
|
||||||
|
},
|
||||||
|
back:{
|
||||||
|
type:String,
|
||||||
|
default:'',
|
||||||
|
required:false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
treeValue:"",
|
||||||
|
treeData:[],
|
||||||
|
url:"/sys/category/loadTreeData",
|
||||||
|
view:'/sys/category/loadDictItem/',
|
||||||
|
tableName:"",
|
||||||
|
text:"",
|
||||||
|
code:"",
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
value () {
|
||||||
|
this.loadItemByCode()
|
||||||
|
},
|
||||||
|
pcode(){
|
||||||
|
this.loadRoot();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created(){
|
||||||
|
this.validateProp().then(()=>{
|
||||||
|
this.loadRoot()
|
||||||
|
this.loadItemByCode()
|
||||||
|
})
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
/**加载一级节点 */
|
||||||
|
loadRoot(){
|
||||||
|
let param = {
|
||||||
|
pid:this.pid,
|
||||||
|
pcode:!this.pcode?'0':this.pcode,
|
||||||
|
condition:this.condition
|
||||||
|
}
|
||||||
|
getAction(this.url,param).then(res=>{
|
||||||
|
if(res.success && res.result){
|
||||||
|
for(let i of res.result){
|
||||||
|
i.value = i.key
|
||||||
|
if(i.leaf==false){
|
||||||
|
i.isLeaf=false
|
||||||
|
}else if(i.leaf==true){
|
||||||
|
i.isLeaf=true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.treeData = [...res.result]
|
||||||
|
}else{
|
||||||
|
console.log("树一级节点查询结果-else",res)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
/** 数据回显*/
|
||||||
|
loadItemByCode(){
|
||||||
|
if(!this.value || this.value=="0"){
|
||||||
|
this.treeValue = []
|
||||||
|
}else{
|
||||||
|
getAction(this.view,{ids:this.value}).then(res=>{
|
||||||
|
if(res.success){
|
||||||
|
let values = this.value.split(',')
|
||||||
|
this.treeValue = res.result.map((item, index) => ({
|
||||||
|
key: values[index],
|
||||||
|
value: values[index],
|
||||||
|
label: item
|
||||||
|
}))
|
||||||
|
this.onLoadTriggleChange(res.result[0]);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onLoadTriggleChange(text){
|
||||||
|
//只有单选才会触发
|
||||||
|
if(!this.multiple && this.loadTriggleChange){
|
||||||
|
this.backValue(this.value,text)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
backValue(value,label){
|
||||||
|
let obj = {}
|
||||||
|
if(this.back){
|
||||||
|
obj[this.back] = label
|
||||||
|
}
|
||||||
|
this.$emit('change', value, obj)
|
||||||
|
},
|
||||||
|
asyncLoadTreeData (treeNode) {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
if (treeNode.$vnode.children) {
|
||||||
|
resolve()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let pid = treeNode.$vnode.key
|
||||||
|
let param = {
|
||||||
|
pid:pid,
|
||||||
|
condition:this.condition
|
||||||
|
}
|
||||||
|
getAction(this.url,param).then(res=>{
|
||||||
|
if(res.success){
|
||||||
|
for(let i of res.result){
|
||||||
|
i.value = i.key
|
||||||
|
if(i.leaf==false){
|
||||||
|
i.isLeaf=false
|
||||||
|
}else if(i.leaf==true){
|
||||||
|
i.isLeaf=true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.addChildren(pid,res.result,this.treeData)
|
||||||
|
this.treeData = [...this.treeData]
|
||||||
|
}
|
||||||
|
resolve()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
addChildren(pid,children,treeArray){
|
||||||
|
if(treeArray && treeArray.length>0){
|
||||||
|
for(let item of treeArray){
|
||||||
|
if(item.key == pid){
|
||||||
|
if(!children || children.length==0){
|
||||||
|
item.isLeaf=true
|
||||||
|
}else{
|
||||||
|
item.children = children
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}else{
|
||||||
|
this.addChildren(pid,children,item.children)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
onChange(value){
|
||||||
|
if(!value){
|
||||||
|
this.$emit('change', '');
|
||||||
|
this.treeValue = ''
|
||||||
|
} else if (value instanceof Array) {
|
||||||
|
//this.$emit('change', value.map(item => item.value).join(','))
|
||||||
|
//this.treeValue = value
|
||||||
|
} else {
|
||||||
|
this.backValue(value.value,value.label)
|
||||||
|
this.treeValue = value
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getCurrTreeData(){
|
||||||
|
return this.treeData
|
||||||
|
},
|
||||||
|
validateProp(){
|
||||||
|
let mycondition = this.condition
|
||||||
|
return new Promise((resolve,reject)=>{
|
||||||
|
if(!mycondition){
|
||||||
|
resolve();
|
||||||
|
}else{
|
||||||
|
try {
|
||||||
|
let test=JSON.parse(mycondition);
|
||||||
|
if(typeof test == 'object' && test){
|
||||||
|
resolve()
|
||||||
|
}else{
|
||||||
|
this.$message.error("组件JTreeSelect-condition传值有误,需要一个json字符串!")
|
||||||
|
reject()
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
this.$message.error("组件JTreeSelect-condition传值有误,需要一个json字符串!")
|
||||||
|
reject()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
//2.2新增 在组件内定义 指定父组件调用时候的传值属性和事件类型 这个牛逼
|
||||||
|
model: {
|
||||||
|
prop: 'value',
|
||||||
|
event: 'change'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
43
src/components/jeecg/JCheckbox.vue
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
<template>
|
||||||
|
<a-checkbox-group :options="options" :value="checkboxArray" v-bind="$attrs" @change="onChange" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'JCheckbox',
|
||||||
|
props: {
|
||||||
|
value:{
|
||||||
|
type: String,
|
||||||
|
required: false
|
||||||
|
},
|
||||||
|
/*label value*/
|
||||||
|
options:{
|
||||||
|
type: Array,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data(){
|
||||||
|
return {
|
||||||
|
checkboxArray:!this.value?[]:this.value.split(",")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch:{
|
||||||
|
value (val) {
|
||||||
|
if(!val){
|
||||||
|
this.checkboxArray = []
|
||||||
|
}else{
|
||||||
|
this.checkboxArray = this.value.split(",")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods:{
|
||||||
|
onChange (checkedValues) {
|
||||||
|
this.$emit('change', checkedValues.join(","));
|
||||||
|
},
|
||||||
|
},
|
||||||
|
model: {
|
||||||
|
prop: 'value',
|
||||||
|
event: 'change'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
429
src/components/jeecg/JCodeEditor.vue
Normal file
@ -0,0 +1,429 @@
|
|||||||
|
<template>
|
||||||
|
<div v-bind="fullScreenParentProps">
|
||||||
|
<a-icon v-if="fullScreen" class="full-screen-icon" :type="iconType" @click="()=>fullCoder=!fullCoder"/>
|
||||||
|
|
||||||
|
<div class="code-editor-cust full-screen-child">
|
||||||
|
<textarea ref="textarea"></textarea>
|
||||||
|
<span @click="nullTipClick" class="null-tip" :class="{'null-tip-hidden':hasCode}" :style="nullTipStyle">{{ placeholderShow }}</span>
|
||||||
|
<template v-if="languageChange">
|
||||||
|
<a-select v-model="mode" size="small" class="code-mode-select" @change="changeMode" placeholder="请选择主题">
|
||||||
|
<a-select-option
|
||||||
|
v-for="mode in modes"
|
||||||
|
:key="mode.value"
|
||||||
|
:value="mode.value">
|
||||||
|
{{ mode.label }}
|
||||||
|
</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script type="text/ecmascript-6">
|
||||||
|
// 引入全局实例
|
||||||
|
import _CodeMirror from 'codemirror'
|
||||||
|
|
||||||
|
// 核心样式
|
||||||
|
import 'codemirror/lib/codemirror.css'
|
||||||
|
// 引入主题后还需要在 options 中指定主题才会生效 darcula gruvbox-dark hopscotch monokai
|
||||||
|
import 'codemirror/theme/panda-syntax.css'
|
||||||
|
//提示css
|
||||||
|
import "codemirror/addon/hint/show-hint.css";
|
||||||
|
|
||||||
|
// 需要引入具体的语法高亮库才会有对应的语法高亮效果
|
||||||
|
// codemirror 官方其实支持通过 /addon/mode/loadmode.js 和 /mode/meta.js 来实现动态加载对应语法高亮库
|
||||||
|
// 但 vue 貌似没有无法在实例初始化后再动态加载对应 JS ,所以此处才把对应的 JS 提前引入
|
||||||
|
import 'codemirror/mode/javascript/javascript.js'
|
||||||
|
import 'codemirror/mode/css/css.js'
|
||||||
|
import 'codemirror/mode/xml/xml.js'
|
||||||
|
import 'codemirror/mode/clike/clike.js'
|
||||||
|
import 'codemirror/mode/markdown/markdown.js'
|
||||||
|
import 'codemirror/mode/python/python.js'
|
||||||
|
import 'codemirror/mode/r/r.js'
|
||||||
|
import 'codemirror/mode/shell/shell.js'
|
||||||
|
import 'codemirror/mode/sql/sql.js'
|
||||||
|
import 'codemirror/mode/swift/swift.js'
|
||||||
|
import 'codemirror/mode/vue/vue.js'
|
||||||
|
|
||||||
|
// 尝试获取全局实例
|
||||||
|
const CodeMirror = window.CodeMirror || _CodeMirror
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'JCodeEditor',
|
||||||
|
props: {
|
||||||
|
// 外部传入的内容,用于实现双向绑定
|
||||||
|
value: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
// 外部传入的语法类型
|
||||||
|
language: {
|
||||||
|
type: String,
|
||||||
|
default: null
|
||||||
|
},
|
||||||
|
languageChange:{
|
||||||
|
type: Boolean,
|
||||||
|
default:false,
|
||||||
|
required:false
|
||||||
|
},
|
||||||
|
placeholder: {
|
||||||
|
type: String,
|
||||||
|
default: null
|
||||||
|
},
|
||||||
|
// 显示行号
|
||||||
|
lineNumbers: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
// 是否显示全屏按钮
|
||||||
|
fullScreen: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
// 全屏以后的z-index
|
||||||
|
zIndex: {
|
||||||
|
type: [Number, String],
|
||||||
|
default: 999
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
// 内部真实的内容
|
||||||
|
code: '',
|
||||||
|
iconType: 'fullscreen',
|
||||||
|
hasCode:false,
|
||||||
|
// 默认的语法类型
|
||||||
|
mode: 'javascript',
|
||||||
|
// 编辑器实例
|
||||||
|
coder: null,
|
||||||
|
// 默认配置
|
||||||
|
options: {
|
||||||
|
// 缩进格式
|
||||||
|
tabSize: 2,
|
||||||
|
// 主题,对应主题库 JS 需要提前引入
|
||||||
|
theme: 'panda-syntax',
|
||||||
|
line: true,
|
||||||
|
// extraKeys: {'Ctrl': 'autocomplete'},//自定义快捷键
|
||||||
|
hintOptions: {
|
||||||
|
tables: {
|
||||||
|
users: ['name', 'score', 'birthDate'],
|
||||||
|
countries: ['name', 'population', 'size']
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// 支持切换的语法高亮类型,对应 JS 已经提前引入
|
||||||
|
// 使用的是 MIME-TYPE ,不过作为前缀的 text/ 在后面指定时写死了
|
||||||
|
modes: [{
|
||||||
|
value: 'css',
|
||||||
|
label: 'CSS'
|
||||||
|
}, {
|
||||||
|
value: 'javascript',
|
||||||
|
label: 'Javascript'
|
||||||
|
}, {
|
||||||
|
value: 'html',
|
||||||
|
label: 'XML/HTML'
|
||||||
|
}, {
|
||||||
|
value: 'x-java',
|
||||||
|
label: 'Java'
|
||||||
|
}, {
|
||||||
|
value: 'x-objectivec',
|
||||||
|
label: 'Objective-C'
|
||||||
|
}, {
|
||||||
|
value: 'x-python',
|
||||||
|
label: 'Python'
|
||||||
|
}, {
|
||||||
|
value: 'x-rsrc',
|
||||||
|
label: 'R'
|
||||||
|
}, {
|
||||||
|
value: 'x-sh',
|
||||||
|
label: 'Shell'
|
||||||
|
}, {
|
||||||
|
value: 'x-sql',
|
||||||
|
label: 'SQL'
|
||||||
|
}, {
|
||||||
|
value: 'x-swift',
|
||||||
|
label: 'Swift'
|
||||||
|
}, {
|
||||||
|
value: 'x-vue',
|
||||||
|
label: 'Vue'
|
||||||
|
}, {
|
||||||
|
value: 'markdown',
|
||||||
|
label: 'Markdown'
|
||||||
|
}],
|
||||||
|
// code 编辑器 是否全屏
|
||||||
|
fullCoder: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
fullCoder:{
|
||||||
|
handler(value) {
|
||||||
|
if(value){
|
||||||
|
this.iconType="fullscreen-exit"
|
||||||
|
}else{
|
||||||
|
this.iconType="fullscreen"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// value: {
|
||||||
|
// immediate: false,
|
||||||
|
// handler(value) {
|
||||||
|
// this._getCoder().then(() => {
|
||||||
|
// this.coder.setValue(value)
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
language: {
|
||||||
|
immediate: true,
|
||||||
|
handler(language) {
|
||||||
|
this._getCoder().then(() => {
|
||||||
|
// 尝试从父容器获取语法类型
|
||||||
|
if (language) {
|
||||||
|
// 获取具体的语法类型对象
|
||||||
|
let modeObj = this._getLanguage(language)
|
||||||
|
|
||||||
|
// 判断父容器传入的语法是否被支持
|
||||||
|
if (modeObj) {
|
||||||
|
this.mode = modeObj.label
|
||||||
|
this.coder.setOption('mode', `text/${modeObj.value}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
placeholderShow() {
|
||||||
|
if (this.placeholder == null) {
|
||||||
|
return `请在此输入${this.language}代码`
|
||||||
|
} else {
|
||||||
|
return this.placeholder
|
||||||
|
}
|
||||||
|
},
|
||||||
|
nullTipStyle(){
|
||||||
|
if (this.lineNumbers) {
|
||||||
|
return { left: '36px' }
|
||||||
|
} else {
|
||||||
|
return { left: '12px' }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// coder 配置
|
||||||
|
coderOptions() {
|
||||||
|
return {
|
||||||
|
tabSize: this.options.tabSize,
|
||||||
|
theme: this.options.theme,
|
||||||
|
lineNumbers: this.lineNumbers,
|
||||||
|
line: true,
|
||||||
|
hintOptions: this.options.hintOptions
|
||||||
|
}
|
||||||
|
},
|
||||||
|
fullScreenParentProps(){
|
||||||
|
let props = {
|
||||||
|
class: ['full-screen-parent', this.fullCoder ? 'full-screen' : ''],
|
||||||
|
style: {}
|
||||||
|
}
|
||||||
|
if (this.fullCoder) {
|
||||||
|
props.style['z-index'] = this.zIndex
|
||||||
|
}
|
||||||
|
return props
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted () {
|
||||||
|
// 初始化
|
||||||
|
this._initialize()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
// 初始化
|
||||||
|
_initialize () {
|
||||||
|
// 初始化编辑器实例,传入需要被实例化的文本域对象和默认配置
|
||||||
|
this.coder = CodeMirror.fromTextArea(this.$refs.textarea, this.coderOptions)
|
||||||
|
// 编辑器赋值
|
||||||
|
if(this.value||this.code){
|
||||||
|
this.hasCode=true
|
||||||
|
this.coder.setValue(this.value || this.code)
|
||||||
|
}else{
|
||||||
|
this.coder.setValue('')
|
||||||
|
this.hasCode=false
|
||||||
|
}
|
||||||
|
// 支持双向绑定
|
||||||
|
this.coder.on('change', (coder) => {
|
||||||
|
this.code = coder.getValue()
|
||||||
|
if(this.code){
|
||||||
|
this.hasCode=true
|
||||||
|
}else{
|
||||||
|
this.hasCode=false
|
||||||
|
}
|
||||||
|
if (this.$emit) {
|
||||||
|
this.$emit('input', this.code)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
this.coder.on('focus', () => {
|
||||||
|
this.hasCode=true
|
||||||
|
})
|
||||||
|
this.coder.on('blur', () => {
|
||||||
|
if(this.code){
|
||||||
|
this.hasCode=true
|
||||||
|
}else{
|
||||||
|
this.hasCode=false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
/* this.coder.on('cursorActivity',()=>{
|
||||||
|
this.coder.showHint()
|
||||||
|
})*/
|
||||||
|
|
||||||
|
},
|
||||||
|
getCodeContent(){
|
||||||
|
return this.code
|
||||||
|
},
|
||||||
|
setCodeContent(val){
|
||||||
|
setTimeout(()=>{
|
||||||
|
if(!val){
|
||||||
|
this.coder.setValue('')
|
||||||
|
}else{
|
||||||
|
this.coder.setValue(val)
|
||||||
|
}
|
||||||
|
},300)
|
||||||
|
},
|
||||||
|
// 获取当前语法类型
|
||||||
|
_getLanguage (language) {
|
||||||
|
// 在支持的语法类型列表中寻找传入的语法类型
|
||||||
|
return this.modes.find((mode) => {
|
||||||
|
// 所有的值都忽略大小写,方便比较
|
||||||
|
let currentLanguage = language.toLowerCase()
|
||||||
|
let currentLabel = mode.label.toLowerCase()
|
||||||
|
let currentValue = mode.value.toLowerCase()
|
||||||
|
|
||||||
|
// 由于真实值可能不规范,例如 java 的真实值是 x-java ,所以讲 value 和 label 同时和传入语法进行比较
|
||||||
|
return currentLabel === currentLanguage || currentValue === currentLanguage
|
||||||
|
})
|
||||||
|
},
|
||||||
|
_getCoder() {
|
||||||
|
let _this = this
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
(function get() {
|
||||||
|
if (_this.coder) {
|
||||||
|
resolve(_this.coder)
|
||||||
|
} else {
|
||||||
|
setTimeout(get, 10)
|
||||||
|
}
|
||||||
|
})()
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 更改模式
|
||||||
|
changeMode (val) {
|
||||||
|
// 修改编辑器的语法配置
|
||||||
|
this.coder.setOption('mode', `text/${val}`)
|
||||||
|
|
||||||
|
// 获取修改后的语法
|
||||||
|
let label = this._getLanguage(val).label.toLowerCase()
|
||||||
|
|
||||||
|
// 允许父容器通过以下函数监听当前的语法值
|
||||||
|
this.$emit('language-change', label)
|
||||||
|
},
|
||||||
|
nullTipClick(){
|
||||||
|
this.coder.focus()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less">
|
||||||
|
.code-editor-cust{
|
||||||
|
flex-grow:1;
|
||||||
|
display:flex;
|
||||||
|
position:relative;
|
||||||
|
height:100%;
|
||||||
|
.CodeMirror{
|
||||||
|
flex-grow:1;
|
||||||
|
z-index:1;
|
||||||
|
.CodeMirror-code{
|
||||||
|
line-height:19px;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
.code-mode-select{
|
||||||
|
position:absolute;
|
||||||
|
z-index:2;
|
||||||
|
right:10px;
|
||||||
|
top:10px;
|
||||||
|
max-width:130px;
|
||||||
|
}
|
||||||
|
.CodeMirror{
|
||||||
|
height: auto;
|
||||||
|
min-height:100%;
|
||||||
|
}
|
||||||
|
.null-tip{
|
||||||
|
position: absolute;
|
||||||
|
top: 4px;
|
||||||
|
left: 36px;
|
||||||
|
z-index: 10;
|
||||||
|
color: #ffffffc9;
|
||||||
|
line-height: initial;
|
||||||
|
}
|
||||||
|
.null-tip-hidden{
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 全屏样式 */
|
||||||
|
.full-screen-parent {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.full-screen-icon {
|
||||||
|
opacity: 0;
|
||||||
|
color: black;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
line-height: 24px;
|
||||||
|
background-color: white;
|
||||||
|
position: absolute;
|
||||||
|
top: 2px;
|
||||||
|
right: 2px;
|
||||||
|
z-index: 9;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: opacity 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
.full-screen-icon {
|
||||||
|
opacity: 1;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: rgba(255, 255, 255, 0.88);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.full-screen {
|
||||||
|
position: fixed;
|
||||||
|
top: 10px;
|
||||||
|
left: 10px;
|
||||||
|
width: calc(100% - 20px);
|
||||||
|
height: calc(100% - 20px);
|
||||||
|
padding: 10px;
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
|
||||||
|
.full-screen-icon {
|
||||||
|
top: 12px;
|
||||||
|
right: 12px;
|
||||||
|
}
|
||||||
|
.full-screen-child {
|
||||||
|
height: 100%;
|
||||||
|
max-height: 100%;
|
||||||
|
min-height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.full-screen-child {
|
||||||
|
min-height: 120px;
|
||||||
|
max-height: 320px;
|
||||||
|
overflow:hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-cursor{
|
||||||
|
height:18.4px !important;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
65
src/components/jeecg/JCron.vue
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
<template>
|
||||||
|
<div class="components-input-demo-presuffix">
|
||||||
|
<a-input @click="openModal" placeholder="corn表达式" v-model="cron" @change="handleOK">
|
||||||
|
<a-icon slot="prefix" type="schedule" title="corn控件"/>
|
||||||
|
<a-icon v-if="cron" slot="suffix" type="close-circle" @click="handleEmpty" title="清空"/>
|
||||||
|
</a-input>
|
||||||
|
<JCronModal ref="innerVueCron" :data="cron" @ok="handleOK"></JCronModal>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import JCronModal from "./modal/JCronModal";
|
||||||
|
export default {
|
||||||
|
name: 'JCron',
|
||||||
|
components: {
|
||||||
|
JCronModal
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
value: {
|
||||||
|
required: false,
|
||||||
|
type: String,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data(){
|
||||||
|
return {
|
||||||
|
cron: this.value,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch:{
|
||||||
|
value(val){
|
||||||
|
this.cron = val
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods:{
|
||||||
|
openModal(){
|
||||||
|
this.$refs.innerVueCron.show();
|
||||||
|
},
|
||||||
|
handleOK(val){
|
||||||
|
this.cron = val;
|
||||||
|
this.$emit("change", this.cron);
|
||||||
|
//this.$emit("change", Object.assign({}, this.cron));
|
||||||
|
},
|
||||||
|
handleEmpty(){
|
||||||
|
this.handleOK('')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
model: {
|
||||||
|
prop: 'value',
|
||||||
|
event: 'change'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style scoped>
|
||||||
|
.components-input-demo-presuffix .anticon-close-circle {
|
||||||
|
cursor: pointer;
|
||||||
|
color: #ccc;
|
||||||
|
transition: color 0.3s;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
.components-input-demo-presuffix .anticon-close-circle:hover {
|
||||||
|
color: #f5222d;
|
||||||
|
}
|
||||||
|
.components-input-demo-presuffix .anticon-close-circle:active {
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
</style>
|
||||||