linwu před 1 rokem
rodič
revize
2277d5fd1c
36 změnil soubory, kde provedl 1028 přidání a 86 odebrání
  1. 1 1
      app/admin/common.php
  2. 57 1
      app/admin/controller/Vote.php
  3. 69 0
      app/admin/view/vote/apply.html
  4. 35 0
      app/admin/view/vote/apply_vote.html
  5. 44 5
      app/admin/view/vote/index.html
  6. 26 0
      app/admin/view/vote/show_num.html
  7. 1 1
      app/common/model/AdminModel.php
  8. 1 1
      app/common/model/ArticleCateModel.php
  9. 1 1
      app/common/model/ArticleModel.php
  10. 1 1
      app/common/model/FeedbackModel.php
  11. 1 1
      app/common/model/MenuModel.php
  12. 1 1
      app/common/model/NavigationModel.php
  13. 1 1
      app/common/model/NoticeModel.php
  14. 1 1
      app/common/model/SettingModel.php
  15. 1 1
      app/common/model/SlideModel.php
  16. 1 1
      app/common/model/UserFollowModel.php
  17. 1 1
      app/common/model/UserModel.php
  18. 2 2
      app/common/model/VoteApplyModel.php
  19. 13 0
      app/mobile/common.php
  20. 67 0
      app/mobile/controller/Login.php
  21. 71 0
      app/mobile/controller/Vote.php
  22. 4 30
      app/mobile/view/index/index.html
  23. 1 0
      app/mobile/view/public/base.html
  24. 1 1
      app/mobile/view/public/list_load.html
  25. 125 0
      app/mobile/view/vote/detail.html
  26. 2 1
      composer.json
  27. 195 1
      composer.lock
  28. 12 16
      public/static/mobile/js/axios_instance.js
  29. 0 8
      public/static/mobile/js/components/articleList.js
  30. 26 0
      public/static/mobile/js/components/voteList.js
  31. 3 0
      vendor/composer/autoload_psr4.php
  32. 24 0
      vendor/composer/autoload_static.php
  33. 203 0
      vendor/composer/installed.json
  34. 33 6
      vendor/composer/installed.php
  35. 2 2
      vendor/composer/platform_check.php
  36. 1 1
      vendor/services.php

+ 1 - 1
app/admin/common.php

@@ -5,4 +5,4 @@ function list_return($list, $count){
     $res = ['code'=>0,'data' => $list,'count'=>$count];
     $response = \think\Response::create($res, 'json');
     throw new \think\exception\HttpResponseException($response);
-}
+}

+ 57 - 1
app/admin/controller/Vote.php

@@ -81,8 +81,64 @@ class Vote extends AdminBaseController
 
         $file_name = "/vote_{$id}.png";
         $link      = url('/mobile/vote/detail') . '?id=' . $id;
-        $file_url  = QrcodeService::getQrcode($file_name, $link);
+        $file_url  = QrcodeService::getQrcode($file_name, $link, 600);
 
         ajax_return(0, '', $file_url);
     }
+
+    /**
+     * 查看票数
+     */
+    public function showNum()
+    {
+        $id = input('id/d', 0);
+
+        $apply = VoteApplyModel::where('vote_id', $id)->select();
+        $res   = [];
+        foreach ($apply as $v) {
+            if (empty($res[$v['option_name']])) {
+                $res[$v['option_name']] = 0;
+            }
+
+            $res[$v['option_name']]++;
+        }
+
+        return view('', [
+            'info' => $res,
+        ]);
+    }
+
+    /**
+     * 投票明细
+     */
+    public function apply()
+    {
+        $vote_list = VoteModel::select();
+
+        return view('', [
+            'vote_list' => $vote_list,
+        ]);
+    }
+
+    public function listApply()
+    {
+        $map = $this->dealEqualInput([], ['vote_id']);
+
+        $list  = VoteApplyModel::with(['user', 'vote'])->where($map)->limit(input('limit'))->page(input('page'))->select();
+        $count = VoteApplyModel::where($map)->count();
+        if ($count == 0) {
+            ajax_return(1, '未查询到数据');
+        }
+        list_return($list, $count);
+    }
+
+    /**
+     * 带活动id的投票明细
+     */
+    public function applyVote()
+    {
+        return view('', [
+            'id' => input('id/d', 0),
+        ]);
+    }
 }

+ 69 - 0
app/admin/view/vote/apply.html

@@ -0,0 +1,69 @@
+<div class="layui-fluid">
+    <div class="layui-card">
+        <div class="layui-form layui-form-pane  layui-card-header layuiadmin-card-header-auto">
+            <div class="layui-form-item">
+                <div class="layui-inline">
+                    <label class="layui-form-label">活动</label>
+                    <div class="layui-input-block">
+                        <select name="vote_id">
+                            <option value="">全部</option>
+                            {volist name="vote_list" id="v"}
+                            <option value="{$v.id}">{$v.title}</option>
+                            {/volist}
+                        </select>
+                    </div>
+                </div>
+                <div class="layui-inline">
+                    <button class="layui-btn" lay-submit lay-filter="{$lay_btn}">
+                        <i class="layui-icon layui-icon-search layuiadmin-button-btn"></i>
+                    </button>
+                </div>
+            </div>
+        </div>
+
+        <div class="layui-card-body">
+            <table id="{$lay_table}" lay-filter="{$lay_table}"></table>
+            <script type="text/html" id="userTpl">
+                {{d.user.nickname}}
+            </script>
+            <script type="text/html" id="voteTpl">
+                {{d.vote.title}}
+            </script>
+        </div>
+    </div>
+</div>
+
+<script>
+    layui.use(['index', 'admin', 'form', 'table'], function () {
+        const form = layui.form;
+        const table = layui.table;
+        form.render();
+
+        table.render({
+            elem: '#{$lay_table}',
+            url: "{:url('vote/listApply')}",
+            cols: [
+                [
+                    {field: 'vote', title: '活动名',templet: '#voteTpl'},
+                    {field: 'option_name', title: '选项名'},
+                    {field: 'user', title: '投票人', width: 160,templet: '#userTpl'},
+                    {field: 'update_time', title: '投票时间', width: 160, align: 'center'},
+                ]
+            ],
+            page: true,
+            limit: 50,
+            cellMinWidth: 150,
+            text: '对不起,加载出现异常!'
+        });
+
+        form.on('submit({$lay_btn})', function (data) {
+            table.reload('{$lay_table}', {
+                where: data.field,
+                page: {
+                    curr: 1
+                }
+            });
+        });
+
+    });
+</script>

+ 35 - 0
app/admin/view/vote/apply_vote.html

@@ -0,0 +1,35 @@
+<div class="layui-fluid">
+    <div class="layui-card">
+        <div class="layui-card-body">
+            <table id="{$lay_table}" lay-filter="{$lay_table}"></table>
+            <script type="text/html" id="userTpl">
+                {{d.user.nickname}}
+            </script>
+        </div>
+    </div>
+</div>
+
+<script>
+    layui.use(['index', 'admin', 'form', 'table'], function () {
+        const form = layui.form;
+        const table = layui.table;
+        form.render();
+
+        table.render({
+            elem: '#{$lay_table}',
+            url: "{:url('vote/listApply')}?vote_id={$id}",
+            cols: [
+                [
+                    {field: 'option_name', title: '选项名'},
+                    {field: 'user', title: '投票人', width: 160,templet: '#userTpl'},
+                    {field: 'update_time', title: '投票时间', width: 160, align: 'center'},
+                ]
+            ],
+            page: true,
+            limit: 50,
+            cellMinWidth: 150,
+            text: '对不起,加载出现异常!'
+        });
+
+    });
+</script>

+ 44 - 5
app/admin/view/vote/index.html

@@ -18,13 +18,13 @@
                 <a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del">
                     <i class="layui-icon layui-icon-delete"></i>删除
                 </a>
-                <a class="layui-btn layui-btn-normal layui-btn-xs" lay-event="edit">
+                <a class="layui-btn layui-btn-normal layui-btn-xs" lay-event="qrcode">
                     <i class="layui-icon layui-icon-picture-fine"></i>查看二维码
                 </a>
-                <a class="layui-btn layui-btn-normal layui-btn-xs" lay-event="edit">
+                <a class="layui-btn layui-btn-normal layui-btn-xs" lay-event="num">
                     <i class="layui-icon layui-icon-form"></i>查看票数
                 </a>
-                <a class="layui-btn layui-btn-normal layui-btn-xs" lay-event="edit">
+                <a class="layui-btn layui-btn-normal layui-btn-xs" lay-event="apply">
                     <i class="layui-icon layui-icon-table"></i>投票明细
                 </a>
             </script>
@@ -73,7 +73,7 @@
             add: function () {
                 const index = layer.open({
                     type: 2,
-                    title: '添加系统消息',
+                    title: '添加活动',
                     content: "{:url('vote/voteForm')}",
                     maxmin: true,
                     area: ['550px', '550px']
@@ -101,12 +101,51 @@
             } else if (obj.event === 'edit') {
                 const index = layer.open({
                     type: 2,
-                    title: '编辑系统消息',
+                    title: '编辑活动',
                     content: "{:url('vote/voteForm')}?id=" + data.id,
                     maxmin: true,
                     area: ['550px', '550px']
                 });
                 layer.full(index);
+            } else if (obj.event === 'qrcode') {
+                admin.req({
+                    url: "{:url('vote/qrcodeVote')}?id=" + data.id,
+                    data: {
+                        id: data.id
+                    },
+                    done: function (res) {
+                        layer.photos({
+                            photos: {
+                                "title": "二维码", //相册标题
+                                "id": 1, //相册id
+                                "start": 0, //初始显示的图片序号,默认0
+                                "data": [   //相册包含的图片,数组格式
+                                    {
+                                        "alt": "二维码",
+                                        "pid": 0, //图片id
+                                        "src": res.data, //原图地址
+                                    }
+                                ]
+                            }
+                        });
+                    }
+                });
+            } else if (obj.event === 'num') {
+                layer.open({
+                    type: 2,
+                    title: '查看票数',
+                    content: "{:url('vote/showNum')}?id=" + data.id,
+                    maxmin: true,
+                    area: ['550px', '550px']
+                });
+            } else if (obj.event === 'apply') {
+                layer.open({
+                    type: 2,
+                    title: '投票明细',
+                    content: "{:url('vote/applyVote')}?id=" + data.id,
+                    maxmin: true,
+                    area: ['700px', '550px']
+                });
             }
         });
 

+ 26 - 0
app/admin/view/vote/show_num.html

@@ -0,0 +1,26 @@
+<div class="layui-fluid" style="background:white;">
+    <div class="layui-row layui-col-space15">
+        <div class="layui-col-md8 layui-col-md-offset2">
+            <table class="layui-table">
+                <colgroup>
+                    <col>
+                    <col>
+                </colgroup>
+                <thead>
+                <tr>
+                    <th>选项名</th>
+                    <th>票数</th>
+                </tr>
+                </thead>
+                <tbody>
+                {volist name="info" id="v"}
+                <tr>
+                    <td>{$key}</td>
+                    <td>{$v}</td>
+                </tr>
+                {/volist}
+                </tbody>
+            </table>
+        </div>
+    </div>
+</div>

+ 1 - 1
app/common/model/AdminModel.php

@@ -5,7 +5,7 @@ namespace app\common\model;
 class AdminModel extends BaseModel
 {
     // 设置表名
-    protected $table = 'admin';
+    protected $name = 'admin';
 
     //自动完成
     protected $autoWriteTimestamp = true;

+ 1 - 1
app/common/model/ArticleCateModel.php

@@ -5,7 +5,7 @@ namespace app\common\model;
 class ArticleCateModel extends BaseModel
 {
     // 设置表名
-    protected $table = 'article_cate';
+    protected $name = 'article_cate';
 
     // 常量
     const STATUS = [1 => '显示', 2 => '隐藏'];

+ 1 - 1
app/common/model/ArticleModel.php

@@ -5,7 +5,7 @@ namespace app\common\model;
 class ArticleModel extends BaseModel
 {
     //设置表名
-    protected $table = 'article';
+    protected $name = 'article';
 
     //自动完成
     protected $autoWriteTimestamp = true;

+ 1 - 1
app/common/model/FeedbackModel.php

@@ -5,7 +5,7 @@ namespace app\common\model;
 class FeedbackModel extends BaseModel
 {
     // 设置表名
-    protected $table = 'feedback';
+    protected $name = 'feedback';
 
     //自动完成
     protected $autoWriteTimestamp = true;

+ 1 - 1
app/common/model/MenuModel.php

@@ -5,7 +5,7 @@ namespace app\common\model;
 class MenuModel extends BaseModel
 {
     // 设置表名
-    protected $table = 'menu';
+    protected $name = 'menu';
 
     // 设置字段自动转换类型
     protected $type = [

+ 1 - 1
app/common/model/NavigationModel.php

@@ -5,7 +5,7 @@ namespace app\common\model;
 class NavigationModel extends BaseModel
 {
     // 设置表名
-    protected $table = 'navigation';
+    protected $name = 'navigation';
 
     // 常量
     const TAB    = [1 => '系统首页'];

+ 1 - 1
app/common/model/NoticeModel.php

@@ -5,7 +5,7 @@ namespace app\common\model;
 class NoticeModel extends BaseModel
 {
     // 设置表名
-    protected $table = 'notice';
+    protected $name = 'notice';
 
     //自动完成
     protected $autoWriteTimestamp = true;

+ 1 - 1
app/common/model/SettingModel.php

@@ -5,7 +5,7 @@ namespace app\common\model;
 class SettingModel extends BaseModel
 {
     // 设置表名
-    protected $table = 'setting';
+    protected $name = 'setting';
 
     // 短信配置
     const SMS = [

+ 1 - 1
app/common/model/SlideModel.php

@@ -5,7 +5,7 @@ namespace app\common\model;
 class SlideModel extends BaseModel
 {
     // 设置表名
-    protected $table = 'slide';
+    protected $name = 'slide';
 
     // 常量
     const TAB    = [1 => '首页轮播图'];

+ 1 - 1
app/common/model/UserFollowModel.php

@@ -5,7 +5,7 @@ namespace app\common\model;
 class UserFollowModel extends BaseModel
 {
     // 设置表名
-    protected $table = 'user_follow';
+    protected $name = 'user_follow';
 
     //自动完成
     protected $autoWriteTimestamp = true;

+ 1 - 1
app/common/model/UserModel.php

@@ -7,7 +7,7 @@ use think\model\concern\SoftDelete;
 class UserModel extends BaseModel
 {
     // 设置表名
-    protected $table = 'user';
+    protected $name = 'user';
 
     // 设置字段自动转换类型
     protected $type = [

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

@@ -12,11 +12,11 @@ class VoteApplyModel extends BaseModel
 
     public function User()
     {
-        return $this->hasMany(UserModel::class, "id", "user_id");
+        return $this->hasOne(UserModel::class, "id", "user_id");
     }
 
     public function Vote()
     {
-        return $this->hasMany(VoteModel::class, "id", "vote_id");
+        return $this->hasOne(VoteModel::class, "id", "vote_id");
     }
 }

+ 13 - 0
app/mobile/common.php

@@ -24,3 +24,16 @@ function ajax_success($data)
     $response = \think\Response::create($res, 'json');
     throw new \think\exception\HttpResponseException($response);
 }
+
+function get_user_id()
+{
+    $sessionUserId = session('mobile.user.id');
+    if (empty($sessionUserId)) {
+        session('back_url',request()->url());
+        $response = redirect('/mobile/login/login');
+        throw new \think\exception\HttpResponseException($response);
+    }
+
+    return $sessionUserId;
+}
+

+ 67 - 0
app/mobile/controller/Login.php

@@ -0,0 +1,67 @@
+<?php
+
+namespace app\mobile\controller;
+
+use app\common\model\UserModel;
+use app\mobile\MobileBaseController;
+
+class Login extends MobileBaseController
+{
+    public function login()
+    {
+        return redirect('https://www.jucai.gov.cn/api/auth/wechat_auth?url=' . urlencode(url('/mobile/login/wechatBack')));
+    }
+
+    /**
+     * 微信回调
+     */
+    public function wechatBack()
+    {
+        $param   = input('param.');
+        $open_id = $param['openid'];
+
+        //登录
+        $user = UserModel::where(['openid' => $open_id])->find();
+        if (empty($user)) {
+            $user = UserModel::create([
+                'nickname'  => $param['nickname'],
+                'avatar'    => $param['headimgurl'],
+                'openid'    => $open_id,
+                'unionid'   => $param['unionid'],
+                'logintime' => time(),
+                'loginip'   => request()->ip(),
+            ]);
+        } else {
+            $user->logintime = time();
+            $user->loginip   = request()->ip();
+            $user->save();
+        }
+
+        session('mobile.user.id', $user['id']);
+
+        $back_url = '/';
+        if (session('?back_url')) {
+            $back_url = session('back_url');
+            session('back_url', null);
+        }
+
+        return redirect($back_url);
+    }
+
+    public function login1()
+    {
+        session('mobile.user.id', 1);
+        $back_url = '/';
+        if (session('?back_url')) {
+            $back_url = session('back_url');
+            session('back_url', null);
+        }
+        return redirect($back_url);
+    }
+
+    public function logout()
+    {
+        session('mobile.user.id', null);
+        return '退出';
+    }
+}

+ 71 - 0
app/mobile/controller/Vote.php

@@ -0,0 +1,71 @@
+<?php
+
+namespace app\mobile\controller;
+
+use app\common\model\VoteApplyModel;
+use app\common\model\VoteModel;
+use app\mobile\MobileBaseController;
+
+class Vote extends MobileBaseController
+{
+    public function listVote()
+    {
+        $list = VoteModel::limit(input('limit', 10))
+            ->page(input('page', 1))
+            ->select();
+
+        ajax_success($list);
+    }
+
+    public function detail()
+    {
+        $id = input('id/d', 0);
+        empty($id) && jump('该活动不存在');
+
+        $info = VoteModel::find($id);
+        empty($info) && jump('该活动不存在');
+
+        $user_id     = get_user_id();
+        $apply       = VoteApplyModel::where('vote_id', $id)->where('user_id', $user_id)->find();
+        $is_apply    = 'false';
+        $option_name = '';
+        if (!empty($apply)) {
+            $is_apply    = 'true';
+            $option_name = $apply['option_name'];
+        }
+
+        return view('', [
+            'info'        => $info,
+            'is_apply'    => $is_apply,
+            'option_name' => $option_name,
+        ]);
+    }
+
+    public function apply()
+    {
+        $id = input('id/d', 0);
+        empty($id) && ajax_return(1, '该活动不存在');
+
+        $vote = VoteModel::find($id);
+        empty($vote) && ajax_return(1, '该活动不存在');
+
+        $option_name = input('option_name', '');
+        if (!in_array($option_name, $vote['option'])) {
+            ajax_return(1, '该选项不存在,请重新选择');
+        }
+
+        $user_id = get_user_id();
+        $check   = VoteApplyModel::where('vote_id', $id)->where('user_id', $user_id)->find();
+        if (!empty($check)) {
+            ajax_return(1, '请勿重复提交!');
+        }
+
+        VoteApplyModel::create([
+            'vote_id'     => $id,
+            'user_id'     => $user_id,
+            'option_name' => $option_name,
+        ]);
+
+        ajax_return();
+    }
+}

+ 4 - 30
app/mobile/view/index/index.html

@@ -1,8 +1,6 @@
 {extend name="public/base"/}
 {block name="css"}
-<style>
 
-</style>
 {/block}
 {block name="body"}
 <van-nav-bar
@@ -11,44 +9,20 @@
         :placeholder="true"
 >
     <template #title>
-        <span class="text-white">首页</span>
+        <span class="text-white">活动列表</span>
     </template>
 </van-nav-bar>
 
-<van-swipe :autoplay="3000" indicator-color="white">
-    {volist name="slide" id="item"}
-    <van-swipe-item>
-        <van-image src="{$item.image}"></van-image>
-    </van-swipe-item>
-    {/volist}
-</van-swipe>
+{include file="public/list_load" list="<vote-list :list='list'></vote-list>" /}
 
-<van-grid :border="false">
-    {volist name="navigation" id="item"}
-    <van-grid-item url="{$item.url}" icon="{$item.image}" text="{$item.title}"></van-grid-item>
-    {/volist}
-</van-grid>
-
-<article-list :list="list"></article-list>
-
-<van-tabbar v-model="active" :placeholder="true">
-    <van-tabbar-item icon="wap-home-o">首页</van-tabbar-item>
-    <van-tabbar-item icon="description" url="{:url('article/index')}">文章</van-tabbar-item>
-    <van-tabbar-item icon="user-circle-o" url="{:url('my/index')}">我的</van-tabbar-item>
-</van-tabbar>
 {/block}
 {block name="script"}
 <script>
     function v_setup() {
-        let base = {};
-
-        base.active = 0;
-        base.list = Vue.reactive({$article});
-
-        return base;
+        return list_load('/vote/listVote');
     }
 </script>
 {/block}
 {block name="vue"}
-<script src="__COMPONENTS__/articleList.js"></script>
+<script src="__COMPONENTS__/voteList.js"></script>
 {/block}

+ 1 - 0
app/mobile/view/public/base.html

@@ -16,6 +16,7 @@
             return v_setup();
         }
     };
+
     const app = Vue.createApp(vue3)
         .use(vant)
         .use(vant.Lazyload);

+ 1 - 1
app/mobile/view/public/list_load.html

@@ -25,7 +25,7 @@
             param.page = base.page.value;
             base.page.value++;
 
-            postJson(url, param).then(function (data) {
+            postJson(url, param).then( ({data}) => {
                 base.loading.value = false;
                 if (base.refreshing.value) base.refreshing.value = false;
                 if (data.length === 0) {

+ 125 - 0
app/mobile/view/vote/detail.html

@@ -0,0 +1,125 @@
+{extend name="public/base"/}
+{block name="css"}
+<style>
+    .article{
+        background:white;
+        padding:0 10px;
+        margin-bottom:10px;
+    }
+
+    .article h3{
+        padding:10px 0;
+        margin:0;
+    }
+
+    .article .article-info{
+        align-items:center;
+        display:flex;
+        justify-content:space-between;
+        margin:5px;
+        font-size:12px;
+    }
+
+    .article .article-info .s-time{
+        color:#b4b4b4;
+    }
+
+    .article .article-info .s-comment{
+        background:#f5f7f9;
+        border-radius:5px;
+        flex-shrink:0;
+        font-size:14px;
+        padding:5px 10px;
+    }
+
+    .content{
+        padding-bottom:1px;
+    }
+
+    .content, .content img{
+        max-width:100%;
+    }
+</style>
+{/block}
+{block name="body"}
+<van-nav-bar
+        class="nav-theme"
+        :fixed="true"
+        :placeholder="true"
+        left-text="返回"
+        left-arrow
+        @click-left="onBack"
+>
+    <template #title>
+        <span class="text-white">活动详情</span>
+    </template>
+</van-nav-bar>
+
+<div class="article">
+    <header>
+        <h3>{$info.title}</h3>
+        <section class="article-info">
+            <div class="s-author">
+                <div class="s-time">
+                    <time>{$info.start_time} 至 {$info.end_time}</time>
+                </div>
+            </div>
+        </section>
+    </header>
+    <section class="content">
+        {$info.content}
+    </section>
+</div>
+
+<van-radio-group v-model="checked" :disabled="is_apply">
+    <van-cell-group inset>
+        {volist name="info.option" id="v"}
+        <van-cell title="{$v}" clickable @click="onOption('{$v}')">
+            <template #right-icon>
+                <van-radio name="{$v}"></van-radio>
+            </template>
+        </van-cell>
+        {/volist}
+        <van-button type="primary" block @click="submit" v-if="!is_apply">提交</van-button>
+    </van-cell-group>
+</van-radio-group>
+{/block}
+{block name="script"}
+<script>
+    function v_setup() {
+        let base = {};
+
+        base.is_click = false;
+        base.is_apply = Vue.ref({$is_apply});
+        base.checked = Vue.ref('{$option_name}');
+        base.onBack = () => {
+            history.back();
+        };
+        base.onOption = (v) => {
+            if (base.is_apply.value) {
+                return false;
+            }
+            base.checked.value = v;
+        };
+        base.submit = () => {
+            if (base.is_click) {
+                return false;
+            }
+            base.is_click = true;
+            if (base.checked.value === '') {
+                vant.showToast('请选择投票的项目');
+                base.is_click = false;
+                return false;
+            }
+            postJson('/vote/apply', {option_name: base.checked.value, id: {$info.id}}).then(({data, code}) => {
+                base.is_click = false;
+                if (code === 0) {
+                    base.is_apply.value = true;
+                }
+            })
+        };
+
+        return base;
+    }
+</script>
+{/block}

+ 2 - 1
composer.json

@@ -26,7 +26,8 @@
         "topthink/think-filesystem": "^1.0",
         "topthink/think-multi-app": "^1.0",
         "topthink/think-view": "^1.0",
-        "topthink/think-captcha": "^3.0"
+        "topthink/think-captcha": "^3.0",
+        "endroid/qr-code": "^4.3"
     },
     "require-dev": {
         "symfony/var-dumper": "^4.2",

+ 195 - 1
composer.lock

@@ -4,8 +4,202 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
         "This file is @generated automatically"
     ],
-    "content-hash": "04e78688bd7119e6b1b2fcb490f8f0d4",
+    "content-hash": "71172db321112b32b124eb3e5a0f9921",
     "packages": [
+        {
+            "name": "bacon/bacon-qr-code",
+            "version": "2.0.8",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/Bacon/BaconQrCode.git",
+                "reference": "8674e51bb65af933a5ffaf1c308a660387c35c22"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/Bacon/BaconQrCode/zipball/8674e51bb65af933a5ffaf1c308a660387c35c22",
+                "reference": "8674e51bb65af933a5ffaf1c308a660387c35c22",
+                "shasum": "",
+                "mirrors": [
+                    {
+                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
+                        "preferred": true
+                    }
+                ]
+            },
+            "require": {
+                "dasprid/enum": "^1.0.3",
+                "ext-iconv": "*",
+                "php": "^7.1 || ^8.0"
+            },
+            "require-dev": {
+                "phly/keep-a-changelog": "^2.1",
+                "phpunit/phpunit": "^7 | ^8 | ^9",
+                "spatie/phpunit-snapshot-assertions": "^4.2.9",
+                "squizlabs/php_codesniffer": "^3.4"
+            },
+            "suggest": {
+                "ext-imagick": "to generate QR code images"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "BaconQrCode\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-2-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Ben Scholzen 'DASPRiD'",
+                    "email": "mail@dasprids.de",
+                    "homepage": "https://dasprids.de/",
+                    "role": "Developer"
+                }
+            ],
+            "description": "BaconQrCode is a QR code generator for PHP.",
+            "homepage": "https://github.com/Bacon/BaconQrCode",
+            "support": {
+                "issues": "https://github.com/Bacon/BaconQrCode/issues",
+                "source": "https://github.com/Bacon/BaconQrCode/tree/2.0.8"
+            },
+            "time": "2022-12-07T17:46:57+00:00"
+        },
+        {
+            "name": "dasprid/enum",
+            "version": "1.0.4",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/DASPRiD/Enum.git",
+                "reference": "8e6b6ea76eabbf19ea2bf5b67b98e1860474012f"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/DASPRiD/Enum/zipball/8e6b6ea76eabbf19ea2bf5b67b98e1860474012f",
+                "reference": "8e6b6ea76eabbf19ea2bf5b67b98e1860474012f",
+                "shasum": "",
+                "mirrors": [
+                    {
+                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
+                        "preferred": true
+                    }
+                ]
+            },
+            "require": {
+                "php": ">=7.1 <9.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^7 | ^8 | ^9",
+                "squizlabs/php_codesniffer": "*"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "DASPRiD\\Enum\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-2-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Ben Scholzen 'DASPRiD'",
+                    "email": "mail@dasprids.de",
+                    "homepage": "https://dasprids.de/",
+                    "role": "Developer"
+                }
+            ],
+            "description": "PHP 7.1 enum implementation",
+            "keywords": [
+                "enum",
+                "map"
+            ],
+            "support": {
+                "issues": "https://github.com/DASPRiD/Enum/issues",
+                "source": "https://github.com/DASPRiD/Enum/tree/1.0.4"
+            },
+            "time": "2023-03-01T18:44:03+00:00"
+        },
+        {
+            "name": "endroid/qr-code",
+            "version": "4.3.5",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/endroid/qr-code.git",
+                "reference": "5630e192948b466d418608ecce697465d20260af"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/endroid/qr-code/zipball/5630e192948b466d418608ecce697465d20260af",
+                "reference": "5630e192948b466d418608ecce697465d20260af",
+                "shasum": "",
+                "mirrors": [
+                    {
+                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
+                        "preferred": true
+                    }
+                ]
+            },
+            "require": {
+                "bacon/bacon-qr-code": "^2.0",
+                "php": "^7.3||^8.0"
+            },
+            "require-dev": {
+                "endroid/quality": "dev-master",
+                "ext-gd": "*",
+                "khanamiryan/qrcode-detector-decoder": "^1.0.4",
+                "setasign/fpdf": "^1.8.2"
+            },
+            "suggest": {
+                "ext-gd": "Enables you to write PNG images",
+                "khanamiryan/qrcode-detector-decoder": "Enables you to use the image validator",
+                "roave/security-advisories": "Makes sure package versions with known security issues are not installed",
+                "setasign/fpdf": "Enables you to use the PDF writer"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "4.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Endroid\\QrCode\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Jeroen van den Enden",
+                    "email": "info@endroid.nl"
+                }
+            ],
+            "description": "Endroid QR Code",
+            "homepage": "https://github.com/endroid/qr-code",
+            "keywords": [
+                "code",
+                "endroid",
+                "php",
+                "qr",
+                "qrcode"
+            ],
+            "support": {
+                "issues": "https://github.com/endroid/qr-code/issues",
+                "source": "https://github.com/endroid/qr-code/tree/4.3.5"
+            },
+            "funding": [
+                {
+                    "url": "https://github.com/endroid",
+                    "type": "github"
+                }
+            ],
+            "time": "2021-09-17T07:50:43+00:00"
+        },
         {
             "name": "league/flysystem",
             "version": "1.1.10",

+ 12 - 16
public/static/mobile/js/axios_instance.js

@@ -5,26 +5,22 @@ const axios_instance = axios.create({
     withCredentials: true,
 });
 
-axios_instance.interceptors.response.use(function (response) {
-    const data = response.data;
-    if (data.code === 1) {
-        if (typeof error === 'function') {
-            error(data.data);
-        } else {
-            Toast(data.msg);
-        }
-    } else if (data.code === 401) {
-        location.href = '/mobile/login/login';
-    }
-    return response.data;
-});
-
-async function postJson(url,data) {
+async function postJson(url,data,error) {
     return  new Promise((resolve, reject) => {
         axios_instance.post(url, JSON.stringify(data), {
             headers: { 'Content-Type': 'application/json;charset=UTF-8' }
         }).then((result) => {
-            return resolve(result.data);
+            const data = result.data;
+            if (data.code === 1) {
+                if (typeof error === 'function') {
+                    return error(data);
+                } else {
+                    vant.showToast(data.msg);
+                }
+            } else if (data.code === 401) {
+                location.href = '/mobile/login/login';
+            }
+            return resolve(data);
         });
     });
 }

+ 0 - 8
public/static/mobile/js/components/articleList.js

@@ -1,13 +1,5 @@
 app.component('article-list', {
     template: `
-    <style>
-        .article-list article{box-shadow:0 0 6px rgba(0, 0, 0, 0.028), 0 0 18px rgba(0, 0, 0, 0.042), 0 0 80px rgba(0, 0, 0, 0.07);border-radius: 5px;width:95%;height:110px;margin:10px auto;display:flex;align-items:center;background:white;padding:5px 10px;}
-        .article-list article .s-left {height:90px;display:flex;flex-direction:column;width: 100%;}
-        .article-list article .s-left.image {width: calc(100% - 120px);}
-        .article-list article .s-left .s-title{font-size: 16px;text-overflow: ellipsis;display: -webkit-box;overflow: hidden;-webkit-box-orient: vertical;-webkit-box-pack: center;-webkit-box-align: center;-webkit-line-clamp: 3;}
-        .article-list article .s-left .s-time{font-size: 12px;color:#999;margin-top:auto;}
-        .article-list article .s-right {width:110px;margin-left:auto;}
-    </style>
     <div class="article-list">
         <article v-for="item in list" @click="toDetail(item.id)">
             <section class="s-left" :class="{image:!!item.header_image}">

+ 26 - 0
public/static/mobile/js/components/voteList.js

@@ -0,0 +1,26 @@
+app.component('vote-list', {
+    template: `
+    <div class="article-list">
+        <article v-for="item in list" @click="toDetail(item.id)">
+            <section class="s-left">
+                <div class="s-title">{{item.title}}</div>
+                <div class="s-time">{{item.start_time}} 至 {{item.end_time}}</div>
+            </section>
+        </article>
+    </div>
+    `,
+    data() {
+        return {}
+    },
+    props: {
+        list: {
+            type: Array,
+            default: [],
+        },
+    },
+    methods: {
+        toDetail(id) {
+            location.href = "/mobile/vote/detail.html?id=" + id;
+        },
+    },
+});

+ 3 - 0
vendor/composer/autoload_psr4.php

@@ -24,4 +24,7 @@ return array(
     'League\\MimeTypeDetection\\' => array($vendorDir . '/league/mime-type-detection/src'),
     'League\\Flysystem\\Cached\\' => array($vendorDir . '/league/flysystem-cached-adapter/src'),
     'League\\Flysystem\\' => array($vendorDir . '/league/flysystem/src'),
+    'Endroid\\QrCode\\' => array($vendorDir . '/endroid/qr-code/src'),
+    'DASPRiD\\Enum\\' => array($vendorDir . '/dasprid/enum/src'),
+    'BaconQrCode\\' => array($vendorDir . '/bacon/bacon-qr-code/src'),
 );

+ 24 - 0
vendor/composer/autoload_static.php

@@ -50,6 +50,18 @@ class ComposerStaticInit8fda6fe797a34d32a281406e65775056
             'League\\Flysystem\\Cached\\' => 24,
             'League\\Flysystem\\' => 17,
         ),
+        'E' => 
+        array (
+            'Endroid\\QrCode\\' => 15,
+        ),
+        'D' => 
+        array (
+            'DASPRiD\\Enum\\' => 13,
+        ),
+        'B' => 
+        array (
+            'BaconQrCode\\' => 12,
+        ),
     );
 
     public static $prefixDirsPsr4 = array (
@@ -129,6 +141,18 @@ class ComposerStaticInit8fda6fe797a34d32a281406e65775056
         array (
             0 => __DIR__ . '/..' . '/league/flysystem/src',
         ),
+        'Endroid\\QrCode\\' => 
+        array (
+            0 => __DIR__ . '/..' . '/endroid/qr-code/src',
+        ),
+        'DASPRiD\\Enum\\' => 
+        array (
+            0 => __DIR__ . '/..' . '/dasprid/enum/src',
+        ),
+        'BaconQrCode\\' => 
+        array (
+            0 => __DIR__ . '/..' . '/bacon/bacon-qr-code/src',
+        ),
     );
 
     public static $fallbackDirsPsr0 = array (

+ 203 - 0
vendor/composer/installed.json

@@ -1,5 +1,208 @@
 {
     "packages": [
+        {
+            "name": "bacon/bacon-qr-code",
+            "version": "2.0.8",
+            "version_normalized": "2.0.8.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/Bacon/BaconQrCode.git",
+                "reference": "8674e51bb65af933a5ffaf1c308a660387c35c22"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/Bacon/BaconQrCode/zipball/8674e51bb65af933a5ffaf1c308a660387c35c22",
+                "reference": "8674e51bb65af933a5ffaf1c308a660387c35c22",
+                "shasum": "",
+                "mirrors": [
+                    {
+                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
+                        "preferred": true
+                    }
+                ]
+            },
+            "require": {
+                "dasprid/enum": "^1.0.3",
+                "ext-iconv": "*",
+                "php": "^7.1 || ^8.0"
+            },
+            "require-dev": {
+                "phly/keep-a-changelog": "^2.1",
+                "phpunit/phpunit": "^7 | ^8 | ^9",
+                "spatie/phpunit-snapshot-assertions": "^4.2.9",
+                "squizlabs/php_codesniffer": "^3.4"
+            },
+            "suggest": {
+                "ext-imagick": "to generate QR code images"
+            },
+            "time": "2022-12-07T17:46:57+00:00",
+            "type": "library",
+            "installation-source": "dist",
+            "autoload": {
+                "psr-4": {
+                    "BaconQrCode\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-2-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Ben Scholzen 'DASPRiD'",
+                    "email": "mail@dasprids.de",
+                    "homepage": "https://dasprids.de/",
+                    "role": "Developer"
+                }
+            ],
+            "description": "BaconQrCode is a QR code generator for PHP.",
+            "homepage": "https://github.com/Bacon/BaconQrCode",
+            "support": {
+                "issues": "https://github.com/Bacon/BaconQrCode/issues",
+                "source": "https://github.com/Bacon/BaconQrCode/tree/2.0.8"
+            },
+            "install-path": "../bacon/bacon-qr-code"
+        },
+        {
+            "name": "dasprid/enum",
+            "version": "1.0.4",
+            "version_normalized": "1.0.4.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/DASPRiD/Enum.git",
+                "reference": "8e6b6ea76eabbf19ea2bf5b67b98e1860474012f"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/DASPRiD/Enum/zipball/8e6b6ea76eabbf19ea2bf5b67b98e1860474012f",
+                "reference": "8e6b6ea76eabbf19ea2bf5b67b98e1860474012f",
+                "shasum": "",
+                "mirrors": [
+                    {
+                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
+                        "preferred": true
+                    }
+                ]
+            },
+            "require": {
+                "php": ">=7.1 <9.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^7 | ^8 | ^9",
+                "squizlabs/php_codesniffer": "*"
+            },
+            "time": "2023-03-01T18:44:03+00:00",
+            "type": "library",
+            "installation-source": "dist",
+            "autoload": {
+                "psr-4": {
+                    "DASPRiD\\Enum\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-2-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Ben Scholzen 'DASPRiD'",
+                    "email": "mail@dasprids.de",
+                    "homepage": "https://dasprids.de/",
+                    "role": "Developer"
+                }
+            ],
+            "description": "PHP 7.1 enum implementation",
+            "keywords": [
+                "enum",
+                "map"
+            ],
+            "support": {
+                "issues": "https://github.com/DASPRiD/Enum/issues",
+                "source": "https://github.com/DASPRiD/Enum/tree/1.0.4"
+            },
+            "install-path": "../dasprid/enum"
+        },
+        {
+            "name": "endroid/qr-code",
+            "version": "4.3.5",
+            "version_normalized": "4.3.5.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/endroid/qr-code.git",
+                "reference": "5630e192948b466d418608ecce697465d20260af"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/endroid/qr-code/zipball/5630e192948b466d418608ecce697465d20260af",
+                "reference": "5630e192948b466d418608ecce697465d20260af",
+                "shasum": "",
+                "mirrors": [
+                    {
+                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
+                        "preferred": true
+                    }
+                ]
+            },
+            "require": {
+                "bacon/bacon-qr-code": "^2.0",
+                "php": "^7.3||^8.0"
+            },
+            "require-dev": {
+                "endroid/quality": "dev-master",
+                "ext-gd": "*",
+                "khanamiryan/qrcode-detector-decoder": "^1.0.4",
+                "setasign/fpdf": "^1.8.2"
+            },
+            "suggest": {
+                "ext-gd": "Enables you to write PNG images",
+                "khanamiryan/qrcode-detector-decoder": "Enables you to use the image validator",
+                "roave/security-advisories": "Makes sure package versions with known security issues are not installed",
+                "setasign/fpdf": "Enables you to use the PDF writer"
+            },
+            "time": "2021-09-17T07:50:43+00:00",
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "4.x-dev"
+                }
+            },
+            "installation-source": "dist",
+            "autoload": {
+                "psr-4": {
+                    "Endroid\\QrCode\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Jeroen van den Enden",
+                    "email": "info@endroid.nl"
+                }
+            ],
+            "description": "Endroid QR Code",
+            "homepage": "https://github.com/endroid/qr-code",
+            "keywords": [
+                "code",
+                "endroid",
+                "php",
+                "qr",
+                "qrcode"
+            ],
+            "support": {
+                "issues": "https://github.com/endroid/qr-code/issues",
+                "source": "https://github.com/endroid/qr-code/tree/4.3.5"
+            },
+            "funding": [
+                {
+                    "url": "https://github.com/endroid",
+                    "type": "github"
+                }
+            ],
+            "install-path": "../endroid/qr-code"
+        },
         {
             "name": "league/flysystem",
             "version": "1.1.10",

+ 33 - 6
vendor/composer/installed.php

@@ -1,15 +1,42 @@
 <?php return array(
     'root' => array(
         'name' => 'topthink/think',
-        'pretty_version' => '1.0.0+no-version-set',
-        'version' => '1.0.0.0',
-        'reference' => NULL,
+        'pretty_version' => 'dev-master',
+        'version' => 'dev-master',
+        'reference' => '20260ea26eb07e076219db61e9c2d77e5f11c7c7',
         'type' => 'project',
         'install_path' => __DIR__ . '/../../',
         'aliases' => array(),
         'dev' => true,
     ),
     'versions' => array(
+        'bacon/bacon-qr-code' => array(
+            'pretty_version' => '2.0.8',
+            'version' => '2.0.8.0',
+            'reference' => '8674e51bb65af933a5ffaf1c308a660387c35c22',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../bacon/bacon-qr-code',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'dasprid/enum' => array(
+            'pretty_version' => '1.0.4',
+            'version' => '1.0.4.0',
+            'reference' => '8e6b6ea76eabbf19ea2bf5b67b98e1860474012f',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../dasprid/enum',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'endroid/qr-code' => array(
+            'pretty_version' => '4.3.5',
+            'version' => '4.3.5.0',
+            'reference' => '5630e192948b466d418608ecce697465d20260af',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../endroid/qr-code',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
         'league/flysystem' => array(
             'pretty_version' => '1.1.10',
             'version' => '1.1.10.0',
@@ -128,9 +155,9 @@
             'dev_requirement' => false,
         ),
         'topthink/think' => array(
-            'pretty_version' => '1.0.0+no-version-set',
-            'version' => '1.0.0.0',
-            'reference' => NULL,
+            'pretty_version' => 'dev-master',
+            'version' => 'dev-master',
+            'reference' => '20260ea26eb07e076219db61e9c2d77e5f11c7c7',
             'type' => 'project',
             'install_path' => __DIR__ . '/../../',
             'aliases' => array(),

+ 2 - 2
vendor/composer/platform_check.php

@@ -4,8 +4,8 @@
 
 $issues = array();
 
-if (!(PHP_VERSION_ID >= 70205)) {
-    $issues[] = 'Your Composer dependencies require a PHP version ">= 7.2.5". You are running ' . PHP_VERSION . '.';
+if (!(PHP_VERSION_ID >= 70300)) {
+    $issues[] = 'Your Composer dependencies require a PHP version ">= 7.3.0". You are running ' . PHP_VERSION . '.';
 }
 
 if ($issues) {

+ 1 - 1
vendor/services.php

@@ -1,5 +1,5 @@
 <?php 
-// This file is automatically generated at:2023-06-09 18:00:15
+// This file is automatically generated at:2023-06-29 16:40:13
 declare (strict_types = 1);
 return array (
   0 => 'think\\captcha\\CaptchaService',