linwu 1 жил өмнө
parent
commit
d51f17ce18

+ 41 - 22
app/admin/controller/Agent.php

@@ -31,9 +31,11 @@ class Agent extends BaseController
         $id         = input('id/d, 0');
         $agent      = AgentModel::with(['muser'])->findOrEmpty($id);
         $workerlist = WorkerModel::order(['id' => 'desc'])->select();
+        $brokerlist = BrokerModel::where('agentid', $id)->select();
         return view('agent/agentform', [
             'workerlist' => $workerlist,
             'agent'      => $agent,
+            'brokerlist' => $brokerlist,
         ]);
     }
 
@@ -61,28 +63,29 @@ class Agent extends BaseController
             ]));
         }
         $data     = [
-            'userid'    => $muser->id,
-            'workerid'  => input('workerid/d', 0),
-            'loginname' => input('loginname/s', ""),
-            'idnumber'  => input('idnumber/s', ""),
-            'title'     => input('title/s', ""),
-            'tilpic'    => input('tilpic/s', ""),
-            'picall'    => input('picall/a', []),
-            'realname'  => input('realname/s', ""),
-            'mobile'    => input('mobile/s', ""),
-            'telephone' => input('telephone/s', ""),
-            'latitude'  => input('latitude/f', 0.00),
-            'longitude' => input('longitude/f', 0.00),
-            'province'  => input('province/s', ""),
-            'city'      => input('city/s', ""),
-            'district'  => input('district/s', ""),
-            'address'   => input('address/s', ""),
-            'details'   => input('details/s', ""),
-            'priority'  => input('priority/d', 0),
-            'remark'    => input('remark/s', ""),
-            'status'    => input('status/d', 1),
-            'is_settle' => input('is_settle/d', 1),
-            'type'      => input('type/d', 1),
+            'userid'            => $muser->id,
+            'workerid'          => input('workerid/d', 0),
+            'loginname'         => input('loginname/s', ""),
+            'idnumber'          => input('idnumber/s', ""),
+            'title'             => input('title/s', ""),
+            'tilpic'            => input('tilpic/s', ""),
+            'picall'            => input('picall/a', []),
+            'realname'          => input('realname/s', ""),
+            'mobile'            => input('mobile/s', ""),
+            'telephone'         => input('telephone/s', ""),
+            'latitude'          => input('latitude/f', 0.00),
+            'longitude'         => input('longitude/f', 0.00),
+            'province'          => input('province/s', ""),
+            'city'              => input('city/s', ""),
+            'district'          => input('district/s', ""),
+            'address'           => input('address/s', ""),
+            'details'           => input('details/s', ""),
+            'priority'          => input('priority/d', 0),
+            'remark'            => input('remark/s', ""),
+            'status'            => input('status/d', 1),
+            'is_settle'         => input('is_settle/d', 1),
+            'type'              => input('type/d', 1),
+            'default_broker_id' => input('default_broker_id/d', 0),
         ];
         $password = input('password/s', "");
         if (empty($id)) {
@@ -357,4 +360,20 @@ class Agent extends BaseController
             'data'  => $list,
         ]));
     }
+
+    /**
+     * 推广码
+     */
+    public function shengwaiqrcode()
+    {
+        $id = input('id/d', 0);
+        error_reporting(E_ERROR);
+        $url = request()->domain(true) . '/mobile/worker/recruit?id=' . $id;
+        header('Content-Type: image/png');
+        ob_clean();
+        $errorCorrectionLevel = "L"; // 纠错级别:L、M、Q、H
+        $matrixPointSize      = "4"; //生成图片大小 :1到10
+        \phpqrcode\QRcode::png($url, false, $errorCorrectionLevel, $matrixPointSize);
+        exit();
+    }
 }

+ 11 - 0
app/admin/view/agent/agentform.html

@@ -53,6 +53,17 @@
 								<input type="radio" name="type" value="2" title="省外经纪人" {eq name="agent.type" value="2" }checked{/eq} />
 							</div>
 						</div>
+						<div class="layui-form-item">
+							<label class="layui-form-label">默认经纪人</label>
+							<div class="layui-input-block">
+								<select name="default_broker_id" lay-search>
+									<option value="">请选择默认经纪人(可搜索)...</option>
+									{volist name="brokerlist" id="vo"}
+									<option value="{$vo['id']}" {$agent.default_broker_id==$vo.id ? 'selected' : '' }>{$vo['title']} - {$vo['mobile']}</option>
+									{/volist}
+								</select>
+							</div>
+						</div>
 						<div class="layui-form-item">
 							<label class="layui-form-label"><span style="color:#f90c05;">*</span>代理名称</label>
 							<div class="layui-input-block">

+ 15 - 4
app/admin/view/agent/agentlist.html

@@ -52,11 +52,14 @@
 				{{#  } }}
 			</script>
 			<script type="text/html" id="setTpl">
-				<a class="layui-btn layui-btn-xs" lay-event="money"><i class="layui-icon layui-icon-table"></i>结算明细</a>
+				{{#  if(d.type == 2){ }}
+					<a class="layui-btn layui-btn-xs" lay-event="qrcode"><i class="layui-icon layui-icon-picture"></i>省外二维码</a>
+				{{#  } }}
+				<a class="layui-btn layui-btn-normal layui-btn-xs" lay-event="money"><i class="layui-icon layui-icon-table"></i>结算明细</a>
 				<a class="layui-btn layui-btn-normal layui-btn-xs" lay-event="settle"><i class="layui-icon layui-icon-edit"></i>收益结算</a>
 				<a class="layui-btn layui-btn-normal layui-btn-xs" lay-event="edit"><i class="layui-icon layui-icon-edit"></i>编辑</a>
-						<a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del"><i class="layui-icon layui-icon-delete"></i>删除</a>
-					</script>
+				<a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del"><i class="layui-icon layui-icon-delete"></i>删除</a>
+			</script>
 		</div>
 	</div>
 </div>
@@ -97,7 +100,7 @@
 					{ field: 'address', width: 200, title: '详细地址', hide: 'true', edit: 'text' },
 					{ field: 'createtime', width: 170, title: '创建时间', sort: true },
 					{ field: 'status_text', title: '状态', minWidth: 80, align: 'center' },
-					{ title: '操作', width: 350, align: 'center', fixed: 'right', toolbar: '#setTpl' }
+					{ title: '操作', width: 430, align: 'center', fixed: 'right', toolbar: '#setTpl' }
 				]
 			],
 			page: true,
@@ -234,6 +237,14 @@
 					area: ['750px', '480px']
 				});
 				layer.full(index);
+			} else if (obj.event === 'qrcode') {
+				layer.open({
+					type: 1,
+					title: '二维码',
+					content: `<img src="/admin.php/agent/shengwaiqrcode.html?id=${data.id}" style="width:380px;display:block;margin:0 auto;"/>`,
+					maxmin: true,
+					area: ['400px', '430px'],
+				});
 			}
 		});
 

+ 31 - 30
app/common/model/Agent.php

@@ -12,36 +12,37 @@ class Agent extends Model
     protected $defaultSoftDelete = 0;
     // 设置字段信息
     protected $schema = [
-        'id'           => 'int',
-        'userid'       => 'int',
-        'workerid'     => 'int',
-        'loginname'    => 'string',
-        'password'     => 'string',
-        'idnumber'     => 'string',
-        'title'        => 'string',
-        'tilpic'       => 'string',
-        'picall'       => 'string',
-        'realname'     => 'string',
-        'mobile'       => 'string',
-        'telephone'    => 'string',
-        'latitude'     => 'float',
-        'longitude'    => 'float',
-        'province'     => 'string',
-        'city'         => 'string',
-        'district'     => 'string',
-        'address'      => 'string',
-        'details'      => 'string',
-        'priority'     => 'int',
-        'remark'       => 'string',
-        'status'       => 'tinyint',
-        'createtime'   => 'int',
-        'wxampcode'    => 'string',
-        'income'       => 'decimal',
-        'income_total' => 'decimal',
-        'is_settle'    => 'tinyint',
-        'money'        => 'decimal',
-        'money_total'  => 'decimal',
-        'type'         => 'tinyint',
+        'id'                => 'int',
+        'userid'            => 'int',
+        'workerid'          => 'int',
+        'loginname'         => 'string',
+        'password'          => 'string',
+        'idnumber'          => 'string',
+        'title'             => 'string',
+        'tilpic'            => 'string',
+        'picall'            => 'string',
+        'realname'          => 'string',
+        'mobile'            => 'string',
+        'telephone'         => 'string',
+        'latitude'          => 'float',
+        'longitude'         => 'float',
+        'province'          => 'string',
+        'city'              => 'string',
+        'district'          => 'string',
+        'address'           => 'string',
+        'details'           => 'string',
+        'priority'          => 'int',
+        'remark'            => 'string',
+        'status'            => 'tinyint',
+        'createtime'        => 'int',
+        'wxampcode'         => 'string',
+        'income'            => 'decimal',
+        'income_total'      => 'decimal',
+        'is_settle'         => 'tinyint',
+        'money'             => 'decimal',
+        'money_total'       => 'decimal',
+        'type'              => 'tinyint',
+        'default_broker_id' => 'int',
     ];
 
     // 设置字段自动转换类型

+ 3 - 0
app/mobile/common.php

@@ -92,6 +92,9 @@ function get_broker()
             }
         }
 
+        if ($broker['type'] == 1) {
+            jump('仅限省外经纪人登录');
+        }
         session('mobile.broker.id', $broker_id);
     } else {
         $broker = \app\common\model\Broker::where('id', $broker_id)->find();

+ 0 - 3
app/mobile/controller/Candidate.php

@@ -31,9 +31,6 @@ class Candidate extends MobileBaseController
             ajax_return(1, $e->getError());
         }
 
-        $idcard_check = OutResumeModel::where('idcard', $data['idcard'])->find();
-        $idcard_check && ajax_return(1, '该身份证号已被登记!');
-
         $mobile_check = OutResumeModel::where('mobile', $data['mobile'])->find();
         $mobile_check && ajax_return(1, '该手机号已被登记!');
 

+ 1 - 1
app/mobile/controller/Index.php

@@ -9,7 +9,7 @@ class Index extends MobileBaseController
     public function index()
     {
         return redirect(url('/mobile/my/index'));
-        return view('index/index');
+//        return view('index/index');
     }
 
 }

+ 25 - 0
app/mobile/controller/My.php

@@ -3,6 +3,7 @@
 namespace app\mobile\controller;
 
 use app\common\model\BrokerIncome as BrokerIncomeModel;
+use app\common\model\OutRecruitReport;
 use app\mobile\MobileBaseController;
 use think\App;
 use think\facade\View;
@@ -73,4 +74,28 @@ class My extends MobileBaseController
         \phpqrcode\QRcode::png($url, false, $errorCorrectionLevel, $matrixPointSize);
         exit();
     }
+
+    /**
+     * 我的报备
+     */
+    public function report()
+    {
+        return view('my/report');
+    }
+
+    public function listReport()
+    {
+        $map = $this->dealEqualInput(['status'],$this->dealLikeInput(['keyword'=>'realname|mobile']));
+
+        $map[] = ['brokerid', '=', $this->_broker['id']];
+        $list  = OutRecruitReport::with(['recruit'])
+            ->where($map)
+            ->order(['id' => 'desc'])
+            ->limit(input('limit', 10))
+            ->page(input('page', 1))
+            ->append(['status_text'])
+            ->select();
+
+        ajax_success($list);
+    }
 }

+ 1 - 4
app/mobile/controller/Recruit.php

@@ -38,7 +38,7 @@ class Recruit extends MobileBaseController
         $map[] = ['status', '=', 1];
 
         $list = OutRecruitModel::where($map)
-            ->order(['id' => 'desc'])
+            ->order(['priority' => 'desc', 'id' => 'desc'])
             ->limit(input('limit', 10))
             ->page(input('page', 1))
             ->select();
@@ -88,9 +88,6 @@ class Recruit extends MobileBaseController
             ajax_return(1, $e->getError());
         }
 
-        $idcard_check = OutRecruitReport::where('idcard', $data['idcard'])->where('recruit_id', $data['recruit_id'])->find();
-        $idcard_check && ajax_return(1, '该身份证号已报备,请勿重复报备!');
-
         $mobile_check = OutRecruitReport::where('mobile', $data['mobile'])->where('recruit_id', $data['recruit_id'])->find();
         $mobile_check && ajax_return(1, '该手机号已报备,请勿重复报备!');
 

+ 0 - 3
app/mobile/controller/Resume.php

@@ -90,9 +90,6 @@ class Resume extends MobileBaseController
             ajax_return(1, $e->getError());
         }
 
-        $idcard_check = OutResumeModel::where('idcard', $data['idcard'])->find();
-        $idcard_check && ajax_return(1, '该身份证号已被登记!');
-
         $mobile_check = OutResumeModel::where('mobile', $data['mobile'])->find();
         $mobile_check && ajax_return(1, '该手机号已被登记!');
 

+ 215 - 0
app/mobile/controller/Worker.php

@@ -0,0 +1,215 @@
+<?php
+
+namespace app\mobile\controller;
+
+use app\common\model\Agent as AgentModel;
+use app\common\model\OutRecruit as OutRecruitModel;
+use app\common\model\Broker as BrokerModel;
+use app\common\model\OutRecruitReport;
+use app\common\model\OutResume as OutResumeModel;
+use app\mobile\MobileBaseController;
+use app\mobile\validate\WorkerReportValidate;
+use think\exception\ValidateException;
+use think\facade\Db;
+
+class Worker extends MobileBaseController
+{
+    /**
+     * 招聘信息
+     */
+    public function index()
+    {
+        $agent_id = session('mobile.agent_id');
+        if (empty($agent_id)) {
+            $agent_id = input('id/d', 0);
+            if (empty($agent_id)) {
+                jump('门店不存在');
+            }
+
+            session('mobile.agent_id', $agent_id);
+        }
+
+        $agent = AgentModel::where([
+            ['id', '=', $agent_id],
+            ['type', '=', 2],
+            ['status', '=', 1],
+        ])->find();
+
+        if (empty($agent)) {
+            session('mobile.agent_id', null);
+            jump('门店不存在');
+        }
+
+        return view('worker/index');
+//        return view('index/index');
+    }
+
+    public function listRecruit()
+    {
+        $map   = $this->dealLikeInput(['keyword' => 'title|company_name']);
+        $map[] = ['status', '=', 1];
+
+        $list = OutRecruitModel::where($map)
+            ->order(['priority' => 'desc', 'id' => 'desc'])
+            ->limit(input('limit', 10))
+            ->page(input('page', 1))
+            ->select();
+
+        ajax_success($list);
+    }
+
+    public function recruitDetail()
+    {
+        $this->get_agent();
+
+        $id = input('id/d', 0);
+        if (empty($id)) {
+            jump('招聘不存在');
+        }
+
+        $info = OutRecruitModel::find($id);
+        if (empty($info) || $info['status'] != 1) {
+            jump('该信息不存在或已下架');
+        }
+
+        return view('worker/recruit_detail', ['info' => $info]);
+    }
+
+    /**
+     * 报备
+     */
+    public function report()
+    {
+        $id = input('id/d', 0);
+        if (empty($id)) {
+            jump('招聘不存在');
+        }
+
+        $info = OutRecruitModel::find($id);
+        if (empty($info) || $info['status'] != 1) {
+            jump('该信息不存在或已下架');
+        }
+
+        $agent  = $this->get_agent();
+        $broker = BrokerModel::field(['title as text', 'id as value'])->where([
+            ['agentid', '=', $agent['id']],
+            ['status', '=', 1],
+            ['type', '=', 3],
+        ])->select();
+        !empty($broker->isEmpty()) && jump('该门店暂无经纪人,无法报备');
+
+        return view('worker/report', [
+            'broker_list' => $broker,
+            'info'        => $info,
+        ]);
+    }
+
+    public function reportPost()
+    {
+        $data  = input('post.');
+        $agent = $this->get_agent();
+        try {
+            validate(WorkerReportValidate::class)->check($data);
+        } catch (ValidateException $e) {
+            ajax_return(1, $e->getError());
+        }
+
+        //简历
+        $resume = OutResumeModel::with(['broker'])->where('mobile', $data['mobile'])->find();
+        $resume && ajax_return(1, '您已有经纪人,请找经纪人报备!经纪人信息' . $resume['broker']['title'] . '(<a href="tel:' . $resume['broker']['mobile'] . '">' . $resume['broker']['mobile'] . '</a>)');
+        //报备记录
+        $report = OutRecruitReport::with(['broker'])->where('mobile', $data['mobile'])->where('recruit_id', $data['recruit_id'])->find();
+        $report && ajax_return(1, '您已有经纪人,请找经纪人报备!经纪人信息' . $report['broker']['title'] . '(<a href="tel:' . $report['broker']['mobile'] . '">' . $report['broker']['mobile'] . '</a>)');
+
+        //添加报备信息
+        if (empty($data['brokerid'])) {
+            $broker           = BrokerModel::where([
+                ['agentid', '=', $agent['id']],
+                ['status', '=', 1],
+                ['type', '=', 3],
+            ])->order(Db::raw('RAND()'))->find();
+            $data['brokerid'] = $broker['id'];
+        } else {
+            $broker = BrokerModel::find($data['brokerid']);
+        }
+
+        $data['workerid']   = $broker['workerid'];
+        $data['agentid']    = $broker['agentid'];
+        $data['createtime'] = time();
+        OutRecruitReport::create($data);
+
+        ajax_return(0, '报名成功,经纪人:' . $broker['title'] . '(<a href="tel:' . $broker['mobile'] . '">' . $broker['mobile'] . '</a>)','/mobile/worker/index');
+    }
+
+    /**
+     * 经纪人
+     */
+    public function broker()
+    {
+        return view();
+    }
+
+    public function listBroker()
+    {
+        $agent = $this->get_agent();
+
+        $list = OutRecruitModel::where('agentid',$agent['id'])
+            ->limit(input('limit', 10))
+            ->page(input('page', 1))
+            ->select();
+
+        ajax_success($list);
+    }
+
+    /**
+     * 报备查询
+     */
+    public function reportFind()
+    {
+        $mobile = input('mobile');
+        if (empty($mobile)) {
+            return view();
+        }
+
+        $report = OutRecruitReport::where('mobile',$mobile)->find();
+        if (empty($report)) {
+            ajax_return(1, '暂无信息');
+        }
+
+        $broker = BrokerModel::find($report['brokerid']);
+        ajax_success($broker);
+    }
+
+    public function listReport()
+    {
+        $map   = $this->dealEqualInput(['mobile']);
+
+        $list = OutRecruitReport::where($map)
+            ->order([ 'id' => 'desc'])
+            ->limit(input('limit', 10))
+            ->page(input('page', 1))
+            ->select();
+
+        ajax_success($list);
+    }
+
+    private function get_agent()
+    {
+        $agent_id = session('mobile.agent_id');
+        if (empty($agent_id)) {
+            jump('门店不存在');
+        }
+
+        $agent = AgentModel::where([
+            ['id', '=', $agent_id],
+            ['type', '=', 2],
+            ['status', '=', 1],
+        ])->find();
+        if (empty($agent)) {
+            session('mobile.agent_id', null);
+            jump('门店不存在');
+        }
+
+        return $agent;
+    }
+}

+ 8 - 10
app/mobile/validate/CandidateValidate.php

@@ -7,20 +7,18 @@ use think\Validate;
 class CandidateValidate extends Validate
 {
     protected $rule = [
-        'name'      => 'require',
+        'name'     => 'require',
         'brokerid' => 'require',
-        'mobile'    => 'require|mobile',
-        'idcard'    => 'require|idCard',
-        'gender'    => 'require',
-        'age'       => 'require|number',
+        'mobile'   => 'require|mobile',
+        'gender'   => 'require',
+        'age'      => 'require|number',
     ];
 
     protected $message = [
-        'name'      => '请选择姓名',
+        'name'     => '请选择姓名',
         'brokerid' => '经纪人不能为空',
-        'mobile'    => '手机号格式不对',
-        'idcard'    => '身份证号格式不对',
-        'gender'    => '请选择性别',
-        'age'       => '年龄格式不对',
+        'mobile'   => '手机号格式不对',
+        'gender'   => '请选择性别',
+        'age'      => '年龄格式不对',
     ];
 }

+ 1 - 3
app/mobile/validate/RecruitValidate.php

@@ -9,14 +9,12 @@ class RecruitValidate extends Validate
     protected $rule = [
         'realname'   => 'require',
         'mobile'     => 'require|mobile',
-        'idcard'     => 'require|idCard',
         'arrivetime' => 'require',
     ];
 
     protected $message = [
-        'name'       => '请填写姓名',
+        'realname'   => '请填写姓名',
         'mobile'     => '手机号格式不对',
-        'idcard'     => '身份证号格式不对',
         'arrivetime' => '请选择出发日期',
     ];
 }

+ 0 - 2
app/mobile/validate/ResumeValidate.php

@@ -9,7 +9,6 @@ class ResumeValidate extends Validate
     protected $rule = [
         'name'   => 'require',
         'mobile' => 'require|mobile',
-        'idcard' => 'require|idCard',
         'gender' => 'require',
         'age'    => 'require|number',
     ];
@@ -17,7 +16,6 @@ class ResumeValidate extends Validate
     protected $message = [
         'name'   => '请选择姓名',
         'mobile' => '手机号格式不对',
-        'idcard' => '身份证号格式不对',
         'gender' => '请选择性别',
         'age'    => '年龄格式不对',
     ];

+ 22 - 0
app/mobile/validate/WorkerReportValidate.php

@@ -0,0 +1,22 @@
+<?php
+
+namespace app\mobile\validate;
+
+use think\Validate;
+
+class WorkerReportValidate extends Validate
+{
+    protected $rule = [
+        'recruit_id' => 'require',
+        'realname'   => 'require',
+        'mobile'     => 'require|mobile',
+        'arrivetime' => 'require',
+    ];
+
+    protected $message = [
+        'recruit_id' => '数据异常,请重试',
+        'realname'   => '请填写姓名',
+        'mobile'     => '手机号格式不对',
+        'arrivetime' => '请选择出发日期',
+    ];
+}

+ 1 - 3
app/mobile/view/candidate/info.html

@@ -42,10 +42,8 @@
         ></van-field>
         <van-field
                 v-model="form.idcard"
-                required
                 label="身份证"
                 placeholder="请填写身份证号"
-                :rules="[{ required: true, message: '请填写身份证号' }]"
         ></van-field>
         <van-field
                 v-model="form.age"
@@ -107,7 +105,7 @@
             jobintention: '',
             address: '',
             education: '',
-            brokerid: {$broker.id},
+            brokerid: 0,
         });
         base.onSubmit = () => {
             postJson("{:url('candidate/infoPost')}", base.form).then(({data}) => {

+ 1 - 1
app/mobile/view/my/index.html

@@ -61,7 +61,7 @@
             ></van-image>
         </template>
     </van-grid-item>
-    <van-grid-item text="报备管理">
+    <van-grid-item text="报备管理" url="/mobile/my/report">
         <template #icon>
             <van-image
                     width="50%"

+ 89 - 0
app/mobile/view/my/report.html

@@ -0,0 +1,89 @@
+{extend name="public/base"/}
+{block name="css"}
+<style>
+    .detail-header {padding:10px;border-bottom:1px solid #eee;text-align:center;}
+    .detail-content {padding:0 10px 20px 10px;}
+    .detail-content .item {margin-top:10px;}
+    .detail-content .title{color:#999;}
+</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>
+<van-search
+        v-model="form.searchKey"
+        placeholder="请输入姓名或手机号"
+        @search="onSearch"
+        @cancel="onCancel"
+        show-action
+>
+    <template #action>
+        <div @click="onCancel">重置</div>
+    </template>
+</van-search>
+
+{include file="public/list_load" list="<report-list @detail='onDetail' :list='list'></report-list>" /}
+
+<van-popup
+        v-model:show="showDetail"
+        position="bottom"
+>
+    <div class="detail-header">报备详情</div>
+    <div class="detail-content">
+        <div class="item"><span class="title">招聘标题:</span>{{detail.recruit.title}}</div>
+        <div class="item"><span class="title">报备姓名:</span>{{detail.realname}}</div>
+        <div class="item"><span class="title">报备电话:</span>{{detail.mobile}}</div>
+        <div class="item"><span class="title">身份证号:</span>{{detail.idcard}}</div>
+        <div class="item"><span class="title">预到时间:</span>{{detail.arrivetime}}</div>
+        <div class="item"><span class="title">报备时间:</span>{{detail.createtime}}</div>
+        <div class="item"><span class="title">报备备注:</span>{{detail.remark}}</div>
+        <div class="item"><span class="title">反馈备注:</span>{{detail.retremark}}</div>
+    </div>
+</van-popup>
+{/block}
+{block name="script"}
+<script>
+    function v_setup() {
+        let base = list_load('my/listReport',{searchKey:''});
+
+        //搜索
+        base.onSearch = () => {
+            base.onRefresh();
+        };
+        base.onCancel = () => {
+            base.form.searchKey = "";
+            base.onRefresh();
+        };
+
+        //详情
+        base.onDetail = (item) => {
+            base.detail = item;
+            base.showDetail.value = true;
+        };
+
+        //头部
+        base.onBack = () => {
+            location.href = "{:url('/mobile/my/index')}";
+        };
+
+        //详情
+        base.detail = Vue.reactive({});
+        base.showDetail = Vue.ref(false);
+
+        return base;
+    }
+</script>
+{/block}
+{block name="vue"}
+<script src="__COMPONENTS__/reportList.js"></script>
+{/block}

+ 0 - 2
app/mobile/view/recruit/report.html

@@ -48,10 +48,8 @@
                     ></van-field>
                     <van-field
                             v-model="form.idcard"
-                            required
                             label="身份证"
                             placeholder="请填写身份证号"
-                            :rules="[{ required: true, message: '请填写身份证号' }]"
                     ></van-field>
                     <van-field
                             v-model="form.arrivetime"

+ 0 - 2
app/mobile/view/resume/form.html

@@ -45,10 +45,8 @@
         ></van-field>
         <van-field
                 v-model="form.idcard"
-                required
                 label="身份证"
                 placeholder="请填写身份证号"
-                :rules="[{ required: true, message: '请填写身份证号' }]"
         ></van-field>
         <van-field
                 v-model="form.age"

+ 71 - 0
app/mobile/view/worker/index.html

@@ -0,0 +1,71 @@
+{extend name="public/base"/}
+{block name="css"}
+<style>
+</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>
+<van-search
+        v-model="form.keyword"
+        placeholder="请输入标题或公司名"
+        @search="onSearch"
+        @cancel="onCancel"
+        show-action
+>
+    <template #action>
+        <div @click="onCancel">重置</div>
+    </template>
+</van-search>
+
+{include file="public/list_load" list="<recruit-list @detail='toDetail' :list='list'></recruit-list>" /}
+
+<van-tabbar v-model="active" :placeholder="true">
+    <van-tabbar-item icon="newspaper-o" url="{:url('worker/index')}">招聘信息</van-tabbar-item>
+    <van-tabbar-item icon="user-o" url="{:url('worker/broker')}">经纪人</van-tabbar-item>
+    <van-tabbar-item icon="search" url="{:url('worker/reportFind')}">报备查询</van-tabbar-item>
+</van-tabbar>
+{/block}
+{block name="script"}
+<script>
+    function v_setup() {
+        let base = list_load('worker/listRecruit',{keyword:''});
+        base.active = 0;
+
+        //搜索
+        base.onSearch = () => {
+            base.onRefresh();
+        };
+        base.onCancel = () => {
+            base.form.keyword = "";
+            base.onRefresh();
+        };
+
+        //列表
+        base.toDetail = (id) => {
+            location.href = "{:url('/mobile/worker/recruitDetail')}?id=" + id;
+        };
+
+
+        //头部
+        base.onBack = () => {
+            location.href = "{:url('/mobile/my/index')}";
+        };
+
+        return base;
+    }
+</script>
+{/block}
+{block name="vue"}
+    <script src="__COMPONENTS__/recruitList.js"></script>
+{/block}

+ 152 - 0
app/mobile/view/worker/recruit_detail.html

@@ -0,0 +1,152 @@
+{extend name="public/base"/}
+{block name="css"}
+<style>
+    .base-content .header {background-image:url("__MIMAGES__/detail_header.jpg");background-repeat:no-repeat;background-size:100% 70px;width:100%;height:70px;display:flex;align-items:center;justify-content:center;padding:0 20px;}
+    .base-content .header .left {flex:1;display:flex;flex-direction:column;}
+    .base-content .header .salary-box {line-height:24px;height:24px;flex:1;}
+    .base-content .header .salary-box .salary {color:white;font-size:24px;font-weight:bold;}
+    .base-content .header .salary-box .text {color:white;font-size:14px;margin-left:5px;}
+    .base-content .header .company-name {color:white;font-size:14px;}
+    .base-content .header .phone-box {display:flex;flex-direction:column;}
+    .base-content .header .phone-box .text{color:white;}
+    .base-content .title {background:white;padding:10px 20px;color:#000;font-size:18px;}
+    .base-content .tags {background:white;padding:0 20px 10px 20px;}
+    .base-content .tags .van-tag {margin-right:5px;}
+    .base-content .introduce {background:white;}
+    .base-content .introduce .introduce-item {border-top:1px solid #f0f0f0;padding:5px 20px;display:flex;align-items:center;}
+    .base-content .introduce .introduce-item .van-image{margin-right:5px;}
+    .base-content .introduce .introduce-item .split{margin:0 15px;}
+    .describe {margin-top:10px;background:white;}
+    .describe .header {padding:10px 20px;font-size:16px;border-bottom:1px solid #f0f0f0;}
+    .describe .content {padding:10px 20px;}
+    .describe .content pre {font-size: 14px;line-height: 20px;padding: 0;margin: 0;font-family: "Microsoft Yahei",arial,"Hiragino Sans GB","Hiragino Sans GB W3",宋体,simsun;}
+</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="base-content">
+    <div class="header">
+        <div class="left">
+            <div class="salary-box">
+                <van-image
+                        width="15px"
+                        src="__MIMAGES__/icon_salary_white.png"
+                ></van-image>
+                <span class="text">工资:</span>
+                <span class="salary">{{info.salary}}</span>
+            </div>
+            <div class="company-name">{{info.company_name}}</div>
+        </div>
+    </div>
+    <div class="title">{{info.title}}</div>
+    <div class="tags" v-if="info.tags.length > 0">
+        <van-tag type="primary" size="large" v-for="tag in info.tags">{{tag}}</van-tag>
+    </div>
+    <div class="introduce">
+        <div class="introduce-item">
+            <van-image
+                    width="15px"
+                    src="__MIMAGES__/icon_num.png"
+            ></van-image>
+            <span>招聘人数:{{info.num}}</span>
+            <span class="split">|</span>
+            <van-image
+                    width="15px"
+                    src="__MIMAGES__/icon_age.png"
+            ></van-image>
+            <span>年龄:{{info.agegroup}}</span>
+        </div>
+        <div class="introduce-item">
+            <van-image
+                    width="15px"
+                    src="__MIMAGES__/icon_address.png"
+            ></van-image>
+            <span>{{info.province}}{{info.city}}{{info.district}}{{info.address}}</span>
+        </div>
+    </div>
+</div>
+
+<div class="describe" v-if="info.requirement">
+    <div class="header">
+        岗位要求
+    </div>
+    <div class="content">
+        <pre>{{info.requirement}}</pre>
+    </div>
+</div>
+
+<div class="describe" v-if="info.comdetails">
+    <div class="header">
+        企业简介
+    </div>
+    <div class="content">
+        <pre>{{info.comdetails}}</pre>
+    </div>
+</div>
+
+<div class="describe" v-if="info.picall.length > 0">
+    <div class="header">
+        相册
+    </div>
+    <div class="content">
+        <van-grid :border="false">
+            <van-grid-item v-for="(image,index) in info.picall">
+                <van-image
+                        :src="image"
+                        @click="showImage(index)"
+                ></van-image>
+            </van-grid-item>
+        </van-grid>
+    </div>
+</div>
+
+<div class="describe" v-if="info.remark">
+    <div class="header">
+        补充说明
+    </div>
+    <div class="content">
+        <pre>{{info.remark}}</pre>
+    </div>
+</div>
+
+<van-floating-bubble @click="onReport">报备</van-floating-bubble>
+{/block}
+{block name="script"}
+<script>
+    function v_setup() {
+        let base = {};
+
+        base.active = Vue.ref(0);
+
+        base.info = Vue.reactive({$info});
+        base.showImage = (index) => {
+            vant.showImagePreview({
+                images: base.info.picall,
+                startPosition: index,
+                loop:false,
+            });
+        };
+
+        base.onReport = () => {
+            location.href = "{:url('worker/report')}?id=" + base.info.id;
+        };
+
+        base.onBack = () => {
+            location.href = "{:url('worker/index')}";
+        };
+
+        return base;
+    }
+</script>
+{/block}

+ 161 - 0
app/mobile/view/worker/report.html

@@ -0,0 +1,161 @@
+{extend name="public/base"/}
+{block name="css"}
+<style>
+.recruit-title {background:white;padding:10px 20px;color:#000;font-size:18px;}
+</style>
+{/block}
+{block name="body"}
+<van-nav-bar
+        class="nav-theme"
+        :fixed="true"
+        :placeholder="true"
+>
+    <template #title>
+        <span class="text-white">报备信息</span>
+    </template>
+</van-nav-bar>
+<div class="recruit-title">{{info.title}}</div>
+<van-form @submit="onSubmit">
+    <div class="lw-title">基础信息</div>
+    <van-cell-group inset>
+        <van-field
+                v-model="form.realname"
+                required
+                label="姓名"
+                placeholder="请填写姓名"
+                :rules="[{ required: true, message: '请填写姓名' }]"
+        ></van-field>
+        <van-field
+                v-model="form.mobile"
+                required
+                label="手机号"
+                placeholder="请填写手机号"
+                :rules="[
+                        { required: true, message: '请填写手机号' },
+                        { validator, message: '请输入正确的手机号'}
+                    ]"
+        ></van-field>
+
+        <van-field
+                v-model="form.arrivetime"
+                required
+                is-link
+                readonly
+                label="出发日期"
+                placeholder="出发日期"
+                @click="showArrivetime = true"
+        ></van-field>
+        <van-popup v-model:show="showArrivetime" round position="bottom">
+            <van-date-picker
+                    title="选择日期"
+                    :min-date="minDate"
+                    @confirm="selectArrivetime"
+                    @cancel="showArrivetime = false"
+            ></van-date-picker>
+        </van-popup>
+        <van-field
+                v-model="form.idcard"
+                label="身份证"
+                placeholder="请填写身份证号"
+        ></van-field>
+        <van-field
+                v-model="brokerText"
+                is-link
+                readonly
+                label="经纪人"
+                placeholder="不选择系统将随机分配"
+                @click="showBrokerPicker = true"
+        ></van-field>
+        <van-popup v-model:show="showBrokerPicker" round position="bottom">
+            <van-picker
+                    :columns="brokerList"
+                    @cancel="showBrokerPicker = false"
+                    @confirm="onBrokerConfirm"
+            ></van-picker>
+        </van-popup>
+        <van-field
+                v-model="form.remark"
+                rows="2"
+                autosize
+                label="备注"
+                type="textarea"
+                maxlength="1000"
+                placeholder="请输入备注"
+                show-word-limit
+        ></van-field>
+    </van-cell-group>
+    <div style="margin: 16px;">
+        <van-button round block type="primary" native-type="submit">
+            提交
+        </van-button>
+    </div>
+</van-form>
+
+<van-dialog v-model:show="dialogShow" title="提示" @confirm="onConfirm">
+    <div v-html="dialogVlue" style="padding:10px 20px;"></div>
+</van-dialog>
+{/block}
+{block name="script"}
+<script>
+    function v_setup() {
+        let base = {};
+        base.dialogShow = Vue.ref(false);
+        base.dialogVlue = Vue.ref('');
+
+        //表单
+        base.info = {$info};
+        base.url = '';
+        base.form = Vue.reactive({
+            recruit_id: base.info.id,
+            realname: '',
+            mobile: '',
+            idcard: '',
+            arrivetime: '',
+            brokerid: 0,
+            remark: '',
+        });
+        base.onSubmit = () => {
+            postJson("{:url('worker/reportPost')}", base.form, function({msg}){
+                base.dialogShow.value = true;
+                base.dialogVlue.value = msg;
+            }).then(({data,msg}) => {
+                base.dialogShow.value = true;
+                base.dialogVlue.value = msg;
+                base.url = data;
+            });
+        };
+        base.onConfirm = () => {
+            console.log(base.url);
+            if (base.url != '') {
+                location.href = base.url;
+            }
+        };
+
+        //经纪人
+        base.brokerList = {$broker_list};
+        base.brokerText = Vue.ref('');
+        base.showBrokerPicker = Vue.ref(false);
+        base.onBrokerConfirm = ({selectedOptions}) => {
+            base.showBrokerPicker.value = false;
+            base.brokerText = selectedOptions[0].text;
+            base.form.brokerid = selectedOptions[0].value;
+        };
+
+        //出发日期
+        base.showArrivetime = Vue.ref(false);
+        base.minDate = new Date();
+        base.selectArrivetime = (value) => {
+            base.form.arrivetime = value.selectedValues.join('-');
+            base.showArrivetime.value = false;
+        };
+
+        //手机号验证
+        base.validator = (val) => {
+            return /^1(?:3\d|4[4-9]|5[0-35-9]|6[67]|7[013-8]|8\d|9\d)\d{8}$/.test(val);
+        };
+
+
+        return base;
+    }
+</script>
+{/block}

+ 11 - 1
public/static/mobile/css/style.css

@@ -62,4 +62,14 @@ html {
 .recruit-list .recruit-item .tags .van-tag{margin-right:5px;}
 .recruit-list .recruit-item .bottom {border-top:1px solid #eee;margin-top:10px;display:flex;padding-top:10px;font-size:14px;color:#666;}
 .recruit-list .recruit-item .bottom .company-name{width:calc(100% - 80px);}
-.recruit-list .recruit-item .bottom .volume{width:80px;display:flex;align-items:center;justify-content:flex-end;}
+.recruit-list .recruit-item .bottom .volume{width:80px;display:flex;align-items:center;justify-content:flex-end;}
+
+.report-list .report-item {background:white;margin-top:10px;padding:0 20px;}
+.report-list .report-item .header {display: flex;padding:10px 0;border-bottom:1px solid #eee;justify-content: space-between;}
+.report-list .report-item .header .title {color:#000;font-weight:bold;}
+.report-list .report-item .header .status {color:var(--red);font-size:14px;width: 50px;text-align: right;}
+.report-list .report-item .content {font-size:14px;padding:10px 0;border-bottom:1px solid #eee;}
+.report-list .report-item .user-info {color:var(--red);font-size:16px;}
+.report-list .report-item .other-info {color:#999;margin-top:2px;}
+.report-list .report-item .tool {display: flex;padding:10px 0;border-bottom:1px solid #eee;justify-content: flex-end;font-size:14px;}
+.report-list .report-item .tool .van-tag {margin-left:10px;}

+ 43 - 0
public/static/mobile/js/components/reportList.js

@@ -0,0 +1,43 @@
+app.component('report-list', {
+    template: `
+    <div class="report-list">
+        <div class="report-item" v-for="item in list">
+            <div class="header">
+                <div class="title">{{item.recruit.title}}</div>
+                <div class="status">{{item.status_text}}</div>
+            </div>
+            <div class="content">
+                <div class="user-info">{{item.realname}} - {{item.mobile}}</div>
+                <div class="other-info">预计到达日期:{{item.arrivetime}}</div>
+                <div class="other-info">报名时间:{{item.createtime}}</div>
+            </div>
+            <div class="tool">
+                <van-tag type="primary" plain size="large" @click="onCall(item.mobile)">求职者电话</van-tag>
+                <van-tag type="primary" plain size="large" @click="onCall(item.recruit.telephone)">公司电话</van-tag>
+                <van-tag type="success" plain size="large" @click="onDetail(item)">详情</van-tag>
+            </div>
+        </div>
+    </div>
+    `,
+    data() {
+        return {}
+    },
+    props: {
+        list: {
+            type: Array,
+            default: [],
+        },
+        is_select: {
+            type: Boolean,
+            default: false,
+        },
+    },
+    methods: {
+        onCall(phone) {
+            window.location.href = "tel:" + phone;
+        },
+        onDetail(item) {
+            this.$emit('detail',item);
+        },
+    },
+});