使用APICloud AVM框架开发预约应用

Posted 蒙特卡洛法

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用APICloud AVM框架开发预约应用相关的知识,希望对你有一定的参考价值。

前段时间跟朋友一起搞了一个预约的项目,前端用的APICloud的AVM框架做的,后端用的php开发的,用的tp5框架,没几天就搞出来了。简单跟大家分享一下开发中的一些功能点的实现吧。也欢迎大家一起探讨。


一、整理项目脑图

使用APICloud


二、项目原型图

原型是用的码前做的,大家可以通过​​www.devbefore.com/protomobile/47942983009476608​​查看


三、项目前端

本项目中前端采用APICloud AVM多端开发技术进行开发,要点包括 swiper 轮播图、网络请求封装等。使用 APICloud 多端技术进行开发,实现一套代码多端运行,支持编译成 android & ios App 以及微信小程序。


1、APICloud使用步骤:

(1)下载 APICloud Studio 3 作为开发工具。下载地址:​​​www.apicloud.com/studio3​​​

(2)注册账号后在控制台创建app,控制台地址:​​www.apicloud.com/console​

使用APICloud

(3)设置证书,一键创建安卓证书

使用APICloud

(4)APICloud Studio3 拉取代码,点击项目,导出云端检出

使用APICloud

检出

使用APICloud

检出后工作目录

(5)修改或者提交项目源码,并为当前项目云编译自定义 Loader 进行真机同步调试预览。

使用 AppLoader 进行真机同步调试预览,后台自动以loader下载到手机端,安装后,点击小圆圈,输入ip地址:192.168.2.152 端口:10916,连接后真机同步,可以看到刚创建后的结果。

使用APICloud

使用APICloud

使用APICloud


2、AVM框架的使用

为什么选择AVM?

  • 易用:有 Vue、React 基础,可快速上手,配套专用的开发工具APICloud Studio3。
  • 多端:一次开发,多端渲染,一个技术栈搞定移动端开发。
  • 功能 API 丰富:提供 1千+ 模块和 2万+ API 可直接调用,面向行业和场景无限制)


(1)UI

官方文档:​​https://docs.apicloud.com/apicloud3/#/component/view?index=4&subIndex=0​

原来有一个叫流浪男的做的AUI框架,还不错,后来就是用一些简单的大公司的框架,这个看自己了。好多UI都是自己设计,自己写一些UI。字体图标用的阿里字体图标。CSS框架,要是没啥选择推荐可以用AUI,这个框架有CSS基础的一看就知道写的啥,而且特别好修改。实在不行了直接改源码。

APICloud官网组装了一套vant的,​​https://docs.apicloud.com/Client-API/AVM-Components/readme.md​


(2)ajax网络交互

// 表单方式提交数据或文件

// 表单方式提交数据或文件
api.ajax(
url: http://192.168.1.101:3101/upLoad,
method: post,
data:
values:
name: haha
,
files:
file: fs://a.gif


, function(ret, err)
if (ret)
api.alert( msg: JSON.stringify(ret) );
else
api.alert( msg: JSON.stringify(err) );

);

// 提交JSON数据
api.ajax(
url: http://192.168.1.101:3101/upLoad,
method: post,
headers:
Content-Type: application/json;charset=utf-8
,
data:
body:
name: haha


, function(ret, err)
if (ret)
api.alert( msg: JSON.stringify(ret) );
else
api.alert( msg: JSON.stringify(err) );

);


(3)vue指令使用(v-for v-show v-if v-else v-for v-on v-bind v-model等)

1>数据绑定

使用 Mustache 语法:

<text text=msg></text>

使用v-bind指令:

<text v-bind:text="msg"></text>

2>事件绑定

<template>
<text onclick="doThis(avm);">Click me!</text>
</template>
<script>
export default
name: test,
methods:
doThis(msg)
api.alert(
msg: msg
);



</script>


(4)注册、登录

1>注册接口链接:​​http://showdoc.deui.cn/web/#/27?page_id=365​

注册代码

<template name=tpl>
<view class="page">
<div class="page1">
<safe-area class="header">
<!-- <text class="header__title">APICloud</text> -->
</safe-area>
<scroll-view class="main">
<view>
<image src="https://baodinglingqian.oss-cn-beijing.aliyuncs.com/1.png" class="touxiang " />
</view>

<div class="zhanghao">
<input placeholder="请输入账号" v-model="zhanghao" maxlength="10" autofocus />
</div>

<div class="mima">
<input type="password" placeholder="请输入密码" v-model="password" />
</div>

<text class="zhuce" @click="reg()">注册</text>
<text class="denglu" @click="handleClick()">登录</text>
</scroll-view>
</div>
<image class="originImage" mode="scaleToFill" src=src></image>

</view>
</template>
<script>
export default
name: "tpl",
apiready()
api.setStatusBarStyle(
style: "light",
color: "-"
);
,
data()
return
zhanghao: ,
password: ,
src: "https://baodinglingqian.oss-cn-beijing.aliyuncs.com/bg.png"
;
,
computed:

,
methods:
handleClick(e)
api.openWin(
name: main,
url: ./main.stml,
pageParam:
name: test

);
,
reg()
var _this = this;
// 提交JSON数据
api.ajax(
url: http://yy.deui.cn/api.php/index/re,
method: get,
// headers:
// Content-Type: application/json;charset=utf-8
// ,
data:
body:
username: _this.zhanghao,
password: _this.password


, function (ret, err)

console.log(JSON.stringify(ret))
if (ret.msg == 返回成功)
api.toast(
msg: 注册成功,
location: "middle"
);
else
api.alert( msg: JSON.stringify(err) );

);


;
</script>
<style>
.denglu
margin-top: 10px;
font-size: 14px;

.touxiang
margin-top: 10%;
width: 150px;
height: 150px;
border-radius: 100px;
margin: 0 auto;

html
width: 100%;
height: 100%;

body
width: 100%;
height: 100%;

.originImage
position: absolute;
top: 0px;
left: 0px;
right: 0px;
bottom: 0px;
z-index: 1;

.page
/* position:fixed; */
position: relative;
z-index: 9;
width: 100%;
height: 100%;

.page1
position: absolute;
top: 0px;
left: 0px;
right: 0px;
bottom: 0px;
z-index: 2;

input
padding-left: 10px;
line-height: 35px;
height: 35px;
border-radius: 5px;

.zhanghao
display: block;
margin: 0 auto;
margin-top: 15%;
margin-bottom: 15px;
height: 60px;

.mima
display: block;
margin: 0 auto;
margin-top: 25px;

.zhuce
width: 100%;
height: 35px;
line-height: 35px;
background-color: coral;
text-align: center;
color: #fff;
margin-top: 25px;

.page
height: 100%;
background-color: white;

.header
background: #81a9c3;
justify-content: center;
align-items: center;

.header__title
color: #fff;
font-size: 18px;
font-weight: bold;
height: 50px;
line-height: 50px;


.main
flex: 1;
padding: 15px;


.h1
font-size: 24px;


.item
flex-direction: row;
padding: 10px 0;

.item__text
color: #333;
white-space: nowrap;


.item__value
margin-left: 5px;


.footer
background: #81a9c3;
flex-direction: row;
justify-content: center;
align-items: center;


.footer__text
color: #fff;
font-size: 14px;
height: 30px;
line-height: 30px;

</style>

使用APICloud

2>登录接口链接:​​http://showdoc.deui.cn/web/#/27?page_id=364​

登录代码

<template name=tpl>
<view class="page">
<div class="page1">
<safe-area class="header">
<!-- <text class="header__title">APICloud</text> -->
</safe-area>
<scroll-view class="main">
<view>
<image src="https://baodinglingqian.oss-cn-beijing.aliyuncs.com/1.png" class="touxiang " />
</view>

<div class="zhanghao">
<input placeholder="请输入账号" v-model="zhanghao" maxlength="10" autofocus />
</div>

<div class="mima">
<input type="password" placeholder="请输入mima" v-model="password" />
</div>

<text class="zhuce" @click="login()">登录</text>
<text class="denglu" @click="handleClick()">注册</text>
</scroll-view>
</div>
<image class="originImage" mode="scaleToFill" src=src></image>

</view>
</template>
<script>
export default
name: "tpl",
apiready()
api.setStatusBarStyle(
style: "light",
color: "-"
);
var value = localStorage.getItem(uid);
api.openWin(
name: home,
url: ./home.stml
);
,
data()
return
zhanghao: ,
password: ,
src: "https://baodinglingqian.oss-cn-beijing.aliyuncs.com/bg.png"
;
,
computed:

,
methods:
handleClick(e)
api.openWin(
name: region,
url: ./region.stml,
pageParam:
name: test

);
// api.toast(
// msg: this.data.text,
// location: "middle"
// );
,
login()
var _this = this;
api.ajax(
url: http://yy.deui.cn/api.php/index/login,
method: get,
// headers:
// Content-Type: application/json;charset=utf-8
// ,
data:
body:
username: _this.zhanghao,
password: _this.password


, function (ret, err)
console.log(JSON.stringify(ret))

localStorage.setItem(uid, ret.data.data[0][id]);

if (ret.msg == 返回成功)
api.toast(
msg: 登录成功,
location: "middle"
);

api.openWin(
name: home,
url: ./home.stml
);
else
api.alert( msg: JSON.stringify(err) );

);



;
</script>
<style>
.denglu
margin-top: 10px;
font-size: 14px;

.touxiang
margin-top: 10%;
width: 150px;
height: 150px;
border-radius: 100px;
margin: 0 auto;

html
width: 100%;
height: 100%;

body
width: 100%;
height: 100%;

.originImage
position: absolute;
top: 0px;
left: 0px;
right: 0px;
bottom: 0px;
z-index: 1;

.page
/* position:fixed; */
position: relative;
z-index: 9;
width: 100%;
height: 100%;

.page1
position: absolute;
top: 0px;
left: 0px;
right: 0px;
bottom: 0px;
z-index: 2;

input
padding-left: 10px;
line-height: 35px;
height: 35px;
border-radius: 5px;

.zhanghao
display: block;
margin: 0 auto;
margin-top: 15%;
margin-bottom: 15px;
height: 60px;

.mima
display: block;
margin: 0 auto;
margin-top: 25px;

.zhuce
width: 100%;
height: 35px;
line-height: 35px;
background-color: coral;
text-align: center;
color: #fff;
margin-top: 25px;

.page
height: 100%;
background-color: white;

.header
background: #81a9c3;
justify-content: center;
align-items: center;

.header__title
color: #fff;
font-size: 18px;
font-weight: bold;
height: 50px;
line-height: 50px;


.main
flex: 1;
padding: 15px;


.h1
font-size: 24px;


.item
flex-direction: row;
padding: 10px 0;

.item__text
color: #333;
white-space: nowrap;


.item__value
margin-left: 5px;


.footer
background: #81a9c3;
flex-direction: row;
justify-content: center;
align-items: center;


.footer__text
color: #fff;
font-size: 14px;
height: 30px;
line-height: 30px;

</style>

使用APICloud

(5)首页轮播图

轮播图链接:​​http://showdoc.deui.cn/web/#/27?page_id=366​

<template name=tpl>
<view class="page">
<div class="page1">
<safe-area class="header">
<text class="header__title">首页</text>
</safe-area>
<scroll-view class="main" scroll-y>
<swiper class="swiper" id="customSwiper" autoplay circular indicator-dots indicator-color="#ddd"
indicator-active-color="#f0f">
<swiper-item class="swiper-item" v-for="(_item,_index) in bannerlist">
<!-- <text class="desc">_item.image</text> -->
<image mode="scaleToFill" src=_item.image></image>
</swiper-item>
</swiper>
<div>
<a-cell-group>
<a-cell v-bind:title="_item.name" v-bind:value="_item.content" v-bind:label="_item.address"
arrow-direction="right" @click="godetial(_item)" v-for="(_item,_index) in shangjialist" />
<!-- <a-cell title="单元格" value="内容" label="描述信息" /> -->
</a-cell-group>
</div>
</scroll-view>
</div>
<image class="originImage" mode="scaleToFill" src=src></image>
</view>
</template>
<script>
import ACellGroup from "../../components/act/a-cell-group";
import ACell from "../../components/act/a-cell";
export default
name: test,
data()
return
shangjialist: [],
bannerlist: [],
current: 0,
src: "https://baodinglingqian.oss-cn-beijing.aliyuncs.com/bg.png"

,
methods:
apiready()
this.banner()
this.allstores()
// var customSwiper = document.getElementById(customSwiper);
// customSwiper.load(
// data: this.data.dataList
// );
,
onchange(e)
this.data.current = e.detail.current;
,
godetial(item)
console.log(JSON.stringify(item))
api.openWin(
name: detial,
url: ./detial.stml,
pageParam:
id: item.id

);
,
banner()
var _this = this;
api.ajax(
url: http://yy.deui.cn/api.php/index/banner,
method: get,
, function (ret, err)
if (ret.msg == 返回成功)
_this.data.bannerlist = ret.data.data
// var customSwiper = document.getElementById(customSwiper);
// customSwiper.load(
// data: _this.data.bannerlist
// );
// console.log(JSON.stringify(_this.bannerlist))
else
api.alert( msg: JSON.stringify(err) );

);
,
allstores()
var _this = this;
api.ajax(
url: http://yy.deui.cn/api.php/index/stores,
method: get,
, function (ret, err)
if (ret.msg == 返回成功)
console.log(1)
console.log(JSON.stringify(ret.data.data))
console.log(1)
var obj = ret.data.data
for (let index = 0; index < obj.length; index++)
const element = obj[index];
element[content] = element[content].substring(0, 9) + ...

console.log(JSON.stringify(obj))
_this.data.shangjialist = obj
else
api.alert( msg: JSON.stringify(err) );

);



</script>
<style>
.denglu
margin-top: 10px;
font-size: 14px;

.touxiang
margin-top: 10%;
width: 150px;
height: 150px;
border-radius: 100px;
margin: 0 auto;

html
width: 100%;
height: 100%;

body
width: 100%;
height: 100%;

.originImage
position: absolute;
top: 0px;
left: 0px;
right: 0px;
bottom: 0px;
z-index: 1;

.page
/* position:fixed; */
position: relative;
z-index: 9;
width: 100%;
height: 100%;

.page1
position: absolute;
top: 0px;
left: 0px;
right: 0px;
bottom: 0px;
z-index: 2;

input
padding-left: 10px;
line-height: 35px;
height: 35px;
border-radius: 5px;

.zhanghao
display: block;
margin: 0 auto;
margin-top: 15%;
margin-bottom: 15px;
height: 60px;

.mima
display: block;
margin: 0 auto;
margin-top: 25px;

.zhuce
width: 100%;
height: 35px;
line-height: 35px;
background-color: coral;
text-align: center;
color: #fff;
margin-top: 25px;

.page
height: 100%;
background-color: white;

.header
background: #81a9c3;
justify-content: center;
align-items: center;

.header__title
color: #fff;
font-size: 18px;
font-weight: bold;
height: 50px;
line-height: 50px;


.main
flex: 1;
padding: 0px;


.h1
font-size: 24px;


.item
flex-direction: row;
padding: 10px 0;

.item__text
color: #333;
white-space: nowrap;


.item__value
margin-left: 5px;


.footer
background: #81a9c3;
flex-direction: row;
justify-content: center;
align-items: center;


.footer__text
color: #fff;
font-size: 14px;
height: 30px;
line-height: 30px;

.main
width: 100%;
height: 100%;

.swiper
width: 100%;
height: 190px;
/* background-color: blue; */

.swiper-item
justify-content: center;

.title
padding: 10px 0;
font-size: 20px;

.desc
width: 100%;
text-align: center;

.container
width: 100%;
height: 200px;

.indicator
flex-direction: row;
justify-content: center;
position: absolute;
width: 100%;
height: 20px;
bottom: 8px;

.indicator-item
width: 15px;
height: 8px;
margin: 3px;

.indicator-item-normal
background-color: #ddd;

.indicator-item-active
background-color: red;

</style>


(6)首页列表

所有店铺链接:​​http://showdoc.deui.cn/web/#/27?page_id=369​

上面的5的代码里面含有了。

<a-cell-group>
<a-cell v-bind:title="_item.name" v-bind:value="_item.content" v-bind:label="_item.address" arrow-direction="right" @click="godetial(_item)" v-for="(_item,_index) in shangjialist" />
</a-cell-group>

shangjialist: [],
allstores()
var _this = this;
api.ajax(
url: http://yy.deui.cn/api.php/index/stores,
method: get,
, function (ret, err)
if (ret.msg == 返回成功)
console.log(1)
console.log(JSON.stringify(ret.data.data))
console.log(1)
var obj = ret.data.data
for (let index = 0; index < obj.length; index++)
const element = obj[index];
element[content] = element[content].substring(0, 9) + ...

console.log(JSON.stringify(obj))
_this.data.shangjialist = obj
else
api.alert( msg: JSON.stringify(err) );

);

使用APICloud


(7)页面传参获取详情

api.openWin(
name: detial,
url: ./detial.stml,
pageParam:
id: 123

);

apiready() //like created
if (api.pageParam.id)
this.data.id = api.pageParam.id

console.log(this.data.id)

店铺详情:​​http://showdoc.deui.cn/web/#/27?page_id=370​

<template>
<view class="page">
<view>
<a-nav-bar v-bind:title="title" left-text="返回" left-arrow @click-left="onClickLeft"
@click-right="onClickRight" />
</view>
<view>
<a-cell-group>
<a-cell title="名称" v-bind:value="store.name" />
<a-cell title="电话" v-bind:value="store.phone" />
<a-cell title="城市" v-bind:value="store.city" />
<a-cell title="地址" v-bind:value="store.address" />
<a-cell title="内容" v-bind:value="store.content" />
</a-cell-group>
<!-- <text text=store.name></text>
<text text=store.city></text>
<text text=store.content></text>
<text text=store.address></text>
<text text=store.phone></text> -->
</view>
<view>
<a-button type="success">产品</a-button>
</view>
<view>
<a-cell-group>
<a-cell v-bind:title="_item.name" v-bind:value="_item.content" label="点击可预约" v-for="(_item,_index) in product" @click="yuyuproduct(_item)" />
</a-cell-group>
</view>
</view>
</template>
<script>
import ACellGroup from "../../components/act/a-cell-group";
import ACell from "../../components/act/a-cell";
import ANavBar from "../../components/act/a-nav-bar";
import AButton from "../../components/act/a-button";
export default
name: detial,
apiready() //like created
if (api.pageParam.id)
this.data.id = api.pageParam.id

console.log(this.data.id)
this.init()
,
data()
return
title: "详情",
id: 1,
store: ,
product:[]

,
methods:
init()
var _this = this;
api.ajax(
url: http://yy.deui.cn/api.php/index/searchstore,
method: get,
data:
body:
id: _this.data.id


, function (ret, err)
if (ret.msg == 返回成功)
console.log(1)
console.log(JSON.stringify(ret.data.product))
console.log(1)
_this.data.store = ret.data.data[0]
_this.data.product = ret.data.product
else
api.alert( msg: JSON.stringify(err) );

);
,
yuyuproduct(_item)
console.log(JSON.stringify(_item))
,
onClickLeft()
api.closeWin();
,
onClickRight()




</script>
<style>
.page
height: 100%;

</style>


(8)导航栏组件

import ANavBar from "../../components/act/a-nav-bar";

<view>

<a-nav-bar v-bind:title="title" left-text="返回" left-arrow @click-left="onClickLeft"

@click-right="onClickRight" />

</view>

注意:导航栏组件的使用,文档中的引用

import ACell from"../../components/act/a-nav-bar.stml";

使用中建议去掉stml后缀,import ACell from"../../components/act/a-nav-bar";

使用APICloud


(9)localStorage 对象使用

main.stml里面的这个,就是用的这个对象

localStorage.setItem(uid, ret.data.data[0][id]);

下面是localStorage的用法

// 设置存储.
sessionStorage.setItem(key, value);

// 获取存储.
var value = sessionStorage.getItem(key);

// 移除存储
sessionStorage.removeItem(key);

// 清除所有存储项
sessionStorage.clear();

// 获取已有存储项数
var length = sessionStorage.length;

// 根据存储项索引获取存储键名
var keyName = sessionStorage.key(index);


(10)APICloud组件、模块的使用

模块中添加模块,如果是H5的需要下载后,放到自己的代码中;如果是原生的模块,需要添加到自己应用中,去require去使用。网上有专门介绍这块的教程,不清楚的可以去搜搜。

使用APICloud


四、项目后台

这块是自己写的php后台,用的tp5框架。

使用APICloud

tp5下的fastadmin框架,可以根据fastadmin一键生成简单后台,数据库文件为:

后台接口代码

<?php

namespace app\\api\\controller;

use app\\common\\controller\\Api;
use think\\Db;
/**
* 首页接口
*/
class Index extends Api

protected $noNeedLogin = [*];
protected $noNeedRight = [*];

/**
* 首页
*
*/
public function index()

$this->success(请求成功);

//注册
public function re()
$username = $this->request->request("username");
$password = md5($this->request->request("password"));
$sql = " INSERT INTO `yuyuuser` (`id`, `group_id`, `username`, `nickname`, `password`, `salt`, `email`, `mobile`, `avatar`, `level`, `gender`, `birthday`, `bio`, `money`, `score`, `successions`, `maxsuccessions`, `prevtime`, `logintime`, `loginip`, `loginfailure`, `joinip`, `jointime`, `createtime`, `updatetime`, `token`, `status`, `verification`) VALUES (NULL, 0, , ".$username .", ".$password.", , , , , 0, 0, NULL, , 0.00, 0, 1, 1, NULL, NULL, , 0, , NULL, NULL, NULL, , , )";
$rst = Db::query($sql);
$data =1;
$this->success(返回成功, [data => $data]);

//登录
public function login()
$username = $this->request->request("username");
$password = md5($this->request->request("password"));
$sql = "SELECT nickname,id FROM yuyuuser where nickname=".$username." and password=".$password." order by id DESC LIMIT 1";
$rst = Db::query($sql);
$this->success(返回成功, [data => $rst]);

//获取轮播图
public function banner()

$sql = "SELECT * FROM `yuyubanner`";
$rst = Db::query($sql);
$this->success(返回成功, [data => $rst]);

//获取网络协议
public function xieyi()

$sql = "SELECT * FROM `yuyuxieyi`";
$rst = Db::query($sql);
$this->success(返回成功, [data => $rst]);

//所有类型
public function leixing()

$sql = " SELECT * FROM `yuyutype`";
$rst = Db::query($sql);
$this->success(返回成功, [data => $rst]);

//所有店面
public function stores()

$sql = " SELECT * FROM `yuyustore`";
$rst = Db::query($sql);
$this->success(返回成功, [data => $rst]);

//店铺信息
public function searchstore()

$id = $this->request->request("id");
$sql = " SELECT * FROM `yuyustore` where id = ".$id;
$sql1 = "SELECT * FROM `yuyuproduct` where store_id = ".$id;

$rst = Db::query($sql);
$rst1 = Db::query($sql1);

$this->success(返回成功, [data => $rst,product=>$rst1]);



以上是关于使用APICloud AVM框架开发预约应用的主要内容,如果未能解决你的问题,请参考以下文章

使用APICloud AVM多端框架开发课程表功能

APICloud AVM框架列表组件list-view的使用flex布局教程

使用APICloud AVM多端框架开发消防检查助手App项目实践分享

使用APICloud AVM框架封装通讯录组件

前端如何低门槛开发iOSAndroid小程序多端应用

使用APICloud AVM多端组件快速实现app中的搜索功能