Browse Source

feat:巡检1.7代码

master
zhaobing’ 10 months ago
parent
commit
ba0e114983
  1. 145
      api/app/lib/controllers/advisoryNotice/advisoryNotice.js
  2. 118
      api/app/lib/controllers/device/network.js
  3. 6
      api/app/lib/index.js
  4. 60
      api/app/lib/models/advisory_notice.js
  5. 66
      api/app/lib/models/network.js
  6. 19
      api/app/lib/routes/advisoryNotice/advisoryNotice.js
  7. 20
      api/app/lib/routes/device/network.js
  8. 18
      script/1.7/schema/1.create_advisory_notice.sql
  9. 26
      script/1.7/schema/2.create_network.sql
  10. 8
      weapp/app.json
  11. BIN
      weapp/images/importantNews.png
  12. 25
      weapp/package/AIOTOverview/AIOTOverview.js
  13. 25
      weapp/package/AIOTOverview/AIOTOverview.wxml
  14. 139
      weapp/package/AIOTOverview/network/network.js
  15. 8
      weapp/package/AIOTOverview/network/network.json
  16. 44
      weapp/package/AIOTOverview/network/network.wxml
  17. 69
      weapp/package/AIOTOverview/network/network.wxss
  18. 108
      weapp/package/advisoryNotice/advisoryNotice.js
  19. 6
      weapp/package/advisoryNotice/advisoryNotice.json
  20. 14
      weapp/package/advisoryNotice/advisoryNotice.wxml
  21. 41
      weapp/package/advisoryNotice/advisoryNotice.wxss
  22. 76
      weapp/package/advisoryNotice/detail/detail.js
  23. 6
      weapp/package/advisoryNotice/detail/detail.json
  24. 11
      weapp/package/advisoryNotice/detail/detail.wxml
  25. 16
      weapp/package/advisoryNotice/detail/detail.wxss
  26. 6
      weapp/package/polling/inspectionRecordDetail/inspectionRecordDetail.js
  27. 41
      weapp/package/riskManagement/riskCalendar/riskCalendar.js
  28. 5
      weapp/package/riskManagement/riskCalendar/riskCalendar.json
  29. 17
      weapp/package/riskManagement/riskCalendar/riskCalendar.wxml
  30. 5
      weapp/package/riskManagement/riskCalendar/riskCalendar.wxss
  31. 72
      weapp/package/troubleshooting/index.js
  32. 6
      weapp/package/troubleshooting/index.wxml
  33. 14
      weapp/pages/home/home.js
  34. 10
      weapp/pages/home/home.wxml
  35. 9
      weapp/pages/home/home.wxss
  36. 7
      weapp/pages/myInfo/myInfo.js
  37. 6
      weapp/pages/myInfo/myInfo.wxml
  38. 7
      weapp/pages/workbench/workbench.js
  39. 4
      weapp/pages/workbench/workbench.wxml
  40. 10
      weapp/utils/getApiUrl.js
  41. 3
      web/client/src/app.js
  42. 60
      web/client/src/sections/advisoryNotice/actions/advisoryNotice.js
  43. 6
      web/client/src/sections/advisoryNotice/actions/index.js
  44. 108
      web/client/src/sections/advisoryNotice/components/addAdvisoryNoticeModal.js
  45. 208
      web/client/src/sections/advisoryNotice/containers/advisoryNotice.js
  46. 5
      web/client/src/sections/advisoryNotice/containers/index.js
  47. 0
      web/client/src/sections/advisoryNotice/containers/style.less
  48. 15
      web/client/src/sections/advisoryNotice/index.js
  49. 14
      web/client/src/sections/advisoryNotice/nav-item.js
  50. 5
      web/client/src/sections/advisoryNotice/reducers/index.js
  51. 12
      web/client/src/sections/advisoryNotice/routes.js
  52. 3
      web/client/src/sections/deviceManage/actions/index.js
  53. 50
      web/client/src/sections/deviceManage/actions/network.js
  54. 103
      web/client/src/sections/deviceManage/components/addNetworkModal.js
  55. 4
      web/client/src/sections/deviceManage/containers/index.js
  56. 213
      web/client/src/sections/deviceManage/containers/network.js
  57. 17
      web/client/src/sections/deviceManage/nav-item.js
  58. 17
      web/client/src/sections/deviceManage/routes.js
  59. 12
      web/client/src/utils/webapi.js

145
api/app/lib/controllers/advisoryNotice/advisoryNotice.js

@ -0,0 +1,145 @@
'use strict';
const moment = require('moment')
async function getAdvisoryNotices (ctx) {
try{
const models = ctx.fs.dc.models
const { limit, page, name,home } = ctx.query
let options
if(home==='true'){
options = {
where: {state:2},
order: [['publish_time', 'desc']],
limit: 1,
}
}else if(home==='false'){
options = {
where: {state:2},
order: [['id', 'asc']],
}
}else{
options = {
where: {},
order: [['id', 'asc']],
}
}
if (name) {
options.where.name = { $like: `%${name}%` };
}
if (limit) {
options.limit = Number(limit);
}
if (page && limit) {
options.offset = Number(page) * Number(limit);
}
const advisoryNoticeList = await models.AdvisoryNotice.findAndCountAll(options)
ctx.status = 200;
ctx.body = advisoryNoticeList
}catch(error){
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {
"message": "获取资讯公告失败"
}
}
}
async function addOrUpdateAdvisoryNotice(ctx){
const { id, title,content,attachments } = ctx.request.body
try{
if(id){
// 更新
await ctx.fs.dc.models.AdvisoryNotice.update({
title,
content,
attachments,
}, {
where: {
id
}
})
ctx.status = 200;
ctx.body = {
message: '更新资讯公告成功'
}
}else{
//新增
await ctx.fs.dc.models.AdvisoryNotice.create({
title,
content,
attachments,
state:1
})
ctx.status = 200;
ctx.body = {
message: '新增资讯公告成功'
}
}
}catch(error){
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {
"message": id?'编辑资讯公告失败':'新增资讯公告失败'
}
}
}
async function delAdvisoryNotice(ctx){
try{
const { id } = ctx.params
await ctx.fs.dc.models.AdvisoryNotice.destroy({
where: {
id
}
})
ctx.status = 200;
ctx.body = {
message: '删除资讯公告成功'
}
}catch(error){
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {
"message": "删除资讯公告失败"
}
}
}
//上架下架
async function updateAdvisoryNoticeState(ctx){
const { id } = ctx.params
const { msg ,publishTime} = ctx.request.body
try{
await ctx.fs.dc.models.AdvisoryNotice.update({
state:msg==='发布'?2:3,
publishTime:msg==='发布'?moment().format('YYYY-MM-DD HH:mm:ss'):publishTime,
},{where:{id}})
ctx.status = 204
}catch(error){
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {
"message": `${msg}公告失败`
}
}
}
module.exports = {
getAdvisoryNotices,
addOrUpdateAdvisoryNotice,
delAdvisoryNotice,
updateAdvisoryNoticeState
}

118
api/app/lib/controllers/device/network.js

@ -0,0 +1,118 @@
'use strict';
const moment = require('moment')
async function getNetworks (ctx) {
try{
const models = ctx.fs.dc.models
const { limit, page, name } = ctx.query
let options = {
where: {},
order: [['id', 'asc']],
include:[{
model: models.Project,
attributes: ['id', 'name','type'],
}]
}
if (name) {
options.where.name = { $like: `%${name}%` };
}
if (limit) {
options.limit = Number(limit);
}
if (page && limit) {
options.offset = Number(page) * Number(limit);
}
const Networks = await models.Network.findAndCountAll(options)
ctx.status = 200;
ctx.body = Networks
}catch(error){
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {
"message": "获取宽带专网失败"
}
}
}
async function addOrUpdateNetwork(ctx){
const { id,name,type,account,indate,projectId } = ctx.request.body
try{
if(id){
// 更新
await ctx.fs.dc.models.Network.update({
name,
type,
account,
indate,
projectId
}, {
where: {
id
}
})
ctx.status = 200;
ctx.body = {
message: '更新宽带专网成功'
}
}else{
//新增
await ctx.fs.dc.models.Network.create({
name,
type,
account,
indate,
projectId
})
ctx.status = 200;
ctx.body = {
message: '新增宽带专网成功'
}
}
}catch(error){
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {
"message": id?'编辑宽带专网失败':'新增宽带专网失败'
}
}
}
async function delNetwork(ctx){
try{
const { id } = ctx.params
await ctx.fs.dc.models.Network.destroy({
where: {
id
}
})
ctx.status = 200;
ctx.body = {
message: '删除宽带专网成功'
}
}catch(error){
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {
"message": "删除宽带专网失败"
}
}
}
module.exports = {
getNetworks,
addOrUpdateNetwork,
delNetwork,
}

6
api/app/lib/index.js

@ -57,7 +57,7 @@ module.exports.models = function (dc) { // dc = { orm: Sequelize对象, ORM: Seq
PatrolPlan, PatrolRecord, ReportInfo, PatrolPlanUser,
CheckItems, CheckItemsGroup,
PatrolTemplate, PatrolTemplateCheckItems, PatrolRecordIssueHandle,
Device, PointDevice
Device, PointDevice,Network
} = dc.models;
PatrolRecord.belongsTo(PatrolPlan, { foreignKey: 'patrolPlanId', targetKey: 'id' });
@ -115,6 +115,6 @@ module.exports.models = function (dc) { // dc = { orm: Sequelize对象, ORM: Seq
Device.belongsToMany(Point,{ through: PointDevice, foreignKey: 'deviceId', otherKey: 'pointId' })
Point.belongsToMany(Device,{ through: PointDevice, foreignKey: 'pointId', otherKey: 'deviceId' })
Network.belongsTo(Project,{ foreignKey: 'projectId', otherKey: 'id' })
Project.hasMany(Network,{ foreignKey: 'projectId', sourceKey: 'id' })
};

60
api/app/lib/models/advisory_notice.js

@ -0,0 +1,60 @@
/* eslint-disable*/
'use strict';
module.exports = dc => {
const DataTypes = dc.ORM;
const sequelize = dc.orm;
const AdvisoryNotice = sequelize.define("AdvisoryNotice", {
id: {
field: "id",
type: DataTypes.INTEGER,
allowNull: false,
primaryKey: true,
autoIncrement: true,
},
title: {
field: "title",
type: DataTypes.STRING,
allowNull: false,
primaryKey: false,
autoIncrement: false
},
publishTime: {
field: "publish_time",
type: DataTypes.DATE,
allowNull: true,
primaryKey: false,
autoIncrement: false,
timezone: false, // 设置为 false 表示不带时区信息的时间戳
},
state: {
field: "state",
type: DataTypes.INTEGER,
allowNull: false,
primaryKey: false,
autoIncrement: false
},
content: {
field: "content",
type: DataTypes.TEXT,
allowNull: false,
primaryKey: false,
autoIncrement: false
},
attachments: {
type: DataTypes.ARRAY(DataTypes.STRING),
allowNull: false,
comment: null,
primaryKey: false,
field: "attachments",
autoIncrement: false
},
}, {
tableName: "advisory_notice",
comment: "",
indexes: []
});
dc.models.AdvisoryNotice = AdvisoryNotice;
return AdvisoryNotice;
};

66
api/app/lib/models/network.js

@ -0,0 +1,66 @@
/* eslint-disable*/
'use strict'
module.exports = dc => {
const DataTypes = dc.ORM
const sequelize = dc.orm
const Network = sequelize.define(
'Network',
{
id: {
field: 'id',
type: DataTypes.INTEGER,
allowNull: false,
primaryKey: true,
autoIncrement: true,
unique: 'network_pk',
},
name: {
field: 'name',
type: DataTypes.STRING,
allowNull: false,
primaryKey: false,
autoIncrement: false,
},
type: {
field: 'type',
type: DataTypes.INTEGER,
allowNull: false,
primaryKey: false,
autoIncrement: false,
// timezone: false, // 设置为 false 表示不带时区信息的时间戳
},
account: {
field: 'account',
type: DataTypes.STRING,
allowNull: false,
primaryKey: false,
autoIncrement: false,
},
indate: {
field: 'indate',
type: DataTypes.DATE,
allowNull: false,
primaryKey: false,
autoIncrement: false,
timezone: false, // 设置为 false 表示不带时区信息的时间戳
},
projectId: {
type: DataTypes.INTEGER,
allowNull: false,
comment: null,
primaryKey: false,
field: 'project_id',
autoIncrement: false,
},
},
{
tableName: 'network',
comment: '',
indexes: [],
}
)
dc.models.Network = Network
return Network
}

19
api/app/lib/routes/advisoryNotice/advisoryNotice.js

@ -0,0 +1,19 @@
'use strict';
const advisoryNotice = require('../../controllers/advisoryNotice/advisoryNotice');
module.exports = function (app, router, opts) {
app.fs.api.logAttr['GET/advisoryNotices/list'] = { content: '获取资讯公告', visible: true };
router.get('/advisoryNotices/list', advisoryNotice.getAdvisoryNotices);
app.fs.api.logAttr['POST/advisoryNotices/addOrUpdate'] = { content: '新增或编辑资讯公告', visible: true };
router.post('/advisoryNotices/addOrUpdate', advisoryNotice.addOrUpdateAdvisoryNotice);
app.fs.api.logAttr['DEL/advisoryNotices/:id'] = { content: '删除资讯公告', visible: true };
router.delete('/advisoryNotices/:id', advisoryNotice.delAdvisoryNotice);
app.fs.api.logAttr['POST/updateAdvisoryNotices/:id'] = { content: '上架或者下架公告', visible: true };
router.post('/updateAdvisoryNotices/:id', advisoryNotice.updateAdvisoryNoticeState);
};

20
api/app/lib/routes/device/network.js

@ -0,0 +1,20 @@
'use strict';
const network = require('../../controllers/device/network');
module.exports = function (app, router, opts, AuthCode) {
app.fs.api.logAttr['POST/network'] = { content: '增加或修改宽带专网', visible: true };
router.post('/network', network.addOrUpdateNetwork)
// 删除设备信息
app.fs.api.logAttr['DEL/network/:id'] = { content: '删除宽带专网', visible: true };
router.del('/network/:id', network.delNetwork)
// 获取设备信息列表
app.fs.api.logAttr['GET/network'] = { content: '获取宽带专网列表', visible: true };
router.get('/network', network.getNetworks);
};

18
script/1.7/schema/1.create_advisory_notice.sql

@ -0,0 +1,18 @@
create table advisory_notice
(
id serial
constraint advisory_notice_pk
primary key,
title varchar(300) not null,
publish_time timestamp without TIME ZONE,
state integer not null,
content text not null,
attachments text[]
);
comment on column advisory_notice.title is '公告标题';
comment on column advisory_notice.publish_time is '发布时间';
comment on column advisory_notice.state is '/*1.草稿,2.已发布,3.已下架*/';

26
script/1.7/schema/2.create_network.sql

@ -0,0 +1,26 @@
create table network
(
id serial
constraint network_pk
primary key,
name varchar(300) not null,
type integer not null,
account varchar(300) not null,
indate timestamp without time zone not null,
project_id integer not null
constraint project_id
references public.project
);
comment on table network is '宽带专网';
comment on column network.name is '专网名称';
comment on column network.type is '专网类型/*1.专网,2.内网*/';
comment on column network.account is '账号';
comment on column network.indate is '有效期';
comment on column network.project_id is '关联的结构物';

8
weapp/app.json

@ -33,7 +33,10 @@
"groundDisasterInspection/groundDisasterInspection",
"AIOTOverview/AIOTOverview",
"AIOTOverview/flowMonitoring/flowMonitoring",
"AIOTOverview/electricityMonitoring/electricityMonitoring"
"AIOTOverview/electricityMonitoring/electricityMonitoring",
"advisoryNotice/advisoryNotice",
"advisoryNotice/detail/detail",
"AIOTOverview/network/network"
]
}
],
@ -87,7 +90,8 @@
}
},
"requiredPrivateInfos": [
"getLocation","chooseLocation"
"getLocation",
"chooseLocation"
],
"sitemapLocation": "sitemap.json",
"usingComponents": {}

BIN
weapp/images/importantNews.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

25
weapp/package/AIOTOverview/AIOTOverview.js

@ -1,5 +1,5 @@
// package/AIOTOverview/AIOTOverview.js
import { getThingsDeploy, getThingsStatus, getCardInfo,getRelationList} from "../../utils/getApiUrl";
import { getThingsDeploy, getThingsStatus, getCardInfo,getRelationList,getNetworks} from "../../utils/getApiUrl";
import { Request } from "../../common";
const moment = require("../../utils/moment");
@ -9,6 +9,7 @@ Page({
* 页面的初始数据
*/
data: {
count:{abnormal:0,normal:0},//宽带专网正常与欠费
data: [],//用电设备数据
normal: 0,//正常
abnormal: 0,//异常
@ -32,6 +33,12 @@ Page({
url: `/package/AIOTOverview/electricityMonitoring/electricityMonitoring?data2=${encodeURIComponent(jsonData2)}`
})
},
//跳转宽带专网
navigatorToNet() {
wx.navigateTo({
url: `/package/AIOTOverview/network/network`
})
},
/**
* 生命周期函数--监听页面加载
*/
@ -106,7 +113,23 @@ Page({
abnormal: data?.filter(item => item.status == 0)?.length
})
}
Request.get(getNetworks()).then(res=>{
if(res.rows.length){
let normal=0
let abnormal=0
res.rows.forEach(q => {
if (moment(q.indate).isBefore(moment())) {
abnormal += 1;
} else {
normal += 1;
}
});
that.setData({
count:{normal,abnormal}
})
}
})
wx.hideLoading()
},

25
weapp/package/AIOTOverview/AIOTOverview.wxml

@ -58,5 +58,30 @@
<view class="content-right" style="color:red">{{iotCardHalt+'个'}}</view>
</view>
</view>
</view>
<!--宽带专网总览-->
<view class="card">
<view class="top">
<view style="display: flex; align-items: center;">
<text class="fontStyle">宽带专网总览</text>
</view>
<view class="detailStyle">
<van-button type="info" round size="small" bindtap="navigatorToNet">查看详情</van-button>
</view>
</view>
<view class="card-content">
<view class="row flex flex-between detail">
<view class="content-left" style="font-weight: bold;">专网条数</view>
<view class="content-right" style="font-weight: bold;">{{(count.normal+count.abnormal)+'个'}}</view>
</view>
<view class="row flex flex-between detail">
<view class="content-left">正常</view>
<view class="content-right">{{count.normal+'个'}}</view>
</view>
<view class="row flex flex-between detail">
<view class="content-left">欠费</view>
<view class="content-right" style="color:yellow">{{count.abnormal+'个'}}</view>
</view>
</view>
</view>
</view>

139
weapp/package/AIOTOverview/network/network.js

@ -0,0 +1,139 @@
// package/AIOTOverview/network/network.js
import { getNetworks,getProjectList} from "../../../utils/getApiUrl";
import { Request } from "../../../common";
import moment from "../../../utils/moment";
Page({
networkDataCopy:[],
/**
* 页面的初始数据
*/
data: {
limit: 10, //条数
page: 0, //当前页
count: 0, //总条数
networkData:[],
structList:[],
// networkDataCopy:[],
curStruId: 'all', // 选中结构物id
},
/**
* 生命周期函数--监听页面加载
*/
onLoad(options) {
this.queryData()
this.obtainStruc()
},
obtainStruc(){
let promiseArr=[]
promiseArr.push(Request.get(getProjectList()))
if(res[0].rows.length){
const filterData=res[0].rows.filter(s => s.type==='管廊' )
sdatas=filterData?.map(item=>( { value: item.id, text:item.name }))
sdatas.unshift({ text: '全部', value: 'all' })
}
this.setData({
structList:sdatas
})
},
queryData(){
const {limit,page}=this.data
let promiseArr=[]
promiseArr.push(Request.get(getNetworks(),{limit,page}))
Promise.all(promiseArr).then(res=>{
let datas=[]//宽带的数据
let sdatas=[]//结构物
if(res[0].rows.length){
datas=res[0].rows.filter(s => s.project.type==='管廊')?.map(q=>({
...q,
indate:moment(q.indate).format('YYYY-MM-DD'),
status:moment(q.indate).isBefore(moment())?1:0
}))
}
this.networkDataCopy=datas
this.setData({
networkData:datas,
})
})
},
onStruChange(e){
if (e.detail) {
let data = []
if (e.detail === 'all') {
data = this.networkDataCopy
} else {
data = this.networkDataCopy.filter(item => item.projectId === e.detail)
}
this.setData({
curStruId: e.detail,
networkData: data
})
}
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady() {
},
/**
* 生命周期函数--监听页面显示
*/
onShow() {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide() {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload() {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh() {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom() {
let _that=this
let page = _that.data.page + 1; //获取当前页数并+1
let { networkData, count } = _that.data;
if (networkData.length == count) {
wx.showToast({
title: '没有更多数据了...',
icon: 'none',
})
return;
}
_that.setData({
page: page, //更新当前页数
})
_that.queryData()
},
/**
* 用户点击右上角分享
*/
onShareAppMessage() {
}
})

8
weapp/package/AIOTOverview/network/network.json

@ -0,0 +1,8 @@
{
"navigationBarTitleText": "专网监控",
"usingComponents": {
"van-dropdown-menu": "@vant/weapp/dropdown-menu/index",
"van-dropdown-item": "@vant/weapp/dropdown-item/index",
"van-empty": "@vant/weapp/empty/index"
}
}

44
weapp/package/AIOTOverview/network/network.wxml

@ -0,0 +1,44 @@
<!--package/AIOTOverview/network/network.wxml-->
<!--package/AIOTOverview/flowMonitoring/flowMonitoring.wxml-->
<view>
<!--结构物选择器-->
<view class="select">
<van-dropdown-menu active-color="#1989fa">
<van-dropdown-item title="{{ '结构物' }}" bind:close="onClose" bind:change="onStruChange" value="{{ curStruId }}" options="{{ structList }}" />
</van-dropdown-menu>
</view>
<!--渲染列表-->
<view wx:if="{{networkData.length}}">
<view class="card" wx:for="{{networkData}}" wx:key='index'>
<view>
<!--头部-->
<view class="top">
<view style="display: flex; align-items: center;">
<text class="fontStyle">{{item.project.name}}</text>
</view>
</view>
<!--内容部分-->
<view class="card-content">
<view class="row flex flex-between detail">
<view class="content-left">账号:{{item.account}}</view>
<view class="content-right" wx:if="{{item.type===1}}">专网类型:专网</view>
<view class="content-right" wx:if="{{item.type===2}}">专网类型:内网</view>
</view>
<view class="row flex flex-between detail content">
<view class="content-left">专网名称:{{item.name}}</view>
<view wx:if="{{item.status==0}}" class="content-right">卡状态:正常</view>
<view wx:if="{{item.status==1}}" class="content-right">卡状态:异常</view>
</view>
<view class="row flex flex-between detail content">
<view class="content-left">有效期:{{item.indate}}</view>
</view>
</view>
</view>
</view>
</view>
<view wx:else>
<van-empty description="暂无数据" />
</view>
</view>

69
weapp/package/AIOTOverview/network/network.wxss

@ -0,0 +1,69 @@
/* package/AIOTOverview/network/network.wxss */
.select {
width: 50%;
}
.select .van-dropdown-menu {
box-shadow: none
}
/* package/AIOTOverview/AIOTOverview.wxss */
.card {
position: relative;
background-color: #fff;
border: 1px solid #ddd;
border-radius: 8px;
/* padding: 10px; */
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
margin: 12px 12px;
}
.top {
display: flex;
justify-content: space-between;
padding: 10px;
/* background-position: bottom; */
}
.card-content {
padding: 0 10px;
}
.card-left {
margin-left: 23px;
margin-bottom: 10px;
font-weight: 500;
font-size: 16px;
color: #000000d9;
}
.detail {
margin: 10px 0
}
.card-right {
margin-right: 18px;
margin-bottom: 10px;
color: #1684FF;
}
.fontStyle {
font-family: PingFangSC-Medium;
font-weight: bold;
}
.content-left {
font-size: 12px;
width: 60%;
}
.content-right {
font-size: 12px;
text-align: left;
width: 40%;
}

108
weapp/package/advisoryNotice/advisoryNotice.js

@ -0,0 +1,108 @@
// package/advisoryNotice/advisoryNotice.js
import { getAdvisoryNotices } from "../../utils/getApiUrl";
import { Request } from "../../common";
const moment = require("../../utils/moment");
Page({
/**
* 页面的初始数据
*/
data: {
limit: 10, //条数
page: 0, //当前页
count: '', //总条数
dataList:[],//公告列表
},
navToDetail:function(e){
const { item } = e.currentTarget.dataset
const res = JSON.stringify(item)
wx.navigateTo({
url: `/package/advisoryNotice/detail/detail?detailData=${encodeURIComponent(res)}`,
})
},
/**
* 生命周期函数--监听页面加载
*/
onLoad(options) {
const {windowHeight}=wx.getSystemInfoSync()
const pageHeight=windowHeight - 48
this.getAdvisoryNotices()
},
getAdvisoryNotices: function () {
const {limit,page}=this.data
wx.showLoading({
title: '加载中'
})
Request.get(getAdvisoryNotices({home:false}),{limit, page}).then(res=>{
if(res.rows.length){
this.setData({
dataList:res.rows,
count:res.count
},()=>{
wx.hideLoading()
})
}
})
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady() {
},
/**
* 生命周期函数--监听页面显示
*/
onShow() {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide() {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload() {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh() {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom() {
let _that = this;
let page = _that.data.page + 1; //获取当前页数并+1
let { dataList, count } = _that.data;
if (dataList.length == count) {
wx.showToast({
title: '没有更多数据了...',
icon: 'none',
})
return;
}
_that.setData({
page: page, //更新当前页数
})
_that.getAdvisoryNotices()
},
/**
* 用户点击右上角分享
*/
onShareAppMessage() {
}
})

6
weapp/package/advisoryNotice/advisoryNotice.json

@ -0,0 +1,6 @@
{
"navigationBarBackgroundColor": "#1979ff",
"navigationBarTextStyle": "white",
"navigationBarTitleText": "资讯公告",
"enablePullDownRefresh": false
}

14
weapp/package/advisoryNotice/advisoryNotice.wxml

@ -0,0 +1,14 @@
<!--package/advisoryNotice/advisoryNotice.wxml-->
<view wx:if="{{dataList.length}}">
<view wx:for="{{dataList}}" wx:key="*this">
<view class='body-item' bindtap="navToDetail" data-item="{{item}}">
<view class='body-info'>{{item.title}}</view>
<image class="right" src="/images/right.svg"></image>
</view>
</view>
</view>
<view wx:if="{{!dataList.length}}">
<!-- 暂无数据 -->
<image class="noData" src="../../images/noData.png"></image>
<view class="noTxt">暂无数据</view>
</view>

41
weapp/package/advisoryNotice/advisoryNotice.wxss

@ -0,0 +1,41 @@
/* package/advisoryNotice/advisoryNotice.wxss */
.right {
width: 32rpx;
height: 32rpx;
display: block;
float: right;
margin: 38rpx 40rpx;
}
.body-item {
height: 110rpx;
flex-direction: row;
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 30rpx;
border-bottom: 1px solid #EFEFF4;
}
.body-info {
font-size: 32rpx;
font-family: "PingFang SC";
font-weight: 600;
}
.noData {
width: 254rpx;
height: 298rpx;
display: block;
margin: 0rpx auto 16rpx;
}
.noTxt {
font-size: 30rpx;
color: #999;
font-weight: bold;
text-align: center;
}

76
weapp/package/advisoryNotice/detail/detail.js

@ -0,0 +1,76 @@
// package/advisoryNotice/detail/detail.js
const moment = require("../../../utils/moment");
Page({
/**
* 页面的初始数据
*/
data: {
detailData:{},//一條詳細記錄
time:'',//发布时间
imgList:[],//图片数组
imgUrl: getApp().globalData.imgUrl,
},
/**
* 生命周期函数--监听页面加载
*/
onLoad(options) {
const data= JSON.parse(decodeURIComponent(options.detailData))
this.setData({
detailData:data,
imgList:data.attachments,
time:moment(data.publishTime).format('YYYY年MM月DD日'),
})
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady() {
},
/**
* 生命周期函数--监听页面显示
*/
onShow() {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide() {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload() {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh() {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom() {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage() {
}
})

6
weapp/package/advisoryNotice/detail/detail.json

@ -0,0 +1,6 @@
{
"navigationBarBackgroundColor": "#1979ff",
"navigationBarTextStyle": "white",
"navigationBarTitleText": "资讯公告明细",
"enablePullDownRefresh": false
}

11
weapp/package/advisoryNotice/detail/detail.wxml

@ -0,0 +1,11 @@
<!--package/advisoryNotice/detail/detail.wxml-->
<view class="card">
<view style="text-align: center;margin-bottom:20rpx">{{detailData.title}}</view>
<view>{{detailData.content}}</view>
<view style="position: absolute; right: 0; margin-top: 20rpx; margin-right:20rpx ;">发布时间:{{time}}</view>
<view wx:for="{{imgList}}" wx:for-item="img" wx:key="*this" >
<image class="img" src="{{imgUrl+img}}" mode="aspectFit" />
</view>
</view>

16
weapp/package/advisoryNotice/detail/detail.wxss

@ -0,0 +1,16 @@
/* package/advisoryNotice/detail/detail.wxss */
.card {
background-color: #fff;
border: 1px solid #ddd;
border-radius: 8px;
padding: 20rpx;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
margin: 20rpx;
position: relative;
}
/* .img {
width: 100px;
height: 100px;
margin-right: 10px;
} */

6
weapp/package/polling/inspectionRecordDetail/inspectionRecordDetail.js

@ -47,6 +47,9 @@ Page({
* 生命周期函数--监听页面加载
*/
onLoad(options) {
wx.showLoading({
title: '加载中'
})
const that = this;
const data = JSON.parse(decodeURIComponent(options.data))
const priorToV1_1 = moment(data.inspectionTime).isBefore(moment('2023-10-18'))
@ -58,7 +61,10 @@ Page({
dataList: data,
priorToV1_1,
nextMultiActiveValues,
},()=>{
wx.hideLoading()
})
},
/**

41
weapp/package/riskManagement/riskCalendar/riskCalendar.js

@ -11,22 +11,42 @@ Page({
show: false,
level: ['全部', '轻微', '中度', '严重'],
curLevel: '全部',
minDate: moment().startOf('day').subtract(6, 'days').valueOf(),
maxDate: moment().endOf('day').valueOf(),
curDate: moment().format('YYYY-MM-DD'),
minDate: moment().startOf('month').valueOf(),
maxDate: moment().endOf('month').valueOf(),
curDate: moment().format('YYYY-MM'),
showList: [],
formatter(day) { return day; },
datePickerShow:false,
datePickerMin:1640966400000,//2022-01-01 00:00:00
end:moment().endOf('month').valueOf()
},
dayData: [], // 每天的异常数据
onDateSelect(e) {
this.setData({ curDate: moment(e.detail).format('YYYY-MM-DD') })
this.setData({ curDate: moment(e.detail).format('YYYY-MM') })
this.calcShowList(this.data.curLevel, moment(e.detail).format('YYYY-MM-DD'))
},
onDateChange(e){
// this.queryData(e.detail,)
const begin=e.detail
const end =moment(e.detail).endOf('month').valueOf()
this.queryData(begin,end)
this.setData({curDate:moment(e.detail).format('YYYY-MM'),
end:end,minDate:begin
})
},
showPopup() {
this.setData({ show: true })
},
closeDatePickerPopup(){
this.setData({datePickerShow:false})
},
datePickerPopup() {
this.setData({
datePickerShow: true
})
},
onCancel() {
this.setData({ show: false })
@ -63,9 +83,13 @@ Page({
*/
onLoad(options) {
const { minDate, maxDate } = this.data;
this.queryData(minDate,maxDate)
},
queryData(minDate,maxDate){
Request.get(getPatrolRecord('all', moment(minDate).format('YYYY-MM-DD HH:mm:ss'), moment(maxDate).format('YYYY-MM-DD HH:mm:ss'), true, 'null',{home:false})).then(res => {
let dayData = new Array(7)
for (let i = 6; i >= 0; i--) {
const daysInMonth = moment(maxDate).daysInMonth();
let dayData = new Array(daysInMonth)
for (let i = daysInMonth-1; i >= 0; i--) {
const month = moment().subtract(i, 'day').month();
const date = moment().subtract(i, 'day').date();
let data = [];
@ -91,7 +115,7 @@ Page({
})
}
})
dayData[6 - i] = { month, date, formatDate: moment().subtract(i, 'day').format('YYYY-MM-DD'), data }
dayData[ daysInMonth- i-1] = { month, date, formatDate: moment().subtract(i, 'day').format('YYYY-MM-DD'), data }
}
const formatter = (day) => {
const month = day.date.getMonth();
@ -103,12 +127,11 @@ Page({
})
return day;
}
this.setData({ formatter });
this.setData({ formatter, datePickerShow:false });
this.dayData = dayData;
this.calcShowList();
})
},
/**
* 生命周期函数--监听页面初次渲染完成
*/

5
weapp/package/riskManagement/riskCalendar/riskCalendar.json

@ -6,6 +6,9 @@
"usingComponents": {
"van-calendar": "@vant/weapp/calendar/index",
"van-picker": "@vant/weapp/picker/index",
"van-popup": "@vant/weapp/popup/index"
"van-popup": "@vant/weapp/popup/index",
"van-icon": "@vant/weapp/icon/index",
"van-datetime-picker": "@vant/weapp/datetime-picker/index"
}
}

17
weapp/package/riskManagement/riskCalendar/riskCalendar.wxml

@ -6,8 +6,21 @@
<image class="card-icon" src="/images/calendar_icon.png" />
<view class="title">巡检日历</view>
</view>
<view class="card-right">{{curDate}}</view>
<image src="/images/calendar_card_bg.png" class="card-bg" />
<view style="z-index: 1;" bindtap="datePickerPopup" class="date">
<view class="card-right">{{curDate}}
<van-icon name="arrow-down" style="float:right;position:relative; top:4px" />
</view>
</view>
<van-popup show="{{ datePickerShow }}" position="bottom" custom-style="height: 50%;" bind:close="closeDatePickerPopup">
<view style="display:flex;justify-content: space-between;padding:24rpx;font-size:larger;border-bottom:1px solid #f5f5f5">
<!-- <view bindtap="closeDatePickerPopup" data-option='cancel'>取消</view>
<view style="color:#07c160;" data-option='confirmed' bindtap="closeDatePickerPopup">
确定
</view> -->
</view>
<van-datetime-picker type="year-month" max-date="{{maxDate}}" min-date="{{ datePickerMin }}" bind:confirm="onDateChange" show-toolbar="{{true}}" />
</van-popup>
</view>
<view class="calendar-box">
<van-calendar
@ -17,7 +30,7 @@
poppable="{{ false }}"
show-confirm="{{ false }}"
min-date="{{ minDate }}"
max-date="{{ maxDate }}"
max-date="{{ end }}"
formatter="{{ formatter }}"
bind:select="onDateSelect"
row-height="48"

5
weapp/package/riskManagement/riskCalendar/riskCalendar.wxss

@ -26,7 +26,12 @@
width: 115px;
height: 67px;
}
.date{
position: absolute;
top: 20px;
right: 1px;
}
.card-left {
margin-left: 23px;
font-weight: 500;

72
weapp/package/troubleshooting/index.js

@ -13,6 +13,7 @@ Page({
data: {
userInfo: wx.getStorageSync("userInfo"),
//
isEdit:false,//管理端控制不可编辑
dataList: [],
currentTab: 0,
// 筛选选择
@ -23,6 +24,8 @@ Page({
// 时间筛选
startTime: '',
endTime: '',
doneLength:0,
willLength:0,
//
timeSelectedUnrealFlag: true,
powerCheckDetail: false
@ -45,9 +48,10 @@ Page({
getData (params) {
Request.get(getPatrolRecordIssueHandle(), {
...params,
...params,type:'haveDone'
}).then(res => {
this.setData({
doneLength:res.length,
dataList: res.map(r => {
return {
...r,
@ -56,6 +60,22 @@ Page({
})
})
})
Request.get(getPatrolRecordIssueHandle(), {
...params,type:'backlog'
}).then(res => {
this.setData({
willLength:res.length,
dataList: res.map(r => {
return {
...r,
createTime: r.createTime ? moment(r.createTime).format('YYYY-MM-DD HH:mm:ss') : '--'
}
})
})
})
},
// 筛选选择
@ -148,8 +168,8 @@ Page({
onDropDownClose () {
const { currentTab, startTime, endTime, pointList, structResult } = this.data
this.getData({
type: currentTab === 0 ? 'backlog' : 'haveDone',
let params={
// type: currentTab === 0 ? 'backlog' : 'haveDone',
startTime,
endTime,
pointId: pointList.length ? (() => {
@ -164,7 +184,9 @@ Page({
}
return sendPointId.join(',')
})() : structResult.length ? '-1' : ''
})
}
this.getData(params)
// this.getCount(params)
},
// 页面跳转
@ -174,12 +196,46 @@ Page({
url: '/package/troubleshooting/shootingForm/index?shootingid=' + shootingid + '&tabIndex=' + this.data.currentTab,
})
},
//求未办和已办数量
// getCount(data){
// Request.get(getPatrolRecordIssueHandle(), {...data,type: 'haveDone'}).then(res=>{
// console.log('res',res)
// if(res.length){
// this.setData({
// doneLength:res.length
// })
// }else{
// this.setData({
// doneLength:0
// })
// }
// })
// Request.get(getPatrolRecordIssueHandle(), {...data,type: 'backlog'}).then(res=>{
// if(res.length){
// this.setData({
// willLength:res.length
// })
// }else{
// this.setData({
// willLength:0
// })
// }
// })
// },
/**
* 生命周期函数--监听页面加载
*/
onLoad (options) {
// this.getCount()
const userInfo = wx.getStorageSync('userInfo');
let bool=false
console.log('userInfo',userInfo)
if(userInfo?.role.includes('管理')){
bool=true
}
this.setData({
isEdit:bool
})
},
/**
@ -198,9 +254,7 @@ Page({
structList: res
})
})
this.getData({
type: this.data.currentTab === 0 ? 'backlog' : 'haveDone'
});
this.getData({ })
setTimeout(() => {
this.setData({
timeSelectedUnrealFlag: false

6
weapp/package/troubleshooting/index.wxml

@ -2,8 +2,8 @@
<view class="page">
<!-- 顶部tab切换 -->
<van-tabs active="{{ currentTab }}" bind:change="clickTab" color="#006BE3">
<van-tab title="待办事项"></van-tab>
<van-tab title="已办事项"></van-tab>
<van-tab title="待办事项({{willLength}})"></van-tab>
<van-tab title="已办事项({{doneLength}})"></van-tab>
</van-tabs>
<view>
<van-dropdown-menu>
@ -61,7 +61,7 @@
<text class="text-key">任务下发时间:</text><text class="text-value">{{item.createTime}}</text>
</view>
<view class="divider"></view>
<van-button class="btn" wx:if="{{powerCheckDetail || currentTab == 0}}" size="small" type="info" round bind:tap="toShootingForm" data-shootingid="{{item.id}}">
<van-button disabled="{{isEdit}}" class="btn" wx:if="{{powerCheckDetail || currentTab == 0}}" size="small" type="info" round bind:click="toShootingForm" data-shootingid="{{item.id}}">
{{
currentTab == 0?
item.state == 1 ?'制定计划':

14
weapp/pages/home/home.js

@ -1,5 +1,5 @@
// pages/home/home.js
import { getPatrolRecord } from "../../utils/getApiUrl";
import { getPatrolRecord,getAdvisoryNotices } from "../../utils/getApiUrl";
import { Request } from "../../common";
const moment = require("../../utils/moment");
@ -29,6 +29,8 @@ Page({
markers: [],
pageHeight:0,//屏幕高度
isShowCallout: false,
advisoryNoticeList:[],//咨询公告
time:'',//最新公告时间
itemList:[
{
picPath:'/images/gas.png',
@ -72,7 +74,12 @@ Page({
}
],
},
//跳转资讯公告页
toDetail(){
wx.navigateTo({
url: '/package/advisoryNotice/advisoryNotice',
})
},
/**
* 生命周期函数--监听页面加载
*/
@ -97,6 +104,7 @@ Page({
wx.showLoading({ title: '加载中' })
const date1 = new Date('1970-01-01 00:00:00');
promiseArr.push(Request.get(getPatrolRecord('all', moment(date1).format('YYYY-MM-DD') + ' 00:00:00', moment('2099-12-31').format('YYYY-MM-DD') + ' 23:59:59', 'null', 'null',{home:true})));
promiseArr.push(Request.get(getAdvisoryNotices({home:true})))
Promise.all(promiseArr).then(res => {
wx.hideLoading()
//与自己相关的所有巡检记录
@ -114,6 +122,8 @@ Page({
}
)||[]
that.setData({
advisoryNoticeList:res[1].rows,
time:moment(res[1].rows[0].publishTime).format('YYYY年MM月DD日'),
allCount:list.length || 0,
allQuestionCount:list?.filter(i=>i.patrolRecordIssueHandles.length>0)?.length || 0,
allHandleCount:list?.filter(i => i?.patrolRecordIssueHandles[0]?.yanshoushijian && parseInt(moment(i?.patrolRecordIssueHandles[0]?.yanshoushijian).format('YYYYMMDD')) === parseInt(moment().format('YYYYMMDD'))).length || 0,

10
weapp/pages/home/home.wxml

@ -12,6 +12,16 @@
</block>
</swiper>
</view>
<!-- 重要资讯 -->
<view style="display: flex;align-items: center;">
<view> <view style="width: 100px;height:100px"><image src="../../images/importantNews.png" style="width: 100%;height:100%" mode="aspectFill" /></view></view>
<view class="ellipsis">{{advisoryNoticeList[0].content}}</view>
</view>
<!-- 时间和更多 -->
<view style="display: flex;justify-content: space-between;margin-top: 5px;">
<view style="margin-left: 100PX;font-size: 12px;">{{time}}</view>
<view><a style="color: blue;font-size: 12px;" bindtap="toDetail">更多</a></view>
</view>
<!--子系统列表-->
<view class="list card" style="display: flex; flex-wrap: wrap;">
<view style="min-width: 25%; margin: 10px 0px;text-align: center;" wx:for="{{itemList}}" wx:for-item="item" wx:key="*this" data-key="{{item.itemName}}" bindtap="jumpToSubSystem">

9
weapp/pages/home/home.wxss

@ -98,3 +98,12 @@
letter-spacing: 0;
text-align: center;
}
.ellipsis {
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 4;
-webkit-box-orient: vertical;
}

7
weapp/pages/myInfo/myInfo.js

@ -16,7 +16,12 @@ Page({
url: '/package/basic/basic',
})
},
//跳转资讯公告页
toDetail(){
wx.navigateTo({
url: '/package/advisoryNotice/advisoryNotice',
})
},
// 登出
logout () {
wx.showModal({

6
weapp/pages/myInfo/myInfo.wxml

@ -38,10 +38,10 @@
</view>
<image class="right" src="/images/right.svg"></image>
</view>
<!-- <view class='body-item'>
<view class='body-info'>通知消息</view>
<view class='body-item' bindtap="toDetail">
<view class='body-info'>资讯公告</view>
<image class="right" src="/images/right.svg"></image>
</view> -->
</view>
</view>
<view class='foot-container'>
<view class='foot-item' bindtap='logout'>

7
weapp/pages/workbench/workbench.js

@ -38,8 +38,13 @@ Page({
},
{
iconPath: '/images/workbench/expert_systems.png',
text: 'AIOT总览',
text: 'AIOT运维',
page: '/package/AIOTOverview/AIOTOverview'
},
{
iconPath: '/images/workbench/issues.png',
text: '维修台账',
page: '/package/troubleshooting/index'
}
]
},

4
weapp/pages/workbench/workbench.wxml

@ -5,8 +5,8 @@
<image src="{{item.iconPath}}" class="item-img" />
<View class="item-text">{{item.text}}</View>
</view>
<view class="workbench-last" >
<!-- <view class="workbench-last" >
</view>
</view> -->
</view>
</view>

10
weapp/utils/getApiUrl.js

@ -150,4 +150,14 @@ exports.getRelationList= () => {
exports.createInvoke= () => {
return `/capabilities/invoke`
}
//获取资讯公告接口
exports.getAdvisoryNotices= (query) => {
const { home } = query;
return `/advisoryNotices/list?home=${home}`
}
exports.getNetworks= () => {
return `/network`
}

3
web/client/src/app.js

@ -11,6 +11,7 @@ import IssueHandle from './sections/issueHandle'
import Shouye from './sections/shouye';
import DeviceManage from './sections/deviceManage';
import ProjectBinding from './sections/projectBinding'
import AdvisoryNotice from './sections/advisoryNotice'
import { Func } from '$utils';
const App = props => {
const { projectName } = props
@ -22,7 +23,7 @@ const App = props => {
return (
<Layout
title={projectName}
sections={[Auth, Shouye, ProjectRegime, Safetymanage, Organization, PatrolManage, IssueHandle, DeviceManage,ProjectBinding]}
sections={[Auth, Shouye, ProjectRegime, Safetymanage, Organization, PatrolManage, IssueHandle, DeviceManage,ProjectBinding,AdvisoryNotice]}
/>
)

60
web/client/src/sections/advisoryNotice/actions/advisoryNotice.js

@ -0,0 +1,60 @@
'use strict';
import { basicAction } from '@peace/utils'
import { ApiTable } from '$utils'
export function getAdvisoryNotices(query) {
return dispatch => basicAction({
type: 'get',
dispatch: dispatch,
query,
actionType: 'GET_ADVISORY_NOTICES',
url: `${ApiTable.getAdvisoryNotices}`,
msg: { error: '获取资讯公告失败' },
reducer: { name: 'advisoryNotice'}
})
}
export function addOrUpdateAdvisoryNotice(data) {
return dispatch => basicAction({
type: 'post',
dispatch: dispatch,
data,
actionType: 'ADD_OR_UPDATE_ADVISORY_NOTICE',
url: `${ApiTable.addOrUpdateAdvisoryNotice}`,
msg: { option: data?.id?'编辑资讯公告':'新增资讯公告' },
})
}
export function delAdvisoryNotice(id) {
return dispatch => basicAction({
type: 'delete',
dispatch: dispatch,
actionType: 'DEL_ADVISORY_NOTICE',
url: ApiTable.delAdvisoryNotice.replace('{id}', id),
msg: { option: '删除资讯公告' },
})
}
export function updateAdvisoryNoticeState(id,data) {
return dispatch => basicAction({
type: 'post',
dispatch: dispatch,
data,
actionType: 'UPDATE_ADVISORY_NOTICE_STATE',
url: ApiTable.updateAdvisoryNoticeState.replace('{id}', id),
msg: { option: data?.msg?.includes('发布')?'发布资讯公告':'下架资讯公告' },
})
}
export default{
getAdvisoryNotices,
addOrUpdateAdvisoryNotice,
delAdvisoryNotice,
updateAdvisoryNoticeState
}

6
web/client/src/sections/advisoryNotice/actions/index.js

@ -0,0 +1,6 @@
'use strict';
import advisoryNotice from './advisoryNotice'
export default {
...advisoryNotice
}

108
web/client/src/sections/advisoryNotice/components/addAdvisoryNoticeModal.js

@ -0,0 +1,108 @@
import React, { useRef, useState, useEffect } from 'react'
import { Button, Form } from 'antd'
import { connect } from 'react-redux'
import { InfoCircleOutlined } from '@ant-design/icons'
import { ModalForm, ProFormSelect, ProFormText, ProFormDatePicker, ProFormTextArea,ProForm } from '@ant-design/pro-form'
import moment from 'moment'
import Uploads from '$components/Uploads'
function AddAdvisoryNoticeModal(props) {
const {
title,
triggerRender,
editData = null,
onFinish,
devices,
actions,
dispatch,
disabled,
} = props
const formItemLayout = { labelCol: { span: 6 }, wrapperCol: { span: 16 } }
const initialValues = editData ? { ...editData } : {}
const [form] = Form.useForm()
const formRef = useRef()
return (
<ModalForm
width={500}
formRef={formRef}
title={title || ''}
initialValues={initialValues}
trigger={triggerRender ? triggerRender : <Button type='primary'>{title || ''}</Button>}
layout='horizontal'
grid={true}
{...formItemLayout}
modalProps={{
destroyOnClose: true,
onCancel: () => {},
}}
onFinish={async values => {
let value = {
title: values?.title,
content: values?.content,
id: initialValues ? initialValues.id : null,
attachments:values?.attachments?.length?
values?.attachments[0]?.name ? values?.attachments.map(u => u.storageUrl) : editData?.attachments:[],
}
if(disabled){
return true
}
return onFinish && (await onFinish(value))
// return true;
}}>
<ProFormText
rules={[{ required: true, message: '资讯标题' }]}
placeholder='请输入资讯标题'
name='title'
label='资讯标题'
disabled={disabled ? true : false}
/>
<ProFormTextArea
rules={[{ required: true, message: '咨询内容' }]}
placeholder='请输入咨询内容'
name='content'
label='咨询内容'
disabled={disabled ? true : false}
/>
<div className='ant-col ant-col-xs-24'>
<Form.Item
label='文件:'
name='attachments'
// rules={[{ required: true, message: '请添加附件!' }]}
disabled={disabled ? true : false}>
<Uploads
disabled={disabled ? true : false}
listType='picture-card'
uploadType='project'
maxFilesNum={10}
maxFileSize={10}
isQiniu={true}
// disabled={true}
fileTypes={['png', 'jpg']}
defaultValue={(() => {
let nextV = []
for (let s of editData?.attachments || []) {
if (s) {
nextV.push({
storageUrl: s,
})
}
}
return nextV
})()}
/>
</Form.Item>
</div>
</ModalForm>
)
}
function mapStateToProps(state) {
const { auth, global, device } = state
return {
loading: device.isRequesting,
clientHeight: global.clientHeight,
actions: global.actions,
}
}
export default connect(mapStateToProps)(AddAdvisoryNoticeModal)

208
web/client/src/sections/advisoryNotice/containers/advisoryNotice.js

@ -0,0 +1,208 @@
import React, { useEffect, useState, useRef, useMemo } from 'react'
import { Spin, Popconfirm, message, Button, Input, Select } from 'antd'
import { connect } from 'react-redux'
import ProTable from '@ant-design/pro-table'
import moment from 'moment'
import AddAdvisoryNoticeModal from '../components/addAdvisoryNoticeModal'
function AdvisorNotice(props) {
const { loading, clientHeight, actions, dispatch } = props
const { advisorNotice } = actions
const tableRef = useRef()
const proTableFormRef = useRef()
const [tableParams, setTableParams] = useState({})
const [dataSource, setDataSource] = useState([])
const queryData = () => {
dispatch(advisorNotice.getAdvisoryNotices()).then(res => {
if (res.success) {
const list = res?.payload?.data?.rows
setDataSource(list)
}
})
}
//初始化
useEffect(() => {
queryData()
}, [])
//新增或编辑
const onFinish = async values => {
const dataToSave = { title: values?.title, content: values?.content,attachments:values?.attachments,id: values?.id }
return dispatch(advisorNotice.addOrUpdateAdvisoryNotice(dataToSave)).then(res => {
if (res.success) {
queryData()
// tableRef.current.reload()
return true
} else {
return false
}
})
}
//删除
const handleDelete = id => {
dispatch(advisorNotice.delAdvisoryNotice(id)).then(res => {
if (res.success) {
queryData()
}
})
}
//查询公告(搜索按钮)
const tableDatas = useMemo(() => {
const { title } = tableParams
let rslt = dataSource
rslt = rslt.filter(s => (title ? (s.title ? s.title === title : false) : true))
return rslt
})
//上架下架处理
const publishHandler=(record)=>{
const msg=record.state===2?'下架':'发布'
const publishTime=record.state===2?moment(record.publishTime).format('YYYY-MM-DD HH:mm:ss'):null
dispatch(advisorNotice.updateAdvisoryNoticeState(record.id,{msg,publishTime})).then(res => {
if (res.success) {
queryData()
}
})
}
const columns = [
{
title: '序号',
dataIndex: 'id',
width: '12%',
render: (text, record, index) => {
return index + 1
},
search: false,
},
{
title: '公告标题',
dataIndex: 'title',
ellipsis: true,
},
{
title: '发布时间',
dataIndex: 'publishTime',
ellipsis: true,
search: false,
render: (text, record, index) => {
return record?.publishTime?moment(record?.publishTime).format('YYYY-MM-DD HH:mm:ss'):'--'
},
},
{
title: '当前状态',
dataIndex: 'state',
ellipsis: true,
search: false,
render: (text, record, index) => {
return record?.state===1?'草稿':record?.state===2?'已发布':'已下架'
},
},
{
title: '操作',
width: 300,
key: 'option',
valueType: 'option',
render: (text, record) => {
const options = []
options.push(
<AddAdvisoryNoticeModal
triggerRender={<a>查看详情</a>}
editData={record}
disabled={true}
title='查看详情'
onFinish={onFinish}
key='lookModel'
/>
)
options.push(
<a onClick={()=>{publishHandler(record)}}>{record?.state===2?'下架':'发布'}</a>
)
record.state ===1||record.state ===3? options.push(
<AddAdvisoryNoticeModal
triggerRender={<a>编辑</a>}
editData={record}
title='编辑资讯'
onFinish={onFinish}
key='editModel'
/>
):''
record.state ===1||record.state ===3?options.push(
<Popconfirm
key='del'
placement='top'
title='是否确认删除资讯?'
onConfirm={() => handleDelete(record.id)}
okText='是'
cancelText='否'>
<a style={{color:'red'}}>删除</a>
</Popconfirm>
):''
return options
},
},
]
return (
<Spin spinning={loading}>
<div id='patrol-record' className='global-main'>
{/* <Spin spinning={loading}> */}
<div style={{ marginBottom: 19 }}>
<div className='top' style={{ marginBottom: 19 }}>
<div className='title'>
<span className='line'></span>
<span className='cn'>咨讯公告</span>
<span className='en'>&nbsp;ADVISORYNOTICE</span>
</div>
<div></div>
</div>
</div>
<AddAdvisoryNoticeModal
triggerRender={<Button type='primary'>新增</Button>}
title='新增资讯'
onFinish={onFinish}
key='addModel'
/>
<ProTable
formRef={proTableFormRef}
rowKey='id'
options={false}
request={async params => {
setTableParams(params)
return {
data: [],
success: true,
}
}}
actionRef={tableRef}
columns={columns}
pagination={{ pageSize: 10, size: 'default', className: 'global-pagination' }}
dataSource={tableDatas || []}
// search={{
// labelWidth: 100,
// }}
// search={{
// optionRender: ({searchText, resetText}, {form}, dom) => [
// <Button type="primary" onClick={searchHandler}>查询</Button>,
// ]
// }}
></ProTable>
{/* </Spin> */}
</div>
</Spin>
)
}
function mapStateToProps(state) {
const { auth, global, advisoryNotice } = state
return {
loading: advisoryNotice.isRequesting,
clientHeight: global.clientHeight,
actions: global.actions,
}
}
export default connect(mapStateToProps)(AdvisorNotice)

5
web/client/src/sections/advisoryNotice/containers/index.js

@ -0,0 +1,5 @@
'use strict';
import AdvisoryNotice from './advisoryNotice'
export { AdvisoryNotice }

0
web/client/src/sections/advisoryNotice/containers/style.less

15
web/client/src/sections/advisoryNotice/index.js

@ -0,0 +1,15 @@
'use strict';
import reducers from './reducers';
import routes from './routes';
import actions from './actions';
import { getNavItem } from './nav-item';
export default {
key: 'advisorNotice',
name: '资讯广告',
reducers: reducers,
routes: routes,
actions: actions,
getNavItem: getNavItem
};

14
web/client/src/sections/advisoryNotice/nav-item.js

@ -0,0 +1,14 @@
import React from 'react';
import { Link } from 'react-router-dom';
import { Menu } from 'antd';
import { HomeOutlined } from '@ant-design/icons';
import { Func } from '$utils';
const SubMenu = Menu.SubMenu;
export function getNavItem (user, dispatch) {
return <Menu.Item key="advisoryNotice" icon={<img src='/assets/images/menu/home.svg' style={{ width: 24, height: 24 }} />}>
<Link to="/advisoryNotice">咨讯公告</Link>
</Menu.Item>
}

5
web/client/src/sections/advisoryNotice/reducers/index.js

@ -0,0 +1,5 @@
'use strict';
export default {
}

12
web/client/src/sections/advisoryNotice/routes.js

@ -0,0 +1,12 @@
'use strict';
import { AdvisoryNotice } from './containers';
export default [{
type: 'inner',
route: {
path: '/advisoryNotice',
key: 'advisoryNotice',
breadcrumb: '咨询公告',
component: AdvisoryNotice,
}
}];

3
web/client/src/sections/deviceManage/actions/index.js

@ -1,7 +1,8 @@
'use strict';
import * as device from './device'
import * as network from './network'
export default {
...device
...device,...network
}

50
web/client/src/sections/deviceManage/actions/network.js

@ -0,0 +1,50 @@
'use strict';
import { basicAction } from '@peace/utils'
import { ApiTable } from '$utils'
export function getNetworks(query) {
return dispatch => basicAction({
type: 'get',
dispatch: dispatch,
query,
actionType: 'GET_NETWORKS',
url: `${ApiTable.getNetworks}`,
msg: { error: '获取宽带专网失败' },
reducer: { name: 'networks'}
})
}
export function addOrUpdateNetwork(data) {
return dispatch => basicAction({
type: 'post',
dispatch: dispatch,
data,
actionType: 'ADD_OR_UPDATE_NETWORK',
url: `${ApiTable.addOrUpdateNetwork}`,
msg: { option: data?.id?'编辑宽带专网':'新增宽带专网' },
})
}
export function delNetwork(id) {
return dispatch => basicAction({
type: 'delete',
dispatch: dispatch,
actionType: 'DEL_NETWORK',
url: ApiTable.delNetwork.replace('{id}', id),
msg: { option: '删除宽带专网' },
})
}
export default{
getNetworks,
addOrUpdateNetwork,
delNetwork,
}

103
web/client/src/sections/deviceManage/components/addNetworkModal.js

@ -0,0 +1,103 @@
import React, { useRef, useState, useEffect } from 'react'
import { Button, Form } from 'antd'
import { connect } from 'react-redux'
import { InfoCircleOutlined } from '@ant-design/icons'
import { ModalForm, ProFormSelect, ProFormText, ProFormDatePicker, ProFormTextArea,ProForm, ProFormTimePicker } from '@ant-design/pro-form'
import moment from 'moment'
function addNetworkModal(props) {
const {
title,
structureListOpt,
triggerRender,
editData = null,
onFinish,
devices,
actions,
dispatch,
type
} = props
const formItemLayout = { labelCol: { span: 6 }, wrapperCol: { span: 16 } }
const initialValues = editData ? { ...editData } : {}
const [form] = Form.useForm()
const formRef = useRef()
return (
<ModalForm
width={500}
formRef={formRef}
title={title || ''}
initialValues={initialValues}
trigger={triggerRender ? triggerRender : <Button type='primary'>{title || ''}</Button>}
layout='horizontal'
grid={true}
{...formItemLayout}
modalProps={{
destroyOnClose: true,
onCancel: () => {},
}}
onFinish={async values => {
console.log('x111',values)
let value = {
name: values?.name,
type:values?.type,
account:values?.account,
indate: values?.indate,
id: initialValues ? initialValues.id : null,
projectId:values?.projectId
}
return onFinish && (await onFinish(value))
// return true;
}}>
<ProFormText
rules={[{ required: true, message: '请输入专网名称' }]}
placeholder='请输入专网名称'
name='name'
label='专网名称'
/>
<ProFormSelect
rules={[{ required: true, message: '请选择专网类型' }]}
placeholder='请选择专网类型'
options={type?.map(s => {
return { label: s.label, value: s.id }
})}
name='type'
label='专网类型'
/>
<ProFormText
rules={[{ required: true, message: '请输入账号' }]}
placeholder='请输入账号'
name='account'
label='账号'
/>
<ProFormDatePicker
rules={[{ required: true, message: '请输入有效期' }]}
placeholder='请输入有效期'
name='indate'
label='有效期'
/>
<ProFormSelect
showSearch
allowClear
rules={[{ required: true, message: '请选择结构物' }]}
placeholder='请选择结构物'
options={structureListOpt?.map(s => {
return { label: s.label, value: s.id }
})}
name='projectId'
label='关联结构物'
/>
</ModalForm>
)
}
function mapStateToProps(state) {
const { auth, global } = state
return {
clientHeight: global.clientHeight,
actions: global.actions,
}
}
export default connect(mapStateToProps)(addNetworkModal)

4
web/client/src/sections/deviceManage/containers/index.js

@ -1,5 +1,5 @@
'use strict';
import DeviceManage from './deviceManage'
export { DeviceManage };
import Network from './network'
export { DeviceManage,Network};

213
web/client/src/sections/deviceManage/containers/network.js

@ -0,0 +1,213 @@
import React, { useEffect, useState, useRef, useMemo } from 'react'
import { Spin, Popconfirm, message, Button, Input, Select } from 'antd'
import { connect } from 'react-redux'
import ProTable from '@ant-design/pro-table'
import moment from 'moment'
import AddNetworkModal from '../components/addNetworkModal';
const type=[{id:1,label:'专网'},{id:2,label:'公网'}]
function Network(props) {
const { loading, clientHeight, actions, dispatch, } = props
const { deviceManage,projectRegime} = actions
const tableRef = useRef()
const proTableFormRef = useRef()
const [tableParams, setTableParams] = useState({})
const [dataSource, setDataSource] = useState([])
const [structureListOpt, setStructureListOpt] = useState([])//巡检结构物
const queryData = () => {
dispatch(deviceManage.getNetworks()).then(res => {
if (res.success) {
const list = res?.payload?.data?.rows
setDataSource(list)
}
})
}
//初始化
useEffect(() => {
dispatch(projectRegime.getProjectList()).then(res => {
if (res.success) {
const dp = res.payload.data?.rows?.map(item => {
return {
label: item?.name,
id: item?.id,
}
})
setStructureListOpt(dp)
}
})
queryData()
}, [])
//新增或编辑
const onFinish = async values => {
const dataToSave = {
name: values?.name,
type:values?.type,
account:values?.account,
indate: values?.indate,
id: values.id ,
projectId:values?.projectId
}
return dispatch(deviceManage.addOrUpdateNetwork(dataToSave)).then(res => {
if (res.success) {
queryData()
// tableRef.current.reload()
return true
} else {
return false
}
})
}
//删除
const handleDelete = id => {
dispatch(deviceManage.delNetwork(id)).then(res => {
if (res.success) {
queryData()
}
})
}
//查询宽带名字(搜索按钮)
const tableDatas = useMemo(() => {
const { name } = tableParams
let rslt = dataSource
rslt = rslt.filter(s => (name ? (s.name ? s.name.includes(name) : false) : true))
return rslt
})
const columns = [
{
title: '专网名称',
dataIndex: 'name',
ellipsis: true,
},
{
title: '专网类型',
dataIndex: 'type',
ellipsis: true,
search: false,
valueEnum: type.reduce((enumObj, { id, label }) => {
enumObj[id] = { text: label };
return enumObj;
}, {}),
},
{
title: '账号',
dataIndex: 'account',
ellipsis: true,
search: false,
},
{
title: '有效期',
dataIndex: 'indate',
ellipsis: true,
search: false,
render: (text, record, index) => {
return record?.indate?moment(record?.indate).format('YYYY-MM-DD'):'--'
},
},
{
title: '关联结构物',
dataIndex: 'projectId',
ellipsis: true,
search: false,
valueEnum: structureListOpt.reduce((enumObj, { id, label }) => {
enumObj[id] = { text: label };
return enumObj;
}, {}),
},
{
title: '操作',
width: 300,
key: 'option',
valueType: 'option',
render: (text, record) => {
const options = []
options
.push( <AddNetworkModal
type={type}
structureListOpt={structureListOpt}
triggerRender={<a>编辑</a>}
editData={record}
title='编辑宽带专网'
onFinish={onFinish}
key='editModel'
/>
)
options.push(
<Popconfirm
key='del'
placement='top'
title='是否确认删除宽带专网?'
onConfirm={() => handleDelete(record.id)}
okText='是'
cancelText='否'>
<a style={{ color: 'red' }}>删除</a>
</Popconfirm>
)
return options
},
},
]
return (
<Spin spinning={loading}>
<div id='patrol-record' className='global-main'>
{/* <Spin spinning={loading}> */}
<div style={{ marginBottom: 19 }}>
<div className='top' style={{ marginBottom: 19 }}>
<div className='title'>
<span className='line'></span>
<span className='cn'>宽带专网</span>
<span className='en'>&nbsp;NETWORK</span>
</div>
<div></div>
</div>
</div>
<AddNetworkModal
type={type}
structureListOpt={structureListOpt}
triggerRender={<Button type='primary'>新增</Button>}
title='新增宽带宽带'
onFinish={onFinish}
key='addModel'
/>
<ProTable
formRef={proTableFormRef}
rowKey='id'
options={false}
request={async params => {
setTableParams(params)
return {
data: [],
success: true,
}
}}
actionRef={tableRef}
columns={columns}
pagination={{ pageSize: 10, size: 'default', className: 'global-pagination' }}
dataSource={tableDatas || []}
></ProTable>
{/* </Spin> */}
</div>
</Spin>
)
}
function mapStateToProps(state) {
const { auth, global, networks } = state
return {
loading: networks.isRequesting,
clientHeight: global.clientHeight,
actions: global.actions,
}
}
export default connect(mapStateToProps)(Network)

17
web/client/src/sections/deviceManage/nav-item.js

@ -2,12 +2,21 @@ import React from 'react';
import { Link } from 'react-router-dom';
import { Menu } from 'antd';
import { Func } from '$utils';
const SubMenu = Menu.SubMenu;
export function getNavItem(user, dispatch) {
return (
<Menu.Item icon={<img src='/assets/images/menu/device.png' style={{ width: 24, height: 24 }} />}
key="deviceManage">
<Link to="/deviceManage">设备管理</Link>
<SubMenu key="deviceManage" icon={<img src='/assets/images/menu/device.png' style={{ width: 24, height: 24 }} />} title={'设备管理'}>
<Menu.Item
// icon={<img src='/assets/images/menu/device.png' style={{ width: 24, height: 24 }} />}
key="deviceCheck">
<Link to="/deviceManage/deviceCheck">设备查看</Link>
</Menu.Item>
<Menu.Item
// icon={<img src='/assets/images/menu/device.png' style={{ width: 24, height: 24 }} />}
key="network">
<Link to="/deviceManage/network">宽带专网</Link>
</Menu.Item>
</SubMenu>
);
}

17
web/client/src/sections/deviceManage/routes.js

@ -1,13 +1,24 @@
'use strict';
import { DeviceManage } from './containers';
import { DeviceManage,Network } from './containers';
export default [{
type: 'inner',
route: {
path: '/deviceManage',
key: 'deviceManage',
breadcrumb: '设备管理',
breadcrumb: '巡检管理',
childRoutes: [{
path: '/deviceCheck',
key: 'deviceCheck',
component: DeviceManage,
breadcrumb: '设备查看',
},
{
path: '/netWork',
key: 'netWork',
component: Network,
breadcrumb: '宽带专网',
}
]
}
}];

12
web/client/src/utils/webapi.js

@ -159,8 +159,16 @@ export const ApiTable = {
delRelation:'anxinyun/project/relation/{id}',
getRelation:'anxinyun/project/relation/list',
//资讯公告
getAdvisoryNotices:'advisoryNotices/list',
addOrUpdateAdvisoryNotice:'advisoryNotices/addOrUpdate',
delAdvisoryNotice:'advisoryNotices/{id}',
updateAdvisoryNoticeState:'updateAdvisoryNotices/{id}',
//宽带专网
getNetworks:'network',
addOrUpdateNetwork:'network',
delNetwork:'network/{id}',
};
export const RouteTable = {

Loading…
Cancel
Save