pull/1/head
pnoker 6 years ago
parent 218402fb7e
commit 8d32210694

@ -8,7 +8,7 @@ services:
image: pnoker/dc3-web:3.0 image: pnoker/dc3-web:3.0
restart: always restart: always
ports: ports:
- 80:80 - 8000:80
- 443:443 - 443:443
container_name: dc3.web container_name: dc3.web
hostname: dc3.com hostname: dc3.com

@ -12,7 +12,7 @@ server {
root /usr/share/nginx/html; root /usr/share/nginx/html;
} }
return 301 https://$server_name$request_uri; return 301 https://$server_name$request_uri;
} }
server { server {
@ -36,6 +36,14 @@ server {
index index.html index.htm; index index.html index.htm;
} }
location ^~/user_api/ {
proxy_pass http://dc3-auth:8300/;
}
location ^~/device_api/ {
proxy_pass http://dc3-manager:8400/;
}
error_page 500 502 503 504 /50x.html; error_page 500 502 503 504 /50x.html;
location = /50x.html { location = /50x.html {
root /usr/share/nginx/html; root /usr/share/nginx/html;

14104
package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -24,6 +24,7 @@
"nprogress": "latest", "nprogress": "latest",
"vue": "^2.6.11", "vue": "^2.6.11",
"vue-axios": "^2.1.5", "vue-axios": "^2.1.5",
"vue-gemini-scrollbar": "^2.0.1",
"vue-router": "^3.1.5", "vue-router": "^3.1.5",
"vuex": "^3.1.2" "vuex": "^3.1.2"
}, },

@ -68,7 +68,7 @@
} }
</style> </style>
</head> </head>
<body ondragstart="return false" onselectstart="return false"> <body ondragstart="return false">
<noscript> <noscript>
<strong>很抱歉,如果没有 JavaScript 支持DC3 WEB 将不能正常工作。请启用浏览器的 JavaScript 然后继续。</strong> <strong>很抱歉,如果没有 JavaScript 支持DC3 WEB 将不能正常工作。请启用浏览器的 JavaScript 然后继续。</strong>
</noscript> </noscript>
@ -89,5 +89,6 @@
</div> </div>
</div> </div>
</div> </div>
<script src="<%= BASE_URL %>js/axios/0.19.2/axios.min.js" charset="utf-8"></script>
</body> </body>
</html> </html>

File diff suppressed because one or more lines are too long

@ -1,61 +0,0 @@
import request from '@/config/axios'
export const groupApi = {
add: (group) => request({
url: '/api/manager/group/add',
method: 'post',
data: group
}),
delete: (id) => request({
url: '/api/manager/group/delete/' + id,
method: 'post'
}),
update: (group) => request({
url: '/api/manager/group/update',
method: 'post',
data: group
}),
selectById: (id) => request({
url: '/api/manager/group/id/' + id,
method: 'get'
}),
list: (group) => request({
url: '/api/manager/group/list',
method: 'post',
data: group
})
};
export const deviceApi = {
add: (group) => request({
url: '/device_api/manager/device/add',
method: 'post',
data: group
}),
delete: (id) => request({
url: '/device_api/manager/device/delete/' + id,
method: 'post'
}),
update: (group) => request({
url: '/device_api/manager/device/update',
method: 'post',
data: group
}),
selectById: (id) => request({
url: '/device_api/manager/device/id/' + id,
method: 'get'
}),
selectByCode: (code) => request({
url: '/device_api/manager/device/code/' + code,
method: 'get'
}),
selectByGroupAndName: (groupId, name) => request({
url: '/device_api/manager/device/group/' + groupId + '/name/' + name,
method: 'get'
}),
list: (group) => request({
url: '/device_api/manager/device/list',
method: 'post',
data: group
})
};

@ -0,0 +1,95 @@
import request from '@/config/axios'
export const groupApi = {
add: (group) => request({
url: '/device_api/manager/group/add',
method: 'post',
data: group
}),
delete: (id) => request({
url: '/device_api/manager/group/delete/' + id,
method: 'post'
}),
update: (group) => request({
url: '/device_api/manager/group/update',
method: 'post',
data: group
}),
selectById: (id) => request({
url: '/device_api/manager/group/id/' + id,
method: 'get'
}),
list: (group) => request({
url: '/device_api/manager/group/list',
method: 'post',
data: group
}),
dictionary: () => request({
url: '/device_api/manager/group/dictionary',
method: 'get'
})
};
export const profileApi = {
add: (profile) => request({
url: '/device_api/manager/profile/add',
method: 'post',
data: profile
}),
delete: (id) => request({
url: '/device_api/manager/profile/delete/' + id,
method: 'post'
}),
update: (profile) => request({
url: '/device_api/manager/profile/update',
method: 'post',
data: profile
}),
selectById: (id) => request({
url: '/device_api/manager/profile/id/' + id,
method: 'get'
}),
list: (profile) => request({
url: '/device_api/manager/profile/list',
method: 'post',
data: profile
}),
dictionary: () => request({
url: '/device_api/manager/profile/dictionary',
method: 'get'
})
};
export const deviceApi = {
add: (device) => request({
url: '/device_api/manager/device/add',
method: 'post',
data: device
}),
delete: (id) => request({
url: '/device_api/manager/device/delete/' + id,
method: 'post'
}),
update: (device) => request({
url: '/device_api/manager/device/update',
method: 'post',
data: device
}),
selectById: (id) => request({
url: '/device_api/manager/device/id/' + id,
method: 'get'
}),
selectByCode: (code) => request({
url: '/device_api/manager/device/code/' + code,
method: 'get'
}),
selectByGroupAndName: (groupId, name) => request({
url: '/device_api/manager/device/group/' + groupId + '/name/' + name,
method: 'get'
}),
list: (device) => request({
url: '/device_api/manager/device/list',
method: 'post',
data: device
})
};

@ -0,0 +1,7 @@
.el-scrollbar__view {
height: 100%;
}
.el-scrollbar__wrap {
overflow-x: hidden;
}

@ -39,13 +39,14 @@ axios.interceptors.response.use(res => {
// 如果请求为 !ok 默认统一处理 // 如果请求为 !ok 默认统一处理
if (!ok) { if (!ok) {
Message({ Message({
center: true,
type: 'error', type: 'error',
showClose: true, showClose: true,
message: message message: message
}); });
return Promise.reject(new Error(message)); return Promise.reject(new Error(message));
} }
return res; return res.data;
}, error => { }, error => {
NProgress.done(); NProgress.done();
return Promise.reject(new Error(error)); return Promise.reject(new Error(error));

@ -8,6 +8,7 @@ import './plugins/element/element.js'
import './config/permission'; import './config/permission';
Vue.use(VueAxios, axios); Vue.use(VueAxios, axios);
Vue.config.productionTip = false; Vue.config.productionTip = false;
new Vue({ new Vue({

@ -1,17 +1,19 @@
import Vue from 'vue' import Vue from 'vue'
import Element from 'element-ui' import Element from 'element-ui'
import Avue from "@smallwei/avue";
import locale from 'element-ui/lib/locale/lang/zh-CN'
import 'element-ui/lib/theme-chalk/index.css'; import 'element-ui/lib/theme-chalk/index.css';
import './element-variables.scss' import './element-variables.scss'
import '@smallwei/avue/lib/index.css'
import locale from 'element-ui/lib/locale/lang/zh-CN'
import GeminiScrollbar from 'vue-gemini-scrollbar'
import baseCard from '@/components/card/base-card' import baseCard from '@/components/card/base-card'
import titleCard from '@/components/card/title-card' import titleCard from '@/components/card/title-card'
import Avue from '@smallwei/avue'
import '@smallwei/avue/lib/index.css'
Vue.use(Element, {locale}); Vue.use(Element, {locale});
Vue.use(Avue); Vue.use(Avue);
Vue.use(GeminiScrollbar);
Vue.component('base-card', baseCard); Vue.component('base-card', baseCard);
Vue.component('title-card', titleCard); Vue.component('title-card', titleCard);

@ -80,4 +80,4 @@ export default [
} }
] ]
} }
] ]

@ -12,11 +12,9 @@ const user = {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
generateToken(user).then(res => { generateToken(user).then(res => {
const data = res.data; const data = res.data;
if (data.ok) { commit('SET_USER', user);
commit('SET_USER', user); commit('SET_TOKEN', data);
commit('SET_TOKEN', data.message); resolve();
resolve();
}
}).catch(error => { }).catch(error => {
reject(error); reject(error);
}) })
@ -24,11 +22,8 @@ const user = {
}, },
CheckTokenValid(body) { CheckTokenValid(body) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
checkTokenValid(body).then(res => { checkTokenValid(body).then(() => {
const data = res.data; resolve();
if (data.ok) {
resolve();
}
}).catch(error => { }).catch(error => {
reject(error) reject(error)
}) })

@ -10,16 +10,15 @@
mode="horizontal" mode="horizontal"
:router=true> :router=true>
<el-menu-item index="/home"><span class="el-icon-menu"/>首页</el-menu-item> <el-menu-item index="/home"><span class="el-icon-menu"/>首页</el-menu-item>
<el-menu-item index="/things">物联</el-menu-item> <el-menu-item index="/picture">驱动</el-menu-item>
<el-menu-item index="/template">模板</el-menu-item> <el-menu-item index="/template">模板</el-menu-item>
<el-menu-item index="/label">位号</el-menu-item>
<el-menu-item index="/things">设备</el-menu-item>
<el-menu-item index="/now">实时</el-menu-item> <el-menu-item index="/now">实时</el-menu-item>
<el-menu-item index="/history">历史</el-menu-item> <el-menu-item index="/history">历史</el-menu-item>
<el-menu-item index="/alarm">报警</el-menu-item>
<el-menu-item index="/label">标签</el-menu-item>
<el-menu-item index="/picture">图片</el-menu-item>
<el-menu-item index="/video">视频</el-menu-item> <el-menu-item index="/video">视频</el-menu-item>
<el-menu-item index="/alarm">报警</el-menu-item>
<el-menu-item index="/setting">设置</el-menu-item> <el-menu-item index="/setting">设置</el-menu-item>
<el-menu-item index="/help">帮助</el-menu-item>
<el-menu-item index="/about">关于</el-menu-item> <el-menu-item index="/about">关于</el-menu-item>
</el-menu> </el-menu>
</el-col> </el-col>
@ -37,8 +36,7 @@
</span> </span>
<el-dropdown-menu slot="dropdown"> <el-dropdown-menu slot="dropdown">
<el-dropdown-item command="profile">个人信息</el-dropdown-item> <el-dropdown-item command="profile">个人信息</el-dropdown-item>
<el-dropdown-item command="setting" divided>设置</el-dropdown-item> <el-dropdown-item command="help">帮助</el-dropdown-item>
<el-dropdown-item command="about">关于</el-dropdown-item>
<el-dropdown-item command="logout" divided>退出登录</el-dropdown-item> <el-dropdown-item command="logout" divided>退出登录</el-dropdown-item>
</el-dropdown-menu> </el-dropdown-menu>
</el-dropdown> </el-dropdown>
@ -46,9 +44,9 @@
</el-col> </el-col>
</div> </div>
<div class="body"> <div class="body">
<el-scrollbar> <GeminiScrollbar>
<router-view/> <router-view/>
</el-scrollbar> </GeminiScrollbar>
</div> </div>
</div> </div>
</template> </template>
@ -136,17 +134,9 @@
right: 0; right: 0;
left: 0; left: 0;
bottom: 0; bottom: 0;
padding: 4px; padding: 4px 1px 4px 4px;
position: absolute; position: absolute;
background: #f0f2f5; background: #f0f2f5;
.el-scrollbar {
height: 100%;
.el-scrollbar__wrap {
overflow-x: hidden;
}
}
} }
</style> </style>

@ -1,65 +1,38 @@
<template> <template>
<el-col :span="24"> <el-col :span="24">
<el-col :span="4"> <base-card>
<base-card> <avue-crud :option="listOption"
<avue-tree :option="treeOption" :data="listData"
:data="treeData" :page="page"
@node-click="nodeClick"/> :table-loading="loading"
</base-card> ref="crud"
</el-col> v-model="listForm"
<el-col :span="20"> @on-load="list"
<base-card> @row-save="listAdd"
<avue-crud :option="option" @row-del="listDelete"
:data="data" @row-update="listUpdate"
:page="page" @search-reset="searchReset"
ref="crud" @search-change="searchChange"
v-model="form" @refresh-change="refreshChange"
@on-load="onLoad" @size-change="sizeChange"
@row-save="rowSave" @current-change="currentChange"
@row-update="rowUpdate" >
@row-del="rowDel" </avue-crud>
@search-change="searchChange" </base-card>
@search-reset="searchReset">
<template slot="menuLeft">
<el-button type="danger"
size="small"
icon="el-icon-delete"
plain>
</el-button>
</template>
</avue-crud>
</base-card>
</el-col>
</el-col> </el-col>
</template> </template>
<script> <script>
import {deviceApi} from '@/api/device' import {deviceApi, groupApi, profileApi} from '@/api/manager'
import {failMessage, successMessage} from "@/util/util"; import {successMessage} from "@/util/util";
export default { export default {
data() { data() {
return { return {
form: {},
query: {}, query: {},
selectionList: [], listForm: {},
page: { listData: [],
currentPage: 1, listOption: {
total: 0,
pageSize: 20
},
treeOption: {
nodeKey: 'id',
size: 'medium',
formOption: {
labelWidth: 100,
column: [{
label: '分组',
prop: 'group'
}],
}
},
option: {
tip: false, tip: false,
index: true, index: true,
stripe: true, stripe: true,
@ -72,31 +45,86 @@
{ {
label: '设备', label: '设备',
prop: 'name', prop: 'name',
width: 220,
span: 24,
search: true,
searchSpan: 5,
rules: [
{
required: true,
message: '请输入设备名称',
trigger: 'blur'
}, {
min: 2,
max: 32,
message: '请输入 2~32 位字长的设备名称',
trigger: 'blur'
}, {
pattern: /^[A-Za-z0-9\u4e00-\u9fa5]+$/,
message: '请输入正确格式的设备名称name01、名称01'
}
]
}, {
label: '编码',
prop: 'code',
width: 280,
search: true,
searchSpan: 5,
disabled: true,
rules: [{
message: '请输入设备编码',
trigger: 'blur'
}]
}, {
label: '分组',
prop: 'groupId',
width: 150,
search: true, search: true,
searchSpan: 5,
type: 'select',
filterable: true,
searchFilterable: true,
dicData: [],
props: {
label: 'name',
value: 'id'
},
rules: [{ rules: [{
required: true, required: true,
message: "请输入设备名称", message: '请选择所属分组',
trigger: "blur" trigger: 'click'
}] }]
}, { }, {
label: '编码', label: '模板',
prop: 'code', prop: 'profileId',
width: 180,
search: true, search: true,
searchSpan: 5,
type: 'select',
filterable: true,
searchFilterable: true,
dicData: [],
props: {
label: 'name',
value: 'id'
},
rules: [{ rules: [{
required: true, required: true,
message: "请输入设备编码", message: '请选择使用模板',
trigger: "blur" trigger: 'click'
}] }]
}, { }, {
label: '状态', label: '状态',
prop: 'status', prop: 'status',
width: 100,
search: true, search: true,
searchSpan: 4,
disabled: true,
type: 'select', type: 'select',
searchFilterable: true,
value: 2,
dicData: [ dicData: [
{ {
label: '全部',
value: -1
}, {
label: '离线', label: '离线',
value: 0 value: 0
}, { }, {
@ -112,123 +140,129 @@
label: '失效', label: '失效',
value: 4 value: 4
} }
], ]
rules: [{
required: true,
message: "请输入设备状态",
trigger: "blur"
}]
}, {
label: '分组',
prop: 'groupId'
}, {
label: '模板',
prop: 'profileId'
}, { }, {
label: '描述', label: '描述',
prop: 'description' prop: 'description',
width: 220,
span: 24,
type: 'textarea'
}, { }, {
label: "创建日期", label: '创建日期',
prop: "createTime", prop: 'createTime',
type: "date", width: 180,
format: "yyyy-MM-dd hh:mm:ss", span: 12,
valueFormat: "yyyy-MM-dd hh:mm:ss" disabled: true,
type: 'date',
format: 'yyyy-MM-dd HH:mm:ss',
valueFormat: 'yyyy-MM-dd HH:mm:ss'
}, { }, {
label: "修改日期", label: '修改日期',
prop: "updateTime", prop: 'updateTime',
type: "date", width: 180,
format: "yyyy-MM-dd hh:mm:ss", span: 12,
valueFormat: "yyyy-MM-dd hh:mm:ss" disabled: true,
type: 'date',
format: 'yyyy-MM-dd HH:mm:ss',
valueFormat: 'yyyy-MM-dd HH:mm:ss'
} }
] ]
}, },
treeData: [ selectionList: [],
{ loading: true,
id: 0, page: {
label: '一级部门', total: 0,
value: 0, pageSize: 20,
children: [ currentPage: 1
{ }
id: 1,
label: '一级部门1',
value: 0,
}
]
}],
data: []
} }
}, },
created() {
this.group();
this.profile();
},
methods: methods:
{ {
onLoad() { list(page) {
deviceApi.list( this.loading = true;
{ deviceApi.list(Object.assign({
page: { page: {
current: this.page.currentPage, current: page.currentPage,
size: this.page.pageSize size: page.pageSize
}
} }
).then(res => { }, this.query)).then(res => {
const data = res.data; const data = res.data;
if (data.ok) { this.page.total = data.total;
this.page.total = data.data.total; this.listData = data.records;
this.data = data.data.records; }).finally(() => {
} this.loading = false;
}); });
}, },
rowSave(row, done, loading) { group() {
deviceApi.add(row).then(res => { groupApi.dictionary().then(res => {
loading(); this.listOption.column[this.$refs.crud.findColumnIndex('groupId')].dicData = res.data;
const data = res.data; }).catch((e) => {
if (data.ok) { console.log(e);
this.onLoad(this.page);
successMessage();
} else {
failMessage();
}
}, error => {
console.log(error);
}); });
done();
}, },
rowUpdate(row, index, done, loading) { profile() {
deviceApi.update(row).then(res => { profileApi.dictionary().then(res => {
this.listOption.column[this.$refs.crud.findColumnIndex('profileId')].dicData = res.data;
}).catch((e) => {
console.log(e);
});
},
listAdd(row, done, loading) {
deviceApi.add(row).then(() => {
loading(); loading();
const data = res.data; this.list(this.page);
if (data.ok) { successMessage();
this.onLoad(this.page); }).finally(() => {
successMessage(); done();
} else {
failMessage();
}
}, error => {
console.log(error);
}); });
done();
}, },
rowDel(row) { listDelete(row) {
this.$confirm('是否删除该条设备?', '提示', { this.$confirm('是否删除该条设备?', '提示', {
confirmButtonText: '确定', confirmButtonText: '确定',
cancelButtonText: '取消', cancelButtonText: '取消',
type: 'warning' type: 'warning'
}).then(() => { }).then(() => {
return deviceApi.delete(row.id); return deviceApi.delete(row.id);
}).then(res => { }).then(() => {
const data = res.data; this.list(this.page);
if (data.ok) { successMessage();
this.onLoad(this.page); });
successMessage(); },
} else { listUpdate(row, index, done, loading) {
failMessage(); deviceApi.update(row).then(() => {
} loading();
this.list(this.page);
successMessage();
}).finally(() => {
done();
}); });
}, },
refreshChange() {
this.list(this.page);
},
currentChange(page) {
this.page.currentPage = page;
},
sizeChange(pageSize) {
this.page.pageSize = pageSize;
},
searchChange(params, done) {
this.query = params;
this.list(this.page);
done();
},
searchReset() {
this.query = {};
this.list(this.page);
}
} }
} }
</script> </script>
<style lang="scss"> <style lang="scss">
.avue-tree {
height: 876px;
}
</style> </style>

@ -13,7 +13,7 @@ module.exports = {
} }
}, },
'/user_api': { '/user_api': {
target: 'http://localhost:8400', target: 'http://dc3-auth:8300',
changeOrigin: true, changeOrigin: true,
ws: true, ws: true,
pathRewrite: { pathRewrite: {
@ -21,7 +21,7 @@ module.exports = {
} }
}, },
'/device_api': { '/device_api': {
target: 'http://localhost:8600', target: 'http://dc3-manager:8400',
changeOrigin: true, changeOrigin: true,
ws: true, ws: true,
pathRewrite: { pathRewrite: {
@ -30,4 +30,4 @@ module.exports = {
} }
} }
} }
}; };

10078
yarn.lock

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save