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

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

一、整理项目脑图

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

二、项目原型图

原型是用的码前做的,大家可以通过​​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 AVM框架开发预约应用

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

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

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

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

检出

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

检出后工作目录

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

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

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

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

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

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 AVM框架开发预约应用

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 AVM框架开发预约应用

(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 AVM框架开发预约应用

(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”;

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

@click-right=“onClickRight” />

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

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

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

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

(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 AVM框架开发预约应用

四、项目后台

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

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

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框架做的,后端用的php开发的,用的tp5框架,没几天就搞出来了。简单跟大家分享一下开发中的一些功能点的实现吧。也欢迎大家一起探讨。

一、整理项目脑图

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

二、项目原型图

原型是用的码前做的,大家可以通过​​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 AVM框架开发预约应用

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

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

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

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

检出

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

检出后工作目录

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

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

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

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

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

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 AVM框架开发预约应用

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 AVM框架开发预约应用

(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 AVM框架开发预约应用

(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”;

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

@click-right=“onClickRight” />

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

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

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

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

(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 AVM框架开发预约应用

四、项目后台

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

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

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]);
    }
}
上一篇:html网页鼠标样式、css精灵、iconfont、过渡动画笔记


下一篇:9.【学成在线案例】