This commit is contained in:
kerwincui
2024-03-17 14:59:23 +08:00
parent 3d44f4674c
commit 5539c1b6af
999 changed files with 115642 additions and 10757 deletions

View File

@@ -1,5 +1,5 @@
# 页面标题
VUE_APP_TITLE = FastBee物联网平台
VUE_APP_TITLE = FastBee物联网系统
# 开发环境配置
ENV = 'development'
@@ -13,13 +13,8 @@ VUE_CLI_BABEL_TRANSPILE_MODULES = true
# 后端接口地址
VUE_APP_SERVER_API_URL = 'http://localhost:8080'
# EMQX接口地址和账号EMQX安装默认账号密码为admin public
VUE_APP_EMQX_API_URL = 'http://localhost:8081'
VUE_APP_EMQX_API_USER_NAME = 'admin'
VUE_APP_EMQX_API_PASSWORD = 'public'
# EMQX消息服务器连接地址
VUE_APP_EMQX_SERVER_URL = 'ws://localhost:8083/mqtt'
# Mqtt消息服务器连接地址
VUE_APP_MQTT_SERVER_URL = 'ws://localhost:8083/mqtt'
# 百度地图AK
VUE_APP_BAI_DU_AK = 'nAtaBg9FYzav6c8P9rF9qXXXXXX'
VUE_APP_BAI_DU_AK = 'nAtaBg9FYzav6c8P9rF9qzsWZfT8O0PD'

View File

@@ -1,5 +1,5 @@
# 页面标题
VUE_APP_TITLE = FastBee物联网平台
VUE_APP_TITLE = FastBee物联网系统
# 生产环境配置
ENV = 'production'
@@ -7,12 +7,8 @@ ENV = 'production'
# 生产环境
VUE_APP_BASE_API = '/prod-api'
# EMQX接口账号后端地址和EMQX接口地址部署时通过nginx配置代理
VUE_APP_EMQX_API_USER_NAME = 'admin'
VUE_APP_EMQX_API_PASSWORD = 'public'
# EMQX消息服务器连接地址
VUE_APP_EMQX_SERVER_URL = 'ws://localhost:8083/mqtt'
# Mqtt消息服务器连接地址,使用空字符串则会自动获取服务器地址
VUE_APP_MQTT_SERVER_URL = ''
# 百度地图AK
VUE_APP_BAI_DU_AK = 'nAtaBg9FYzav6c8P9rF9qzsWZXXXXXX'
VUE_APP_BAI_DU_AK = 'nAtaBg9FYzav6c8P9rF9qzsWZfT8O0PD'

View File

@@ -1,5 +1,5 @@
# 页面标题
VUE_APP_TITLE = FastBee物联网平台
VUE_APP_TITLE = FastBee物联网系统
NODE_ENV = production
@@ -9,12 +9,8 @@ ENV = 'staging'
# 测试环境
VUE_APP_BASE_API = '/stage-api'
# EMQX接口账号后端地址和EMQX接口地址部署时通过nginx配置代理
VUE_APP_EMQX_API_USER_NAME = 'admin'
VUE_APP_EMQX_API_PASSWORD = 'public'
# EMQX消息服务器连接地址
VUE_APP_EMQX_SERVER_URL = 'ws://localhost:8083/mqtt'
# Mqtt消息服务器连接地址
VUE_APP_MQTT_SERVER_URL = 'ws://localhost:8083/mqtt'
# 百度地图AK
VUE_APP_BAI_DU_AK = 'nAtaBg9FYzav6c8P9rF9qzsWZXXXXXX'

View File

@@ -6,5 +6,4 @@ src/assets
public
# 忽略当前目录下为js的文件的语法检查
*.js
# 忽略当前目录下为vue的文件的语法检查
*.vue
*.vue

View File

@@ -1,4 +1,14 @@
// ESlint 检查配置
/**
*
* 规则说明见 https://cn.eslint.org/docs/rules/
* eslint-plugin-vue 规则见 https://github.com/vuejs/eslint-plugin-vue
*
* "off" 或 0 - 关闭规则
* "warn" 或 1 - 开启规则使用警告级别的错误warn (不会导致程序退出)
* "error" 或 2 - 开启规则使用错误级别的错误error (当被触发的时候,程序会退出)
*
*/
module.exports = {
root: true,
parserOptions: {
@@ -13,19 +23,20 @@ module.exports = {
extends: ['plugin:vue/recommended', 'eslint:recommended'],
// add your custom rules here
//it is base on https://github.com/vuejs/eslint-config-vue
rules: {
"vue/max-attributes-per-line": [2, {
"singleline": 10,
"multiline": {
"max": 1,
"allowFirstLine": false
'vue/max-attributes-per-line': [2, {
'singleline': 10,
'multiline': {
'max': 1,
'allowFirstLine': false
}
}],
"vue/singleline-html-element-content-newline": "off",
"vue/multiline-html-element-content-newline":"off",
"vue/name-property-casing": ["error", "PascalCase"],
"vue/no-v-html": "off",
'vue/html-self-closing': 'off',
'vue/singleline-html-element-content-newline': 'off',
'vue/multiline-html-element-content-newline': 'off',
'vue/no-template-shadow': "off",
'vue/name-property-casing': ['error', 'PascalCase'],
'vue/no-v-html': 'off',
'accessor-pairs': 2,
'arrow-spacing': [2, {
'before': true,
@@ -38,7 +49,7 @@ module.exports = {
'camelcase': [0, {
'properties': 'always'
}],
'comma-dangle': [2, 'never'],
'comma-dangle': [2, 'always-multiline'],
'comma-spacing': [2, {
'before': false,
'after': true
@@ -167,13 +178,13 @@ module.exports = {
'avoidEscape': true,
'allowTemplateLiterals': true
}],
'semi': [2, 'never'],
'semi': [2, 'always'],
'semi-spacing': [2, {
'before': false,
'after': true
}],
'space-before-blocks': [2, 'always'],
'space-before-function-paren': [2, 'never'],
'space-before-function-paren': 0,
'space-in-parens': [2, 'never'],
'space-infix-ops': 2,
'space-unary-ops': [2, {

1
vue/.gitignore vendored
View File

@@ -12,7 +12,6 @@ selenium-debug.log
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj

4
vue/.prettierignore Normal file
View File

@@ -0,0 +1,4 @@
.eslintrc.js
/dist/
/node_modules/**
/public/*

10
vue/.prettierrc.js Normal file
View File

@@ -0,0 +1,10 @@
module.exports = {
printWidth: 220,
singleQuote: true, // 使用单引号而不是双引号
semi: true, // 句尾是否加;
proseWrap: 'preserve',
tabWidth: 4,
trailingComma: 'es5', // 在对象或数组最后一个元素后面是否加逗号在ES5中加尾逗号
bracketSpacing: true, // 在对象,数组括号与文字之间加空格 "{ foo: bar }"
htmlWhitespaceSensitivity: 'ignore', // > 不乱换行
};

View File

@@ -7,6 +7,6 @@ echo.
cd %~dp0
cd ..
npm install --registry=https://registry.npm.taobao.org
npm install --registry=https://registry.npmmirror.com
pause

View File

@@ -1,16 +1,16 @@
{
"name": "fastbee",
"version": "3.8.0",
"version": "3.8.5",
"description": "FastBee物联网平台",
"author": "kerwincui",
"license": "GPL3.0",
"license": "AGPL3.0",
"scripts": {
"dev": "vue-cli-service serve",
"build:prod": "vue-cli-service build",
"build:stage": "vue-cli-service build --mode staging",
"preview": "node build/index.js --preview",
"dev": "vue-cli-service serve --open",
"build:prod": "set NODE_OPTIONS=--openssl-legacy-provider && vue-cli-service build --report",
"build:stage": "set NODE_OPTIONS=--openssl-legacy-provider && vue-cli-service build --mode staging",
"preview": "set NODE_OPTIONS=--openssl-legacy-provider && node build/index.js --preview",
"lint": "eslint --ext .js,.vue src"
},
},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
@@ -36,24 +36,28 @@
"url": "https://gitee.com/y_project/RuoYi-Vue.git"
},
"dependencies": {
"@easydarwin/easywasmplayer": "^4.0.7",
"@jiaminghi/data-view": "^2.10.0",
"@riophae/vue-treeselect": "0.4.0",
"axios": "0.24.0",
"clipboard": "2.0.6",
"clipboard": "2.0.8",
"codemirror": "^5.65.2",
"core-js": "3.19.1",
"echarts": "^5.3.1",
"element-ui": "2.15.6",
"core-js": "3.25.3",
"echarts": "5.4.0",
"element-china-area-data": "^4.1.1",
"element-ui": "2.15.10",
"file-saver": "2.0.5",
"fuse.js": "6.4.3",
"highlight.js": "9.18.5",
"js-beautify": "1.13.0",
"js-cookie": "3.0.1",
"jsencrypt": "3.2.1",
"jsencrypt": "3.0.0-rc.1",
"jshint": "^2.13.4",
"jsonlint": "^1.6.3",
"moment": "^2.29.4",
"mqtt": "^4.3.3",
"nprogress": "0.2.0",
"quill": "^1.3.7",
"quill": "1.3.7",
"screenfull": "5.0.2",
"script-loader": "^0.7.2",
"sortablejs": "1.10.2",
@@ -63,25 +67,25 @@
"vue-codemirror": "^4.0.6",
"vue-count-to": "1.0.13",
"vue-cropper": "0.5.5",
"vue-easytable": "^2.14.0",
"vue-json-viewer": "^2.2.21",
"vue-meta": "2.4.0",
"vue-qr": "^4.0.9",
"vue-router": "3.4.9",
"vue-seamless-scroll": "^1.1.23",
"vuedraggable": "2.24.3",
"vuex": "3.6.0",
"@jiaminghi/data-view": "^2.10.0",
"vue-easytable": "^2.14.0",
"vue-seamless-scroll": "^1.1.23"
"vuex": "3.6.0"
},
"devDependencies": {
"@vue/cli-plugin-babel": "4.4.6",
"@vue/cli-plugin-eslint": "4.4.6",
"@vue/cli-service": "4.4.6",
"babel-eslint": "10.1.0",
"babel-plugin-dynamic-import-node": "^2.3.3",
"chalk": "4.1.0",
"compression-webpack-plugin": "5.0.2",
"connect": "3.6.6",
"eslint": "7.15.0",
"eslint": "^7.28.0",
"eslint-plugin-vue": "7.2.0",
"lint-staged": "10.5.3",
"runjs": "4.4.2",
@@ -89,8 +93,7 @@
"sass-loader": "10.1.1",
"script-ext-html-webpack-plugin": "2.1.5",
"svg-sprite-loader": "5.1.1",
"vue-template-compiler": "2.6.12",
"mockjs": "^1.1.0"
"vue-template-compiler": "2.6.12"
},
"engines": {
"node": ">=8.9",

View File

@@ -1,15 +1,18 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="renderer" content="webkit">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<script src="./js/echarts.min.js"></script>
<title><%= webpackConfig.name %></title>
<!--[if lt IE 11]><script>window.location.href='/html/ie.html';</script><![endif]-->
<style>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="renderer" content="webkit">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title>
<%= webpackConfig.name %>
</title>
<!--[if lt IE 11]><script>window.location.href='/html/ie.html';</script><![endif]-->
<style>
html,
body,
#app {
@@ -17,6 +20,7 @@
margin: 0px;
padding: 0px;
}
.chromeframe {
margin: 0.2em 0;
background: #ccc;
@@ -93,6 +97,7 @@
-ms-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
-ms-transform: rotate(360deg);
@@ -106,6 +111,7 @@
-ms-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
-ms-transform: rotate(360deg);
@@ -194,20 +200,30 @@
color: #FFF;
opacity: 0.5;
}
img {
max-width: 100%;
}
/* 清除地图LOGO */
/* .BMap_cpyCtrl {
display: none!important;
}
.anchorBL {
display: none!important;
} */
</style>
</head>
<body>
<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>
</head>
<body>
<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>
</html>

View File

@@ -1,15 +1,19 @@
<template>
<div id="app" style="background-color:#03050C" v-if="$route.meta.bigScreen">
<div id="app" style="background-color:#0e2e87" v-if="$route.meta.bigScreen">
<router-view />
</div>
<div id="app" v-else>
<router-view />
<theme-picker />
</div>
</template>
<script>
export default {
name: 'App',
import ThemePicker from "@/components/ThemePicker";
export default {
name: "App",
components: { ThemePicker },
metaInfo() {
return {
title: this.$store.state.settings.dynamicTitle && this.$store.state.settings.title,
@@ -18,5 +22,10 @@ export default {
}
}
}
}
};
</script>
<style scoped>
#app .theme-picker {
display: none;
}
</style>

View File

@@ -1,127 +1,146 @@
import request from '@/utils/request'
import request from '@/utils/request';
// 查询设备列表
export function listDevice(query) {
return request({
url: '/iot/device/list',
method: 'get',
params: query
})
return request({
url: '/iot/device/list',
method: 'get',
params: query,
});
}
// 查询未授权设备列表
export function listUnAuthDevice(query) {
return request({
url: '/iot/device/unAuthlist',
method: 'get',
params: query
})
return request({
url: '/iot/device/unAuthlist',
method: 'get',
params: query,
});
}
// 查询分组可添加设备分页列表
export function listDeviceByGroup(query) {
return request({
url: '/iot/device/listByGroup',
method: 'get',
params: query
})
return request({
url: '/iot/device/listByGroup',
method: 'get',
params: query,
});
}
// 查询设备简短列表
export function listDeviceShort(query) {
return request({
url: '/iot/device/shortList',
method: 'get',
params: query
})
return request({
url: '/iot/device/shortList',
method: 'get',
params: query,
});
}
// 查询所有设备简短列表
export function listAllDeviceShort() {
return request({
url: '/iot/device/all',
method: 'get',
})
return request({
url: '/iot/device/all',
method: 'get',
});
}
// 查询设备详细
export function getDevice(deviceId) {
return request({
url: '/iot/device/' + deviceId,
method: 'get'
})
return request({
url: '/iot/device/' + deviceId,
method: 'get',
});
}
// 设备数据同步
export function deviceSynchronization(serialNumber) {
return request({
url: '/iot/device/synchronization/' + serialNumber,
method: 'get'
})
return request({
url: '/iot/device/synchronization/' + serialNumber,
method: 'get',
});
}
// 根据设备编号查询设备详细
export function getDeviceBySerialNumber(serialNumber) {
return request({
url: '/iot/device/getDeviceBySerialNumber/' + serialNumber,
method: 'get'
})
return request({
url: '/iot/device/getDeviceBySerialNumber/' + serialNumber,
method: 'get',
});
}
// 查询设备统计信息
export function getDeviceStatistic() {
return request({
url: '/iot/device/statistic',
method: 'get'
})
return request({
url: '/iot/device/statistic',
method: 'get',
});
}
// 查询设备运行状态详细
export function getDeviceRunningStatus(deviceId) {
return request({
url: '/iot/device/runningStatus/' + deviceId,
method: 'get'
})
export function getDeviceRunningStatus(params) {
return request({
url: '/iot/device/runningStatus',
method: 'get',
params: params,
});
}
// 查询设备物模型的值
export function getDeviceThingsModelValue(deviceId) {
return request({
url: '/iot/device/thingsModelValue/' + deviceId,
method: 'get'
})
return request({
url: '/iot/device/thingsModelValue/' + deviceId,
method: 'get',
});
}
// 新增设备
export function addDevice(data) {
return request({
url: '/iot/device',
method: 'post',
data: data
})
return request({
url: '/iot/device',
method: 'post',
data: data,
});
}
// 修改设备
export function updateDevice(data) {
return request({
url: '/iot/device',
method: 'put',
data: data
})
return request({
url: '/iot/device',
method: 'put',
data: data,
});
}
// 删除设备
export function delDevice(deviceId) {
return request({
url: '/iot/device/' + deviceId,
method: 'delete'
})
return request({
url: '/iot/device/' + deviceId,
method: 'delete',
});
}
// 生成设备编号
export function generatorDeviceNum() {
return request({
url: '/iot/device/generator',
method: 'get'
})
}
export function generatorDeviceNum(params) {
return request({
url: '/iot/device/generator',
method: 'get',
params: params,
});
}
export function getGwDevCode(params) {
return request({
url: '/iot/device/gwDevCount',
method: 'get',
params: params,
});
}
//mqtt连接参数查看
export function getMqttConnect(params) {
return request({
url: '/iot/device/getMqttConnectData',
method: 'get',
params: params,
});
}

View File

@@ -18,6 +18,15 @@ export function listMonitor(query) {
})
}
// 查询设备监测数据
export function listHistory(query) {
return request({
url: '/iot/deviceLog/history',
method: 'get',
params: query
})
}
// 查询设备日志详细
export function getDeviceLog(logId) {
return request({

View File

@@ -1,20 +1,29 @@
import request from '@/utils/request'
import request from '@/utils/request';
// 查询设备用户列表
export function listDeviceUser(query) {
return request({
url: '/iot/deviceUser/list',
method: 'get',
params: query
})
params: query,
});
}
// 查询设备用户详细
export function getDeviceUser(deviceId, userId) {
return request({
url: '/iot/deviceUser/' + deviceId + '/' + userId,
method: 'get'
})
method: 'get',
});
}
// 查询用户
export function shareUser(query) {
return request({
url: '/iot/deviceUser/shareUser',
method: 'get',
params: query,
});
}
// 新增设备用户
@@ -22,8 +31,8 @@ export function addDeviceUser(data) {
return request({
url: '/iot/deviceUser',
method: 'post',
data: data
})
data: data,
});
}
// 新增多个设备用户
@@ -31,8 +40,8 @@ export function addDeviceUsers(data) {
return request({
url: '/iot/deviceUser/addDeviceUsers',
method: 'post',
data: data
})
data: data,
});
}
// 修改设备用户
@@ -40,8 +49,8 @@ export function updateDeviceUser(data) {
return request({
url: '/iot/deviceUser',
method: 'put',
data: data
})
data: data,
});
}
// 删除设备用户
@@ -49,6 +58,6 @@ export function delDeviceUser(device) {
return request({
url: '/iot/deviceUser',
method: 'delete',
data: device
})
data: device,
});
}

View File

@@ -0,0 +1,45 @@
import request from '@/utils/request'
// 查询事件日志列表
export function listEventLog(query) {
return request({
url: '/iot/event/list',
method: 'get',
params: query
})
}
// 查询事件日志详细
export function getEventLog(logId) {
return request({
url: '/iot/event/' + logId,
method: 'get'
})
}
// 新增事件日志
export function addEventLog(data) {
return request({
url: '/iot/event',
method: 'post',
data: data
})
}
// 修改事件日志
export function updateEventLog(data) {
return request({
url: '/iot/event',
method: 'put',
data: data
})
}
// 删除事件日志
export function delLog(logId) {
return request({
url: '/iot/event/' + logId,
method: 'delete'
})
}

View File

@@ -0,0 +1,44 @@
import request from '@/utils/request'
// 查询设备服务下发日志列表
export function listLog(query) {
return request({
url: '/iot/log/list',
method: 'get',
params: query
})
}
// 查询设备服务下发日志详细
export function getLog(id) {
return request({
url: '/iot/log/' + id,
method: 'get'
})
}
// 新增设备服务下发日志
export function addLog(data) {
return request({
url: '/iot/log',
method: 'post',
data: data
})
}
// 修改设备服务下发日志
export function updateLog(data) {
return request({
url: '/iot/log',
method: 'put',
data: data
})
}
// 删除设备服务下发日志
export function delLog(id) {
return request({
url: '/iot/log/' + id,
method: 'delete'
})
}

View File

@@ -1,20 +1,28 @@
import request from '@/utils/request'
import request from '@/utils/request';
// 查询物模型列表
export function listModel(query) {
return request({
url: '/iot/model/list',
method: 'get',
params: query
})
params: query,
});
}
// 查询物模型详细
export function getModel(modelId) {
return request({
url: '/iot/model/' + modelId,
method: 'get'
})
method: 'get',
});
}
// 查询物模型对应分享设备用户权限列表
export function permListModel(productId) {
return request({
url: '/iot/model/permList/' + productId,
method: 'get',
});
}
// 新增物模型
@@ -22,8 +30,8 @@ export function addModel(data) {
return request({
url: '/iot/model',
method: 'post',
data: data
})
data: data,
});
}
// 导入通用物模型
@@ -31,8 +39,8 @@ export function importModel(data) {
return request({
url: '/iot/model/import',
method: 'post',
data: data
})
data: data,
});
}
// 修改物模型
@@ -40,22 +48,31 @@ export function updateModel(data) {
return request({
url: '/iot/model',
method: 'put',
data: data
})
data: data,
});
}
// 删除物模型
export function delModel(modelId) {
return request({
url: '/iot/model/' + modelId,
method: 'delete'
})
method: 'delete',
});
}
// 根据产品ID获取缓存的物模型
export function cacheJsonThingsModel(productId){
export function cacheJsonThingsModel(productId) {
return request({
url: '/iot/model/cache/' + productId,
method: 'get'
})
method: 'get',
});
}
// 同步采集点模板到产品物模型
export function synchron(data) {
return request({
url: '/iot/model/synchron',
method: 'post',
data: data,
});
}

36
vue/src/api/iot/netty.js Normal file
View File

@@ -0,0 +1,36 @@
import request from '@/utils/request'
// 集群下所有客户端列表
export function listNettyMqttClient(query) {
return request({
url: '/iot/mqtt/clients',
method: 'get',
params: query
})
}
export function clientOut(query) {
return request({
url: '/iot/mqtt/client/out',
method: 'get',
params: query
})
}
export function getNettyMqttStats() {
return request({
url: '/bashBoard/stats',
method: 'get',
})
}
export function statisticNettyMqtt(query) {
return request({
url: '/bashBoard/metrics',
method: 'get',
params: query
})
}

62
vue/src/api/iot/point.js Normal file
View File

@@ -0,0 +1,62 @@
import request from '@/utils/request'
// 查询变量模板从机采集点列表
export function listPoint(query) {
return request({
url: '/iot/point/list',
method: 'get',
params: query
})
}
// 查询变量模板从机采集点详细
export function getPoint(id) {
return request({
url: '/iot/point/' + id,
method: 'get'
})
}
// 新增变量模板从机采集点
export function addPoint(data) {
return request({
url: '/iot/point',
method: 'post',
data: data
})
}
// 修改变量模板从机采集点
export function updatePoint(data) {
return request({
url: '/iot/point',
method: 'put',
data: data
})
}
// 删除变量模板从机采集点
export function delPoint(id) {
return request({
url: '/iot/point/' + id,
method: 'delete'
})
}
//根据从机id删除采集点数据
export function delBySlaveId(data){
return request({
url: '/iot/point/delBySlaveId',
method: 'delete',
data: data,
})
}
//..
export function selectByTemp(query){
return request({
url: '/iot/point/getPoints',
method: 'get',
params: query
})
}

View File

@@ -43,6 +43,14 @@ export function updateProduct(data) {
})
}
// 获取产品下设备的数量
export function deviceCount(productId) {
return request({
url: '/iot/product/deviceCount/' + productId,
method: 'get'
})
}
// 更新产品状态
export function changeProductStatus(data) {
return request({
@@ -59,3 +67,12 @@ export function delProduct(productId) {
method: 'delete'
})
}
// 根据采集点模板id查询所有产品
export function selectByTempleId(params) {
return request({
url: '/iot/product/queryByTemplateId',
method: 'get',
params: params
})
}

View File

@@ -0,0 +1,44 @@
import request from '@/utils/request'
// 查询协议列表
export function listProtocol(query) {
return request({
url: '/iot/protocol/list',
method: 'get',
params: query
})
}
// 查询协议详细
export function getProtocol(id) {
return request({
url: '/iot/protocol/' + id,
method: 'get'
})
}
// 新增协议
export function addProtocol(data) {
return request({
url: '/iot/protocol',
method: 'post',
data: data
})
}
// 修改协议
export function updateProtocol(data) {
return request({
url: '/iot/protocol',
method: 'put',
data: data
})
}
// 删除协议
export function delProtocol(id) {
return request({
url: '/iot/protocol/' + id,
method: 'delete'
})
}

View File

@@ -0,0 +1,29 @@
import request from '@/utils/request'
//查询设备实时数据
export function runStatus(params) {
return request({
url: '/iot/runtime/runState',
method: 'get',
params: params,
})
}
//查询设备实时数据
export function serviceInvoke(data) {
return request({
url: '/iot/runtime/service/invoke',
method: 'post',
data: data,
})
}
//查询设备服务下发日志
export function funcLog(params) {
return request({
url: '/iot/runtime/funcLog',
method: 'get',
params: params,
})
}

53
vue/src/api/iot/salve.js Normal file
View File

@@ -0,0 +1,53 @@
import request from '@/utils/request'
// 查询变量模板设备从机列表
export function listSalve(query) {
return request({
url: '/iot/salve/list',
method: 'get',
params: query
})
}
// 查询变量模板设备从机详细
export function getSalve(id) {
return request({
url: '/iot/salve/' + id,
method: 'get'
})
}
// 新增变量模板设备从机
export function addSalve(data) {
return request({
url: '/iot/salve',
method: 'post',
data: data
})
}
// 修改变量模板设备从机
export function updateSalve(data) {
return request({
url: '/iot/salve',
method: 'put',
data: data
})
}
// 删除变量模板设备从机
export function delSalve(id) {
return request({
url: '/iot/salve/' + id,
method: 'delete'
})
}
//根据产品id查询从机列表
export function listByPid(params){
return request({
url: "/iot/salve/listByPId",
method: 'get',
params: params,
})
}

62
vue/src/api/iot/temp.js Normal file
View File

@@ -0,0 +1,62 @@
import request from '@/utils/request'
// 查询设备采集变量模板列表
export function listTemp(query) {
return request({
url: '/iot/temp/list',
method: 'get',
params: query
})
}
// 查询设备采集变量模板详细
export function getTemp(templateId) {
return request({
url: '/iot/temp/' + templateId,
method: 'get'
})
}
// 新增设备采集变量模板
export function addTemp(data) {
return request({
url: '/iot/temp',
method: 'post',
data: data
})
}
// 修改设备采集变量模板
export function updateTemp(data) {
return request({
url: '/iot/temp',
method: 'put',
data: data
})
}
// 删除设备采集变量模板
export function delTemp(templateId) {
return request({
url: '/iot/temp/' + templateId,
method: 'delete'
})
}
//根据产品查询采集点关联
export function getDeviceTemp(params){
return request({
url: '/iot/temp/getTemp' ,
method: 'get',
params: params,
})
}
export function getTempByPId(params){
return request({
url: '/iot/temp/getTempByPid',
method: 'get',
params: params,
})
}

View File

@@ -42,3 +42,12 @@ export function delTemplate(templateId) {
method: 'delete'
})
}
// 查询通用物模型详细
export function getAllPoints(params) {
return request({
url: '/iot/template/getPoints',
method: 'get',
params: params,
})
}

View File

@@ -27,3 +27,24 @@ export function listUser(query) {
params: query
})
}
// 获取所有下发的topic
export function getTopics(params){
return request({
url: '/iot/tool/getTopics',
method: 'get',
params: params,
})
}
// 获取所有下发的topic
export function decode(params){
return request({
url: '/iot/tool/decode',
method: 'get',
params: params,
})
}

View File

@@ -1,4 +1,4 @@
import request from '@/utils/request'
import request from '@/utils/request';
// 登录方法
export function login(username, password, code, uuid) {
@@ -6,16 +6,16 @@ export function login(username, password, code, uuid) {
username,
password,
code,
uuid
}
uuid,
};
return request({
url: '/login',
headers: {
isToken: false
isToken: false,
},
method: 'post',
data: data
})
data: data,
});
}
// 注册方法
@@ -23,18 +23,34 @@ export function register(data) {
return request({
url: '/register',
headers: {
isToken: false
isToken: false,
},
method: 'post',
data: data
})
data: data,
});
}
// 获取用户详细信息
export function getInfo() {
return request({
url: '/getInfo',
method: 'get'
method: 'get',
});
}
// 检查BindID
export function checkBindId(bindId) {
return request({
url: '/auth/checkBindId/' + bindId,
method: 'get',
});
}
// 微信绑定获取结果信息
export function getWxBindMsg(wxBindMsgId) {
return request({
url: '/wechat/getWxBindMsg?wxBindMsgId=' + wxBindMsgId,
method: 'get',
})
}
@@ -42,8 +58,8 @@ export function getInfo() {
export function logout() {
return request({
url: '/logout',
method: 'post'
})
method: 'post',
});
}
// 获取验证码
@@ -51,64 +67,41 @@ export function getCodeImg() {
return request({
url: '/captchaImage',
headers: {
isToken: false
isToken: false,
},
method: 'get',
timeout: 20000
})
timeout: 20000,
});
}
//查看是否存在bindId
export function checkBindId(bindId) {
// 微信登录直接跳转登录
export function socialLogin(loginId) {
return request({
url: '/auth/checkBindId/' + bindId,
url: '/auth/login/' + loginId,
method: 'get',
})
});
}
//查看是否存在errorId
export function getErrorMsg(errorId) {
return request({
url: '/auth/getErrorMsg/' + errorId,
method: 'get',
})
}
// 登录方法
export function bindLogin(username, password, code, uuid, bindId) {
const data = {
username,
password,
code,
uuid,
bindId
}
// 微信登录绑定登录
export function bindLogin(data) {
return request({
url: '/auth/bind/login',
headers: {
isToken: false
isToken: false,
},
method: 'post',
data: data
})
data: data,
});
}
// 注册方法
// 三方登录注册绑定
export function bindRegister(data) {
return request({
url: '/auth/bind/register',
headers: {
isToken: false
isToken: false,
},
method: 'post',
data: data
})
}
//跳转登录
export function redirectLogin(loginId) {
return request({
url: '/auth/login/' + loginId,
method: 'get',
})
timeout: 20000,
data: data,
});
}

View File

@@ -7,3 +7,51 @@ export function getCache() {
method: 'get'
})
}
// 查询缓存名称列表
export function listCacheName() {
return request({
url: '/monitor/cache/getNames',
method: 'get'
})
}
// 查询缓存键名列表
export function listCacheKey(cacheName) {
return request({
url: '/monitor/cache/getKeys/' + cacheName,
method: 'get'
})
}
// 查询缓存内容
export function getCacheValue(cacheName, cacheKey) {
return request({
url: '/monitor/cache/getValue/' + cacheName + '/' + cacheKey,
method: 'get'
})
}
// 清理指定名称缓存
export function clearCacheName(cacheName) {
return request({
url: '/monitor/cache/clearCacheName/' + cacheName,
method: 'delete'
})
}
// 清理指定键名缓存
export function clearCacheKey(cacheKey) {
return request({
url: '/monitor/cache/clearCacheKey/' + cacheKey,
method: 'delete'
})
}
// 清理全部缓存
export function clearCacheAll() {
return request({
url: '/monitor/cache/clearCacheAll',
method: 'delete'
})
}

View File

@@ -17,6 +17,14 @@ export function delLogininfor(infoId) {
})
}
// 解锁用户登录状态
export function unlockLogininfor(userName) {
return request({
url: '/monitor/logininfor/unlock/' + userName,
method: 'get'
})
}
// 清空登录日志
export function cleanLogininfor() {
return request({

View File

@@ -25,22 +25,6 @@ export function getDept(deptId) {
})
}
// 查询部门下拉树结构
export function treeselect() {
return request({
url: '/system/dept/treeselect',
method: 'get'
})
}
// 根据角色ID查询部门树结构
export function roleDeptTreeselect(roleId) {
return request({
url: '/system/dept/roleDeptTreeselect/' + roleId,
method: 'get'
})
}
// 新增部门
export function addDept(data) {
return request({

View File

@@ -108,4 +108,12 @@ export function authUserSelectAll(data) {
method: 'put',
params: data
})
}
}
// 根据角色ID查询部门树结构
export function deptTreeSelect(roleId) {
return request({
url: '/system/role/deptTree/' + roleId,
method: 'get'
})
}

View File

@@ -1,5 +1,5 @@
import request from '@/utils/request'
import { praseStrEmpty } from "@/utils/ruoyi";
import { parseStrEmpty } from "@/utils/ruoyi";
// 查询用户列表
export function listUser(query) {
@@ -13,7 +13,7 @@ export function listUser(query) {
// 查询用户详细
export function getUser(userId) {
return request({
url: '/system/user/' + praseStrEmpty(userId),
url: '/system/user/' + parseStrEmpty(userId),
method: 'get'
})
}
@@ -69,7 +69,21 @@ export function changeUserStatus(userId, status) {
data: data
})
}
// 获取微信二维码
export function getLoginParam() {
return request({
url: '/wechat/getWxBindQr',
method: 'get',
});
}
// 解除绑定
export function secureBind(data) {
return request({
url: '/wechat/cancelBind',
method: 'post',
data:data
})
}
// 查询用户个人信息
export function getUserProfile() {
return request({
@@ -125,3 +139,11 @@ export function updateAuthRole(data) {
params: data
})
}
// 查询部门下拉树结构
export function deptTreeSelect() {
return request({
url: '/system/user/deptTree',
method: 'get'
})
}

View File

@@ -0,0 +1,44 @@
import request from '@/utils/request'
// 查询文件存储配置列表
export function listOssConfig(query) {
return request({
url: '/oss/ossConfig/list',
method: 'get',
params: query
})
}
// 查询文件存储配置详细
export function getOssConfig(id) {
return request({
url: '/oss/ossConfig/' + id,
method: 'get'
})
}
// 新增文件存储配置
export function addOssConfig(data) {
return request({
url: '/oss/ossConfig',
method: 'post',
data: data
})
}
// 修改文件存储配置
export function updateOssConfig(data) {
return request({
url: '/oss/ossConfig',
method: 'put',
data: data
})
}
// 删除文件存储配置
export function delOssConfig(id) {
return request({
url: '/oss/ossConfig/' + id,
method: 'delete'
})
}

View File

@@ -0,0 +1,44 @@
import request from '@/utils/request'
// 查询文件记录列表
export function listOssDetail(query) {
return request({
url: '/oss/OssDetail/list',
method: 'get',
params: query
})
}
// 查询文件记录详细
export function getOssDetail(id) {
return request({
url: '/oss/OssDetail/' + id,
method: 'get'
})
}
// 新增文件记录
export function addOssDetail(data) {
return request({
url: '/oss/OssDetail',
method: 'post',
data: data
})
}
// 修改文件记录
export function updateOssDetail(data) {
return request({
url: '/oss/OssDetail',
method: 'put',
data: data
})
}
// 删除文件记录
export function delOssDetail(id) {
return request({
url: '/oss/OssDetail/' + id,
method: 'delete'
})
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.8 KiB

After

Width:  |  Height:  |  Size: 9.3 KiB

View File

@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1696736330576" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6319" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M512.42 920.16c-88.25 0-176.5-6.43-264.14-19.28l-0.26-0.04c-30.68-4.81-61.57-21.45-86.98-46.85-25.41-25.41-42.05-56.3-46.85-86.98l-0.04-0.26a1818.793 1818.793 0 0 1 0-528.28l0.04-0.26c4.81-30.68 21.44-61.57 46.85-86.98 25.41-25.41 56.3-42.05 86.98-46.85l0.26-0.04a1818.793 1818.793 0 0 1 528.28 0l0.26 0.04c30.68 4.81 61.57 21.44 86.98 46.85s42.05 56.3 46.85 86.98l0.04 0.26a1818.793 1818.793 0 0 1 0 528.28l-0.04 0.26c-4.81 30.68-21.44 61.57-46.85 86.98-25.41 25.41-56.3 42.05-86.98 46.85l-0.26 0.04a1820.45 1820.45 0 0 1-264.14 19.28z m-256.03-73.69c169.89 24.91 342.15 24.91 512.05 0 39.74-6.3 81.56-48.12 87.86-87.86 24.9-169.87 24.9-342.16 0-512.03-6.3-39.75-48.12-81.57-87.86-87.86a1764.188 1764.188 0 0 0-512.03 0c-39.74 6.3-81.57 48.12-87.86 87.86a1764.188 1764.188 0 0 0 0 512.03c6.28 39.74 48.1 81.56 87.84 87.86z" fill="#64A0CF" p-id="6320"></path><path d="M626.33 337.19L416.49 547.03c-10.19 10.19-26.72 10.19-36.92 0l-12.58-12.58c-10.19-10.19-10.19-26.72 0-36.92l209.84-209.84c10.19-10.19 26.72-10.19 36.92 0l12.58 12.58c10.19 10.19 10.19 26.72 0 36.92z" fill="#9EEFD9" p-id="6321"></path><path d="M627.01 731.07l-12.58 12.58c-10.19 10.19-26.72 10.19-36.92 0L367.67 533.81c-10.19-10.19-10.19-26.72 0-36.92l12.58-12.58c10.19-10.19 26.72-10.19 36.92 0l209.84 209.84c10.19 10.2 10.19 26.72 0 36.92z" fill="#9EEFD9" p-id="6322"></path></svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1676963808794" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="11069" width="128" height="128" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M885.1 962.6H139.5c-42.2 0-76.6-34.3-76.6-76.6V140.4c0-42.2 34.3-76.6 76.6-76.6h745.6c42.2 0 76.6 34.3 76.6 76.6V886c-0.1 42.2-34.4 76.6-76.6 76.6zM139.5 110.5c-16.5 0-30 13.4-30 30V886c0 16.5 13.4 30 30 30h745.6c16.5 0 30-13.4 30-30V140.4c0-16.5-13.4-30-30-30H139.5z" fill="#1890ff" p-id="11070"></path><path d="M745.3 536.5h-466c-12.9 0-23.3-10.4-23.3-23.3s10.4-23.3 23.3-23.3h466c12.9 0 23.3 10.4 23.3 23.3s-10.4 23.3-23.3 23.3z" fill="#1890ff" p-id="11071"></path><path d="M512.3 769.5c-12.9 0-23.3-10.4-23.3-23.3v-466c0-12.9 10.4-23.3 23.3-23.3s23.3 10.4 23.3 23.3v466c0 12.9-10.4 23.3-23.3 23.3z" fill="#1890ff" p-id="11072"></path></svg>

After

Width:  |  Height:  |  Size: 978 B

View File

@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1667669082784" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="14339" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><path d="M853.333333 682.666667a128 128 0 0 0-73.813333 23.893333l-104.533333-61.866667A159.573333 159.573333 0 0 0 682.666667 597.333333a170.666667 170.666667 0 0 0-128-164.693333V333.653333a128 128 0 1 0-85.333334 0v98.986667A170.666667 170.666667 0 0 0 341.333333 597.333333c0.170667 16.085333 2.730667 32.042667 7.68 47.36l-104.533333 61.866667A128 128 0 0 0 170.666667 682.666667a128 128 0 1 0 128 128 128 128 0 0 0-5.12-34.133334l98.133333-58.453333a170.666667 170.666667 0 0 0 240.64 0l98.133333 58.453333A128 128 0 1 0 853.333333 682.666667zM170.666667 853.333333a42.666667 42.666667 0 1 1 0-85.333333 42.666667 42.666667 0 0 1 0 85.333333z m341.333333-682.666666a42.666667 42.666667 0 1 1 0 85.333333 42.666667 42.666667 0 0 1 0-85.333333z m0 512a85.333333 85.333333 0 1 1 0-170.666667 85.333333 85.333333 0 0 1 0 170.666667z m341.333333 170.666666a42.666667 42.666667 0 1 1 0-85.333333 42.666667 42.666667 0 0 1 0 85.333333z" p-id="14340"></path></svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1667669857229" class="icon" viewBox="0 0 1102 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="15177" xmlns:xlink="http://www.w3.org/1999/xlink" width="137.75" height="128"><path d="M117.208615 703.015385V551.384615L0 530.668308v482.540307l117.208615-41.432615v-165.415385H303.261538L385.969231 682.456615l-103.424-62.070153-48.206769 82.707692H117.208615zM1102.769231 551.384615L261.907692 0H165.415385L34.422154 206.769231V275.692308l751.300923 482.461538 62.070154-6.931692L1102.769231 551.384615zM34.422154 317.046154v110.276923l758.232615 475.608615h68.844308l34.500923-34.500923 34.422154-103.424s-96.413538 69.001846-103.345231 69.001846C792.654769 806.360615 34.422154 317.046154 34.422154 317.046154z" p-id="15178"></path></svg>

After

Width:  |  Height:  |  Size: 892 B

View File

@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1695807499295" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3428" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M853.3248 1024H170.6752C76.8 1024 0 947.2 0 853.3248V170.6752C0 76.8 76.8 0 170.6752 0h682.6496C947.2 0 1024 76.8 1024 170.6752v682.6496C1024 947.2 947.2 1024 853.3248 1024z" fill="#3AC2B5" p-id="3429"></path><path d="M785.92 479.5648c-5.12-3.4048-11.0848-3.4048-17.0752-1.6896l-81.0496 35.84v-72.5504c0-19.6096-15.36-34.9696-34.9952-34.9696H265.3952c-9.3952 0-17.92 3.4048-24.7552 10.24-6.8352 6.8096-10.24 15.36-10.24 24.7296v281.6C230.4 742.4 245.76 757.76 265.3952 757.76H652.8c19.6352 0 34.9952-15.36 34.9952-34.9952V670.72l81.0496 35.84c5.12 2.56 11.9552 1.7152 17.0752-1.7152 5.12-3.4048 7.68-8.5248 7.68-14.4896V494.08c0-5.9648-3.4048-11.0848-7.68-14.5152zM551.2448 596.48l-114.3296 65.7152c-5.12 2.56-11.1104 2.56-16.2304 0a16.512 16.512 0 0 1-8.5248-14.5152v-130.56c0-5.9648 3.4048-11.0848 8.5248-14.5152 5.12-2.56 11.1104-2.56 16.2304 0l114.3296 65.7152c5.12 2.56 8.5504 8.5248 8.5504 14.5152-0.8704 5.12-3.4304 11.0848-8.5504 13.6448z m-47.7696-207.36a62.72 62.72 0 0 1-53.76-30.72 60.8768 60.8768 0 0 1 0-61.44 62.72 62.72 0 0 1 53.76-30.72 61.184 61.184 0 0 1 61.44 61.44 61.184 61.184 0 0 1-61.44 61.44z m-123.7504 0a44.6208 44.6208 0 0 1-44.3648-44.3648c0-23.9104 19.6352-44.3904 44.3648-44.3904 23.9104 0 44.3904 19.6352 44.3904 44.3904 0 24.7296-19.6352 44.3648-44.3904 44.3648z" fill="#FFFFFF" p-id="3430"></path></svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 18 KiB

View File

@@ -0,0 +1,2 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1656035183065" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3395" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css">@font-face { font-family: feedback-iconfont; src: url("//at.alicdn.com/t/font_1031158_u69w8yhxdu.woff2?t=1630033759944") format("woff2"), url("//at.alicdn.com/t/font_1031158_u69w8yhxdu.woff?t=1630033759944") format("woff"), url("//at.alicdn.com/t/font_1031158_u69w8yhxdu.ttf?t=1630033759944") format("truetype"); }
</style></defs><path d="M958.88 730.06H65.12c-18.28 0-33.12-14.82-33.12-33.12V68.91c0-18.29 14.83-33.12 33.12-33.12h893.77c18.28 0 33.12 14.82 33.12 33.12v628.03c-0.01 18.3-14.84 33.12-33.13 33.12zM98.23 663.83h827.53v-561.8H98.23v561.8z" p-id="3396"></path><path d="M512 954.55c-18.28 0-33.12-14.82-33.12-33.12V733.92c0-18.29 14.83-33.12 33.12-33.12s33.12 14.82 33.12 33.12v187.51c0 18.3-14.84 33.12-33.12 33.12z" p-id="3397"></path><path d="M762.01 988.21H261.99c-18.28 0-33.12-14.82-33.12-33.12 0-18.29 14.83-33.12 33.12-33.12h500.03c18.28 0 33.12 14.82 33.12 33.12-0.01 18.29-14.84 33.12-33.13 33.12zM514.74 578.55c-21.63 0-43.31-3.87-64.21-11.65-45.95-17.13-82.49-51.13-102.86-95.74-5.07-11.08-0.19-24.19 10.89-29.26 11.08-5.09 24.19-0.18 29.26 10.91 15.5 33.88 43.25 59.7 78.14 72.71 34.93 12.99 72.79 11.64 106.66-3.85 33.22-15.17 58.8-42.26 72.03-76.3 4.42-11.37 17.21-17.01 28.57-12.58 11.36 4.42 16.99 17.22 12.57 28.58-17.42 44.82-51.1 80.5-94.82 100.47-24.34 11.12-50.25 16.71-76.23 16.71z" p-id="3398"></path><path d="M325.27 528.78c-1.66 0-3.34-0.18-5.02-0.57-11.88-2.77-19.28-14.63-16.49-26.51l18.84-81c1.34-5.82 5-10.84 10.13-13.92 5.09-3.09 11.3-3.96 17.03-2.41l80.51 21.43c11.79 3.14 18.8 15.23 15.67 27.02-3.15 11.79-15.42 18.75-27.02 15.65l-58.49-15.57-13.69 58.81c-2.37 10.2-11.45 17.07-21.47 17.07zM360.8 351.01c-2.65 0-5.37-0.49-8-1.51-11.36-4.41-16.99-17.21-12.59-28.57 17.4-44.79 51.06-80.47 94.8-100.48 92.15-42.06 201.25-1.39 243.31 90.68 5.07 11.08 0.19 24.19-10.89 29.26-11.13 5.07-24.19 0.17-29.26-10.91-31.97-69.91-114.9-100.82-184.79-68.86-33.22 15.19-58.8 42.28-71.99 76.29-3.41 8.74-11.75 14.1-20.59 14.1z" p-id="3399"></path><path d="M684.68 376.74c-1.47 0-2.95-0.15-4.42-0.44l-81.61-16.68c-11.94-2.45-19.64-14.11-17.21-26.06 2.44-11.96 14.1-19.64 26.04-17.22l59.29 12.12 10.23-59.5c2.05-12 13.52-20.19 25.48-18.01 12.03 2.06 20.09 13.48 18.02 25.5l-14.08 81.96a22.089 22.089 0 0 1-9.29 14.49c-3.7 2.51-8.03 3.84-12.45 3.84z" p-id="3400"></path></svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1676963891061" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="18978" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><path d="M877.1 950.7H148.9c-41.2 0-74.8-33.5-74.8-74.8V147.6c0-41.2 33.5-74.8 74.8-74.8h728.3c41.2 0 74.8 33.5 74.8 74.8v728.3c-0.1 41.3-33.6 74.8-74.9 74.8zM148.9 118.4c-16.1 0-29.3 13.1-29.3 29.3V876c0 16.1 13.1 29.3 29.3 29.3h728.3c16.1 0 29.3-13.1 29.3-29.3V147.6c0-16.1-13.1-29.3-29.3-29.3H148.9z" fill="#1890ff" p-id="18979"></path><path d="M740.6 534.6H285.4c-12.6 0-22.8-10.2-22.8-22.8s10.2-22.8 22.8-22.8h455.2c12.6 0 22.8 10.2 22.8 22.8s-10.2 22.8-22.8 22.8z" fill="#1890ff" p-id="18980"></path></svg>

After

Width:  |  Height:  |  Size: 837 B

View File

@@ -1 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1569580729849" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1939" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M513.3 958.5c-142.2 0-397.9-222.1-401.6-440.5V268c1.7-39.6 31.7-72.3 71.1-77.3 49-4.6 97.1-16.5 142.7-35.3 47.8-14 91.9-38.3 129.4-71.1 30.3-24.4 72.9-26.3 105.3-4.6 39.9 30.7 83.8 55.9 130.5 74.6 48.6 14.7 98.2 25.9 148.4 33.7 38.5 7.6 67.1 40.3 69.5 79.5 3.3 84.9 2.5 169.9-2.6 254.7-33.7 281.6-253.7 436.4-392.7 436.3z m-0.1-813.7c-7.2-0.2-14.3 2-20 6.4-39.7 35.2-86.8 61.1-137.7 75.7-46.8 19.2-96.2 31-146.6 35.2-11 3.2-18.8 13-19.5 24.4v230.1c3.5 180.3 223.3 361 323.9 361s287.3-120.2 317.6-360.5c7.3-142.7 0-228.6 0-229.6-1.3-13.3-11-24.3-24-27.3-49.6-7.7-98.6-19-146.5-33.7-46.3-19.5-89.7-45.3-129-76.7-5.8-3.8-12.7-5.5-19.5-4.9l1.3-0.1z" fill="#fff" p-id="1940"></path><path d="M750.1 428L490.7 673.2c-11.7 11.1-29.5 12.9-43.1 4.2l-6.8-5.8-141.2-149.4c-9.3-9.3-12.7-22.9-9-35.5 3.8-12.6 14.1-22.1 27-24.8 12.9-2.7 26.1 1.9 34.6 11.9L469 597.5l233.7-221c14.6-12.8 36.8-11.6 49.9 2.7 13.2 14.2 11.5 35.3-2.5 48.8" fill="#fff" p-id="1941"></path></svg>
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1569580729849" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1939" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M513.3 958.5c-142.2 0-397.9-222.1-401.6-440.5V268c1.7-39.6 31.7-72.3 71.1-77.3 49-4.6 97.1-16.5 142.7-35.3 47.8-14 91.9-38.3 129.4-71.1 30.3-24.4 72.9-26.3 105.3-4.6 39.9 30.7 83.8 55.9 130.5 74.6 48.6 14.7 98.2 25.9 148.4 33.7 38.5 7.6 67.1 40.3 69.5 79.5 3.3 84.9 2.5 169.9-2.6 254.7-33.7 281.6-253.7 436.4-392.7 436.3z m-0.1-813.7c-7.2-0.2-14.3 2-20 6.4-39.7 35.2-86.8 61.1-137.7 75.7-46.8 19.2-96.2 31-146.6 35.2-11 3.2-18.8 13-19.5 24.4v230.1c3.5 180.3 223.3 361 323.9 361s287.3-120.2 317.6-360.5c7.3-142.7 0-228.6 0-229.6-1.3-13.3-11-24.3-24-27.3-49.6-7.7-98.6-19-146.5-33.7-46.3-19.5-89.7-45.3-129-76.7-5.8-3.8-12.7-5.5-19.5-4.9l1.3-0.1z" fill="#999" p-id="1940"></path><path d="M750.1 428L490.7 673.2c-11.7 11.1-29.5 12.9-43.1 4.2l-6.8-5.8-141.2-149.4c-9.3-9.3-12.7-22.9-9-35.5 3.8-12.6 14.1-22.1 27-24.8 12.9-2.7 26.1 1.9 34.6 11.9L469 597.5l233.7-221c14.6-12.8 36.8-11.6 49.9 2.7 13.2 14.2 11.5 35.3-2.5 48.8" fill="#999" p-id="1941"></path></svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1694102575985" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4034" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M937.6 326.4c-20.8-28.8-60.8-35.2-89.6-16l-64 44.8V352c0-88-72-160-160-160H240C152 192 80 264 80 352v320c0 88 72 160 160 160h384c84.8 0 153.6-65.6 160-147.2l65.6 44.8c11.2 8 24 11.2 36.8 11.2 35.2 0 64-28.8 64-64V363.2c-1.6-12.8-4.8-25.6-12.8-36.8zM720 672c0 52.8-43.2 96-96 96H240c-52.8 0-96-43.2-96-96V352c0-52.8 43.2-96 96-96h384c52.8 0 96 43.2 96 96v320z m164.8 4.8L784 606.4V433.6l100.8-70.4v313.6z" fill="#cdcdcd" p-id="4035"></path><path d="M288 400m-48 0a48 48 0 1 0 96 0 48 48 0 1 0-96 0Z" fill="#cdcdcd" p-id="4036"></path></svg>

After

Width:  |  Height:  |  Size: 872 B

View File

@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1695808416395" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6545" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M760.3712 954.624H274.1248c-107.264 0-194.2016-86.9376-194.2016-194.2016V274.1248c0-107.264 86.9376-194.2016 194.2016-194.2016h486.2464c107.264 0 194.2016 86.9376 194.2016 194.2016v486.2464c0.0512 107.264-86.9376 194.2528-194.2016 194.2528z" fill="#6FA7FF" p-id="6546"></path><path d="M830.208 346.2656c-17.7664-10.24-38.912-10.24-56.6784 0l-52.6848 30.4128v-8.6528c0-66.048-53.7088-119.7568-119.7568-119.7568H311.2448c-66.048 0-119.7568 53.7088-119.7568 119.7568v300.1856c0 66.048 53.7088 119.7568 119.7568 119.7568h172.6464c14.1312 0 25.6-11.4688 25.6-25.6s-11.4688-25.6-25.6-25.6H311.2448c-37.7856 0-68.5568-30.7712-68.5568-68.5568V368.0256c0-37.7856 30.7712-68.5568 68.5568-68.5568h289.8944c37.7856 0 68.5568 30.7712 68.5568 68.5568v300.1856c0 37.7856-30.7712 68.5568-68.5568 68.5568-14.1312 0-25.6 11.4688-25.6 25.6s11.4688 25.6 25.6 25.6c66.048 0 119.7568-53.7088 119.7568-119.7568v-8.6528l52.6848 30.4128c8.8576 5.12 18.5856 7.68 28.3136 7.68 9.728 0 19.456-2.56 28.3136-7.68 17.7152-10.24 28.3136-28.5696 28.3136-49.1008V395.3664c0.0512-20.48-10.5472-38.8608-28.3136-49.1008z m-22.8352 294.6048c0 2.6112-1.4848 3.9936-2.7136 4.7104-1.2288 0.7168-3.2256 1.3312-5.4784 0l-78.2848-45.2096V435.8144l78.2848-45.2096c2.2528-1.28 4.1984-0.7168 5.4784 0 1.2288 0.7168 2.7136 2.1504 2.7136 4.7104v245.5552z" fill="#F7F8F8" p-id="6547"></path><path d="M323.0208 363.6224c-14.1312 0-25.6 11.4688-25.6 25.6s11.4688 25.6 25.6 25.6H425.984c14.1312 0 25.6-11.4688 25.6-25.6s-11.4688-25.6-25.6-25.6H323.0208z" fill="#F7F8F8" p-id="6548"></path></svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

View File

@@ -0,0 +1,39 @@
<?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">
<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="配置面板" width="48" height="40" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="setting-copy-2" width="48" height="40" transform="translate(-1190.000000, -136.000000)">
<g id="Group-8" width="48" height="40" 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="0" y="0" width="48" height="10"></rect>
<rect id="Rectangle-18" fill="#ff6b03" mask="url(#mask-3)" x="0" y="0" width="16" height="40"></rect>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

View File

@@ -17,7 +17,7 @@ $--button-font-weight: 400;
$--border-color-light: #dfe4ed;
$--border-color-lighter: #e6ebf5;
$--table-border:1px solid#dfe6ec;
$--table-border: 1px solid #dfe6ec;
/* icon font path, required */
$--font-path: '~element-ui/lib/theme-chalk/fonts';

View File

@@ -124,8 +124,28 @@ aside {
padding: 20px;
}
.card-margin-bottom{
margin-bottom: 6px;
}
.card-padding-bottom{
padding-bottom: 100px;
}
.form-item-right{
float: right;
}
.form-minus-bomttom{
margin-bottom: -20px;
}
.big-box-padding{
padding: 6px;
}
.components-container {
margin: 30px 50px;
margin: 10px;
position: relative;
}

View File

@@ -37,7 +37,7 @@
.mb10 {
margin-bottom: 10px;
}
.ml0 {
.ml10 {
margin-left: 10px;
}
.mt20 {
@@ -49,7 +49,7 @@
.mb20 {
margin-bottom: 20px;
}
.m20 {
.ml20 {
margin-left: 20px;
}
@@ -60,6 +60,10 @@
color: inherit;
}
.el-message-box__status + .el-message-box__message{
word-break: break-word;
}
.el-dialog:not(.is-fullscreen) {
margin-top: 6vh !important;
}
@@ -135,9 +139,8 @@
}
/** 表格更多操作下拉样式 */
.el-table .el-dropdown-link {
.el-table .el-dropdown-link,.el-table .el-dropdown-selfdefine {
cursor: pointer;
color: #409EFF;
margin-left: 5px;
}
@@ -250,9 +253,10 @@
}
.avatar-upload-preview {
position: absolute;
position: relative;
top: 50%;
transform: translate(50%, -50%);
left: 50%;
transform: translate(-50%, -50%);
width: 200px;
height: 200px;
border-radius: 50%;
@@ -271,3 +275,18 @@
position: relative;
float: right;
}
/* 修改switch按钮样式 */
.el-switch__core{
width:45px!important;
height:22px;
border-radius:2px;
}
.el-switch__core:after{
width:20px;
height:18px;
border-radius:2px;
}
.el-switch.is-checked .el-switch__core::after{
margin-left:-21px;
}

View File

@@ -7,6 +7,10 @@
position: relative;
}
.sidebarHide {
margin-left: 0!important;
}
.sidebar-container {
-webkit-transition: width .28s;
transition: width 0.28s;

View File

@@ -12,11 +12,16 @@
}
/* fade-transform */
.fade-transform--move,
.fade-transform-leave-active,
.fade-transform-enter-active {
transition: all .5s;
}
.fade-transform-leave-active {
position: absolute;
}
.fade-transform-enter {
opacity: 0;
transform: translateX(-30px);

View File

@@ -89,7 +89,6 @@ export default {
this.editor.on("inputRead", () => {
this.editor.showHint();
});
debugger;
this.editor.setSize("auto", this.height);
if (typeof this.value !== "undefined") {
this.editor.setValue(this.value);
@@ -126,4 +125,4 @@ export default {
.json-editor >>> .cm-s-rubyblue span.cm-string {
color: #f08047;
}
</style>
</style>

View File

@@ -26,7 +26,7 @@
<el-radio v-model='radioValue' :label="4">
指定
<el-select clearable v-model="checkboxList" placeholder="可多选" multiple style="width:100%">
<el-option v-for="item in 60" :key="item" :value="item-1">{{item-1}}</el-option>
<el-option v-for="item in 24" :key="item" :value="item-1">{{item-1}}</el-option>
</el-select>
</el-radio>
</el-form-item>
@@ -111,4 +111,4 @@ export default {
}
}
}
</script>
</script>

View File

@@ -273,7 +273,7 @@ export default {
insValue = 5;
} else {
this.$refs[refName].checkboxList = value.split(",");
insValue = 7;
insValue = 6;
}
} else if (name == "year") {
if (value == "") {

View File

@@ -60,7 +60,7 @@
<el-radio v-model='radioValue' :label="6">
指定
<el-select clearable v-model="checkboxList" placeholder="可多选" multiple style="width:100%">
<el-option v-for="(item,index) of weekList" :key="index" :label="item.value" :value="item.key">{{item.value}}</el-option>
<el-option v-for="(item,index) of weekList" :key="index" :label="item.value" :value="String(item.key)">{{item.value}}</el-option>
</el-select>
</el-radio>
</el-form-item>

View File

@@ -1,7 +1,23 @@
import Vue from 'vue'
import store from '@/store'
import DataDict from '@/utils/dict'
import { getDicts as getDicts } from '@/api/system/dict/data'
function searchDictByKey(dict, key) {
if (key == null && key == "") {
return null
}
try {
for (let i = 0; i < dict.length; i++) {
if (dict[i].key == key) {
return dict[i].value
}
}
} catch (e) {
return null
}
}
function install() {
Vue.use(DataDict, {
metas: {
@@ -9,7 +25,19 @@ function install() {
labelField: 'dictLabel',
valueField: 'dictValue',
request(dictMeta) {
return getDicts(dictMeta.type).then(res => res.data)
const storeDict = searchDictByKey(store.getters.dict, dictMeta.type)
if (storeDict) {
return new Promise(resolve => { resolve(storeDict) })
} else {
return new Promise((resolve, reject) => {
getDicts(dictMeta.type).then(res => {
store.dispatch('dict/setDict', { key: dictMeta.type, value: res.data })
resolve(res.data)
}).catch(error => {
reject(error)
})
})
}
},
},
},

View File

@@ -1,9 +1,20 @@
<template>
<div>
<el-upload :action="uploadUrl" :before-upload="handleBeforeUpload" :on-success="handleUploadSuccess" :on-error="handleUploadError" name="file" :show-file-list="false" :headers="headers" style="display: none" ref="upload" v-if="this.type == 'url'">
<div>
<el-upload
:action="uploadUrl"
:before-upload="handleBeforeUpload"
:on-success="handleUploadSuccess"
:on-error="handleUploadError"
name="file"
:show-file-list="false"
:headers="headers"
style="display: none"
ref="upload"
v-if="this.type == 'url'"
>
</el-upload>
<div class="editor" ref="editor" :style="styles"></div>
</div>
</div>
</template>
<script>
@@ -11,290 +22,251 @@ import Quill from "quill";
import "quill/dist/quill.core.css";
import "quill/dist/quill.snow.css";
import "quill/dist/quill.bubble.css";
import {
getToken
} from "@/utils/auth";
import { getToken } from "@/utils/auth";
export default {
name: "Editor",
props: {
/* 编辑器的内容 */
value: {
type: String,
default: "",
},
/* 高度 */
height: {
type: Number,
default: null,
},
/* 最小高度 */
minHeight: {
type: Number,
default: null,
},
/* 只读 */
readOnly: {
type: Boolean,
default: false,
},
// 上传文件大小限制(MB)
fileSize: {
type: Number,
default: 5,
},
/* 类型base64格式、url格式 */
type: {
type: String,
default: "url",
}
name: "Editor",
props: {
/* 编辑器的内容 */
value: {
type: String,
default: "",
},
data() {
return {
uploadUrl: process.env.VUE_APP_BASE_API + "/common/upload", // 上传的图片服务器地址
headers: {
Authorization: "Bearer " + getToken()
},
Quill: null,
currentValue: "",
options: {
theme: "snow",
bounds: document.body,
debug: "warn",
modules: {
// 工具栏配置
toolbar: [
["bold", "italic", "underline", "strike"], // 加粗 斜体 下划线 删除线
["blockquote", "code-block"], // 引用 代码块
[{
list: "ordered"
}, {
list: "bullet"
}], // 有序、无序列表
[{
indent: "-1"
}, {
indent: "+1"
}], // 缩进
[{
size: ["small", false, "large", "huge"]
}], // 字体大小
[{
header: [1, 2, 3, 4, 5, 6, false]
}], // 标题
[{
color: []
}, {
background: []
}], // 字体颜色、字体背景颜色
[{
align: []
}], // 对齐方式
["clean"], // 清除文本格式
["link", "image", "video"] // 链接、图片、视频
],
},
placeholder: "请输入内容",
readOnly: this.readOnly,
},
};
/* 高度 */
height: {
type: Number,
default: null,
},
computed: {
styles() {
let style = {};
if (this.minHeight) {
style.minHeight = `${this.minHeight}px`;
}
if (this.height) {
style.height = `${this.height}px`;
}
return style;
/* 最小高度 */
minHeight: {
type: Number,
default: null,
},
/* 只读 */
readOnly: {
type: Boolean,
default: false,
},
// 上传文件大小限制(MB)
fileSize: {
type: Number,
default: 5,
},
/* 类型base64格式、url格式 */
type: {
type: String,
default: "url",
}
},
data() {
return {
uploadUrl: process.env.VUE_APP_BASE_API + "/common/upload", // 上传的图片服务器地址
headers: {
Authorization: "Bearer " + getToken()
},
Quill: null,
currentValue: "",
options: {
theme: "snow",
bounds: document.body,
debug: "warn",
modules: {
// 工具栏配置
toolbar: [
["bold", "italic", "underline", "strike"], // 加粗 斜体 下划线 删除线
["blockquote", "code-block"], // 引用 代码块
[{ list: "ordered" }, { list: "bullet" }], // 有序、无序列表
[{ indent: "-1" }, { indent: "+1" }], // 缩进
[{ size: ["small", false, "large", "huge"] }], // 字体大小
[{ header: [1, 2, 3, 4, 5, 6, false] }], // 标题
[{ color: [] }, { background: [] }], // 字体颜色、字体背景颜色
[{ align: [] }], // 对齐方式
["clean"], // 清除文本格式
["link", "image", "video"] // 链接、图片、视频
],
},
placeholder: "请输入内容",
readOnly: this.readOnly,
},
};
},
computed: {
styles() {
let style = {};
if (this.minHeight) {
style.minHeight = `${this.minHeight}px`;
}
if (this.height) {
style.height = `${this.height}px`;
}
return style;
},
watch: {
value: {
handler(val) {
if (val !== this.currentValue) {
this.currentValue = val === null ? "" : val;
if (this.Quill) {
this.Quill.pasteHTML(this.currentValue);
}
}
},
immediate: true,
},
},
mounted() {
this.init();
},
beforeDestroy() {
this.Quill = null;
},
methods: {
init() {
const editor = this.$refs.editor;
this.Quill = new Quill(editor, this.options);
// 如果设置了上传地址则自定义图片上传事件
if (this.type == 'url') {
let toolbar = this.Quill.getModule("toolbar");
toolbar.addHandler("image", (value) => {
this.uploadType = "image";
if (value) {
this.$refs.upload.$children[0].$refs.input.click();
} else {
this.quill.format("image", false);
}
});
}
},
watch: {
value: {
handler(val) {
if (val !== this.currentValue) {
this.currentValue = val === null ? "" : val;
if (this.Quill) {
this.Quill.pasteHTML(this.currentValue);
this.Quill.on("text-change", (delta, oldDelta, source) => {
const html = this.$refs.editor.children[0].innerHTML;
const text = this.Quill.getText();
const quill = this.Quill;
this.currentValue = html;
this.$emit("input", html);
this.$emit("on-change", {
html,
text,
quill
});
});
this.Quill.on("text-change", (delta, oldDelta, source) => {
this.$emit("on-text-change", delta, oldDelta, source);
});
this.Quill.on("selection-change", (range, oldRange, source) => {
this.$emit("on-selection-change", range, oldRange, source);
});
this.Quill.on("editor-change", (eventName, ...args) => {
this.$emit("on-editor-change", eventName, ...args);
});
},
// 上传前校检格式和大小
handleBeforeUpload(file) {
// 校检文件大小
if (this.fileSize) {
const isLt = file.size / 1024 / 1024 < this.fileSize;
if (!isLt) {
this.$message.error(`上传文件大小不能超过 ${this.fileSize} MB!`);
return false;
}
}
return true;
},
handleUploadSuccess(res, file) {
// 获取富文本组件实例
let quill = this.Quill;
// 如果上传成功
if (res.code == 200) {
// 获取光标所在位置
let length = quill.getSelection().index;
// 插入图片 res.url为服务器返回的图片地址
quill.insertEmbed(length, "image", process.env.VUE_APP_BASE_API + res.fileName);
// 调整光标到最后
quill.setSelection(length + 1);
} else {
this.$message.error("图片插入失败");
}
},
handleUploadError() {
this.$message.error("图片插入失败");
},
}
}
},
immediate: true,
},
},
mounted() {
this.init();
},
beforeDestroy() {
this.Quill = null;
},
methods: {
init() {
const editor = this.$refs.editor;
this.Quill = new Quill(editor, this.options);
// 如果设置了上传地址则自定义图片上传事件
if (this.type == 'url') {
let toolbar = this.Quill.getModule("toolbar");
toolbar.addHandler("image", (value) => {
this.uploadType = "image";
if (value) {
this.$refs.upload.$children[0].$refs.input.click();
} else {
this.quill.format("image", false);
}
});
}
this.Quill.pasteHTML(this.currentValue);
this.Quill.on("text-change", (delta, oldDelta, source) => {
const html = this.$refs.editor.children[0].innerHTML;
const text = this.Quill.getText();
const quill = this.Quill;
this.currentValue = html;
this.$emit("input", html);
this.$emit("on-change", { html, text, quill });
});
this.Quill.on("text-change", (delta, oldDelta, source) => {
this.$emit("on-text-change", delta, oldDelta, source);
});
this.Quill.on("selection-change", (range, oldRange, source) => {
this.$emit("on-selection-change", range, oldRange, source);
});
this.Quill.on("editor-change", (eventName, ...args) => {
this.$emit("on-editor-change", eventName, ...args);
});
},
// 上传前校检格式和大小
handleBeforeUpload(file) {
// 校检文件大小
if (this.fileSize) {
const isLt = file.size / 1024 / 1024 < this.fileSize;
if (!isLt) {
this.$message.error(`上传文件大小不能超过 ${this.fileSize} MB!`);
return false;
}
}
return true;
},
handleUploadSuccess(res, file) {
// 获取富文本组件实例
let quill = this.Quill;
// 如果上传成功
if (res.code == 200) {
// 获取光标所在位置
let length = quill.getSelection().index;
// 插入图片 res.url为服务器返回的图片地址
quill.insertEmbed(length, "image", process.env.VUE_APP_BASE_API + res.fileName);
// 调整光标到最后
quill.setSelection(length + 1);
} else {
this.$message.error("图片插入失败");
}
},
handleUploadError() {
this.$message.error("图片插入失败");
},
},
};
</script>
<style>
.editor,
.ql-toolbar {
white-space: pre-wrap !important;
line-height: normal !important;
.editor, .ql-toolbar {
white-space: pre-wrap !important;
line-height: normal !important;
}
.quill-img {
display: none;
display: none;
}
.ql-snow .ql-tooltip[data-mode="link"]::before {
content: "请输入链接地址:";
content: "请输入链接地址:";
}
.ql-snow .ql-tooltip.ql-editing a.ql-action::after {
border-right: 0px;
content: "保存";
padding-right: 0px;
border-right: 0px;
content: "保存";
padding-right: 0px;
}
.ql-snow .ql-tooltip[data-mode="video"]::before {
content: "请输入视频地址:";
content: "请输入视频地址:";
}
.ql-snow .ql-picker.ql-size .ql-picker-label::before,
.ql-snow .ql-picker.ql-size .ql-picker-item::before {
content: "14px";
content: "14px";
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="small"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="small"]::before {
content: "10px";
content: "10px";
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="large"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="large"]::before {
content: "18px";
content: "18px";
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="huge"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="huge"]::before {
content: "32px";
content: "32px";
}
.ql-snow .ql-picker.ql-header .ql-picker-label::before,
.ql-snow .ql-picker.ql-header .ql-picker-item::before {
content: "文本";
content: "文本";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="1"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before {
content: "标题1";
content: "标题1";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="2"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before {
content: "标题2";
content: "标题2";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="3"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before {
content: "标题3";
content: "标题3";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="4"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before {
content: "标题4";
content: "标题4";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="5"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before {
content: "标题5";
content: "标题5";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="6"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]::before {
content: "标题6";
content: "标题6";
}
.ql-snow .ql-picker.ql-font .ql-picker-label::before,
.ql-snow .ql-picker.ql-font .ql-picker-item::before {
content: "标准字体";
content: "标准字体";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="serif"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="serif"]::before {
content: "衬线字体";
content: "衬线字体";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="monospace"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="monospace"]::before {
content: "等宽字体";
content: "等宽字体";
}
</style>

View File

@@ -1,6 +1,7 @@
<template>
<div class="upload-file">
<el-upload
multiple
:action="uploadFileUrl"
:before-upload="handleBeforeUpload"
:file-list="fileList"
@@ -11,7 +12,7 @@
:show-file-list="false"
:headers="headers"
class="upload-file-uploader"
ref="upload"
ref="fileUpload"
>
<!-- 上传按钮 -->
<el-button size="mini" type="primary">选取文件</el-button>
@@ -26,7 +27,7 @@
<!-- 文件列表 -->
<transition-group class="upload-file-list el-upload-list el-upload-list--text" name="el-fade-in-linear" tag="ul">
<li :key="file.uid" class="el-upload-list__item ele-upload-list__item-content" v-for="(file, index) in fileList">
<li :key="file.url" class="el-upload-list__item ele-upload-list__item-content" v-for="(file, index) in fileList">
<el-link :href="`${baseUrl}${file.url}`" :underline="false" target="_blank">
<span class="el-icon-document"> {{ getFileName(file.name) }} </span>
</el-link>
@@ -69,6 +70,8 @@ export default {
},
data() {
return {
number: 0,
uploadList: [],
baseUrl: process.env.VUE_APP_BASE_API,
uploadFileUrl: process.env.VUE_APP_BASE_API + "/iot/tool/upload", // 上传文件服务器地址
headers: {
@@ -112,17 +115,11 @@ export default {
handleBeforeUpload(file) {
// 校检文件类型
if (this.fileType) {
let fileExtension = "";
if (file.name.lastIndexOf(".") > -1) {
fileExtension = file.name.slice(file.name.lastIndexOf(".") + 1);
}
const isTypeOk = this.fileType.some((type) => {
if (file.type.indexOf(type) > -1) return true;
if (fileExtension && fileExtension.indexOf(type) > -1) return true;
return false;
});
const fileName = file.name.split('.');
const fileExt = fileName[fileName.length - 1];
const isTypeOk = this.fileType.indexOf(fileExt) >= 0;
if (!isTypeOk) {
this.$message.error(`文件格式不正确, 请上传${this.fileType.join("/")}格式文件!`);
this.$modal.msgError(`文件格式不正确, 请上传${this.fileType.join("/")}格式文件!`);
return false;
}
}
@@ -130,35 +127,55 @@ export default {
if (this.fileSize) {
const isLt = file.size / 1024 / 1024 < this.fileSize;
if (!isLt) {
this.$message.error(`上传文件大小不能超过 ${this.fileSize} MB!`);
this.$modal.msgError(`上传文件大小不能超过 ${this.fileSize} MB!`);
return false;
}
}
this.$modal.loading("正在上传文件,请稍候...");
this.number++;
return true;
},
// 文件个数超出
handleExceed() {
this.$message.error(`上传文件数量不能超过 ${this.limit} 个!`);
this.$modal.msgError(`上传文件数量不能超过 ${this.limit} 个!`);
},
// 上传失败
handleUploadError(err) {
this.$message.error("上传失败, 请重试");
this.$modal.msgError("上传文件失败,请重试");
this.$modal.closeLoading()
},
// 上传成功回调
handleUploadSuccess(res, file) {
this.$message.success("上传成功");
this.fileList.push({ name: res.fileName, url: res.fileName });
this.$emit("input", this.listToString(this.fileList));
if (res.code === 200) {
this.uploadList.push({ name: res.fileName, url: res.fileName });
this.uploadedSuccessfully();
} else {
this.number--;
this.$modal.closeLoading();
this.$modal.msgError(res.msg);
this.$refs.fileUpload.handleRemove(file);
this.uploadedSuccessfully();
}
},
// 删除文件
handleDelete(index) {
this.fileList.splice(index, 1);
this.$emit("input", this.listToString(this.fileList));
},
// 上传结束处理
uploadedSuccessfully() {
if (this.number > 0 && this.uploadList.length === this.number) {
this.fileList = this.fileList.concat(this.uploadList);
this.uploadList = [];
this.number = 0;
this.$emit("input", this.listToString(this.fileList));
this.$modal.closeLoading();
}
},
// 获取文件名称
getFileName(name) {
if (name.lastIndexOf("/") > -1) {
return name.slice(name.lastIndexOf("/") + 1).toLowerCase();
return name.slice(name.lastIndexOf("/") + 1);
} else {
return "";
}
@@ -195,4 +212,4 @@ export default {
.ele-upload-list__item-content-action .el-link {
margin-right: 10px;
}
</style>
</style>

View File

@@ -90,7 +90,6 @@ export default {
threshold: 0.4,
location: 0,
distance: 100,
maxPatternLength: 32,
minMatchCharLength: 1,
keys: [{
name: 'title',

View File

@@ -0,0 +1,90 @@
<template>
<el-image
:src="`${realSrc}`"
fit="cover"
:style="`width:${realWidth};height:${realHeight};`"
:preview-src-list="realSrcList"
>
<div slot="error" class="image-slot">
<i class="el-icon-picture-outline"></i>
</div>
</el-image>
</template>
<script>
import { isExternal } from "@/utils/validate";
export default {
name: "ImagePreview",
props: {
src: {
type: String,
default: ""
},
width: {
type: [Number, String],
default: ""
},
height: {
type: [Number, String],
default: ""
}
},
computed: {
realSrc() {
if (!this.src) {
return;
}
let real_src = this.src.split(",")[0];
if (isExternal(real_src)) {
return real_src;
}
return process.env.VUE_APP_BASE_API + real_src;
},
realSrcList() {
if (!this.src) {
return;
}
let real_src_list = this.src.split(",");
let srcList = [];
real_src_list.forEach(item => {
if (isExternal(item)) {
return srcList.push(item);
}
return srcList.push(process.env.VUE_APP_BASE_API + item);
});
return srcList;
},
realWidth() {
return typeof this.width == "string" ? this.width : `${this.width}px`;
},
realHeight() {
return typeof this.height == "string" ? this.height : `${this.height}px`;
}
},
};
</script>
<style lang="scss" scoped>
.el-image {
border-radius: 5px;
background-color: #ebeef5;
box-shadow: 0 0 5px 1px #ccc;
::v-deep .el-image__inner {
transition: all 0.3s;
cursor: pointer;
&:hover {
transform: scale(1.2);
}
}
::v-deep .image-slot {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
color: #909399;
font-size: 30px;
}
}
</style>

View File

@@ -1,6 +1,7 @@
<template>
<div class="component-upload-image">
<el-upload
multiple
:action="uploadImgUrl"
list-type="picture-card"
:on-success="handleUploadSuccess"
@@ -8,8 +9,8 @@
:limit="limit"
:on-error="handleUploadError"
:on-exceed="handleExceed"
name="file"
:on-remove="handleRemove"
ref="imageUpload"
:on-remove="handleDelete"
:show-file-list="true"
:headers="headers"
:file-list="fileList"
@@ -70,6 +71,8 @@ export default {
},
data() {
return {
number: 0,
uploadList: [],
dialogImageUrl: "",
dialogVisible: false,
hideUpload: false,
@@ -114,20 +117,6 @@ export default {
},
},
methods: {
// 删除图片
handleRemove(file, fileList) {
const findex = this.fileList.map(f => f.name).indexOf(file.name);
if(findex > -1) {
this.fileList.splice(findex, 1);
this.$emit("input", this.listToString(this.fileList));
}
},
// 上传成功回调
handleUploadSuccess(res) {
this.fileList.push({ name: res.fileName, url: process.env.VUE_APP_BASE_API +res.fileName });
this.$emit("input", this.listToString(this.fileList));
this.loading.close();
},
// 上传前loading加载
handleBeforeUpload(file) {
let isImg = false;
@@ -146,35 +135,58 @@ export default {
}
if (!isImg) {
this.$message.error(
`文件格式不正确, 请上传${this.fileType.join("/")}图片格式文件!`
);
this.$modal.msgError(`文件格式不正确, 请上传${this.fileType.join("/")}图片格式文件!`);
return false;
}
if (this.fileSize) {
const isLt = file.size / 1024 / 1024 < this.fileSize;
if (!isLt) {
this.$message.error(`上传头像图片大小不能超过 ${this.fileSize} MB!`);
this.$modal.msgError(`上传头像图片大小不能超过 ${this.fileSize} MB!`);
return false;
}
}
this.loading = this.$loading({
lock: true,
text: "上传中",
background: "rgba(0, 0, 0, 0.7)",
});
this.$modal.loading("正在上传图片,请稍候...");
this.number++;
},
// 文件个数超出
handleExceed() {
this.$message.error(`上传文件数量不能超过 ${this.limit} 个!`);
this.$modal.msgError(`上传文件数量不能超过 ${this.limit} 个!`);
},
// 上传成功回调
handleUploadSuccess(res, file) {
if (res.code === 200) {
this.uploadList.push({ name: res.fileName, url: res.fileName });
this.uploadedSuccessfully();
} else {
this.number--;
this.$modal.closeLoading();
this.$modal.msgError(res.msg);
this.$refs.imageUpload.handleRemove(file);
this.uploadedSuccessfully();
}
},
// 删除图片
handleDelete(file) {
const findex = this.fileList.map(f => f.name).indexOf(file.name);
if(findex > -1) {
this.fileList.splice(findex, 1);
this.$emit("input", this.listToString(this.fileList));
}
},
// 上传失败
handleUploadError() {
this.$message({
type: "error",
message: "上传失败",
});
this.loading.close();
this.$modal.msgError("上传图片失败,请重试");
this.$modal.closeLoading();
},
// 上传结束处理
uploadedSuccessfully() {
if (this.number > 0 && this.uploadList.length === this.number) {
this.fileList = this.fileList.concat(this.uploadList);
this.uploadList = [];
this.number = 0;
this.$emit("input", this.listToString(this.fileList));
this.$modal.closeLoading();
}
},
// 预览
handlePictureCardPreview(file) {
@@ -186,7 +198,9 @@ export default {
let strs = "";
separator = separator || ",";
for (let i in list) {
strs += list[i].url.replace(this.baseUrl, "") + separator;
if (list[i].url) {
strs += list[i].url.replace(this.baseUrl, "") + separator;
}
}
return strs != '' ? strs.substr(0, strs.length - 1) : '';
}

View File

@@ -61,6 +61,10 @@ export default {
default: false
}
},
data() {
return {
};
},
computed: {
currentPage: {
get() {
@@ -81,6 +85,9 @@ export default {
},
methods: {
handleSizeChange(val) {
if (this.currentPage * val > this.total) {
this.currentPage = 1
}
this.$emit('pagination', { page: this.currentPage, limit: val })
if (this.autoScroll) {
scrollTo(0, 800)

View File

@@ -1,5 +1,5 @@
<template>
<div ref="rightPanel" :class="{show:show}" class="rightPanel-container">
<div ref="rightPanel" class="rightPanel-container">
<div class="rightPanel-background" />
<div class="rightPanel">
<div class="rightPanel-items">
@@ -10,18 +10,12 @@
</template>
<script>
import { addClass, removeClass } from '@/utils'
export default {
name: 'RightPanel',
props: {
clickNotClose: {
default: false,
type: Boolean
},
buttonTop: {
default: 250,
type: Number
}
},
computed: {
@@ -35,25 +29,16 @@ export default {
value: val
})
}
},
theme() {
return this.$store.state.settings.theme
},
}
},
watch: {
show(value) {
if (value && !this.clickNotClose) {
this.addEventClick()
}
if (value) {
addClass(document.body, 'showRightPanel')
} else {
removeClass(document.body, 'showRightPanel')
}
}
},
mounted() {
this.insertToBody()
this.addEventClick()
},
beforeDestroy() {
@@ -65,29 +50,16 @@ export default {
window.addEventListener('click', this.closeSidebar)
},
closeSidebar(evt) {
const parent = evt.target.closest('.rightPanel')
const parent = evt.target.closest('.el-drawer__body')
if (!parent) {
this.show = false
window.removeEventListener('click', this.closeSidebar)
}
},
insertToBody() {
const elx = this.$refs.rightPanel
const body = document.querySelector('body')
body.insertBefore(elx, body.firstChild)
}
}
}
</script>
<style>
.showRightPanel {
overflow: hidden;
position: relative;
width: calc(100% - 15px);
}
</style>
<style lang="scss" scoped>
.rightPanel-background {
position: fixed;
@@ -113,21 +85,6 @@ export default {
z-index: 40000;
}
.show {
transition: all .3s cubic-bezier(.7, .3, .1, 1);
.rightPanel-background {
z-index: 20000;
opacity: 1;
width: 100%;
height: 100%;
}
.rightPanel {
transform: translate(0);
}
}
.handle-button {
width: 48px;
height: 48px;

View File

@@ -1,7 +1,7 @@
<template>
<div class="top-right-btn">
<div class="top-right-btn" :style="style">
<el-row>
<el-tooltip class="item" effect="dark" :content="showSearch ? '隐藏搜索' : '显示搜索'" placement="top">
<el-tooltip class="item" effect="dark" :content="showSearch ? '隐藏搜索' : '显示搜索'" placement="top" v-if="search">
<el-button size="mini" circle icon="el-icon-search" @click="toggleSearch()" />
</el-tooltip>
<el-tooltip class="item" effect="dark" content="刷新" placement="top">
@@ -42,6 +42,23 @@ export default {
columns: {
type: Array,
},
search: {
type: Boolean,
default: true,
},
gutter: {
type: Number,
default: 10,
},
},
computed: {
style() {
const ret = {};
if (this.gutter) {
ret.marginRight = `${this.gutter / 2}px`;
}
return ret;
}
},
created() {
// 显隐列初始默认隐藏列

View File

@@ -30,13 +30,14 @@
<script>
import { constantRoutes } from "@/router";
// 隐藏侧边栏路由
const hideList = ['/index', '/user/profile'];
export default {
data() {
return {
// 顶部栏初始数
visibleNumber: 5,
// 是否为首次加载
isFrist: false,
// 当前激活菜单的 index
currentIndex: undefined
};
@@ -71,7 +72,7 @@ export default {
for (var item in router.children) {
if (router.children[item].parentPath === undefined) {
if(router.path === "/") {
router.children[item].path = "/redirect/" + router.children[item].path;
router.children[item].path = "/" + router.children[item].path;
} else {
if(!this.ishttp(router.children[item].path)) {
router.children[item].path = router.path + "/" + router.children[item].path;
@@ -87,22 +88,18 @@ export default {
// 默认激活的菜单
activeMenu() {
const path = this.$route.path;
let activePath = this.defaultRouter();
if (path.lastIndexOf("/") > 0) {
let activePath = path;
if (path !== undefined && path.lastIndexOf("/") > 0 && hideList.indexOf(path) === -1) {
const tmpPath = path.substring(1, path.length);
activePath = "/" + tmpPath.substring(0, tmpPath.indexOf("/"));
} else if ("/index" == path || "" == path) {
if (!this.isFrist) {
this.isFrist = true;
} else {
activePath = "index";
if (!this.$route.meta.link) {
this.$store.dispatch('app/toggleSideBarHide', false);
}
} else if(!this.$route.children) {
activePath = path;
this.$store.dispatch('app/toggleSideBarHide', true);
}
var routes = this.activeRoutes(activePath);
if (routes.length === 0) {
activePath = this.currentIndex || this.defaultRouter()
this.activeRoutes(activePath);
}
this.activeRoutes(activePath);
return activePath;
},
},
@@ -121,29 +118,21 @@ export default {
const width = document.body.getBoundingClientRect().width / 3;
this.visibleNumber = parseInt(width / 85);
},
// 默认激活的路由
defaultRouter() {
let router;
Object.keys(this.routers).some((key) => {
if (!this.routers[key].hidden) {
router = this.routers[key].path;
return true;
}
});
return router;
},
// 菜单选择事件
handleSelect(key, keyPath) {
this.currentIndex = key;
const route = this.routers.find(item => item.path === key);
if (this.ishttp(key)) {
// http(s):// 路径新窗口打开
window.open(key, "_blank");
} else if (key.indexOf("/redirect") !== -1) {
// /redirect 路径内部打开
this.$router.push({ path: key.replace("/redirect", "") });
} else if (!route || !route.children) {
// 没有子路由路径内部打开
this.$router.push({ path: key });
this.$store.dispatch('app/toggleSideBarHide', true);
} else {
// 显示左侧联动菜单
this.activeRoutes(key);
this.$store.dispatch('app/toggleSideBarHide', false);
}
},
// 当前激活的路由
@@ -158,10 +147,11 @@ export default {
}
if(routes.length > 0) {
this.$store.commit("SET_SIDEBAR_ROUTERS", routes);
} else {
this.$store.dispatch('app/toggleSideBarHide', true);
}
return routes;
},
ishttp(url) {
ishttp(url) {
return url.indexOf('http://') !== -1 || url.indexOf('https://') !== -1
}
},

View File

@@ -3,10 +3,12 @@ import hasPermi from './permission/hasPermi'
import dialogDrag from './dialog/drag'
import dialogDragWidth from './dialog/dragWidth'
import dialogDragHeight from './dialog/dragHeight'
import clipboard from './module/clipboard'
const install = function(Vue) {
Vue.directive('hasRole', hasRole)
Vue.directive('hasPermi', hasPermi)
Vue.directive('clipboard', clipboard)
Vue.directive('dialogDrag', dialogDrag)
Vue.directive('dialogDragWidth', dialogDragWidth)
Vue.directive('dialogDragHeight', dialogDragHeight)

View File

@@ -0,0 +1,54 @@
/**
* v-clipboard 文字复制剪贴
* Copyright (c) 2021 ruoyi
*/
import Clipboard from 'clipboard'
export default {
bind(el, binding, vnode) {
switch (binding.arg) {
case 'success':
el._vClipBoard_success = binding.value;
break;
case 'error':
el._vClipBoard_error = binding.value;
break;
default: {
const clipboard = new Clipboard(el, {
text: () => binding.value,
action: () => binding.arg === 'cut' ? 'cut' : 'copy'
});
clipboard.on('success', e => {
const callback = el._vClipBoard_success;
callback && callback(e);
});
clipboard.on('error', e => {
const callback = el._vClipBoard_error;
callback && callback(e);
});
el._vClipBoard = clipboard;
}
}
},
update(el, binding) {
if (binding.arg === 'success') {
el._vClipBoard_success = binding.value;
} else if (binding.arg === 'error') {
el._vClipBoard_error = binding.value;
} else {
el._vClipBoard.text = function () { return binding.value; };
el._vClipBoard.action = () => binding.arg === 'cut' ? 'cut' : 'copy';
}
},
unbind(el, binding) {
if (!el._vClipboard) return
if (binding.arg === 'success') {
delete el._vClipBoard_success;
} else if (binding.arg === 'error') {
delete el._vClipBoard_error;
} else {
el._vClipBoard.destroy();
delete el._vClipBoard;
}
}
}

View File

@@ -2,15 +2,19 @@
<section class="app-main">
<transition name="fade-transform" mode="out-in">
<keep-alive :include="cachedViews">
<router-view :key="key" />
<router-view v-if="!$route.meta.link" :key="key" />
</keep-alive>
</transition>
<iframe-toggle />
</section>
</template>
<script>
import iframeToggle from "./IframeToggle/index"
export default {
name: 'AppMain',
components: { iframeToggle },
computed: {
cachedViews() {
return this.$store.state.tagsView.cachedViews
@@ -31,7 +35,7 @@ export default {
overflow: hidden;
}
.fixed-header+.app-main {
.fixed-header + .app-main {
padding-top: 50px;
}
@@ -41,7 +45,7 @@ export default {
min-height: calc(100vh - 84px);
}
.fixed-header+.app-main {
.fixed-header + .app-main {
padding-top: 84px;
}
}

View File

@@ -0,0 +1,24 @@
<template>
<transition-group name="fade-transform" mode="out-in">
<inner-link
v-for="(item, index) in iframeViews"
:key="item.path"
:iframeId="'iframe' + index"
v-show="$route.path === item.path"
:src="item.meta.link"
></inner-link>
</transition-group>
</template>
<script>
import InnerLink from "../InnerLink/index"
export default {
components: { InnerLink },
computed: {
iframeViews() {
return this.$store.state.tagsView.iframeViews
}
}
}
</script>

View File

@@ -1,27 +1,47 @@
<template>
<div :style="'height:' + height" v-loading="loading" element-loading-text="正在加载页面,请稍候!">
<iframe
:id="iframeId"
style="width: 100%; height: 100%"
:src="src"
frameborder="no"
></iframe>
</div>
</template>
<script>
export default {
data() {
return {};
},
render() {
const { $route: { meta: { link } }, } = this;
if ({ link }.link === "") {
return "404";
props: {
src: {
type: String,
default: "/"
},
iframeId: {
type: String
}
let url = { link }.link;
const height = document.documentElement.clientHeight - 94.5 + "px";
const style = { height: height };
return (
<div style={style}>
<iframe
src={url}
frameborder="no"
style="width: 100%; height: 100%"
scrolling="auto"
></iframe>
</div>
);
},
data() {
return {
loading: false,
height: document.documentElement.clientHeight - 94.5 + "px;"
};
},
mounted() {
var _this = this;
const iframeId = ("#" + this.iframeId).replace(/\//g, "\\/");
const iframe = document.querySelector(iframeId);
// iframe页面loading控制
if (iframe.attachEvent) {
this.loading = true;
iframe.attachEvent("onload", function () {
_this.loading = false;
});
} else {
this.loading = true;
iframe.onload = function () {
_this.loading = false;
};
}
}
};
</script>

View File

@@ -8,6 +8,14 @@
<div class="right-menu">
<template v-if="device!=='mobile'">
<search id="header-search" class="right-menu-item" />
<el-tooltip content="源码地址" effect="dark" placement="bottom">
<ruo-yi-git id="ruoyi-git" class="right-menu-item hover-effect" />
</el-tooltip>
<el-tooltip content="文档地址" effect="dark" placement="bottom">
<ruo-yi-doc id="ruoyi-doc" class="right-menu-item hover-effect" />
</el-tooltip>
<screenfull id="screenfull" class="right-menu-item hover-effect" />

View File

@@ -1,78 +1,76 @@
<template>
<div class="drawer-container">
<div>
<div class="setting-drawer-content">
<div class="setting-drawer-title">
<h3 class="drawer-title">主题风格设置</h3>
<el-drawer size="280px" :visible="visible" :with-header="false" :append-to-body="true" :show-close="false">
<div class="drawer-container">
<div>
<div class="setting-drawer-content">
<div class="setting-drawer-title">
<h3 class="drawer-title">主题风格设置</h3>
</div>
<div class="setting-drawer-block-checbox">
<div class="setting-drawer-block-checbox-item" @click="handleTheme('theme-dark')">
<img src="@/assets/images/dark.svg" alt="dark">
<div v-if="sideTheme === 'theme-dark'" class="setting-drawer-block-checbox-selectIcon" style="display: block;">
<i aria-label="图标: check" class="anticon anticon-check">
<svg viewBox="64 64 896 896" data-icon="check" width="1em" height="1em" :fill="theme" aria-hidden="true" focusable="false" class="">
<path d="M912 190h-69.9c-9.8 0-19.1 4.5-25.1 12.2L404.7 724.5 207 474a32 32 0 0 0-25.1-12.2H112c-6.7 0-10.4 7.7-6.3 12.9l273.9 347c12.8 16.2 37.4 16.2 50.3 0l488.4-618.9c4.1-5.1.4-12.8-6.3-12.8z"/>
</svg>
</i>
</div>
</div>
<div class="setting-drawer-block-checbox-item" @click="handleTheme('theme-light')">
<img src="@/assets/images/light.svg" alt="light">
<div v-if="sideTheme === 'theme-light'" class="setting-drawer-block-checbox-selectIcon" style="display: block;">
<i aria-label="图标: check" class="anticon anticon-check">
<svg viewBox="64 64 896 896" data-icon="check" width="1em" height="1em" :fill="theme" aria-hidden="true" focusable="false" class="">
<path d="M912 190h-69.9c-9.8 0-19.1 4.5-25.1 12.2L404.7 724.5 207 474a32 32 0 0 0-25.1-12.2H112c-6.7 0-10.4 7.7-6.3 12.9l273.9 347c12.8 16.2 37.4 16.2 50.3 0l488.4-618.9c4.1-5.1.4-12.8-6.3-12.8z"/>
</svg>
</i>
</div>
</div>
</div>
<div class="drawer-item">
<span>主题颜色</span>
<theme-picker style="float: right;height: 26px;margin: -3px 8px 0 0;" @change="themeChange" />
</div>
</div>
<div class="setting-drawer-block-checbox">
<div class="setting-drawer-block-checbox-item" @click="handleTheme('theme-dark')">
<img src="@/assets/images/dark.svg" alt="dark">
<div v-if="sideTheme === 'theme-dark'" class="setting-drawer-block-checbox-selectIcon" style="display: block;">
<i aria-label="图标: check" class="anticon anticon-check">
<svg viewBox="64 64 896 896" data-icon="check" width="1em" height="1em" :fill="theme" aria-hidden="true"
focusable="false" class="">
<path
d="M912 190h-69.9c-9.8 0-19.1 4.5-25.1 12.2L404.7 724.5 207 474a32 32 0 0 0-25.1-12.2H112c-6.7 0-10.4 7.7-6.3 12.9l273.9 347c12.8 16.2 37.4 16.2 50.3 0l488.4-618.9c4.1-5.1.4-12.8-6.3-12.8z"/>
</svg>
</i>
</div>
</div>
<div class="setting-drawer-block-checbox-item" @click="handleTheme('theme-light')">
<img src="@/assets/images/light.svg" alt="light">
<div v-if="sideTheme === 'theme-light'" class="setting-drawer-block-checbox-selectIcon" style="display: block;">
<i aria-label="图标: check" class="anticon anticon-check">
<svg viewBox="64 64 896 896" data-icon="check" width="1em" height="1em" :fill="theme" aria-hidden="true"
focusable="false" class="">
<path
d="M912 190h-69.9c-9.8 0-19.1 4.5-25.1 12.2L404.7 724.5 207 474a32 32 0 0 0-25.1-12.2H112c-6.7 0-10.4 7.7-6.3 12.9l273.9 347c12.8 16.2 37.4 16.2 50.3 0l488.4-618.9c4.1-5.1.4-12.8-6.3-12.8z"/>
</svg>
</i>
</div>
</div>
<el-divider/>
<h3 class="drawer-title">系统布局配置</h3>
<div class="drawer-item">
<span>开启 TopNav</span>
<el-switch v-model="topNav" class="drawer-switch" />
</div>
<div class="drawer-item">
<span>主题颜色</span>
<theme-picker style="float: right;height: 26px;margin: -3px 8px 0 0;" @change="themeChange" />
<span>开启 Tags-Views</span>
<el-switch v-model="tagsView" class="drawer-switch" />
</div>
<div class="drawer-item">
<span>固定 Header</span>
<el-switch v-model="fixedHeader" class="drawer-switch" />
</div>
<div class="drawer-item">
<span>显示 Logo</span>
<el-switch v-model="sidebarLogo" class="drawer-switch" />
</div>
<div class="drawer-item">
<span>动态标题</span>
<el-switch v-model="dynamicTitle" class="drawer-switch" />
</div>
<el-divider/>
<el-button size="small" type="primary" plain icon="el-icon-document-add" @click="saveSetting">保存配置</el-button>
<el-button size="small" plain icon="el-icon-refresh" @click="resetSetting">重置配置</el-button>
</div>
<el-divider/>
<h3 class="drawer-title">系统布局配置</h3>
<div class="drawer-item">
<span>开启 TopNav</span>
<el-switch v-model="topNav" class="drawer-switch" />
</div>
<div class="drawer-item">
<span>开启 Tags-Views</span>
<el-switch v-model="tagsView" class="drawer-switch" />
</div>
<div class="drawer-item">
<span>固定 Header</span>
<el-switch v-model="fixedHeader" class="drawer-switch" />
</div>
<div class="drawer-item">
<span>显示 Logo</span>
<el-switch v-model="sidebarLogo" class="drawer-switch" />
</div>
<div class="drawer-item">
<span>动态标题</span>
<el-switch v-model="dynamicTitle" class="drawer-switch" />
</div>
<el-divider/>
<el-button size="small" type="primary" plain icon="el-icon-document-add" @click="saveSetting">保存配置</el-button>
<el-button size="small" plain icon="el-icon-refresh" @click="resetSetting">重置配置</el-button>
</div>
</div>
</el-drawer>
</template>
<script>
@@ -87,6 +85,11 @@ export default {
};
},
computed: {
visible: {
get() {
return this.$store.state.settings.showSettings
}
},
fixedHeader: {
get() {
return this.$store.state.settings.fixedHeader
@@ -108,6 +111,7 @@ export default {
value: val
})
if (!val) {
this.$store.dispatch('app/toggleSideBarHide', false);
this.$store.commit("SET_SIDEBAR_ROUTERS", this.$store.state.permission.defaultRoutes);
}
}
@@ -231,7 +235,7 @@ export default {
}
.drawer-container {
padding: 24px;
padding: 20px;
font-size: 14px;
line-height: 1.5;
word-wrap: break-word;

View File

@@ -21,7 +21,11 @@ export default {
}
if (title) {
vnodes.push(<span slot='title'>{(title)}</span>)
if (title.length > 5) {
vnodes.push(<span slot='title' title={(title)}>{(title)}</span>)
} else {
vnodes.push(<span slot='title'>{(title)}</span>)
}
}
return vnodes
}

View File

@@ -7,7 +7,7 @@
</router-link>
<router-link v-else key="expand" class="sidebar-logo-link" to="/">
<img v-if="logo" :src="logo" class="sidebar-logo" />
<h1 class="sidebar-title" :style="{ color: sideTheme === 'theme-dark' ? variables.logoTitleColor : variables.logoLightTitleColor }">{{ title }} </h1>
<span class="sidebar-title" :style="{ color: sideTheme === 'theme-dark' ? variables.logoTitleColor : variables.logoLightTitleColor }">{{ title }} </span>
</router-link>
</transition>
</div>
@@ -35,7 +35,7 @@ export default {
},
data() {
return {
title: 'FastBee物联网平台',
title: 'FastBee',
logo: logoImg
}
}
@@ -58,8 +58,8 @@ export default {
height: 50px;
line-height: 50px;
background: #2b2f3a;
text-align: center;
overflow: hidden;
margin-left:15px;
& .sidebar-logo-link {
height: 100%;
@@ -69,17 +69,16 @@ export default {
width: 32px;
height: 32px;
vertical-align: middle;
margin-right: 12px;
}
& .sidebar-title {
display: inline-block;
margin: 0;
color: #fff;
font-weight: 600;
font-weight: 400;
line-height: 50px;
font-size: 14px;
font-family: Avenir, Helvetica Neue, Arial, Helvetica, sans-serif;
font-size: 20px;
font-family:"微软雅黑";
vertical-align: middle;
}
}

View File

@@ -133,6 +133,9 @@ export default {
const { name } = this.$route
if (name) {
this.$store.dispatch('tagsView/addView', this.$route)
if (this.$route.meta.link) {
this.$store.dispatch('tagsView/addIframeView', this.$route)
}
}
return false
},
@@ -153,6 +156,9 @@ export default {
},
refreshSelectedTag(view) {
this.$tab.refreshPage(view);
if (this.$route.meta.link) {
this.$store.dispatch('tagsView/delIframeView', this.$route)
}
},
closeSelectedTag(view) {
this.$tab.closePage(view).then(({ visitedViews }) => {

View File

@@ -1,8 +1,8 @@
<template>
<div :class="classObj" class="app-wrapper" :style="{'--current-color': theme}">
<div v-if="device==='mobile'&&sidebar.opened" class="drawer-bg" @click="handleClickOutside"/>
<sidebar class="sidebar-container"/>
<div :class="{hasTagsView:needTagsView}" class="main-container">
<sidebar v-if="!sidebar.hide" class="sidebar-container" />
<div :class="{hasTagsView:needTagsView,sidebarHide:sidebar.hide}" class="main-container">
<div :class="{'fixed-header':fixedHeader}">
<navbar />
<tags-view v-if="needTagsView" />
@@ -101,6 +101,10 @@ export default {
width: calc(100% - 54px);
}
.sidebarHide .fixed-header {
width: 100%;
}
.mobile .fixed-header {
width: 100%;
}

View File

@@ -7,7 +7,6 @@
*/
import router from '@/router'
import { isString, isHtmlElement } from './types'
import UtilVar from "@/config/UtilVar";
export const returnWeek = () => {
var week = new Date().getDay();
switch (week) {
@@ -274,7 +273,7 @@ export const readFile = (data) => {
reader.onload = (e) => {
console.log('--导出--', JSON.parse(reader.result))
let result = JSON.parse(reader.result)
if (result.code == UtilVar.code) {
if (result.code == 401) {
router.push("/login")
}
resole(result)

View File

@@ -4,6 +4,7 @@ import Cookies from 'js-cookie'
import Element from 'element-ui'
import './assets/styles/element-variables.scss'
import busEvent from '@/utils/busEvent'
import '@/assets/styles/index.scss' // global css
import '@/assets/styles/ruoyi.scss' // ruoyi css
@@ -29,6 +30,8 @@ import Editor from "@/components/Editor"
import FileUpload from "@/components/FileUpload"
// 图片上传组件
import ImageUpload from "@/components/ImageUpload"
// 图片预览组件
import ImagePreview from "@/components/ImagePreview"
// 字典标签组件
import DictTag from '@/components/DictTag'
// 头部标签组件
@@ -36,7 +39,7 @@ import VueMeta from 'vue-meta'
// 字典数据组件
import DictData from '@/components/DictData'
// Echart
import echarts from 'echarts'
import * as echarts from 'echarts'
// 一键复制粘贴板组件
import VueClipboard from 'vue-clipboard2'
// Mqtt工具
@@ -45,29 +48,27 @@ import mqttTool from '@/utils/mqttTool'
import ItemWrap from './views/bigScreen/components/item-wrap/item-wrap.vue'
import Message from './views/bigScreen/components/message/message.vue'
import Reacquire from './views/bigScreen/components/reacquire/reacquire.vue'
import Echart from './views/bigScreen/components/echart/index.vue'
import {loading,borderBox13,digitalFlop,waterLevelPond,scrollBoard,capsuleChart,borderBox8,decoration12,decoration3,decoration9,activeRingChart} from '@jiaminghi/data-view'
import {loading,borderBox13,digitalFlop,capsuleChart,borderBox8} from '@jiaminghi/data-view'
import * as filters from '@/directive/filters'
require('./mock/mock')//是否使用mock
// datav组件
// datav组件 ,会导致生成文件无法打开
Vue.use(loading)
Vue.use(borderBox13)
Vue.use(borderBox8)
Vue.use(digitalFlop)
Vue.use(capsuleChart)
Vue.use(waterLevelPond)
Vue.use(scrollBoard)
Vue.use(decoration12)
Vue.use(activeRingChart)
Vue.use(decoration3)
Vue.use(decoration9)
// 自定义组件
Vue.component("Echart",Echart)
Vue.component("ItemWrap",ItemWrap)
Vue.component("Message",Message)
Vue.component("Reacquire",Reacquire)
// 全局方法挂载
Vue.prototype.getDicts = getDicts
Vue.prototype.getConfigKey = getConfigKey
@@ -80,6 +81,7 @@ Vue.prototype.download = download
Vue.prototype.handleTree = handleTree
Vue.prototype.$echarts = echarts
Vue.prototype.$mqttTool = mqttTool
Vue.prototype.$busEvent = busEvent
// 全局组件挂载
Vue.component('DictTag', DictTag)
@@ -88,14 +90,13 @@ Vue.component('RightToolbar', RightToolbar)
Vue.component('Editor', Editor)
Vue.component('FileUpload', FileUpload)
Vue.component('ImageUpload', ImageUpload)
Vue.component('ImagePreview', ImagePreview)
Vue.use(VueClipboard)
Vue.use(directive)
Vue.use(plugins)
Vue.use(VueMeta)
DictData.install()
// 全局数据过滤器
Object.keys(filters).forEach(k => Vue.filter(k, filters[k]));
/**
* If you don't want to use mock-server
* you want to use MockJs for mock api
@@ -118,7 +119,7 @@ new Vue({
render: h => h(App)
})
// 带边框
// 表格带边框
Element.Table.props.border = {
default:true,
type:Boolean

View File

@@ -1,11 +1,12 @@
import router from './router'
import store from './store'
import {Message} from 'element-ui'
import { Message } from 'element-ui'
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'
import {getToken} from '@/utils/auth'
import { getToken } from '@/utils/auth'
import { isRelogin } from '@/utils/request'
NProgress.configure({showSpinner: false})
NProgress.configure({ showSpinner: false })
const whiteList = ['/login', '/auth-redirect', '/bind', '/register']
@@ -15,32 +16,25 @@ router.beforeEach((to, from, next) => {
to.meta.title && store.dispatch('settings/setTitle', to.meta.title)
/* has token*/
if (to.path === '/login') {
if (to.query.bindId) {
store.dispatch('BindUser', to.query.bindId).then((res) => {
Message.success(res.msg);
next({path: '/user/profile'})
}).catch(err=>{
next({path: '/'})
})
} else {
next({path: '/'})
}
next({ path: '/' })
NProgress.done()
} else {
if (store.getters.roles.length === 0) {
isRelogin.show = true
// 判断当前用户是否已拉取完user_info信息
store.dispatch('GetInfo').then(() => {
isRelogin.show = false
store.dispatch('GenerateRoutes').then(accessRoutes => {
// 根据roles权限生成可访问的路由表
router.addRoutes(accessRoutes) // 动态添加可访问路由表
next({...to, replace: true}) // hack方法 确保addRoutes已完成
next({ ...to, replace: true }) // hack方法 确保addRoutes已完成
})
}).catch(err => {
store.dispatch('LogOut').then(() => {
Message.error(err)
next({path: '/'})
store.dispatch('LogOut').then(() => {
Message.error(err)
next({ path: '/' })
})
})
})
} else {
next()
}

View File

@@ -2,13 +2,14 @@ import axios from 'axios'
import { Message } from 'element-ui'
import { saveAs } from 'file-saver'
import { getToken } from '@/utils/auth'
import errorCode from '@/utils/errorCode'
import { blobValidate } from "@/utils/ruoyi";
const baseURL = process.env.VUE_APP_BASE_API
export default {
name(name, isDelete = true) {
var url = baseURL + "/common/download?fileName=" + encodeURI(name) + "&delete=" + isDelete
var url = baseURL + "/common/download?fileName=" + encodeURIComponent(name) + "&delete=" + isDelete
axios({
method: 'get',
url: url,
@@ -18,14 +19,14 @@ export default {
const isLogin = await blobValidate(res.data);
if (isLogin) {
const blob = new Blob([res.data])
this.saveAs(blob, decodeURI(res.headers['download-filename']))
this.saveAs(blob, decodeURIComponent(res.headers['download-filename']))
} else {
Message.error('无效的会话,或者会话已过期,请重新登录。');
this.printErrMsg(res.data);
}
})
},
resource(resource) {
var url = baseURL + "/common/download/resource?resource=" + encodeURI(resource);
var url = baseURL + "/common/download/resource?resource=" + encodeURIComponent(resource);
axios({
method: 'get',
url: url,
@@ -35,9 +36,9 @@ export default {
const isLogin = await blobValidate(res.data);
if (isLogin) {
const blob = new Blob([res.data])
this.saveAs(blob, decodeURI(res.headers['download-filename']))
this.saveAs(blob, decodeURIComponent(res.headers['download-filename']))
} else {
Message.error('无效的会话,或者会话已过期,请重新登录。');
this.printErrMsg(res.data);
}
})
},
@@ -54,12 +55,18 @@ export default {
const blob = new Blob([res.data], { type: 'application/zip' })
this.saveAs(blob, name)
} else {
Message.error('无效的会话,或者会话已过期,请重新登录。');
this.printErrMsg(res.data);
}
})
},
saveAs(text, name, opts) {
saveAs(text, name, opts);
},
async printErrMsg(data) {
const resText = await data.text();
const rspObj = JSON.parse(resText);
const errMsg = errorCode[rspObj.code] || rspObj.msg || errorCode['default']
Message.error(errMsg);
}
}

View File

@@ -4,20 +4,21 @@ import router from '@/router';
export default {
// 刷新当前tab页签
refreshPage(obj) {
const { path, matched } = router.currentRoute;
const { path, query, matched } = router.currentRoute;
if (obj === undefined) {
matched.forEach((m) => {
if (m.components && m.components.default && m.components.default.name) {
if (!['Layout', 'ParentView'].includes(m.components.default.name)) {
obj = { name: m.components.default.name, path: path };
obj = { name: m.components.default.name, path: path, query: query };
}
}
});
}
return store.dispatch('tagsView/delCachedView', obj).then(() => {
const { path } = obj
const { path, query } = obj
router.replace({
path: '/redirect' + path
path: '/redirect' + path,
query: query
})
})
},
@@ -54,10 +55,10 @@ export default {
return store.dispatch('tagsView/delOthersViews', obj || router.currentRoute);
},
// 添加tab页签
openPage(title, url) {
openPage(title, url, params) {
var obj = { path: url, meta: { title: title } }
store.dispatch('tagsView/addView', obj);
return router.push(url);
return router.push({ path: url, query: params });
},
// 修改tab页签
updatePage(obj) {

View File

@@ -17,6 +17,8 @@ import Layout from '@/layout'
* redirect: noRedirect // 当设置 noRedirect 的时候该路由在面包屑导航中不可被点击
* name:'router-name' // 设定路由的名字,一定要填写不然使用<keep-alive>时会出现各种问题
* query: '{"id": 1, "name": "ry"}' // 访问路由的默认传递参数
* roles: ['admin', 'common'] // 访问路由的角色权限
* permissions: ['a:a:a', 'b:b:b'] // 访问路由的菜单权限
* meta : {
noCache: true // 如果设置为true则不会被 <keep-alive> 缓存(默认 false)
title: 'title' // 设置该路由在侧边栏和面包屑中展示的名字
@@ -35,34 +37,34 @@ export const constantRoutes = [
children: [
{
path: '/redirect/:path(.*)',
component: (resolve) => require(['@/views/redirect'], resolve)
component: () => import('@/views/redirect')
}
]
},
{
{
path: '/bigScreen',
component: (resolve) => require(['@/views/bigScreen/home'], resolve),
component: () => import('@/views/bigScreen/home'),
hidden: true,
meta: { bigScreen: true }
},
{
path: '/login',
component: (resolve) => require(['@/views/login'], resolve),
component: () => import('@/views/login'),
hidden: true
},
{
path: '/register',
component: (resolve) => require(['@/views/register'], resolve),
component: () => import('@/views/register'),
hidden: true
},
{
path: '/404',
component: (resolve) => require(['@/views/error/404'], resolve),
component: () => import('@/views/error/404'),
hidden: true
},
{
path: '/401',
component: (resolve) => require(['@/views/error/401'], resolve),
component: () => import('@/views/error/401'),
hidden: true
},
{
@@ -72,7 +74,7 @@ export const constantRoutes = [
children: [
{
path: 'index',
component: (resolve) => require(['@/views/index'], resolve),
component: () => import('@/views/index'),
name: 'Index',
meta: { title: '首页', icon: 'dashboard', affix: true }
}
@@ -86,20 +88,25 @@ export const constantRoutes = [
children: [
{
path: 'profile',
component: (resolve) => require(['@/views/system/user/profile/index'], resolve),
component: () => import('@/views/system/user/profile/index'),
name: 'Profile',
meta: { title: '个人中心', icon: 'user' }
}
]
},
}
]
// 动态路由,基于用户权限动态去加载
export const dynamicRoutes = [
{
path: '/system/user-auth',
component: Layout,
hidden: true,
permissions: ['system:user:edit'],
children: [
{
path: 'role/:userId(\\d+)',
component: (resolve) => require(['@/views/system/user/authRole'], resolve),
component: () => import('@/views/system/user/authRole'),
name: 'AuthRole',
meta: { title: '分配角色', activeMenu: '/system/user' }
}
@@ -109,10 +116,11 @@ export const constantRoutes = [
path: '/system/role-auth',
component: Layout,
hidden: true,
permissions: ['system:role:edit'],
children: [
{
path: 'user/:roleId(\\d+)',
component: (resolve) => require(['@/views/system/role/authUser'], resolve),
component: () => import('@/views/system/role/authUser'),
name: 'AuthUser',
meta: { title: '分配用户', activeMenu: '/system/role' }
}
@@ -122,10 +130,11 @@ export const constantRoutes = [
path: '/system/dict-data',
component: Layout,
hidden: true,
permissions: ['system:dict:list'],
children: [
{
path: 'index/:dictId(\\d+)',
component: (resolve) => require(['@/views/system/dict/data'], resolve),
component: () => import('@/views/system/dict/data'),
name: 'Data',
meta: { title: '字典数据', activeMenu: '/system/dict' }
}
@@ -135,10 +144,11 @@ export const constantRoutes = [
path: '/monitor/job-log',
component: Layout,
hidden: true,
permissions: ['monitor:job:list'],
children: [
{
path: 'index',
component: (resolve) => require(['@/views/monitor/job/log'], resolve),
path: 'index/:jobId(\\d+)',
component: () => import('@/views/monitor/job/log'),
name: 'JobLog',
meta: { title: '调度日志', activeMenu: '/monitor/job' }
}
@@ -148,10 +158,11 @@ export const constantRoutes = [
path: '/tool/gen-edit',
component: Layout,
hidden: true,
permissions: ['tool:gen:edit'],
children: [
{
path: 'index',
component: (resolve) => require(['@/views/tool/gen/editTable'], resolve),
path: 'index/:tableId(\\d+)',
component: () => import('@/views/tool/gen/editTable'),
name: 'GenEdit',
meta: { title: '修改生成配置', activeMenu: '/tool/gen' }
}
@@ -161,23 +172,30 @@ export const constantRoutes = [
path: '/iot',
component: Layout,
hidden: true,
permissions: ['iot:device:add'],
children: [
{
path: 'product-edit',
component: (resolve) => require(['@/views/iot/product/product-edit'], resolve),
component: () => import('@/views/iot/product/product-edit'),
name: 'ProductEdit',
meta: { title: '编辑产品', activeMenu: '/iot/product',nocache: true}
},
{
path: 'device-edit',
component: (resolve) => require(['@/views/iot/device/device-edit'], resolve),
component: () => import('@/views/iot/device/device-edit'),
name: 'DeviceEdit',
meta: { title: '编辑设备', activeMenu: '/iot/device', noCache: true}
},
}
]
}
},
]
// 防止连续点击多次路由报错
let routerPush = Router.prototype.push;
Router.prototype.push = function push(location) {
return routerPush.call(this, location).catch(err => err)
}
export default new Router({
mode: 'history', // 去掉url中的#
scrollBehavior: () => ({ y: 0 }),

View File

@@ -17,7 +17,7 @@ module.exports = {
/**
* 是否显示 tagsView
*/
tagsView: true,
tagsView: false,
/**
* 是否固定头部

View File

@@ -2,6 +2,7 @@ const getters = {
sidebar: state => state.app.sidebar,
size: state => state.app.size,
device: state => state.app.device,
dict: state => state.dict.dict,
visitedViews: state => state.tagsView.visitedViews,
cachedViews: state => state.tagsView.cachedViews,
token: state => state.user.token,

View File

@@ -1,6 +1,7 @@
import Vue from 'vue'
import Vuex from 'vuex'
import app from './modules/app'
import dict from './modules/dict'
import user from './modules/user'
import tagsView from './modules/tagsView'
import permission from './modules/permission'
@@ -12,6 +13,7 @@ Vue.use(Vuex)
const store = new Vuex.Store({
modules: {
app,
dict,
user,
tagsView,
permission,

View File

@@ -3,7 +3,8 @@ import Cookies from 'js-cookie'
const state = {
sidebar: {
opened: Cookies.get('sidebarStatus') ? !!+Cookies.get('sidebarStatus') : true,
withoutAnimation: false
withoutAnimation: false,
hide: false
},
device: 'desktop',
size: Cookies.get('size') || 'medium'
@@ -11,6 +12,9 @@ const state = {
const mutations = {
TOGGLE_SIDEBAR: state => {
if (state.sidebar.hide) {
return false;
}
state.sidebar.opened = !state.sidebar.opened
state.sidebar.withoutAnimation = false
if (state.sidebar.opened) {
@@ -30,6 +34,9 @@ const mutations = {
SET_SIZE: (state, size) => {
state.size = size
Cookies.set('size', size)
},
SET_SIDEBAR_HIDE: (state, status) => {
state.sidebar.hide = status
}
}
@@ -45,6 +52,9 @@ const actions = {
},
setSize({ commit }, size) {
commit('SET_SIZE', size)
},
toggleSideBarHide({ commit }, status) {
commit('SET_SIDEBAR_HIDE', status)
}
}

View File

@@ -0,0 +1,50 @@
const state = {
dict: new Array()
}
const mutations = {
SET_DICT: (state, { key, value }) => {
if (key !== null && key !== "") {
state.dict.push({
key: key,
value: value
})
}
},
REMOVE_DICT: (state, key) => {
try {
for (let i = 0; i < state.dict.length; i++) {
if (state.dict[i].key == key) {
state.dict.splice(i, i)
return true
}
}
} catch (e) {
}
},
CLEAN_DICT: (state) => {
state.dict = new Array()
}
}
const actions = {
// 设置字典
setDict({ commit }, data) {
commit('SET_DICT', data)
},
// 删除字典
removeDict({ commit }, key) {
commit('REMOVE_DICT', key)
},
// 清空字典
cleanDict({ commit }) {
commit('CLEAN_DICT')
}
}
export default {
namespaced: true,
state,
mutations,
actions
}

View File

@@ -1,4 +1,5 @@
import { constantRoutes } from '@/router'
import auth from '@/plugins/auth'
import router, { constantRoutes, dynamicRoutes } from '@/router'
import { getRouters } from '@/api/menu'
import Layout from '@/layout/index'
import ParentView from '@/components/ParentView'
@@ -21,12 +22,7 @@ const permission = {
state.defaultRoutes = constantRoutes.concat(routes)
},
SET_TOPBAR_ROUTES: (state, routes) => {
// 顶部导航菜单默认添加统计报表栏指向首页
const index = [{
path: 'index',
meta: { title: '统计报表', icon: 'dashboard' }
}]
state.topbarRouters = routes.concat(index);
state.topbarRouters = routes
},
SET_SIDEBAR_ROUTERS: (state, routes) => {
state.sidebarRouters = routes
@@ -42,7 +38,9 @@ const permission = {
const rdata = JSON.parse(JSON.stringify(res.data))
const sidebarRoutes = filterAsyncRouter(sdata)
const rewriteRoutes = filterAsyncRouter(rdata, false, true)
const asyncRoutes = filterDynamicRoutes(dynamicRoutes);
rewriteRoutes.push({ path: '*', redirect: '/404', hidden: true })
router.addRoutes(asyncRoutes);
commit('SET_ROUTES', rewriteRoutes)
commit('SET_SIDEBAR_ROUTERS', constantRoutes.concat(sidebarRoutes))
commit('SET_DEFAULT_ROUTES', sidebarRoutes)
@@ -106,6 +104,23 @@ function filterChildren(childrenMap, lastRouter = false) {
return children
}
// 动态路由遍历,验证是否具备权限
export function filterDynamicRoutes(routes) {
const res = []
routes.forEach(route => {
if (route.permissions) {
if (auth.hasPermiOr(route.permissions)) {
res.push(route)
}
} else if (route.roles) {
if (auth.hasRoleOr(route.roles)) {
res.push(route)
}
}
})
return res
}
export const loadView = (view) => {
if (process.env.NODE_ENV === 'development') {
return (resolve) => require([`@/views/${view}`], resolve)

View File

@@ -12,22 +12,7 @@ const state = {
tagsView: storageSetting.tagsView === undefined ? tagsView : storageSetting.tagsView,
fixedHeader: storageSetting.fixedHeader === undefined ? fixedHeader : storageSetting.fixedHeader,
sidebarLogo: storageSetting.sidebarLogo === undefined ? sidebarLogo : storageSetting.sidebarLogo,
dynamicTitle: storageSetting.dynamicTitle === undefined ? dynamicTitle : storageSetting.dynamicTitle,
sbtxSwiper: true, //设备提醒轮播
ssyjSwiper: true, //实时预警轮播
isScale: true, //是否进行全局适配
defaultOption: {
step: 4.4, // 数值越大速度滚动越快
hoverStop: true, // 是否开启鼠标悬停stop
openWatch: true, // 开启数据实时监控刷新dom
direction: 1, // 0向下 1向上 2向左 3向右
limitMoveNum: 4, // 开始无缝滚动的数据量 this.dataList.length
singleHeight: 0, // 单步运动停止的高度(默认值0是无缝不停止的滚动) direction => 0/1
singleWidth: 0, // 单步运动停止的宽度(默认值0是无缝不停止的滚动) direction => 2/3
waitTime: 3000 // 单步运动停止的时间(默认值1000ms)
},
echartsAutoTime: 3000, //echarts 图自动请求接口时间
dynamicTitle: storageSetting.dynamicTitle === undefined ? dynamicTitle : storageSetting.dynamicTitle
}
const mutations = {
CHANGE_SETTING: (state, { key, value }) => {

View File

@@ -1,9 +1,18 @@
const state = {
visitedViews: [],
cachedViews: []
cachedViews: [],
iframeViews: []
}
const mutations = {
ADD_IFRAME_VIEW: (state, view) => {
if (state.iframeViews.some(v => v.path === view.path)) return
state.iframeViews.push(
Object.assign({}, view, {
title: view.meta.title || 'no-name'
})
)
},
ADD_VISITED_VIEW: (state, view) => {
if (state.visitedViews.some(v => v.path === view.path)) return
state.visitedViews.push(
@@ -18,7 +27,6 @@ const mutations = {
state.cachedViews.push(view.name)
}
},
DEL_VISITED_VIEW: (state, view) => {
for (const [i, v] of state.visitedViews.entries()) {
if (v.path === view.path) {
@@ -26,6 +34,10 @@ const mutations = {
break
}
}
state.iframeViews = state.iframeViews.filter(item => item.path !== view.path)
},
DEL_IFRAME_VIEW: (state, view) => {
state.iframeViews = state.iframeViews.filter(item => item.path !== view.path)
},
DEL_CACHED_VIEW: (state, view) => {
const index = state.cachedViews.indexOf(view.name)
@@ -36,6 +48,7 @@ const mutations = {
state.visitedViews = state.visitedViews.filter(v => {
return v.meta.affix || v.path === view.path
})
state.iframeViews = state.iframeViews.filter(item => item.path === view.path)
},
DEL_OTHERS_CACHED_VIEWS: (state, view) => {
const index = state.cachedViews.indexOf(view.name)
@@ -45,16 +58,15 @@ const mutations = {
state.cachedViews = []
}
},
DEL_ALL_VISITED_VIEWS: state => {
// keep affix tags
const affixTags = state.visitedViews.filter(tag => tag.meta.affix)
state.visitedViews = affixTags
state.iframeViews = []
},
DEL_ALL_CACHED_VIEWS: state => {
state.cachedViews = []
},
UPDATE_VISITED_VIEW: (state, view) => {
for (let v of state.visitedViews) {
if (v.path === view.path) {
@@ -63,7 +75,6 @@ const mutations = {
}
}
},
DEL_RIGHT_VIEWS: (state, view) => {
const index = state.visitedViews.findIndex(v => v.path === view.path)
if (index === -1) {
@@ -77,10 +88,13 @@ const mutations = {
if (i > -1) {
state.cachedViews.splice(i, 1)
}
if(item.meta.link) {
const fi = state.iframeViews.findIndex(v => v.path === item.path)
state.iframeViews.splice(fi, 1)
}
return false
})
},
DEL_LEFT_VIEWS: (state, view) => {
const index = state.visitedViews.findIndex(v => v.path === view.path)
if (index === -1) {
@@ -94,6 +108,10 @@ const mutations = {
if (i > -1) {
state.cachedViews.splice(i, 1)
}
if(item.meta.link) {
const fi = state.iframeViews.findIndex(v => v.path === item.path)
state.iframeViews.splice(fi, 1)
}
return false
})
}
@@ -104,13 +122,15 @@ const actions = {
dispatch('addVisitedView', view)
dispatch('addCachedView', view)
},
addIframeView({ commit }, view) {
commit('ADD_IFRAME_VIEW', view)
},
addVisitedView({ commit }, view) {
commit('ADD_VISITED_VIEW', view)
},
addCachedView({ commit }, view) {
commit('ADD_CACHED_VIEW', view)
},
delView({ dispatch, state }, view) {
return new Promise(resolve => {
dispatch('delVisitedView', view)
@@ -127,13 +147,18 @@ const actions = {
resolve([...state.visitedViews])
})
},
delIframeView({ commit, state }, view) {
return new Promise(resolve => {
commit('DEL_IFRAME_VIEW', view)
resolve([...state.iframeViews])
})
},
delCachedView({ commit, state }, view) {
return new Promise(resolve => {
commit('DEL_CACHED_VIEW', view)
resolve([...state.cachedViews])
})
},
delOthersViews({ dispatch, state }, view) {
return new Promise(resolve => {
dispatch('delOthersVisitedViews', view)
@@ -156,7 +181,6 @@ const actions = {
resolve([...state.cachedViews])
})
},
delAllViews({ dispatch, state }, view) {
return new Promise(resolve => {
dispatch('delAllVisitedViews', view)
@@ -179,18 +203,15 @@ const actions = {
resolve([...state.cachedViews])
})
},
updateVisitedView({ commit }, view) {
commit('UPDATE_VISITED_VIEW', view)
},
delRightTags({ commit }, view) {
return new Promise(resolve => {
commit('DEL_RIGHT_VIEWS', view)
resolve([...state.visitedViews])
})
},
delLeftTags({ commit }, view) {
return new Promise(resolve => {
commit('DEL_LEFT_VIEWS', view)

View File

@@ -1,6 +1,5 @@
import {login, logout, getInfo, bindLogin, bindRegister, redirectLogin} from '@/api/login'
import {bindUser} from '@/api/iot/platform'
import {getToken, setToken, removeToken} from '@/utils/auth'
import { login, logout, getInfo } from '@/api/login';
import { getToken, setToken, removeToken, setUserId, removeUserId } from '@/utils/auth';
const user = {
state: {
@@ -8,127 +7,103 @@ const user = {
name: '',
avatar: '',
roles: [],
permissions: []
permissions: [],
},
mutations: {
SET_TOKEN: (state, token) => {
state.token = token
state.token = token;
},
SET_NAME: (state, name) => {
state.name = name
},
SET_USERID: (state, userId) => {
state.userId = userId
state.name = name;
},
SET_AVATAR: (state, avatar) => {
state.avatar = avatar
state.avatar = avatar;
},
SET_ROLES: (state, roles) => {
state.roles = roles
state.roles = roles;
},
SET_PERMISSIONS: (state, permissions) => {
state.permissions = permissions
}
state.permissions = permissions;
},
SET_MQTT: (state, mqtt) => {
state.mqtt = mqtt;
},
},
actions: {
// 登录
Login({commit}, userInfo) {
const username = userInfo.username.trim()
const password = userInfo.password
const code = userInfo.code
const uuid = userInfo.uuid
const bindId = userInfo.bindId;
Login({ commit }, userInfo) {
const username = userInfo.username.trim();
const password = userInfo.password;
const code = userInfo.code;
const uuid = userInfo.uuid;
return new Promise((resolve, reject) => {
if (bindId === undefined || bindId === "") {
login(username, password, code, uuid).then(res => {
setToken(res.token)
commit('SET_TOKEN', res.token)
resolve()
}).catch(error => {
reject(error)
login(username, password, code, uuid)
.then((res) => {
setToken(res.token);
commit('SET_TOKEN', res.token);
resolve();
})
} else {
bindLogin(username, password, code, uuid, bindId).then(res => {
setToken(res.token)
commit('SET_TOKEN', res.token)
resolve()
}).catch(error => {
reject(error)
})
}
})
},
RedirectLogin({commit}, loginId) {
return new Promise((resolve, reject) => {
redirectLogin(loginId).then(res => {
setToken(res.token)
commit('SET_TOKEN', res.token)
resolve()
}).catch(error => {
reject(error)
})
})
},
BindUser({commit}, bindId) {
return new Promise((resolve, reject) => {
bindUser(bindId).then(res => {
resolve(res)
}).catch(error => {
reject(error)
})
})
.catch((error) => {
reject(error);
});
});
},
// 获取用户信息
GetInfo({commit, state}) {
GetInfo({ commit, state }) {
return new Promise((resolve, reject) => {
getInfo().then(res => {
const user = res.user
const avatar = user.avatar == "" ? require("@/assets/images/profile.jpg") : process.env.VUE_APP_BASE_API + user.avatar;
if (res.roles && res.roles.length > 0) { // 验证返回的roles是否是一个非空数组
commit('SET_ROLES', res.roles)
commit('SET_PERMISSIONS', res.permissions)
} else {
commit('SET_ROLES', ['ROLE_DEFAULT'])
}
commit('SET_NAME', user.userName)
commit('SET_AVATAR', avatar)
commit('SET_USERID', user.userId)
resolve(res)
}).catch(error => {
reject(error)
})
})
getInfo()
.then((res) => {
const user = res.user;
const avatar = user.avatar === '' || user.avatar == null ? require('@/assets/images/profile.jpg') : process.env.VUE_APP_BASE_API + user.avatar;
if (res.roles && res.roles.length > 0) {
// 验证返回的roles是否是一个非空数组
commit('SET_ROLES', res.roles);
commit('SET_PERMISSIONS', res.permissions);
} else {
commit('SET_ROLES', ['ROLE_DEFAULT']);
}
commit('SET_NAME', user.userName);
commit('SET_AVATAR', avatar);
commit('SET_MQTT', res.mqtt);
setUserId(user.userId);
resolve(res);
})
.catch((error) => {
reject(error);
});
});
},
// 退出系统
LogOut({commit, state}) {
LogOut({ commit, state }) {
return new Promise((resolve, reject) => {
logout(state.token).then(() => {
commit('SET_TOKEN', '')
commit('SET_ROLES', [])
commit('SET_PERMISSIONS', [])
removeToken()
resolve()
}).catch(error => {
reject(error)
})
})
logout(state.token)
.then(() => {
commit('SET_TOKEN', '');
commit('SET_ROLES', []);
commit('SET_PERMISSIONS', []);
removeToken();
removeUserId();
resolve();
})
.catch((error) => {
reject(error);
});
});
},
// 前端 登出
FedLogOut({commit}) {
return new Promise(resolve => {
commit('SET_TOKEN', '')
removeToken()
resolve()
})
}
}
}
FedLogOut({ commit }) {
return new Promise((resolve) => {
commit('SET_TOKEN', '');
removeToken();
resolve();
});
},
},
};
export default user
export default user;

View File

@@ -1,6 +1,7 @@
import Cookies from 'js-cookie'
const TokenKey = 'Admin-Token'
const UserId = 'userId'
export function getToken() {
return Cookies.get(TokenKey)
@@ -13,3 +14,15 @@ export function setToken(token) {
export function removeToken() {
return Cookies.remove(TokenKey)
}
export function getUserId() {
return Cookies.get(UserId)
}
export function setUserId(userId) {
return Cookies.set(UserId, userId)
}
export function removeUserId() {
return Cookies.remove(UserId)
}

Some files were not shown because too many files have changed in this diff Show More