浏览代码

Merge branch 'rprofit' of 39.97.239.116:gyfl/xyzshop into rprofit

xiaoyu 2 年之前
父节点
当前提交
75f96442b3

+ 2 - 1
admin/config/config.ini.php

@@ -19,7 +19,8 @@ $config['receive_bank'] = [
         '椰子浙商银行',
         '趣带娃招行',
         '椰林浦发',
-        '椰林平安'
+        '椰林平安',
+        '椰林广发'
     ],
     'LZKJ_COMPANY' => [
         '琳珠收款'

+ 3 - 3
admin/templates/default/analysis.cov.mch_order_send.php

@@ -102,10 +102,10 @@
                 <td>
                     <select name="filter_wave">
                         <option value=""><?php echo $lang['nc_please_choose']; ?></option>
-                        <option value="60">1分钟</option>
-                        <option value="300">5分钟</option>
-                        <option value="600">10分钟</option>
                         <option value="900">15分钟</option>
+                        <option value="1800">半小时</option>
+                        <option value="3600">1小时</option>
+                        <option value="7200">2小时</option>
                         <option value="0" selected>关闭</option>
                     </select>
                 </td>

+ 3 - 3
admin/templates/default/analysis.cov.provider.php

@@ -126,10 +126,10 @@
                 <td>
                     <select name="filter_wave">
                         <option value=""><?php echo $lang['nc_please_choose']; ?></option>
-                        <option value="60">1分钟</option>
-                        <option value="300">5分钟</option>
-                        <option value="600">10分钟</option>
                         <option value="900">15分钟</option>
+                        <option value="1800">半小时</option>
+                        <option value="3600">1小时</option>
+                        <option value="7200">2小时</option>
                         <option value="0" selected>关闭</option>
                     </select>
                 </td>

+ 3 - 3
admin/templates/default/analysis.cov.system.php

@@ -101,10 +101,10 @@
                 <td>
                     <select name="filter_wave">
                         <option value=""><?php echo $lang['nc_please_choose']; ?></option>
-                        <option value="60">1分钟</option>
-                        <option value="300">5分钟</option>
-                        <option value="600">10分钟</option>
                         <option value="900">15分钟</option>
+                        <option value="1800">半小时</option>
+                        <option value="3600">1小时</option>
+                        <option value="7200">2小时</option>
                         <option value="0" selected>关闭</option>
                     </select>
                 </td>

+ 3 - 3
admin/templates/default/analysis.provider.php

@@ -126,10 +126,10 @@
                 <td>
                     <select name="filter_wave">
                         <option value=""><?php echo $lang['nc_please_choose']; ?></option>
-                        <option value="60">1分钟</option>
-                        <option value="300">5分钟</option>
-                        <option value="600">10分钟</option>
                         <option value="900">15分钟</option>
+                        <option value="1800">半小时</option>
+                        <option value="3600">1小时</option>
+                        <option value="7200">2小时</option>
                         <option value="0" selected>关闭</option>
                     </select>
                 </td>

+ 19 - 1
docker/compose/xiaoyu/admin/docker-compose.yml

@@ -85,4 +85,22 @@ services:
 #      - ../../../../data/upload:/var/www/html/data/upload
 #      - ../../../../data/log:/var/www/html/data/log
 #    container_name: "panda-token-refresh"
-#    command: [ php,"/var/www/html/crontab/index.php",'vendor','token_refresh' ]
+#    command: [ php,"/var/www/html/crontab/index.php",'vendor','token_refresh' ]
+
+  vapisrv:
+    image: php-zts:7.3.18
+    ports:
+      - 9103:9103
+    volumes:
+      - ../../../../:/var/www/html
+      - ../conf/etc/localtime:/etc/localtime:ro
+      - ../conf/php/php.ini:/usr/local/etc/php/php.ini
+      - ../../../../data/upload:/var/www/html/data/upload
+      - ../../../../data/log:/var/www/html/data/log
+      - ../conf/php/vapi-spwan-start:/usr/local/bin/docker-spwan-start
+    container_name: "panda-vapi"
+    command: [ 'docker-spwan-start' ]
+    deploy:
+      resources:
+        limits:
+          cpus: '8'

+ 9 - 0
docker/compose/xiaoyu/conf/nginx/nginx.conf

@@ -70,6 +70,15 @@ http
             include fastcgi_params;
         }
 
+        location ~ /vapi/[/\w]+\.php$ {
+            root           $folder_name;
+            fastcgi_pass   vapisrv:9103;
+            fastcgi_index  index.php;
+            fastcgi_param  SCRIPT_FILENAME  $folder_name$fastcgi_script_name;
+            fastcgi_param  SIGN $http_sign;
+            include fastcgi_params;
+        }
+
         location ~ \.php$ {
 	        add_header Cache-Control no-store;
             root           $folder_name;

+ 11 - 0
docker/compose/xiaoyu/conf/php/vapi-spwan-start

@@ -0,0 +1,11 @@
+#!/bin/sh
+set -e
+spawn-fcgi -a 0.0.0.0 -p 9103 -F 16 -f "php /var/www/html/vapi/vapi.php"
+
+time=$(date "+%Y%m%d")
+
+if [ ! -f "/var/www/html/data/log/${time}-vapi.log" ]; then
+    touch "/var/www/html/data/log/${time}-vapi.log"
+fi
+
+tail -f "/var/www/html/data/log/${time}-vapi.log"

+ 14 - 0
docker/compose/xyz/plot/docker-compose.yml

@@ -0,0 +1,14 @@
+version: "3.7"
+
+services:
+  flasksrv:
+    image: pycpu:3.7.10
+    ports:
+      - "5000:5000"
+    volumes:
+      - ../conf/etc/localtime:/etc/localtime:ro
+      - /nfs/upload:/var/www/html/data/upload
+      - /mnt/shoplog:/var/www/html/data/log
+      - /mnt/stdata:/var/www/html/data/stdata
+    container_name: "panda-flask"
+    command: ['python','app.py']

+ 70 - 46
helper/refill/RefillBase.php

@@ -214,7 +214,6 @@ class RefillBase
         catch (Exception $ex) {
             $tran->rollback();
             Log::record("Error:" . $ex->getMessage(), Log::ERR);
-
             Swoole\Coroutine::sleep(5);
             util::push_notify($chname,$input);
             return false;
@@ -726,64 +725,89 @@ class RefillBase
 
     public function query_net($order_id)
     {
-        $mod_order = Model('vr_order');
-        $order_info = $mod_order->getOrderInfo(['order_id' => $order_id]);
+        $query_handler = function ($order_id, $order_info)
+        {
+            $mod_refill = Model('refill_order');
+            $refill_info = $mod_refill->getOrderInfo(['order_id' => $order_id,'inner_status' => 0]);
+            $chname = $refill_info['channel_name'];
 
-        if(empty($order_info)) return false;
+            if($order_info['order_state'] == ORDER_STATE_PAY) {
+                $query_able = true;
+            }
+            else {
+                $query_able = false;
+            }
 
-        $mod_refill = Model('refill_order');
-        $refill_info = $mod_refill->getOrderInfo(['order_id' => $order_id,'inner_status' => 0]);
-        $chname = $refill_info['channel_name'];
-        $mchid = $refill_info['mchid'];
-        $mch_order = $refill_info['mch_order'];
+            $can_try = false;
+            if($query_able)
+            {
+                if (empty($chname)) return [false, $can_try, $chname];
 
-        if($order_info['order_state'] == ORDER_STATE_PAY) {
-            $query_able = true;
-        }
-        else {
-            $query_able = false;
-        }
+                $provider = $this->mPolicy->provider($chname);
+                if(empty($provider)) return [false, $can_try, $chname];
 
-        if($query_able)
-        {
-            if(empty($chname)) return false;
+                [$state, $order_state] = $provider->query($refill_info);
 
-            $provider = $this->mPolicy->provider($chname);
-            if(empty($provider)) return false;
+                if(!$state) {
+                    QueueClient::async_push("QueryOrderNeterr",['order_id' => $order_id],30);
+                    $neterr = true;
+                }
+                elseif($order_state == ORDER_STATE_SUCCESS || $order_state == ORDER_STATE_CANCEL)
+                {
+                    $neterr = false;
+                    $logic_vr_order = Logic("vr_order");
+                    $logic_vr_order->changeOrderStateSend($order_id, true);
 
-            [$state, $order_state] = $provider->query($refill_info);
-            if(!$state) {
-                QueueClient::async_push("QueryOrderNeterr",['order_id' => $order_id],30);
-                $neterr = true;
-            }
-            elseif($order_state == ORDER_STATE_SUCCESS || $order_state == ORDER_STATE_CANCEL)
-            {
-                $neterr = false;
-                $logic_vr_order = Logic("vr_order");
-                $logic_vr_order->changeOrderStateSend($order_id, true);
+                    $data = ['commit_time' => time()];
+                    $mod_refill->edit($order_id, $data);
+                    QueueClient::async_push("QueryRefillState", ['order_id' => $order_id], 1);
+                }
+                elseif ($order_state == ORDER_STATE_NOEXIST) {
+                    $neterr = false;
+                    $logic_vr_order = Logic("vr_order");
+                    $logic_vr_order->changeOrderStateSend($order_id, true);
+                    $can_try = true;
+                }
+                else {
+                    $neterr = true;
+                    QueueClient::async_push("QueryOrderNeterr",['order_id' => $order_id],30);
+                }
 
-                $data = ['commit_time' => time()];
-                $mod_refill->edit($order_id, $data);
-                QueueClient::async_push("QueryRefillState", ['order_id' => $order_id], 1);
+                util::monitor_netchk($chname,$neterr);
             }
-            elseif ($order_state == ORDER_STATE_NOEXIST) {
-                $neterr = false;
-                $logic_vr_order = Logic("vr_order");
-                $logic_vr_order->changeOrderStateCancel($order_info, '', "{$chname}查询订单不存在.",true,true);
 
-                $mod_refill->edit($order_id, ['notify_time' => time(), 'notify_state' => 1]);
-                util::pop_queue_order($mchid,$mch_order);
-                QueueClient::push("NotifyMerchantComplete", ['order_id' => $order_id, 'manual' => false]);
-            }
-            else {
-                $neterr = true;
+            return [true,$can_try,$chname];
+        };
+
+        $mod_order = Model('vr_order');
+        $order_info = $mod_order->getOrderInfo(['order_id' => $order_id]);
+        if (empty($order_info) || $order_info['order_state'] != ORDER_STATE_PAY) return false;
+
+        try {
+            $can_try = false;
+            $tran = new trans_wapper($mod_order, 'query_net change order state trans');
+            $order_info = $mod_order->getOrderInfo(['order_id' => $order_id], '*', true, true);
+            [$ret, $can_try, $chname] = $query_handler($order_id, $order_info);
+            $tran->commit();
+            $trans_succ = true;
+        }
+        catch (Exception $ex) {
+            Log::record("Error:" . $ex->getMessage(), Log::ERR);
+            $trans_succ = false;
+            $tran->rollback();
+            $ret = false;
+        }
+
+        if($can_try)
+        {
+            if($trans_succ) {
+                $this->proc_notify($order_id, false, true, $chname);
+            } else {
                 QueueClient::async_push("QueryOrderNeterr",['order_id' => $order_id],30);
             }
-
-            util::monitor_netchk($chname,$neterr);
         }
 
-        return true;
+        return $ret;
     }
 
     public function manual_success($order_id)

二进制
helper/refill/api/xyz/guochuang/20220826广东移动调价函.png


+ 1 - 1
helper/refill/api/xyz/guochuang/config.php

@@ -72,7 +72,7 @@ class config
         "4-10-13" => 10.22, "4-20-13" => 19.94, "4-30-13" => 29.91, "4-50-13" => 49.85, "4-100-13" => 99.7, "4-200-13" => 199.4, "4-300-13" => 300.9, "4-500-13" => 501.5,//福建 13
         "4-10-5" => 10.035, "4-20-5" => 20.07, "4-30-5" => 30.09, "4-50-5" => 50.15, "4-100-5" => 100.3, "4-200-5" => 200.4, "4-300-5" => 300.6, "4-500-5" => 501,//内蒙古 5
         "4-30-18" => 29.835, "4-50-18" => 49.725, "4-100-18" => 99.45, "4-200-18" => 198.3,//湖南 18
-        "4-10-19" => 10, "4-20-19" => 20, "4-30-19" => 29.97, "4-50-19" => 49.95, "4-100-19" => 99.9, "4-200-19" => 199.8, "4-300-19" => 299.7, "4-500-19" => 499.5,//广东 19
+        "4-10-19" => 10, "4-20-19" => 20, "4-30-19" => 29.88, "4-50-19" => 49.8, "4-100-19" => 99.6, "4-200-19" => 199.2, "4-300-19" => 298.8, "4-500-19" => 498,//广东 19
         "4-10-7" => 9.93, "4-20-7" => 19.86, "4-30-7" => 29.52, "4-50-7" => 49.2, "4-100-7" => 98.4, "4-200-7" => 196.8, "4-300-7" => 295.2, "4-500-7" => 492,//吉林 7
         "4-10-1" => 10.31, "4-20-1" => 20.32, "4-30-1" => 30.33, "4-50-1" => 50.35, "4-100-1" => 100.4, "4-200-1" => 200.3, "4-300-1" => 300.45, "4-500-1" => 500.75,//北京 1
         "4-10-22" => 10.015, "4-20-22" => 20.03, "4-30-22" => 30.045, "4-50-22" => 50.075, "4-100-22" => 100.15, "4-200-22" => 200.3, "4-300-22" => 300.45, "4-500-22" => 500.75,//重庆 22

+ 1 - 1
helper/refill/api/yl/guochuang/config.php

@@ -72,7 +72,7 @@ class config
         "4-10-13" => 10.22, "4-20-13" => 19.94, "4-30-13" => 29.91, "4-50-13" => 49.85, "4-100-13" => 99.7, "4-200-13" => 199.4, "4-300-13" => 300.9, "4-500-13" => 501.5,//福建 13
         "4-10-5" => 10.035, "4-20-5" => 20.07, "4-30-5" => 30.09, "4-50-5" => 50.15, "4-100-5" => 100.3, "4-200-5" => 200.4, "4-300-5" => 300.6, "4-500-5" => 501,//内蒙古 5
         "4-30-18" => 29.835, "4-50-18" => 49.725, "4-100-18" => 99.45, "4-200-18" => 198.3,//湖南 18
-        "4-10-19" => 10, "4-20-19" => 20, "4-30-19" => 29.97, "4-50-19" => 49.95, "4-100-19" => 99.9, "4-200-19" => 199.8, "4-300-19" => 299.7, "4-500-19" => 499.5,//广东 19
+        "4-10-19" => 10, "4-20-19" => 20, "4-30-19" => 29.88, "4-50-19" => 49.8, "4-100-19" => 99.6, "4-200-19" => 199.2, "4-300-19" => 298.8, "4-500-19" => 498,//广东 19
         "4-10-7" => 9.93, "4-20-7" => 19.86, "4-30-7" => 29.52, "4-50-7" => 49.2, "4-100-7" => 98.4, "4-200-7" => 196.8, "4-300-7" => 295.2, "4-500-7" => 492,//吉林 7
         "4-10-1" => 10.31, "4-20-1" => 20.32, "4-30-1" => 30.33, "4-50-1" => 50.35, "4-100-1" => 100.4, "4-200-1" => 200.3, "4-300-1" => 300.45, "4-500-1" => 500.75,//北京 1
         "4-10-22" => 10.015, "4-20-22" => 20.03, "4-30-22" => 30.045, "4-50-22" => 50.075, "4-100-22" => 100.15, "4-200-22" => 200.3, "4-300-22" => 300.45, "4-500-22" => 500.75,//重庆 22

+ 21 - 2
plot/app.py

@@ -24,7 +24,7 @@ logging.basicConfig(filename='/var/www/html/data/log/flask.log',
                     level=logging.DEBUG)
 logger = logging.getLogger('plot')
 
-from refill import ChannelCumPainter, MerchantPainter
+from refill import ChannelCumPainter, MerchantPainter, ChannelCovPainter
 from refill import filter_chname, filter_cardtype, filter_mchids, get_channels, get_mchids
 
 
@@ -62,7 +62,26 @@ def ch_ratio():
         chnames = request.args.get('chnames')
         chnames = filter_chname(chnames)
 
-        painter = ChannelCumPainter(start_time=start_time, end_time=end_time, chnames=chnames, card_types=card_types, spec=spec, filter_wave=filter_wave)
+        painter = ChannelCumPainter(start_time=start_time, end_time=end_time, chnames=chnames, card_types=card_types, spec=spec,
+                                    filter_wave=filter_wave)
+        buf, ratios = painter.paint()
+        data = base64.b64encode(buf.getbuffer()).decode("ascii")
+
+        return jsonify({'img': data, 'ratios': ratios, 'state': 'success'})
+    except Exception as ex:
+        return onError(ex)
+
+
+@app.route('/plot/ch_covratio')
+def ch_covratio():
+    try:
+        logger.debug('start ch_covratio')
+        start_time, end_time, card_types, spec, filter_wave = parse_parmeter()
+        chnames = request.args.get('chnames')
+        chnames = filter_chname(chnames)
+
+        painter = ChannelCovPainter(start_time=start_time, end_time=end_time, chnames=chnames, card_types=card_types, spec=spec,
+                                    filter_wave=filter_wave)
         buf, ratios = painter.paint()
         data = base64.b64encode(buf.getbuffer()).decode("ascii")
 

+ 56 - 0
plot/refill/ChannelCovPainter.py

@@ -0,0 +1,56 @@
+from .DataStream import EChPosmap as pos_map
+from .ChannelReader import ChannelReader
+from .ChannelPainter import ChannelPainter, ratio_pathes
+from matplotlib.figure import Figure
+from matplotlib import ticker
+from io import BytesIO
+import numpy as np
+from .algorithm import calc_cov_chratios
+import time as time
+
+import logging
+logger = logging.getLogger('ChannelCumPainter')
+
+class ChannelCovPainter(ChannelPainter):
+    def __init__(self, start_time: int, end_time: int, chnames: set = None, card_types: set = None, spec: int = None, filter_wave: int = None):
+        self._reader = ChannelReader()
+        if filter_wave is None:
+            filter_wave = 3600
+        self._chnames, self._card_types, self._spec, self._filter_wave = chnames, card_types, spec, filter_wave
+        _days, self._start_time, self._end_time, self._interval = self.calc_time(self._reader, start_time, end_time)
+        pass
+
+    def paint(self):
+        reader = self._reader
+        self._days, _start_time, _end_time, _interval = self.calc_time(self._reader, self._start_time - self._filter_wave, self._end_time)
+
+        tuple_pathes = reader.many_tuple_path(self._days, self._chnames, self._card_types, self._spec)
+        gen = ratio_pathes(self._reader, tuple_pathes, self._days, self._spec)
+        if len(self._days) == 0:
+            return BytesIO()
+
+        day_stamp = self._days[0]
+        fig_create, fig_flush = self._fig_funs()
+        ax, fig = fig_create()
+        x = np.array([d - self._start_time for d in range(self._start_time, self._end_time)])
+        window = np.ones(self._filter_wave)
+
+        chname_ratios = []
+        for _chname, _card_type, _spec, _data in gen:
+            succ, count, y = calc_cov_chratios(_data, pos_map, _start_time - day_stamp, _end_time - day_stamp, window, self._start_time - day_stamp)
+
+            label, ratio = self._label(chname=_chname, succ=succ, count=count, card_type=_card_type, spec=_spec)
+            ax.plot(x, y, ls='-', label=label)
+            if _card_type is None and _spec is None and _chname != 'all':
+                chname_ratios.append((_chname, ratio))
+
+        ticks = [d - self._start_time for d in range(self._start_time, self._end_time + 1, self._interval)]
+        xlables = [time.strftime('%d-%H:%M:%S', time.localtime(d + self._start_time)) for d in ticks]
+        buf = fig_flush(ax, fig, ticks, xlables)
+
+        chname_ratios = sorted(chname_ratios, key=lambda x: (x[1], x[0]), reverse=True)
+        result = []
+        for name, ratio in chname_ratios:
+            result.append(f'{name}:{ratio}')
+
+        return buf, result

+ 3 - 2
plot/refill/ChannelPainter.py

@@ -13,11 +13,12 @@ import logging
 logger = logging.getLogger('ChannelPainter')
 
 _all_channels = set()
-def add_channel(channel):
+def _add_channel(channel):
     if channel not in _all_channels:
         _all_channels.add(channel)
 
 def get_channels():
+    logger.debug(_all_channels)
     return list(_all_channels)
 
 def ratio_pathes(reader: ChannelReader, tuple_pathes: dict, days: list, spec=None):
@@ -29,7 +30,7 @@ def ratio_pathes(reader: ChannelReader, tuple_pathes: dict, days: list, spec=Non
         all_datas = None
 
     for name, tup in tuple_pathes.items():
-        add_channel(name)
+        _add_channel(name)
         mch_datas = reader.init_data(count)
         for _card_type, _spec in tup:
             if spec is not None and _spec != spec:

+ 3 - 1
plot/refill/__init__.py

@@ -9,6 +9,7 @@ from .NetchkReader import NetchkReader
 from .ChannelReader import ChannelReader
 
 from .ChannelCumPainter import ChannelCumPainter
+from .ChannelCovPainter import ChannelCovPainter
 from .ChannelPainter import get_channels
 from .MerchantPainter import MerchantPainter,get_mchids
 from .helper import filter_chname, filter_cardtype, filter_mchids
@@ -21,7 +22,8 @@ from .server_util import opt_parse
 __all__ = ['DataWriteStream', 'DataReadStream',
            'MerchantWriter', 'ChannelWriter', 'NetchkWriter','WriteConsumer',
            'MerchantReader', 'NetchkReader', 'ChannelReader',
-           'ChannelCumPainter', 'MerchantPainter', 'get_channels', 'get_mchids',
+           'ChannelCumPainter', 'ChannelCovPainter',
+           'MerchantPainter', 'get_channels', 'get_mchids',
            'queueListener', 'open_hdf5', 'day_stamp', 'time_border',
            'filter_chname', 'filter_cardtype', 'filter_mchids',
            'MAmountCalc','MProfitRatioCalc',

+ 21 - 0
plot/refill/algorithm.py

@@ -10,6 +10,8 @@ def calc_chratios(data, pos_map, start, end):
     view = view[:, start:end]
 
     all = np.cumsum(view, axis=1)
+
+    all = np.cumsum(view, axis=1)
     succ = all[0, :]
     commit = all[0, :] + all[1, :]
     commit += 0.0000001
@@ -17,6 +19,25 @@ def calc_chratios(data, pos_map, start, end):
     y = y.ravel()
     return int(all[0, -1]), int(all[0, -1] + all[1, -1]), y
 
+def calc_cov_chratios(data, pos_map, start, end, window, split_pos):
+    view = data[[pos_map.succ_count, pos_map.fail_count, pos_map.commit_count], :]
+    view = view[:, start:end]
+
+    sums = np.sum(view, axis=1)
+    succs = sums[0]
+    fails = sums[1]
+    commits = sums[2]
+
+    succ = view[0, :]
+    fail = view[1, :]
+    succ = np.convolve(succ, window, 'same')
+    fail = np.convolve(fail, window, 'same')
+    commit = succ + fail + 0.0000001
+    y = succ / commit
+    y = y[split_pos - start:]
+
+    return int(succs), int(succs + fails), y
+
 
 def calc_chspeed(data, pos_map, start, end):
     view = data[[pos_map.commit_count], :]

+ 8 - 0
plot/testPlot.py

@@ -51,6 +51,14 @@ class MyTestCase(unittest.TestCase):
         painter = ChannelCumPainter(start_time=start_time, end_time=end_time, chnames=set(), card_types={4, 5, 6})
         painter.paint()
 
+    def test_chcov(self):
+        from refill import ChannelCovPainter
+
+        start_time = int(time.time()) - 10 * 86400 - 3600
+        end_time = int(time.time()) - 10 * 86400
+        painter = ChannelCovPainter(start_time=start_time, end_time=end_time, chnames=set(), card_types={4, 5, 6},filter_wave=3600)
+        painter.paint()
+
     def testDays(self):
         from refill import MerchantReader
         from refill import ChannelReader

+ 28 - 12
vapi/control/retail.php

@@ -7,31 +7,47 @@ class retailControl extends vbaseControl
         parent::__construct();
     }
 
-    public function retail_recordOp()
+    private function check_params($params)
     {
-        $channel_code = $_POST['channel_code'];
+        $channel_code = $params['channel_code'];
         if(empty($channel_code)) {
-            return self::outerr(300,"渠道信息有误.");
+            return [false, "渠道信息有误."];
         }
-        $province = $_POST['province'] ?? '';
-        $city = $_POST['city'] ?? '';
-        $area = $_POST['area'] ?? '';
-        $address = $_POST['address'] ?? '';
+        $province = $params['province'] ?? '';
+        $city = $params['city'] ?? '';
+        $area = $params['area'] ?? '';
+        $address = $params['address'] ?? '';
         if(empty($province) || empty($city) || empty($area) || empty($address)) {
-            return self::outerr(300,"地址信息有误.");
+            return [false, "地址信息有误."];
         }
 
-        $applicant_name = $_POST['applicant_name'];
-        $contact_phone = $_POST['contact_phone'];
+        $applicant_name = $params['applicant_name'];
+        $contact_phone = $params['contact_phone'];
         if(empty($applicant_name) || empty($contact_phone)) {
-            return self::outerr(300,"联系人信息有误.");
+            return [false, "联系人信息有误."];
+        }
+        if(!preg_match('/^1\d{10}$/', $contact_phone)) {
+            return [false, "联系人电话格式有误."];
+        }
+        $retail = Model('')->table('retail')->where(['contact_phone' => $contact_phone])->find();
+        if(!empty($retail)) {
+            return [false, "此联系电话已申请过."];
         }
 
-        $params = [
+        $insert = [
             'channel_code' => $channel_code, 'province' => $province, 'city' => $city, 'area' => $area,
             'address' => $address, 'applicant_name' => $applicant_name, 'contact_phone' => $contact_phone,
             'create_time' => time(), 'retail_sn' => $this->make_sn()
         ];
+        return [true, $insert];
+    }
+
+    public function retail_recordOp()
+    {
+        [$success, $params] = $this->check_params($_POST);
+        if ($success === false) {
+            return self::outerr(300, $params);
+        }
 
         $resp = Model('')->table('retail')->insert($params);
         if ($resp) {