Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
IoTSharp
IoTSharp
提交
be1998e5
IoTSharp
项目概览
IoTSharp
/
IoTSharp
9 个月 前同步成功
通知
15
Star
2
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
IoTSharp
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
未验证
提交
be1998e5
编写于
6月 20, 2019
作者:
麦壳饼
提交者:
GitHub
6月 20, 2019
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #7 from masterchen/master
ui changes
上级
839f477c
37449b72
变更
14
展开全部
隐藏空白更改
内联
并排
Showing
14 changed file
with
1038 addition
and
1124 deletion
+1038
-1124
IoTSharp/ClientApp/package.json
IoTSharp/ClientApp/package.json
+2
-1
IoTSharp/ClientApp/src/api/device.js
IoTSharp/ClientApp/src/api/device.js
+47
-14
IoTSharp/ClientApp/src/router/index.js
IoTSharp/ClientApp/src/router/index.js
+26
-11
IoTSharp/ClientApp/src/utils/request.js
IoTSharp/ClientApp/src/utils/request.js
+1
-3
IoTSharp/ClientApp/src/views/device/add.vue
IoTSharp/ClientApp/src/views/device/add.vue
+0
-381
IoTSharp/ClientApp/src/views/device/component-lib.vue
IoTSharp/ClientApp/src/views/device/component-lib.vue
+141
-0
IoTSharp/ClientApp/src/views/device/device-board.vue
IoTSharp/ClientApp/src/views/device/device-board.vue
+611
-0
IoTSharp/ClientApp/src/views/device/device-visionboard.vue
IoTSharp/ClientApp/src/views/device/device-visionboard.vue
+198
-0
IoTSharp/ClientApp/src/views/device/utils.js
IoTSharp/ClientApp/src/views/device/utils.js
+2
-0
IoTSharp/ClientApp/src/views/login/index.vue
IoTSharp/ClientApp/src/views/login/index.vue
+7
-6
IoTSharp/ClientApp/src/views/login/index.vue.bak
IoTSharp/ClientApp/src/views/login/index.vue.bak
+0
-340
IoTSharp/ClientApp/src/views/login/register.vue
IoTSharp/ClientApp/src/views/login/register.vue
+2
-3
IoTSharp/ClientApp/src/views/login/register.vue.bak
IoTSharp/ClientApp/src/views/login/register.vue.bak
+0
-365
IoTSharp/ClientApp/src/views/permission/role.vue
IoTSharp/ClientApp/src/views/permission/role.vue
+1
-0
未找到文件。
IoTSharp/ClientApp/package.json
浏览文件 @
be1998e5
...
@@ -51,7 +51,7 @@
...
@@ -51,7 +51,7 @@
"codemirror"
:
"5.45.0"
,
"codemirror"
:
"5.45.0"
,
"driver.js"
:
"0.9.5"
,
"driver.js"
:
"0.9.5"
,
"dropzone"
:
"5.5.1"
,
"dropzone"
:
"5.5.1"
,
"echarts"
:
"4.2.1"
,
"echarts"
:
"
^
4.2.1"
,
"element-ui"
:
"2.7.0"
,
"element-ui"
:
"2.7.0"
,
"file-saver"
:
"2.0.1"
,
"file-saver"
:
"2.0.1"
,
"fuse.js"
:
"3.4.4"
,
"fuse.js"
:
"3.4.4"
,
...
@@ -66,6 +66,7 @@
...
@@ -66,6 +66,7 @@
"sortablejs"
:
"1.8.4"
,
"sortablejs"
:
"1.8.4"
,
"tasksfile"
:
"^5.1.0"
,
"tasksfile"
:
"^5.1.0"
,
"tui-editor"
:
"1.3.3"
,
"tui-editor"
:
"1.3.3"
,
"v-charts"
:
"^1.19.0"
,
"vue"
:
"2.6.10"
,
"vue"
:
"2.6.10"
,
"vue-count-to"
:
"1.0.13"
,
"vue-count-to"
:
"1.0.13"
,
"vue-i18n"
:
"^8.11.2"
,
"vue-i18n"
:
"^8.11.2"
,
...
...
IoTSharp/ClientApp/src/api/device.js
浏览文件 @
be1998e5
import
request
from
'
@/utils/request
'
import
request
from
'
@/utils/request
'
// Get all of the customer's devices.
export
function
getDevices
(
id
)
{
export
function
getDevices
(
id
)
{
return
request
({
return
request
({
url
:
'
/Devices/Customers/
'
+
id
,
url
:
'
/Devices/Customers/
'
+
id
,
...
@@ -7,35 +8,67 @@ export function getDevices(id) {
...
@@ -7,35 +8,67 @@ export function getDevices(id) {
})
})
}
}
export
function
postDevice
(
data
)
{
// Get a device's detail
export
function
getDevice
(
id
)
{
return
request
({
return
request
({
url
:
'
/Devices
'
,
url
:
'
/Devices/
'
+
id
,
method
:
'
get
'
})
}
// Create a new device
export
function
creatDevice
(
data
)
{
return
request
({
url
:
'
/Devices/
'
,
method
:
'
post
'
,
method
:
'
post
'
,
data
data
})
})
}
}
export
function
fetchArticle
(
id
)
{
// DELETE: api/Devices/5
export
function
deleteDevice
(
data
)
{
return
request
({
return
request
({
url
:
'
/
article/detail
'
,
url
:
'
/
Devices
'
,
method
:
'
get
'
,
method
:
'
delete
'
,
params
:
{
id
}
data
})
})
}
}
// for pagin usage,current not support
export
function
fetch
Pv
(
pv
)
{
export
function
getDevice
Pv
(
pv
)
{
return
request
({
return
request
({
url
:
'
/
article
/pv
'
,
url
:
'
/
Devices
/pv
'
,
method
:
'
get
'
,
method
:
'
get
'
,
params
:
{
pv
}
params
:
{
pv
}
})
})
}
}
// modify device
export
function
updateDevice
(
id
,
data
)
{
export
function
updateArticle
(
data
)
{
return
request
({
return
request
({
url
:
'
/article/update
'
,
url
:
`/Devices/
${
id
}
`
,
method
:
'
p
os
t
'
,
method
:
'
p
u
t
'
,
data
data
})
})
}
}
// Get a device's credentials
export
function
getDeviceAccessToken
(
id
)
{
return
request
({
url
:
`/Devices/
${
id
}
/Identity`
,
method
:
'
get
'
})
}
// Request attribute values by device access token from the server
export
function
getDeviceAttributes
(
id
)
{
return
request
({
url
:
`/Devices/
${
id
}
/AttributeLatest`
,
method
:
'
get
'
})
}
// Request telemetry values by device access token from the server
export
function
getDeviceTelemetryLatest
(
id
)
{
return
request
({
url
:
`/Devices/
${
id
}
/TelemetryLatest`
,
method
:
'
get
'
})
}
IoTSharp/ClientApp/src/router/index.js
浏览文件 @
be1998e5
...
@@ -7,10 +7,10 @@ Vue.use(Router)
...
@@ -7,10 +7,10 @@ Vue.use(Router)
import
Layout
from
'
@/layout
'
import
Layout
from
'
@/layout
'
/* Router Modules */
/* Router Modules */
import
componentsRouter
from
'
./modules/components
'
//
import componentsRouter from './modules/components'
import
chartsRouter
from
'
./modules/charts
'
//
import chartsRouter from './modules/charts'
import
tableRouter
from
'
./modules/table
'
//
import tableRouter from './modules/table'
import
nestedRouter
from
'
./modules/nested
'
//
import nestedRouter from './modules/nested'
/**
/**
* Note: sub-menu only appear when route children.length >= 1
* Note: sub-menu only appear when route children.length >= 1
...
@@ -110,12 +110,27 @@ export const constantRoutes = [
...
@@ -110,12 +110,27 @@ export const constantRoutes = [
}
}
},
},
{
{
path
:
'
ad
d
'
,
path
:
'
boar
d
'
,
component
:
()
=>
import
(
'
@/views/device/
ad
d
'
),
component
:
()
=>
import
(
'
@/views/device/
device-boar
d
'
),
name
:
'
Device
Ad
d
'
,
name
:
'
Device
Boar
d
'
,
meta
:
{
meta
:
{
title
:
'
添加设备
'
title
:
'
设备详情
'
// if do not set roles, means: this page does not require permission
}
},
{
path
:
'
compomentlib
'
,
component
:
()
=>
import
(
'
@/views/device/component-lib
'
),
name
:
'
ComponentLib
'
,
meta
:
{
title
:
'
部件库
'
}
},
{
path
:
'
DeviceVisionBoardboard
'
,
component
:
()
=>
import
(
'
@/views/device/device-visionboard
'
),
name
:
'
DeviceVisionBoardboard
'
,
meta
:
{
title
:
'
仪表盘
'
}
}
},
},
{
{
...
@@ -204,8 +219,8 @@ export const asyncRoutes = [
...
@@ -204,8 +219,8 @@ export const asyncRoutes = [
}
}
]
]
},
},
/** when your routing map is too long, you can split it into small modules **/
/** when your routing map is too long, you can split it into small modules **/
/*
componentsRouter,
componentsRouter,
chartsRouter,
chartsRouter,
nestedRouter,
nestedRouter,
...
@@ -414,7 +429,7 @@ export const asyncRoutes = [
...
@@ -414,7 +429,7 @@ export const asyncRoutes = [
}
}
]
]
},
},
*/
// 404 page must be placed at the end !!!
// 404 page must be placed at the end !!!
{
path
:
'
*
'
,
redirect
:
'
/404
'
,
hidden
:
true
}
{
path
:
'
*
'
,
redirect
:
'
/404
'
,
hidden
:
true
}
]
]
...
...
IoTSharp/ClientApp/src/utils/request.js
浏览文件 @
be1998e5
...
@@ -6,6 +6,7 @@ import { getToken } from '@/utils/auth'
...
@@ -6,6 +6,7 @@ import { getToken } from '@/utils/auth'
// create an axios instance
// create an axios instance
const
service
=
axios
.
create
({
const
service
=
axios
.
create
({
baseURL
:
process
.
env
.
VUE_APP_BASE_API
,
// url = base url + request url
baseURL
:
process
.
env
.
VUE_APP_BASE_API
,
// url = base url + request url
// baseURL: process.env.BASE_API,
// withCredentials: true, // send cookies when cross-domain requests
// withCredentials: true, // send cookies when cross-domain requests
timeout
:
5000
// request timeout
timeout
:
5000
// request timeout
})
})
...
@@ -44,9 +45,6 @@ service.interceptors.response.use(
...
@@ -44,9 +45,6 @@ service.interceptors.response.use(
*/
*/
response
=>
{
response
=>
{
const
res
=
response
.
data
const
res
=
response
.
data
console
.
log
(
'
response =
'
)
console
.
log
(
response
)
console
.
log
(
'
response token =
'
)
// if the custom code is not 20000, it is judged as an error.
// if the custom code is not 20000, it is judged as an error.
if
(
res
.
code
!==
10000
)
{
if
(
res
.
code
!==
10000
)
{
Message
({
Message
({
...
...
IoTSharp/ClientApp/src/views/device/add.vue
已删除
100755 → 0
浏览文件 @
839f477c
<
template
>
<div
class=
"app-container"
>
<div
class=
"filter-container"
>
<el-input
v-model=
"listQuery.title"
placeholder=
"Title"
style=
"width: 200px;"
class=
"filter-item"
@
keyup.enter.native=
"handleFilter"
/>
<el-select
v-model=
"listQuery.importance"
placeholder=
"Imp"
clearable
style=
"width: 90px"
class=
"filter-item"
>
<el-option
v-for=
"item in importanceOptions"
:key=
"item"
:label=
"item"
:value=
"item"
/>
</el-select>
<el-select
v-model=
"listQuery.type"
placeholder=
"Type"
clearable
class=
"filter-item"
style=
"width: 130px"
>
<el-option
v-for=
"item in calendarTypeOptions"
:key=
"item.key"
:label=
"item.display_name+'('+item.key+')'"
:value=
"item.key"
/>
</el-select>
<el-select
v-model=
"listQuery.sort"
style=
"width: 140px"
class=
"filter-item"
@
change=
"handleFilter"
>
<el-option
v-for=
"item in sortOptions"
:key=
"item.key"
:label=
"item.label"
:value=
"item.key"
/>
</el-select>
<el-button
v-waves
class=
"filter-item"
type=
"primary"
icon=
"el-icon-search"
@
click=
"handleFilter"
>
Search
</el-button>
<el-button
class=
"filter-item"
style=
"margin-left: 10px;"
type=
"primary"
icon=
"el-icon-edit"
@
click=
"handleCreate"
>
Add
</el-button>
<el-button
v-waves
:loading=
"downloadLoading"
class=
"filter-item"
type=
"primary"
icon=
"el-icon-download"
@
click=
"handleDownload"
>
Export
</el-button>
<el-checkbox
v-model=
"showReviewer"
class=
"filter-item"
style=
"margin-left:15px;"
@
change=
"tableKey=tableKey+1"
>
reviewer
</el-checkbox>
</div>
<el-table
:key=
"tableKey"
v-loading=
"listLoading"
:data=
"list"
border
fit
highlight-current-row
style=
"width: 100%;"
@
sort-change=
"sortChange"
>
<el-table-column
label=
"ID"
prop=
"id"
sortable=
"custom"
align=
"center"
width=
"80"
>
<template
slot-scope=
"scope"
>
<span>
{{
scope
.
row
.
id
}}
</span>
</
template
>
</el-table-column>
<el-table-column
label=
"Date"
width=
"150px"
align=
"center"
>
<
template
slot-scope=
"scope"
>
<span>
{{
scope
.
row
.
timestamp
|
parseTime
(
'
{y
}
-{m
}
-{d
}
{h
}
:{i
}
'
)
}}
<
/span
>
<
/template
>
<
/el-table-column
>
<
el
-
table
-
column
label
=
"
Title
"
min
-
width
=
"
150px
"
>
<
template
slot
-
scope
=
"
{row
}
"
>
<
span
class
=
"
link-type
"
@
click
=
"
handleUpdate(row)
"
>
{{
row
.
title
}}
<
/span
>
<
el
-
tag
>
{{
row
.
type
|
typeFilter
}}
<
/el-tag
>
<
/template
>
<
/el-table-column
>
<
el
-
table
-
column
label
=
"
Author
"
width
=
"
110px
"
align
=
"
center
"
>
<
template
slot
-
scope
=
"
scope
"
>
<
span
>
{{
scope
.
row
.
author
}}
<
/span
>
<
/template
>
<
/el-table-column
>
<
el
-
table
-
column
v
-
if
=
"
showReviewer
"
label
=
"
Reviewer
"
width
=
"
110px
"
align
=
"
center
"
>
<
template
slot
-
scope
=
"
scope
"
>
<
span
style
=
"
color:red;
"
>
{{
scope
.
row
.
reviewer
}}
<
/span
>
<
/template
>
<
/el-table-column
>
<
el
-
table
-
column
label
=
"
Imp
"
width
=
"
80px
"
>
<
template
slot
-
scope
=
"
scope
"
>
<
svg
-
icon
v
-
for
=
"
n in +scope.row.importance
"
:
key
=
"
n
"
icon
-
class
=
"
star
"
class
=
"
meta-item__icon
"
/>
<
/template
>
<
/el-table-column
>
<
el
-
table
-
column
label
=
"
Readings
"
align
=
"
center
"
width
=
"
95
"
>
<
template
slot
-
scope
=
"
{row
}
"
>
<
span
v
-
if
=
"
row.pageviews
"
class
=
"
link-type
"
@
click
=
"
handleFetchPv(row.pageviews)
"
>
{{
row
.
pageviews
}}
<
/span
>
<
span
v
-
else
>
0
<
/span
>
<
/template
>
<
/el-table-column
>
<
el
-
table
-
column
label
=
"
Status
"
class
-
name
=
"
status-col
"
width
=
"
100
"
>
<
template
slot
-
scope
=
"
{row
}
"
>
<
el
-
tag
:
type
=
"
row.status | statusFilter
"
>
{{
row
.
status
}}
<
/el-tag
>
<
/template
>
<
/el-table-column
>
<
el
-
table
-
column
label
=
"
Actions
"
align
=
"
center
"
width
=
"
230
"
class
-
name
=
"
small-padding fixed-width
"
>
<
template
slot
-
scope
=
"
{row
}
"
>
<
el
-
button
type
=
"
primary
"
size
=
"
mini
"
@
click
=
"
handleUpdate(row)
"
>
Edit
<
/el-button
>
<
el
-
button
v
-
if
=
"
row.status!='published'
"
size
=
"
mini
"
type
=
"
success
"
@
click
=
"
handleModifyStatus(row,'published')
"
>
Publish
<
/el-button
>
<
el
-
button
v
-
if
=
"
row.status!='draft'
"
size
=
"
mini
"
@
click
=
"
handleModifyStatus(row,'draft')
"
>
Draft
<
/el-button
>
<
el
-
button
v
-
if
=
"
row.status!='deleted'
"
size
=
"
mini
"
type
=
"
danger
"
@
click
=
"
handleModifyStatus(row,'deleted')
"
>
Delete
<
/el-button
>
<
/template
>
<
/el-table-column
>
<
/el-table
>
<
pagination
v
-
show
=
"
total>0
"
:
total
=
"
total
"
:
page
.
sync
=
"
listQuery.page
"
:
limit
.
sync
=
"
listQuery.limit
"
@
pagination
=
"
getList
"
/>
<
el
-
dialog
:
title
=
"
textMap[dialogStatus]
"
:
visible
.
sync
=
"
dialogFormVisible
"
>
<
el
-
form
ref
=
"
dataForm
"
:
rules
=
"
rules
"
:
model
=
"
temp
"
label
-
position
=
"
left
"
label
-
width
=
"
70px
"
style
=
"
width: 400px; margin-left:50px;
"
>
<
el
-
form
-
item
label
=
"
Type
"
prop
=
"
type
"
>
<
el
-
select
v
-
model
=
"
temp.type
"
class
=
"
filter-item
"
placeholder
=
"
Please select
"
>
<
el
-
option
v
-
for
=
"
item in calendarTypeOptions
"
:
key
=
"
item.key
"
:
label
=
"
item.display_name
"
:
value
=
"
item.key
"
/>
<
/el-select
>
<
/el-form-item
>
<
el
-
form
-
item
label
=
"
Date
"
prop
=
"
timestamp
"
>
<
el
-
date
-
picker
v
-
model
=
"
temp.timestamp
"
type
=
"
datetime
"
placeholder
=
"
Please pick a date
"
/>
<
/el-form-item
>
<
el
-
form
-
item
label
=
"
Title
"
prop
=
"
title
"
>
<
el
-
input
v
-
model
=
"
temp.title
"
/>
<
/el-form-item
>
<
el
-
form
-
item
label
=
"
Status
"
>
<
el
-
select
v
-
model
=
"
temp.status
"
class
=
"
filter-item
"
placeholder
=
"
Please select
"
>
<
el
-
option
v
-
for
=
"
item in statusOptions
"
:
key
=
"
item
"
:
label
=
"
item
"
:
value
=
"
item
"
/>
<
/el-select
>
<
/el-form-item
>
<
el
-
form
-
item
label
=
"
Imp
"
>
<
el
-
rate
v
-
model
=
"
temp.importance
"
:
colors
=
"
['#99A9BF', '#F7BA2A', '#FF9900']
"
:
max
=
"
3
"
style
=
"
margin-top:8px;
"
/>
<
/el-form-item
>
<
el
-
form
-
item
label
=
"
Remark
"
>
<
el
-
input
v
-
model
=
"
temp.remark
"
:
autosize
=
"
{ minRows: 2, maxRows: 4
}
"
type
=
"
textarea
"
placeholder
=
"
Please input
"
/>
<
/el-form-item
>
<
/el-form
>
<
div
slot
=
"
footer
"
class
=
"
dialog-footer
"
>
<
el
-
button
@
click
=
"
dialogFormVisible = false
"
>
Cancel
<
/el-button
>
<
el
-
button
type
=
"
primary
"
@
click
=
"
dialogStatus==='create'?createData():updateData()
"
>
Confirm
<
/el-button
>
<
/div
>
<
/el-dialog
>
<
el
-
dialog
:
visible
.
sync
=
"
dialogPvVisible
"
title
=
"
Reading statistics
"
>
<
el
-
table
:
data
=
"
pvData
"
border
fit
highlight
-
current
-
row
style
=
"
width: 100%
"
>
<
el
-
table
-
column
prop
=
"
key
"
label
=
"
Channel
"
/>
<
el
-
table
-
column
prop
=
"
pv
"
label
=
"
Pv
"
/>
<
/el-table
>
<
span
slot
=
"
footer
"
class
=
"
dialog-footer
"
>
<
el
-
button
type
=
"
primary
"
@
click
=
"
dialogPvVisible = false
"
>
Confirm
<
/el-button
>
<
/span
>
<
/el-dialog
>
<
/div
>
<
/template
>
<
script
>
import
{
fetchList
,
fetchPv
,
createArticle
,
updateArticle
}
from
'
@/api/article
'
import
waves
from
'
@/directive/waves
'
// waves directive
import
{
parseTime
}
from
'
@/utils
'
import
Pagination
from
'
@/components/Pagination
'
// secondary package based on el-pagination
const
calendarTypeOptions
=
[
{
key
:
'
CN
'
,
display_name
:
'
China
'
}
,
{
key
:
'
US
'
,
display_name
:
'
USA
'
}
,
{
key
:
'
JP
'
,
display_name
:
'
Japan
'
}
,
{
key
:
'
EU
'
,
display_name
:
'
Eurozone
'
}
]
// arr to obj, such as
{
CN
:
"
China
"
,
US
:
"
USA
"
}
const
calendarTypeKeyValue
=
calendarTypeOptions
.
reduce
((
acc
,
cur
)
=>
{
acc
[
cur
.
key
]
=
cur
.
display_name
return
acc
}
,
{
}
)
export
default
{
name
:
'
DeviceAdd
'
,
components
:
{
Pagination
}
,
directives
:
{
waves
}
,
filters
:
{
statusFilter
(
status
)
{
const
statusMap
=
{
published
:
'
success
'
,
draft
:
'
info
'
,
deleted
:
'
danger
'
}
return
statusMap
[
status
]
}
,
typeFilter
(
type
)
{
return
calendarTypeKeyValue
[
type
]
}
}
,
data
()
{
return
{
tableKey
:
0
,
list
:
null
,
total
:
0
,
listLoading
:
true
,
listQuery
:
{
page
:
1
,
limit
:
20
,
importance
:
undefined
,
title
:
undefined
,
type
:
undefined
,
sort
:
'
+id
'
}
,
importanceOptions
:
[
1
,
2
,
3
],
calendarTypeOptions
,
sortOptions
:
[{
label
:
'
ID Ascending
'
,
key
:
'
+id
'
}
,
{
label
:
'
ID Descending
'
,
key
:
'
-id
'
}
],
statusOptions
:
[
'
published
'
,
'
draft
'
,
'
deleted
'
],
showReviewer
:
false
,
temp
:
{
id
:
undefined
,
importance
:
1
,
remark
:
''
,
timestamp
:
new
Date
(),
title
:
''
,
type
:
''
,
status
:
'
published
'
}
,
dialogFormVisible
:
false
,
dialogStatus
:
''
,
textMap
:
{
update
:
'
Edit
'
,
create
:
'
Create
'
}
,
dialogPvVisible
:
false
,
pvData
:
[],
rules
:
{
type
:
[{
required
:
true
,
message
:
'
type is required
'
,
trigger
:
'
change
'
}
],
timestamp
:
[{
type
:
'
date
'
,
required
:
true
,
message
:
'
timestamp is required
'
,
trigger
:
'
change
'
}
],
title
:
[{
required
:
true
,
message
:
'
title is required
'
,
trigger
:
'
blur
'
}
]
}
,
downloadLoading
:
false
}
}
,
created
()
{
this
.
getList
()
}
,
methods
:
{
getList
()
{
this
.
listLoading
=
true
fetchList
(
this
.
listQuery
).
then
(
response
=>
{
this
.
list
=
response
.
data
.
items
this
.
total
=
response
.
data
.
total
// Just to simulate the time of the request
setTimeout
(()
=>
{
this
.
listLoading
=
false
}
,
1.5
*
1000
)
}
)
}
,
handleFilter
()
{
this
.
listQuery
.
page
=
1
this
.
getList
()
}
,
handleModifyStatus
(
row
,
status
)
{
this
.
$message
({
message
:
'
操作Success
'
,
type
:
'
success
'
}
)
row
.
status
=
status
}
,
sortChange
(
data
)
{
const
{
prop
,
order
}
=
data
if
(
prop
===
'
id
'
)
{
this
.
sortByID
(
order
)
}
}
,
sortByID
(
order
)
{
if
(
order
===
'
ascending
'
)
{
this
.
listQuery
.
sort
=
'
+id
'
}
else
{
this
.
listQuery
.
sort
=
'
-id
'
}
this
.
handleFilter
()
}
,
resetTemp
()
{
this
.
temp
=
{
id
:
undefined
,
importance
:
1
,
remark
:
''
,
timestamp
:
new
Date
(),
title
:
''
,
status
:
'
published
'
,
type
:
''
}
}
,
handleCreate
()
{
this
.
resetTemp
()
this
.
dialogStatus
=
'
create
'
this
.
dialogFormVisible
=
true
this
.
$nextTick
(()
=>
{
this
.
$refs
[
'
dataForm
'
].
clearValidate
()
}
)
}
,
createData
()
{
this
.
$refs
[
'
dataForm
'
].
validate
((
valid
)
=>
{
if
(
valid
)
{
this
.
temp
.
id
=
parseInt
(
Math
.
random
()
*
100
)
+
1024
// mock a id
this
.
temp
.
author
=
'
vue-element-admin
'
createArticle
(
this
.
temp
).
then
(()
=>
{
this
.
list
.
unshift
(
this
.
temp
)
this
.
dialogFormVisible
=
false
this
.
$notify
({
title
:
'
Success
'
,
message
:
'
Created Successfully
'
,
type
:
'
success
'
,
duration
:
2000
}
)
}
)
}
}
)
}
,
handleUpdate
(
row
)
{
this
.
temp
=
Object
.
assign
({
}
,
row
)
// copy obj
this
.
temp
.
timestamp
=
new
Date
(
this
.
temp
.
timestamp
)
this
.
dialogStatus
=
'
update
'
this
.
dialogFormVisible
=
true
this
.
$nextTick
(()
=>
{
this
.
$refs
[
'
dataForm
'
].
clearValidate
()
}
)
}
,
updateData
()
{
this
.
$refs
[
'
dataForm
'
].
validate
((
valid
)
=>
{
if
(
valid
)
{
const
tempData
=
Object
.
assign
({
}
,
this
.
temp
)
tempData
.
timestamp
=
+
new
Date
(
tempData
.
timestamp
)
// change Thu Nov 30 2017 16:41:05 GMT+0800 (CST) to 1512031311464
updateArticle
(
tempData
).
then
(()
=>
{
for
(
const
v
of
this
.
list
)
{
if
(
v
.
id
===
this
.
temp
.
id
)
{
const
index
=
this
.
list
.
indexOf
(
v
)
this
.
list
.
splice
(
index
,
1
,
this
.
temp
)
break
}
}
this
.
dialogFormVisible
=
false
this
.
$notify
({
title
:
'
Success
'
,
message
:
'
Update Successfully
'
,
type
:
'
success
'
,
duration
:
2000
}
)
}
)
}
}
)
}
,
handleDelete
(
row
)
{
this
.
$notify
({
title
:
'
Success
'
,
message
:
'
Delete Successfully
'
,
type
:
'
success
'
,
duration
:
2000
}
)
const
index
=
this
.
list
.
indexOf
(
row
)
this
.
list
.
splice
(
index
,
1
)
}
,
handleFetchPv
(
pv
)
{
fetchPv
(
pv
).
then
(
response
=>
{
this
.
pvData
=
response
.
data
.
pvData
this
.
dialogPvVisible
=
true
}
)
}
,
handleDownload
()
{
this
.
downloadLoading
=
true
import
(
'
@/vendor/Export2Excel
'
).
then
(
excel
=>
{
const
tHeader
=
[
'
timestamp
'
,
'
title
'
,
'
type
'
,
'
importance
'
,
'
status
'
]
const
filterVal
=
[
'
timestamp
'
,
'
title
'
,
'
type
'
,
'
importance
'
,
'
status
'
]
const
data
=
this
.
formatJson
(
filterVal
,
this
.
list
)
excel
.
export_json_to_excel
({
header
:
tHeader
,
data
,
filename
:
'
table-list
'
}
)
this
.
downloadLoading
=
false
}
)
}
,
formatJson
(
filterVal
,
jsonData
)
{
return
jsonData
.
map
(
v
=>
filterVal
.
map
(
j
=>
{
if
(
j
===
'
timestamp
'
)
{
return
parseTime
(
v
[
j
])
}
else
{
return
v
[
j
]
}
}
))
}
}
}
<
/script
>
IoTSharp/ClientApp/src/views/device/component-lib.vue
0 → 100644
浏览文件 @
be1998e5
<
template
>
<div>
<div
class=
"mixin-components-container"
>
<el-row
v-for=
"(page, index) of pages"
:key=
"index"
:gutter=
"8"
style=
"margin-top:10px;"
>
<el-col
v-for=
"(item, innerindex) of page"
:key=
"item.id"
:offset=
"innerindex > 0 ? 2 : 1"
:span=
"6"
>
<el-card
class=
"box-card"
>
<div
slot=
"header"
class=
"clearfix"
>
<span>
{{
item
.
name
}}
</span>
</div>
<div
v-if=
"item.vChartType === 've-line'"
>
<ve-line
:data=
"item.chartData"
/>
</div>
<div
v-if=
"item.vChartType === 've-gauge'"
>
<ve-gauge
:data=
"item.chartData"
:settings=
"item.settings"
/>
</div>
</el-card>
</el-col>
</el-row>
</div>
</div>
</
template
>
<
script
>
// import PanThumb from '@/components/PanThumb'
// import MdInput from '@/components/MDinput'
import
VeLine
from
'
v-charts/lib/line.common
'
import
VeGauge
from
'
v-charts/lib/gauge.common
'
import
{
deepClone
}
from
'
@/utils
'
// https://codesandbox.io/s/z69myovqzx
// https://segmentfault.com/q/1010000012529833
const
DEV_COMPONENT_STORAGE_KEY
=
'
devcomponents
'
const
cardDefaultInfo
=
{
id
:
'
123
'
,
name
:
'
Testname
'
,
title
:
'
chart
'
,
vChartType
:
'
type
'
,
chartData
:
null
,
settings
:
null
}
export
default
{
name
:
'
ComponentLib
'
,
components
:
{
VeLine
,
VeGauge
},
data
()
{
const
validate
=
(
rule
,
value
,
callback
)
=>
{
if
(
value
.
length
!==
6
)
{
callback
(
new
Error
(
'
请输入六个字符
'
))
}
else
{
callback
()
}
}
this
.
chartGaugeSettings
=
{
dimension
:
'
type
'
,
metrics
:
'
value
'
}
return
{
demo
:
{
title
:
''
},
demoRules
:
{
title
:
[{
required
:
true
,
trigger
:
'
change
'
,
validator
:
validate
}]
},
cardInfo
:
Object
.
assign
({},
cardDefaultInfo
),
allChartList
:
[],
chartLineData
:
{
columns
:
[
'
日期
'
,
'
Meter1
'
,
'
Meter2
'
,
'
Meter3
'
],
rows
:
[
{
日期
:
'
1/1
'
,
Meter1
:
1393
,
Meter2
:
1093
,
Meter3
:
0.32
},
{
日期
:
'
1/2
'
,
Meter1
:
3530
,
Meter2
:
3230
,
Meter3
:
0.26
},
{
日期
:
'
1/3
'
,
Meter1
:
2923
,
Meter2
:
2623
,
Meter3
:
0.76
},
{
日期
:
'
1/4
'
,
Meter1
:
1723
,
Meter2
:
1423
,
Meter3
:
0.49
},
{
日期
:
'
1/5
'
,
Meter1
:
3792
,
Meter2
:
3492
,
Meter3
:
0.323
},
{
日期
:
'
1/6
'
,
Meter1
:
4593
,
Meter2
:
4293
,
Meter3
:
0.78
}
]
},
chartDefaultGaugeData
:
{
columns
:
[
'
type
'
,
'
a
'
,
'
b
'
,
'
value
'
],
rows
:
[
{
type
:
'
温度
'
,
value
:
20
,
a
:
1
,
b
:
2
}
]
},
chartGaugeData
:
{
columns
:
[
'
type
'
,
'
a
'
,
'
b
'
,
'
value
'
],
rows
:
[
{
type
:
'
温度
'
,
value
:
80
,
a
:
1
,
b
:
2
}
]
}
}
},
computed
:
{
pages
()
{
const
pages
=
[]
this
.
allChartList
.
forEach
((
item
,
index
)
=>
{
const
page
=
Math
.
floor
(
index
/
4
)
// 4代表4条为一行,随意更改
if
(
!
pages
[
page
])
{
pages
[
page
]
=
[]
}
pages
[
page
].
push
(
item
)
})
return
pages
}
},
created
()
{
const
tempcardInfo
=
deepClone
(
this
.
cardInfo
)
tempcardInfo
.
chartData
=
this
.
chartLineData
tempcardInfo
.
name
=
'
threeMeterLineChart
'
tempcardInfo
.
vChartType
=
'
ve-line
'
this
.
allChartList
.
push
(
tempcardInfo
)
const
tempcardInfo2
=
deepClone
(
this
.
cardInfo
)
tempcardInfo2
.
id
=
'
456
'
tempcardInfo2
.
name
=
'
oneValueGaugeChart
'
tempcardInfo2
.
vChartType
=
'
ve-gauge
'
tempcardInfo2
.
chartData
=
this
.
chartGaugeData
tempcardInfo2
.
settings
=
this
.
chartGaugeSettings
this
.
allChartList
.
push
(
tempcardInfo2
)
window
.
localStorage
.
setItem
(
DEV_COMPONENT_STORAGE_KEY
,
JSON
.
stringify
(
this
.
allChartList
))
console
.
log
(
'
all chart list:
'
)
console
.
log
(
this
.
allChartList
)
},
methods
:
{
// 这里用于定义方法
change
()
{
console
.
log
(
'
change gauge data:
'
)
this
.
chartGaugeData
=
this
.
chartDefaultGaugeData
}
}
}
</
script
>
<
style
scoped
>
.mixin-components-container
{
background-color
:
#f0f2f5
;
padding
:
10px
;
min-height
:
calc
(
100vh
-
84px
);
}
.component-item
{
min-height
:
50px
;
}
</
style
>
IoTSharp/ClientApp/src/views/device/device-board.vue
0 → 100644
浏览文件 @
be1998e5
此差异已折叠。
点击以展开。
IoTSharp/ClientApp/src/views/device/device-visionboard.vue
0 → 100644
浏览文件 @
be1998e5
<
template
>
<div>
<div
class=
"mixin-components-container"
>
<el-row
v-for=
"(page, index) in pages"
:key=
"index"
:gutter=
"8"
style=
"margin-top:10px;"
>
<el-col
v-for=
"(item, innerindex) of page"
:key=
"item.id"
:offset=
"innerindex > 0 ? 2 : 1"
:span=
"6"
>
<el-card
class=
"box-card"
>
<div
slot=
"header"
class=
"clearfix"
>
<span>
{{
item
.
name
}}
</span>
</div>
<div
v-if=
"item.vChartType === 've-line'"
>
<ve-line
:data=
"item.chartData"
/>
</div>
<div
v-if=
"item.vChartType === 've-gauge'"
>
<ve-gauge
:data=
"item.chartData"
:settings=
"item.settings"
/>
</div>
</el-card>
</el-col>
</el-row>
</div>
</div>
</
template
>
<
script
>
// import PanThumb from '@/components/PanThumb'
// import MdInput from '@/components/MDinput'
import
VeLine
from
'
v-charts/lib/line.common
'
import
VeGauge
from
'
v-charts/lib/gauge.common
'
import
{
deepClone
}
from
'
@/utils
'
import
{
bus
}
from
'
./utils.js
'
// https://codesandbox.io/s/z69myovqzx
// https://segmentfault.com/q/1010000012529833
const
cardDefaultInfo
=
{
id
:
'
123
'
,
name
:
'
Testname
'
,
title
:
'
chart
'
,
vChartType
:
'
type
'
,
chartData
:
null
,
settings
:
null
}
/*
const devChartBindingData = {
id: '',
deviceId: '',
devName: '',
devBindedAttrId: '',
devBindedAttr: '',
devBingedChart: ''
}
*/
export
default
{
name
:
'
ComponentLib
'
,
components
:
{
VeLine
,
VeGauge
},
data
()
{
const
validate
=
(
rule
,
value
,
callback
)
=>
{
if
(
value
.
length
!==
6
)
{
callback
(
new
Error
(
'
请输入六个字符
'
))
}
else
{
callback
()
}
}
this
.
chartGaugeSettings
=
{
dimension
:
'
type
'
,
metrics
:
'
value
'
,
dataName
:
{
'
温度
'
:
'
温度
'
}
}
return
{
demo
:
{
title
:
''
},
demoRules
:
{
title
:
[{
required
:
true
,
trigger
:
'
change
'
,
validator
:
validate
}]
},
cardInfo
:
Object
.
assign
({},
cardDefaultInfo
),
allChartList
:
[],
pages
:
[],
refreshTimer
:
null
,
chartLineData
:
{
columns
:
[
'
日期
'
,
'
Meter1
'
,
'
Meter2
'
,
'
Meter3
'
],
rows
:
[
{
日期
:
'
1/1
'
,
Meter1
:
1393
,
Meter2
:
1093
,
Meter3
:
0.32
},
{
日期
:
'
1/2
'
,
Meter1
:
3530
,
Meter2
:
3230
,
Meter3
:
0.26
},
{
日期
:
'
1/3
'
,
Meter1
:
2923
,
Meter2
:
2623
,
Meter3
:
0.76
},
{
日期
:
'
1/4
'
,
Meter1
:
1723
,
Meter2
:
1423
,
Meter3
:
0.49
},
{
日期
:
'
1/5
'
,
Meter1
:
3792
,
Meter2
:
3492
,
Meter3
:
0.323
},
{
日期
:
'
1/6
'
,
Meter1
:
4593
,
Meter2
:
4293
,
Meter3
:
0.78
}
]
},
chartDefaultGaugeData
:
{
title
:
'
温度
'
,
columns
:
[
'
type
'
,
'
a
'
,
'
b
'
,
'
value
'
],
rows
:
[
{
type
:
'
温度
'
,
value
:
20
,
a
:
1
,
b
:
2
}
]
},
chartGaugeData
:
{
title
:
'
温度
'
,
columns
:
[
'
type
'
,
'
a
'
,
'
b
'
,
'
value
'
],
rows
:
[
{
type
:
'
温度
'
,
value
:
80
,
a
:
1
,
b
:
2
}
]
},
devChartBindingDataReceived
:
null
}
},
computed
()
{
// this.refreshPages()
/*
pages() {
const pages = []
this.allChartList.forEach((item, index) => {
const page = Math.floor(index / 4) // 4代表4条为一行,随意更改
if (!pages[page]) {
pages[page] = []
}
pages[page].push(item)
})
return pages
}
*/
},
created
()
{
var
chartDataInfo
=
JSON
.
parse
(
window
.
localStorage
.
getItem
(
'
datachartbinginfo
'
))
console
.
log
(
'
from local storage:
'
)
console
.
log
(
chartDataInfo
)
const
tempcardInfo
=
deepClone
(
this
.
cardInfo
)
tempcardInfo
.
vChartType
=
chartDataInfo
.
devBingedChart
tempcardInfo
.
name
=
chartDataInfo
.
devName
if
(
tempcardInfo
.
vChartType
===
'
ve-gauge
'
)
{
tempcardInfo
.
chartData
=
this
.
chartGaugeData
tempcardInfo
.
settings
=
this
.
chartGaugeSettings
}
if
(
tempcardInfo
.
vChartType
===
'
ve-line
'
)
{
tempcardInfo
.
chartData
=
this
.
chartLineData
}
this
.
allChartList
.
push
(
tempcardInfo
)
// start
this
.
refreshTimer
=
setInterval
(()
=>
{
for
(
let
i
=
0
;
i
<
this
.
allChartList
.
length
;
i
++
)
{
// todo, only show how to
if
(
this
.
allChartList
[
i
].
vChartType
===
'
ve-gauge
'
)
{
var
rdmValue
=
Math
.
floor
(
Math
.
random
()
*
10
)
+
25
this
.
allChartList
[
i
].
chartData
.
rows
=
[{
type
:
'
温度
'
,
value
:
rdmValue
,
a
:
1
,
b
:
2
}]
}
}
},
2000
)
console
.
log
(
'
created called all chart list:
'
)
console
.
log
(
this
.
allChartList
)
this
.
refreshPages
()
// this.$forceUpdate()
bus
.
$on
(
'
devbindingdata
'
,
(
data
)
=>
{
console
.
log
(
'
Received data:
'
)
// this.refreshPages()
// this.$forceUpdate()
})
},
mounted
()
{
},
beforeDestroy
()
{
clearInterval
(
this
.
refreshTimer
)
},
methods
:
{
// 这里用于定义方法
change
()
{
console
.
log
(
'
change gauge data:
'
)
this
.
chartGaugeData
=
this
.
chartDefaultGaugeData
},
refreshPages
()
{
console
.
log
(
'
calculate paegs!
'
)
this
.
allChartList
.
forEach
((
item
,
index
)
=>
{
const
page
=
Math
.
floor
(
index
/
4
)
// 4代表4条为一行,随意更改
if
(
!
this
.
pages
[
page
])
{
this
.
pages
[
page
]
=
[]
}
this
.
pages
[
page
].
push
(
item
)
})
console
.
log
(
this
.
pages
)
}
}
}
</
script
>
<
style
scoped
>
.mixin-components-container
{
background-color
:
#f0f2f5
;
padding
:
10px
;
min-height
:
calc
(
100vh
-
84px
);
}
.component-item
{
min-height
:
50px
;
}
</
style
>
IoTSharp/ClientApp/src/views/device/utils.js
0 → 100644
浏览文件 @
be1998e5
import
Vue
from
'
vue
'
export
const
bus
=
new
Vue
()
IoTSharp/ClientApp/src/views/login/index.vue
浏览文件 @
be1998e5
...
@@ -46,17 +46,18 @@
...
@@ -46,17 +46,18 @@
<div
class=
"block"
>
<div
class=
"block"
>
<el-button
:loading=
"loading"
type=
"primary"
class=
"item-btn"
size=
"medium"
style=
"width:25%"
@
click.native.prevent=
"handleLogin"
>
登录
</el-button>
<el-button
:loading=
"loading"
type=
"primary"
class=
"item-btn"
size=
"medium"
style=
"width:25%"
@
click.native.prevent=
"handleLogin"
>
登录
</el-button>
<el-button
type=
"primary"
class=
"item-btn"
size=
"medium"
@
click.native.prevent=
"gotoRegisterPage"
>
我要注册
</el-button>
<el-button
type=
"primary"
class=
"item-btn"
size=
"medium"
@
click.native.prevent=
"gotoRegisterPage"
>
我要注册
</el-button>
</div>
</div>
</div>
</div>
<div
style=
"position:relative;margin-top:30px"
>
<div
style=
"position:relative;margin-top:30px"
>
<div
class=
"tips"
>
<div
class=
"tips"
>
<span
>
Please register the user first.t
he username must be email.
</span>
<span
style=
"color:gray"
>
Please register first.T
he username must be email.
</span>
</div>
</div>
<div
class=
"tips"
>
<div
class=
"tips"
>
<span
style=
"margin-right:18px;"
>
The password must contain upper and lower case letters, numbers, and symbols.
</span>
<span
style=
"margin-right:18px;color:gray"
>
The password must contain upper and lower case letters, numbers, and symbols.
</span>
</div>
<div
style=
"position:relative"
align=
"right"
>
<el-button
class=
"item-btn"
type=
"primary"
@
click=
"showDialog=true"
>
Getting a tenant?
</el-button>
</div>
</div>
<el-button
class=
"thirdparty-button"
type=
"primary"
@
click=
"showDialog=true"
>
Getting a tenant?
</el-button>
</div>
</div>
</el-form>
</el-form>
...
@@ -74,11 +75,11 @@
...
@@ -74,11 +75,11 @@
<
script
>
<
script
>
import
{
validEmail
}
from
'
@/utils/validate
'
import
{
validEmail
}
from
'
@/utils/validate
'
import
SocialSign
from
'
./components/SocialSignin
'
//
import SocialSign from './components/SocialSignin'
export
default
{
export
default
{
name
:
'
Login
'
,
name
:
'
Login
'
,
components
:
{
SocialSign
},
//
components: { SocialSign },
data
()
{
data
()
{
const
validateUsername
=
(
rule
,
value
,
callback
)
=>
{
const
validateUsername
=
(
rule
,
value
,
callback
)
=>
{
if
(
!
validEmail
(
value
))
{
if
(
!
validEmail
(
value
))
{
...
...
IoTSharp/ClientApp/src/views/login/index.vue.bak
已删除
100755 → 0
浏览文件 @
839f477c
<template>
<div class="login-container">
<el-form ref="loginForm" :model="loginForm" :rules="loginRules" class="login-form" auto-complete="on" label-position="left">
<div class="title-container">
<h3 class="title">IoTSharp登录入口</h3>
</div>
<el-form-item prop="username">
<span class="svg-container">
<svg-icon icon-class="user" />
</span>
<el-input
ref="username"
v-model="loginForm.username"
placeholder="Username"
name="username"
type="text"
tabindex="1"
auto-complete="on"
/>
</el-form-item>
<el-tooltip v-model="capsTooltip" content="Caps lock is On" placement="right" manual>
<el-form-item prop="password">
<span class="svg-container">
<svg-icon icon-class="password" />
</span>
<el-input
:key="passwordType"
ref="password"
v-model="loginForm.password"
:type="passwordType"
placeholder="Password"
name="password"
tabindex="2"
auto-complete="on"
@keyup.native="checkCapslock"
@blur="capsTooltip = false"
@keyup.enter.native="handleLogin"
/>
<span class="show-pwd" @click="showPwd">
<svg-icon :icon-class="passwordType === 'password' ? 'eye' : 'eye-open'" />
</span>
</el-form-item>
</el-tooltip>
<div style="position:relative" align="right">
<div class="block">
<el-button :loading="loading" type="primary" class="item-btn" size="medium" style="width:25%" @click.native.prevent="handleLogin">登陆</el-button>
<el-button type="primary" class="item-btn" size="medium" @click.native.prevent="handleRegister">我要注册</el-button>
</div>
</div>
<div style="position:relative;margin-top:30px">
<div class="tips">
<span>Username : admin</span>
<span>Password : any</span>
</div>
<div class="tips">
<span style="margin-right:18px;">Username : editor</span>
<span>Password : any</span>
</div>
<el-button class="thirdparty-button" type="primary" @click="showDialog=true">
Or connect with
</el-button>
</div>
</el-form>
<el-dialog title="Or connect with" :visible.sync="showDialog">
Can not be simulated on local, so please combine you own business simulation! ! !
<br>
<br>
<br>
<social-sign />
</el-dialog>
</div>
</template>
<script>
import { validUsername } from '@/utils/validate'
import SocialSign from './components/SocialSignin'
export default {
name: 'Login',
components: { SocialSign },
data() {
const validateUsername = (rule, value, callback) => {
if (!validUsername(value)) {
callback(new Error('Please enter the correct user name'))
} else {
callback()
}
}
const validatePassword = (rule, value, callback) => {
if (value.length < 6) {
callback(new Error('The password can not be less than 6 digits'))
} else {
callback()
}
}
return {
loginForm: {
username: 'iotmaster@iotsharp.net',
password: 'Admin_123'
},
loginRules: {
username: [{ required: true, trigger: 'blur', validator: validateUsername }],
password: [{ required: true, trigger: 'blur', validator: validatePassword }]
},
passwordType: 'password',
capsTooltip: false,
loading: false,
showDialog: false,
redirect: undefined,
otherQuery: {}
}
},
watch: {
$route: {
handler: function(route) {
const query = route.query
if (query) {
this.redirect = query.redirect
this.otherQuery = this.getOtherQuery(query)
}
},
immediate: true
}
},
created() {
// window.addEventListener('storage', this.afterQRScan)
},
mounted() {
if (this.loginForm.username === '') {
this.$refs.username.focus()
} else if (this.loginForm.password === '') {
this.$refs.password.focus()
}
},
destroyed() {
// window.removeEventListener('storage', this.afterQRScan)
},
methods: {
checkCapslock({ shiftKey, key } = {}) {
if (key && key.length === 1) {
if (shiftKey && (key >= 'a' && key <= 'z') || !shiftKey && (key >= 'A' && key <= 'Z')) {
this.capsTooltip = true
} else {
this.capsTooltip = false
}
}
if (key === 'CapsLock' && this.capsTooltip === true) {
this.capsTooltip = false
}
},
showPwd() {
if (this.passwordType === 'password') {
this.passwordType = ''
} else {
this.passwordType = 'password'
}
this.$nextTick(() => {
this.$refs.password.focus()
})
},
handleLogin() {
this.$refs.loginForm.validate(valid => {
if (valid) {
this.loading = true
console.log('value = ' + valid)
this.$store.dispatch('user/login', this.loginForm)
.then(() => {
console.log('push to home')
this.$router.push({ path: this.redirect || '/', query: this.otherQuery })
this.loading = false
})
.catch(() => {
this.loading = false
})
} else {
console.log('error submit!!')
return false
}
})
},
handleRegister() {
this.$router.push({ path: this.redirect || '/login/register', query: this.otherQuery })
},
getOtherQuery(query) {
return Object.keys(query).reduce((acc, cur) => {
if (cur !== 'redirect') {
acc[cur] = query[cur]
}
return acc
}, {})
}
// afterQRScan() {
// if (e.key === 'x-admin-oauth-code') {
// const code = getQueryObject(e.newValue)
// const codeMap = {
// wechat: 'code',
// tencent: 'code'
// }
// const type = codeMap[this.auth_type]
// const codeName = code[type]
// if (codeName) {
// this.$store.dispatch('LoginByThirdparty', codeName).then(() => {
// this.$router.push({ path: this.redirect || '/' })
// })
// } else {
// alert('第三方登录失败')
// }
// }
// }
}
}
</script>
<style lang="scss">
/* 修复input 背景不协调 和光标变色 */
/* Detail see https://github.com/PanJiaChen/vue-element-admin/pull/927 */
$bg:#283443;
$light_gray:#fff;
$cursor: #fff;
@supports (-webkit-mask: none) and (not (cater-color: $cursor)) {
.login-container .el-input input {
color: $cursor;
}
}
/* reset element-ui css */
.login-container {
.el-input {
display: inline-block;
height: 47px;
width: 85%;
input {
background: transparent;
border: 0px;
-webkit-appearance: none;
border-radius: 0px;
padding: 12px 5px 12px 15px;
color: $light_gray;
height: 47px;
caret-color: $cursor;
&:-webkit-autofill {
box-shadow: 0 0 0px 1000px $bg inset !important;
-webkit-text-fill-color: $cursor !important;
}
}
}
.el-form-item {
border: 1px solid rgba(255, 255, 255, 0.1);
background: rgba(0, 0, 0, 0.1);
border-radius: 5px;
color: #454545;
}
}
</style>
<style lang="scss" scoped>
$bg:#2d3a4b;
$dark_gray:#889aa4;
$light_gray:#eee;
.login-container {
min-height: 100%;
width: 100%;
background-color: $bg;
overflow: hidden;
.login-form {
position: relative;
width: 520px;
max-width: 100%;
padding: 160px 35px 0;
margin: 0 auto;
overflow: hidden;
}
.tips {
font-size: 14px;
color: #fff;
margin-bottom: 10px;
span {
&:first-of-type {
margin-right: 16px;
}
}
}
.svg-container {
padding: 6px 5px 6px 15px;
color: $dark_gray;
vertical-align: middle;
width: 30px;
display: inline-block;
}
.title-container {
position: relative;
.title {
font-size: 26px;
color: $light_gray;
margin: 0px auto 40px auto;
text-align: center;
font-weight: bold;
}
}
.show-pwd {
position: absolute;
right: 10px;
top: 7px;
font-size: 16px;
color: $dark_gray;
cursor: pointer;
user-select: none;
}
.thirdparty-button {
position: absolute;
right: 0;
bottom: 6px;
}
@media only screen and (max-width: 470px) {
.thirdparty-button {
display: none;
}
}
}
</style>
IoTSharp/ClientApp/src/views/login/register.vue
浏览文件 @
be1998e5
...
@@ -70,9 +70,10 @@
...
@@ -70,9 +70,10 @@
</span>
</span>
</el-form-item>
</el-form-item>
</el-tooltip>
</el-tooltip>
<div
style=
"position:relative"
align=
"
center
"
>
<div
style=
"position:relative"
align=
"
right
"
>
<div
class=
"block"
>
<div
class=
"block"
>
<el-button
:loading=
"loading"
type=
"primary"
class=
"item-btn"
size=
"medium"
@
click.native.prevent=
"handleRegister"
>
Register
</el-button>
<el-button
:loading=
"loading"
type=
"primary"
class=
"item-btn"
size=
"medium"
@
click.native.prevent=
"handleRegister"
>
Register
</el-button>
<el-button
class=
"item-btn"
type=
"primary"
@
click=
"showDialog=true"
>
Getting a tenant?
</el-button>
</div>
</div>
<div
class=
"block"
>
<div
class=
"block"
>
<el-button
class=
"thirdparty-button"
type=
"primary"
@
click=
"showDialog=true"
>
Getting a tenant?
</el-button>
<el-button
class=
"thirdparty-button"
type=
"primary"
@
click=
"showDialog=true"
>
Getting a tenant?
</el-button>
...
@@ -99,11 +100,9 @@
...
@@ -99,11 +100,9 @@
<
script
>
<
script
>
// import { validUsername } from '@/utils/validate'
// import { validUsername } from '@/utils/validate'
// import SocialSign from './components/SocialSignin'
import
customerId
from
'
@/utils/test-customer-id
'
import
customerId
from
'
@/utils/test-customer-id
'
export
default
{
export
default
{
name
:
'
Register
'
,
name
:
'
Register
'
,
// components: { SocialSign },
data
()
{
data
()
{
const
validatePassword
=
(
rule
,
value
,
callback
)
=>
{
const
validatePassword
=
(
rule
,
value
,
callback
)
=>
{
if
(
value
==
null
||
value
.
length
<
6
||
value
.
trim
().
length
===
''
)
{
if
(
value
==
null
||
value
.
length
<
6
||
value
.
trim
().
length
===
''
)
{
...
...
IoTSharp/ClientApp/src/views/login/register.vue.bak
已删除
100755 → 0
浏览文件 @
839f477c
<template>
<div class="login-container">
<el-form ref="loginForm" :model="loginForm" :rules="loginRules" class="login-form" auto-complete="on" label-position="left">
<div class="title-container">
<h3 class="title">IoTSharp注册</h3>
</div>
<el-form-item prop="username">
<span class="svg-container">
<svg-icon icon-class="message" />
</span>
<el-input
ref="username"
v-model="loginForm.username"
placeholder="Username"
name="username"
type="text"
tabindex="1"
auto-complete="on"
/>
</el-form-item>
<el-form-item prop="username">
<span class="svg-container">
<svg-icon icon-class="phone" />
</span>
<el-input
ref="username"
v-model="loginForm.username"
placeholder="Username"
name="username"
type="text"
tabindex="1"
auto-complete="on"
/>
</el-form-item>
<el-form-item prop="username">
<span class="svg-container">
<svg-icon icon-class="user" />
</span>
<el-input
ref="username"
v-model="loginForm.username"
placeholder="Username"
name="username"
type="text"
tabindex="1"
auto-complete="on"
/>
</el-form-item>
<el-tooltip v-model="capsTooltip" content="Caps lock is On" placement="right" manual>
<el-form-item prop="password">
<span class="svg-container">
<svg-icon icon-class="password" />
</span>
<el-input
:key="passwordType"
ref="password"
v-model="loginForm.password"
:type="passwordType"
placeholder="Password"
name="password"
tabindex="2"
auto-complete="on"
@keyup.native="checkCapslock"
@blur="capsTooltip = false"
@keyup.enter.native="handleLogin"
/>
<span class="show-pwd" @click="showPwd">
<svg-icon :icon-class="passwordType === 'password' ? 'eye' : 'eye-open'" />
</span>
</el-form-item>
</el-tooltip>
<div style="position:relative" align="center">
<div class="block">
<el-button type="primary" class="item-btn" size="medium" @click.native.prevent="handleLogin">注册</el-button>
</div>
</div>
<div style="position:relative;margin-top:30px">
<div class="tips">
<span>Username : admin</span>
<span>Password : any</span>
</div>
<div class="tips">
<span style="margin-right:18px;">Username : editor</span>
<span>Password : any</span>
</div>
<el-button class="thirdparty-button" type="primary" @click="showDialog=true">
Or connect with
</el-button>
</div>
</el-form>
<el-dialog title="Or connect with" :visible.sync="showDialog">
Can not be simulated on local, so please combine you own business simulation! ! !
<br>
<br>
<br>
<social-sign />
</el-dialog>
</div>
</template>
<script>
import { validUsername } from '@/utils/validate'
import SocialSign from './components/SocialSignin'
export default {
name: 'Register',
components: { SocialSign },
data() {
const validateUsername = (rule, value, callback) => {
if (!validUsername(value)) {
callback(new Error('Please enter the correct user name'))
} else {
callback()
}
}
const validatePassword = (rule, value, callback) => {
if (value.length < 6) {
callback(new Error('The password can not be less than 6 digits'))
} else {
callback()
}
}
return {
loginForm: {
username: 'iotmaster@iotsharp.net',
password: 'Admin_123'
},
loginRules: {
username: [{ required: true, trigger: 'blur', validator: validateUsername }],
password: [{ required: true, trigger: 'blur', validator: validatePassword }]
},
passwordType: 'password',
capsTooltip: false,
loading: false,
showDialog: false,
redirect: undefined,
otherQuery: {}
}
},
watch: {
$route: {
handler: function(route) {
const query = route.query
if (query) {
this.redirect = query.redirect
this.otherQuery = this.getOtherQuery(query)
}
},
immediate: true
}
},
created() {
// window.addEventListener('storage', this.afterQRScan)
},
mounted() {
if (this.loginForm.username === '') {
this.$refs.username.focus()
} else if (this.loginForm.password === '') {
this.$refs.password.focus()
}
},
destroyed() {
// window.removeEventListener('storage', this.afterQRScan)
},
methods: {
checkCapslock({ shiftKey, key } = {}) {
if (key && key.length === 1) {
if (shiftKey && (key >= 'a' && key <= 'z') || !shiftKey && (key >= 'A' && key <= 'Z')) {
this.capsTooltip = true
} else {
this.capsTooltip = false
}
}
if (key === 'CapsLock' && this.capsTooltip === true) {
this.capsTooltip = false
}
},
showPwd() {
if (this.passwordType === 'password') {
this.passwordType = ''
} else {
this.passwordType = 'password'
}
this.$nextTick(() => {
this.$refs.password.focus()
})
},
handleLogin() {
this.$refs.loginForm.validate(valid => {
if (valid) {
this.loading = true
console.log('value = ' + valid)
this.$store.dispatch('user/login', this.loginForm)
.then(() => {
console.log('push to home')
this.$router.push({ path: this.redirect || '/', query: this.otherQuery })
this.loading = false
})
.catch(() => {
this.loading = false
})
} else {
console.log('error submit!!')
return false
}
})
},
getOtherQuery(query) {
return Object.keys(query).reduce((acc, cur) => {
if (cur !== 'redirect') {
acc[cur] = query[cur]
}
return acc
}, {})
}
// afterQRScan() {
// if (e.key === 'x-admin-oauth-code') {
// const code = getQueryObject(e.newValue)
// const codeMap = {
// wechat: 'code',
// tencent: 'code'
// }
// const type = codeMap[this.auth_type]
// const codeName = code[type]
// if (codeName) {
// this.$store.dispatch('LoginByThirdparty', codeName).then(() => {
// this.$router.push({ path: this.redirect || '/' })
// })
// } else {
// alert('第三方登录失败')
// }
// }
// }
}
}
</script>
<style lang="scss">
/* 修复input 背景不协调 和光标变色 */
/* Detail see https://github.com/PanJiaChen/vue-element-admin/pull/927 */
$bg:#283443;
$light_gray:#fff;
$cursor: #fff;
@supports (-webkit-mask: none) and (not (cater-color: $cursor)) {
.login-container .el-input input {
color: $cursor;
}
}
/* reset element-ui css */
.login-container {
.el-input {
display: inline-block;
height: 47px;
width: 85%;
input {
background: transparent;
border: 0px;
-webkit-appearance: none;
border-radius: 0px;
padding: 12px 5px 12px 15px;
color: $light_gray;
height: 47px;
caret-color: $cursor;
&:-webkit-autofill {
box-shadow: 0 0 0px 1000px $bg inset !important;
-webkit-text-fill-color: $cursor !important;
}
}
}
.el-form-item {
border: 1px solid rgba(255, 255, 255, 0.1);
background: rgba(0, 0, 0, 0.1);
border-radius: 5px;
color: #454545;
}
}
</style>
<style lang="scss" scoped>
$bg:#2d3a4b;
$dark_gray:#889aa4;
$light_gray:#eee;
.login-container {
min-height: 100%;
width: 100%;
background-color: $bg;
overflow: hidden;
.login-form {
position: relative;
width: 520px;
max-width: 100%;
padding: 160px 35px 0;
margin: 0 auto;
overflow: hidden;
}
.tips {
font-size: 14px;
color: #fff;
margin-bottom: 10px;
span {
&:first-of-type {
margin-right: 16px;
}
}
}
.svg-container {
padding: 6px 5px 6px 15px;
color: $dark_gray;
vertical-align: middle;
width: 30px;
display: inline-block;
}
.title-container {
position: relative;
.title {
font-size: 26px;
color: $light_gray;
margin: 0px auto 40px auto;
text-align: center;
font-weight: bold;
}
}
.show-pwd {
position: absolute;
right: 10px;
top: 7px;
font-size: 16px;
color: $dark_gray;
cursor: pointer;
user-select: none;
}
.thirdparty-button {
position: absolute;
right: 0;
bottom: 6px;
}
@media only screen and (max-width: 470px) {
.thirdparty-button {
display: none;
}
}
}
</style>
IoTSharp/ClientApp/src/views/permission/role.vue
浏览文件 @
be1998e5
...
@@ -205,6 +205,7 @@ export default {
...
@@ -205,6 +205,7 @@ export default {
const
isEdit
=
this
.
dialogType
===
'
edit
'
const
isEdit
=
this
.
dialogType
===
'
edit
'
const
checkedKeys
=
this
.
$refs
.
tree
.
getCheckedKeys
()
const
checkedKeys
=
this
.
$refs
.
tree
.
getCheckedKeys
()
const
checkednodes
=
this
.
$refs
.
tree
.
getCheckedNodes
()
this
.
role
.
routes
=
this
.
generateTree
(
deepClone
(
this
.
serviceRoutes
),
'
/
'
,
checkedKeys
)
this
.
role
.
routes
=
this
.
generateTree
(
deepClone
(
this
.
serviceRoutes
),
'
/
'
,
checkedKeys
)
if
(
isEdit
)
{
if
(
isEdit
)
{
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录