Pārlūkot izejas kodu

Merge branch 'master' of http://18.167.157.193:1026/guanli/ngds into feature/1540-theo-auto-mesure-up

theo 3 gadi atpakaļ
vecāks
revīzija
bfc781f0c4
32 mainītis faili ar 678 papildinājumiem un 131 dzēšanām
  1. 2 0
      .gitignore
  2. 4 0
      backendApi/config/urlManagerRules.php
  3. 37 4
      backendApi/modules/v1/controllers/AdController.php
  4. 25 0
      backendApi/modules/v1/controllers/ArticleController.php
  5. 39 0
      backendApi/modules/v1/controllers/BaseController.php
  6. 7 7
      backendApi/modules/v1/models/lists/user/MoveList.php
  7. 1 1
      backendEle/src/components/ExcelUploader.vue
  8. 3 3
      backendEle/src/components/Uploader.vue
  9. 22 10
      backendEle/src/router/index.js
  10. 8 1
      backendEle/src/utils/tool.js
  11. 54 15
      backendEle/src/views/ad/edit.vue
  12. 121 15
      backendEle/src/views/ad/list.vue
  13. 1 1
      backendEle/src/views/ad/location.vue
  14. 57 0
      backendEle/src/views/article/detail.vue
  15. 17 9
      backendEle/src/views/shop/index.vue
  16. 2 2
      backendEle/src/views/user/move.vue
  17. 5 5
      common/helpers/LoggerTool.php
  18. 83 3
      common/helpers/bonus/BonusCalc.php
  19. 2 0
      common/helpers/bonus/CalcCache.php
  20. 50 0
      common/models/CalcBonusQuarter.php
  21. 14 14
      common/models/forms/AdForm.php
  22. 5 10
      common/models/forms/UploadForm.php
  23. 1 1
      frontendApi/modules/v1/controllers/BonusController.php
  24. 2 2
      frontendApi/modules/v1/controllers/FinanceController.php
  25. 1 1
      frontendApi/modules/v1/controllers/UserController.php
  26. 1 1
      frontendEle/src/components/Uploader.vue
  27. 11 5
      frontendEle/src/views/dashboard/index.vue
  28. 60 15
      frontendEle/src/views/shop/index.vue
  29. 2 1
      frontendEle/src/views/shop/order.vue
  30. 3 3
      frontendEle/src/views/user/dec.vue
  31. 2 2
      frontendEle/src/views/user/id-card.vue_bak
  32. 36 0
      sql/upgrade/1350.sql

+ 2 - 0
.gitignore

@@ -24,3 +24,5 @@ vendor
 frontendApi/web/pdfs/
 #composer.json
 composer.lock
+backendApi/web/uploads
+frontendApi/web/uploads

+ 4 - 0
backendApi/config/urlManagerRules.php

@@ -496,6 +496,8 @@ return [
             'GET index' => 'index',
             'GET,POST add' => 'add',
             'GET,POST edit/<id>' => 'edit',
+            'GET detail' => 'detail',
+            'GET detail/<id>' => 'detail',
             'GET,POST article-delete' => 'article-delete',
             'GET category' => 'category',
             'POST category-add' => 'category-add',
@@ -512,6 +514,8 @@ return [
             'GET,POST add' => 'add',
             'GET,POST edit/<id>' => 'edit',
             'GET,POST ad-delete' => 'ad-delete',
+            'GET,POST ad-hide' => 'ad-hide',
+            'GET,POST ad-un-hide' => 'ad-un-hide',
             'GET location' => 'location',
             'GET sort' => 'sort',
             'GET status' => 'status',

+ 37 - 4
backendApi/modules/v1/controllers/AdController.php

@@ -13,6 +13,7 @@ use common\helpers\Form;
 use common\helpers\Log;
 use common\models\Ad;
 use common\models\AdLocation;
+use common\models\Article;
 use common\models\forms\AdForm;
 use common\models\forms\UploadForm;
 use Yii;
@@ -65,6 +66,8 @@ class AdController extends BaseController
             'orderBy' => 'AD.SORT DESC,AD.CREATED_AT ASC',
         ]);
         $data['allLocation'] = AdLocation::getAllLocation();
+        $data['allArticle'] = Article::find()->select('ID,TITLE')->asArray()->all();
+
         return static::notice($data);
     }
 
@@ -75,14 +78,16 @@ class AdController extends BaseController
      */
     public function actionAdd(){
         if(Yii::$app->request->isPost) {
-            return parent::edit(AdForm::class, '添加广告成功', null, null, null, function($formModel, $result){
+            return parent::edit(AdForm::class, 'Add Ad Succeed', null, null, null, function($formModel, $result){
                 // 添加操作日志
                 // Log::adminHandle('添加广告:'.$result->TITLE);
             });
         }
         // 获取全部分类
         $allLocation = AdLocation::getAllLocation();
-        return static::notice(['allLocation'=>$allLocation]);
+        $allArticle = Article::findAllAsArray();
+
+        return static::notice(['allLocation'=>$allLocation, 'allArticle' => $allArticle]);
     }
 
     /**
@@ -93,7 +98,7 @@ class AdController extends BaseController
     public function actionEdit(){
         $id = Yii::$app->request->get('id');
         if(Yii::$app->request->isPost) {
-            return parent::edit(AdForm::class, '编辑广告成功', null, null, null, function($formModel, $result){
+            return parent::edit(AdForm::class, 'Edit Ad Succeed', null, null, null, function($formModel, $result){
                 // 添加操作日志
                 // Log::adminHandle('编辑广告:'.$result->TITLE);
             });
@@ -101,7 +106,8 @@ class AdController extends BaseController
         $oneData = Ad::findOneAsArray(['ID'=>$id]);
         // 获取全部分类
         $allLocation = AdLocation::getAllLocation();
-        return static::notice(['oneData'=>$oneData, 'allLocation'=>$allLocation]);
+        $allArticle = Article::findAllAsArray();
+        return static::notice(['oneData'=>$oneData, 'allLocation'=>$allLocation, 'allArticle' => $allArticle]);
     }
 
     /**
@@ -120,6 +126,33 @@ class AdController extends BaseController
         return $result;
     }
 
+    /**
+     * 隐藏
+     * @return mixed
+     * @throws \yii\db\Exception
+     * @throws \yii\web\HttpException
+     */
+    public function actionAdHide(){
+        $adForm = new AdForm();
+        $result = static::hide(Ad::class, 'hide', function ($selected) use ($adForm) {
+        }, function ($selected) use ($adForm) {
+        }, true);
+        return $result;
+    }
+
+    /**
+     * 取消隐藏
+     * @return mixed
+     * @throws \yii\db\Exception
+     * @throws \yii\web\HttpException
+     */
+    public function actionAdUnHide(){
+        $adForm = new AdForm();
+        $result = static::hide(Ad::class, 'un-hide', function ($selected) use ($adForm) {
+        }, function ($selected) use ($adForm) {
+        }, true);
+        return $result;
+    }
     /**
      * 排序
      * @return mixed

+ 25 - 0
backendApi/modules/v1/controllers/ArticleController.php

@@ -138,4 +138,29 @@ class ArticleController extends BaseController
         return $result;
     }
 
+    /**
+     * 获取文章详细
+     * @return mixed
+     * @throws \yii\web\HttpException
+     */
+    public function actionDetail()
+    {
+        $id = \Yii::$app->request->get('id');
+        $data = null;
+        if($id){
+            $data = Article::findOneAsArray('ID=:ID AND STATUS=1', [':ID'=>$id], 'ID,TITLE,CID,CREATED_AT');
+        }
+        if($data){
+            // 暂时先从文件中取内容
+            $path = \Yii::getAlias('@common/runtime/articleContent/').$data['ID'];
+            if(!file_exists($path)){
+                $data['CONTENT'] = '';
+            } else {
+                $data['CONTENT'] = file_get_contents($path);
+            }
+            return static::notice($data);
+        } else {
+            return static::notice('Article not exists!', 400); // 文章不存在
+        }
+    }
 }

+ 39 - 0
backendApi/modules/v1/controllers/BaseController.php

@@ -126,6 +126,45 @@ class BaseController extends \yii\rest\ActiveController {
         }
     }
 
+    /**
+     * 隐藏方法
+     *
+     */
+    public static function hide($modelClass, $statusTo, callable $beforeFun = null, callable $afterFun = null) {
+        $selected = \Yii::$app->request->get('selected');
+        if (!$selected) {
+            $selected = \Yii::$app->request->post('selected');
+        }
+        if (!$selected) {
+            return self::notice('must select one item to hide', 500); // 必须选择一条删除数据
+        }
+        if (is_array($selected)) {
+            $condition = ['AND', ['IN', 'ID', $selected]];
+            $params = [];
+        } else {
+            $condition = 'ID=:ID';
+            $params = [':ID' => $selected];
+        }
+        $transaction = \Yii::$app->db->beginTransaction();
+        try {
+            if (!is_array($selected)) {
+                $selected = [$selected];
+            }
+            if ($beforeFun) $beforeFun($selected);
+            if ($statusTo == 'hide') {
+                $modelClass::updateAll(['STATUS' => 0], $condition, $params);
+            } else {
+                $modelClass::updateAll(['STATUS' => 1], $condition, $params);
+            }
+            if ($afterFun) $afterFun($selected);
+            $transaction->commit();
+            return self::notice('hide successfully');//删除成功
+        } catch (Exception $e) {
+            $transaction->rollBack();
+            return self::notice($e->getMessage(), 500);
+        }
+    }
+
     /**
      * 删除方法
      * @param $modelClass

+ 7 - 7
backendApi/modules/v1/models/lists/user/MoveList.php

@@ -149,17 +149,17 @@ class MoveList extends \common\libs\dataList\DataList implements DataListInterfa
     {
         if(!$this->filterTypes){
             $this->filterTypes = [
-                'MOVE_USER_NAME'=> ['isUserTable' => false,'name'=> 'Mobile members'],//移动的会员
-                'MOVE_REAL_NAME'=> ['isUserTable' => false,'name'=> 'Mobile members name'],//移动的会员姓名
-                'filterStatus'=> ['isUserTable' => false,'name'=> 'Audit status'],//审核状态
+                'MOVE_USER_NAME'=> ['isUserTable' => false,'name'=> 'Move member code'], // 移动的会员
+                'MOVE_REAL_NAME'=> ['isUserTable' => false,'name'=> 'Move member name'], // 移动的会员姓名
+                'filterStatus'=> ['isUserTable' => false,'name'=> 'Status'], // 审核状态
 //                'moveType'=> ['isUserTable' => false,'name'=> '移网类型', 'other'=> 'select','selectData'=>UserMove::TYPE_NAME],
 //                'FROM_USER_NAME'=> ['isUserTable' => false,'name'=> '移动前接点'],
 //                'TO_USER_NAME'=> ['isUserTable' => false,'name'=> '移动后接点', 'other'=> 'decLevel'],
-                'PERIOD_NUM'=> ['isUserTable' => false,'name'=> 'Number of periods when moving'],//移动时的期数
-                'MOVE_ADMIN_NAME'=> ['isUserTable' => false,'name'=> 'Mobile administrator'],//移网管理员
-                'AUDIT_ADMIN_NAME'=> ['isUserTable' => false,'name'=> 'Audit administrator'],//审核管理员
+                'PERIOD_NUM'=> ['isUserTable' => false,'name'=> 'Period of moving'], // 移动时的期数
+                'MOVE_ADMIN_NAME'=> ['isUserTable' => false,'name'=> 'Administrator of moving'], // 移网管理员
+                'AUDIT_ADMIN_NAME'=> ['isUserTable' => false,'name'=> 'Administrator of reviewing'], // 审核管理员
 //                'CREATED_AT' => ['isUserTable' => false, 'name' => '申请时间', 'other' => 'date'],
-                'AUDITED_AT' => ['isUserTable' => false, 'name' => 'Audit time', 'other' => 'date'],//审核时间
+                'AUDITED_AT' => ['isUserTable' => false, 'name' => 'Audit time', 'other' => 'Review time'], // 审核时间
             ];
         }
         return $this->filterTypes;

+ 1 - 1
backendEle/src/components/ExcelUploader.vue

@@ -113,7 +113,7 @@
       uploaderHandleSuccess(response, file) {
         if (response.success) {
           this.$message({
-            message: '上传成功',
+            message: 'Successful',
             type: 'success'
           })
           // 显示进度框

+ 3 - 3
backendEle/src/components/Uploader.vue

@@ -99,7 +99,7 @@ export default {
       else if (this.defaultImageUrl !== null) {
         //this.uploaderShow = false
         //this.uploaderDisabled = true
-        
+
         this.uploaderLoading = false
         return this.defaultImageUrl
       }
@@ -127,7 +127,7 @@ export default {
       // console.log(response)
       if (response.success) {
         this.$message({
-          message: '上传成功',
+          message: 'Successful',
           type: 'success'
         })
         this.successImageUrl = URL.createObjectURL(file.raw)
@@ -167,4 +167,4 @@ export default {
     color: #8c939d;
     text-align: center;
   }
-</style>
+</style>

+ 22 - 10
backendEle/src/router/index.js

@@ -1458,6 +1458,18 @@ export const constantRouterMap = [
           ],
         },
       },
+      {
+        path: '/article/detail/:id',
+        component: _import('article/detail'),
+        name: 'article_detail',
+        meta: {
+          title: 'Article Detail',
+          breadcrumb: [
+            {title: 'Dashboard', path: '/dashboard/index'},
+            {title: 'Article Management', path: '/article/list'},
+          ],
+        },
+      },
     ]
   },
   {
@@ -1648,7 +1660,7 @@ export const constantRouterMap = [
           title: 'Ad',
           breadcrumb: [
             {title: 'Dashboard', path: '/dashboard/index'},
-            {title: 'Ad management', path: '/ad/location'},
+            {title: 'Ad Management', path: '/ad/location'},
           ],
         },
       },
@@ -1657,12 +1669,12 @@ export const constantRouterMap = [
         component: _import('ad/list'),
         name: 'ad_list',
         meta: {
-          title: '广告列表',
+          title: 'Ad List', // 广告列表
           highLight: '/ad/location',
           breadcrumb: [
             {title: 'Dashboard', path: '/dashboard/index'},
-            {title: '广告管理', path: '/ad/location'},
-            {title: '广告位', path: '/ad/location'},
+            {title: 'Ad Management', path: '/ad/location'}, // 广告管理
+            {title: 'Ad Location', path: '/ad/location'}, // 广告位
           ],
         },
       },
@@ -1671,12 +1683,12 @@ export const constantRouterMap = [
         component: _import('ad/edit'),
         name: 'ad_add',
         meta: {
-          title: '添加广告',
+          title: 'Ad Add', // 添加广告
           highLight: '/ad/location',
           breadcrumb: [
             {title: 'Dashboard', path: '/dashboard/index'},
-            {title: '广告管理', path: '/ad/location'},
-            {title: '广告位', path: '/ad/location'},
+            {title: 'Ad Management', path: '/ad/location'}, // 广告管理
+            {title: 'Ad Location', path: '/ad/location'}, // 广告位
           ],
         },
       },
@@ -1685,12 +1697,12 @@ export const constantRouterMap = [
         component: _import('ad/edit'),
         name: 'ad_edit',
         meta: {
-          title: '编辑广告',
+          title: 'Ad Edit', // 编辑广告
           highLight: '/ad/location',
           breadcrumb: [
             {title: 'Dashboard', path: '/dashboard/index'},
-            {title: '广告管理', path: '/ad/location'},
-            {title: '广告位', path: '/ad/location'},
+            {title: 'Ad Management', path: '/ad/location'}, // 广告管理
+            {title: 'Ad Location', path: '/ad/location'}, // 广告位
           ],
         },
       },

+ 8 - 1
backendEle/src/utils/tool.js

@@ -2,7 +2,7 @@ import errorCode from './errorCode'
 import baseInfo from './baseInfo'
 import userInfo from './userInfo'
 import router from '@/router'
-import {PRICE_IS_ROUND} from './config'
+import {PRICE_IS_ROUND,SERVER_API_DOMAIN} from './config'
 import ElementUI from 'element-ui'
 
 let tool = {
@@ -261,6 +261,13 @@ let tool = {
       let searchStr = new RegExp('(\\?|&)('+paramName+'=)([^&]*)(&|$)')
       window.location.href = window.location.href.replace(searchStr, '$1$2'+value+'$4')
     }
+  },
+
+  imageRenderSoup(cover) {
+    return cover.indexOf(SERVER_API_DOMAIN) > 0
+  },
+  imageRenderLang(cover) {
+    return SERVER_API_DOMAIN + '/uploads/' + cover
   }
 }
 

+ 54 - 15
backendEle/src/views/ad/edit.vue

@@ -2,26 +2,31 @@
   <div v-loading="loading">
     <div class="white-box">
       <el-form ref="form" :model="form" label-width="100px" style="">
-        <el-form-item label="标题">
+        <el-form-item label="Title"> <!-- 标题 -->
           <el-input v-model="form.title" style="width: 400px;">></el-input>
         </el-form-item>
-        <el-form-item label="广告位">
-          <el-select v-model="form.lid" placeholder="请选择广告位" style="width: 400px;">
+        <el-form-item label="Ad Location"> <!-- 广告位 -->
+          <el-select v-model="form.lid" placeholder="Select Ad Location" style="width: 400px;"> <!-- 请选择广告位 -->
             <el-option v-for="item in allLocation" :label="item.LOCATION_NAME" :value="item.ID"
                        :key="item.ID"></el-option>
           </el-select>
         </el-form-item>
-        <el-form-item label="广告类型">
-          <el-select v-model="form.type" placeholder="请选择广告类型" style="width: 400px;">
-            <el-option label="外链" value="1" :key="1"></el-option>
-            <el-option label="文章" value="2" :key="2"></el-option>
+        <el-form-item label="Type"> <!-- 广告类型 -->
+          <el-select v-model="form.type" placeholder="Select Type" style="width: 400px;"> <!-- 请选择广告类型 -->
+            <el-option label="External Link" value="1" :key="1"></el-option> <!-- 外链 -->
+            <el-option label="Article" value="2" :key="2"></el-option> <!-- 文章 -->
           </el-select>
         </el-form-item>
-        <el-form-item :label="form.type==='1' ? '链接地址' : '文章ID'">
-          <el-input v-model="form.content" style="width: 400px;">></el-input>
-          <span class="note">注:外链请明确输入 http://或https://,文章则不需要输入</span>
+        <el-form-item v-if="form.type==='1'" label="Url"> <!-- '链接地址' '文章ID' -->
+          <el-input v-model="url" style="width: 400px;"></el-input>
+          <span class="note"></span> <!-- 注:外链请明确输入 http://或https://,文章则不需要输入 -->
         </el-form-item>
-        <el-form-item label="广告图片">
+        <el-form-item v-else label="Article"> <!-- '文章ID' -->
+          <el-select v-model="article" placeholder="Select Article" style="width: 400px;">
+            <el-option v-for="item in allArticle" :label="item.TITLE" :value="item.ID" :key="item.ID"></el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="Image"> <!-- 广告图片 -->
           <leo-uploader :requestRoute="'ad/upload'" :defaultImageUrl="defaultImageUrl" width="400px" height="160px"
                         @on-success="handleSuccess"></leo-uploader>
         </el-form-item>
@@ -36,6 +41,7 @@
 <script>
 import network from '../../utils/network'
 import LeoUploader from '../../components/Uploader'
+import {SERVER_API_HTTP_TYPE,SERVER_API_DOMAIN} from '@/utils/config'
 
 export default {
   name: 'ad_edit',
@@ -46,16 +52,28 @@ export default {
         this.form.title = response.oneData.TITLE
         this.form.lid = response.oneData.LID
         this.form.type = response.oneData.TYPE
+
+        this.imageAd = response.oneData.IMAGE;
+        this.form.image = response.oneData.IMAGE.indexOf('http') > -1 ? response.oneData.IMAGE : SERVER_API_HTTP_TYPE + SERVER_API_DOMAIN + '/uploads/' + response.oneData.IMAGE;
+        this.defaultImageUrl = response.oneData.IMAGE.indexOf('http') > -1 ? response.oneData.IMAGE : SERVER_API_HTTP_TYPE + SERVER_API_DOMAIN + '/uploads/' + response.oneData.IMAGE;
+
         this.form.content = response.oneData.CONTENT
-        this.form.image = response.oneData.IMAGE
-        this.defaultImageUrl = response.oneData.IMAGE
+        if (response.oneData.TYPE === '1') {
+            this.url = response.oneData.CONTENT
+        } else {
+            this.article = response.oneData.CONTENT
+        }
+
         this.allLocation = response.allLocation
+        this.allArticle = response.allArticle
+
         this.loading = false
         this.isEdit = true
       })
     } else {
       network.getData('ad/add').then(response => {
         this.allLocation = response.allLocation
+        this.allArticle = response.allArticle
         this.loading = false
       })
     }
@@ -74,6 +92,10 @@ export default {
       loading: false,
       submitButtonStat: false,
       isEdit: false,
+      imageAd: '',
+      allArticle: [],
+      url: '',
+      article: '',
     }
   },
   methods: {
@@ -83,6 +105,9 @@ export default {
       if (this.$route.name === 'ad_edit') {
         path = 'ad/edit/' + this.$route.params.id
       }
+
+      this.form.image = this.imageAd
+      this.form.content = this.form.type === '1' ? this.url : this.article
       network.postData(path, this.form).then(response => {
         this.submitButtonStat = false
         this.$message({
@@ -90,13 +115,27 @@ export default {
           type: 'success'
         })
         this.$router.go(-1)
-      }).catch(response => {
+      }).catch(_ => {
         this.submitButtonStat = false
       })
     },
     handleSuccess (imageUrl) {
-      this.form.image = imageUrl
+      this.imageAd = imageUrl
+      this.form.image = imageUrl.indexOf('http') > -1 ? imageUrl : SERVER_API_HTTP_TYPE + SERVER_API_DOMAIN + '/uploads/' + imageUrl;
+      this.defaultImageUrl = imageUrl.indexOf('http') > -1 ? imageUrl : SERVER_API_HTTP_TYPE + SERVER_API_DOMAIN + '/uploads/' + imageUrl;
     },
+  },
+  watch: {
+      'form.type': {
+          deep: true,
+          handler: function handler(modern) {
+              if (modern === '1') {
+                  this.article = ''
+              } else {
+                  this.url = ''
+              }
+          }
+      }
   }
 }
 </script>

+ 121 - 15
backendEle/src/views/ad/list.vue

@@ -5,58 +5,78 @@
                 @selection-change="handleSelectionChange" @row-click="handleExpand">
         <el-table-column type="expand">
           <template slot-scope="scope">
-            <img :src="scope.row.IMAGE" :alt="scope.row.TITLE">
+            <a v-if="scope.row.TYPE === '1'" :href="getHref(scope.row.CONTENT)" target="_blank" class="islide">
+                <img :src="getImage(scope.row.IMAGE)" width="100px" height="100px" :alt="scope.row.TITLE">
+            </a>
+            <router-link v-else :to="`/article/detail/${scope.row.CONTENT}`" target="_blank" class="islide">
+                <img :src="getImage(scope.row.IMAGE)" width="100px" height="100px" :alt="scope.row.TITLE">
+            </router-link>
           </template>
         </el-table-column>
         <el-table-column type="selection" width="55"></el-table-column>
-        <el-table-column label="广告标题" prop="TITLE" width="250">
+        <el-table-column label="Ad Title" prop="TITLE" width="250"> <!-- 广告标题 -->
           <template slot-scope="scope">
             <el-tag type="" size="small" class="no-border">{{scope.row.TITLE}}</el-tag>
           </template>
         </el-table-column>
-        <el-table-column label="广告位" width="150">
+        <el-table-column label="Ad Location" width="150"> <!-- 广告位 -->
           <template slot-scope="scope">
             <el-tag type="warning" size="small" class="no-border">{{allData.allLocation[scope.row.LID].LOCATION_NAME}}</el-tag>
           </template>
         </el-table-column>
-        <el-table-column label="类型">
+        <el-table-column label="Type"> <!-- 类型 -->
           <template slot-scope="scope">
             <template v-if="scope.row.TYPE === '1'">
-              <el-tag type="success">外链</el-tag>
+              <el-tag type="success">External Links</el-tag> <!-- 外链 -->
             </template>
             <template v-else-if="scope.row.TYPE === '2'">
-              <el-tag>文章</el-tag>
+              <el-tag>Article</el-tag> <!-- 文章 -->
             </template>
           </template>
         </el-table-column>
-        <el-table-column label="连接或文章ID" prop="CONTENT" width="120"></el-table-column>
-        <el-table-column label="排序" width="100">
+        <el-table-column label="Content" prop="CONTENT" width="120">
+          <template slot-scope="scope">
+            <div v-if="scope.row.TYPE === '1'">
+                <el-link type="primary" target="_blank" :href="getHref(scope.row.CONTENT)">{{ scope.row.CONTENT }}</el-link>
+            </div><!-- 链接 -->
+            <div v-else-if="scope.row.TYPE === '2'">
+                <router-link :to="`/article/detail/${scope.row.CONTENT}`" target="_blank" style="cursor: pointer;">{{ getContent(scope.row.CONTENT) }}</router-link>
+            </div><!-- 文章 -->
+          </template>
+        </el-table-column>
+        <el-table-column label="Sort" width="100"> <!-- 排序 -->
           <template slot-scope="scope">
             <el-input v-model="scope.row.SORT" min="0" max="99" @change="handleChangeSort(scope.row, scope.row.SORT)"
                       @click.native.stop=""></el-input>
           </template>
         </el-table-column>
-        <el-table-column label="创建人">
+        <el-table-column label="Creator"> <!-- 创建人 -->
           <template slot-scope="scope">
             {{scope.row.CREATE_ADMIN_NAME}}
           </template>
         </el-table-column>
-        <el-table-column label="创建时间" width="180">
+        <el-table-column label="Created Time" width="180"> <!-- 创建时间 -->
           <template slot-scope="scope">
             {{tool.formatDate(scope.row.CREATED_AT)}}
           </template>
         </el-table-column>
-        <el-table-column label="修改人">
+        <el-table-column label="Modified By"> <!-- 修改人 -->
           <template slot-scope="scope">
             {{scope.row.UPDATE_ADMIN_NAME}}
           </template>
         </el-table-column>
-        <el-table-column label="修改时间" width="180">
+        <el-table-column label="Modified Time" width="180"> <!-- 修改时间 -->
           <template slot-scope="scope">
             {{tool.formatDate(scope.row.UPDATED_AT)}}
           </template>
         </el-table-column>
-        <el-table-column fixed="right" label="操作" width="180">
+        <el-table-column label="Status"> <!-- 状态 -->
+          <template slot-scope="scope">
+            <div v-if="scope.row.STATUS === '1'">Show</div>
+            <div v-else>Hide</div>
+          </template>
+        </el-table-column>
+        <el-table-column fixed="right" label="Action" width="180"> <!-- 操作 -->
           <template slot-scope="scope">
             <el-dropdown size="small" trigger="click" v-if="permission.hasPermission(`ad/ad-delete`) || permission.hasPermission(`ad/edit`)">
               <el-button type="primary" size="small" @click.stop="">
@@ -65,6 +85,8 @@
               <el-dropdown-menu slot="dropdown">
                 <el-dropdown-item command="edit" @click.native="handleEdit(scope.row)" v-if="permission.hasPermission(`ad/edit`)">Edit</el-dropdown-item>
                 <el-dropdown-item command="delete" @click.native="handleDelete(scope.row)" v-if="permission.hasPermission(`ad/ad-delete`)">Delete</el-dropdown-item>
+                <el-dropdown-item command="hide" @click.native="handleHide(scope.row)" v-if="permission.hasPermission(`ad/ad-hide`)">Hide</el-dropdown-item>
+                <el-dropdown-item command="un-hide" @click.native="handleUnHide(scope.row)" v-if="permission.hasPermission(`ad/ad-un-hide`)">UnHide</el-dropdown-item>
               </el-dropdown-menu>
             </el-dropdown>
           </template>
@@ -77,9 +99,11 @@
           </el-button>
           <el-dropdown-menu slot="dropdown">
             <el-dropdown-item command="delete" @click.native="handleMuliDel()">Delete</el-dropdown-item>
+            <el-dropdown-item command="hide" @click.native="handleMultiHide()">Hide</el-dropdown-item>
+            <el-dropdown-item command="un-hide" @click.native="handleMultiUnHide()">UnHide</el-dropdown-item>
           </el-dropdown-menu>
         </el-dropdown>
-        <el-button type="primary" size="small" @click="handleAdd" icon="el-icon-plus" v-if="permission.hasPermission(`ad/add`)">添加广告</el-button>
+        <el-button type="primary" size="small" @click="handleAdd" icon="el-icon-plus" v-if="permission.hasPermission(`ad/add`)">Add Ad</el-button>
         <pagination :total="totalCount" :page_size="pageSize" @size-change="handleSizeChange" @current-change="handleCurrentChange"></pagination>
       </div>
     </div>
@@ -93,6 +117,8 @@ import tool from '@/utils/tool'
 import store from '@/utils/vuexStore'
 import permission from '@/utils/permission'
 import Pagination from '@/components/Pagination'
+import {SERVER_API_HTTP_TYPE,SERVER_API_DOMAIN} from '@/utils/config'
+import article from "../article";
 
 export default {
   name: 'ad_list',
@@ -112,6 +138,7 @@ export default {
       pageSize: 20,
       tool: tool,
       permission: permission,
+      allArticle: [],
     }
   },
   methods: {
@@ -136,9 +163,21 @@ export default {
     handleDelete (row) {
       this.delData(row.ID)
     },
+    handleHide (row) {
+      this.hideData(row.ID)
+    },
+    handleUnHide(row) {
+      this.unHideData(row.ID)
+    },
     handleMuliDel () {
       this.delData()
     },
+    handleMultiHide () {
+      this.hideData()
+    },
+    handleMultiUnHide () {
+      this.unHideData()
+    },
     handleChangeSort (row, sort) {
       network.getData('/ad/sort', {id: row.ID, sort: sort}).then(response => {
         this.getData(this.currentPage, this.pageSize)
@@ -149,11 +188,12 @@ export default {
       let obj = this
       network.getPageData(this, `ad/list/${this.$route.params.lid}`, page, pageSize, null, function (response) {
         obj.allData = response
+        obj.allArticle = response.allArticle
       })
     },
     delData (id = null) {
       let obj = this
-      obj.$confirm('确定删除选定的数据?', 'Notice', {
+      obj.$confirm('Are you sure to delete the selected data?', 'Notice', { // 确定删除选定的数据?
         confirmButtonText: 'confirm', // 确定
         cancelButtonText: 'cancel', // 取消
         type: 'warning'
@@ -180,6 +220,72 @@ export default {
 
       })
     },
+    hideData (id = null) {
+      let obj = this
+      obj.$confirm('Are you sure to hide the selected data?', 'Notice', { // 确定删除选定的数据?
+        confirmButtonText: 'confirm', // 确定
+        cancelButtonText: 'cancel', // 取消
+        type: 'warning'
+      }).then(() => {
+        let selectedIds = []
+        if (id === null) {
+          for (let val of obj.multipleSelection) {
+            selectedIds.push(val.ID)
+          }
+        } else {
+          selectedIds.push(id)
+        }
+        return network.postData(`ad/ad-hide`, {
+          selected: selectedIds
+        })
+      }).then(response => {
+        this.$message({
+          message: response,
+          type: 'success'
+        })
+        obj.getData(obj.currentPage, obj.pageSize)
+      }).catch(response => {
+
+      })
+    },
+    unHideData (id = null) {
+      let obj = this
+      obj.$confirm('Are you sure to un-hide the selected data?', 'Notice', { // 确定删除选定的数据?
+        confirmButtonText: 'confirm', // 确定
+        cancelButtonText: 'cancel', // 取消
+        type: 'warning'
+      }).then(() => {
+        let selectedIds = []
+        if (id === null) {
+          for (let val of obj.multipleSelection) {
+            selectedIds.push(val.ID)
+          }
+        } else {
+          selectedIds.push(id)
+        }
+        return network.postData(`ad/ad-un-hide`, {
+          selected: selectedIds
+        })
+      }).then(response => {
+        this.$message({
+          message: response,
+          type: 'success'
+        })
+        obj.getData(obj.currentPage, obj.pageSize)
+      }).catch(response => {
+
+      })
+    },
+    getImage(imageUrl) {
+      return imageUrl.indexOf('http') > -1 ? imageUrl : SERVER_API_HTTP_TYPE + SERVER_API_DOMAIN + '/uploads/' + imageUrl;
+    },
+    getContent(aid) {
+      let titles = this.allArticle.filter(article => article.ID === aid).map(article => article.TITLE);
+      return titles.length > 0 ? titles[0] : aid;
+    },
+    getHref(link) {
+        return link.indexOf('http') > -1 ? link : 'http://' + link;
+    },
   }
 }
 

+ 1 - 1
backendEle/src/views/ad/location.vue

@@ -35,7 +35,7 @@
                 Action<i class="el-icon-arrow-down el-icon--right"></i>
               </el-button>
               <el-dropdown-menu slot="dropdown">
-                <el-dropdown-item command="edit" @click.native="handleShow(scope.row)">查看</el-dropdown-item> <!--  -->
+                <el-dropdown-item command="edit" @click.native="handleShow(scope.row)">View</el-dropdown-item> <!--  -->
               </el-dropdown-menu>
             </el-dropdown>
           </template>

+ 57 - 0
backendEle/src/views/article/detail.vue

@@ -0,0 +1,57 @@
+<template>
+  <div v-loading="loading">
+    <div class="white-box">
+      <div class="white-box-title">
+        <h1>{{title}}</h1>
+        <span>{{tool.formatDate(createdAt)}}</span>
+      </div>
+      <div v-html="content" class="white-box-content">
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import Vue from 'vue'
+import network from '@/utils/network'
+import tool from '@/utils/tool'
+import store from '@/utils/vuexStore'
+
+export default {
+  name: 'article_detail',
+  mounted () {
+    this.getData()
+  },
+  data () {
+    return {
+      title: null,
+      content: null,
+      createdAt: '',
+      loading: true,
+      tool: tool,
+    }
+  },
+  methods: {
+    handleCurrentChange (page) {
+      this.getData(page, this.pageSize)
+    },
+    handleSizeChange (pageSize) {
+      this.getData(this.currentPage, pageSize)
+    },
+    getData () {
+      network.getData(`article/detail/${this.$route.params.id}`).then(response => {
+        this.title = response.TITLE
+        this.content = response.CONTENT
+        this.createdAt = response.CREATED_AT
+        this.loading = false
+      })
+    },
+  }
+}
+
+</script>
+
+<style scoped>
+  .white-box-title span{color: #999}
+  .white-box-content{font-size: 16px;padding: 15px 0;line-height: 2;}
+</style>

+ 17 - 9
backendEle/src/views/shop/index.vue

@@ -127,11 +127,11 @@
                                 v-model="form.content">
                         </el-input><!-- 请输入内容 -->
                     </el-form-item>
-                    <el-form-item label="order"> <!-- 排序 -->
+                    <el-form-item label="Order"> <!-- 排序 -->
                         <el-input v-model="form.sort"></el-input>
                     </el-form-item>
 
-                    <el-form-item label="upload images"> <!-- 上传图片 -->
+                    <el-form-item label="Upload Images"> <!-- 上传图片 -->
                        <div class='up_load'>
                            <!-- <img v-if="form.cover&&img_show" :src="form.cover" alt=""> -->
                             <leo-uploader
@@ -162,7 +162,7 @@
     import permission from '@/utils/permission'
     import Pagination from '@/components/Pagination'
     import filterHelper from '@/utils/filterHelper'
-    import {FRONTEND_SERVER} from '@/utils/config'
+    import {FRONTEND_SERVER,SERVER_API_HTTP_TYPE,SERVER_API_DOMAIN} from '@/utils/config'
     import store from './../../utils/vuexStore'
      import LeoUploader from '@/components/Uploader';
     export default {
@@ -251,7 +251,9 @@
                 this.$router.push({path: `/shop/goods-add`})
             },
             upLoadSuccess(file){
-                this.form.cover=file;
+                // this.form.cover=file;
+                this.form.cover = SERVER_API_HTTP_TYPE + SERVER_API_DOMAIN + '/uploads/' + file;
+                this.form.coverOrigin = file
                 this.img_show=false;
             },
             handleEditShow(row) {
@@ -308,15 +310,21 @@
                     vueObj.form.content=response.goodsInfo.CONTENT
                     vueObj.form.sort=response.goodsInfo.SORT
                     vueObj.form.id=response.goodsInfo.ID
-                    vueObj.form.cover=response.goodsInfo.COVER
+                    // vueObj.form.cover=response.goodsInfo.COVER
                     vueObj.form.categoryType=parseInt(response.goodsInfo.CATEGORY_TYPE)
                     vueObj.form.taxRate=response.goodsInfo.TAX_RATE
                     // vueObj.form.sellType=vueObj.form.sellType.map((item,index)=>{
                     //   return response.goodsInfo.SELL_TYPE.some(val=>(index+1).toString()==val)
                     //   })
 
-                    this.$forceUpdate()
+                    vueObj.form.coverOrigin = response.goodsInfo.COVER
+                    if (response.goodsInfo.COVER.indexOf('/') === -1) {
+                        vueObj.form.cover = SERVER_API_HTTP_TYPE + SERVER_API_DOMAIN + '/uploads/' + response.goodsInfo.COVER
+                    } else {
+                        vueObj.form.cover = response.goodsInfo.COVER
+                    }
 
+                    this.$forceUpdate()
                 })
             },
             handleEdit() {
@@ -343,6 +351,8 @@
                 })
                 this.form.giftType=sen_gift;
                 this.form.sellType = 1
+                this.form.cover = this.form.coverOrigin;
+                delete this.form.coverOrigin;
 
                 network.postData(path, {...this.form}).then(response => {
                     this.$message({
@@ -385,10 +395,8 @@
             getData (page, pageSize) {
                 let filterData = this.filterModel
                 /*this.allData = response*/
-                network.getPageData(this, 'shop/index', page, pageSize, this.filterModel, response=>{
-                    console.log(response)
+                network.getPageData(this, 'shop/index', page, pageSize, this.filterModel, response => {
                     this.filterTypes = response.filterTypes
-
                 })
             },
             handleGoodUp(id){

+ 2 - 2
backendEle/src/views/user/move.vue

@@ -2,10 +2,10 @@
   <div v-loading="loading">
     <div class="white-box">
       <el-tabs v-model="filterStatus" @tab-click="handleFilterStatusClick">
-        <el-tab-pane label="whole" name="-1" :lazy="true"></el-tab-pane><!-- 全部 -->
+        <el-tab-pane label="All" name="-1" :lazy="true"></el-tab-pane><!-- 全部 -->
         <el-tab-pane label="To be reviewed" name="0" :lazy="true"></el-tab-pane><!-- 待审核 -->
         <el-tab-pane label="Approved" name="1" :lazy="true"></el-tab-pane><!-- 审核通过 -->
-        <el-tab-pane label="Audit reject" name="3" :lazy="true"></el-tab-pane><!-- 审核拒绝 -->
+        <el-tab-pane label="Rejected" name="3" :lazy="true"></el-tab-pane><!-- 审核拒绝 -->
       </el-tabs>
       <div class="filter-box">
         <filter-user ref="filterUser" :filter-types.sync="filterTypes" @select-value="handleFilterUser"></filter-user>

+ 5 - 5
common/helpers/LoggerTool.php

@@ -12,7 +12,7 @@ class LoggerTool
     {
         $logger = new Logger('info');
         // 添加一些处理器
-        $logger->pushHandler(new StreamHandler(__DIR__ . "/../runtime/debug/trace.log", Logger::DEBUG));
+        $logger->pushHandler(new StreamHandler(__DIR__ . "/../runtime/logs/trace.log", Logger::DEBUG));
         $logger->pushHandler(new FirePHPHandler());
         $logger->info(json_encode($message));
     }
@@ -21,7 +21,7 @@ class LoggerTool
     {
         $logger = new Logger('error');
         // 添加一些处理器
-        $logger->pushHandler(new StreamHandler(__DIR__ . "/../runtime/debug/trace.log", Logger::DEBUG));
+        $logger->pushHandler(new StreamHandler(__DIR__ . "/../runtime/logs/error.log", Logger::DEBUG));
         $logger->pushHandler(new FirePHPHandler());
         $logger->error(json_encode($message));
     }
@@ -30,7 +30,7 @@ class LoggerTool
     {
         $logger = new Logger('warning');
         // 添加一些处理器
-        $logger->pushHandler(new StreamHandler(__DIR__ . "/../runtime/debug/trace.log", Logger::DEBUG));
+        $logger->pushHandler(new StreamHandler(__DIR__ . "/../runtime/logs/warning.log", Logger::DEBUG));
         $logger->pushHandler(new FirePHPHandler());
         $logger->warning(json_encode($message));
     }
@@ -39,7 +39,7 @@ class LoggerTool
     {
         $logger = new Logger('notice');
         // 添加一些处理器
-        $logger->pushHandler(new StreamHandler(__DIR__ . "/../runtime/debug/trace.log", Logger::DEBUG));
+        $logger->pushHandler(new StreamHandler(__DIR__ . "/../runtime/logs/notice.log", Logger::DEBUG));
         $logger->pushHandler(new FirePHPHandler());
         $logger->notice(json_encode($message));
     }
@@ -48,7 +48,7 @@ class LoggerTool
     {
         $logger = new Logger('debug');
         // 添加一些处理器
-        $logger->pushHandler(new StreamHandler(__DIR__ . "/../runtime/debug/trace.log", Logger::DEBUG));
+        $logger->pushHandler(new StreamHandler(__DIR__ . "/../runtime/logs/debug.log", Logger::DEBUG));
         $logger->pushHandler(new FirePHPHandler());
         $logger->debug(json_encode($message));
     }

+ 83 - 3
common/helpers/bonus/BonusCalc.php

@@ -16,6 +16,7 @@ use common\helpers\Tool;
 use common\models\CalcBonus;
 use common\models\CalcBonusBD;
 use common\models\CalcBonusBS;
+use common\models\CalcBonusQuarter;
 use common\models\CalcBonusBT;
 use common\models\CalcBonusCF;
 use common\models\CalcBonusFL;
@@ -314,6 +315,12 @@ class BonusCalc extends BaseObject {
             echo('计算车奖' . ($this->_sysConfig['openGarage']['VALUE'] ? '完成' : '关闭').',耗时:' . round($t23 - $t22, 3) . ',内存使用:' . (round(memory_get_usage() / 1024 / 1024, 3)) . 'MB' . PHP_EOL . PHP_EOL);
             $this->_updatePercent(69);
 
+            // 计算季度奖
+            $this->calcQuarter();
+            // 将用户写入缓存
+            $this->calcQuarterUser();
+            $t24 = microtime(true);
+            echo('计算季度奖' . ($this->_sysConfig['openQuarter']['VALUE'] ? '完成' : '关闭').',耗时:' . round($t24 - $t23, 3) . ',内存使用:' . (round(memory_get_usage() / 1024 / 1024, 3)) . 'MB' . PHP_EOL . PHP_EOL);
 
             //把奖金会员写入缓存
             $this->loopMonthBonusUserFromDbToCache();
@@ -1642,6 +1649,23 @@ class BonusCalc extends BaseObject {
         return true;
     }
 
+    /**
+     * 季度奖计算
+     *
+     */
+    public function calcQuarter() {
+        if( !$this->_isCalcMonth || !in_array($this->_calcMonth, [3,6,9,12])) {
+            // 不是结算月,则不进行计算
+            print_r('不是季结点,进这里,不计算季度奖');
+            return false;
+        }
+        $result = \Yii::$app->db->createCommand("CALL QtrCalc(:periodNum)")
+            ->bindValue(':periodNum' , $this->_periodNum )
+            ->execute();
+
+        return $result;
+    }
+
     // 执行蓝星管理奖金的存储过程
     public function calcBsProcedure() {
         if( !$this->_isCalcMonth ) {
@@ -1982,6 +2006,55 @@ class BonusCalc extends BaseObject {
         return true;
     }
 
+    /**
+     * 季度奖写用户缓存
+     *
+     */
+    public function calcQuarterUser(int $offset = 0) {
+        if( !$this->_isCalcMonth || !in_array($this->_calcMonth, [3,6,9,12])) {
+            // 不是结算月,则不进行计算
+            return false;
+        }
+        $allData = CalcBonusQuarter::finduseDbCalc()
+                ->where('PERIOD_NUM=:PERIOD_NUM', [':PERIOD_NUM' => $this->_periodNum])
+                ->groupBy('USER_ID')
+                ->offset($offset)
+                ->limit($this->_limit)
+                ->asArray()
+                ->all();
+        if ($allData){
+            // 达标条件:会员级别:钻卡
+            $config = json_decode($this->_sysConfig['openGL']['OPTIONS'], true);
+            $minDecLevel = $config['mntDec'] ?? [];
+
+            foreach ($allData as $user) {
+                // 扣除相应的复消积分和管理费
+                $deductData = $this->deduct($user['USER_ID'], $user['ORI_BONUS']);
+                $realBonusBs = $deductData['surplus']; // 扣除管理费和复消积分后的实发蓝星奖金
+                $manageTax = $deductData['manageTax']; // 管理费
+                $point = $deductData['reConsumePoints'] + $user['RECONSUME_POINTS'];// 复消积分
+                // 管理奖钻卡发放
+//                if (in_array($user['LAST_DEC_LV'], $minDecLevel)) {
+                // 把对碰后的奖金存入缓存中
+                CalcCache::bonus($user['USER_ID'], $this->_periodNum, 'BONUS_QUARTER', $user['ORI_BONUS'], $deductData);
+                // 加入月奖的会员
+                CalcCache::addHasMonthBonusUsers($user['USER_ID'], $this->_periodNum);
+//                }
+
+                // 更新蓝星奖金存储过程的实发金额数据
+                CalcBonusQuarter::updateAll([
+                    'RECONSUME_POINTS' => $point,
+                    'AMOUNT' => $realBonusBs,
+                    'MANAGE_TAX' => $manageTax],
+                    'USER_ID=:USER_ID AND PERIOD_NUM=:PERIOD_NUM',
+                    [':USER_ID' => $user['USER_ID'], ':PERIOD_NUM' => $this->_periodNum]);
+            }
+            return $this->calcQuarterUser($offset + $this->_limit);
+        }
+        unset($allData);
+        return true;
+    }
+
     /**
      * 蓝星管理奖金
      * @param int $offset
@@ -3724,10 +3797,10 @@ class BonusCalc extends BaseObject {
 
                 $monthSumData = CalcBonus::findUseSlaves()
                 ->select('SUM(BONUS_GX) AS BONUS_GX_SUM, SUM(BONUS_GL) AS BONUS_GL_SUM')
-                ->where('USER_ID=:USER_ID AND CALC_MONTH=:CALC_MONTH', 
+                ->where('USER_ID=:USER_ID AND CALC_MONTH=:CALC_MONTH',
                     [
-                        'USER_ID'=>$userId, 
-                        'CALC_MONTH'=>$this->_calcYearMonth
+                        'USER_ID' => $userId,
+                        'CALC_MONTH' => $this->_calcYearMonth
                     ]
                 )
                 ->asArray()
@@ -3742,6 +3815,11 @@ class BonusCalc extends BaseObject {
             }
         }
 
+        if( $this->_isCalcMonth ) { //季度奖
+            if(in_array($this->_calcMonth, [3,6,9,12])){ // 季度奖
+            }
+        }
+
         $result = [
             'USER_ID' => $userId,
             'LAST_USER_NAME' => $baseInfo['USER_NAME'],
@@ -3815,6 +3893,8 @@ class BonusCalc extends BaseObject {
             'ORI_BONUS_VIP' => $bonus['ORI_BONUS_VIP'],
             'ORI_BONUS_STANDARD' => $standardBonus,
             'ORI_CAPPED_BONUS_QY' => $bonus['ORI_CAPPED_BONUS_QY'], // 团队奖封顶前的奖金
+            'BONUS_QUARTER' => $bonus['BONUS_QUARTER'],
+            'ORI_BONUS_QUARTER' => $bonus['ORI_BONUS_QUARTER'],
 
             'BONUS_TOURISM' => $tourismBonus, // 旅游奖
             'BONUS_VILLA' => $villaBonus, // 房奖

+ 2 - 0
common/helpers/bonus/CalcCache.php

@@ -1478,6 +1478,7 @@ class CalcCache {
             'BONUS_YC' => 0,
             'BONUS_VIP' => 0,
             'BONUS_BS' => 0,
+            'BONUS_QUARTER' => 0,
             'BONUS_YC_EXTRA' => 0,
             'ORI_BONUS_BD' => 0,
             'ORI_BONUS_BS' => 0,
@@ -1485,6 +1486,7 @@ class CalcCache {
             'BONUS_BS_ABBR' => 0,
             'ORI_BONUS_BS_MNT' => 0,
             'ORI_BONUS_BS_ABBR' => 0,
+            'ORI_BONUS_QUARTER' => 0,
             'ORI_BONUS_TG' => 0,
             'ORI_BONUS_XF' => 0,
             'ORI_BONUS_YJ' => 0,

+ 50 - 0
common/models/CalcBonusQuarter.php

@@ -0,0 +1,50 @@
+<?php
+
+namespace common\models;
+
+use Yii;
+
+
+class CalcBonusQuarter extends \common\components\ActiveRecord
+{
+    /**
+     * @inheritdoc
+     */
+    public static function tableName()
+    {
+        return '{{%CALC_BONUS_QUARTER}}';
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function rules()
+    {
+        return [
+            [['USER_ID', 'PERIOD_NUM', 'CALC_MONTH', 'CREATED_AT'], 'required'],
+            [['AMOUNT', 'ORI_BONUS', 'MANAGE_TAX'], 'number'],
+            [['PERIOD_NUM', 'CALC_MONTH', 'CREATED_AT'], 'integer'],
+            [['ID', 'USER_ID'], 'string', 'max' => 32],
+            [['ID'], 'unique'],
+        ];
+    }
+
+    /**
+     * @inheritdoc
+     */
+    public function attributeLabels()
+    {
+        return [
+            'ID' => 'ID',
+            'USER_ID' => '会员ID',
+            'ORI_BONUS' => '原奖金',
+            'MANAGE_TAX' => '管理费',
+            'RECONSUME_POINTS' => '复消积分',
+            'AMOUNT' => '金额',
+            'CALC_YEAR' => '所在结算年',
+            'CALC_MONTH' => '所在结算月',
+            'PERIOD_NUM' => '结算期数',
+            'CREATED_AT' => '创建时间',
+        ];
+    }
+}

+ 14 - 14
common/models/forms/AdForm.php

@@ -43,7 +43,7 @@ class AdForm extends Model
         return [
             [['id', 'title', 'image', 'type', 'lid', 'content', 'sort', 'status'], 'trim'],
             [['id', 'title', 'image', 'type', 'lid', 'content', 'sort', 'status'], 'required'],
-            [['image'], 'url'],
+//            [['image'], 'url'],
             [['id'], 'exist', 'targetClass'=>Ad::class, 'targetAttribute'=>'ID'],
             [['id'], 'initModel'],
             [['lid'], 'exist', 'targetClass'=>AdLocation::class, 'targetAttribute'=>'ID'],
@@ -56,13 +56,13 @@ class AdForm extends Model
     {
         return [
             'id' => 'ID',
-            'title' => '标题',
-            'image' => '图片',
-            'type' => '类型',
-            'lid' => '广告位',
-            'content' => '链接地址或文章ID',
-            'sort' => '排序',
-            'status' => '状态',
+            'title' => 'Title',// 标题
+            'image' => 'Image', // 图片
+            'type' => 'Type', // 类型
+            'lid' => 'Ad', // 广告位
+            'content' => 'External link or article ID', // 链接地址或文章ID
+            'sort' => 'Order', // 排序
+            'status' => 'State', // 状态
         ];
     }
 
@@ -96,7 +96,7 @@ class AdForm extends Model
      */
     public function isType($attribute){
         if(!in_array($this->type, [Ad::TYPE_LINK, Ad::TYPE_ARTICLE])){
-            $this->addError($attribute, '类型错误');
+            $this->addError($attribute, 'Type error'); // 类型错误
         }
     }
 
@@ -106,7 +106,7 @@ class AdForm extends Model
      */
     public function isContent($attribute){
         if($this->content == ""){
-            $this->addError($attribute, '内容错误');
+            $this->addError($attribute, 'Content error'); // 内容错误
         }
     }
 
@@ -152,11 +152,11 @@ class AdForm extends Model
         }
         if($this->scenario == 'add'){
             $this->adminOperateLogger->afterInsert($model)->clean()->save([
-                'optType' => '添加广告',
+                'optType' => 'Add',
             ]);
         }else{
             $this->adminOperateLogger->afterUpdate($model)->clean()->save([
-                'optType' => '编辑广告',
+                'optType' => 'Edit',
             ]);
         }
         return $model;
@@ -178,7 +178,7 @@ class AdForm extends Model
             return null;
         }
         $this->adminOperateLogger->afterUpdate($model)->clean()->save([
-            'optType' => '广告排序',
+            'optType' => 'Ad Order', // 广告排序
         ]);
         return $model;
     }
@@ -215,7 +215,7 @@ class AdForm extends Model
      */
     public function delete($selected) {
         $this->adminOperateLogger->clean()->save([
-            'optType' => '删除广告',
+            'optType' => 'Delete Ad', // 删除广告
         ]);
     }
 }

+ 5 - 10
common/models/forms/UploadForm.php

@@ -32,7 +32,7 @@ class UploadForm extends Model {
 
     private $_ocrResult;
     private $_remoteScenario = [
-        'idCardFront', 'idCardBack', 'ad', 'invoiceFront','proveFront','goodsImg'
+//        'idCardFront', 'idCardBack', 'ad', 'invoiceFront','proveFront','goodsImg'
     ];
 
     /**
@@ -143,6 +143,8 @@ class UploadForm extends Model {
                     $uploadCategory = Uploads::CATEGORY_ID_CARD;
                     $uploadRemark = $oneUser['REAL_NAME'] . '身份证背面';
                     break;
+                case 'proveFront':
+                case 'goodsImg':
                 case 'ad':
                     $uploadCategory = Uploads::CATEGORY_IMAGE;
                     $uploadRemark = $this->file->baseName;
@@ -151,14 +153,6 @@ class UploadForm extends Model {
                     $uploadCategory = Uploads::CATEGORY_EXCEL;
                     $uploadRemark = $this->file->baseName;
                     break;
-                case 'proveFront':
-                    $uploadCategory = Uploads::CATEGORY_IMAGE;
-                    $uploadRemark = $this->file->baseName;
-                    break;
-                case 'goodsImg':
-                    $uploadCategory = Uploads::CATEGORY_IMAGE;
-                    $uploadRemark = $this->file->baseName;
-                    break;
                 default :
                     $uploadCategory = Uploads::CATEGORY_UN_KNOW;
                     $uploadRemark = $this->file->baseName;
@@ -189,7 +183,8 @@ class UploadForm extends Model {
                 $uploadInfo = [
                     'fileName' => $this->file->baseName . '.' . $this->file->extension,
                     'category' => $uploadCategory,
-                    'url' => $localPath,
+//                    'url' => $localPath,
+                    'url' => $this->file->baseName . '.' . $this->file->extension,
                     'fileSize' => null,
                     'md5' => null,
                 ];

+ 1 - 1
frontendApi/modules/v1/controllers/BonusController.php

@@ -845,7 +845,7 @@ class BonusController extends BaseController {
             //$formModel->token = \Yii::$app->request->post('uploadToken');
             $formModel->token = \Yii::$app->request->request('uploadToken');
             if ($formModel->file && $formModel->upload()) {
-                return static::notice('上传成功');
+                return static::notice('Successful');
             } else {
                 return static::notice(Form::formatErrorsForApi($formModel->getErrors()), 400);
             }

+ 2 - 2
frontendApi/modules/v1/controllers/FinanceController.php

@@ -281,7 +281,7 @@ class FinanceController extends BaseController {
             //$formModel->token = \Yii::$app->request->post('uploadToken');
             $formModel->token = \Yii::$app->request->request('uploadToken');
             if ($formModel->file && $formModel->upload()) {
-                return static::notice('上传成功');
+                return static::notice('Successful');
             } else {
                 return static::notice(Form::formatErrorsForApi($formModel->getErrors()), 400);
             }
@@ -547,7 +547,7 @@ class FinanceController extends BaseController {
             $formModel->token = \Yii::$app->request->request('uploadToken');
             $formModel->rechargeId = $id;
             if ($formModel->file && $formModel->upload()) {
-                return static::notice('上传成功');
+                return static::notice('Successful');
             } else {
                 return static::notice(Form::formatErrorsForApi($formModel->getErrors()), 400);
             }

+ 1 - 1
frontendApi/modules/v1/controllers/UserController.php

@@ -137,7 +137,7 @@ class UserController extends BaseController {
             //$formModel->token = \Yii::$app->request->post('uploadToken');
             $formModel->token = \Yii::$app->request->request('uploadToken');
             if ($formModel->file && $formModel->upload()) {
-                return static::notice('上传成功');
+                return static::notice('Successful');
             } else {
                 return static::notice(Form::formatErrorsForApi($formModel->getErrors()), 400);
             }

+ 1 - 1
frontendEle/src/components/Uploader.vue

@@ -112,7 +112,7 @@
         this.$message.closeAll()
         if (response.success) {
           this.$message({
-            message: '上传成功',
+            message: 'Successful',
             type: 'success'
           })
           this.successImageUrl = URL.createObjectURL(file.raw)

+ 11 - 5
frontendEle/src/views/dashboard/index.vue

@@ -34,12 +34,14 @@
     <el-carousel trigger="click" :height="bannerHeight+'px'">
       <el-carousel-item v-for="(item,key) in slides" :key="key">
         <template v-if="item.TYPE==='1'">
-          <a :href="item.CONTENT" target="_blank" class="islide">
-            <img ref="bannerHeight" :src="item.IMAGE" alt="" @load="imgLoad">
-          </a>
+          <router-link :to="`/shop/index`" target="_self" class="islide">
+            <img ref="bannerHeight" :src="imageArticle(item.IMAGE)" alt="" @load="imgLoad">
+          </router-link>
         </template>
         <template v-else>
-          <router-link :to="`/article/detail/${item.CONTENT}`" target="_blank" class="islide"><img ref="bannerHeight" :src="item.IMAGE" alt="" @load="imgLoad"></router-link>
+          <router-link :to="`/article/detail/${item.CONTENT}`" target="_blank" class="islide">
+            <img ref="bannerHeight" :src="imageArticle(item.IMAGE)" alt="" @load="imgLoad">
+          </router-link>
         </template>
       </el-carousel-item>
     </el-carousel>
@@ -70,6 +72,7 @@
   import baseInfo from '@/utils/baseInfo'
   import userInfo from '@/utils/userInfo'
   import countUp from 'vue-countup-v2'
+  import {SERVER_API_HTTP_TYPE,SERVER_API_DOMAIN} from '@/utils/config'
 
   export default {
     name: 'dashboard_index',
@@ -154,7 +157,10 @@
             _this.bannerHeight = _this.$refs.bannerHeight[0].height
           })
         }
-      }
+      },
+      imageArticle(imageUrl) {
+        return imageUrl.indexOf('http') > -1 ? imageUrl : SERVER_API_HTTP_TYPE + SERVER_API_DOMAIN + '/uploads/' + imageUrl;
+      },
     }
   }
 </script>

+ 60 - 15
frontendEle/src/views/shop/index.vue

@@ -19,7 +19,8 @@
 
                       <el-table-column label="Product picture" ><!--图片-->
                         <template slot-scope="scope">
-                          <img :src="scope.row.COVER" alt="" style="width:100px" >
+<!--                          <img :src="scope.row.COVER" alt="" style="width:100px" >-->
+                          <el-image style="width: 100px; height: 100px" :src="scope.row.COVER" :preview-src-list="[scope.row.COVER]"></el-image>
                         </template>
                       </el-table-column>
 
@@ -59,22 +60,33 @@
                 </el-tab-pane>
             </el-tabs>
             <div class="white-box-footer">
-
-                <el-button @click="goToAccounts()">Check Out</el-button><!--去结算-->
-
-                <pagination :total="totalCount" :page_size="pageSize" @size-change="handleSizeChange" @current-change="handleCurrentChange"></pagination>
+                <el-row>
+                  <el-col :span="3">
+                      <el-button type="primary" size="small" @click="goToAccounts()">Check Out</el-button><!--去结算-->
+                  </el-col>
+                  <el-col :span="15">
+                      <div class='flex data' style="line-height: 35px; font-size: 14px;">
+                          <div style="margin-right: 2rem;">Price:₦ {{ sell_price_sum }}</div><!--商品价格-->
+                          <div style="margin-right: 2rem;">BV:{{ price_pv_sum }}</div><!--商品BV-->
+                          <div>Tax:₦ {{ tax_sum }}</div><!--商品BV-->
+                      </div>
+                  </el-col>
+                  <el-col :span="6">
+                      <pagination :total="totalCount" :page_size="pageSize" @size-change="handleSizeChange" @current-change="handleCurrentChange"></pagination>
+                  </el-col>
+                </el-row>
             </div>
         </div>
     </div>
 </template>
 
 <script>
-    import network from '@/utils/network'
-    import baseInfo from '@/utils/baseInfo'
-    import store from '@/utils/vuexStore'
-    import tool from '@/utils/tool'
-    import Pagination from '@/components/Pagination'
-    export default {
+import network from '@/utils/network'
+import tool from '@/utils/tool'
+import {SERVER_API_DOMAIN, SERVER_API_HTTP_TYPE} from '@/utils/config'
+import Pagination from '@/components/Pagination'
+
+export default {
         name: "index",
         components: {Pagination},
         mounted() {
@@ -102,6 +114,9 @@
                 goodsCategory: '1',
                 goodsActive: [],
                 maxHeight: tool.getTableHeight(),
+                sell_price_sum: 0.00,
+                price_pv_sum: 0.00,
+                tax_sum: 0.00,
             }
         },
         watch: {
@@ -117,7 +132,7 @@
         },
         methods: {
             handleChange(val){
-                console.log(val);
+
             },
             goToAccounts() {
                 if (this.multipleSelection.length <= 0) {
@@ -166,7 +181,27 @@
                     }
                 }
                 this.multipleSelection[this.currentPage] = val;
-                console.log(this.multipleSelection);
+
+                // 计算统计
+                this.handleSureChange()
+            },
+            handleSureChange() {
+                if (this.multipleSelection.length > 0) {
+                    let accumulatorSellPrice = 0, accumulatorPricePv = 0, accumulatorTax = 0;
+                    this.multipleSelection.forEach(item => {
+                        item.forEach(accumulator => { accumulatorSellPrice += accumulator.SELL_PRICE * accumulator.chose_num * accumulator.DISCOUNT / 100; });
+                        item.forEach(accumulator => { accumulatorPricePv += Number(accumulator.PRICE_PV) * Number(accumulator.chose_num) * (Number(accumulator.DISCOUNT) / 100); });
+                        item.forEach(accumulator => { accumulatorTax += tool.calculateTax(Number(accumulator.SELL_PRICE), Number(accumulator.TAX_RATE), Number(accumulator.chose_num)); });
+                    })
+
+                    this.sell_price_sum = parseFloat(accumulatorSellPrice).toFixed(2);
+                    this.price_pv_sum = parseFloat(accumulatorPricePv).toFixed(2);
+                    this.tax_sum = parseFloat(accumulatorTax).toFixed(2);
+                } else {
+                    this.sell_price_sum = 0.00;
+                    this.price_pv_sum = 0.00;
+                    this.tax_sum = 0.00;
+                }
             },
             handleInputNumber(val, row){
                 let pageList = this.multipleSelection[this.currentPage];
@@ -181,6 +216,8 @@
 
                 if( selectStatus ) {
                     this.multipleSelection[this.currentPage] = pageList;
+                  // 计算统计
+                  this.handleSureChange()
                 }
             },
             getScope(scope){
@@ -236,14 +273,16 @@
                                 if( pageList[j].ID === obj.tableData[i].ID ) {
                                     obj.numList[i] = pageList[j].chose_num;
                                     obj.tableData[i].chose_num = pageList[j].chose_num;
-                                    obj.$refs.multipleTable.toggleRowSelection(obj.tableData[i],true);
+                                    // obj.$refs.multipleTable.toggleRowSelection(obj.tableData[i],true);
                                     break;
                                 }
                             }
+                            if (obj.tableData[i].COVER.indexOf('/') === -1) {
+                              obj.tableData[i].COVER = SERVER_API_HTTP_TYPE + SERVER_API_DOMAIN + '/uploads/' + obj.tableData[i].COVER
+                            }
                         }
                         obj.selectLock = false;
                     })
-
                 })
             },
             // 获取商品类型,填充tabs页
@@ -258,6 +297,12 @@
                 this.goodsCategory = tab.name
                 // 查询商品列表
                 this.getData()
+                // 清空合计、已选商品
+                this.sell_price_sum = 0.00
+                this.price_pv_sum = 0.00
+                this.tax_sum = 0.00
+                this.numList = []
+                this.tableData.map(ele => ele.chose_num = 1)
             },
         }
 

+ 2 - 1
frontendEle/src/views/shop/order.vue

@@ -13,7 +13,8 @@
 
             <el-table-column label="Product picture" ><!--图片-->
               <template slot-scope="scope">
-                <img :src="scope.row.COVER" alt="" style="width:100%">
+<!--                <img :src="scope.row.COVER" alt="" style="width:100%">-->
+                <el-image style="width: 100px; height: 100px" :src="scope.row.COVER" :preview-src-list="[scope.row.COVER]"></el-image>
               </template>
             </el-table-column>
 

+ 3 - 3
frontendEle/src/views/user/dec.vue

@@ -115,9 +115,9 @@
                             <div class="white-box-footer flex">
                                 <el-button @click="getSum()">Total Calculation</el-button><!--计算合计-->
                                 <div class='flex data' style="flex:1;justify-content: flex-end;">
-                                    <div style="margin-right:2rem">Product price:₦{{sell_price_sum}}</div><!--商品价格-->
-                                    <div style="margin-right:2rem">Product BV:{{price_pv_sum}}</div><!--商品BV-->
-                                    <div>Product Tax:₦{{tax_sum}}</div><!--商品BV-->
+                                    <div style="margin-right:2rem">Price:₦{{sell_price_sum}}</div><!--商品价格-->
+                                    <div style="margin-right:2rem">BV:{{price_pv_sum}}</div><!--商品BV-->
+                                    <div>Tax:₦{{tax_sum}}</div><!--商品BV-->
                                 </div>
                             </div>
 

+ 2 - 2
frontendEle/src/views/user/id-card.vue_bak

@@ -61,7 +61,7 @@
             handleSuccess(response, file){
                 if(response.success){
                     this.$message({
-                        message: '上传成功',
+                        message: 'Successful',
                         type: 'success'
                     });
                     this.imageUrl = URL.createObjectURL(file.raw);
@@ -119,4 +119,4 @@
         height: 320px;
         display: block;
     }
-</style>
+</style>

+ 36 - 0
sql/upgrade/1350.sql

@@ -0,0 +1,36 @@
+DROP TABLE IF EXISTS `AR_QTR_CALC_USER`;
+CREATE TABLE `AR_QTR_CALC_USER`  (
+  `ID` int(11) NOT NULL AUTO_INCREMENT,
+  `USER_ID` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+  `AMOUNT` decimal(16, 3) NULL DEFAULT NULL,
+  `CALC_YEAR` int(11) NULL DEFAULT NULL,
+  `CALC_MONTH` int(11) NULL DEFAULT NULL,
+  `PERIOD_NUM` int(11) NULL DEFAULT NULL,
+  PRIMARY KEY (`ID`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 106 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
+
+
+DROP TABLE IF EXISTS `AR_QTR_CALC_RECORD`;
+CREATE TABLE `AR_QTR_CALC_RECORD`  (
+  `ID` int(11) NOT NULL AUTO_INCREMENT,
+  `EVENT` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
+  `CREATION_TIME` datetime(0) NULL DEFAULT NULL,
+  `CALC_PERIOD_ID` int(11) NULL DEFAULT NULL,
+  PRIMARY KEY (`ID`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 406209 CHARACTER SET = utf8 COLLATE = utf8_general_ci  ROW_FORMAT = Dynamic;
+
+
+DROP TABLE IF EXISTS `AR_CALC_BONUS_QUARTER`;
+CREATE TABLE `AR_CALC_BONUS_QUARTER`  (
+  `ID` int(11) NOT NULL AUTO_INCREMENT,
+  `USER_ID` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+  `ORI_BONUS` decimal(16, 3) NULL DEFAULT NULL,
+  `MANAGE_TAX` decimal(16, 3) NULL DEFAULT NULL,
+  `AMOUNT` decimal(16, 3) NULL DEFAULT NULL,
+  `RECONSUME_POINTS` decimal(16, 3) NULL DEFAULT NULL,
+  `CALC_YEAR` int(11) NULL DEFAULT NULL,
+  `CALC_MONTH` int(11) NULL DEFAULT NULL,
+  `PERIOD_NUM` int(11) NULL DEFAULT NULL,
+  `CREATED_AT` datetime(0) NOT NULL,
+  PRIMARY KEY (`ID`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 2005 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;