作者 李忠强

更新

  1 +{"files":[],"license":"regular","licenseto":"10789","licensekey":"89rbzyMwR7egBFAo EyUfEJxJ9VFzYuZOURRwgg==","domains":[],"licensecodes":[],"validations":[]}
  1 +<?php
  2 +
  3 +namespace addons\address;
  4 +
  5 +use think\Addons;
  6 +
  7 +/**
  8 + * 地址选择
  9 + * @author [MiniLing] <[laozheyouxiang@163.com]>
  10 + */
  11 +class Address extends Addons
  12 +{
  13 +
  14 + /**
  15 + * 插件安装方法
  16 + * @return bool
  17 + */
  18 + public function install()
  19 + {
  20 + return true;
  21 + }
  22 +
  23 + /**
  24 + * 插件卸载方法
  25 + * @return bool
  26 + */
  27 + public function uninstall()
  28 + {
  29 + return true;
  30 + }
  31 +
  32 +}
  1 +require([], function () {
  2 + //绑定data-toggle=addresspicker属性点击事件
  3 +
  4 + $(document).on('click', "[data-toggle='addresspicker']", function () {
  5 + var that = this;
  6 + var callback = $(that).data('callback');
  7 + var input_id = $(that).data("input-id") ? $(that).data("input-id") : "";
  8 + var lat_id = $(that).data("lat-id") ? $(that).data("lat-id") : "";
  9 + var lng_id = $(that).data("lng-id") ? $(that).data("lng-id") : "";
  10 + var lat = lat_id ? $("#" + lat_id).val() : '';
  11 + var lng = lng_id ? $("#" + lng_id).val() : '';
  12 + var url = "/addons/address/index/select";
  13 + url += (lat && lng) ? '?lat=' + lat + '&lng=' + lng : '';
  14 + Fast.api.open(url, '位置选择', {
  15 + callback: function (res) {
  16 + input_id && $("#" + input_id).val(res.address).trigger("change");
  17 + lat_id && $("#" + lat_id).val(res.lat).trigger("change");
  18 + lng_id && $("#" + lng_id).val(res.lng).trigger("change");
  19 + try {
  20 + //执行回调函数
  21 + if (typeof callback === 'function') {
  22 + callback.call(that, res);
  23 + }
  24 + } catch (e) {
  25 +
  26 + }
  27 + }
  28 + });
  29 + });
  30 +});
  1 +<?php
  2 +
  3 +return array(
  4 + array(
  5 + 'name' => 'maptype',
  6 + 'title' => '默认地图类型',
  7 + 'type' => 'radio',
  8 + 'content' =>
  9 + array(
  10 + 'baidu' => '百度地图',
  11 + 'amap' => '高德地图',
  12 + 'tencent' => '腾讯地图',
  13 + ),
  14 + 'value' => 'baidu',
  15 + 'rule' => 'required',
  16 + 'msg' => '',
  17 + 'tip' => '',
  18 + 'ok' => '',
  19 + 'extend' => '',
  20 + ),
  21 + array(
  22 + 'name' => 'location',
  23 + 'title' => '默认检索城市',
  24 + 'type' => 'string',
  25 + 'content' =>
  26 + array(),
  27 + 'value' => '北京',
  28 + 'rule' => 'required',
  29 + 'msg' => '',
  30 + 'tip' => '',
  31 + 'ok' => '',
  32 + 'extend' => '',
  33 + ),
  34 + array(
  35 + 'name' => 'zoom',
  36 + 'title' => '默认缩放级别',
  37 + 'type' => 'string',
  38 + 'content' =>
  39 + array(),
  40 + 'value' => '12',
  41 + 'rule' => 'required',
  42 + 'msg' => '',
  43 + 'tip' => '',
  44 + 'ok' => '',
  45 + 'extend' => '',
  46 + ),
  47 + array(
  48 + 'name' => 'lat',
  49 + 'title' => '默认Lat',
  50 + 'type' => 'string',
  51 + 'content' =>
  52 + array(),
  53 + 'value' => '39.919990',
  54 + 'rule' => 'required',
  55 + 'msg' => '',
  56 + 'tip' => '',
  57 + 'ok' => '',
  58 + 'extend' => '',
  59 + ),
  60 + array(
  61 + 'name' => 'lng',
  62 + 'title' => '默认Lng',
  63 + 'type' => 'string',
  64 + 'content' =>
  65 + array(),
  66 + 'value' => '116.456270',
  67 + 'rule' => 'required',
  68 + 'msg' => '',
  69 + 'tip' => '',
  70 + 'ok' => '',
  71 + 'extend' => '',
  72 + ),
  73 + array(
  74 + 'name' => 'baidukey',
  75 + 'title' => '百度地图KEY',
  76 + 'type' => 'string',
  77 + 'content' =>
  78 + array(),
  79 + 'value' => 'hAeMFHmpyHa2ZjaCH9VVridl',
  80 + 'rule' => 'required',
  81 + 'msg' => '',
  82 + 'tip' => '',
  83 + 'ok' => '',
  84 + 'extend' => '',
  85 + ),
  86 + array(
  87 + 'name' => 'amapkey',
  88 + 'title' => '高德地图KEY',
  89 + 'type' => 'string',
  90 + 'content' =>
  91 + array(),
  92 + 'value' => '608d75903d29ad471362f8c58c550daf',
  93 + 'rule' => 'required',
  94 + 'msg' => '',
  95 + 'tip' => '',
  96 + 'ok' => '',
  97 + 'extend' => '',
  98 + ),
  99 + array(
  100 + 'name' => 'tencentkey',
  101 + 'title' => '腾讯地图KEY',
  102 + 'type' => 'string',
  103 + 'content' =>
  104 + array(),
  105 + 'value' => '608d75903d29ad471362f8c58c550daf',
  106 + 'rule' => 'required',
  107 + 'msg' => '',
  108 + 'tip' => '',
  109 + 'ok' => '',
  110 + 'extend' => '',
  111 + ),
  112 + array(
  113 + 'name' => '__tips__',
  114 + 'title' => '温馨提示',
  115 + 'type' => '',
  116 + 'content' =>
  117 + array(),
  118 + 'value' => '请先申请对应地图的Key,配置后再使用',
  119 + 'rule' => '',
  120 + 'msg' => '',
  121 + 'tip' => '',
  122 + 'ok' => '',
  123 + 'extend' => 'alert-danger-light',
  124 + ),
  125 +);
  1 +<?php
  2 +
  3 +namespace addons\address\controller;
  4 +
  5 +use think\addons\Controller;
  6 +use think\Config;
  7 +use think\Hook;
  8 +
  9 +class Index extends Controller
  10 +{
  11 +
  12 + public function index()
  13 + {
  14 + // 语言检测
  15 + $lang = strip_tags($this->request->langset());
  16 +
  17 + $site = Config::get("site");
  18 +
  19 + // 配置信息
  20 + $config = [
  21 + 'site' => array_intersect_key($site, array_flip(['name', 'cdnurl', 'version', 'timezone', 'languages'])),
  22 + 'upload' => null,
  23 + 'modulename' => 'addons',
  24 + 'controllername' => 'index',
  25 + 'actionname' => 'index',
  26 + 'jsname' => 'addons/address',
  27 + 'moduleurl' => '',
  28 + 'language' => $lang
  29 + ];
  30 + $config = array_merge($config, Config::get("view_replace_str"));
  31 +
  32 + // 配置信息后
  33 + Hook::listen("config_init", $config);
  34 + // 加载当前控制器语言包
  35 + $this->view->assign('site', $site);
  36 + $this->view->assign('config', $config);
  37 +
  38 + return $this->view->fetch();
  39 + }
  40 +
  41 + /**
  42 + * 选择地址
  43 + * @return string
  44 + * @throws \think\Exception
  45 + */
  46 + public function select()
  47 + {
  48 + $config = get_addon_config('address');
  49 + $lat = $this->request->get('lat', $config['lat']);
  50 + $lng = $this->request->get('lng', $config['lng']);
  51 + $this->view->assign('lat', $lat);
  52 + $this->view->assign('lng', $lng);
  53 + $this->view->assign('location', $config['location']);
  54 + return $this->view->fetch('index/' . $config['maptype']);
  55 + }
  56 +
  57 +}
  1 +name = address
  2 +title = 地址选择
  3 +intro = 地图位置选择插件,可返回地址和经纬度
  4 +author = FastAdmin
  5 +website = https://www.fastadmin.net
  6 +version = 1.0.5
  7 +state = 1
  8 +url = /addons/address
  9 +license = regular
  10 +licenseto = 10789
  1 +<!DOCTYPE html>
  2 +<html>
  3 +<head>
  4 + <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
  5 + <title>地址选择器</title>
  6 + <link rel="stylesheet" href="__CDN__/assets/css/bootstrap.min.css"/>
  7 + <link rel="stylesheet" href="__CDN__/assets/css/fastadmin.min.css"/>
  8 + <link rel="stylesheet" href="__CDN__/assets/libs/font-awesome/css/font-awesome.min.css"/>
  9 + <style type="text/css">
  10 + body {
  11 + margin: 0;
  12 + padding: 0;
  13 + }
  14 +
  15 + #container {
  16 + position: absolute;
  17 + left: 0;
  18 + top: 0;
  19 + right: 0;
  20 + bottom: 0;
  21 + }
  22 +
  23 + .confirm {
  24 + position: absolute;
  25 + bottom: 30px;
  26 + right: 4%;
  27 + z-index: 99;
  28 + height: 50px;
  29 + width: 50px;
  30 + line-height: 50px;
  31 + font-size: 15px;
  32 + text-align: center;
  33 + background-color: white;
  34 + background: #1ABC9C;
  35 + color: white;
  36 + border: none;
  37 + cursor: pointer;
  38 + border-radius: 50%;
  39 + }
  40 +
  41 + .search {
  42 + position: absolute;
  43 + width: 400px;
  44 + top: 0;
  45 + left: 50%;
  46 + padding: 5px;
  47 + margin-left: -200px;
  48 + }
  49 +
  50 + .amap-marker-label {
  51 + border: 0;
  52 + background-color: transparent;
  53 + }
  54 +
  55 + .info {
  56 + padding: .75rem 1.25rem;
  57 + margin-bottom: 1rem;
  58 + border-radius: .25rem;
  59 + position: fixed;
  60 + top: 2rem;
  61 + background-color: white;
  62 + width: auto;
  63 + min-width: 22rem;
  64 + border-width: 0;
  65 + left: 1.8rem;
  66 + box-shadow: 0 2px 6px 0 rgba(114, 124, 245, .5);
  67 + }
  68 + </style>
  69 +</head>
  70 +<body>
  71 +<div class="search">
  72 + <div class="input-group">
  73 + <input type="text" id="place" name="q" class="form-control" placeholder="输入地点"/>
  74 + <span class="input-group-btn">
  75 + <button type="submit" name="search" id="search-btn" class="btn btn-success">
  76 + <i class="fa fa-search"></i>
  77 + </button>
  78 + </span>
  79 + </div>
  80 +</div>
  81 +<div class="confirm">确定</div>
  82 +<div id="container"></div>
  83 +<script type="text/javascript" src="//webapi.amap.com/maps?v=1.4.11&key={$config.amapkey|default=''}&plugin=AMap.ToolBar,AMap.Autocomplete,AMap.PlaceSearch,AMap.Geocoder"></script>
  84 +<!-- UI组件库 1.0 -->
  85 +<script src="//webapi.amap.com/ui/1.0/main.js?v=1.0.11"></script>
  86 +<script src="__CDN__/assets/libs/jquery/dist/jquery.min.js"></script>
  87 +<script type="text/javascript">
  88 + $(function () {
  89 + var as, address, map, lat, lng, geocoder;
  90 + var init = function () {
  91 + AMapUI.loadUI(['misc/PositionPicker', 'misc/PoiPicker'], function (PositionPicker, PoiPicker) {
  92 + //加载PositionPicker,loadUI的路径参数为模块名中 'ui/' 之后的部分
  93 + map = new AMap.Map('container', {
  94 + zoom: parseInt('{$config.zoom}')
  95 + });
  96 + geocoder = new AMap.Geocoder({
  97 + radius: 1000 //范围,默认:500
  98 + });
  99 + var positionPicker = new PositionPicker({
  100 + mode: 'dragMarker',//设定为拖拽地图模式,可选'dragMap'、'dragMarker',默认为'dragMap'
  101 + map: map//依赖地图对象
  102 + });
  103 + //输入提示
  104 + var autoOptions = {
  105 + input: "place"
  106 + };
  107 +
  108 + var relocation = function (lnglat) {
  109 + lng = lnglat.lng;
  110 + lat = lnglat.lat;
  111 + map.panTo([lng, lat]);
  112 + positionPicker.start(lnglat);
  113 + geocoder.getAddress(lng + ',' + lat, function (status, result) {
  114 + if (status === 'complete' && result.regeocode) {
  115 + var address = result.regeocode.formattedAddress;
  116 + var label = '<div class="info">地址:' + address + '<br>经度:' + lng + '<br>纬度:' + lat + '</div>';
  117 + positionPicker.marker.setLabel({
  118 + content: label //显示内容
  119 + });
  120 + } else {
  121 + console.log(JSON.stringify(result));
  122 + }
  123 + });
  124 + };
  125 + var auto = new AMap.Autocomplete(autoOptions);
  126 +
  127 + //构造地点查询类
  128 + var placeSearch = new AMap.PlaceSearch({
  129 + map: map
  130 + });
  131 + //注册监听,当选中某条记录时会触发
  132 + AMap.event.addListener(auto, "select", function (e) {
  133 + placeSearch.setCity(e.poi.adcode);
  134 + placeSearch.search(e.poi.name); //关键字查询查询
  135 + });
  136 + AMap.event.addListener(map, 'click', function (e) {
  137 + relocation(e.lnglat);
  138 + });
  139 +
  140 + //加载工具条
  141 + var tool = new AMap.ToolBar();
  142 + map.addControl(tool);
  143 +
  144 + var poiPicker = new PoiPicker({
  145 + input: 'place',
  146 + placeSearchOptions: {
  147 + map: map,
  148 + pageSize: 6 //关联搜索分页
  149 + }
  150 + });
  151 + poiPicker.on('poiPicked', function (poiResult) {
  152 + poiPicker.hideSearchResults();
  153 + $('.poi .nearpoi').text(poiResult.item.name);
  154 + $('.address .info').text(poiResult.item.address);
  155 + $('#address').val(poiResult.item.address);
  156 + $("#place").val(poiResult.item.name);
  157 +
  158 + relocation(poiResult.item.location);
  159 + });
  160 +
  161 + positionPicker.on('success', function (positionResult) {
  162 + as = positionResult.position;
  163 + address = positionResult.address;
  164 + lat = as.lat;
  165 + lng = as.lng;
  166 + });
  167 + positionPicker.on('fail', function (positionResult) {
  168 + address = '';
  169 + });
  170 + positionPicker.start();
  171 + });
  172 + };
  173 +
  174 + //点击确定后执行回调赋值
  175 + var close = function (data) {
  176 + var index = parent.Layer.getFrameIndex(window.name);
  177 + var callback = parent.$("#layui-layer" + index).data("callback");
  178 + //再执行关闭
  179 + parent.Layer.close(index);
  180 + //再调用回传函数
  181 + if (typeof callback === 'function') {
  182 + callback.call(undefined, data);
  183 + }
  184 + };
  185 +
  186 + //点击搜索按钮
  187 + $(document).on('click', '.confirm', function () {
  188 + var zoom = map.getZoom();
  189 + var data = {lat: lat, lng: lng, zoom: zoom, address: address};
  190 + close(data);
  191 + });
  192 + init();
  193 + });
  194 +</script>
  195 +</body>
  196 +</html>
  1 +<!DOCTYPE html>
  2 +<html>
  3 +<head>
  4 + <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
  5 + <title>地址选择器</title>
  6 + <link rel="stylesheet" href="__CDN__/assets/css/bootstrap.min.css"/>
  7 + <link rel="stylesheet" href="__CDN__/assets/css/fastadmin.min.css"/>
  8 + <link rel="stylesheet" href="__CDN__/assets/libs/font-awesome/css/font-awesome.min.css"/>
  9 + <style type="text/css">
  10 + body {
  11 + margin: 0;
  12 + padding: 0;
  13 + }
  14 +
  15 + #container {
  16 + position: absolute;
  17 + left: 0;
  18 + top: 0;
  19 + right: 0;
  20 + bottom: 0;
  21 + }
  22 +
  23 + .confirm {
  24 + position: absolute;
  25 + bottom: 30px;
  26 + right: 4%;
  27 + z-index: 99;
  28 + height: 50px;
  29 + width: 50px;
  30 + line-height: 50px;
  31 + font-size: 15px;
  32 + text-align: center;
  33 + background-color: white;
  34 + background: #1ABC9C;
  35 + color: white;
  36 + border: none;
  37 + cursor: pointer;
  38 + border-radius: 50%;
  39 + }
  40 +
  41 + .search {
  42 + position: absolute;
  43 + width: 400px;
  44 + top: 0;
  45 + left: 50%;
  46 + padding: 5px;
  47 + margin-left: -200px;
  48 + }
  49 +
  50 + label.BMapLabel {
  51 + max-width: inherit;
  52 + padding: .75rem 1.25rem;
  53 + margin-bottom: 1rem;
  54 + background-color: white;
  55 + width: auto;
  56 + min-width: 22rem;
  57 + border: none;
  58 + box-shadow: 0 2px 6px 0 rgba(114, 124, 245, .5);
  59 + }
  60 +
  61 + </style>
  62 +</head>
  63 +<body>
  64 +<div class="search">
  65 + <div class="input-group">
  66 + <input type="text" id="place" name="q" class="form-control" placeholder="输入地点"/>
  67 + <div id="searchResultPanel" style="border:1px solid #C0C0C0;width:150px;height:auto; display:none;"></div>
  68 + <span class="input-group-btn">
  69 + <button type="button" name="search" id="address" class="btn btn-success">
  70 + <i class="fa fa-search"></i>
  71 + </button>
  72 + </span>
  73 + </div>
  74 +</div>
  75 +<div class="confirm">确定</div>
  76 +<div id="container"></div>
  77 +<script type="text/javascript" src="//api.map.baidu.com/api?v=2.0&ak={$config.baidukey|default=''}"></script>
  78 +<script src="__CDN__/assets/libs/jquery/dist/jquery.min.js"></script>
  79 +<script type="text/javascript">
  80 + $(function () {
  81 + // 百度地图API功能
  82 + function G(id) {
  83 + return document.getElementById(id);
  84 + }
  85 +
  86 + var map, marker, searchService, address = null, lng, lat;
  87 +
  88 + var init = function () {
  89 + map = new BMap.Map("container"); // 创建地图实例
  90 + var point = new BMap.Point({$lng}, {$lat}); // 创建点坐标
  91 + map.enableScrollWheelZoom(true); //开启鼠标滚轮缩放
  92 + map.centerAndZoom(point, parseInt("{$config.zoom}")); // 初始化地图,设置中心点坐标和地图级别
  93 +
  94 + var size = new BMap.Size(10, 20);
  95 + map.addControl(new BMap.CityListControl({
  96 + anchor: BMAP_ANCHOR_TOP_LEFT,
  97 + offset: size,
  98 + }));
  99 +
  100 + var geoc = new BMap.Geocoder();
  101 +
  102 + var addpoint = function (point) {
  103 + //通过点击百度地图,可以获取到对应的point, 由point的lng、lat属性就可以获取对应的经度纬度
  104 + var pt = point;
  105 + geoc.getLocation(pt, function (rs) {
  106 + //对象可以获取到详细的地址信息
  107 + address = rs.address;
  108 + deletePoint();
  109 + var mk = new BMap.Marker(pt);
  110 + map.addOverlay(mk);
  111 + map.panTo(pt);
  112 + var label = new BMap.Label('<div class="info">地址:' + address + '<br>经度:' + pt.lng + '<br>纬度:' + pt.lat + '</div>', {offset: new BMap.Size(16, 20)});
  113 + label.setStyle({
  114 + border: 'none',
  115 + padding: '.75rem 1.25rem'
  116 + });
  117 + mk.setLabel(label);
  118 + //将对应的HTML元素设置值
  119 + lng = pt.lng;
  120 + lat = pt.lat;
  121 + });
  122 + };
  123 +
  124 + if ("{$lng}" != '' && "{$lat}" != '') {
  125 + addpoint(point);
  126 + }
  127 +
  128 + ac = new BMap.Autocomplete({"input": "place", "location": map}); //建立一个自动完成的对象
  129 + ac.addEventListener("onhighlight", function (e) { //鼠标放在下拉列表上的事件
  130 + var str = "";
  131 + var _value = e.fromitem.value;
  132 + var value = "";
  133 + if (e.fromitem.index > -1) {
  134 + value = _value.province + _value.city + _value.district + _value.street + _value.business;
  135 + }
  136 + str = "FromItem<br />index = " + e.fromitem.index + "<br />value = " + value;
  137 +
  138 + value = "";
  139 + if (e.toitem.index > -1) {
  140 + _value = e.toitem.value;
  141 + value = _value.province + _value.city + _value.district + _value.street + _value.business;
  142 + }
  143 + str += "<br />ToItem<br />index = " + e.toitem.index + "<br />value = " + value;
  144 + G("searchResultPanel").innerHTML = str;
  145 + });
  146 + ac.addEventListener("onconfirm", function (e) { //鼠标点击下拉列表后的事件
  147 + var _value = e.item.value;
  148 + myValue = _value.province + _value.city + _value.district + _value.street + _value.business;
  149 + G("searchResultPanel").innerHTML = "onconfirm<br />index = " + e.item.index + "<br />myValue = " + myValue;
  150 + setPlace();
  151 + });
  152 +
  153 + function setPlace() {
  154 + map.clearOverlays(); //清除地图上所有覆盖物
  155 + function myFun() {
  156 + var result = local.getResults().getPoi(0);
  157 + var pp = result.point; //获取第一个智能搜索的结果
  158 + map.centerAndZoom(pp, 18);
  159 + map.addOverlay(new BMap.Marker(pp)); //添加标注
  160 + lng = pp.lng;
  161 + lat = pp.lat;
  162 + address = result.address;
  163 + }
  164 +
  165 + var local = new BMap.LocalSearch(map, { //智能搜索
  166 + onSearchComplete: myFun
  167 + });
  168 + local.search(myValue);
  169 + }
  170 +
  171 + map.addEventListener("click", function (e) {
  172 + //通过点击百度地图,可以获取到对应的point, 由point的lng、lat属性就可以获取对应的经度纬度
  173 + var pt = e.point;
  174 + addpoint(e.point);
  175 + });
  176 +
  177 + /**
  178 + * 清除覆盖物
  179 + */
  180 + function deletePoint() {
  181 + var allOverlay = map.getOverlays();
  182 + for (var i = 0; i < allOverlay.length; i++) {
  183 + map.removeOverlay(allOverlay[i]);
  184 + }
  185 + }
  186 + };
  187 +
  188 + var close = function (data) {
  189 + var index = parent.Layer.getFrameIndex(window.name);
  190 + var callback = parent.$("#layui-layer" + index).data("callback");
  191 + //再执行关闭
  192 + parent.Layer.close(index);
  193 + //再调用回传函数
  194 + if (typeof callback === 'function') {
  195 + callback.call(undefined, data);
  196 + }
  197 + };
  198 +
  199 + //点击确定后执行回调赋值
  200 + $(document).on('click', '.confirm', function () {
  201 + var zoom = map.getZoom();
  202 + var data = {lat: lat, lng: lng, zoom: zoom, address: address};
  203 + close(data);
  204 + });
  205 +
  206 + init();
  207 + });
  208 +</script>
  209 +</body>
  210 +</html>
  1 +<!DOCTYPE html>
  2 +<html>
  3 +<head>
  4 + <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
  5 +
  6 + <title>地图位置(经纬度)选择插件 - FastAdmin</title>
  7 +
  8 + <!-- Bootstrap Core CSS -->
  9 + <link href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" rel="stylesheet">
  10 +
  11 + <!-- Custom CSS -->
  12 + <link href="https://cdn.demo.fastadmin.net/assets/css/frontend.css" rel="stylesheet">
  13 +
  14 + <!-- Plugin CSS -->
  15 + <link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet">
  16 +
  17 + <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
  18 + <!--[if lt IE 9]>
  19 + <script src="https://cdn.jsdelivr.net/npm/html5shiv@3.7.3/dist/html5shiv.min.js"></script>
  20 + <script src="https://cdn.jsdelivr.net/npm/respond.js@1.4.2/dest/respond.min.js"></script>
  21 + <![endif]-->
  22 +</head>
  23 +<body>
  24 +<div class="container">
  25 +
  26 + <div class="bs-docs-section clearfix">
  27 + <div class="row">
  28 + <div class="col-lg-12">
  29 + <div class="page-header">
  30 + <h2 id="navbar">地图位置(经纬度)选择示例</h2>
  31 + </div>
  32 +
  33 + <div class="bs-component">
  34 + <form action="" method="post" role="form">
  35 + <div class="form-group">
  36 + <label for=""></label>
  37 + <input type="text" class="form-control" name="" id="address" placeholder="地址">
  38 + </div>
  39 + <div class="form-group">
  40 + <label for=""></label>
  41 + <input type="text" class="form-control" name="" id="lng" placeholder="经度">
  42 + </div>
  43 + <div class="form-group">
  44 + <label for=""></label>
  45 + <input type="text" class="form-control" name="" id="lat" placeholder="纬度">
  46 + </div>
  47 +
  48 + <button type="button" class="btn btn-primary" data-toggle='addresspicker' data-input-id="address" data-lng-id="lng" data-lat-id="lat">点击选择地址获取经纬度</button>
  49 + </form>
  50 + </div>
  51 +
  52 + <div class="page-header">
  53 + <h2 id="code">调用代码</h2>
  54 + </div>
  55 + <div class="bs-component">
  56 + <textarea class="form-control" rows="17">
  57 +<form action="" method="post" role="form">
  58 + <div class="form-group">
  59 + <label for=""></label>
  60 + <input type="text" class="form-control" name="" id="address" placeholder="地址">
  61 + </div>
  62 + <div class="form-group">
  63 + <label for=""></label>
  64 + <input type="text" class="form-control" name="" id="lng" placeholder="经度">
  65 + </div>
  66 + <div class="form-group">
  67 + <label for=""></label>
  68 + <input type="text" class="form-control" name="" id="lat" placeholder="纬度">
  69 + </div>
  70 +
  71 + <button type="button" class="btn btn-primary" data-toggle='addresspicker' data-input-id="address" data-lng-id="lng" data-lat-id="lat">点击选择地址获取经纬度</button>
  72 +</form>
  73 + </textarea>
  74 + </div>
  75 + <div class="page-header">
  76 + <h2 id="navbar">参数说明</h2>
  77 + </div>
  78 +
  79 + <div class="bs-component">
  80 + <table class="table table-condensed table-hover">
  81 + <thead>
  82 + <tr>
  83 + <th>参数</th>
  84 + <th>释义</th>
  85 + </tr>
  86 + </thead>
  87 + <tbody>
  88 + <tr>
  89 + <td>data-input-id</td>
  90 + <td>填充地址的文本框ID</td>
  91 + </tr>
  92 + <tr>
  93 + <td>data-lng-id</td>
  94 + <td>填充经度的文本框ID</td>
  95 + </tr>
  96 + <tr>
  97 + <td>data-lat-id</td>
  98 + <td>填充纬度的文本框ID</td>
  99 + </tr>
  100 + </tbody>
  101 + </table>
  102 + </div>
  103 +
  104 + </div>
  105 + </div>
  106 + </div>
  107 +
  108 +</div>
  109 +<script type="text/javascript">
  110 + var require = {
  111 + config: {$config | json_encode
  112 + }
  113 + }
  114 + ;
  115 +</script>
  116 +
  117 +<script>
  118 + require.callback = function () {
  119 + define('addons/address', ['jquery', 'bootstrap', 'frontend', 'template'], function ($, undefined, Frontend, Template) {
  120 + var Controller = {
  121 + index: function () {
  122 + ;
  123 + }
  124 + };
  125 + return Controller;
  126 + });
  127 + define('lang', function () {
  128 + return [];
  129 + });
  130 + }
  131 +</script>
  132 +
  133 +
  134 +<script src="__CDN__/assets/js/require.min.js" data-main="__CDN__/assets/js/require-frontend.min.js?v={$site.version}"></script>
  135 +</body>
  136 +</html>
  1 +<!DOCTYPE html>
  2 +<html>
  3 +<head>
  4 + <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
  5 + <title>地址选择器</title>
  6 + <link rel="stylesheet" href="__CDN__/assets/css/bootstrap.min.css"/>
  7 + <link rel="stylesheet" href="__CDN__/assets/css/fastadmin.min.css"/>
  8 + <link rel="stylesheet" href="__CDN__/assets/libs/font-awesome/css/font-awesome.min.css"/>
  9 + <style type="text/css">
  10 + body {
  11 + margin: 0;
  12 + padding: 0;
  13 + }
  14 +
  15 + #container {
  16 + position: absolute;
  17 + left: 0;
  18 + top: 0;
  19 + right: 0;
  20 + bottom: 0;
  21 + }
  22 +
  23 + .confirm {
  24 + position: absolute;
  25 + bottom: 30px;
  26 + right: 4%;
  27 + z-index: 99;
  28 + height: 50px;
  29 + width: 50px;
  30 + line-height: 50px;
  31 + font-size: 15px;
  32 + text-align: center;
  33 + background-color: white;
  34 + background: #1ABC9C;
  35 + color: white;
  36 + border: none;
  37 + cursor: pointer;
  38 + border-radius: 50%;
  39 + }
  40 +
  41 + .search {
  42 + position: absolute;
  43 + width: 400px;
  44 + top: 0;
  45 + left: 50%;
  46 + padding: 5px;
  47 + margin-left: -200px;
  48 + }
  49 + </style>
  50 +</head>
  51 +<body>
  52 +<div class="search">
  53 + <div class="input-group">
  54 + <input type="text" id="place" name="q" class="form-control" placeholder="输入地点"/>
  55 + <span class="input-group-btn">
  56 + <button type="submit" name="search" id="search-btn" class="btn btn-success">
  57 + <i class="fa fa-search"></i>
  58 + </button>
  59 + </span>
  60 + </div>
  61 +</div>
  62 +<div class="confirm">确定</div>
  63 +<div id="container"></div>
  64 +<script charset="utf-8" src="//map.qq.com/api/js?v=2.exp&libraries=place&key={$config.tencentkey|default=''}"></script>
  65 +<script src="__CDN__/assets/libs/jquery/dist/jquery.min.js"></script>
  66 +<script type="text/javascript">
  67 + $(function () {
  68 + var map, marker, geocoder, infoWin, searchService, address = null;
  69 + var init = function () {
  70 + var center = new qq.maps.LatLng({$lat}, {$lng});
  71 + map = new qq.maps.Map(document.getElementById('container'), {
  72 + center: center,
  73 + zoom: parseInt("{$config.zoom}")
  74 + });
  75 + //初始化marker
  76 + initmarker(center);
  77 +
  78 + //实例化信息窗口
  79 + infoWin = new qq.maps.InfoWindow({
  80 + map: map
  81 + });
  82 + geocoder = new qq.maps.Geocoder({
  83 + complete: function (result) {
  84 + infoWin.open();
  85 + address = result.detail.addressComponents.province +
  86 + result.detail.addressComponents.city +
  87 + result.detail.addressComponents.district;
  88 + if (result.detail.addressComponents.streetNumber == '') {
  89 + address += result.detail.addressComponents.street;
  90 + } else {
  91 + address += result.detail.addressComponents.streetNumber;
  92 + }
  93 + infoWin.setContent(address);
  94 + infoWin.setPosition(result.detail.location);
  95 + }
  96 + });
  97 + //显示当前marker的位置信息窗口
  98 + geocoder.getAddress(center);
  99 +
  100 + var latlngBounds = new qq.maps.LatLngBounds();
  101 + //查询poi类信息
  102 + searchService = new qq.maps.SearchService({
  103 + complete: function (results) {
  104 + var pois = results.detail.pois;
  105 + for (var i = 0, l = pois.length; i < l; i++) {
  106 + var poi = pois[i];
  107 + latlngBounds.extend(poi.latLng);
  108 + initmarker(poi.latLng);
  109 + //显示当前marker的位置信息窗口
  110 + geocoder.getAddress(poi.latLng);
  111 + }
  112 + map.fitBounds(latlngBounds);
  113 + }
  114 + });
  115 + //实例化自动完成
  116 + var ap = new qq.maps.place.Autocomplete(document.getElementById('place'));
  117 + //添加监听事件
  118 + qq.maps.event.addListener(ap, "confirm", function (res) {
  119 + searchKeyword();
  120 + });
  121 + qq.maps.event.addListener(
  122 + map,
  123 + 'click',
  124 + function (event) {
  125 + try {
  126 + infoWin.setContent('<div style="text-align:center;white-space:nowrap;margin:10px;">加载中</div>');
  127 + var latLng = event.latLng,
  128 + lat = latLng.getLat().toFixed(5),
  129 + lng = latLng.getLng().toFixed(5);
  130 + var location = new qq.maps.LatLng(lat, lng);
  131 + //调用获取位置方法
  132 + geocoder.getAddress(location);
  133 + infoWin.setPosition(location);
  134 + marker.setPosition(location);
  135 + } catch (e) {
  136 + console.log(e);
  137 + }
  138 + }
  139 + );
  140 + };
  141 +
  142 + //实例化marker和监听拖拽结束事件
  143 + var initmarker = function (latLng) {
  144 + marker = new qq.maps.Marker({
  145 + map: map,
  146 + position: latLng,
  147 + draggable: true,
  148 + title: '拖动图标选择位置'
  149 + });
  150 + //监听拖拽结束
  151 + qq.maps.event.addListener(marker, 'dragend', function (event) {
  152 + var latLng = event.latLng,
  153 + lat = latLng.getLat().toFixed(5),
  154 + lng = latLng.getLng().toFixed(5);
  155 + var location = new qq.maps.LatLng(lat, lng);
  156 + //调用获取位置方法
  157 + geocoder.getAddress(location);
  158 + });
  159 + };
  160 + var close = function (data) {
  161 + var index = parent.Layer.getFrameIndex(window.name);
  162 + var callback = parent.$("#layui-layer" + index).data("callback");
  163 + //再执行关闭
  164 + parent.Layer.close(index);
  165 + //再调用回传函数
  166 + if (typeof callback === 'function') {
  167 + callback.call(undefined, data);
  168 + }
  169 + };
  170 +
  171 + //执行搜索方法
  172 + var searchKeyword = function () {
  173 + searchService.clear();//先清除
  174 + marker.setMap(null);
  175 + infoWin.close();
  176 + var keyword = $("#place").val();
  177 + searchService.setLocation("{$location}");//设置默认检索范围(默认为全国),类型可以是坐标或指定的城市名称。
  178 + searchService.setPageIndex(0);//设置检索的特定页数。
  179 + searchService.setPageCapacity(1);//设置每页返回的结果数量。
  180 + searchService.search(keyword);//开始查询
  181 + };
  182 +
  183 + //点击确定后执行回调赋值
  184 + $(document).on('click', '.confirm', function () {
  185 + var as = marker.getPosition();
  186 + var x = as.getLat().toFixed(5);
  187 + var y = as.getLng().toFixed(5);
  188 + var zoom = map.getZoom();
  189 + var data = {lat: x, lng: y, zoom: zoom, address: address};
  190 + close(data);
  191 + });
  192 +
  193 + //点击搜索按钮
  194 + $(document).on('click', '#search-btn', function () {
  195 + if ($("#place").val() == '')
  196 + return;
  197 + searchKeyword();
  198 + });
  199 +
  200 + init();
  201 + });
  202 +</script>
  203 +</body>
  204 +</html>
@@ -121,7 +121,6 @@ class Classification extends Api @@ -121,7 +121,6 @@ class Classification extends Api
121 121
122 /** 122 /**
123 * @ApiTitle (商品规格) 123 * @ApiTitle (商品规格)
124 - * @ApiSummary (分类按钮页面右侧商品列表 初次点击分类页面可不传分类id值)  
125 * @ApiMethod (POST) 124 * @ApiMethod (POST)
126 * @ApiHeaders (name=token, type=string, required=true, description="请求的Token") 125 * @ApiHeaders (name=token, type=string, required=true, description="请求的Token")
127 * @ApiParams (name=goods_id, type=integer, required=true, description="商品id") 126 * @ApiParams (name=goods_id, type=integer, required=true, description="商品id")
@@ -130,6 +129,7 @@ class Classification extends Api @@ -130,6 +129,7 @@ class Classification extends Api
130 'msg':'返回成功' 129 'msg':'返回成功'
131 'data':{ 130 'data':{
132 // 规格组合完毕的列表 131 // 规格组合完毕的列表
  132 + // 如果sku是空数组 为单规格商品 只需要用list的值
133 "list": [ 133 "list": [
134 { 134 {
135 "goods_spec_id": 103, 135 "goods_spec_id": 103,
@@ -137,7 +137,7 @@ class Classification extends Api @@ -137,7 +137,7 @@ class Classification extends Api
137 "goods_no": "SNHW001", 137 "goods_no": "SNHW001",
138 "goods_price": "4499.00", 138 "goods_price": "4499.00",
139 "line_price": "0.00", 139 "line_price": "0.00",
140 - "stock_num": 941, 140 + "stock_num": 941, 库存
141 "goods_sales": 58, 141 "goods_sales": 58,
142 "goods_weight": 500, 142 "goods_weight": 500,
143 "spec_sku_id": "44_46", // 搜索字段 组合sku里面的id搜索 从小到大排序 143 "spec_sku_id": "44_46", // 搜索字段 组合sku里面的id搜索 从小到大排序
@@ -64,6 +64,86 @@ class Goods extends Api @@ -64,6 +64,86 @@ class Goods extends Api
64 $this->success('商品详情',$goods); 64 $this->success('商品详情',$goods);
65 } 65 }
66 66
  67 +
  68 + /**
  69 + * @ApiTitle (商品规格)
  70 + * @ApiMethod (POST)
  71 + * @ApiHeaders (name=token, type=string, required=true, description="请求的Token")
  72 + * @ApiParams (name=goods_id, type=integer, required=true, description="商品id")
  73 + * @ApiReturn ({
  74 + 'code':'1',
  75 + 'msg':'返回成功'
  76 + 'data':{
  77 + // 规格组合完毕的列表
  78 + "list": [
  79 + {
  80 + "goods_spec_id": 103,
  81 + "goods_id": 22,
  82 + "goods_no": "SNHW001",
  83 + "goods_price": "4499.00",
  84 + "line_price": "0.00",
  85 + "stock_num": 941,
  86 + "goods_sales": 58,
  87 + "goods_weight": 500,
  88 + "spec_sku_id": "44_46", // 搜索字段 组合sku里面的id搜索 从小到大排序
  89 + "spec_image": "",
  90 + "create_time": 1542784591,
  91 + "update_time": 1543242861
  92 + }
  93 + ],
  94 + // 规格展示的列表
  95 + "sku": [
  96 + {
  97 + "name": "颜色",
  98 + "second": [
  99 + {
  100 + "id": 44,
  101 + "name": "亮黑色"
  102 + }
  103 + ]
  104 + },
  105 + {
  106 + "name": "内存",
  107 + "second": [
  108 + {
  109 + "id": 46,
  110 + "name": "6GB+64GB"
  111 + }
  112 + ]
  113 + }
  114 + ]
  115 + }
  116 + })
  117 + */
  118 + public function goodsSku()
  119 + {
  120 + $goods_id = $this->request->post('goods_id');
  121 + $goodsspecrelmodel = new GoodsSpecRel();
  122 + $list = $goodsspecrelmodel
  123 + ->where('goods_id',$goods_id)
  124 + ->select();
  125 + $array = [];
  126 + foreach ($list as $key => $value){
  127 + if (!isset($array[$value['spec_id']])){
  128 + $array[$value['spec_id']]['name'] = Db::name('litestore_spec')
  129 + ->where('id',$value['spec_id'])
  130 + ->value('spec_name');
  131 + }
  132 + $spec_value =Db::name('litestore_spec_value')
  133 + ->where('id',$value['spec_value_id'])
  134 + ->value('spec_value');
  135 + $array[$value['spec_id']]['second'][] = [
  136 + 'id' => $value['spec_value_id'],
  137 + 'name' => $spec_value
  138 + ];
  139 + }
  140 + $array = array_values($array);
  141 + $goods_spec = GoodsSpec::all(['goods_id'=>$goods_id]);
  142 + $this->success('商品规格',['list'=>$goods_spec,'sku'=>$array]);
  143 + }
  144 +
  145 +
  146 +
67 /** 147 /**
68 * @ApiTitle (商品详情页评价) 148 * @ApiTitle (商品详情页评价)
69 * @ApiMethod (POST) 149 * @ApiMethod (POST)
  1 +<?php
  2 +
  3 +
  4 +namespace app\api\controller;
  5 +
  6 +
  7 +use app\api\model\GoodsSpec;
  8 +use app\api\model\SpecValue;
  9 +use app\common\controller\Api;
  10 +
  11 +class Order extends Api
  12 +{
  13 + protected $noNeedLogin = ['*'];
  14 + protected $noNeedRight = ['*'];
  15 +
  16 + /**
  17 + * @ApiTitle (下单页面)
  18 + * @ApiSummary ([{"goods_id":22,"goods_sku_id":106,"number":2},{"goods_id":23,"goods_sku_id":66,"number":2}])
  19 + * @ApiMethod (POST)
  20 + * @ApiHeaders (name=token, type=string, required=true, description="请求的Token")
  21 + * @ApiParams (name="data_json", type="string", required=true, description="下单的商品json数据")
  22 + * @ApiParams (name="goods_id", type="integer", required=false, description="商品id 此值不传 json数组注释用")
  23 + * @ApiParams (name="goods_sku_id", type="integer", required=false, description="规格id 此值不传 json数组注释用")
  24 + * @ApiParams (name="number", type="integer", required=false, description="购买数量 此值不传 json数组注释用")
  25 + * @ApiReturn ({
  26 + 'code':'1',
  27 + 'msg':'返回成功'
  28 + })
  29 + */
  30 + public function orderCalculation()
  31 + {
  32 + $json = $this->request->post('data_json');
  33 + if (!$json) $this->error('data_json参数不能为空');
  34 + $json = '[{"goods_id":22,"goods_sku_id":106,"number":2},{"goods_id":23,"goods_sku_id":66,"number":2}]';
  35 + $data = json_decode($json,true);
  36 + $goodsmodel = new \app\api\model\Goods();
  37 + $skumodel = new GoodsSpec();
  38 + $specmodel = new SpecValue();
  39 + $goods_array = [];
  40 + $sum_price = 0;
  41 + foreach ($data as $key => $value){
  42 + if (!is_numeric($value['goods_id']) || !is_numeric($value['goods_sku_id']) || !is_numeric($value['number'])){
  43 + $this->error('参数不合法');
  44 + }
  45 + $goods = $goodsmodel->where('goods_id',$value['goods_id'])->field('goods_id,goods_name,image,spec_type')->find();
  46 + if (!$goods) $this->error('商品不存在');
  47 + $sku = $skumodel->where('goods_spec_id',$value['goods_sku_id'])
  48 + ->field('goods_spec_id,spec_sku_id,goods_price')->find();
  49 + if (!$sku) $this->error('商品规格不存在');
  50 + $goods['sku_id'] = $sku['goods_spec_id'];
  51 + $goods['sku_price'] = $sku['goods_price'];
  52 + if ($goods['spec_type'] == 10){
  53 + $goods['sku_name'] ='';
  54 + }else{
  55 + $ids = explode('_',$sku['spec_sku_id']);
  56 + $sku_name = $specmodel->whereIn('id',$ids)->column('spec_value');
  57 + $goods['sku_name'] = implode(' ',$sku_name);
  58 + }
  59 + $goods['number'] = $value['number'];
  60 + $goods_array[] = $goods;
  61 + $sum_price = bcadd($sum_price,bcmul($sku['goods_price'],$value['number'],2),2);
  62 + }
  63 + $this->success('下单页详情',['list'=>$goods_array,'price'=>$sum_price]);
  64 + }
  65 +}
@@ -8,6 +8,7 @@ use app\common\library\Sms; @@ -8,6 +8,7 @@ use app\common\library\Sms;
8 use fast\Http; 8 use fast\Http;
9 use fast\Random; 9 use fast\Random;
10 use think\Config; 10 use think\Config;
  11 +use think\Db;
11 use think\Validate; 12 use think\Validate;
12 13
13 /** 14 /**
@@ -15,7 +16,7 @@ use think\Validate; @@ -15,7 +16,7 @@ use think\Validate;
15 */ 16 */
16 class User extends Api 17 class User extends Api
17 { 18 {
18 - protected $noNeedLogin = ['login', 'mobilelogin', 'register', 'resetpwd', 'changeemail', 'changemobile', 'third']; 19 + protected $noNeedLogin = ['third'];
19 protected $noNeedRight = '*'; 20 protected $noNeedRight = '*';
20 21
21 public function _initialize() 22 public function _initialize()
@@ -30,23 +31,28 @@ class User extends Api @@ -30,23 +31,28 @@ class User extends Api
30 31
31 /** 32 /**
32 * 会员中心 33 * 会员中心
  34 + * @ApiReturn (
  35 + * data:{
  36 + * nickname 昵称
  37 + * avatar 头像
  38 + * pay 待支付
  39 + * wait_send 待发货
  40 + * wait_collect 待收货
  41 + * wait_comment 待评价
  42 + * }
  43 + * )
33 */ 44 */
34 public function index() 45 public function index()
35 { 46 {
36 - $this->success('', ['welcome' => $this->auth->nickname]);  
37 - }  
38 -  
39 - /**  
40 - * 退出登录  
41 - * @ApiMethod (POST)  
42 - */  
43 - public function logout()  
44 - {  
45 - if (!$this->request->isPost()) {  
46 - $this->error(__('Invalid parameters'));  
47 - }  
48 - $this->auth->logout();  
49 - $this->success(__('Logout successful')); 47 + $data = [];
  48 + $data['nickname'] = $this->auth->nickname;
  49 + $data['avatar'] = cdnurl($this->auth->avatar,true);
  50 + $data['mobile'] = $this->auth->mobile;
  51 + $data['pay'] = Db::name('litestore_order')->where('user_id',$this->auth->id)->where('pay_status','10')->count();
  52 + $data['wait_send'] = Db::name('litestore_order')->where('user_id',$this->auth->id)->where('freight_status','10')->count();
  53 + $data['wait_collect'] = Db::name('litestore_order')->where('user_id',$this->auth->id)->where('receipt_status','10')->count();
  54 + $data['wait_comment'] = Db::name('litestore_order')->where('user_id',$this->auth->id)->where('receipt_status','20')->count();
  55 + $this->success('会员中心', ['welcome' => $this->auth->nickname]);
50 } 56 }
51 57
52 /** 58 /**
@@ -54,106 +60,28 @@ class User extends Api @@ -54,106 +60,28 @@ class User extends Api
54 * 60 *
55 * @ApiMethod (POST) 61 * @ApiMethod (POST)
56 * @param string $avatar 头像地址 62 * @param string $avatar 头像地址
57 - * @param string $username 用户名 63 + * @param string $mobile 联系方式
58 * @param string $nickname 昵称 64 * @param string $nickname 昵称
59 - * @param string $bio 个人简介  
60 */ 65 */
61 public function profile() 66 public function profile()
62 { 67 {
63 $user = $this->auth->getUser(); 68 $user = $this->auth->getUser();
64 - $username = $this->request->post('username'); 69 + $mobile = $this->request->post('mobile');
65 $nickname = $this->request->post('nickname'); 70 $nickname = $this->request->post('nickname');
66 - $bio = $this->request->post('bio');  
67 $avatar = $this->request->post('avatar', '', 'trim,strip_tags,htmlspecialchars'); 71 $avatar = $this->request->post('avatar', '', 'trim,strip_tags,htmlspecialchars');
68 - if ($username) {  
69 - $exists = \app\common\model\User::where('username', $username)->where('id', '<>', $this->auth->id)->find();  
70 - if ($exists) {  
71 - $this->error(__('Username already exists'));  
72 - }  
73 - $user->username = $username; 72 + if ($mobile) {
  73 + $user->mobile = $mobile;
74 } 74 }
75 if ($nickname) { 75 if ($nickname) {
76 - $exists = \app\common\model\User::where('nickname', $nickname)->where('id', '<>', $this->auth->id)->find();  
77 - if ($exists) {  
78 - $this->error(__('Nickname already exists'));  
79 - }  
80 $user->nickname = $nickname; 76 $user->nickname = $nickname;
81 } 77 }
82 - $user->bio = $bio; 78 + if ($avatar) {
83 $user->avatar = $avatar; 79 $user->avatar = $avatar;
84 - $user->save();  
85 - $this->success();  
86 - }  
87 -  
88 - /**  
89 - * 修改邮箱  
90 - *  
91 - * @ApiMethod (POST)  
92 - * @param string $email 邮箱  
93 - * @param string $captcha 验证码  
94 - */  
95 - public function changeemail()  
96 - {  
97 - $user = $this->auth->getUser();  
98 - $email = $this->request->post('email');  
99 - $captcha = $this->request->post('captcha');  
100 - if (!$email || !$captcha) {  
101 - $this->error(__('Invalid parameters'));  
102 } 80 }
103 - if (!Validate::is($email, "email")) {  
104 - $this->error(__('Email is incorrect'));  
105 - }  
106 - if (\app\common\model\User::where('email', $email)->where('id', '<>', $user->id)->find()) {  
107 - $this->error(__('Email already exists'));  
108 - }  
109 - $result = Ems::check($email, $captcha, 'changeemail');  
110 - if (!$result) {  
111 - $this->error(__('Captcha is incorrect'));  
112 - }  
113 - $verification = $user->verification;  
114 - $verification->email = 1;  
115 - $user->verification = $verification;  
116 - $user->email = $email;  
117 $user->save(); 81 $user->save();
118 -  
119 - Ems::flush($email, 'changeemail');  
120 $this->success(); 82 $this->success();
121 } 83 }
122 84
123 - /**  
124 - * 修改手机号  
125 - *  
126 - * @ApiMethod (POST)  
127 - * @param string $mobile 手机号  
128 - * @param string $captcha 验证码  
129 - */  
130 - public function changemobile()  
131 - {  
132 - $user = $this->auth->getUser();  
133 - $mobile = $this->request->post('mobile');  
134 - $captcha = $this->request->post('captcha');  
135 - if (!$mobile || !$captcha) {  
136 - $this->error(__('Invalid parameters'));  
137 - }  
138 - if (!Validate::regex($mobile, "^1\d{10}$")) {  
139 - $this->error(__('Mobile is incorrect'));  
140 - }  
141 - if (\app\common\model\User::where('mobile', $mobile)->where('id', '<>', $user->id)->find()) {  
142 - $this->error(__('Mobile already exists'));  
143 - }  
144 - $result = Sms::check($mobile, $captcha, 'changemobile');  
145 - if (!$result) {  
146 - $this->error(__('Captcha is incorrect'));  
147 - }  
148 - $verification = $user->verification;  
149 - $verification->mobile = 1;  
150 - $user->verification = $verification;  
151 - $user->mobile = $mobile;  
152 - $user->save();  
153 -  
154 - Sms::flush($mobile, 'changemobile');  
155 - $this->success();  
156 - }  
157 85
158 /** 86 /**
159 * 第三方登录 87 * 第三方登录
@@ -481,3 +481,27 @@ if (!function_exists('check_ip_allowed')) { @@ -481,3 +481,27 @@ if (!function_exists('check_ip_allowed')) {
481 } 481 }
482 } 482 }
483 } 483 }
  484 +
  485 +if (!function_exists('getDistance')) {
  486 + function getDistance($lat1, $lng1, $lat2, $lng2)
  487 + {
  488 + $EARTH_RADIUS = 6378.137;
  489 + $radLat1 = rad($lat1);
  490 + $radLat2 = rad($lat2);
  491 + $a = $radLat1 - $radLat2;
  492 + $b = rad($lng1) - rad($lng2);
  493 + $s = 2 * asin(sqrt(pow(sin($a / 2), 2) + cos($radLat1) * cos($radLat2) * pow(sin($b / 2), 2)));
  494 + $s = $s * $EARTH_RADIUS;
  495 + $s = round($s * 10000) / 10000;
  496 +
  497 + return $s;
  498 + }
  499 +}
  500 +
  501 +if (!function_exists('rad')) {
  502 +
  503 + function rad($d)
  504 + {
  505 + return $d * 3.1415926 / 180.0;
  506 + }
  507 +}
1 define([], function () { 1 define([], function () {
2 - require.config({ 2 + require([], function () {
  3 + //绑定data-toggle=addresspicker属性点击事件
  4 +
  5 + $(document).on('click', "[data-toggle='addresspicker']", function () {
  6 + var that = this;
  7 + var callback = $(that).data('callback');
  8 + var input_id = $(that).data("input-id") ? $(that).data("input-id") : "";
  9 + var lat_id = $(that).data("lat-id") ? $(that).data("lat-id") : "";
  10 + var lng_id = $(that).data("lng-id") ? $(that).data("lng-id") : "";
  11 + var lat = lat_id ? $("#" + lat_id).val() : '';
  12 + var lng = lng_id ? $("#" + lng_id).val() : '';
  13 + var url = "/addons/address/index/select";
  14 + url += (lat && lng) ? '?lat=' + lat + '&lng=' + lng : '';
  15 + Fast.api.open(url, '位置选择', {
  16 + callback: function (res) {
  17 + input_id && $("#" + input_id).val(res.address).trigger("change");
  18 + lat_id && $("#" + lat_id).val(res.lat).trigger("change");
  19 + lng_id && $("#" + lng_id).val(res.lng).trigger("change");
  20 + try {
  21 + //执行回调函数
  22 + if (typeof callback === 'function') {
  23 + callback.call(that, res);
  24 + }
  25 + } catch (e) {
  26 +
  27 + }
  28 + }
  29 + });
  30 + });
  31 +});
  32 +
  33 +require.config({
3 paths: { 34 paths: {
4 'litestorefreight_delivery': '../addons/litestore/js/litestorefreight_delivery', 35 'litestorefreight_delivery': '../addons/litestore/js/litestorefreight_delivery',
5 'litestorefreight_regionalChoice': '../addons/litestore/js/litestorefreight_regionalChoice', 36 'litestorefreight_regionalChoice': '../addons/litestore/js/litestorefreight_regionalChoice',