如何用App实现巡检业务数字化?以YonBuilder移动开发平台APICloud为例

本文涉及的产品
mPaaS订阅基础套餐,标准版 3个月
文档翻译,文档翻译 1千页
文本翻译,文本翻译 100万字符
简介: 一款消防检查app可以有效减少繁复工作、提升巡检效率。本文将详细介绍如何使用YonBuilder移动开发平台开发消防检查助手app。

巡检是企事业单位的常见场景之一,以消防检查为例,秋冬季节气温下降、生产繁忙,用火、用电、用气情况大量增加,消防安全事件多发,一款消防检查app可以有效减少繁复工作、提升巡检效率。本文将详细介绍如何使用YonBuilder移动开发平台开发消防检查助手app。

一、功能介绍

把消防检查过程中,需要手写填报的文档,在app端以表单填写进行实现;同时可以添加手写签名、关联照片,而且app端表单填报项目可进行下拉选择,极大提高了工作效率;表单填报完成之后可通过系统后台生成word模板文件,app端下载到手机,通过手机连接打印机,可打印纸质文件。App开发采用AVM框架,后台采用PHP。

功能要点:

1、场所登记,分为九小场所和合用场所登记;

2、监督检查记录;

3、责令整改通知书;

4、基本情况拍照,检查过程记录拍照;

5、后台针对上述数据进行多维度分析,导出Excel表格、Word模板文件。

二、思维导图



编辑切换为居中

添加图片注释,不超过 140 字(可选)


三、用到的模块



编辑切换为居中

添加图片注释,不超过 140 字(可选)


四、项目目录



编辑

添加图片注释,不超过 140 字(可选)


五、开发介绍

1、首页导航

系统首页使用tabLayout,可以将相关参数配置在JSON文件中,再在config.xml中将content的值设置成该JSON文件的路径。如果底部导航没有特殊需求这里强烈建议大家使用tabLayout为app进行布局,官方已经将各类手机屏幕及不同的分辨率进行了适配,免去了很多关于适配方面的问题。



编辑切换为居中

添加图片注释,不超过 140 字(可选)


{

"name": "root",

"textOffset": 6,

"color": "#999999",

"selectedColor": "#004494",

"scrollEnabled": false,

"hideNavigationBar": false,

"bgColor": "#fff",

"navigationBar": {

"background": "./images/navbk.png",

"shadow": "rgba(0,0,0,0)",

"color": "#fff",

"fontSize": 18,

"hideBackButton": true

},

"tabBar": {

"background": "#fff",

"shadow": "#eee",

"color": "#5E5E5E",

"selectedColor": "#004494",

"textOffset": 3,

"fontSize": 11,

"scrollEnabled": true,

"index": 0,

"preload": 1,

"frames": [

{

"title": "首页",

"name": "home",

"url": "./pages/index/home"

},

{

"title": "历史记录",

"name": "course",

"url": "./pages/history/records"

},

{

"title": "我的",

"name": "user",

"url": "./pages/user/wode"

}

],

"list": [

{

"text": "首页",

"iconPath": "./images/home.png",

"selectedIconPath": "./images/home-o.png"

},

{

"text": "历史记录",

"iconPath": "./images/his.png",

"selectedIconPath": "./images/his-o.png"

},

{

"text": "我的",

"iconPath": "./images/my.png",

"selectedIconPath": "./images/my-o.png"

}

]

}

}

由于导航使用的tablayout,所有app初始化需要执行的操作,只需要在第一个加载的页面执行即可全局响应。可通过 tabBar中的"index"字段来确定第一个需要加载的页面,通过"preload"来确定需要预加载几个页面。

2、动态权限

动态权限的获取在第一个初始化的页面执行即可。本项目中需要用到存储、相机、相册3个权限。用到的是官方的API方法hasPermission。



编辑切换为居中

添加图片注释,不超过 140 字(可选)


//提示获取存储权限

var limits=[];

var resultList = api.hasPermission({

list: ['storage','camera','photos']

});

if (resultList[0].granted) {

// 已授权,可以继续下一步操作

} else {

limits.push(resultList[0].name);

}

if (resultList[1].granted) {

// 已授权,可以继续下一步操作

} else {

limits.push(resultList[1].name);

}

if (resultList[2].granted) {

// 已授权,可以继续下一步操作

} else {

limits.push(resultList[2].name);

}

if(limits.length>0){

api.requestPermission({

list: limits,

}, function(res) {

// console.log(JSON.stringify(res));

});

}

manifest.xml文件,关于targetSdkVersion的值的大小,这里可以根据下文图片中的说明,结合项目需要上架的平台自行设置。



编辑

添加图片注释,不超过 140 字(可选)




编辑切换为居中

添加图片注释,不超过 140 字(可选)




编辑切换为居中

添加图片注释,不超过 140 字(可选)


<?xml version="1.0" encoding="UTF-8"?>

<manifest>

<application name="targetSdkVersion" value="28"/>

</manifest>

3、消息事件

本项目中通过发送事件sendEvent和监听事件addEventListener,消息事件要学会合理运用来提升app中各个页面之间交互的体验。下面对实现在表单提交成功之后刷新列表页、登陆成功之后跳转页面时重新加载用户信息的具体操作进行说明。

表单数据提交成功之后,在回调里发送事件"addbase",然后关闭页面,跳转至列表页,在列表页的apiready中监听“addbase”事件,在监听成功回调中执行刷新列表的操作。

onsubmit(e){

let result = e.detail.value;


this.data.dwmc = result.dwmc?result.dwmc:this.data.dwmc;

this.data.dwdz = result.dwdz?result.dwdz:this.data.dwdz;

//省略其他字段

let params = {

data:{

values:{

secret: Config.secret,

userid: api.getPrefs({sync: true,key: 'userid'}),

partid: api.getPrefs({sync: true,key: 'partid'}),

id:this.data.id,

dwmc:this.data.dwmc,

dwdz:this.data.dwdz,

//省略

}

}

}

api.showProgress();

Model.addbase(params, (res,err) => {

// console.log(JSON.stringify(res));

// console.log(JSON.stringify(err));

if (res && res.flag == 'Success') {

api.toast({

msg:'登记成功'

});

api.sendEvent({

name: 'addbase',

});

api.closeWin();

} else {

api.toast({

msg:res.msg

})

}

api.hideProgress();

});

},

apiready(){

this.data.tab=api.pageParam.tab;

this.data.tabtitle=api.pageParam.tabtitle;

this.data.refresherTriggered = true;

this.loadData(false);

api.addEventListener({

name: 'setuserinfo'

}, (ret, err) => {

this.loadData(false);

});

//监听增加修改基本信息

api.addEventListener({

name: 'addbase'

}, (ret, err) => {

this.loadData(false);

});

api.addEventListener({

name: 'delbase'

}, (ret, err) => {

this.loadData(false);

});

},

4、接口调用

将接口调用和接口配置分别封装2个JS插件,model.js和config.js。统一管理,避免了在每个页面进行接口调用时都重复写一遍代码,有效简化了每个功能页面的代码量,只需要在回调里专注写自己的业务逻辑即可。

import $util from "../../utils/util.js"

import {Model} from "../../utils/model.js"

import {Config} from "../../utils/config.js"

config.js


class Config{

constructor(){}

}


Config.restUrl = 'http://xiaofang.*******.cn/api.php/Home/Index';

Config.secret = '99d0fd93-***************************';


Config.addbase ='/addbase';//登记基本信息表

Config.querylist ='/querylist';//查询登记单位列表

Config.querybasebyid ='/querybasebyid';//查询登记单位基本信息详情

Config.querybaseinfobyid ='/querybaseinfobyid';//查询登记单位基本信息详情

Config.exportbase ='/exportbase';//下载登记单位基本信息

Config.deletebasebyid ='/deletebasebyid';//删除登记单位基本信息

Config.login ='/login';//登陆

Config.getpart ='/getpart';//获取单位列表

Config.register ='/register';//用户注册

/**省略**/

Config.checkUserStatus ='/checkUserStatus';//获取用户状态


export {Config};

model.js

import {Config} from './config.js';


class Model {

constructor() {}

}


/*登记基本信息表 */

Model.addbase = function (param, callback){

param.url = Config.addbase;

param.method = 'post';

this.request(param, callback);

}


/*查询登记单位列表 */

Model.querylist = function (param, callback){

param.url = Config.querylist;

param.method = 'post';

this.request(param, callback);

}


/*查询登记单位基本信息详情 */

Model.querybasebyid = function (param, callback){

param.url = Config.querybasebyid;

param.method = 'post';

this.request(param, callback);

}


/*查询登记单位基本信息详情 */

Model.querybaseinfobyid = function (param, callback){

param.url = Config.querybaseinfobyid;

param.method = 'post';

this.request(param, callback);

}


/*下载登记单位基本信息 */

Model.exportbase = function (param, callback){

param.url = Config.exportbase;

param.method = 'post';

this.request(param, callback);

}


/*删除登记单位基本信息 */

Model.deletebasebyid = function (param, callback){

param.url = Config.deletebasebyid;

param.method = 'post';

this.request(param, callback);

}


/*登陆模块 */

Model.login = function (param, callback){

param.url = Config.login;

param.method = 'post';

this.request(param, callback);

}


/**省略**/


/*获取用户状态 */

Model.checkUserStatus = function (param, callback){

param.url = Config.checkUserStatus;

param.method = 'post';

this.request(param, callback);

}


Model.request = function(p, callback) {

var param = p;

if (!param.headers) {

param.headers = {};

}


if (param.data && param.data.body) {

param.headers['Content-Type'] = 'application/json; charset=utf-8';

}

if (param.url) {

param.url = Config.restUrl + param.url;

}


api.ajax(param, function(ret, err) {

callback && callback(ret, err);

});

}


export {Model};

5、数据列表及分页查询

数据列表的展示,采用scroll-view标签,通过onrefresherrefresh,onrefresherrefresh触发的事件中进行数据列表的刷新和分页查询。通过refresher-triggered这个属性来设置当前下拉刷新状态,true 表示下拉刷新已经被触发,false 表示下拉刷新未被触发。如果想默认下拉刷新一下可以在apiready中将之设置为true,以此来代替执行数据刷新操作。

如果列表中的每一项的元素较少,而且没有样式的特殊要求,也可以使用list-view来实现。

下面是单位列表的完整页面代码。其他页面的列表基本功能都是一致的,只是在每一项的样式及参数个数上存在差异。

<template name='unitlist'>

<view class="page">

<scroll-view class="main" scroll-y enable-back-to-top refresher-enabled refresher-triggered={refresherTriggered} onrefresherrefresh={this.onrefresherrefresh} onscrolltolower={this.onscrolltolower}>

<view class="search-box">

<input class="serach-input" placeholder="请输入单位名称检索" confirm-type="search" onconfirm="onconfirm" oninput={this.getKey}/>

<text class="search-btn" onclick="onconfirm">搜索</text>

</view>

<view class="item-box">

<view class="item" data-id={item.id} onclick={this.openTable} v-for="(item, index) in list">

<text class="item-content">{{item.name}}</text>

<view class="item-sub">

<view class="item-sub-box">

<image class="item-sub-ico" src="../../images/DW.png" mode="aspectFit"></image>

<text class="item-info">{{item.address}}</text>

</view>

<view class="item-sub-box">

<image class="item-sub-ico" src="../../images/CT.png" mode="aspectFit"></image>

<text class="item-info">{{item.type}}</text>

</view>

</view>

</view>

</view>

<view class="footer">

<text class="loadDesc">{loadStateDesc}</text>

</view>

</scroll-view>

</view>

</template>

<script>

import {Model} from '../../utils/model.js'

import {Config} from "../../utils/config.js"

import $util from "../../utils/util.js"

export default {

name: 'unitlist',

data() {

return{

list:[],

skip: 0,

loading: false,

refresherTriggered: false,

haveMoreData: true,

tab:'',

tabtitle:'',

key:''

}

},

computed: {

loadStateDesc(){

if (this.data.loading || this.data.haveMoreData) {

return '加载中...';

} else if (this.list.length > 0) {

return '没有更多啦';

} else {

return '暂时没有内容';

}

}

},

methods: {

apiready(){

this.data.tab=api.pageParam.tab;

this.data.tabtitle=api.pageParam.tabtitle;

this.data.refresherTriggered = true;

this.loadData(false);

api.addEventListener({

name: 'setuserinfo'

}, (ret, err) => {

this.loadData(false);

});

//监听增加修改基本信息

api.addEventListener({

name: 'addbase'

}, (ret, err) => {

this.loadData(false);

});

api.addEventListener({

name: 'delbase'

}, (ret, err) => {

this.loadData(false);

});

},

loadData(loadMore) {

this.data.loading = true;

var that = this;

var limit = 20;

var skip = loadMore?that.data.skip+1:0;

let params = {

data:{

values:{

secret: Config.secret,

userid: api.getPrefs({sync: true,key: 'userid'}),

roleid: api.getPrefs({sync: true,key: 'roleid'}),

partid: api.getPrefs({sync: true,key: 'partid'}),

skip: skip,

limit: limit,

key:this.data.key

}

}

}

api.showProgress();

Model.querylist(params, (res,err) => {

// console.log(JSON.stringify(res));

// console.log(JSON.stringify(err));

if (res && res.flag == 'Success') {

let lists = res.data;

that.data.haveMoreData = lists.length == limit;

if (loadMore) {

that.data.list = that.data.list.concat(lists);

} else {

that.data.list = lists;

}

that.data.skip = skip;

} else {

that.data.haveMoreData = false;

}

that.data.loading = false;

that.data.refresherTriggered = false;

api.hideProgress();

});

},

//打开填写表格

openTable(e) {

var id = e.currentTarget.dataset.id;

$util.openWin({

name: this.data.tab,

url: '../index/'+this.data.tab+'.stml',

title: this.data.tabtitle,

pageParam:{

id:id

}

});

},

/*下拉刷新页面*/

onrefresherrefresh(){

this.data.refresherTriggered = true;

this.loadData(false);

},

onscrolltolower() {

if (this.data.haveMoreData) {

this.loadData(true);

}

},

getKey(e){

this.data.key = e.detail.value;

},

onconfirm(){

this.loadData(false);

}

}

}

</script>

<style>

.main {

height: 100%;

background-color: #eaf0fa;

}

.item-box{

background-color: #fff;

margin: 5px;

}

.item{

border-bottom: 1px solid #efefef;

margin: 0 10px;

justify-content:flex-start;

flex-direction:column;

}

.item-content{

font-size: 17PX;

margin-top: 10px;

}

.item-info{

font-size: 13PX;

color: #666;

margin: 10px 0;

}

.item-sub{

justify-content:space-between;

flex-direction:row;

}

.footer {

height: 44px;

justify-content: center;

align-items: center;

}

.loadDesc {

width: 200px;

text-align: center;

}

.item-sub-ico{

width: 15px;

margin: 10px 0;

}

.item-sub-box{

flex-flow: row nowrap;

}

.search-box{

flex-flow: row nowrap;

align-items: center;

background-color: #2c6ddc;

border-radius: 5px;

margin: 5px;

}

.serach-input{

padding: 5px;

width: 80%;

height: 50px;

border-top-left-radius: 5px;

border-bottom-left-radius: 5px;

}

.search-btn{

width: 20%;

text-align: center;

color: #ffffff;

}

</style>

6、双击退出程序

在首页页面和登陆页面中,添加双击退出程序功能,避免出现单击退出键出现不必要的页面跳转失误。此监听事件要在apiready中执行。

//监听返回 双击退出程序

api.setPrefs({

key: 'time_last',

value: '0'

});

api.addEventListener({

name : 'keyback'

}, function(ret, err) {

var time_last = api.getPrefs({sync: true,key: 'time_last'});

var time_now = Date.parse(new Date());

if (time_now - time_last > 2000) {

api.setPrefs({key:'time_last',value:time_now});

api.toast({

msg : '再按一次退出APP',

duration : 2000,

location : 'bottom'

});

} else {

api.closeWidget({

silent : true

});

}

});

7、账号有效性确认

由于后台针对用户账号,启用了停用功能,后台一旦设置账号停用,app中也应相应地将用户进行退出系统操作。此操作在首页的apiready中进行执行。

isLogin(){

if(!api.getPrefs({sync: true,key:'userid'})){

$util.openWin({

name: 'login',

url: '../user/login.stml',

title: '',

hideNavigationBar:true

});

}

else{

let params = {

data:{

values:{

secret: Config.secret,

userid: api.getPrefs({sync: true,key:'userid'})

}

}

}

api.showProgress();

Model.checkUserStatus(params, (res,err) => {

// console.log(JSON.stringify(res));

// console.log(JSON.stringify(err));

if (res && res.flag == 'Success') {

if(ret.data=='02'){

//清楚缓存用户数据

api.removePrefs({

key: 'name'

});

api.removePrefs({

key: 'userid'

});

api.removePrefs({

key: 'partname'

});

api.removePrefs({

key: 'partid'

});

api.removePrefs({

key: 'role'

});

api.removePrefs({

key: 'rolename'

});

api.removePrefs({

key: 'username'

});

//用户已停用 退出系统

$util.openWin({

name: 'login',

url: '../user/login.stml',

title: '',

hideNavigationBar:true

});

}

} else {

//清除用户信息

api.removePrefs({

key: 'name'

});

api.removePrefs({

key: 'userid'

});

api.removePrefs({

key: 'partname'

});

api.removePrefs({

key: 'partid'

});

api.removePrefs({

key: 'role'

});

api.removePrefs({

key: 'rolename'

});

api.removePrefs({

key: 'username'

});

//用户异常 退出重新登陆

$util.openWin({

name: 'login',

url: '../user/login.stml',

title: '',

hideNavigationBar:true

});

}

api.hideProgress();

});

}

}

8、表单提交、回显

表单使用的是AVM的 from组件,通过onsubmit进行表单数据提交。其中主要用到了input、textarea、radio、checkbox;每个控件的具体使用方法,在官方文档中否有详细的介绍。下面就具体的代码示例进行展示。



编辑切换为居中

添加图片注释,不超过 140 字(可选)


页面代码

<template name='addbase'>

<scroll-view class="page" scroll-y>

<form onsubmit={this.onsubmit}>

<view class="item">

<text>单位名称:</text>

<input name="dwmc" value={this.data.dwmc} placeholder="请输入单位名称"/>

</view>

<view class="item">

<text>单位地址:</text>

<input name="dwdz" value={this.data.dwdz} placeholder="请输入单位详细地址"/>

</view>

<checkbox-group class="item" name="dwlb">

<text>单位类别:</text>

<view class="item-checkbox">

<label v-for="item in dwlbarr">

<checkbox value={item} v-bind:checked="this.data.seldwlb.indexOf(item)!=-1?true:false"/>

<text>{item}</text>

</label>

</view>

<input name="dwlb_qt" value={this.data.dwlb_qt} placeholder="请输入单位类别"/>

</checkbox-group>

<checkbox-group class="item" name="dwxz">

<text>单位性质:</text>

<view class="item-checkbox">

<label v-for="item in dwxzarr">

<checkbox value={item} v-bind:checked="this.data.seldwxz.indexOf(item)!=-1?true:false"/>

<text>{item}</text>

</label>

</view>

</checkbox-group>

<view class="item">

<text>职工总数:</text>

<input name="zgzs" value={this.data.zgzs} keyboard-type="number" placeholder="请输入单位职工总数"/>

</view>

<view class="item">

<text>消防安全责任人:</text>

<input name="xfaqzrr_xm" value={this.data.xfaqzrr_xm} placeholder="请输入负责人姓名"/>

<input name="xfaqzrr_zw" value={this.data.xfaqzrr_zw} placeholder="请输入负责人职务"/>

<input name="xfaqzrr_dh" value={this.data.xfaqzrr_dh} keyboard-type="number" placeholder="请输入负责人电话"/>

</view>

<view class="item">

<text>消防安全管理人:</text>

<input name="xfaqglr_xm" value={this.data.xfaqglr_xm} placeholder="请输入管理人姓名"/>

<input name="xfaqglr_zw" value={this.data.xfaqglr_zw} placeholder="请输入管理人职务"/>

<input name="xfaqglr_dh" value={this.data.xfaqglr_dh} keyboard-type="number" placeholder="请输入管理人电话"/>

</view>

<view class="item">

<text>专兼职防火干部:</text>

<input name="zjzfhgb_xm" value={this.data.zjzfhgb_xm} placeholder="请输入专兼职防火干部姓名"/>

<input name="zjzfhgb_zw" value={this.data.zjzfhgb_zw} placeholder="请输入专兼职防火干部职务"/>

<input name="zjzfhgb_dh" value={this.data.zjzfhgb_dh} keyboard-type="number" placeholder="请输入专兼职防火干部电话"/>

</view>

<view class="item">

<label class="label-box">

<text class="label-title">建筑层数(层)</text>

<input class="label-input" name="jzcs" value={this.data.jzcs} keyboard-type="number" placeholder="请输入建筑层数(层)"/>

</label>

<label class="label-box">

<text class="label-title">所在层数(层)</text>

<input class="label-input" name="szcs" value={this.data.szcs} keyboard-type="number" placeholder="请输入所在层数(层)"/>

</label>

<label class="label-box">

<text class="label-title">建筑高度(m)</text>

<input class="label-input" name="jzgd" value={this.data.jzgd} keyboard-type="number" placeholder="请输入建筑高度(m)"/>

</label>

<label class="label-box">

<text class="label-title">总建筑面积(㎡)</text>

<input class="label-input" name="zjzmj" value={this.data.zjzmj} keyboard-type="decimal" placeholder="请输入总建筑面积(㎡)"/>

</label>

<label class="label-box">

<text class="label-title">每层建筑面积(㎡)</text>

<input class="label-input" name="mcjzmj" value={this.data.mcjzmj} keyboard-type="decimal" placeholder="请输入每层建筑面积(㎡)"/>

</label>

<label class="label-box">

<text class="label-title">营业面积(㎡)</text>

<input class="label-input" name="yymj" value={this.data.yymj} keyboard-type="decimal" placeholder="请输入营业面积(㎡)"/>

</label>

<label class="label-box">

<text class="label-title">检查时间</text>

<input class="label-input" name="jcsj" value={this.data.jcsj} keyboard-type="number" placeholder="请输入检查时间"/>

</label>

<label class="label-box">

<text class="label-title">投入使用时间</text>

<input class="label-input" name="trsysj" value={this.data.trsysj} keyboard-type="number" placeholder="请输入投入使用时间"/>

</label>

<label class="label-box">

<text class="label-title">开业时间</text>

<input class="label-input" name="kysj" value={this.data.kysj} keyboard-type="number" placeholder="请输入开业时间"/>

</label>

<label class="label-box">

<text class="label-title">租赁房屋户主姓名</text>

<input class="label-input" name="zlfwhzxm" value={this.data.zlfwhzxm} placeholder="请输入租赁房屋户主姓名"/>

</label>

</view>

<view class="item">

<text>生产经营状况:</text>

<input name="scjyzk" value={this.data.scjyzk} placeholder="请输入单位生产经营状况"/>

</view>

<view class="item">

<text>隶属社区:</text>

<input name="lssq" value={this.data.lssq} placeholder="请输入单位隶属社区"/>

</view>

<radio-group class="item" name="ssyjfl">

<text>三色预警分类:</text>

<view class="item-checkbox">

<label v-for="item in ssyjflarr">

<radio value={item} v-bind:checked="this.data.ssyjfl==item?true:false"/>

<text>{item}</text>

</label>

</view>

</radio-group>

<view class="item">

<text>消防设置种类及数量:</text>

<textarea name="xfsszljsl" value={this.data.xfsszljsl} placeholder="请输入消防设置种类及数量"/>

</view>

<view class="item">

<text>检查登记情况:</text>

<textarea name="jcqkdj_1" value={this.data.jcqkdj_1} placeholder="请输入检查登记情况"/>

<textarea name="jcqkdj_2" value={this.data.jcqkdj_2} placeholder="请输入检查登记情况"/>

<textarea name="jcqkdj_3" value={this.data.jcqkdj_3} placeholder="请输入检查登记情况"/>

<textarea name="jcqkdj_4" value={this.data.jcqkdj_4} placeholder="请输入检查登记情况"/>

</view>

<view class="item">

<text>填表说明:</text>

</view>

<button class="btn-submit" type="submit">提交</button>

</form>

<button v-show="isdelete" class="btn-delete" type="button" @click="delbase">删除</button>

</scroll-view>

</template>

表单提交

data() {

return{

dwmc:'',

dwdz:'',

dwlb:'',

dwxz:'',

zgzs:0,

xfaqzrr_xm:'',

xfaqzrr_zw:'',

xfaqzrr_dh:'',

xfaqglr_xm:'',

xfaqglr_zw:'',

xfaqglr_dh:'',

zjzfhgb_xm:'',

zjzfhgb_zw:'',

zjzfhgb_dh:'',

jzcs:null,

jzgd:null,

zjzmj:null,

mcjzmj:null,

szcs:null,

yymj:null,

jcsj:'',

trsysj:'',

kysj:'',

zlfwhzxm:'',

scjyzk:'',

lssq:'',

ssyjfl:'',

xfsszljsl:'',

jcqkdj_1:'',

jcqkdj_2:'',

jcqkdj_3:'',

jcqkdj_4:'',

dwlb_qt:'',

id:0,

ssyjflarr:['红','黄','绿'],

dwlbarr:['购物场所','餐饮场所','住宿场所','公共娱乐场所','休闲健身场所','医疗场所','教学场所','生产加工企业','易燃易爆危险品销售、储存场所','其他'],

dwxzarr:['国有','集体','股份合作公司','股份有限公司','港澳台投资','中外合资','个体私营','其他'],

seldwlb:[],

seldwxz:[],

isdelete:false,

dateList: [$formatDate.lastYear30(),[1,2,3,4,5,6,7,8,9,10,11,12],[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31]],

jcsjSelectorValue:[0,0,0],

trsysjSelectorValue:[0,0,0],

kysjSelectorValue:[0,0,0]

}

},

数据回显

//查询已添加的数据

loadData(){

let params = {

data:{

values:{

secret: Config.secret,

id:this.data.id

}

}

}

api.showProgress();

Model.querybasebyid(params, (res,err) => {

// console.log(JSON.stringify(res));

// console.log(JSON.stringify(err));

if (res && res.flag == 'Success') {

//填充数据

let result=res.data;


this.data.dwmc = result.dwmc?result.dwmc:this.data.dwmc;

this.data.dwdz = result.dwdz?result.dwdz:this.data.dwdz;

this.data.seldwlb = result.dwlb?result.dwlb.split(','):this.data.dwlb;

this.data.dwlb_qt = result.dwlb_qt?result.dwlb_qt:this.data.dwlb_qt;

this.data.seldwxz = result.dwxz?result.dwxz.split(','):this.data.dwxz;

this.data.zgzs = result.zgzs?result.zgzs:this.data.zgzs;

this.data.xfaqzrr_xm = result.xfaqzrr_xm?result.xfaqzrr_xm:this.data.xfaqzrr_xm;

this.data.xfaqzrr_zw = result.xfaqzrr_zw?result.xfaqzrr_zw:this.data.xfaqzrr_zw;

this.data.xfaqzrr_dh = result.xfaqzrr_dh?result.xfaqzrr_dh:this.data.xfaqzrr_dh;

this.data.xfaqglr_xm = result.xfaqglr_xm?result.xfaqglr_xm:this.data.xfaqglr_xm;

this.data.xfaqglr_zw = result.xfaqglr_zw?result.xfaqglr_zw:this.data.xfaqglr_zw;

this.data.xfaqglr_dh = result.xfaqglr_dh?result.xfaqglr_dh:this.data.xfaqglr_dh;

this.data.zjzfhgb_xm = result.zjzfhgb_xm?result.zjzfhgb_xm:this.data.zjzfhgb_xm;

this.data.zjzfhgb_zw = result.zjzfhgb_zw?result.zjzfhgb_zw:this.data.zjzfhgb_zw;

this.data.zjzfhgb_dh = result.zjzfhgb_dh?result.zjzfhgb_dh:this.data.zjzfhgb_dh;

this.data.jzcs = result.jzcs?result.jzcs:this.data.jzcs;

this.data.jzgd = result.jzgd?result.jzgd:this.data.jzgd;

this.data.zjzmj = result.zjzmj?result.zjzmj:this.data.zjzmj;

this.data.mcjzmj = result.mcjzmj?result.mcjzmj:this.data.mcjzmj;

this.data.szcs = result.szcs?result.szcs:this.data.szcs;

this.data.yymj = result.yymj?result.yymj:this.data.yymj;

this.data.jcsj = result.jcsj?result.jcsj:this.data.jcsj;

this.data.trsysj = result.trsysj?result.trsysj:this.data.trsysj;

this.data.kysj = result.kysj?result.kysj:this.data.kysj;

this.data.zlfwhzxm = result.zlfwhzxm?result.zlfwhzxm:this.data.zlfwhzxm;

this.data.scjyzk = result.scjyzk?result.scjyzk:this.data.scjyzk;

this.data.lssq = result.lssq?result.lssq:this.data.lssq;

this.data.ssyjfl = result.ssyjfl?result.ssyjfl:this.data.ssyjfl;

this.data.xfsszljsl = result.xfsszljsl?result.xfsszljsl:this.data.xfsszljsl;

this.data.jcqkdj_1 = result.jcqkdj_1?result.jcqkdj_1:this.data.jcqkdj_1;

this.data.jcqkdj_2 = result.jcqkdj_1?result.jcqkdj_2:this.data.jcqkdj_2;

this.data.jcqkdj_3 = result.jcqkdj_1?result.jcqkdj_3:this.data.jcqkdj_3;

this.data.jcqkdj_4 = result.jcqkdj_1?result.jcqkdj_4:this.data.jcqkdj_4;


} else {

api.toast({

msg:res.msg

})

}

api.hideProgress();

});

},

9、拍照及上传照片,图片预览

拍照使用的是FNPhotograph模块,自带UI的open接口,可选择拍摄照片的质量,可配置使用摄像头方向,同时可配置照片不用存储到相册中、禁用显示相册按钮,保证用户只能现场拍照,可以满足项目需求。



图片上传失败

重试


项目中很多页面涉及到图片预览功能,分为单图预览和多图预览。图片预览采用的是photoBrowser模块。photoBrowser是一个图片浏览器,支持单张、多张图片查看的功能,可放大缩小图片,支持本地和网络图片资源。若是网络图片资源则会被缓存到本地,缓存到本地上的资源可以通过clearCache接口手动清除。同时本模块支持横竖屏显示,在本app支持横竖屏的情况下,本模块底层会自动监听当前设备的位置状态,自动适配横竖屏以展示图片。



编辑切换为居中

添加图片注释,不超过 140 字(可选)


getPicture(e){

this.data.type = e.currentTarget.dataset.type;

api.actionSheet({

title: '请选择',

cancelTitle: '取消',

buttons: ['选择图片','图片预览']

}, (ret, err)=> {

// console.log(JSON.stringify(ret));

// console.log(JSON.stringify(err));

// var index = ret.buttonIndex;

if(ret.buttonIndex==1){

var FNPhotograph = api.require('FNPhotograph');

FNPhotograph.open({

album: true ,

quality: 'medium'

}, (ret)=>{

// console.log(JSON.stringify(ret));

if(ret.eventType=='takePhoto'){

FNPhotograph.close();

//上传图片

let params = {

data:{

values:{

secret: Config.secret,

baseid:this.data.baseid,

type:this.data.type

},

files:{

'file':ret.imagePath,

}

}

}

api.showProgress();

Model.addbasepicbyid(params, (res,err) => {

// console.log(JSON.stringify(res));

// console.log(JSON.stringify(err));

if (res && res.flag == 'Success') {

if(this.data.type=='01'){

this.data.src1=res.data;

}

else if(this.data.type=='02'){

this.data.src2=res.data;

}

else if(this.data.type=='03'){

this.data.src3=res.data;

}

else if(this.data.type=='04'){

this.data.src4=res.data;

}

} else {

api.toast({

msg:res.msg

})

}

api.hideProgress();

});

}

});

}

else if(ret.buttonIndex==2){

//图片预览

let src='';

if(this.data.type=='01'){

src=this.data.src1;

}

else if(this.data.type=='02'){

src=this.data.src2;

}

else if(this.data.type=='03'){

src=this.data.src3;

}

else if(this.data.type=='04'){

src=this.data.src4;

}

var photoBrowser = api.require('photoBrowser');

photoBrowser.open({

images: [

src

],

placeholderImg: 'widget://res/img/apicloud.png',

bgColor: '#000'

}, (ret, err) => {

if (ret) {

if(ret.eventType=='click'){

photoBrowser.close();

}

} else {

api.toast({

msg:'图片预览失败'

})

}

});

}

});

}

10、页面之间的跳转和参数传递

封装工具类until.js,在其中定义了openWin方法来实现页面之间的跳转。页面跳转时参数的传递通过pageParam添加参数进行,在跳转到的页面通过api.pageParam.xxx在apiready中进行接收。

<view class="tab-item" data-url="addbase" data-title="九小场所登记" tapmode @click="openPage">

<image class="tab-item-logo" src="../../images/JB.png" mode="scaleToFill"></image>

<text class="tab-item-title"> 九小场所登记</text>

</view>

methods: {

apiready(){//like created

this.data.id=api.pageParam.id;

},

openPage(e){

let title = e.currentTarget.dataset.title;

let url = e.currentTarget.dataset.url;

$util.openWin({

name: url,

url: '../index/'+url+'.stml',

title: title,

pageParam:{

id:this.data.id

}

});

}

}

util.js

const $util = {

openWin(param){

var param = {

name: param.name,

url: param.url,

title: param.title||'',

pageParam: param.pageParam||{},

hideNavigationBar: param.hideNavigationBar || false,

navigationBar:{

background:'../../images/navbk.png',

shadow: '#fff',

color: '#fff'

}

};

if (this.isApp()) {

api.openTabLayout(param);

} else {

api.openWin(param);

}

},

isApp(){

if (api.platform && api.platform == 'app') {

return true;

}

return false;

},

fitRichText(richtext, width){

var str = `<img style="max-width:${width}px;"`;

var result = richtext.replace(/\<img/gi, str);

return result;

}

}

export default $util;

11、导航栏自定义按钮点击事件

如果是首页加载的页面,可以在首页中通过索引index进行判断然后分别配置;如果在单独的页面中需要添加的话,可在页面的apiready中进行配置。



编辑切换为居中

添加图片注释,不超过 140 字(可选)


首页中的配置,需要注意的是,如果是页面直接跳转,配置多个页面时没有问题;但如果按钮事件是执行某个页面具体的方法时,就会出现问题。这里建议如果按钮事件是执行某个页面具体的方法,不要在首页中配置,可在页面中通过其他方式进行实现。因为首页配置的内容会在全局使用,而且加载成功之后,通过tabbar切换页面的时候,是不会进行页面刷新操作的。

apiready() {

//导航设置

api.addEventListener({

name:'tabitembtn'

}, (ret) => {

api.setTabBarAttr({

index: ret.index

});

if(ret.index==0){

api.setTabLayoutAttr({

hideNavigationBar:true,

animated:false

});

}

else if(ret.index==2){

api.setNavBarAttr({

rightButtons: [{

iconPath:'widget://image/chart.png'

}]

});

api.setTabLayoutAttr({

hideNavigationBar:false,

animated:false

});

api.addEventListener({

name:'navitembtn'

}, (ret)=>{

if(ret.type=='right'){

$util.openWin({

name: 'chart',

url: 'widget://html/test.html',

title: '统计分析',

pageParam:{


}

})

}

})

}

else{

api.setTabLayoutAttr({

hideNavigationBar:false,

animated:false

});

api.setNavBarAttr({

rightButtons: [{

}]

});

api.addEventListener({

name:'navitembtn'

}, (ret)=>{


})

}

});

},

单独页面中的配置

apiready(){

//添加右上角按钮

api.setNavBarAttr({

rightButtons: [{

text: '添加'

}]

});

//监听右上角按钮点击事件

api.addEventListener({

name: 'navitembtn'

}, (ret, err)=> {

if (ret.type == 'right') {

$util.openWin({

name: 'addjcpics',

url: 'addjcpics.stml',

title: '添加检查记录照片',

pageParam:{

baseid:this.data.baseid

}

});

}

});

},

12、手写签名

手写签名用到的是drawingBoard模块。开发者可自定义固定宽高(w、h)的 “frame”,该“frame”即是可手写签名的背景透明的画板,可将此画板固定在指定的 frame 或 window 上,从而自定义出符合自己需求的各种UI效果的签名功能。



编辑切换为居中

添加图片注释,不超过 140 字(可选)


<template name='signature'>

<view class="page">

<view class="flowbottom">

<button class="btn-clear" tapmode @click="clear">重写</button>

<button class="btn" tapmode @click="submit" disabled={this.data.btn_disabled}>确定</button>

</view>

</view>

</template>

<script>

export default {

name: 'signature',

data() {

return{

btn_disabled:false,

type:''

}

},

methods: {

apiready(){

this.data.type = api.pageParam.type;

var drawingBoard = api.require('drawingBoard');

drawingBoard.open({

rect: {

x: 10,

y: 100,

w: api.frameWidth-20,

h: (api.frameWidth-20)/2

},

styles: {

brush: {

color: '#000000',

width: 3

},

bgColor: '#f0f0f0'

},

fixedOn: api.frameName

});

},

clear(){

var drawingBoard = api.require('drawingBoard');

drawingBoard.clear();

},

submit(){

this.data.btn_disabled = true;

var drawingBoard = api.require('drawingBoard');

drawingBoard.save({

savePath: 'fs://drawingBoard/'+Date.now()+'.png',

copyToAlbum: false

}, (ret)=> {

// console.log(JSON.stringify(ret));

if(ret.absolutePath=='undefined'){

this.data.btn_disabled = false;

api.toast({

msg:'签名失败,请稍后再试'

});

}

else{

//

api.sendEvent({

name: 'singture_success',

extra: {

src: ret.absolutePath,

type:this.data.type

}

});

drawingBoard.close();

api.closeWin();

}

});

}

}

}

</script>

<style>

.page {

display: flex;

flex-flow: row nowrap;

height: 100%;

width: 100%;

background-color: #eaf0fa;

}

.flowbottom{

width: 100%;

align-self: flex-end;

padding: 10px;

}

.btn {

display: block;

height: 50px;

width: 100%;

background:#1492ff;

border-radius: 5px;

color: #fff;

font-size: 20px;

font-weight: bolder;

padding: 0;

margin-top: 10px;

}

.btn-clear {

display: block;

height: 50px;

width: 100%;

background:#ff0000;

border-radius: 5px;

color: #fff;

font-size: 20px;

font-weight: bolder;

padding: 0;

margin-top: 10px;

}

</style>

13、清除缓存

由于项目中有很多拍照、查看照片场景,在使用的过程中,就会产生很多的缓存,导致应用反应变慢。所以在应用中增加了清除缓存功能,用的是官方提供的api.clearCache。

在个人中心 apiready中先获取到应用中的缓存,然后点击清除缓存按钮即可清除。

<view class="item" onclick="clearCache">

<image class="item-icon" src="../../images/w_02.png" mode="widthFix"></image>

<text class="item-title">缓存</text>

<text class="item-right-cache">{cache}M</text>

</view>

apiready(){

//获取APP缓存 异步返回结果:

api.getCacheSize((ret) => {

this.data.cache = parseInt(ret.size/1024/1024).toFixed(1);

});

},

clearCache(){

api.clearCache(() => {

api.toast({

msg: '清除完成'

});

});

this.data.cache=0;

},

14、下载并打开word文件

点击下载word文件按钮,调用系统接口,接口会把文件的路径进行返回,先通过api.download将文件下载到本地,然后通过模块docInteraction调用第三方app打开文档。



编辑切换为居中

添加图片注释,不超过 140 字(可选)


//监听右上角按钮点击事件

api.addEventListener({

name: 'navitembtn'

}, (ret, err) => {

if (ret.type == 'right') {

let params = {

data:{

values:{

secret: Config.secret,

id:this.data.id

}

}

}

api.showProgress();

Model.exportbase(params, (res,err) => {

if (res && res.flag == 'Success') {

//下载文件

api.download({

url: res.data,

report: true,

cache: false,

allowResume: true

}, (ret, err)=> {

// console.log(JSON.stringify(ret));

if (ret.state == 1) {

//下载成功 跳转WORD预览页面

var docInteraction =

api.require('docInteraction');

docInteraction.open({

path: ret.savePath

}, (ret, err) => {

});

} else {

if(ret.percent>0){

api.toast({

msg:'正在下载'+ret.percent+'%'

})

}

else{

api.toast({

msg:'下载失败,请稍后再试'

})

}

}

});

} else {

api.toast({

msg:'下载失败,请稍后再试'

})

}

api.hideProgress();

});

}

});

15、登录、退出

通过api.setPrefs存储用户登录信息,退出登录清空数据。

//登陆APP

submit() {

var that = this;

var user = that.data.user;

var psw = that.data.psw;

if (!user) {

this.showToast("姓名不能为空");

return;

}

if (!psw) {

this.showToast("密码不能为空");

return;

}


api.showProgress();

const params = {

data: {

values:{

secret: Config.secret,

user:user,

psw:psw

}

}

};

Model.login(params, (res,err) => {

// console.log(JSON.stringify(res));

// console.log(JSON.stringify(err));

if (res && res.flag == "Success") {

that.showToast("提交成功");

api.setPrefs({key:'name',value:res.data.name});

api.setPrefs({key:'userid',value:res.data.id});

api.setPrefs({key:'roleid',value:res.data.role});

api.setPrefs({key:'rolename',value:res.data.rolename});

api.setPrefs({key:'partid',value:res.data.part});

api.setPrefs({key:'partname',value:res.data.partname});

api.setPrefs({key:'username',value:res.data.username});


api.toast({

msg:'登陆成功,欢迎使用'

})


api.sendEvent({

name: 'setuserinfo',

});

api.closeWin();

} else {

that.showToast('登陆失败,请稍后再试');

}

api.hideProgress();

});

},

api.setPrefs设置偏好数据,数据会存储到本地文件系统。api.removePrefs清除本地存储的数据。

loginout(){

api.confirm({

title: '提示',

msg: '确定要退出登录?',

buttons: ['确定', '取消']

}, (ret, err) => {

var index = ret.buttonIndex;

if(index == 1){

//清除用户信息

api.removePrefs({

key: 'name'

});

api.removePrefs({

key: 'userid'

});

api.removePrefs({

key: 'partname'

});

api.removePrefs({

key: 'partid'

});

api.removePrefs({

key: 'role'

});

api.removePrefs({

key: 'rolename'

});

api.removePrefs({

key: 'username'

});


api.toast({

msg:'请重新登陆APP'

})

$util.openWin({

name: 'login',

url: '../user/login.stml',

title: '',

hideNavigationBar:true

});

}

});

}

后台接口

导出word用到了PhpWord,通过composer进行安装,然后再需要调用的地方直接调用,具体使用方法请参代码中示例;其中导出word模板文件有涉及到图片的导出。


<?php

namespace Home\Controller;

use Think\Controller;

class IndexController extends Controller {

//用户登陆

public function login(){

checkscret('secret');//验证授权码

checkdataPost('user');//用户名

checkdataPost('psw');//密码


$user=$_POST['user'];

$psw=$_POST['psw'];


$map['username']=$user;

$map['password']=$psw;


$map['status']='01';//注册之后 需要审核一下


$releaseInfo=M()->table('user')->field('id,name,username,part,role,getrolename(role) rolename,getpartname(part) partname')->where($map)->find();


if($releaseInfo){

returnApiSuccess('查询成功',$releaseInfo);

}

else{

returnApiError('查询失败!');

exit();

}


}

//用户注册

public function register(){

checkscret('secret');//验证授权码

checkdataPost('username');//用户名

checkdataPost('password');//密码


$username=$_POST['username'];

$name=$_POST['name'];

$password=$_POST['password'];

$part=$_POST['part'];


$data['username']=$username;

$data['name']=$name;

$data['password']=$password;

$data['part']=$part;

$data['role']=3;

$data['status']='02';//已注册未审核


$releaseInfo=M()->table('user')->data($data)->add();


if($releaseInfo){

returnApiSuccess('注册成功',$releaseInfo);

}

else{

returnApiError('注册失败!');

exit();

}

}


//基本信息登记

public function addbase(){

checkscret('secret');//验证授权码

checkdataPost('userid');

checkdataPost('partid');


//对应字段

$dwmc=$_POST['dwmc'];

$dwdz=$_POST['dwdz'];

$dwlb=$_POST['dwlb'];

$dwxz=$_POST['dwxz'];

$zgzs=$_POST['zgzs'];

$xfaqzrr_xm=$_POST['xfaqzrr_xm'];

$xfaqzrr_zw=$_POST['xfaqzrr_zw'];

$xfaqzrr_dh=$_POST['xfaqzrr_dh'];

$xfaqglr_xm=$_POST['xfaqglr_xm'];

$xfaqglr_zw=$_POST['xfaqglr_zw'];

$xfaqglr_dh=$_POST['xfaqglr_dh'];

$zjzfhgb_xm=$_POST['zjzfhgb_xm'];

$zjzfhgb_zw=$_POST['zjzfhgb_zw'];

$zjzfhgb_dh=$_POST['zjzfhgb_dh'];

$jzcs=$_POST['jzcs'];

$jzgd=$_POST['jzgd'];

$zjzmj=$_POST['zjzmj'];

$mcjzmj=$_POST['mcjzmj'];

$szcs=$_POST['szcs'];

$yymj=$_POST['yymj'];

$jcsj=$_POST['jcsj'];

$trsysj=$_POST['trsysj'];

$kysj=$_POST['kysj'];

$zlfwhzxm=$_POST['zlfwhzxm'];

$scjyzk=$_POST['scjyzk'];

$lssq=$_POST['lssq'];

$ssyjfl=$_POST['ssyjfl'];

$xfsszljsl=$_POST['xfsszljsl'];

$jcqkdj_1=$_POST['jcqkdj_1'];

$jcqkdj_2=$_POST['jcqkdj_2'];

$jcqkdj_3=$_POST['jcqkdj_3'];

$jcqkdj_4=$_POST['jcqkdj_4'];

$dwlb_qt=$_POST['dwlb_qt'];


$userid=$_POST['userid'];

$partid=$_POST['partid'];


$id=$_POST['id'];


//数据

$data['dwmc']=$dwmc;

$data['dwdz']=$dwdz;

$data['dwlb']=$dwlb;

$data['dwxz']=$dwxz;

$data['zgzs']=$zgzs;

$data['xfaqzrr_xm']=$xfaqzrr_xm;

$data['xfaqzrr_zw']=$xfaqzrr_zw;

$data['xfaqzrr_dh']=$xfaqzrr_dh;

$data['xfaqglr_xm']=$xfaqglr_xm;

$data['xfaqglr_zw']=$xfaqglr_zw;

$data['xfaqglr_dh']=$xfaqglr_dh;

$data['zjzfhgb_xm']=$zjzfhgb_xm;

$data['zjzfhgb_zw']=$zjzfhgb_zw;

$data['zjzfhgb_dh']=$zjzfhgb_dh;

$data['jzcs']=$jzcs;

$data['jzgd']=$jzgd;

$data['zjzmj']=$zjzmj;

$data['mcjzmj']=$mcjzmj;

$data['szcs']=$szcs;

$data['yymj']=$yymj;

$data['jcsj']=$jcsj;

$data['trsysj']=$trsysj;

$data['kysj']=$kysj;

$data['zlfwhzxm']=$zlfwhzxm;

$data['scjyzk']=$scjyzk;

$data['lssq']=$lssq;

$data['ssyjfl']=$ssyjfl;

$data['xfsszljsl']=$xfsszljsl;

$data['jcqkdj_1']=$jcqkdj_1;

$data['jcqkdj_2']=$jcqkdj_2;

$data['jcqkdj_3']=$jcqkdj_3;

$data['jcqkdj_4']=$jcqkdj_4;

$data['dwlb_qt']=$dwlb_qt;


$data['userid']=$userid;

$data['partid']=$partid;

$data['create_time']=time();


if($id){

$map['id']=$id;

//插入数据

$releaseInfo=M()->table('base')->where($map)->save($data);

}

else{

//插入数据

$releaseInfo=M()->table('base')->data($data)->add();

}


if($releaseInfo){

returnApiSuccess('登记成功',$releaseInfo);

}

else{

returnApiError( '登记失败,请稍后再试');

exit();

}

}


//删除登记信息

public function deletebasebyid(){

checkscret('secret');//验证授权码

checkdataPost('id');


$id=$_POST['id'];


$map['id']=$id;


$releaseInfo=M()->table('base')->where($map)->delete();


if($releaseInfo){

returnApiSuccess('删除成功',$releaseInfo);

}

else{

returnApiError('删除失败!');

exit();

}

}


//查询登记单位列表

public function querylist(){

checkscret('secret');//验证授权码

checkdataPost('limit');//下一次加载多少条

checkdataPost('userid');


$limit=$_POST['limit'];

$skip=$_POST['skip'];

if(empty($skip)){

$skip=0;

}


$userid=$_POST['userid'];


$map['userid']=$userid;


$releaseInfo=M()->table('base')->field('id,dwmc as name,dwdz as address,dwlb as type')->where($map)->limit($skip*$limit,$limit)->order('create_time desc')->select();


if($releaseInfo){

returnApiSuccess('查询成功',$releaseInfo);

}

else{

returnApiError('查询失败!');

exit();

}

}


//查询单位基本信息详情

public function querybasebyid(){

checkscret('secret');//验证授权码

checkdataPost('id');//ID


$id=$_POST['id'];


$map['id']=$id;


$releaseInfo=M()->table('base')->where($map)->find();


if($releaseInfo){

returnApiSuccess('查询成功',$releaseInfo);

}

else{

returnApiError('查询失败!');

exit();

}

}


//查询基本信息

public function querybaseinfobyid(){

checkscret('secret');//验证授权码

checkdataPost('id');//ID


$id=$_POST['id'];


$map['id']=$id;


$releaseInfo=M()->table('base')->field('dwmc,dwdz,dwxz,jzgd,jzcs,yymj')->where($map)->find();


if($releaseInfo){

returnApiSuccess('查询成功',$releaseInfo);

}

else{

returnApiError('查询失败!');

exit();

}

}


//导出基本信息表

public function exportbase(){

checkscret('secret');//验证授权码

checkdataPost('id');//ID


$id=$_POST['id'];


$map['id']=$id;


$data=M()->table('base')->where($map)->find();


if ($data) {

require_once "./vendor/autoload.php";

$tmp = new \PhpOffice\PhpWord\TemplateProcessor('./Public/template/temp_base.docx'); //打开模板

$tmp->setValue('dwmc', $data['dwmc']);

$tmp->setValue('dwdz', $data['dwdz']);

$tmp->setValue('dwlb', $data['dwlb']);

$tmp->setValue('dwxz', $data['dwxz']);

$tmp->setValue('zgzs', $data['zgzs']);


$tmp->setValue('xfaqzrr_xm', $data['xfaqzrr_xm']);

$tmp->setValue('xfaqzrr_zw', $data['xfaqzrr_zw']);

$tmp->setValue('xfaqzrr_dh', $data['xfaqzrr_dh']);


$tmp->setValue('xfaqglr_xm', $data['xfaqglr_xm']);

$tmp->setValue('xfaqglr_zw', $data['xfaqglr_zw']);

$tmp->setValue('xfaqglr_dh', $data['xfaqglr_dh']);


$tmp->setValue('zjzfhgb_xm', $data['zjzfhgb_xm']);

$tmp->setValue('zjzfhgb_zw', $data['zjzfhgb_zw']);

$tmp->setValue('zjzfhgb_dh', $data['zjzfhgb_dh']);


$tmp->setValue('jzcs', $data['jzcs']);

$tmp->setValue('jzgd', $data['jzgd']);

$tmp->setValue('zjzmj', $data['zjzmj']);

$tmp->setValue('mcjzmj', $data['mcjzmj']);

$tmp->setValue('kysj', $data['kysj']);

$tmp->setValue('szcs', $data['szcs']);

$tmp->setValue('yymj', $data['yymj']);

$tmp->setValue('jcsj', $data['jcsj']);

$tmp->setValue('trsysj', $data['trsysj']);

$tmp->setValue('zlfwhzxm', $data['zlfwhzxm']);

$tmp->setValue('scjyzk', $data['scjyzk']);

$tmp->setValue('lssq', $data['lssq']);

$tmp->setValue('ssyjfl', $data['ssyjfl']);

$tmp->setValue('xfsszljsl', $data['xfsszljsl']);

$tmp->setValue('jcqkdj_1', $data['jcqkdj_1']);

$tmp->setValue('jcqkdj_2', $data['jcqkdj_2']);

$tmp->setValue('jcqkdj_3', $data['jcqkdj_3']);

$tmp->setValue('jcqkdj_4', $data['jcqkdj_4']);


$tmp->setValue('dwlb_qt', $data['dwlb_qt']);


$tmp->saveAs('./Uploads/九小场所基本情况管理登记表_'.$data['dwmc'].'.docx');

returnApiSuccess('导出成功','http://xiaofang.*********.cn/Uploads/九小场所基本情况管理登记表_'.$data['dwmc'].'.docx');

}

else{

returnApiError('导出失败,请稍后再试!');

exit();

}

}


//消防安全综合治理登记

public function addxfaqzljl(){

checkscret('secret');//验证授权码

checkdataPost('userid');

checkdataPost('partid');


//对应字段

$dwmc=$_POST['dwmc'];

$jcsj=$_POST['jcsj'];

$bjccsmc=$_POST['bjccsmc'];

$bjccsdz=$_POST['bjccsdz'];

$jyz=$_POST['jyz'];

$jyzlxfs=$_POST['jyzlxfs'];

$jzlx=$_POST['jzlx'];

$sfdjjc=$_POST['sfdjjc'];

$sfkf=$_POST['sfkf'];

$djcs=$_POST['djcs'];

$jclb=$_POST['jclb'];

$ltjzcl=$_POST['ltjzcl'];

$sfzr=$_POST['sfzr'];

$jzrs=$_POST['jzrs'];

$jzcs=$_POST['jzcs'];

$zsqysfyaqck=$_POST['zsqysfyaqck'];

$zsqysfytswc=$_POST['zsqysfytswc'];

$zrxs=$_POST['zrxs'];

$hzzdbjxt=$_POST['hzzdbjxt'];

$zdpsmhxt=$_POST['zdpsmhxt'];

$snxfs=$_POST['snxfs'];

$mhq=$_POST['mhq'];

$mhqsl=$_POST['mhqsl'];

$xfssqtqk=$_POST['xfssqtqk'];

$dqxlqk=$_POST['dqxlqk'];

$ddzxcsyqk=$_POST['ddzxcsyqk'];

$sfsymhgwjrqnsbd=$_POST['sfsymhgwjrqnsbd'];

$sfcfyrybwxp=$_POST['sfcfyrybwxp'];

$yrybwxpcfsyqk=$_POST['yrybwxpcfsyqk'];

$sfdqkzxfpx=$_POST['sfdqkzxfpx'];

$ydsh=$_POST['ydsh'];

$yhjzgqk=$_POST['yhjzgqk'];


$userid=$_POST['userid'];

$partid=$_POST['partid'];


$id=$_POST['id'];

$baseid=$_POST['baseid'];


//数据

$data['dwmc']=$dwmc;

$data['jcsj']=$jcsj;

$data['bjccsmc']=$bjccsmc;

$data['bjccsdz']=$bjccsdz;

$data['jyz']=$jyz;

$data['jyzlxfs']=$jyzlxfs;

$data['jzlx']=$jzlx;

$data['sfdjjc']=$sfdjjc;

$data['sfkf']=$sfkf;

$data['djcs']=$djcs;

$data['jclb']=$jclb;

$data['ltjzcl']=$ltjzcl;

$data['sfzr']=$sfzr;

$data['jzrs']=$jzrs;

$data['jzcs']=$jzcs;

$data['zsqysfyaqck']=$zsqysfyaqck;

$data['zsqysfytswc']=$zsqysfytswc;

$data['zrxs']=$zrxs;

$data['hzzdbjxt']=$hzzdbjxt;

$data['zdpsmhxt']=$zdpsmhxt;

$data['snxfs']=$snxfs;

$data['mhq']=$mhq;

$data['mhqsl']=$mhqsl;

$data['xfssqtqk']=$xfssqtqk;

$data['dqxlqk']=$dqxlqk;

$data['ddzxcsyqk']=$ddzxcsyqk;

$data['sfsymhgwjrqnsbd']=$sfsymhgwjrqnsbd;

$data['sfcfyrybwxp']=$sfcfyrybwxp;

$data['yrybwxpcfsyqk']=$yrybwxpcfsyqk;

$data['sfdqkzxfpx']=$sfdqkzxfpx;

$data['ydsh']=$ydsh;

$data['yhjzgqk']=$yhjzgqk;


$data['baseid']=$baseid;


$data['userid']=$userid;

$data['partid']=$partid;

$data['create_time']=time();


//保存文件

$upload = new \Think\Upload(); // 实例化上传类

$upload->rootPath = './Uploads/'; // 设置附件上传根目录

$upload->saveName = array('uniqid', mt_rand(1,999999).'_'.md5(uniqid())); // 自定义图片重命名

$upload->exts = array('jpg', 'jpeg' ,'png'); // 设置附件上传类型 只允许照片

// 上传文件

$uploadinfo = $upload->upload();


if($uploadinfo){

if($uploadinfo['file1']['savepath'] && $uploadinfo['file1']['savename']){

$data['signature_check']="/Uploads/".$uploadinfo['file1']['savepath'].$uploadinfo['file1']['savename'];

}

if($uploadinfo['file2']['savepath'] && $uploadinfo['file2']['savename']){

$data['signature_bcheck']="/Uploads/".$uploadinfo['file2']['savepath'].$uploadinfo['file2']['savename'];

}

}


if($id){

$map['id']=$id;

//插入数据

$releaseInfo=M()->table('zhzljl')->where($map)->save($data);

}

else{

//插入数据

$releaseInfo=M()->table('zhzljl')->data($data)->add();

}


if($releaseInfo){

returnApiSuccess('登记成功',$releaseInfo);

}

else{

returnApiError( '登记失败,请稍后再试');

exit();

}

}


//查询综合检查记录

public function queryxfaqzljlyid(){

checkscret('secret');//验证授权码

checkdataPost('baseid');


$baseid=$_POST['baseid'];


$map['baseid']=$baseid;


$releaseInfo=M()->table('zhzljl')->where($map)->find();


if($releaseInfo){

returnApiSuccess('查询成功',$releaseInfo);

}

else{

returnApiError( '查询失败,请稍后再试');

exit();

}

}


//导出

public function exportxfaqzljl(){

checkscret('secret');//验证授权码

checkdataPost('id');//ID


$id=$_POST['id'];


$map['id']=$id;


$data=M()->table('xf_zhzljl')->where($map)->find();


if ($data) {

require_once "./vendor/autoload.php";

$tmp = new \PhpOffice\PhpWord\TemplateProcessor('./Public/template/temp_zljl.docx'); //打开模板

$tmp->setValue('dwmc', $data['dwmc']);

$tmp->setValue('jcsj', $data['jcsj']);

$tmp->setValue('bjccsmc', $data['bjccsmc']);

$tmp->setValue('bjccsdz', $data['bjccsdz']);

$tmp->setValue('jyz', $data['jyz']);

$tmp->setValue('jyzlxfs', $data['jyzlxfs']);

$tmp->setValue('jzlx', $data['jzlx']);

$tmp->setValue('sfdjjc', $data['sfdjjc']);

$tmp->setValue('djcs', $data['djcs']);

$tmp->setValue('sfkf', $data['sfkf']);

$tmp->setValue('jclb', $data['jclb']);

$tmp->setValue('ltjzcl', $data['ltjzcl']);

$tmp->setValue('sfzr', $data['sfzr']);

$tmp->setValue('jzrs', $data['jzrs']);

$tmp->setValue('jzcs', $data['jzcs']);

$tmp->setValue('zsqysfyaqck', $data['zsqysfyaqck']);

$tmp->setValue('zsqysfytswc', $data['zsqysfytswc']);

$tmp->setValue('zrxs', $data['zrxs']);


$tmp->setValue('hzzdbjxt', $data['hzzdbjxt']);

$tmp->setValue('zdpsmhxt', $data['zdpsmhxt']);

$tmp->setValue('snxfs', $data['snxfs']);

$tmp->setValue('mhq', $data['mhq']);

$tmp->setValue('mhqsl', $data['mhqsl']);

$tmp->setValue('xfssqtqk', $data['xfssqtqk']);


$tmp->setValue('dqxlqk', $data['dqxlqk']);

$tmp->setValue('ddzxcsyqk ', $data['ddzxcsyqk']);

$tmp->setValue('sfsymhgwjrqnsbd', $data['sfsymhgwjrqnsbd']);

$tmp->setValue('sfcfyrybwp', $data['sfcfyrybwxp']);

$tmp->setValue('yrybwxpcfsyqk', $data['yrybwxpcfsyqk']);

$tmp->setValue('sfdqkzxfpx', $data['sfdqkzxfpx']);

$tmp->setValue('ydsh', $data['ydsh']);

$tmp->setValue('yhjzgqk', $data['yhjzgqk']);


$tmp->setImageValue('signature_check', ['path' => '.'.$data['signature_check'], 'width' => 120, 'height' => 20]);

$tmp->setImageValue('signature_bcheck', ['path' => '.'.$data['signature_bcheck'], 'width' => 120, 'height' => 20]);


$tmp->saveAs('./Uploads/合用场所消防安全综合治理记录表_'.$data['bjccsmc'].'.docx');

returnApiSuccess('导出成功','http://xiaofang.********.cn/Uploads/合用场所消防安全综合治理记录表_'.$data['bjccsmc'].'.docx');

}

else{

returnApiError('导出失败,请稍后再试!');

exit();

}

}


//添加基本信息照片

public function addbasepicbyid(){

checkscret('secret');//验证授权码

checkdataPost('baseid');

checkdataPost('type');


$baseid=$_POST['baseid'];

$type=$_POST['type'];


$map['baseid']=$baseid;


$data['baseid']=$baseid;


//保存文件

$upload = new \Think\Upload(); // 实例化上传类

$upload->rootPath = './Uploads/'; // 设置附件上传根目录

$upload->saveName = array('uniqid', mt_rand(1,999999).'_'.md5(uniqid())); // 自定义图片重命名

$upload->exts = array('jpg', 'jpeg' ,'png'); // 设置附件上传类型 只允许照片

// 上传文件

$uploadinfo = $upload->upload();


if($uploadinfo){

if($type=='01'){

$data['mt']="/Uploads/".$uploadinfo['file']['savepath'].$uploadinfo['file']['savename'];

}

else if($type=='02'){

$data['yyzz']="/Uploads/".$uploadinfo['file']['savepath'].$uploadinfo['file']['savename'];

}

else if($type=='03'){

$data['dlqk']="/Uploads/".$uploadinfo['file']['savepath'].$uploadinfo['file']['savename'];

}

else if($type=='04'){

$data['sfz']="/Uploads/".$uploadinfo['file']['savepath'].$uploadinfo['file']['savename'];

}

}

$data['create_time']=time();


if($this->checkbasepic($baseid)){

$releaseInfo=M()->table('basepic')->where($map)->save($data);

}

else{

$releaseInfo=M()->table('basepic')->data($data)->add();

}


if($releaseInfo){

returnApiSuccess('添加成功',"http://xiaofang.******.cn/Uploads/".$uploadinfo['file']['savepath'].$uploadinfo['file']['savename']);

}

else{

returnApiError('添加失败!');

exit();

}

}


function checkbasepic($baseid){

$map['baseid']=$baseid;


$ret=M()->table('basepic')->where($map)->find();


if($ret){

return true;

}

else{

return false;

}

}

}巡检是企事业单位的常见场景之一,以消防检查为例,秋冬季节气温下降、生产繁忙,用火、用电、用气情况大量增加,消防安全事件多发,一款消防检查app可以有效减少繁复工作、提升巡检效率。本文将详细介绍如何使用YonBuilder移动开发平台开发消防检查助手app。

一、功能介绍

把消防检查过程中,需要手写填报的文档,在app端以表单填写进行实现;同时可以添加手写签名、关联照片,而且app端表单填报项目可进行下拉选择,极大提高了工作效率;表单填报完成之后可通过系统后台生成word模板文件,app端下载到手机,通过手机连接打印机,可打印纸质文件。App开发采用AVM框架,后台采用PHP。

功能要点:

1、场所登记,分为九小场所和合用场所登记;

2、监督检查记录;

3、责令整改通知书;

4、基本情况拍照,检查过程记录拍照;

5、后台针对上述数据进行多维度分析,导出Excel表格、Word模板文件。

二、思维导图



编辑切换为居中

添加图片注释,不超过 140 字(可选)


三、用到的模块



编辑切换为居中

添加图片注释,不超过 140 字(可选)


四、项目目录



编辑

添加图片注释,不超过 140 字(可选)


五、开发介绍

1、首页导航

系统首页使用tabLayout,可以将相关参数配置在JSON文件中,再在config.xml中将content的值设置成该JSON文件的路径。如果底部导航没有特殊需求这里强烈建议大家使用tabLayout为app进行布局,官方已经将各类手机屏幕及不同的分辨率进行了适配,免去了很多关于适配方面的问题。



编辑切换为居中

添加图片注释,不超过 140 字(可选)


{

"name": "root",

"textOffset": 6,

"color": "#999999",

"selectedColor": "#004494",

"scrollEnabled": false,

"hideNavigationBar": false,

"bgColor": "#fff",

"navigationBar": {

"background": "./images/navbk.png",

"shadow": "rgba(0,0,0,0)",

"color": "#fff",

"fontSize": 18,

"hideBackButton": true

},

"tabBar": {

"background": "#fff",

"shadow": "#eee",

"color": "#5E5E5E",

"selectedColor": "#004494",

"textOffset": 3,

"fontSize": 11,

"scrollEnabled": true,

"index": 0,

"preload": 1,

"frames": [

{

"title": "首页",

"name": "home",

"url": "./pages/index/home"

},

{

"title": "历史记录",

"name": "course",

"url": "./pages/history/records"

},

{

"title": "我的",

"name": "user",

"url": "./pages/user/wode"

}

],

"list": [

{

"text": "首页",

"iconPath": "./images/home.png",

"selectedIconPath": "./images/home-o.png"

},

{

"text": "历史记录",

"iconPath": "./images/his.png",

"selectedIconPath": "./images/his-o.png"

},

{

"text": "我的",

"iconPath": "./images/my.png",

"selectedIconPath": "./images/my-o.png"

}

]

}

}

由于导航使用的tablayout,所有app初始化需要执行的操作,只需要在第一个加载的页面执行即可全局响应。可通过 tabBar中的"index"字段来确定第一个需要加载的页面,通过"preload"来确定需要预加载几个页面。

2、动态权限

动态权限的获取在第一个初始化的页面执行即可。本项目中需要用到存储、相机、相册3个权限。用到的是官方的API方法hasPermission。



编辑切换为居中

添加图片注释,不超过 140 字(可选)


//提示获取存储权限

var limits=[];

var resultList = api.hasPermission({

list: ['storage','camera','photos']

});

if (resultList[0].granted) {

// 已授权,可以继续下一步操作

} else {

limits.push(resultList[0].name);

}

if (resultList[1].granted) {

// 已授权,可以继续下一步操作

} else {

limits.push(resultList[1].name);

}

if (resultList[2].granted) {

// 已授权,可以继续下一步操作

} else {

limits.push(resultList[2].name);

}

if(limits.length>0){

api.requestPermission({

list: limits,

}, function(res) {

// console.log(JSON.stringify(res));

});

}

manifest.xml文件,关于targetSdkVersion的值的大小,这里可以根据下文图片中的说明,结合项目需要上架的平台自行设置。



编辑

添加图片注释,不超过 140 字(可选)




编辑切换为居中

添加图片注释,不超过 140 字(可选)




编辑切换为居中

添加图片注释,不超过 140 字(可选)


<?xml version="1.0" encoding="UTF-8"?>

<manifest>

<application name="targetSdkVersion" value="28"/>

</manifest>

3、消息事件

本项目中通过发送事件sendEvent和监听事件addEventListener,消息事件要学会合理运用来提升app中各个页面之间交互的体验。下面对实现在表单提交成功之后刷新列表页、登陆成功之后跳转页面时重新加载用户信息的具体操作进行说明。

表单数据提交成功之后,在回调里发送事件"addbase",然后关闭页面,跳转至列表页,在列表页的apiready中监听“addbase”事件,在监听成功回调中执行刷新列表的操作。

onsubmit(e){

let result = e.detail.value;


this.data.dwmc = result.dwmc?result.dwmc:this.data.dwmc;

this.data.dwdz = result.dwdz?result.dwdz:this.data.dwdz;

//省略其他字段

let params = {

data:{

values:{

secret: Config.secret,

userid: api.getPrefs({sync: true,key: 'userid'}),

partid: api.getPrefs({sync: true,key: 'partid'}),

id:this.data.id,

dwmc:this.data.dwmc,

dwdz:this.data.dwdz,

//省略

}

}

}

api.showProgress();

Model.addbase(params, (res,err) => {

// console.log(JSON.stringify(res));

// console.log(JSON.stringify(err));

if (res && res.flag == 'Success') {

api.toast({

msg:'登记成功'

});

api.sendEvent({

name: 'addbase',

});

api.closeWin();

} else {

api.toast({

msg:res.msg

})

}

api.hideProgress();

});

},

apiready(){

this.data.tab=api.pageParam.tab;

this.data.tabtitle=api.pageParam.tabtitle;

this.data.refresherTriggered = true;

this.loadData(false);

api.addEventListener({

name: 'setuserinfo'

}, (ret, err) => {

this.loadData(false);

});

//监听增加修改基本信息

api.addEventListener({

name: 'addbase'

}, (ret, err) => {

this.loadData(false);

});

api.addEventListener({

name: 'delbase'

}, (ret, err) => {

this.loadData(false);

});

},

4、接口调用

将接口调用和接口配置分别封装2个JS插件,model.js和config.js。统一管理,避免了在每个页面进行接口调用时都重复写一遍代码,有效简化了每个功能页面的代码量,只需要在回调里专注写自己的业务逻辑即可。

import $util from "../../utils/util.js"

import {Model} from "../../utils/model.js"

import {Config} from "../../utils/config.js"

config.js


class Config{

constructor(){}

}


Config.restUrl = 'http://xiaofang.*******.cn/api.php/Home/Index';

Config.secret = '99d0fd93-***************************';


Config.addbase ='/addbase';//登记基本信息表

Config.querylist ='/querylist';//查询登记单位列表

Config.querybasebyid ='/querybasebyid';//查询登记单位基本信息详情

Config.querybaseinfobyid ='/querybaseinfobyid';//查询登记单位基本信息详情

Config.exportbase ='/exportbase';//下载登记单位基本信息

Config.deletebasebyid ='/deletebasebyid';//删除登记单位基本信息

Config.login ='/login';//登陆

Config.getpart ='/getpart';//获取单位列表

Config.register ='/register';//用户注册

/**省略**/

Config.checkUserStatus ='/checkUserStatus';//获取用户状态


export {Config};

model.js

import {Config} from './config.js';


class Model {

constructor() {}

}


/*登记基本信息表 */

Model.addbase = function (param, callback){

param.url = Config.addbase;

param.method = 'post';

this.request(param, callback);

}


/*查询登记单位列表 */

Model.querylist = function (param, callback){

param.url = Config.querylist;

param.method = 'post';

this.request(param, callback);

}


/*查询登记单位基本信息详情 */

Model.querybasebyid = function (param, callback){

param.url = Config.querybasebyid;

param.method = 'post';

this.request(param, callback);

}


/*查询登记单位基本信息详情 */

Model.querybaseinfobyid = function (param, callback){

param.url = Config.querybaseinfobyid;

param.method = 'post';

this.request(param, callback);

}


/*下载登记单位基本信息 */

Model.exportbase = function (param, callback){

param.url = Config.exportbase;

param.method = 'post';

this.request(param, callback);

}


/*删除登记单位基本信息 */

Model.deletebasebyid = function (param, callback){

param.url = Config.deletebasebyid;

param.method = 'post';

this.request(param, callback);

}


/*登陆模块 */

Model.login = function (param, callback){

param.url = Config.login;

param.method = 'post';

this.request(param, callback);

}


/**省略**/


/*获取用户状态 */

Model.checkUserStatus = function (param, callback){

param.url = Config.checkUserStatus;

param.method = 'post';

this.request(param, callback);

}


Model.request = function(p, callback) {

var param = p;

if (!param.headers) {

param.headers = {};

}


if (param.data && param.data.body) {

param.headers['Content-Type'] = 'application/json; charset=utf-8';

}

if (param.url) {

param.url = Config.restUrl + param.url;

}


api.ajax(param, function(ret, err) {

callback && callback(ret, err);

});

}


export {Model};

5、数据列表及分页查询

数据列表的展示,采用scroll-view标签,通过onrefresherrefresh,onrefresherrefresh触发的事件中进行数据列表的刷新和分页查询。通过refresher-triggered这个属性来设置当前下拉刷新状态,true 表示下拉刷新已经被触发,false 表示下拉刷新未被触发。如果想默认下拉刷新一下可以在apiready中将之设置为true,以此来代替执行数据刷新操作。

如果列表中的每一项的元素较少,而且没有样式的特殊要求,也可以使用list-view来实现。

下面是单位列表的完整页面代码。其他页面的列表基本功能都是一致的,只是在每一项的样式及参数个数上存在差异。

<template name='unitlist'>

<view class="page">

<scroll-view class="main" scroll-y enable-back-to-top refresher-enabled refresher-triggered={refresherTriggered} onrefresherrefresh={this.onrefresherrefresh} onscrolltolower={this.onscrolltolower}>

<view class="search-box">

<input class="serach-input" placeholder="请输入单位名称检索" confirm-type="search" onconfirm="onconfirm" oninput={this.getKey}/>

<text class="search-btn" onclick="onconfirm">搜索</text>

</view>

<view class="item-box">

<view class="item" data-id={item.id} onclick={this.openTable} v-for="(item, index) in list">

<text class="item-content">{{item.name}}</text>

<view class="item-sub">

<view class="item-sub-box">

<image class="item-sub-ico" src="../../images/DW.png" mode="aspectFit"></image>

<text class="item-info">{{item.address}}</text>

</view>

<view class="item-sub-box">

<image class="item-sub-ico" src="../../images/CT.png" mode="aspectFit"></image>

<text class="item-info">{{item.type}}</text>

</view>

</view>

</view>

</view>

<view class="footer">

<text class="loadDesc">{loadStateDesc}</text>

</view>

</scroll-view>

</view>

</template>

<script>

import {Model} from '../../utils/model.js'

import {Config} from "../../utils/config.js"

import $util from "../../utils/util.js"

export default {

name: 'unitlist',

data() {

return{

list:[],

skip: 0,

loading: false,

refresherTriggered: false,

haveMoreData: true,

tab:'',

tabtitle:'',

key:''

}

},

computed: {

loadStateDesc(){

if (this.data.loading || this.data.haveMoreData) {

return '加载中...';

} else if (this.list.length > 0) {

return '没有更多啦';

} else {

return '暂时没有内容';

}

}

},

methods: {

apiready(){

this.data.tab=api.pageParam.tab;

this.data.tabtitle=api.pageParam.tabtitle;

this.data.refresherTriggered = true;

this.loadData(false);

api.addEventListener({

name: 'setuserinfo'

}, (ret, err) => {

this.loadData(false);

});

//监听增加修改基本信息

api.addEventListener({

name: 'addbase'

}, (ret, err) => {

this.loadData(false);

});

api.addEventListener({

name: 'delbase'

}, (ret, err) => {

this.loadData(false);

});

},

loadData(loadMore) {

this.data.loading = true;

var that = this;

var limit = 20;

var skip = loadMore?that.data.skip+1:0;

let params = {

data:{

values:{

secret: Config.secret,

userid: api.getPrefs({sync: true,key: 'userid'}),

roleid: api.getPrefs({sync: true,key: 'roleid'}),

partid: api.getPrefs({sync: true,key: 'partid'}),

skip: skip,

limit: limit,

key:this.data.key

}

}

}

api.showProgress();

Model.querylist(params, (res,err) => {

// console.log(JSON.stringify(res));

// console.log(JSON.stringify(err));

if (res && res.flag == 'Success') {

let lists = res.data;

that.data.haveMoreData = lists.length == limit;

if (loadMore) {

that.data.list = that.data.list.concat(lists);

} else {

that.data.list = lists;

}

that.data.skip = skip;

} else {

that.data.haveMoreData = false;

}

that.data.loading = false;

that.data.refresherTriggered = false;

api.hideProgress();

});

},

//打开填写表格

openTable(e) {

var id = e.currentTarget.dataset.id;

$util.openWin({

name: this.data.tab,

url: '../index/'+this.data.tab+'.stml',

title: this.data.tabtitle,

pageParam:{

id:id

}

});

},

/*下拉刷新页面*/

onrefresherrefresh(){

this.data.refresherTriggered = true;

this.loadData(false);

},

onscrolltolower() {

if (this.data.haveMoreData) {

this.loadData(true);

}

},

getKey(e){

this.data.key = e.detail.value;

},

onconfirm(){

this.loadData(false);

}

}

}

</script>

<style>

.main {

height: 100%;

background-color: #eaf0fa;

}

.item-box{

background-color: #fff;

margin: 5px;

}

.item{

border-bottom: 1px solid #efefef;

margin: 0 10px;

justify-content:flex-start;

flex-direction:column;

}

.item-content{

font-size: 17PX;

margin-top: 10px;

}

.item-info{

font-size: 13PX;

color: #666;

margin: 10px 0;

}

.item-sub{

justify-content:space-between;

flex-direction:row;

}

.footer {

height: 44px;

justify-content: center;

align-items: center;

}

.loadDesc {

width: 200px;

text-align: center;

}

.item-sub-ico{

width: 15px;

margin: 10px 0;

}

.item-sub-box{

flex-flow: row nowrap;

}

.search-box{

flex-flow: row nowrap;

align-items: center;

background-color: #2c6ddc;

border-radius: 5px;

margin: 5px;

}

.serach-input{

padding: 5px;

width: 80%;

height: 50px;

border-top-left-radius: 5px;

border-bottom-left-radius: 5px;

}

.search-btn{

width: 20%;

text-align: center;

color: #ffffff;

}

</style>

6、双击退出程序

在首页页面和登陆页面中,添加双击退出程序功能,避免出现单击退出键出现不必要的页面跳转失误。此监听事件要在apiready中执行。

//监听返回 双击退出程序

api.setPrefs({

key: 'time_last',

value: '0'

});

api.addEventListener({

name : 'keyback'

}, function(ret, err) {

var time_last = api.getPrefs({sync: true,key: 'time_last'});

var time_now = Date.parse(new Date());

if (time_now - time_last > 2000) {

api.setPrefs({key:'time_last',value:time_now});

api.toast({

msg : '再按一次退出APP',

duration : 2000,

location : 'bottom'

});

} else {

api.closeWidget({

silent : true

});

}

});

7、账号有效性确认

由于后台针对用户账号,启用了停用功能,后台一旦设置账号停用,app中也应相应地将用户进行退出系统操作。此操作在首页的apiready中进行执行。

isLogin(){

if(!api.getPrefs({sync: true,key:'userid'})){

$util.openWin({

name: 'login',

url: '../user/login.stml',

title: '',

hideNavigationBar:true

});

}

else{

let params = {

data:{

values:{

secret: Config.secret,

userid: api.getPrefs({sync: true,key:'userid'})

}

}

}

api.showProgress();

Model.checkUserStatus(params, (res,err) => {

// console.log(JSON.stringify(res));

// console.log(JSON.stringify(err));

if (res && res.flag == 'Success') {

if(ret.data=='02'){

//清楚缓存用户数据

api.removePrefs({

key: 'name'

});

api.removePrefs({

key: 'userid'

});

api.removePrefs({

key: 'partname'

});

api.removePrefs({

key: 'partid'

});

api.removePrefs({

key: 'role'

});

api.removePrefs({

key: 'rolename'

});

api.removePrefs({

key: 'username'

});

//用户已停用 退出系统

$util.openWin({

name: 'login',

url: '../user/login.stml',

title: '',

hideNavigationBar:true

});

}

} else {

//清除用户信息

api.removePrefs({

key: 'name'

});

api.removePrefs({

key: 'userid'

});

api.removePrefs({

key: 'partname'

});

api.removePrefs({

key: 'partid'

});

api.removePrefs({

key: 'role'

});

api.removePrefs({

key: 'rolename'

});

api.removePrefs({

key: 'username'

});

//用户异常 退出重新登陆

$util.openWin({

name: 'login',

url: '../user/login.stml',

title: '',

hideNavigationBar:true

});

}

api.hideProgress();

});

}

}

8、表单提交、回显

表单使用的是AVM的 from组件,通过onsubmit进行表单数据提交。其中主要用到了input、textarea、radio、checkbox;每个控件的具体使用方法,在官方文档中否有详细的介绍。下面就具体的代码示例进行展示。



编辑切换为居中

添加图片注释,不超过 140 字(可选)


页面代码

<template name='addbase'>

<scroll-view class="page" scroll-y>

<form onsubmit={this.onsubmit}>

<view class="item">

<text>单位名称:</text>

<input name="dwmc" value={this.data.dwmc} placeholder="请输入单位名称"/>

</view>

<view class="item">

<text>单位地址:</text>

<input name="dwdz" value={this.data.dwdz} placeholder="请输入单位详细地址"/>

</view>

<checkbox-group class="item" name="dwlb">

<text>单位类别:</text>

<view class="item-checkbox">

<label v-for="item in dwlbarr">

<checkbox value={item} v-bind:checked="this.data.seldwlb.indexOf(item)!=-1?true:false"/>

<text>{item}</text>

</label>

</view>

<input name="dwlb_qt" value={this.data.dwlb_qt} placeholder="请输入单位类别"/>

</checkbox-group>

<checkbox-group class="item" name="dwxz">

<text>单位性质:</text>

<view class="item-checkbox">

<label v-for="item in dwxzarr">

<checkbox value={item} v-bind:checked="this.data.seldwxz.indexOf(item)!=-1?true:false"/>

<text>{item}</text>

</label>

</view>

</checkbox-group>

<view class="item">

<text>职工总数:</text>

<input name="zgzs" value={this.data.zgzs} keyboard-type="number" placeholder="请输入单位职工总数"/>

</view>

<view class="item">

<text>消防安全责任人:</text>

<input name="xfaqzrr_xm" value={this.data.xfaqzrr_xm} placeholder="请输入负责人姓名"/>

<input name="xfaqzrr_zw" value={this.data.xfaqzrr_zw} placeholder="请输入负责人职务"/>

<input name="xfaqzrr_dh" value={this.data.xfaqzrr_dh} keyboard-type="number" placeholder="请输入负责人电话"/>

</view>

<view class="item">

<text>消防安全管理人:</text>

<input name="xfaqglr_xm" value={this.data.xfaqglr_xm} placeholder="请输入管理人姓名"/>

<input name="xfaqglr_zw" value={this.data.xfaqglr_zw} placeholder="请输入管理人职务"/>

<input name="xfaqglr_dh" value={this.data.xfaqglr_dh} keyboard-type="number" placeholder="请输入管理人电话"/>

</view>

<view class="item">

<text>专兼职防火干部:</text>

<input name="zjzfhgb_xm" value={this.data.zjzfhgb_xm} placeholder="请输入专兼职防火干部姓名"/>

<input name="zjzfhgb_zw" value={this.data.zjzfhgb_zw} placeholder="请输入专兼职防火干部职务"/>

<input name="zjzfhgb_dh" value={this.data.zjzfhgb_dh} keyboard-type="number" placeholder="请输入专兼职防火干部电话"/>

</view>

<view class="item">

<label class="label-box">

<text class="label-title">建筑层数(层)</text>

<input class="label-input" name="jzcs" value={this.data.jzcs} keyboard-type="number" placeholder="请输入建筑层数(层)"/>

</label>

<label class="label-box">

<text class="label-title">所在层数(层)</text>

<input class="label-input" name="szcs" value={this.data.szcs} keyboard-type="number" placeholder="请输入所在层数(层)"/>

</label>

<label class="label-box">

<text class="label-title">建筑高度(m)</text>

<input class="label-input" name="jzgd" value={this.data.jzgd} keyboard-type="number" placeholder="请输入建筑高度(m)"/>

</label>

<label class="label-box">

<text class="label-title">总建筑面积(㎡)</text>

<input class="label-input" name="zjzmj" value={this.data.zjzmj} keyboard-type="decimal" placeholder="请输入总建筑面积(㎡)"/>

</label>

<label class="label-box">

<text class="label-title">每层建筑面积(㎡)</text>

<input class="label-input" name="mcjzmj" value={this.data.mcjzmj} keyboard-type="decimal" placeholder="请输入每层建筑面积(㎡)"/>

</label>

<label class="label-box">

<text class="label-title">营业面积(㎡)</text>

<input class="label-input" name="yymj" value={this.data.yymj} keyboard-type="decimal" placeholder="请输入营业面积(㎡)"/>

</label>

<label class="label-box">

<text class="label-title">检查时间</text>

<input class="label-input" name="jcsj" value={this.data.jcsj} keyboard-type="number" placeholder="请输入检查时间"/>

</label>

<label class="label-box">

<text class="label-title">投入使用时间</text>

<input class="label-input" name="trsysj" value={this.data.trsysj} keyboard-type="number" placeholder="请输入投入使用时间"/>

</label>

<label class="label-box">

<text class="label-title">开业时间</text>

<input class="label-input" name="kysj" value={this.data.kysj} keyboard-type="number" placeholder="请输入开业时间"/>

</label>

<label class="label-box">

<text class="label-title">租赁房屋户主姓名</text>

<input class="label-input" name="zlfwhzxm" value={this.data.zlfwhzxm} placeholder="请输入租赁房屋户主姓名"/>

</label>

</view>

<view class="item">

<text>生产经营状况:</text>

<input name="scjyzk" value={this.data.scjyzk} placeholder="请输入单位生产经营状况"/>

</view>

<view class="item">

<text>隶属社区:</text>

<input name="lssq" value={this.data.lssq} placeholder="请输入单位隶属社区"/>

</view>

<radio-group class="item" name="ssyjfl">

<text>三色预警分类:</text>

<view class="item-checkbox">

<label v-for="item in ssyjflarr">

<radio value={item} v-bind:checked="this.data.ssyjfl==item?true:false"/>

<text>{item}</text>

</label>

</view>

</radio-group>

<view class="item">

<text>消防设置种类及数量:</text>

<textarea name="xfsszljsl" value={this.data.xfsszljsl} placeholder="请输入消防设置种类及数量"/>

</view>

<view class="item">

<text>检查登记情况:</text>

<textarea name="jcqkdj_1" value={this.data.jcqkdj_1} placeholder="请输入检查登记情况"/>

<textarea name="jcqkdj_2" value={this.data.jcqkdj_2} placeholder="请输入检查登记情况"/>

<textarea name="jcqkdj_3" value={this.data.jcqkdj_3} placeholder="请输入检查登记情况"/>

<textarea name="jcqkdj_4" value={this.data.jcqkdj_4} placeholder="请输入检查登记情况"/>

</view>

<view class="item">

<text>填表说明:</text>

</view>

<button class="btn-submit" type="submit">提交</button>

</form>

<button v-show="isdelete" class="btn-delete" type="button" @click="delbase">删除</button>

</scroll-view>

</template>

表单提交

data() {

return{

dwmc:'',

dwdz:'',

dwlb:'',

dwxz:'',

zgzs:0,

xfaqzrr_xm:'',

xfaqzrr_zw:'',

xfaqzrr_dh:'',

xfaqglr_xm:'',

xfaqglr_zw:'',

xfaqglr_dh:'',

zjzfhgb_xm:'',

zjzfhgb_zw:'',

zjzfhgb_dh:'',

jzcs:null,

jzgd:null,

zjzmj:null,

mcjzmj:null,

szcs:null,

yymj:null,

jcsj:'',

trsysj:'',

kysj:'',

zlfwhzxm:'',

scjyzk:'',

lssq:'',

ssyjfl:'',

xfsszljsl:'',

jcqkdj_1:'',

jcqkdj_2:'',

jcqkdj_3:'',

jcqkdj_4:'',

dwlb_qt:'',

id:0,

ssyjflarr:['红','黄','绿'],

dwlbarr:['购物场所','餐饮场所','住宿场所','公共娱乐场所','休闲健身场所','医疗场所','教学场所','生产加工企业','易燃易爆危险品销售、储存场所','其他'],

dwxzarr:['国有','集体','股份合作公司','股份有限公司','港澳台投资','中外合资','个体私营','其他'],

seldwlb:[],

seldwxz:[],

isdelete:false,

dateList: [$formatDate.lastYear30(),[1,2,3,4,5,6,7,8,9,10,11,12],[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31]],

jcsjSelectorValue:[0,0,0],

trsysjSelectorValue:[0,0,0],

kysjSelectorValue:[0,0,0]

}

},

数据回显

//查询已添加的数据

loadData(){

let params = {

data:{

values:{

secret: Config.secret,

id:this.data.id

}

}

}

api.showProgress();

Model.querybasebyid(params, (res,err) => {

// console.log(JSON.stringify(res));

// console.log(JSON.stringify(err));

if (res && res.flag == 'Success') {

//填充数据

let result=res.data;


this.data.dwmc = result.dwmc?result.dwmc:this.data.dwmc;

this.data.dwdz = result.dwdz?result.dwdz:this.data.dwdz;

this.data.seldwlb = result.dwlb?result.dwlb.split(','):this.data.dwlb;

this.data.dwlb_qt = result.dwlb_qt?result.dwlb_qt:this.data.dwlb_qt;

this.data.seldwxz = result.dwxz?result.dwxz.split(','):this.data.dwxz;

this.data.zgzs = result.zgzs?result.zgzs:this.data.zgzs;

this.data.xfaqzrr_xm = result.xfaqzrr_xm?result.xfaqzrr_xm:this.data.xfaqzrr_xm;

this.data.xfaqzrr_zw = result.xfaqzrr_zw?result.xfaqzrr_zw:this.data.xfaqzrr_zw;

this.data.xfaqzrr_dh = result.xfaqzrr_dh?result.xfaqzrr_dh:this.data.xfaqzrr_dh;

this.data.xfaqglr_xm = result.xfaqglr_xm?result.xfaqglr_xm:this.data.xfaqglr_xm;

this.data.xfaqglr_zw = result.xfaqglr_zw?result.xfaqglr_zw:this.data.xfaqglr_zw;

this.data.xfaqglr_dh = result.xfaqglr_dh?result.xfaqglr_dh:this.data.xfaqglr_dh;

this.data.zjzfhgb_xm = result.zjzfhgb_xm?result.zjzfhgb_xm:this.data.zjzfhgb_xm;

this.data.zjzfhgb_zw = result.zjzfhgb_zw?result.zjzfhgb_zw:this.data.zjzfhgb_zw;

this.data.zjzfhgb_dh = result.zjzfhgb_dh?result.zjzfhgb_dh:this.data.zjzfhgb_dh;

this.data.jzcs = result.jzcs?result.jzcs:this.data.jzcs;

this.data.jzgd = result.jzgd?result.jzgd:this.data.jzgd;

this.data.zjzmj = result.zjzmj?result.zjzmj:this.data.zjzmj;

this.data.mcjzmj = result.mcjzmj?result.mcjzmj:this.data.mcjzmj;

this.data.szcs = result.szcs?result.szcs:this.data.szcs;

this.data.yymj = result.yymj?result.yymj:this.data.yymj;

this.data.jcsj = result.jcsj?result.jcsj:this.data.jcsj;

this.data.trsysj = result.trsysj?result.trsysj:this.data.trsysj;

this.data.kysj = result.kysj?result.kysj:this.data.kysj;

this.data.zlfwhzxm = result.zlfwhzxm?result.zlfwhzxm:this.data.zlfwhzxm;

this.data.scjyzk = result.scjyzk?result.scjyzk:this.data.scjyzk;

this.data.lssq = result.lssq?result.lssq:this.data.lssq;

this.data.ssyjfl = result.ssyjfl?result.ssyjfl:this.data.ssyjfl;

this.data.xfsszljsl = result.xfsszljsl?result.xfsszljsl:this.data.xfsszljsl;

this.data.jcqkdj_1 = result.jcqkdj_1?result.jcqkdj_1:this.data.jcqkdj_1;

this.data.jcqkdj_2 = result.jcqkdj_1?result.jcqkdj_2:this.data.jcqkdj_2;

this.data.jcqkdj_3 = result.jcqkdj_1?result.jcqkdj_3:this.data.jcqkdj_3;

this.data.jcqkdj_4 = result.jcqkdj_1?result.jcqkdj_4:this.data.jcqkdj_4;


} else {

api.toast({

msg:res.msg

})

}

api.hideProgress();

});

},

9、拍照及上传照片,图片预览

拍照使用的是FNPhotograph模块,自带UI的open接口,可选择拍摄照片的质量,可配置使用摄像头方向,同时可配置照片不用存储到相册中、禁用显示相册按钮,保证用户只能现场拍照,可以满足项目需求。



编辑切换为居中

添加图片注释,不超过 140 字(可选)


项目中很多页面涉及到图片预览功能,分为单图预览和多图预览。图片预览采用的是photoBrowser模块。photoBrowser是一个图片浏览器,支持单张、多张图片查看的功能,可放大缩小图片,支持本地和网络图片资源。若是网络图片资源则会被缓存到本地,缓存到本地上的资源可以通过clearCache接口手动清除。同时本模块支持横竖屏显示,在本app支持横竖屏的情况下,本模块底层会自动监听当前设备的位置状态,自动适配横竖屏以展示图片。



编辑切换为居中

添加图片注释,不超过 140 字(可选)


getPicture(e){

this.data.type = e.currentTarget.dataset.type;

api.actionSheet({

title: '请选择',

cancelTitle: '取消',

buttons: ['选择图片','图片预览']

}, (ret, err)=> {

// console.log(JSON.stringify(ret));

// console.log(JSON.stringify(err));

// var index = ret.buttonIndex;

if(ret.buttonIndex==1){

var FNPhotograph = api.require('FNPhotograph');

FNPhotograph.open({

album: true ,

quality: 'medium'

}, (ret)=>{

// console.log(JSON.stringify(ret));

if(ret.eventType=='takePhoto'){

FNPhotograph.close();

//上传图片

let params = {

data:{

values:{

secret: Config.secret,

baseid:this.data.baseid,

type:this.data.type

},

files:{

'file':ret.imagePath,

}

}

}

api.showProgress();

Model.addbasepicbyid(params, (res,err) => {

// console.log(JSON.stringify(res));

// console.log(JSON.stringify(err));

if (res && res.flag == 'Success') {

if(this.data.type=='01'){

this.data.src1=res.data;

}

else if(this.data.type=='02'){

this.data.src2=res.data;

}

else if(this.data.type=='03'){

this.data.src3=res.data;

}

else if(this.data.type=='04'){

this.data.src4=res.data;

}

} else {

api.toast({

msg:res.msg

})

}

api.hideProgress();

});

}

});

}

else if(ret.buttonIndex==2){

//图片预览

let src='';

if(this.data.type=='01'){

src=this.data.src1;

}

else if(this.data.type=='02'){

src=this.data.src2;

}

else if(this.data.type=='03'){

src=this.data.src3;

}

else if(this.data.type=='04'){

src=this.data.src4;

}

var photoBrowser = api.require('photoBrowser');

photoBrowser.open({

images: [

src

],

placeholderImg: 'widget://res/img/apicloud.png',

bgColor: '#000'

}, (ret, err) => {

if (ret) {

if(ret.eventType=='click'){

photoBrowser.close();

}

} else {

api.toast({

msg:'图片预览失败'

})

}

});

}

});

}

10、页面之间的跳转和参数传递

封装工具类until.js,在其中定义了openWin方法来实现页面之间的跳转。页面跳转时参数的传递通过pageParam添加参数进行,在跳转到的页面通过api.pageParam.xxx在apiready中进行接收。

<view class="tab-item" data-url="addbase" data-title="九小场所登记" tapmode @click="openPage">

<image class="tab-item-logo" src="../../images/JB.png" mode="scaleToFill"></image>

<text class="tab-item-title"> 九小场所登记</text>

</view>

methods: {

apiready(){//like created

this.data.id=api.pageParam.id;

},

openPage(e){

let title = e.currentTarget.dataset.title;

let url = e.currentTarget.dataset.url;

$util.openWin({

name: url,

url: '../index/'+url+'.stml',

title: title,

pageParam:{

id:this.data.id

}

});

}

}

util.js

const $util = {

openWin(param){

var param = {

name: param.name,

url: param.url,

title: param.title||'',

pageParam: param.pageParam||{},

hideNavigationBar: param.hideNavigationBar || false,

navigationBar:{

background:'../../images/navbk.png',

shadow: '#fff',

color: '#fff'

}

};

if (this.isApp()) {

api.openTabLayout(param);

} else {

api.openWin(param);

}

},

isApp(){

if (api.platform && api.platform == 'app') {

return true;

}

return false;

},

fitRichText(richtext, width){

var str = `<img style="max-width:${width}px;"`;

var result = richtext.replace(/\<img/gi, str);

return result;

}

}

export default $util;

11、导航栏自定义按钮点击事件

如果是首页加载的页面,可以在首页中通过索引index进行判断然后分别配置;如果在单独的页面中需要添加的话,可在页面的apiready中进行配置。



编辑切换为居中

添加图片注释,不超过 140 字(可选)


首页中的配置,需要注意的是,如果是页面直接跳转,配置多个页面时没有问题;但如果按钮事件是执行某个页面具体的方法时,就会出现问题。这里建议如果按钮事件是执行某个页面具体的方法,不要在首页中配置,可在页面中通过其他方式进行实现。因为首页配置的内容会在全局使用,而且加载成功之后,通过tabbar切换页面的时候,是不会进行页面刷新操作的。

apiready() {

//导航设置

api.addEventListener({

name:'tabitembtn'

}, (ret) => {

api.setTabBarAttr({

index: ret.index

});

if(ret.index==0){

api.setTabLayoutAttr({

hideNavigationBar:true,

animated:false

});

}

else if(ret.index==2){

api.setNavBarAttr({

rightButtons: [{

iconPath:'widget://image/chart.png'

}]

});

api.setTabLayoutAttr({

hideNavigationBar:false,

animated:false

});

api.addEventListener({

name:'navitembtn'

}, (ret)=>{

if(ret.type=='right'){

$util.openWin({

name: 'chart',

url: 'widget://html/test.html',

title: '统计分析',

pageParam:{


}

})

}

})

}

else{

api.setTabLayoutAttr({

hideNavigationBar:false,

animated:false

});

api.setNavBarAttr({

rightButtons: [{

}]

});

api.addEventListener({

name:'navitembtn'

}, (ret)=>{


})

}

});

},

单独页面中的配置

apiready(){

//添加右上角按钮

api.setNavBarAttr({

rightButtons: [{

text: '添加'

}]

});

//监听右上角按钮点击事件

api.addEventListener({

name: 'navitembtn'

}, (ret, err)=> {

if (ret.type == 'right') {

$util.openWin({

name: 'addjcpics',

url: 'addjcpics.stml',

title: '添加检查记录照片',

pageParam:{

baseid:this.data.baseid

}

});

}

});

},

12、手写签名

手写签名用到的是drawingBoard模块。开发者可自定义固定宽高(w、h)的 “frame”,该“frame”即是可手写签名的背景透明的画板,可将此画板固定在指定的 frame 或 window 上,从而自定义出符合自己需求的各种UI效果的签名功能。



编辑切换为居中

添加图片注释,不超过 140 字(可选)


<template name='signature'>

<view class="page">

<view class="flowbottom">

<button class="btn-clear" tapmode @click="clear">重写</button>

<button class="btn" tapmode @click="submit" disabled={this.data.btn_disabled}>确定</button>

</view>

</view>

</template>

<script>

export default {

name: 'signature',

data() {

return{

btn_disabled:false,

type:''

}

},

methods: {

apiready(){

this.data.type = api.pageParam.type;

var drawingBoard = api.require('drawingBoard');

drawingBoard.open({

rect: {

x: 10,

y: 100,

w: api.frameWidth-20,

h: (api.frameWidth-20)/2

},

styles: {

brush: {

color: '#000000',

width: 3

},

bgColor: '#f0f0f0'

},

fixedOn: api.frameName

});

},

clear(){

var drawingBoard = api.require('drawingBoard');

drawingBoard.clear();

},

submit(){

this.data.btn_disabled = true;

var drawingBoard = api.require('drawingBoard');

drawingBoard.save({

savePath: 'fs://drawingBoard/'+Date.now()+'.png',

copyToAlbum: false

}, (ret)=> {

// console.log(JSON.stringify(ret));

if(ret.absolutePath=='undefined'){

this.data.btn_disabled = false;

api.toast({

msg:'签名失败,请稍后再试'

});

}

else{

//

api.sendEvent({

name: 'singture_success',

extra: {

src: ret.absolutePath,

type:this.data.type

}

});

drawingBoard.close();

api.closeWin();

}

});

}

}

}

</script>

<style>

.page {

display: flex;

flex-flow: row nowrap;

height: 100%;

width: 100%;

background-color: #eaf0fa;

}

.flowbottom{

width: 100%;

align-self: flex-end;

padding: 10px;

}

.btn {

display: block;

height: 50px;

width: 100%;

background:#1492ff;

border-radius: 5px;

color: #fff;

font-size: 20px;

font-weight: bolder;

padding: 0;

margin-top: 10px;

}

.btn-clear {

display: block;

height: 50px;

width: 100%;

background:#ff0000;

border-radius: 5px;

color: #fff;

font-size: 20px;

font-weight: bolder;

padding: 0;

margin-top: 10px;

}

</style>

13、清除缓存

由于项目中有很多拍照、查看照片场景,在使用的过程中,就会产生很多的缓存,导致应用反应变慢。所以在应用中增加了清除缓存功能,用的是官方提供的api.clearCache。

在个人中心 apiready中先获取到应用中的缓存,然后点击清除缓存按钮即可清除。

<view class="item" onclick="clearCache">

<image class="item-icon" src="../../images/w_02.png" mode="widthFix"></image>

<text class="item-title">缓存</text>

<text class="item-right-cache">{cache}M</text>

</view>

apiready(){

//获取APP缓存 异步返回结果:

api.getCacheSize((ret) => {

this.data.cache = parseInt(ret.size/1024/1024).toFixed(1);

});

},

clearCache(){

api.clearCache(() => {

api.toast({

msg: '清除完成'

});

});

this.data.cache=0;

},

14、下载并打开word文件

点击下载word文件按钮,调用系统接口,接口会把文件的路径进行返回,先通过api.download将文件下载到本地,然后通过模块docInteraction调用第三方app打开文档。



编辑切换为居中

添加图片注释,不超过 140 字(可选)


//监听右上角按钮点击事件

api.addEventListener({

name: 'navitembtn'

}, (ret, err) => {

if (ret.type == 'right') {

let params = {

data:{

values:{

secret: Config.secret,

id:this.data.id

}

}

}

api.showProgress();

Model.exportbase(params, (res,err) => {

if (res && res.flag == 'Success') {

//下载文件

api.download({

url: res.data,

report: true,

cache: false,

allowResume: true

}, (ret, err)=> {

// console.log(JSON.stringify(ret));

if (ret.state == 1) {

//下载成功 跳转WORD预览页面

var docInteraction =

api.require('docInteraction');

docInteraction.open({

path: ret.savePath

}, (ret, err) => {

});

} else {

if(ret.percent>0){

api.toast({

msg:'正在下载'+ret.percent+'%'

})

}

else{

api.toast({

msg:'下载失败,请稍后再试'

})

}

}

});

} else {

api.toast({

msg:'下载失败,请稍后再试'

})

}

api.hideProgress();

});

}

});

15、登录、退出

通过api.setPrefs存储用户登录信息,退出登录清空数据。

//登陆APP

submit() {

var that = this;

var user = that.data.user;

var psw = that.data.psw;

if (!user) {

this.showToast("姓名不能为空");

return;

}

if (!psw) {

this.showToast("密码不能为空");

return;

}


api.showProgress();

const params = {

data: {

values:{

secret: Config.secret,

user:user,

psw:psw

}

}

};

Model.login(params, (res,err) => {

// console.log(JSON.stringify(res));

// console.log(JSON.stringify(err));

if (res && res.flag == "Success") {

that.showToast("提交成功");

api.setPrefs({key:'name',value:res.data.name});

api.setPrefs({key:'userid',value:res.data.id});

api.setPrefs({key:'roleid',value:res.data.role});

api.setPrefs({key:'rolename',value:res.data.rolename});

api.setPrefs({key:'partid',value:res.data.part});

api.setPrefs({key:'partname',value:res.data.partname});

api.setPrefs({key:'username',value:res.data.username});


api.toast({

msg:'登陆成功,欢迎使用'

})


api.sendEvent({

name: 'setuserinfo',

});

api.closeWin();

} else {

that.showToast('登陆失败,请稍后再试');

}

api.hideProgress();

});

},

api.setPrefs设置偏好数据,数据会存储到本地文件系统。api.removePrefs清除本地存储的数据。

loginout(){

api.confirm({

title: '提示',

msg: '确定要退出登录?',

buttons: ['确定', '取消']

}, (ret, err) => {

var index = ret.buttonIndex;

if(index == 1){

//清除用户信息

api.removePrefs({

key: 'name'

});

api.removePrefs({

key: 'userid'

});

api.removePrefs({

key: 'partname'

});

api.removePrefs({

key: 'partid'

});

api.removePrefs({

key: 'role'

});

api.removePrefs({

key: 'rolename'

});

api.removePrefs({

key: 'username'

});


api.toast({

msg:'请重新登陆APP'

})

$util.openWin({

name: 'login',

url: '../user/login.stml',

title: '',

hideNavigationBar:true

});

}

});

}

后台接口

导出word用到了PhpWord,通过composer进行安装,然后再需要调用的地方直接调用,具体使用方法请参代码中示例;其中导出word模板文件有涉及到图片的导出。


<?php

namespace Home\Controller;

use Think\Controller;

class IndexController extends Controller {

//用户登陆

public function login(){

checkscret('secret');//验证授权码

checkdataPost('user');//用户名

checkdataPost('psw');//密码


$user=$_POST['user'];

$psw=$_POST['psw'];


$map['username']=$user;

$map['password']=$psw;


$map['status']='01';//注册之后 需要审核一下


$releaseInfo=M()->table('user')->field('id,name,username,part,role,getrolename(role) rolename,getpartname(part) partname')->where($map)->find();


if($releaseInfo){

returnApiSuccess('查询成功',$releaseInfo);

}

else{

returnApiError('查询失败!');

exit();

}


}

//用户注册

public function register(){

checkscret('secret');//验证授权码

checkdataPost('username');//用户名

checkdataPost('password');//密码


$username=$_POST['username'];

$name=$_POST['name'];

$password=$_POST['password'];

$part=$_POST['part'];


$data['username']=$username;

$data['name']=$name;

$data['password']=$password;

$data['part']=$part;

$data['role']=3;

$data['status']='02';//已注册未审核


$releaseInfo=M()->table('user')->data($data)->add();


if($releaseInfo){

returnApiSuccess('注册成功',$releaseInfo);

}

else{

returnApiError('注册失败!');

exit();

}

}


//基本信息登记

public function addbase(){

checkscret('secret');//验证授权码

checkdataPost('userid');

checkdataPost('partid');


//对应字段

$dwmc=$_POST['dwmc'];

$dwdz=$_POST['dwdz'];

$dwlb=$_POST['dwlb'];

$dwxz=$_POST['dwxz'];

$zgzs=$_POST['zgzs'];

$xfaqzrr_xm=$_POST['xfaqzrr_xm'];

$xfaqzrr_zw=$_POST['xfaqzrr_zw'];

$xfaqzrr_dh=$_POST['xfaqzrr_dh'];

$xfaqglr_xm=$_POST['xfaqglr_xm'];

$xfaqglr_zw=$_POST['xfaqglr_zw'];

$xfaqglr_dh=$_POST['xfaqglr_dh'];

$zjzfhgb_xm=$_POST['zjzfhgb_xm'];

$zjzfhgb_zw=$_POST['zjzfhgb_zw'];

$zjzfhgb_dh=$_POST['zjzfhgb_dh'];

$jzcs=$_POST['jzcs'];

$jzgd=$_POST['jzgd'];

$zjzmj=$_POST['zjzmj'];

$mcjzmj=$_POST['mcjzmj'];

$szcs=$_POST['szcs'];

$yymj=$_POST['yymj'];

$jcsj=$_POST['jcsj'];

$trsysj=$_POST['trsysj'];

$kysj=$_POST['kysj'];

$zlfwhzxm=$_POST['zlfwhzxm'];

$scjyzk=$_POST['scjyzk'];

$lssq=$_POST['lssq'];

$ssyjfl=$_POST['ssyjfl'];

$xfsszljsl=$_POST['xfsszljsl'];

$jcqkdj_1=$_POST['jcqkdj_1'];

$jcqkdj_2=$_POST['jcqkdj_2'];

$jcqkdj_3=$_POST['jcqkdj_3'];

$jcqkdj_4=$_POST['jcqkdj_4'];

$dwlb_qt=$_POST['dwlb_qt'];


$userid=$_POST['userid'];

$partid=$_POST['partid'];


$id=$_POST['id'];


//数据

$data['dwmc']=$dwmc;

$data['dwdz']=$dwdz;

$data['dwlb']=$dwlb;

$data['dwxz']=$dwxz;

$data['zgzs']=$zgzs;

$data['xfaqzrr_xm']=$xfaqzrr_xm;

$data['xfaqzrr_zw']=$xfaqzrr_zw;

$data['xfaqzrr_dh']=$xfaqzrr_dh;

$data['xfaqglr_xm']=$xfaqglr_xm;

$data['xfaqglr_zw']=$xfaqglr_zw;

$data['xfaqglr_dh']=$xfaqglr_dh;

$data['zjzfhgb_xm']=$zjzfhgb_xm;

$data['zjzfhgb_zw']=$zjzfhgb_zw;

$data['zjzfhgb_dh']=$zjzfhgb_dh;

$data['jzcs']=$jzcs;

$data['jzgd']=$jzgd;

$data['zjzmj']=$zjzmj;

$data['mcjzmj']=$mcjzmj;

$data['szcs']=$szcs;

$data['yymj']=$yymj;

$data['jcsj']=$jcsj;

$data['trsysj']=$trsysj;

$data['kysj']=$kysj;

$data['zlfwhzxm']=$zlfwhzxm;

$data['scjyzk']=$scjyzk;

$data['lssq']=$lssq;

$data['ssyjfl']=$ssyjfl;

$data['xfsszljsl']=$xfsszljsl;

$data['jcqkdj_1']=$jcqkdj_1;

$data['jcqkdj_2']=$jcqkdj_2;

$data['jcqkdj_3']=$jcqkdj_3;

$data['jcqkdj_4']=$jcqkdj_4;

$data['dwlb_qt']=$dwlb_qt;


$data['userid']=$userid;

$data['partid']=$partid;

$data['create_time']=time();


if($id){

$map['id']=$id;

//插入数据

$releaseInfo=M()->table('base')->where($map)->save($data);

}

else{

//插入数据

$releaseInfo=M()->table('base')->data($data)->add();

}


if($releaseInfo){

returnApiSuccess('登记成功',$releaseInfo);

}

else{

returnApiError( '登记失败,请稍后再试');

exit();

}

}


//删除登记信息

public function deletebasebyid(){

checkscret('secret');//验证授权码

checkdataPost('id');


$id=$_POST['id'];


$map['id']=$id;


$releaseInfo=M()->table('base')->where($map)->delete();


if($releaseInfo){

returnApiSuccess('删除成功',$releaseInfo);

}

else{

returnApiError('删除失败!');

exit();

}

}


//查询登记单位列表

public function querylist(){

checkscret('secret');//验证授权码

checkdataPost('limit');//下一次加载多少条

checkdataPost('userid');


$limit=$_POST['limit'];

$skip=$_POST['skip'];

if(empty($skip)){

$skip=0;

}


$userid=$_POST['userid'];


$map['userid']=$userid;


$releaseInfo=M()->table('base')->field('id,dwmc as name,dwdz as address,dwlb as type')->where($map)->limit($skip*$limit,$limit)->order('create_time desc')->select();


if($releaseInfo){

returnApiSuccess('查询成功',$releaseInfo);

}

else{

returnApiError('查询失败!');

exit();

}

}


//查询单位基本信息详情

public function querybasebyid(){

checkscret('secret');//验证授权码

checkdataPost('id');//ID


$id=$_POST['id'];


$map['id']=$id;


$releaseInfo=M()->table('base')->where($map)->find();


if($releaseInfo){

returnApiSuccess('查询成功',$releaseInfo);

}

else{

returnApiError('查询失败!');

exit();

}

}


//查询基本信息

public function querybaseinfobyid(){

checkscret('secret');//验证授权码

checkdataPost('id');//ID


$id=$_POST['id'];


$map['id']=$id;


$releaseInfo=M()->table('base')->field('dwmc,dwdz,dwxz,jzgd,jzcs,yymj')->where($map)->find();


if($releaseInfo){

returnApiSuccess('查询成功',$releaseInfo);

}

else{

returnApiError('查询失败!');

exit();

}

}


//导出基本信息表

public function exportbase(){

checkscret('secret');//验证授权码

checkdataPost('id');//ID


$id=$_POST['id'];


$map['id']=$id;


$data=M()->table('base')->where($map)->find();


if ($data) {

require_once "./vendor/autoload.php";

$tmp = new \PhpOffice\PhpWord\TemplateProcessor('./Public/template/temp_base.docx'); //打开模板

$tmp->setValue('dwmc', $data['dwmc']);

$tmp->setValue('dwdz', $data['dwdz']);

$tmp->setValue('dwlb', $data['dwlb']);

$tmp->setValue('dwxz', $data['dwxz']);

$tmp->setValue('zgzs', $data['zgzs']);


$tmp->setValue('xfaqzrr_xm', $data['xfaqzrr_xm']);

$tmp->setValue('xfaqzrr_zw', $data['xfaqzrr_zw']);

$tmp->setValue('xfaqzrr_dh', $data['xfaqzrr_dh']);


$tmp->setValue('xfaqglr_xm', $data['xfaqglr_xm']);

$tmp->setValue('xfaqglr_zw', $data['xfaqglr_zw']);

$tmp->setValue('xfaqglr_dh', $data['xfaqglr_dh']);


$tmp->setValue('zjzfhgb_xm', $data['zjzfhgb_xm']);

$tmp->setValue('zjzfhgb_zw', $data['zjzfhgb_zw']);

$tmp->setValue('zjzfhgb_dh', $data['zjzfhgb_dh']);


$tmp->setValue('jzcs', $data['jzcs']);

$tmp->setValue('jzgd', $data['jzgd']);

$tmp->setValue('zjzmj', $data['zjzmj']);

$tmp->setValue('mcjzmj', $data['mcjzmj']);

$tmp->setValue('kysj', $data['kysj']);

$tmp->setValue('szcs', $data['szcs']);

$tmp->setValue('yymj', $data['yymj']);

$tmp->setValue('jcsj', $data['jcsj']);

$tmp->setValue('trsysj', $data['trsysj']);

$tmp->setValue('zlfwhzxm', $data['zlfwhzxm']);

$tmp->setValue('scjyzk', $data['scjyzk']);

$tmp->setValue('lssq', $data['lssq']);

$tmp->setValue('ssyjfl', $data['ssyjfl']);

$tmp->setValue('xfsszljsl', $data['xfsszljsl']);

$tmp->setValue('jcqkdj_1', $data['jcqkdj_1']);

$tmp->setValue('jcqkdj_2', $data['jcqkdj_2']);

$tmp->setValue('jcqkdj_3', $data['jcqkdj_3']);

$tmp->setValue('jcqkdj_4', $data['jcqkdj_4']);


$tmp->setValue('dwlb_qt', $data['dwlb_qt']);


$tmp->saveAs('./Uploads/九小场所基本情况管理登记表_'.$data['dwmc'].'.docx');

returnApiSuccess('导出成功','http://xiaofang.*********.cn/Uploads/九小场所基本情况管理登记表_'.$data['dwmc'].'.docx');

}

else{

returnApiError('导出失败,请稍后再试!');

exit();

}

}


//消防安全综合治理登记

public function addxfaqzljl(){

checkscret('secret');//验证授权码

checkdataPost('userid');

checkdataPost('partid');


//对应字段

$dwmc=$_POST['dwmc'];

$jcsj=$_POST['jcsj'];

$bjccsmc=$_POST['bjccsmc'];

$bjccsdz=$_POST['bjccsdz'];

$jyz=$_POST['jyz'];

$jyzlxfs=$_POST['jyzlxfs'];

$jzlx=$_POST['jzlx'];

$sfdjjc=$_POST['sfdjjc'];

$sfkf=$_POST['sfkf'];

$djcs=$_POST['djcs'];

$jclb=$_POST['jclb'];

$ltjzcl=$_POST['ltjzcl'];

$sfzr=$_POST['sfzr'];

$jzrs=$_POST['jzrs'];

$jzcs=$_POST['jzcs'];

$zsqysfyaqck=$_POST['zsqysfyaqck'];

$zsqysfytswc=$_POST['zsqysfytswc'];

$zrxs=$_POST['zrxs'];

$hzzdbjxt=$_POST['hzzdbjxt'];

$zdpsmhxt=$_POST['zdpsmhxt'];

$snxfs=$_POST['snxfs'];

$mhq=$_POST['mhq'];

$mhqsl=$_POST['mhqsl'];

$xfssqtqk=$_POST['xfssqtqk'];

$dqxlqk=$_POST['dqxlqk'];

$ddzxcsyqk=$_POST['ddzxcsyqk'];

$sfsymhgwjrqnsbd=$_POST['sfsymhgwjrqnsbd'];

$sfcfyrybwxp=$_POST['sfcfyrybwxp'];

$yrybwxpcfsyqk=$_POST['yrybwxpcfsyqk'];

$sfdqkzxfpx=$_POST['sfdqkzxfpx'];

$ydsh=$_POST['ydsh'];

$yhjzgqk=$_POST['yhjzgqk'];


$userid=$_POST['userid'];

$partid=$_POST['partid'];


$id=$_POST['id'];

$baseid=$_POST['baseid'];


//数据

$data['dwmc']=$dwmc;

$data['jcsj']=$jcsj;

$data['bjccsmc']=$bjccsmc;

$data['bjccsdz']=$bjccsdz;

$data['jyz']=$jyz;

$data['jyzlxfs']=$jyzlxfs;

$data['jzlx']=$jzlx;

$data['sfdjjc']=$sfdjjc;

$data['sfkf']=$sfkf;

$data['djcs']=$djcs;

$data['jclb']=$jclb;

$data['ltjzcl']=$ltjzcl;

$data['sfzr']=$sfzr;

$data['jzrs']=$jzrs;

$data['jzcs']=$jzcs;

$data['zsqysfyaqck']=$zsqysfyaqck;

$data['zsqysfytswc']=$zsqysfytswc;

$data['zrxs']=$zrxs;

$data['hzzdbjxt']=$hzzdbjxt;

$data['zdpsmhxt']=$zdpsmhxt;

$data['snxfs']=$snxfs;

$data['mhq']=$mhq;

$data['mhqsl']=$mhqsl;

$data['xfssqtqk']=$xfssqtqk;

$data['dqxlqk']=$dqxlqk;

$data['ddzxcsyqk']=$ddzxcsyqk;

$data['sfsymhgwjrqnsbd']=$sfsymhgwjrqnsbd;

$data['sfcfyrybwxp']=$sfcfyrybwxp;

$data['yrybwxpcfsyqk']=$yrybwxpcfsyqk;

$data['sfdqkzxfpx']=$sfdqkzxfpx;

$data['ydsh']=$ydsh;

$data['yhjzgqk']=$yhjzgqk;


$data['baseid']=$baseid;


$data['userid']=$userid;

$data['partid']=$partid;

$data['create_time']=time();


//保存文件

$upload = new \Think\Upload(); // 实例化上传类

$upload->rootPath = './Uploads/'; // 设置附件上传根目录

$upload->saveName = array('uniqid', mt_rand(1,999999).'_'.md5(uniqid())); // 自定义图片重命名

$upload->exts = array('jpg', 'jpeg' ,'png'); // 设置附件上传类型 只允许照片

// 上传文件

$uploadinfo = $upload->upload();


if($uploadinfo){

if($uploadinfo['file1']['savepath'] && $uploadinfo['file1']['savename']){

$data['signature_check']="/Uploads/".$uploadinfo['file1']['savepath'].$uploadinfo['file1']['savename'];

}

if($uploadinfo['file2']['savepath'] && $uploadinfo['file2']['savename']){

$data['signature_bcheck']="/Uploads/".$uploadinfo['file2']['savepath'].$uploadinfo['file2']['savename'];

}

}


if($id){

$map['id']=$id;

//插入数据

$releaseInfo=M()->table('zhzljl')->where($map)->save($data);

}

else{

//插入数据

$releaseInfo=M()->table('zhzljl')->data($data)->add();

}


if($releaseInfo){

returnApiSuccess('登记成功',$releaseInfo);

}

else{

returnApiError( '登记失败,请稍后再试');

exit();

}

}


//查询综合检查记录

public function queryxfaqzljlyid(){

checkscret('secret');//验证授权码

checkdataPost('baseid');


$baseid=$_POST['baseid'];


$map['baseid']=$baseid;


$releaseInfo=M()->table('zhzljl')->where($map)->find();


if($releaseInfo){

returnApiSuccess('查询成功',$releaseInfo);

}

else{

returnApiError( '查询失败,请稍后再试');

exit();

}

}


//导出

public function exportxfaqzljl(){

checkscret('secret');//验证授权码

checkdataPost('id');//ID


$id=$_POST['id'];


$map['id']=$id;


$data=M()->table('xf_zhzljl')->where($map)->find();


if ($data) {

require_once "./vendor/autoload.php";

$tmp = new \PhpOffice\PhpWord\TemplateProcessor('./Public/template/temp_zljl.docx'); //打开模板

$tmp->setValue('dwmc', $data['dwmc']);

$tmp->setValue('jcsj', $data['jcsj']);

$tmp->setValue('bjccsmc', $data['bjccsmc']);

$tmp->setValue('bjccsdz', $data['bjccsdz']);

$tmp->setValue('jyz', $data['jyz']);

$tmp->setValue('jyzlxfs', $data['jyzlxfs']);

$tmp->setValue('jzlx', $data['jzlx']);

$tmp->setValue('sfdjjc', $data['sfdjjc']);

$tmp->setValue('djcs', $data['djcs']);

$tmp->setValue('sfkf', $data['sfkf']);

$tmp->setValue('jclb', $data['jclb']);

$tmp->setValue('ltjzcl', $data['ltjzcl']);

$tmp->setValue('sfzr', $data['sfzr']);

$tmp->setValue('jzrs', $data['jzrs']);

$tmp->setValue('jzcs', $data['jzcs']);

$tmp->setValue('zsqysfyaqck', $data['zsqysfyaqck']);

$tmp->setValue('zsqysfytswc', $data['zsqysfytswc']);

$tmp->setValue('zrxs', $data['zrxs']);


$tmp->setValue('hzzdbjxt', $data['hzzdbjxt']);

$tmp->setValue('zdpsmhxt', $data['zdpsmhxt']);

$tmp->setValue('snxfs', $data['snxfs']);

$tmp->setValue('mhq', $data['mhq']);

$tmp->setValue('mhqsl', $data['mhqsl']);

$tmp->setValue('xfssqtqk', $data['xfssqtqk']);


$tmp->setValue('dqxlqk', $data['dqxlqk']);

$tmp->setValue('ddzxcsyqk ', $data['ddzxcsyqk']);

$tmp->setValue('sfsymhgwjrqnsbd', $data['sfsymhgwjrqnsbd']);

$tmp->setValue('sfcfyrybwp', $data['sfcfyrybwxp']);

$tmp->setValue('yrybwxpcfsyqk', $data['yrybwxpcfsyqk']);

$tmp->setValue('sfdqkzxfpx', $data['sfdqkzxfpx']);

$tmp->setValue('ydsh', $data['ydsh']);

$tmp->setValue('yhjzgqk', $data['yhjzgqk']);


$tmp->setImageValue('signature_check', ['path' => '.'.$data['signature_check'], 'width' => 120, 'height' => 20]);

$tmp->setImageValue('signature_bcheck', ['path' => '.'.$data['signature_bcheck'], 'width' => 120, 'height' => 20]);


$tmp->saveAs('./Uploads/合用场所消防安全综合治理记录表_'.$data['bjccsmc'].'.docx');

returnApiSuccess('导出成功','http://xiaofang.********.cn/Uploads/合用场所消防安全综合治理记录表_'.$data['bjccsmc'].'.docx');

}

else{

returnApiError('导出失败,请稍后再试!');

exit();

}

}


//添加基本信息照片

public function addbasepicbyid(){

checkscret('secret');//验证授权码

checkdataPost('baseid');

checkdataPost('type');


$baseid=$_POST['baseid'];

$type=$_POST['type'];


$map['baseid']=$baseid;


$data['baseid']=$baseid;


//保存文件

$upload = new \Think\Upload(); // 实例化上传类

$upload->rootPath = './Uploads/'; // 设置附件上传根目录

$upload->saveName = array('uniqid', mt_rand(1,999999).'_'.md5(uniqid())); // 自定义图片重命名

$upload->exts = array('jpg', 'jpeg' ,'png'); // 设置附件上传类型 只允许照片

// 上传文件

$uploadinfo = $upload->upload();


if($uploadinfo){

if($type=='01'){

$data['mt']="/Uploads/".$uploadinfo['file']['savepath'].$uploadinfo['file']['savename'];

}

else if($type=='02'){

$data['yyzz']="/Uploads/".$uploadinfo['file']['savepath'].$uploadinfo['file']['savename'];

}

else if($type=='03'){

$data['dlqk']="/Uploads/".$uploadinfo['file']['savepath'].$uploadinfo['file']['savename'];

}

else if($type=='04'){

$data['sfz']="/Uploads/".$uploadinfo['file']['savepath'].$uploadinfo['file']['savename'];

}

}

$data['create_time']=time();


if($this->checkbasepic($baseid)){

$releaseInfo=M()->table('basepic')->where($map)->save($data);

}

else{

$releaseInfo=M()->table('basepic')->data($data)->add();

}


if($releaseInfo){

returnApiSuccess('添加成功',"http://xiaofang.******.cn/Uploads/".$uploadinfo['file']['savepath'].$uploadinfo['file']['savename']);

}

else{

returnApiError('添加失败!');

exit();

}

}


function checkbasepic($baseid){

$map['baseid']=$baseid;


$ret=M()->table('basepic')->where($map)->find();


if($ret){

return true;

}

else{

return false;

}

}

}

目录
相关文章
|
6月前
|
传感器 人工智能 监控
Uni-app智慧工地数据大屏可视化监管平台源码带APP
智慧工地的核心是数字化,它通过传感器、监控设备、智能终端等技术手段,实现对工地各个环节的实时数据采集和传输,如环境温度、湿度、噪音等数据信息,将数据汇集到云端进行处理和分析,生成各种报表、图表和预警信息,帮助管理人员了解工地的实时状况,及时做出决策和调整,
168 0
|
6月前
|
人工智能 监控 安全
java基于微服务架构的智慧工地监管平台源码带APP
劳务管理: 工种管理、分包商管理、信息采集、班组管理、花名册、零工采集、 现场统计、考勤管理、考勤明细、工资管理、零工签证
319 4
|
6月前
|
人工智能 监控 数据可视化
Java智慧工地可视化APP信息管理平台源码
利用物联网、云计算等先进信息化技术手段,实时掌握施工工地全方位的现场情况,提高数据获取的准确性、及时性、真实性和响应速度。
85 3
|
5月前
|
开发框架 移动开发 JavaScript
SpringCloud微服务实战——搭建企业级开发框架(四十七):【移动开发】整合uni-app搭建移动端快速开发框架-添加Axios并实现登录功能
在uni-app中,使用axios实现网络请求和登录功能涉及以下几个关键步骤: 1. **安装axios和axios-auth-refresh**: 在项目的`package.json`中添加axios和axios-auth-refresh依赖,可以通过HBuilderX的终端窗口运行`yarn add axios axios-auth-refresh`命令来安装。 2. **配置自定义常量**: 创建`project.config.js`文件,配置全局常量,如API基础URL、TenantId、APP_CLIENT_ID和APP_CLIENT_SECRET等。
217 60
|
4月前
|
JSON 前端开发 API
移动端---------app开发03----apicloud必须掌握的代码
移动端---------app开发03----apicloud必须掌握的代码
|
4月前
|
前端开发 开发者
移动端-------app开发02,了解apicloud功能和使用,真机测试
移动端-------app开发02,了解apicloud功能和使用,真机测试
|
5月前
|
前端开发 小程序
新版校园跑腿外卖独立版+APP+小程序前端外卖配送平台源码
同城校园跑腿外卖配送平台源码,支持自定义diy 你可以设计你的页面,设计你自己的风格,支持多校园,独立版本,多商户,有用户端,骑手端,商家端,强大的功能
185 3
|
6月前
|
开发框架 移动开发 JavaScript
SpringCloud微服务实战——搭建企业级开发框架(四十六):【移动开发】整合uni-app搭建移动端快速开发框架-环境搭建
正如优秀的软件设计一样,uni-app把一些移动端常用的功能做成了独立的服务或者插件,我们在使用的时候只需要选择使用即可。但是在使用这些服务或者插件时一定要区分其提供的各种服务和插件的使用场景,例如其提供的【uni-starter快速开发项目模版】几乎集成了移动端所需的所有基础功能,使用非常方便,但是其许可协议只允许对接其uniCloud的JS开发服务端,不允许对接自己的php、java等其他后台系统。
301 61
|
6月前
|
监控 数据可视化 安全
智慧工地SaaS可视化平台源码,PC端+APP端,支持二开,项目使用,微服务+Java++vue+mysql
环境实时数据、动态监测报警,实时监控施工环境状态,有针对性地预防施工过程中的环境污染问题,打造文明生态施工,创造绿色的生态环境。
60 0
智慧工地SaaS可视化平台源码,PC端+APP端,支持二开,项目使用,微服务+Java++vue+mysql
|
6月前
|
前端开发 Android开发 iOS开发
应用研发平台EMAS使用 aliyun-react-native-push 库接入推送和辅助通道,推送都可以收到,但是在App切到后台或者杀掉进程之后就收不到推送了,是需要配置什么吗?
【2月更文挑战第31天】应用研发平台EMAS使用 aliyun-react-native-push 库接入推送和辅助通道,推送都可以收到,但是在App切到后台或者杀掉进程之后就收不到推送了,是需要配置什么吗?
114 2