Commit 2d99e938 by hank

设备组页面

parent 79192f5e
...@@ -224,12 +224,55 @@ class UsersApi extends ApiClient { ...@@ -224,12 +224,55 @@ class UsersApi extends ApiClient {
url: `/calendar/get/info/${id}` url: `/calendar/get/info/${id}`
}) })
} }
/** 更新日程 */
deleteSchedule(id) { deleteSchedule(id) {
return this.request({ return this.request({
method: 'post', method: 'post',
url: `/calendar/del/info/${id}` url: `/calendar/del/info/${id}`
}) })
} }
/** 添加设备组 */
getGroupList(page: number = 1, limit: number = 1000000) {
return this.request({
method: 'post',
url: `/calendar/get/list?p=${page}&c=${limit}`,
data: {}
})
}
/** 添加设备组 */
addGroup(id) {
return this.request({
method: 'post',
url: `/calendar/del/info/${id}`
})
}
/** 编辑设备组 */
getGroupDevice(id) {
return this.request({
method: 'post',
url: `/calendar/del/info/${id}`
})
}
editGroup(id) {
return this.request({
method: 'post',
url: `/calendar/del/info/${id}`
})
}
/** 删除设备组 */
deleteGroup(id) {
return this.request({
method: 'post',
url: `/calendar/del/info/${id}`
})
}
/** 删除设备组,摸个设备 */
deleteGroupDevice(id) {
return this.request({
method: 'post',
url: `/calendar/del/info/${id}`
})
}
} }
export default new UsersApi() export default new UsersApi()
...@@ -48,6 +48,8 @@ class App extends Component { ...@@ -48,6 +48,8 @@ class App extends Component {
'pages/home/device/my_device/index', 'pages/home/device/my_device/index',
'pages/home/device/add/index', 'pages/home/device/add/index',
'pages/home/device/my_film/index', 'pages/home/device/my_film/index',
'pages/home/device/group_detail/index',
'pages/home/device/group_device_bind/index',
'pages/home/tempaltes/film_detail', 'pages/home/tempaltes/film_detail',
'pages/home/tempaltes/film_page', 'pages/home/tempaltes/film_page',
'pages/home/tempaltes/film_preview', 'pages/home/tempaltes/film_preview',
......
@import '@styles/var.scss';
.device-list {
width: 100%;
height: 100%;
position: relative;
&-add-btn {
right: 30px;
bottom: 200px;
width: 108px;
height: 108px;
display: flex;
color: white;
font-size: 50px;
position: absolute;
border-radius: 60px;
align-items: center;
justify-content: center;
background-color: $bgColor;
background-image: linear-gradient(176deg, #ffab20 0%, #ff720e 97%);
}
.group-item {
position: relative;
padding: 24px 24px;
-webkit-box-sizing: border-box;
box-sizing: border-box;
color: #333;
font-size: 32px;
line-height: 1.5;
&::after {
content: '';
position: absolute;
-webkit-transform-origin: center;
-ms-transform-origin: center;
transform-origin: center;
-webkit-box-sizing: border-box;
box-sizing: border-box;
pointer-events: none;
top: auto;
left: 24px;
right: 0;
bottom: 0;
-webkit-transform: scaleY(0.5);
-ms-transform: scaleY(0.5);
transform: scaleY(0.5);
border-bottom: 1px solid #d6e4ef;
}
}
&-select {
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
position: absolute;
align-items: center;
flex-direction: column;
justify-content: center;
background-color: rgba($color: #000, $alpha: 0.7);
z-index: 2;
&-modal {
width: 400px;
padding: 0 20px;
border-radius: 6px;
background-color: white;
&-item {
padding: 20px 0;
}
}
}
}
import api from '@/api/index'
import { ComponentClass } from 'react'
import { AtSwipeAction } from 'taro-ui'
import { connect } from '@tarojs/redux'
import ListView from '@/conpoments/list_view'
import Taro, { Component, Config } from '@tarojs/taro'
import { View, Text } from '@tarojs/components'
import DeviceItem from '@/conpoments/device_item'
import { getFilmList } from '@/actions/asyncCounter'
import { showMyToast } from '@/common/utils'
import './index.scss'
export interface IDeviceItem {
filmId: any
filmName: any
mqttTopic: string
equipmentType: any
equipmentId: string
equipmentUrl: string
equipmentName: string
equipmentState: string
calendarId?: string
}
type PageStateProps = {
list: any[]
count: number
}
type PageDispatchProps = {
getFilmListData: (page: number) => void
}
type PageOwnProps = {
height: number
}
type PageState = {
deviceCode: string
showModal: boolean
deviceList: IDeviceItem[]
groupId: string | ''
}
type IProps = PageStateProps & PageDispatchProps & PageOwnProps
interface DeviceGroup {
props: IProps
state: PageState
}
@connect(
({ counter }) => {
const { list, count } = counter.filmData
return { list, count }
},
dispacth => ({
getFilmListData(page: number) {
dispacth(getFilmList(page))
}
})
)
class DeviceGroup extends Component {
config: Config = {
navigationBarTitleText: '组详情'
}
protected page = 1
constructor(props: any) {
super(props)
const { id } = this.$router.params
this.state = {
deviceCode: '',
deviceList: [],
showModal: false,
groupId: id
}
this.selectAddDevice = this.selectAddDevice.bind(this)
Taro.setNavigationBarTitle({
title: '组详情'
})
}
async componentWillMount() {
this.getDate()
}
componentDidShow() {
this.page = 1
this.getDate()
}
async getDate() {
this.props.getFilmListData(this.page)
}
selectAddDevice() {
const groupId = this.$router.params.id
Taro.navigateTo({ url: `/pages/home/device/group_device_bind/index?id=${groupId}` })
}
async handleItem(item: IDeviceItem, info) {
const { text } = info
const { equipmentId } = item
if (text === '删除') {
Taro.showModal({ content: '确定要删除?' }).then(async ({ confirm }) => {
if (confirm) {
try {
await api.common.deleteGroupDevice(equipmentId)
this.getDate()
showMyToast({ title: '删除成功~' })
} catch (error) {
console.error(error)
showMyToast({ result: error, title: '失败成功~' })
}
}
})
}
}
async pullingUp(done: any) {
this.page++
await this.getDate()
done()
}
async pullingDown(done: any) {
this.page = 1
await this.getDate()
setTimeout(() => {
done()
}, 500)
}
goDetail(equipmentId) {
Taro.navigateTo({ url: `/pages/home/device/device_detail/index?equipmentId=${equipmentId}` })
}
render() {
const { list, count, height } = this.props
return (
<View className="device-list">
<ListView
count={count}
height={height}
dataListLength={list.length}
pullingUp={done => this.pullingUp(done)}
pullingDown={done => this.pullingDown(done)}
>
{list.map(item => (
<AtSwipeAction
autoClose
key={item.equipmentId}
onClick={info => this.handleItem(item, info)}
options={[
{
text: '删除',
style: {
backgroundColor: '#FF4949'
}
}
]}
>
<View className="group-item" onClick={() => this.goDetail(item.equipmentId)}>
<DeviceItem {...item} />
</View>
</AtSwipeAction>
))}
</ListView>
<View className="device-list-add-btn" onClick={this.selectAddDevice}>
<Text className="icon">+</Text>
</View>
</View>
)
}
}
export default DeviceGroup as ComponentClass<PageOwnProps, PageState>
@import '@styles/var.scss';
.device-bind {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
&-scroll {
flex: 1;
&-view {
height: 100%;
}
}
&-item {
display: flex;
align-items: center;
flex-direction: row;
justify-content: center;
&-checkbox {
margin-left: 30px;
}
&-info {
flex: 1;
}
}
&-bottom-bar {
.all {
// width: 200px;
display: inline-block;
flex: 1;
}
.enter {
display: inline-block;
width: 150px;
}
padding: 0 20px;
display: flex;
align-items: center;
// flex-direction: row;
justify-content: space-between;
}
}
import api from '@/api/index'
import { ComponentClass } from 'react'
import { connect } from '@tarojs/redux'
import { showMyToast } from '@/common/utils'
import DeviceItem from '@/conpoments/device_item'
import { getFilmList } from '@/actions/asyncCounter'
import Taro, { Component, Config } from '@tarojs/taro'
import { View, Text, ScrollView, Button, Checkbox, Label } from '@tarojs/components'
import './index.scss'
type PageStateProps = {
list: any[]
count: number
}
type PageDispatchProps = {
getFilmListData: (page: number) => void
}
type PageOwnProps = {}
type PageState = {
page: number
filmId: string
checked: Set<string>
}
type IProps = PageStateProps & PageDispatchProps & PageOwnProps
interface DeviceSelect {
props: IProps
state: PageState
}
@connect(
({ counter }) => {
const { list, count } = counter.filmData
return { list, count }
},
dispatch => ({
getFilmListData(page: number) {
dispatch(getFilmList(page))
}
})
)
class DeviceSelect extends Component {
config: Config = {
navigationBarTitleText: '设备管理'
}
constructor(props) {
super(props)
const { filmId } = this.$router.params || ''
this.state = {
filmId,
page: 1,
checked: new Set()
}
this.updateBind = this.updateBind.bind(this)
this.changeAllCheck = this.changeAllCheck.bind(this)
}
componentWillMount() {
this.getData()
}
getData() {
const { page } = this.state
this.props.getFilmListData(page)
}
changeItem({ equipmentId }) {
if (this.state.checked.has(equipmentId)) {
this.state.checked.delete(equipmentId)
const newSet = this.state.checked
this.setState({
checked: new Set([...newSet])
})
} else {
this.setState({
checked: new Set([...this.state.checked, equipmentId])
})
}
// console.log({ item })
}
async updateBind() {
const { checked, filmId } = this.state
if (!filmId) return
try {
await api.common.updateEquipmentBinding([...checked], filmId)
showMyToast({ title: '修改成功~' })
Taro.navigateBack()
} catch (error) {
console.error(error)
showMyToast({ title: '修改失败~' })
}
}
changeAllCheck() {
const { list } = this.props
const { checked } = this.state
if (list.length === 0) return
if (checked.size !== list.length) {
// 没全选
const checkedId = list.reduce((previous, { equipmentId }) => {
previous.push(equipmentId)
return previous
}, [])
this.setState({
checked: new Set([...checkedId])
})
} else {
// 已全选
this.setState({
checked: new Set()
})
}
}
shouldComponentUpdate(nextProps: IProps, nextState: PageState) {
const { checked } = this.state
const { checked: _checked } = nextState
const { list } = this.props
const { list: _list } = nextProps
return checked !== _checked || list !== _list
}
render() {
const { list } = this.props
const { checked } = this.state
const { size } = checked
return (
<View className="device-bind">
<View className="device-bind-scroll">
<ScrollView className="device-bind-scroll-view">
{list.map(item => (
<View key={item.equipmentId}>
<Label className="device-bind-item" onClick={() => this.changeItem(item)}>
<Checkbox
value=""
className="device-bind-item-checkbox"
checked={checked.has(item.equipmentId)}
/>
<View className="device-bind-item-info">
<DeviceItem {...item} />
</View>
</Label>
</View>
))}
</ScrollView>
</View>
<View className="device-bind-bottom-bar">
<Text className="all" onClick={this.changeAllCheck}>
全选,共选择{size}
</Text>
<Button className="enter" onClick={this.updateBind}>
确定
</Button>
</View>
</View>
)
}
}
export default DeviceSelect as ComponentClass<PageOwnProps, PageState>
@import '@styles/var.scss';
.device-list {
width: 100%;
height: 100%;
position: relative;
&-add-btn {
right: 30px;
bottom: 200px;
width: 108px;
height: 108px;
display: flex;
color: white;
font-size: 50px;
position: absolute;
border-radius: 60px;
align-items: center;
justify-content: center;
background-color: $bgColor;
background-image: linear-gradient(176deg, #ffab20 0%, #ff720e 97%);
}
.group-item {
position: relative;
padding: 24px 24px;
-webkit-box-sizing: border-box;
box-sizing: border-box;
color: #333;
font-size: 32px;
line-height: 1.5;
&::after {
content: '';
position: absolute;
-webkit-transform-origin: center;
-ms-transform-origin: center;
transform-origin: center;
-webkit-box-sizing: border-box;
box-sizing: border-box;
pointer-events: none;
top: auto;
left: 24px;
right: 0;
bottom: 0;
-webkit-transform: scaleY(0.5);
-ms-transform: scaleY(0.5);
transform: scaleY(0.5);
border-bottom: 1px solid #d6e4ef;
}
}
&-select {
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
position: absolute;
align-items: center;
flex-direction: column;
justify-content: center;
background-color: rgba($color: #000, $alpha: 0.7);
z-index: 2;
&-modal {
width: 400px;
padding: 0 20px;
border-radius: 6px;
background-color: white;
&-item {
padding: 20px 0;
}
}
}
}
.film-modal {
padding: 20px 50px;
&-text {
font-size: 28px;
}
&-input {
padding: 10px;
font-size: 28px;
border-radius: 6px;
margin: 15px 0 20px;
color: $input-color;
border: 1px solid $border-color;
}
}
import api from '@/api/index'
import { ComponentClass } from 'react'
import { AtSwipeAction } from 'taro-ui'
import { connect } from '@tarojs/redux'
import ListView from '@/conpoments/list_view'
import Taro, { Component } from '@tarojs/taro'
import { View, Text, Input } from '@tarojs/components'
import Modal from '@/conpoments/modal'
import { getFilmList } from '@/actions/asyncCounter'
import { showMyToast } from '@/common/utils'
import Ble from '@/common/bluetooth'
import './index.scss'
import template from '@/api/template'
export interface IDeviceItem {
filmId: any
filmName: any
mqttTopic: string
equipmentType: any
equipmentId: string
equipmentUrl: string
equipmentName: string
equipmentState: string
calendarId?: string
}
type PageStateProps = {
list: any[]
count: number
}
type PageDispatchProps = {
getFilmListData: (page: number) => void
}
type PageOwnProps = {
height: number
}
type PageState = {
deviceCode: string
showModal: boolean
temp: any
deviceList: IDeviceItem[]
}
type IProps = PageStateProps & PageDispatchProps & PageOwnProps
interface DeviceGroup {
props: IProps
state: PageState
}
@connect(
({ counter }) => {
const { list, count } = counter.filmData
return { list, count }
},
dispacth => ({
getFilmListData(page: number) {
dispacth(getFilmList(page))
}
})
)
class DeviceGroup extends Component {
protected page = 1
constructor(props: any) {
super(props)
this.state = {
deviceCode: '',
deviceList: [],
showModal: false,
temp: {
name: ''
}
}
this.cancelModal = this.cancelModal.bind(this)
this.AddGroup = this.AddGroup.bind(this)
this.inputConfirm = this.inputConfirm.bind(this)
}
async componentWillMount() {
this.getDate()
}
componentDidShow() {
this.page = 1
this.getDate()
}
async getDate() {
this.cancelModal()
this.props.getFilmListData(this.page)
}
AddGroup() {
this.setState({
showModal: !this.state.showModal,
temp: {
name: ''
}
})
}
cancelModal() {
this.setState({ showModal: false })
}
selectItem(url: string) {
this.cancelModal()
Taro.navigateTo({ url })
}
async handleItem(item, info) {
const { text } = info
const { equipmentId } = item
if (text === '编辑') {
// console.log('')
this.setState({
showModal: true,
temp: Object.assign({ name: '测试组名' }, item)
})
} else if (text === '删除') {
Taro.showModal({ content: '确定要删除?' }).then(async ({ confirm }) => {
if (confirm) {
try {
await api.common.deleteGroup(equipmentId)
this.getDate()
showMyToast({ title: '删除成功~' })
} catch (error) {
console.error(error)
showMyToast({ result: error, title: '失败成功~' })
}
}
})
}
}
async pullingUp(done: any) {
this.page++
await this.getDate()
done()
}
async pullingDown(done: any) {
this.page = 1
await this.getDate()
setTimeout(() => {
done()
}, 500)
}
goDetail(id) {
Taro.navigateTo({ url: `/pages/home/device/group_detail/index?id=${id}` })
}
inputConfirm() {
console.log()
const { temp } = this.state
if (!temp.name) {
showMyToast({ title: '请输入设备组名称' })
return
}
if (temp.equipmentId) {
console.log('更新')
api.common
.editGroup(temp.name)
.then(() => {
showMyToast({ title: '更新成功' })
})
.catch(() => {
showMyToast({ title: '更新失败' })
})
} else {
console.log('创建')
api.common
.addGroup(temp.name)
.then(() => {
showMyToast({ title: '创建成功' })
})
.catch(() => {
showMyToast({ title: '创建失败' })
})
}
}
changeName({ target }) {
let value = target.value
this.setState({
temp: Object.assign(this.state.temp, {
name: value
})
})
}
render() {
const { list, count, height } = this.props
const { showModal, temp } = this.state
let name = temp && temp.name ? '设备组信息' : '新建设备组'
return (
<View className="device-list">
<ListView
count={count}
height={height}
dataListLength={list.length}
pullingUp={done => this.pullingUp(done)}
pullingDown={done => this.pullingDown(done)}
>
{list.map(item => (
<AtSwipeAction
autoClose
key={item.equipmentId}
onClick={info => this.handleItem(item, info)}
options={[
{
text: '编辑',
style: {
backgroundColor: '#6190E8'
}
},
{
text: '删除',
style: {
backgroundColor: '#FF4949'
}
}
]}
>
<View className="group-item" onClick={() => this.goDetail(item.equipmentId)}>
<View className="group-item-content">{item.equipmentName}</View>
</View>
</AtSwipeAction>
))}
</ListView>
<View className="device-list-add-btn" onClick={this.AddGroup}>
<Text className="icon">+</Text>
</View>
{/* <AtModal isOpened>
<AtModalContent>
<View className="select-item" onClick={() => this.selectItem('')}>
<Text>扫码添加设备</Text>
</View>
<View className="select-item" onClick={() => this.selectItem('')}>
<Text>输入PIN码添加设备</Text>
</View>
</AtModalContent>
</AtModal> */}
{showModal ? (
<Modal title={name} onConfirm={this.inputConfirm} onCancel={this.cancelModal}>
<View className="film-modal">
<Input
placeholder="请输入设备组名称"
className="film-modal-input"
value={temp.name}
onInput={this.changeName}
/>
</View>
</Modal>
) : null}
</View>
)
}
}
export default DeviceGroup as ComponentClass<PageOwnProps, PageState>
import ShopList from './shop_list' import ShopList from './shop_list'
import DeviceList from './device_list' import DeviceList from './device_list'
import DeviceGroup from './group_list'
import { ComponentClass } from 'react' import { ComponentClass } from 'react'
import { AtTabs, AtTabsPane } from 'taro-ui' import { AtTabs, AtTabsPane } from 'taro-ui'
import Taro, { Component, Config } from '@tarojs/taro' import Taro, { Component, Config } from '@tarojs/taro'
...@@ -25,7 +26,7 @@ interface Device { ...@@ -25,7 +26,7 @@ interface Device {
state: PageState state: PageState
} }
const tabList = [{ title: '我的设备' }, { title: '设备商城' }] const tabList = [{ title: '我的设备' }, { title: '设备组' }, { title: '设备商城' }]
class Device extends Component { class Device extends Component {
config: Config = { config: Config = {
navigationBarTitleText: '', navigationBarTitleText: '',
...@@ -56,6 +57,11 @@ class Device extends Component { ...@@ -56,6 +57,11 @@ class Device extends Component {
</AtTabsPane> </AtTabsPane>
<AtTabsPane className="at-tabs-page" current={current} index={1}> <AtTabsPane className="at-tabs-page" current={current} index={1}>
<View style={{ height: `${windowHeight}px` }}> <View style={{ height: `${windowHeight}px` }}>
<DeviceGroup height={windowHeight} />
</View>
</AtTabsPane>
<AtTabsPane className="at-tabs-page" current={current} index={2}>
<View style={{ height: `${windowHeight}px` }}>
<ShopList height={windowHeight} /> <ShopList height={windowHeight} />
</View> </View>
</AtTabsPane> </AtTabsPane>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment