Browse Source

add device api

voice
刘嘉炜 5 years ago
parent
commit
765a189de8
  1. 2
      src/pages/employee/manage/manage.vue
  2. 15
      src/store/actions.js
  3. 34
      src/store/device.js
  4. 4
      src/store/index.js
  5. 32
      src/subpackage/device/components/store_name/store_name.vue
  6. 7
      src/subpackage/device/js/device_api.js
  7. 275
      src/subpackage/device/js/ouxuanac.md
  8. 21
      src/subpackage/device/pages/index/index.vue
  9. 120
      src/subpackage/device/pages/switch_manage/switch_manage.vue

2
src/pages/employee/manage/manage.vue

@ -59,7 +59,7 @@
<view class="ei-author">
<view>权限</view>
<view>
<view class="tag-active" v-if="k.extension.permission.menu.length == 9">全部权限</view>
<view class="tag-active" v-if="k.extension.permission.menu.length == 10">全部权限</view>
<view v-else v-for="e in k.extension.permission.menu" :key="e">{{permissionObj[e] || ''}}</view>
</view>
</view>

15
src/store/actions.js

@ -1,5 +1,16 @@
// 异步方法
import { servers } from '../js/server';
import { API } from '../js/api';
export default {
getBrandInfo({commit, state}){
return servers.get({
url: API.calc,
data: {},
failMsg: '加载数据失败!'
})
.then(res=>{
commit('setBrandInfo',res);
return res;
})
}
}

34
src/store/device.js

@ -0,0 +1,34 @@
import deviceServer from '../subpackage/device/js/device_server';
import deviceApi from '../subpackage/device/js/device_api';
export default {
state(){
return {
storeList: [],
curStoreInfo: {}
}
},
mutations: {
setStoreList(state, query){
state.storeList = query;
},
setStoreInfo(state, query){
state.curStoreInfo = query;
}
},
actions: { // 小程序模块化访问失败 this.$store.dispatch('device/getStoreList')
getStoreList({ commit, state , rootState}){
return deviceServer.get({
url: deviceApi.stadiumList,
data: { brand_id: rootState.brandInfo.brand.id },
failMsg: '加载失败!',
})
.then(res=>{
let _list = res.list || [];
commit('setStoreList', _list);
if(JSON.stringify(state.curStoreInfo) == '{}'&&_list.length)commit('setStoreInfo', _list[0]);
return res;
})
}
}
}

4
src/store/index.js

@ -2,9 +2,13 @@ import Vue from 'vue';
import Vuex from 'vuex';
import mutations from './mutations';
import actions from './actions';
import device from './device';
Vue.use(Vuex);
export default new Vuex.Store({
modules: {
device
},
state: {
// #ifdef MP-WEIXIN
APPID: uni.getAccountInfoSync().miniProgram.appId,

32
src/subpackage/device/components/store_name/store_name.vue

@ -1,18 +1,37 @@
<template>
<view class="store-name">
<image class="sn-logo"></image>
<view class="sn-txt">欧轩智能羽毛球馆(番禺店) </view>
<image class="sn-arrow" mode="aspectFit" src="../../static/images/arrow_b2.png"></image>
</view>
<picker class="store-name-picker" :range="storeList" range-key="name" @change="storeChange">
<view class="store-name">
<image class="sn-logo" mode="aspectFit" :src="curStoreInfo.logo || ''"></image>
<view class="sn-txt">{{curStoreInfo.name || '-'}}</view>
<image class="sn-arrow" mode="aspectFit" src="../../static/images/arrow_b2.png"></image>
</view>
</picker>
</template>
<script>
import { mapState } from 'vuex'
export default {
computed: {
...mapState({
storeList: state => state.device.storeList,
curStoreInfo: state => state.device.curStoreInfo,
})
},
methods: {
storeChange(e){
let { storeList, curStoreInfo } = this;
let _curSelect = storeList[e.detail.value];
if(_curSelect.id!==curStoreInfo.id)this.$store.commit('setStoreInfo', _curSelect);
console.log(e)
}
}
}
</script>
<style>
.store-name-picker{
width: 100%;
}
.store-name{
display: flex;
align-items: center;
@ -27,7 +46,6 @@ export default {
margin-right: 20upx;
width: 52upx;
height: 52upx;
background-color: skyblue;
}
.sn-txt{
flex-grow: 1;

7
src/subpackage/device/js/device_api.js

@ -1,7 +1,12 @@
import { ORIGIN } from '../../../js/api';
export const DEVICE_API = {
hardwareList:`${ORIGIN}/admin/stadium/hardware/list`, // 品牌信息
stadiumList:`${ORIGIN}/stadium/list`, // 店铺列表
hardwareList:`${ORIGIN}/admin/stadium/hardware/list`, // 设备列表
ouxuanac:`${ORIGIN}/ouxuanac/sendPacket`, // 中控控制
// ouxuanac--> http://api.ouxuan.net/project/233/interface/api/10012 接口文档
// ouxuanac--> http://git.ouxuan.net/ouxuanac/ouxuanac-common/src/branch/master/cmd.ts // 接口参数结构 || ouxuanac.md
}
export default DEVICE_API;

275
src/subpackage/device/js/ouxuanac.md

@ -0,0 +1,275 @@
### 请求示例
``` json
{
"device":"00-10-7a-0f-6d-7a",
"data":{ // 此对象为下面提供的function对象
"name":"set-rpio",
"value":{
"id":"12",
"status":"low"
}
},
"token": ""
}
```
### 接口参数数据结构
```ts
enum RelayOP {
Low = "low", // 低电位,为开启
High = "high", // 高电位, 为关闭
}
//--------------------------if 通讯方式为开关量时使用-----------------------------
//原生继电器
function relayPacket(id: string, op: RelayOP) {
return {
"name": "set-rpio",
"value": {
"id": id,
"status": op
}
}
}
//原生继电器获取状态 通讯方式为开关量时使用
function relayGetPacket(id: string) {
return {
"name": "get-rpio",
"value": {
"id": id,
}
}
}
//-------------------------------------------------------
//--------------------------if 通讯方式485,且设备类型为 照明/风扇/门禁/水阀 时使用-----------------------------
//485继电器 p为继电器口和原生继电器id意义一致
function relay485Packet(id: string, p: string, o: RelayOP) {
return {
"name": "zzio404d-gpio",
"value": {
"id": id,
"p": p,
"o": o,
}
}
}
//获取状态 返回RelayOP
function relay485StatusPacket(id: string, p: string) {
return {
"name": "zzio404d-gpio-status",
"value": {
"id": id,
"p": p,
}
}
}
//-------------------------------------------------------
//--------------------------if 通讯方式Tcp,且设备类型为 照明/风扇/门禁/水阀 时使用-----------------------------
//Tcp继电器 o为空时获取状态
function relayTcpPacket(tcp: string, id: string, p: string, o: RelayOP) {
return {
"name": "zzio404d-gpio-tcp",
"value": {
"tcp": tcp,
"id": id,
"p": p,
"o": o,
}
}
}
//获取状态 返回RelayOP
function relayTcpStatusPacket(tcp: string, id: string, p: string) {
return {
"name": "zzio404d-gpio-status-tcp",
"value": {
"id": id,
"tcp": tcp,
"p": p,
}
}
}
enum AirOP {
status = "status",
on = "on",
off = "off",
}
//--------------------------if 通讯方式485, 设备类型为空调 ,硬件型号为Acmelec 时使用-----------------------------
//485通讯的acmelec
function air485AcmelecPacket(id: string, op: AirOP) {
return {
"name": "acmelec",
"value": {
"id": id,
"op": op,
}
}
}
//--------------------------if 通讯方式485, 设备类型为空调 ,硬件型号为Zhongnan 时使用-----------------------------
//485的中南
function air485ZhongnanPacket(id: string, op: AirOP) {
return {
"name": "zhongnan",
"value": {
"id": id,
"op": op,
}
}
}
//--------------------------if 通讯方式485, 设备类型为空调 ,硬件型号为Jianda 时使用-----------------------------
//485的仁大建科
function air485JiandaPacket(id: string, op: AirOP) {
return {
"name": "ray-air-rs",
"value": {
"id": id,
"op": op,
}
}
}
//--------------------------if 通讯方式tcp, 设备类型为空调 ,硬件型号为Jianda 时使用-----------------------------
//tcp的仁大建科
function airTcpJiandaPacket(tcp: string, id: string, op: AirOP) {
return {
"name": "ray-air-rs-tcp",
"value": {
"tcp": tcp,
"id": id,
"op": op,
}
}
}
enum LockerOP {
status = "status",
on = "on",
}
//--------------------------if 通讯方式485, 设备类型为储物柜时使用-----------------------------
//485 储物柜
//tcp 储物柜 cid为硬件地址id id为具体箱子的id
function Locker485Packet(id: string, cid: string, op: LockerOP) {
return {
"name": "lock-b",
"value": {
"id": id,
"cid": cid,
"op": op,
}
}
}
//--------------------------if 通讯方式tcp, 设备类型为储物柜时使用-----------------------------
//tcp 储物柜 cid为硬件地址id id为具体箱子的id
function LockerTcpPacket(tcp: string, cid: string, id: string, op: LockerOP) {
return {
"name": "lock-b-tcp",
"value": {
"tcp": tcp,
"id": id,
"cid": cid,
"op": op,
}
}
}
//--------------------------if 通讯方式tcp, 设备类型为售货柜 硬件型号为 yunyin 时使用-----------------------------
//售货柜出货
function YunyinPacket(tcp: string, id: string) {
//请求三次接口 重置 开启 重置
return [
{
"name": "yunyin-reseq",
"value": {
"tcp": tcp,
"id": id,
}
},
{
"name": "yunyin-pop",
"value": {
"tcp": tcp,
"id": id,
}
},
{
"name": "yunyin-reseq",
"value": {
"tcp": tcp,
"id": id,
}
},
]
}
//获取yunyin机器码
function YunyinMacPacket(tcp: string) {
return [
{
"name": "yunyin-mac",
"value": {
"tcp": tcp,
}
}
]
}
enum CoffeeboxTemperature {
hot = "hot", //热
cold = "cold", //冷
}
//--------------------------if 通讯方式tcp, 设备类型为咖啡机 硬件型号为 miaoque 时使用-----------------------------
function CoffeeboxPacket(tcp: string, id: string, t: CoffeeboxTemperature) {
return {
"name": "coffeebox-tcp",
"value": {
"tcp": tcp,
"id": id,
"t": t,
}
}
}
//--------------------------if 通讯方式tcp, 设备类型为门闸时使用-----------------------------
//门闸
function GatePacket(tcp: string, cid: string,) {
return {
"name": "gate",
"value": {
"tcp": tcp,
"cid": cid, //进出控制ID |进入-> enter_id 离开-> leave_id|
},
"is_delay": true,
"queue_group": "gate",
}
}
```

21
src/subpackage/device/pages/index/index.vue

@ -45,16 +45,16 @@ export default {
tabArr,
}
},
onLoad(){
deviceServer.get({
url: deviceApi.hardwareList,
data: {
'filter[hardware_type]': 'GateControl',
'filter[stadium_id]': 151,
},
failMsg: '加载失败!',
})
.then(console.log)
async onLoad(){
try{
util.showLoad();
let _brandInfo = await this.$store.dispatch('getBrandInfo');
await this.$store.dispatch('getStoreList');
util.hideLoad();
}catch(err){
util.hideLoad();
}
},
methods: {
getImgPath(id){
@ -63,6 +63,7 @@ export default {
},
routeTo(e){
if(e.path == '')return util.showNone('暂未开放!');
if(e.id != 5)return util.showNone(`开发中!`);
util.routeTo(`${rootPage}${e.path}?sid=${e.id}`, 'nT');
}
}

120
src/subpackage/device/pages/switch_manage/switch_manage.vue

@ -3,25 +3,27 @@
<store-name></store-name>
<view class="sm-tit">{{pageInfo.name || '-'}}</view>
<view class="sm-list">
<view class="sl-item" v-for="i in 5" :key="i">
<view class="sl-item" v-for="(e, i) in deviceList" :key="i">
<view class="si-top">
<image mode="aspectFit" :src="getIcon()"></image>
<view class="st-right">
<view class="sr-name">大堂</view>
<view class="sr-bot">
<view>
<text>设备在线</text>
<view class="sr-name">{{e.hardware_name || '-'}}</view>
<!-- 门闸没有状态查询 -->
<view class="sr-bot" v-if="pageInfo.id !=5">
<!-- 请求接口自定义字段设备状态 1->在线0->离线 -->
<view :class="[e.defineStatus == 1?'active':'']">
<text>{{ e.defineStatus == 1 ? '设备在线' : e.defineStatus == 0?'设备离线' : '-' }}</text>
</view>
<image mode="aspectFit" src="/subpackage/device/static/images/refresh.png"></image>
</view>
</view>
</view>
<view class="si-bottom" v-if="pageInfo.isOpen || pageInfo.isClose">
<view v-if="pageInfo.isOpen">
<view v-if="pageInfo.isOpen" @click="operateBtn({ info: e, status: 1 })">
<image mode="aspectFit" :src="pageInfo.openIcon || ''"></image>
<view>{{pageInfo.openName || '-'}}</view>
</view>
<view v-if="pageInfo.isClose">
<view v-if="pageInfo.isClose" @click="operateBtn({ info: e, status: 0 })">
<image mode="aspectFit" :src="pageInfo.closeIcon || ''"></image>
<view>{{pageInfo.closeName || '-'}}</view>
</view>
@ -32,76 +34,151 @@
</template>
<script>
//
import store_name from '../../components/store_name/store_name';
import deviceServer from '../../js/device_server';
import deviceApi from '../../js/device_api';
const showArr = {
's1': {
id: 1, name: '照明管理', isOpen: true, isClose: true,
openIcon: '/subpackage/device/static/images/open.png',
closeIcon: '/subpackage/device/static/images/close.png',
openName: '开', closeName: '关',
openName: '开', closeName: '关', hardware_type: 'Light'
},
's2': {
id: 2, name: '空调管理', isOpen: true, isClose: true,
openIcon: '/subpackage/device/static/images/open.png',
closeIcon: '/subpackage/device/static/images/close.png',
openName: '开', closeName: '关',
openName: '开', closeName: '关', hardware_type: 'Air'
},
's3': {
id: 3, name: '风扇管理', isOpen: true, isClose: true,
openIcon: '/subpackage/device/static/images/open.png',
closeIcon: '/subpackage/device/static/images/close.png',
openName: '开', closeName: '关',
openName: '开', closeName: '关', hardware_type: 'Fan'
},
's4': {
id: 4, name: '门禁管理', isOpen: true, isClose: false,
openIcon: '/subpackage/device/static/images/open.png',
closeIcon: '/subpackage/device/static/images/close.png',
openName: '开', closeName: '关',
openName: '开', closeName: '关', hardware_type: 'AccessControl'
},
's5': {
id: 5, name: '门闸管理', isOpen: true, isClose: true,
openIcon: '/subpackage/device/static/images/in.png',
closeIcon: '/subpackage/device/static/images/out.png',
openName: '进', closeName: '出',
openName: '进', closeName: '出', hardware_type: 'GateControl'
},
's6': {
id: 6, name: '平板管理', isOpen: false, isClose: false,
openIcon: '/subpackage/device/static/images/open.png',
closeIcon: '/subpackage/device/static/images/close.png',
openName: '开', closeName: '关',
openName: '开', closeName: '关', hardware_type: ''
},
's11': {
id: 11, name: '水阀管理', isOpen: true, isClose: true,
openIcon: '/subpackage/device/static/images/open.png',
closeIcon: '/subpackage/device/static/images/close.png',
openName: '开', closeName: '关',
openName: '开', closeName: '关', hardware_type: 'WaterValve'
},
's12': {
id: 12, name: '互动设备管理', isOpen: true, isClose: true,
openIcon: '/subpackage/device/static/images/open.png',
closeIcon: '/subpackage/device/static/images/close.png',
openName: '开', closeName: '关',
openName: '开', closeName: '关', hardware_type: ''
},
}
import { mapState } from 'vuex';
import util from '../../../../utils/util';
export default {
components: {
'store-name': store_name
},
computed: {
...mapState({
curStoreInfo: state => state.device.curStoreInfo,
})
},
watch: {
curStoreInfo(newVal, oldVal){
this.getDeviceList({
stadium_id: newVal.id,
hardware_type: this.pageInfo.hardware_type
})
}
},
data(){
return {
pageInfo: {}
pageInfo: {},
deviceList: [],
}
},
onLoad(options){
let _pageInfo = showArr[`s${options.sid}`] || {};
this.pageInfo = _pageInfo;
uni.setNavigationBarTitle({ title: _pageInfo.name });
this.getDeviceList({
stadium_id: this.curStoreInfo.id,
hardware_type: _pageInfo.hardware_type
})
},
methods: {
getDeviceList({
stadium_id,
hardware_type,
limit = 100,
page = 1
}){
util.showLoad();
deviceServer.get({
url: deviceApi.hardwareList,
data: {
'filter[hardware_type]': hardware_type,
'filter[stadium_id]': stadium_id,
'limit': limit,
'page': page,
},
failMsg: '加载失败!'
})
.then(res=>{
util.hideLoad();
let _list = res.list || [];
this.deviceList = _list;
console.log(res)
})
.catch(util.hideLoad)
},
// status 0 -> 1 ->
operateBtn({ info, status }){
let { curStoreInfo } = this;
let _cid = status === 1? info.enter_id + '':status === 0?info.leave_id:''; // ID |-> enter_id -> leave_id|
let _query = {
name: 'gate',
value: {
tcp: info.hardware_net_addr + '',
cid: _cid
},
is_delay: true,
queue_group: 'gate'
}
deviceServer.post({
url: deviceApi.ouxuanac,
data: {
device: curStoreInfo.device_name, // ,
data: _query, // src\subpackage\device\js\ouxuanac.md
},
failMsg: '操作失败!'
})
.then(res=>{
console.log(res);
})
},
getIcon(){
let { pageInfo } = this;
if(!pageInfo.id)return '';
@ -162,6 +239,7 @@ export default {
line-height: 28upx;
border-radius: 28upx;
border: 2upx solid #9A9A9D;
color: #9A9A9D;
&::before{
content: '';
margin-right: 12upx;
@ -171,7 +249,13 @@ export default {
width: 8upx;
height: 8upx;
border-radius: 50%;
background-color: $themeColor;
background-color: #9A9A9D;
}
&.active{
color: #333333;
&::before{
background-color: $themeColor;
}
}
}
>image{

Loading…
Cancel
Save