caviar 3 years ago
parent
commit
b5c2cab525

+ 5 - 6
app/admin/controller/Supplier.php

@@ -4,20 +4,19 @@
 namespace app\admin\controller;
 
 use app\BaseController;
-use app\common\model\SupplierModel;
+use app\common\model\CompanyModel;
 use think\App;
 use think\facade\View;
 use think\Request;
 
-class Supplier extends BaseController
+class Company extends BaseController
 {
 
     private $model;
 
-
     public function __construct(App $app)
     {
-        $this->model = new SupplierModel();
+        $this->model = new CompanyModel();
         parent::__construct($app);
     }
 
@@ -42,7 +41,7 @@ class Supplier extends BaseController
 
     public function edit() {
         $params = $this->request->param();
-        $supplier = $this->model->findById($params['id']);
+        $company = $this->model->findById($params['id']);
         if($this->request->isAjax()) {
             $res = $this->model->where('id', $params['id'])->update([
                 'name'  =>  $params['name'],
@@ -51,7 +50,7 @@ class Supplier extends BaseController
             ]);
             return $res ? $this->ok(true) : $this->fail(false);
         }
-        View::assign('supplier',$supplier);
+        View::assign('company', $company);
         return view();
     }
 

+ 3 - 3
app/admin/controller/PaymentChannel.php

@@ -11,9 +11,7 @@ use think\Request;
 
 class PaymentChannel extends BaseController
 {
-
     private $model;
-
     public function __construct(App $app)
     {
         $this->model = new PaymentChannelModel();
@@ -21,7 +19,9 @@ class PaymentChannel extends BaseController
     }
 
     public function index() {
-        View::assign("list",$this->model->findAll());
+        $list = $this->model->findAll();
+        foreach ($list as &$item) $item['type_str'] = ['默认类型', '御龙币设置', '信用卡设置'][$item['type'] - 1];
+        View::assign("list", $list);
         return view();
     }
 

+ 14 - 12
app/admin/controller/Product.php

@@ -4,9 +4,9 @@
 namespace app\admin\controller;
 
 use app\BaseController;
+use app\common\model\CompanyModel;
 use app\common\model\ProductCategoryModel;
 use app\common\model\ProductModel;
-use app\common\model\SupplierModel;
 use think\App;
 use think\facade\View;
 use think\Request;
@@ -16,14 +16,14 @@ class Product extends BaseController
 
     private $productModel;
     private $categoryModel;
-    private $supplierModel;
+    private $companyModel;
 
     public function __construct(App $app)
     {
         parent::__construct($app);
         $this->productModel = new ProductModel();
         $this->categoryModel = new ProductCategoryModel();
-        $this->supplierModel = new SupplierModel();
+        $this->companyModel = new CompanyModel();
     }
 
     /**
@@ -55,28 +55,29 @@ class Product extends BaseController
             $category = $this->categoryModel->findById($params['category_id']);
             if(!$category)
                 return $this->fail(lang('Category does not exist'));
-            $supplier = $this->supplierModel->findById($params['supplier_id']);
-            if(!$supplier)
+            $company = $this->companyModel->findById($params['company_id']);
+            if(!$company)
                 return $this->fail(lang('Company does not exist'));
             $res = $this->productModel->save([
                 'bar_code'  =>  $params['bar_code'],
                 'name'      =>  $params['name'] ?? null,
                 'image'     =>  $params['image'] ?? null,
                 'category_id'   =>  $params['category_id'] ?? null,
-                'supplier_id' =>  $supplier->id,
+                'company_id' =>  $company->id,
                 'is_serve'      =>  $params['is_serve'],
                 'purchase_price'=>  $params['purchase_price'],
                 'real_price' =>  $params['real_price'],
                 'lineate_price' => $params['lineate_price'],
                 'is_upload_numerology'  =>  $params['is_upload_numerology'],
                 'is_gather_annuity' =>  $params["is_gather_annuity"],
-                'annuity'   =>  $params["annuity"]
+                'annuity'   =>  $params["annuity"],
+                'tax_rate'  =>  $params['tax_rate']
             ]);
             return $this->ok($res);
         }
         View::assign([
             'all_category' => recursion($this->categoryModel->findAll(),0),
-            "all_supplier" => $this->supplierModel->findAll()
+            "all_company" => $this->companyModel->findAll()
         ]);
         return view();
     }
@@ -90,15 +91,15 @@ class Product extends BaseController
             $category = $this->categoryModel->findById($params['category_id']);
             if(!$category)
                 return $this->fail(lang('Category does not exist'));
-            $supplier = $this->supplierModel->findById($params['supplier_id'] ?? 0);
-            if(!$supplier)
+            $company = $this->companyModel->findById($params['company_id'] ?? 0);
+            if(!$company)
                 return $this->fail(lang('Company does not exist'));
             $res = $this->productModel->where('id',$params['id'])->update([
                 'bar_code'  =>  $params['bar_code'],
                 'name'      =>  isset($params['name']) ? $params['name'] : $product->name,
                 'image'     =>  isset($params['image']) ? $params['image'] : $product->image,
                 'category_id'   =>  $category->id,
-                'supplier_id' =>  $supplier->id,
+                'company_id' =>  $company->id,
                 'is_serve'      =>  (int)$params['is_serve'],
                 'purchase_price'=>  isset($params['purchase_price']) ? $params['purchase_price'] : $product->purchase_price,
                 'real_price' =>  isset($params['real_price']) && $params['real_price'] > 0 ? $params['real_price'] : $product->real_price,
@@ -106,6 +107,7 @@ class Product extends BaseController
                 'is_upload_numerology'  =>  $params['is_upload_numerology'],
                 'is_gather_annuity' =>  $params["is_gather_annuity"],
                 'annuity'   =>  $params["annuity"],
+                'tax_rate'  =>  $params['tax_rate'],
                 'update_time' => time()
             ]);
             return $this->ok($res);
@@ -113,7 +115,7 @@ class Product extends BaseController
         View::assign([
             'product'   =>  $product,
             'all_category' => recursion($this->categoryModel->findAll(),0),
-            'all_supplier' => $this->supplierModel->findAll()
+            'all_company' => $this->companyModel->findAll()
         ]);
         return view();
     }

+ 5 - 1
app/admin/lang/zh-cn.php

@@ -156,7 +156,11 @@ return [
     "Reception rules"   =>  "前台权限",
     "Backstage permission"  =>  "后台权限",
     "Relevance department"  => "关联部门",
-    "Data rules"    =>  "数据权限"
+    "Data rules"    =>  "数据权限",
+    "Tax rate"      =>  "消费税比例",
+    'Is upload code'    =>  '是否需要上传记录付款编号',
+    'Zue Coin Exchange Rate' =>  '御龙币兑换比例',
+    'Zue Coin Consume Rate' =>  '御龙币消费比例',
 ];
 
 

+ 1 - 1
app/admin/middleware.php

@@ -7,6 +7,6 @@ return [
     // \think\middleware\LoadLangPack::class,
     // Session初始化
     // \think\middleware\SessionInit::class
-//    \app\common\middleware\VerifyToken::class,
+    \app\common\middleware\VerifyToken::class,
     \think\middleware\LoadLangPack::class
 ];

+ 3 - 2
app/admin/view/supplier/add.html

@@ -42,11 +42,11 @@
     </div>
 </div>
 <script>
-    layui.use(['laydate','form','upload'], () => {
+    layui.use(['form'], () => {
         const form = layui.form;
 
         form.on('submit(caviar_submit_btn)', (data) =>{
-            const response = request('{:url("admin/supplier/add")}',data.field)
+            const response = request('{:url("admin/company/add")}',data.field)
             response.then((res) => {
                 console.log(res);
                 res.code === 200 ? layer.msg("{:lang('Succeed')}", {icon: 1,time:500},() => {
@@ -56,4 +56,5 @@
             return false;
         });
     });
+
 </script>

+ 4 - 4
app/admin/view/supplier/edit.html

@@ -13,14 +13,14 @@
                                     <div class="layui-form-item">
                                         <label class="layui-form-label">{:lang("Name")}</label>
                                         <div class="layui-input-block">
-                                            <input name="id" value="{$supplier.id}" hidden>
-                                            <input type="text" value="{$supplier.name}" name="name" lay-verify="required" lay-reqtext="{:lang('Please fill in')}" autocomplete="off" class="layui-input">
+                                            <input name="id" value="{$company.id}" hidden>
+                                            <input type="text" value="{$company.name}" name="name" lay-verify="required" lay-reqtext="{:lang('Please fill in')}" autocomplete="off" class="layui-input">
                                         </div>
                                     </div>
                                     <div class="layui-form-item layui-form-text">
                                         <label class="layui-form-label">{:lang('Introduce')}</label>
                                         <div class="layui-input-block">
-                                            <textarea name="introduce" placeholder="{:lang('Please fill in')}" class="layui-textarea">{$supplier.introduce}</textarea>
+                                            <textarea name="introduce" placeholder="{:lang('Please fill in')}" class="layui-textarea">{$company.introduce}</textarea>
                                         </div>
                                     </div>
                                     <div class="layui-form-item">
@@ -46,7 +46,7 @@
     layui.use(['laydate','form','upload'], () => {
         const form = layui.form;
         form.on('submit(caviar_submit_btn)', (data) =>{
-            const response = request('{:url("admin/supplier/edit")}',data.field)
+            const response = request('{:url("admin/company/edit")}',data.field)
             response.then((res) => {
                 console.log(res);
                 res.code === 200 ? layer.msg("{:lang('Succeed')}", {icon: 1,time:500},() => {

+ 4 - 33
app/admin/view/supplier/index.html

@@ -4,41 +4,12 @@
 <div class="container-fluid">
     <div class="row">
         <div class="col-lg-12">
-<!--            <div class="card" id="select_card_caviar"  style="display: none">-->
-<!--                <div class="card-header">{$Think.lang.condition}</div>-->
-<!--                <div class="card-body">-->
-<!--                    <form action="{:url('admin/supplier/index')}" method="post" class="form-horizontal form-search">-->
-<!--                        <div class="row">-->
-<!--                            <div class="col-md-4">-->
-<!--                                <div class="form-group">-->
-<!--                                    <label class="w-120 pull-left control-label">{:lang("Store")}</label>-->
-<!--                                    <div class="pull-left w-120-calc">-->
-<!--                                        <select class="form-control pull-left" name="store_id">-->
-<!--                                            <option value="0" selected>{:lang("Unknown")}</option>-->
-<!--                                        </select>-->
-<!--                                    </div>-->
-<!--                                </div>-->
-<!--                            </div>-->
-<!--                            <div class="col-md-4">-->
-<!--                                <div class="form-group">-->
-<!--                                    <label class="w-120 pull-left control-label"></label>-->
-<!--                                    <div class="pull-left w-120-calc">-->
-<!--                                        <button class="btn btn-success m-r-5" id="caviar_send_btn" type="submit" href="#">{:lang('search')}</button>-->
-<!--                                    </div>-->
-<!--                                </div>-->
-<!--                            </div>-->
-<!--                        </div>-->
-
-<!--                    </form>-->
-<!--                </div>-->
-<!--            </div>-->
             <div class="card">
                 <div class="card-toolbar clearfix">
                     <div class="toolbar-btn-action">
-<!--                        <a class="btn btn-success m-r-5" id="caviar_search_btn" href="#!" onclick="select_card_switch()">{$Think.lang.unfold_search}</a>-->
-                        <a class="btn btn-primary m-r-5" href="#!" onclick="add('{:url(\'admin/supplier/add\')}')"><i class="mdi mdi-plus"></i> {:lang('add')}</a>
+                        <a class="btn btn-primary m-r-5" href="#!" onclick="add('{:url(\'admin/company/add\')}')"><i class="mdi mdi-plus"></i> {:lang('add')}</a>
                         <a class="btn btn-danger" href="#!" onclick="
-                            caviar_checkbox_delete('{:url(\'admin/supplier/delete\')}', ['{:lang(\'Check at least one box\')}','{:lang(\'Succeed\')}'],'{:lang(\'Warn\')}','{:lang(\'Are you sure you want to delete the selected data\')}',['{:lang(\'Confirm\')}'])"
+                            caviar_checkbox_delete('{:url(\'admin/company/delete\')}', ['{:lang(\'Check at least one box\')}','{:lang(\'Succeed\')}'],'{:lang(\'Warn\')}','{:lang(\'Are you sure you want to delete the selected data\')}',['{:lang(\'Confirm\')}'])"
                         ><i class="mdi mdi-window-close"></i> {:lang('delete')}</a>
                     </div>
                 </div>
@@ -73,9 +44,9 @@
                                 <td>{$item.update_time}</td>
                                 <td>
                                     <div class="btn-group">
-                                        <a class="btn btn-xs btn-default" href="#!" title="{:lang('select')}" data-toggle="tooltip" onclick='view("/admin/supplier/edit?id={$item.id}","{:lang(\"Info\")}")'><i class="mdi mdi-eye"></i></a>
+                                        <a class="btn btn-xs btn-default" href="#!" title="{:lang('select')}" data-toggle="tooltip" onclick='view("/admin/company/edit?id={$item.id}","{:lang(\"Info\")}")'><i class="mdi mdi-eye"></i></a>
                                         <a class="btn btn-xs btn-default" href="#!" title="{:lang('delete')}" data-toggle="tooltip" onclick='
-                                           deletingASingle("{:url(\"admin/supplier/delete\")}","{$item.id}",["{:lang(\"Succeed\")}"],"{:lang(\"Warn\")}","{:lang(\"Are you sure you want to delete the selected data\")}",["{:lang(\"Confirm\")}"])'
+                                           deletingASingle("{:url(\"admin/company/delete\")}","{$item.id}",["{:lang(\"Succeed\")}"],"{:lang(\"Warn\")}","{:lang(\"Are you sure you want to delete the selected data\")}",["{:lang(\"Confirm\")}"])'
                                         ><i class="mdi mdi-window-close"></i></a>
                                     </div>
                                 </td>

+ 44 - 5
app/admin/view/payment_channel/add.html

@@ -10,7 +10,6 @@
                         <div class="card">
                             <div class="card-body">
                                 <form class="layui-form">
-
                                     <div class="layui-form-item">
                                         <label class="layui-form-label">{:lang("Name")}</label>
                                         <div class="layui-input-block">
@@ -29,6 +28,40 @@
                                     </div>
 
                                     <div class="layui-form-item">
+                                        <label class="layui-form-label">{:lang('Is upload code')}</label>
+                                        <div class="layui-input-block">
+                                            <select name="is_upload_code" lay-filter="required">
+                                                <option value="0" >{:lang("No")}</option>
+                                                <option value="1" selected>{:lang("Yes")}</option>
+                                            </select>
+                                        </div>
+                                    </div>
+
+                                    <div class="layui-form-item">
+                                        <label class="layui-form-label">{:lang('Type')}</label>
+                                        <div class="layui-input-block">
+                                            <select name="type" lay-filter="type">
+                                                <option value="1" >默认类型</option>
+                                                <option value="2" >御龙币设置</option>
+                                                <option value="3" >信用卡设置</option>
+                                            </select>
+                                        </div>
+                                    </div>
+
+                                    <div class="layui-form-item zue-coin" hidden>
+                                        <label class="layui-form-label">{:lang("Zue Coin Exchange Rate")}</label>
+                                        <div class="layui-input-block">
+                                            <input type="number" value="0" name="zue_coin_exchange_rate" class="layui-input">
+                                        </div>
+                                    </div>
+                                    <div class="layui-form-item zue-coin" hidden>
+                                        <label class="layui-form-label">{:lang("Zue Coin Consume Rate")}</label>
+                                        <div class="layui-input-block">
+                                            <input type="number" value="0" name="zue_coin_consume_rate" class="layui-input">
+                                        </div>
+                                    </div>
+
+                                    <div class="layui-form-item">
                                         <div class="layui-input-block">
                                             <button type="submit" class="layui-btn" lay-submit="" lay-filter="caviar_submit_btn">{:lang('Submit')}</button>
                                             <button type="reset" class="layui-btn layui-btn-primary">{:lang("Reset")}</button>
@@ -44,7 +77,6 @@
 
             </div>
         </main>
-        <!--End 页面主要内容-->
     </div>
 </div>
 <script>
@@ -52,12 +84,19 @@
     //当你在iframe页面关闭自身时
     // var index = parent.layer.getFrameIndex(window.name); //先得到当前iframe层的索引
     // parent.layer.close(index); //再执行关闭
-    layui.use(['laydate','form','upload'], () => {
-        const laydate = layui.laydate;
+    layui.use(['form','upload'], () => {
         const form = layui.form;
-
         const upload = layui.upload;
 
+        form.on('select(type)',function (data) {
+            const value = data.value;
+            if(value == 2) {
+                $(".zue-coin").css('display','block');
+            } else {
+                $('.zue-coin').css('display','none');
+            }
+        });
+
         //执行实例
         upload.render({
             elem: '#upload_img' //绑定元素

+ 4 - 10
app/admin/view/payment_channel/index.html

@@ -21,6 +21,8 @@
                                 </th>
                                 <th>{:lang("ID")}</th>
                                 <th>{:lang('Name')}</th>
+                                <th>{:lang('Type')}</th>
+                                <th>{:lang('Is upload code')}</th>
                                 <th>{:lang('icon')}</th>
                                 <th>{:lang('update_time')}</th>
                                 <th>{:lang('operation')}</th>
@@ -36,6 +38,8 @@
                                 </td>
                                 <td>{$item.id}</td>
                                 <td>{$item.name}</td>
+                                <td>{$item.type_str}</td>
+                                <td>{if $item.is_upload_code == 1}是{else /}否{/if}</td>
                                 <td><img class="small-img" src="{$item.icon}" onclick="image_magnify()" ></td>
                                 <td>{$item.update_time}</td>
                                 <td>
@@ -57,13 +61,3 @@
     </div>
 </div>
 
-<style>
-
-</style>
-
-<script type="text/javascript">
-    if(check_params(["{params.store_id}"]))
-        $('#select_card_caviar').css('display','block');
-</script>
-
-

+ 9 - 2
app/admin/view/product/add.html

@@ -69,8 +69,8 @@
                   <div class="layui-form-item">
                     <label class="layui-form-label">{:lang('Company')}</label>
                     <div class="layui-input-block">
-                      <select name="supplier_id" lay-filter="required">
-                        {volist name="all_supplier" id="item"}
+                      <select name="company_id" lay-filter="required">
+                        {volist name="all_company" id="item"}
                         <option value="{$item.id}" >{$item.name}</option>
                         {/volist}
                       </select>
@@ -99,6 +99,13 @@
                   </div>
 
                   <div class="layui-form-item">
+                    <label class="layui-form-label">{:lang("Tax rate")}</label>
+                    <div class="layui-input-block">
+                      <input type="number" value="0.00" name="tax_rate" lay-verify="required" lay-reqtext="{:lang('Please fill in')}" autocomplete="off" class="layui-input">
+                    </div>
+                  </div>
+
+                  <div class="layui-form-item">
                     <label class="layui-form-label">{:lang("Is upload numerology")}</label>
                     <div class="layui-input-block">
                       <input type="radio" name="is_upload_numerology" value="0" title="{:lang('No')}" checked>

+ 10 - 3
app/admin/view/product/edit.html

@@ -71,9 +71,9 @@
                   <div class="layui-form-item">
                       <label class="layui-form-label">{:lang('Company')}</label>
                       <div class="layui-input-block">
-                          <select name="supplier_id" lay-filter="required">
-                              {volist name="all_supplier" id="item"}
-                              <option value="{$item.id}" {if $product.supplier_id == $item.id} selected {/if} >{$item.name}</option>
+                          <select name="company_id" lay-filter="required">
+                              {volist name="all_company" id="item"}
+                              <option value="{$item.id}" {if $product.company_id == $item.id} selected {/if} >{$item.name}</option>
                               {/volist}
                           </select>
                       </div>
@@ -101,6 +101,13 @@
                   </div>
 
                   <div class="layui-form-item">
+                      <label class="layui-form-label">{:lang("Tax rate")}</label>
+                      <div class="layui-input-block">
+                          <input type="number" value="{$product.tax_rate}" name="tax_rate" lay-verify="required" lay-reqtext="{:lang('Please fill in')}" autocomplete="off" class="layui-input">
+                      </div>
+                  </div>
+
+                  <div class="layui-form-item">
                       <label class="layui-form-label">{:lang("Is upload numerology")}</label>
                       <div class="layui-input-block">
                           <input type="radio" name="is_upload_numerology" value="0" title="{:lang('No')}" {if $product.is_upload_numerology == 0} checked {/}>

+ 3 - 1
app/admin/view/product/index.html

@@ -90,6 +90,7 @@
                                 <th>{:lang('Purchase Price')}</th>
                                 <th>{:lang('Real price')}</th>
                                 <th>{:lang('Lineate price')}</th>
+                                <th>{:lang('Tax rate')}</th>
                                 <th>{:lang('Is upload numerology')}</th>
                                 <th>{:lang('Is gather annuity')}</th>
                                 <th>{:lang('Annuity')}</th>
@@ -110,11 +111,12 @@
                                 <td>{$item.name}</td>
                                 <td><img class="small-img" src="{$item.image}" onclick="image_magnify()" ></td>
                                 <td>{$item.category.name}</td>
-                                <td>{$item.supplier.name}</td>
+                                <td>{$item.company.name}</td>
                                 <td>{if $item.is_serve == 1}{:lang("Yes")}{else /}{:lang("No")}{/if}</td>
                                 <td>{$item.purchase_price}</td>
                                 <td>{$item.real_price}</td>
                                 <td>{$item.lineate_price}</td>
+                                <td>{$item.tax_rate}</td>
                                 <td>{if $item.is_upload_numerology == 1} {:lang("Yes")}{else /}{:lang("No")}{/if}</td>
                                 <td>{if $item.is_gather_annuity == 1} {:lang("Yes")}{else /}{:lang("No")}{/if}</td>
                                 <td>{if $item.is_gather_annuity == 1}{$item.annuity}{else /}/{/if}</td>

+ 2 - 2
app/common/model/SupplierModel.php

@@ -4,10 +4,10 @@
 namespace app\common\model;
 
 
-class SupplierModel extends BaseModel
+class CompanyModel extends BaseModel
 {
 
-    protected $table = 'erp_supplier';
+    protected $table = 'erp_company';
 
     protected function genSchema(array $schema)
     {

+ 3 - 3
app/common/model/ProductModel.php

@@ -17,8 +17,8 @@ class ProductModel extends BaseModel
         return self::hasOne(ProductCategoryModel::class,'id','category_id');
     }
 
-    public function supplier() {
-        return self::hasOne(SupplierModel::class,'id','supplier_id');
+    public function company() {
+        return self::hasOne(CompanyModel::class,'id','company_id');
     }
 
     /**
@@ -37,7 +37,7 @@ class ProductModel extends BaseModel
         if(!is_null($params['is_serve']))
             array_push($where,['erp_product.is_serve', '=', $params['is_serve']]);
 
-        return $this->with(['category', 'supplier'])
+        return $this->with(['category', 'company'])
             ->where($where)
             ->order('create_time','desc')
             ->paginate(['list_rows'=>10, "query" => $params]);

+ 0 - 2
extend/.gitignore

@@ -1,2 +0,0 @@
-*
-!.gitignore

+ 114 - 0
extend/Jwt.php

@@ -0,0 +1,114 @@
+<?php
+
+/**
+ * Jwt
+ */
+class Jwt
+{
+    //头部
+    private static $header = array(
+        'alg' => 'HS256', //生成signature的算法
+        'typ' => 'JWT'    //类型
+    );
+
+    //使用HMAC生成信息摘要时所使用的密钥
+    private static $key = '123456';
+
+    /**
+     * 获取jwt token
+     * @param array $payload jwt载荷   格式如下非必须
+     * [
+     *  'iss'=>'jwt_admin',  //该JWT的签发者
+     *  'iat'=>time(),  //签发时间
+     *  'exp'=>time()+7200,  //过期时间
+     *  'nbf'=>time()+60,  //该时间之前不接收处理该Token
+     *  'sub'=>'www.admin.com',  //面向的用户
+     *  'jti'=>md5(uniqid('JWT').time())  //该Token唯一标识
+     * ]
+     * @return bool|string
+     */
+    public static function getToken(array $payload)
+    {
+        if (is_array($payload)) {
+            $base64header = self::base64UrlEncode(json_encode(self::$header, JSON_UNESCAPED_UNICODE));
+            $base64payload = self::base64UrlEncode(json_encode($payload, JSON_UNESCAPED_UNICODE));
+            $token = $base64header . '.' . $base64payload . '.' . self::signature($base64header . '.' . $base64payload, self::$key, self::$header['alg']);
+            return $token;
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * 验证token是否有效,默认验证exp,nbf,iat时间
+     * @param string $Token 需要验证的token
+     * @return bool|string
+     */
+
+    public static function verifyToken(string $Token)
+    {
+        $tokens = explode('.', $Token);
+        if (count($tokens) != 3)
+            return false;
+        list($base64header, $base64payload, $sign) = $tokens;
+        //获取jwt算法
+        $base64decodeheader = json_decode(self::base64UrlDecode($base64header), JSON_OBJECT_AS_ARRAY);
+        if (empty($base64decodeheader['alg']))
+            return false;
+        //签名验证
+        if (self::signature($base64header . '.' . $base64payload, self::$key, $base64decodeheader['alg']) !== $sign)
+            return false;
+        $payload = json_decode(self::base64UrlDecode($base64payload), JSON_OBJECT_AS_ARRAY);
+        //签发时间大于当前服务器时间验证失败
+        if (isset($payload['iat']) && $payload['iat'] > time())
+            return false;
+
+        //过期时间小宇当前服务器时间验证失败
+        if (isset($payload['exp']) && $payload['exp'] < time())
+            return false;
+        //该nbf时间之前不接收处理该Token
+        if (isset($payload['nbf']) && $payload['nbf'] > time())
+            return false;
+        return $payload;
+    }
+
+    /**
+     * base64UrlEncode   https://jwt.io/  中base64UrlEncode编码实现
+     * @param string $input 需要编码的字符串
+     * @return string
+     */
+    private static function base64UrlEncode(string $input)
+    {
+        return str_replace('=', '', strtr(base64_encode($input), '+/', '-_'));
+    }
+
+    /**
+     * base64UrlEncode  https://jwt.io/  中base64UrlEncode解码实现
+     * @param string $input 需要解码的字符串
+     * @return bool|string
+     */
+    private static function base64UrlDecode(string $input)
+    {
+        $remainder = strlen($input) % 4;
+        if ($remainder) {
+            $addlen = 4 - $remainder;
+            $input .= str_repeat('=', $addlen);
+        }
+        return base64_decode(strtr($input, '-_', '+/'));
+    }
+
+    /**
+     * HMACSHA256签名   https://jwt.io/  中HMACSHA256签名实现
+     * @param string $input 为base64UrlEncode(header).".".base64UrlEncode(payload)
+     * @param string $key
+     * @param string $alg   算法方式
+     * @return mixed
+     */
+    private static function signature(string $input, string $key, string $alg = 'HS256')
+    {
+        $alg_config = array(
+            'HS256' => 'sha256'
+        );
+        return self::base64UrlEncode(hash_hmac($alg_config[$alg], $input, $key, true));
+    }
+}

+ 118 - 0
extend/RedLock.php

@@ -0,0 +1,118 @@
+<?php
+declare (strict_types = 1);
+
+class RedLock
+{
+    private $retryDelay;
+    private $retryCount;
+    private $clockDriftFactor = 0.01;
+
+    private $quorum;
+
+    private $servers = array();
+    private $instances = array();
+
+    function __construct( $retryDelay = 200, $retryCount = 3)
+    {
+        $this->servers = [
+            [
+                'host'       => env('redis.host','127.0.0.1'),
+                'port'       => env('redis.port', 6379),
+                'password'   => env('redis.password', '123456'),
+                'select'     => env('redis.select', 10),
+                'timeout'    => env('redis.timeout', 1000),
+            ]
+        ];
+        $this->retryDelay = $retryDelay;
+        $this->retryCount = $retryCount;
+
+        $this->quorum  = min(count($this->servers), (count($this->servers) / 2 + 1));
+    }
+
+    public function lock($resource, $ttl = 600)
+    {
+        $this->initInstances();
+
+        $token = uniqid();
+        $retry = $this->retryCount;
+
+        do {
+            $n = 0;
+
+            $startTime = microtime(true) * 1000;
+
+            foreach ($this->instances as $instance) {
+                if ($this->lockInstance($instance, $resource, $token, $ttl)) {
+                    $n++;
+                }
+            }
+
+            # Add 2 milliseconds to the drift to account for Redis expires
+            # precision, which is 1 millisecond, plus 1 millisecond min drift
+            # for small TTLs.
+            $drift = ($ttl * $this->clockDriftFactor) + 2;
+
+            $validityTime = $ttl - (microtime(true) * 1000 - $startTime) - $drift;
+
+            if ($n >= $this->quorum && $validityTime > 0) {
+                return [
+                    'validity' => $validityTime,
+                    'resource' => $resource,
+                    'token'    => $token,
+                ];
+
+            } else {
+                foreach ($this->instances as $instance) {
+                    $this->unlockInstance($instance, $resource, $token);
+                }
+            }
+
+            // Wait a random delay before to retry
+            $delay = mt_rand(floor($this->retryDelay / 2), $this->retryDelay);
+            usleep($delay * 1000);
+
+            $retry--;
+
+        } while ($retry > 0);
+
+        return false;
+    }
+
+    public function unlock(array $lock)
+    {
+        $this->initInstances();
+        $resource = $lock['resource'];
+        $token    = $lock['token'];
+
+        foreach ($this->instances as $instance) {
+            $this->unlockInstance($instance, $resource, $token);
+        }
+    }
+
+    private function initInstances()
+    {
+        if (empty($this->instances)) {
+            foreach ($this->servers as $server) {
+                $redis = new \think\cache\driver\Redis($server);
+                $this->instances[] = $redis;
+            }
+        }
+    }
+
+    private function lockInstance($instance, $resource, $token, $ttl)
+    {
+        return $instance->set($resource, $token, ['NX', 'PX' => $ttl]);
+    }
+
+    private function unlockInstance($instance, $resource, $token)
+    {
+        $script = '
+            if redis.call("GET", KEYS[1]) == ARGV[1] then
+                return redis.call("DEL", KEYS[1])
+            else
+                return 0
+            end
+        ';
+        return $instance->eval($script, [$resource, $token], 1);
+    }
+}

+ 52 - 0
task.text

@@ -0,0 +1,52 @@
+2022.12.22周会议纪要
+
+4.后台收款渠道管理 御龙币需要配置兑换比例和单个订单消费比例
+5.后台收款渠道管理  需要增加字段是否需要记录付款编号  前端需要知道哪个付款方式需要填写编号
+6.后台收款渠道管理  Visa/Master和 DINERS支付方式 需要设置信用卡分期数的费用比例,需要增加的字段参考支付方式文档
+
+zue_coin_exchange_rate
+zue_coin_consume_rate
+
+3.订单列表 增加导出功能 可供财务计算员工业绩
+8.整理财务报表需求
+7.御龙币可先建数据表,可以展示数据
+
+
+Visa/Master
+[
+    {q: '1'}
+]
+
+
+
+
+{
+    type:"一次性付款",
+    channels: [
+        {type: "Maybank"},
+        {type: "UOB"},
+        {type: "DBS"},
+    ],
+},
+{
+    type:"分期付款",
+    channels: [
+            {type: "Maybank", amortize: [{month: 6, fee_rate: 6}, {month: 12, fee_rate: 8}]...},
+            {type: "UOB"},
+            {type: "DBS"},
+        ],
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+