浏览代码

'0710-2244-c01'

zory 3 周之前
父节点
当前提交
29e92f9be6

+ 86 - 0
app/command/MiniTask.php

@@ -0,0 +1,86 @@
+<?php
+
+namespace app\command;
+
+use app\extra\tools\XcJob;
+use app\model\blue\BlueTask;
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+
+class MiniTask extends Command
+{
+
+
+    protected static string $defaultName = 'min:task';
+
+    protected static string $defaultDescription = '小程序星川任务';
+
+    protected function execute(InputInterface $input, OutputInterface $output): int
+    {
+        try {
+            $nextPage = 1;$done = 0;
+            $output->writeln("===小程序星川任务开始==={$nextPage}==>".getDateFull());
+            while (is_numeric($nextPage)) {
+                [$state,$resp] = (new XcJob)->token()->getTaskList($nextPage);
+                if (!$state) {
+                    $nextPage = null;
+                    $output->writeln("===获取全部任务失败==>".getDateFull());
+                    return self::SUCCESS;
+                }
+                if (!$resp['has_more']) {
+                    $nextPage = null;
+                    $output->writeln("===没有更多啦==>".getDateFull());
+                    return self::SUCCESS;
+                }
+                $model = (new BlueTask);
+                foreach ($resp['list'] as $key => $val)
+                {
+                    $data = (new XcJob)->token()->getTaskDetail($val['demand_info']['id']); // 获取任务详情
+                    if ($data['base_resp']['status_code'] <> 0)
+                    {
+                        $nextPage = null;
+                        $output->writeln("===获取任务详情失败==>".getDateFull());
+                        return self::SUCCESS;
+                    }
+                    $task  = [
+                        "expiration_time_end"   => date("Y-m-d H:i:s",$data['task_detail_info']['task_base_info']['expiration_time_end']),
+                        "title"                 => $data['task_detail_info']['task_base_info']['demand_name']??'',
+                        "product_cover_url"     => $data['task_detail_info']['object_field_info']['object_product_info']['product_cover_url']??'',
+                        "product_name"          => $data['task_detail_info']['object_field_info']['object_product_info']['product_name']??'',
+                        "shop_name"             => $data['task_detail_info']['object_field_info']['object_product_info']['shop_name']??'',
+                        "product_id"            => $data['task_detail_info']['object_field_info']['object_product_info']['external_product_id']??'',
+                        "product_link"          => $data['task_detail_info']['object_field_info']['object_product_info']['product_link']??'',
+                        "product_price"         => $data['task_detail_info']['component_info']['ecom_info']['ecoms'][0]['price']?$data['task_detail_info']['component_info']['ecom_info']['ecoms'][0]['price']*100:'0',
+                        "auto"                  => 2,
+                        "job_id"                => $val['demand_info']['id'],
+                        "category"              => "douyin",
+                        "category_detail"       => $data['task_detail_info']['task_base_info']['second_class_category_name']??'',
+                        "product_selling_point" => $data['task_detail_info']['object_field_info']['object_product_info']['product_selling_point_detail']??'',
+                        "target_audience"       => $data['task_detail_info']['object_field_info']['object_product_info']['target_audience_desc']??'',
+                        "creative_material_types"       => $data['task_detail_info']['star_qc_unite_info']['creative_material_types']?json_encode($data['task_detail_info']['star_qc_unite_info']['creative_material_types']):[],
+                        "content"               => $data['task_detail_info']['task_base_info']['other']?nl2br($data['task_detail_info']['task_base_info']['other']):'',
+                        "total_budget"          => $data['task_detail_info']['project_detail_info']['base_project_info']['total_budget']??0, // 0不上限
+                    ];
+                    $taskData = $model->where("product_id",$task['product_id'])->findOrEmpty();
+                    if ($taskData->isEmpty()) { // 新增
+                        $taskData->insertGetId($task);
+                        $output->writeln("{$val['demand_info']['id']}===入库成功!~==>".getDateFull());
+                    } else {
+                        // 更新
+                        $output->writeln("{$val['demand_info']['id']}===已存在,不入库!~==>".getDateFull());
+                    }
+                }
+                $nextPage = $nextPage+1;
+                $output->writeln("===当前页码{$nextPage}==>".getDateFull());
+            }
+            return self::SUCCESS;
+        } catch (\Throwable $throwable) {
+            echo getDateFull()."==报错啦===".$throwable->getFile()."\n";
+            echo getDateFull()."==报错啦===".$throwable->getLine()."\n";
+            echo getDateFull()."==报错啦===".$throwable->getMessage()."\n";
+            return self::SUCCESS;
+        }
+    }
+
+}

+ 76 - 0
app/controller/jiandao/StarJob.php

@@ -0,0 +1,76 @@
+<?php
+
+namespace app\controller\jiandao;
+
+use app\extra\basic\Base;
+use app\model\blue\BlueExpertPlatform;
+use LinFly\Annotation\Route\Controller;
+use LinFly\Annotation\Route\Route;
+use support\Request;
+use support\Response;
+use yzh52521\EasyHttp\Http;
+
+
+#[Controller(prefix: "/v2")]
+class StarJob extends Base
+{
+
+
+    #[Route(path: "task/push",methods: "get")]
+    public function pushJobList(Request $request): Response
+    {
+        try {
+            $resp = Http::asJson()->post("https://api.jiandaoyun.com/api/v1/automation/tenant/69dc899f71c9656940c3db33/hooks/69e07cb9d9016a508ad1dfad0bb32ba47135e0453631e9e6",[
+                "time" => time()
+            ])->array();
+            return success("ok",$resp);
+        } catch (\Throwable $throwable) {
+            return error($throwable->getMessage());
+        }
+    }
+
+    /**
+     * 获取已添加的任务
+     * @param Request $request
+     * @return Response
+     */
+    #[Route(path: "task/param",methods: "post")]
+    public function getJobList(Request $request): Response
+    {
+        try {
+            $param = $request->all();
+            print_r($param);
+            return success("ok");
+        } catch (\Throwable $throwable) {
+            return error($throwable->getMessage());
+        }
+    }
+
+    /**
+     * 检查达人数据是否存在
+     * @param Request $request
+     * @return Response
+     */
+    #[Route(path: "task/star",methods: "post")]
+    public function checkStarId(Request $request): Response
+    {
+        try {
+            $param = $this->_valid([
+                "total.require"     => trans("empty.require"),
+                "uid.require"       => trans("empty.require"),
+                "platform.require"  => trans("empty.require"),
+            ],$request->method());
+            if (!is_array($param)) return error($param);
+            $star = (new BlueExpertPlatform)->where(['unique_id' => $param['uid'],'source' => $param['platform']])->findOrEmpty();
+            if ($star->isEmpty()) return error("数据不存在");
+            if ($param['total'] == 0) return success("ok");
+            $star->jd_exist = 1;
+            $state = $star->save();
+            if (!$state) return errorTrans("error.data");
+            return success("ok");
+        } catch (\Throwable $throwable) {
+            return error($throwable->getMessage());
+        }
+    }
+
+}

+ 102 - 0
app/controller/v2/Bank.php

@@ -0,0 +1,102 @@
+<?php
+
+namespace app\controller\v2;
+
+use app\extra\basic\Base;
+use app\extra\service\blue\UserBankService;
+use app\middleware\WxMiddleware;
+use app\model\blue\BlueBankCompany;
+use app\model\blue\BlueUserBank;
+use app\validate\blue\BankValidate;
+use DI\Attribute\Inject;
+use LinFly\Annotation\Route\Controller;
+use LinFly\Annotation\Route\Middleware;
+use LinFly\Annotation\Route\Route;
+use support\Request;
+use support\Response;
+
+/**
+ * 银行卡操作
+ */
+#[Controller(prefix: "/wx_v2/bank"),Middleware(WxMiddleware::class)]
+class Bank extends Base
+{
+
+
+    protected array $noNeedLogin = ["getBankList"];
+
+    #[Inject]
+    protected BankValidate $validate;
+
+    #[Inject]
+    protected BlueUserBank $model;
+
+    #[Inject]
+    protected UserBankService $service;
+
+
+    /**
+     * 获取银行列表
+     * @param Request $request
+     * @return Response
+     */
+    #[Route(path: "list",methods: "get")]
+    public function getBankList(Request $request): Response
+    {
+        try {
+            $param = $this->_valid([
+                "name.require"  => trans("empty.require")
+            ]);
+            if (!is_array($param)) return error($param);
+            $data = (new BlueBankCompany)->where("name","like","%{$param['name']}%")->select()->toArray();
+            return successTrans("success.data",$data);
+        } catch (\Throwable $throwable) {
+            return error($throwable->getMessage());
+        }
+    }
+
+    /**
+     * 绑定银行卡
+     * @param Request $request
+     * @return Response
+     */
+    #[Route(path: "bind",methods: "post")]
+    public function bindUserBank(Request $request): Response
+    {
+        try {
+            $param = $request->post();
+            $param['openid'] = $request->user['openid'];
+            if (!$this->validate->scene('add')->check($param)) return error($this->validate->getError());
+            $bank = (new BlueBankCompany)->where("bank_code",$param['bank_code'])->findOrEmpty();
+            if ($bank->isEmpty()) return error("开户行不存在");
+            $param['bank_name'] = $bank['name'];
+            $state = $this->model->setAutoData($param);
+            if (!$state) return errorTrans("error.data");
+            return successTrans("success.data");
+        } catch (\Throwable $throwable) {
+            return error($throwable->getMessage());
+        }
+    }
+
+
+    /**
+     * 绑定银行卡列表
+     * @param Request $request
+     * @return Response
+     */
+    #[Route(path: "bind/list",methods: "get")]
+    public function bindUserList(Request $request): Response
+    {
+        try {
+            $param = $request->all();
+            if (empty($param['size'])) return errorTrans("empty.require");
+            $param['pageSize'] = $param['size'];
+            $param['openid'] = $request->user['openid'];
+            $list = $this->service->getList($param);
+            return successTrans("success.data",pageFormat($list));
+        } catch (\Throwable $throwable) {
+            return error($throwable->getMessage());
+        }
+    }
+
+}

+ 39 - 1
app/controller/v2/Portal.php

@@ -3,6 +3,7 @@
 namespace app\controller\v2;
 
 use app\extra\basic\Base;
+use app\extra\service\blue\ExpertPlatformService;
 use app\extra\service\blue\TaskService;
 use app\middleware\WxMiddleware;
 use app\model\blue\BlueBanner;
@@ -21,7 +22,7 @@ class Portal extends Base
 {
 
 
-    protected array $noNeedLogin = ['getPortal'];
+    protected array $noNeedLogin = ['getPortal','getStarList'];
 
     #[Inject]
     protected TaskService $service;
@@ -61,4 +62,41 @@ class Portal extends Base
         }
     }
 
+    /**
+     * 达人之家
+     * @param Request $request
+     * @return Response
+     */
+    #[Route(path: "star",methods: "get")]
+    public function getStarList(Request $request): Response
+    {
+        try {
+            $param = $this->_valid([
+                "nick.default"      => "",
+                "source.default"    => ""
+            ],$request->method());
+            if (!is_array($param)) return error($param);
+            $data = (new ExpertPlatformService)->getListStar($param,"id,nickname,avatar,follower_count,unique_id,openid");
+            if (empty($data)) return successTrans("success.data",$data);
+            $return = [];
+            foreach ($data as $key=>$val) {
+                $return[$key] = [
+                    "id"        => $val['id'],
+                    "nickname"  => $val['nickname'],
+                    "avatar"    => $val['avatar'],
+                    "follower"  => formatMoneyKw($val['follower_count']),
+                    "income"    => 0,
+                    "job"       => count($val['job']),
+                    "level"     => [
+                        "name"  => $val['user']['level']['name']??'-',
+                        "num"   => $val['user']['level']['level']??0
+                    ],
+                ];
+            }
+            return successTrans("success.data",$return);
+        } catch (\Throwable $throwable) {
+            return error($throwable->getMessage());
+        }
+    }
+
 }

+ 236 - 0
app/controller/v2/Task.php

@@ -0,0 +1,236 @@
+<?php
+
+namespace app\controller\v2;
+
+use app\extra\basic\Base;
+use app\extra\service\blue\TaskService;
+use app\extra\tools\XcJob;
+use app\middleware\WxMiddleware;
+use app\model\blue\BlueCategory;
+use app\model\blue\BlueExpert;
+use app\model\blue\BlueExpertPlatform;
+use app\model\blue\BlueTask;
+use app\model\blue\BlueTaskUser;
+use DI\Attribute\Inject;
+use LinFly\Annotation\Route\Controller;
+use LinFly\Annotation\Route\Middleware;
+use LinFly\Annotation\Route\Route;
+use support\Request;
+use support\Response;
+use yzh52521\EasyHttp\Http;
+
+
+#[Controller(prefix: "/wx_v2/task"),Middleware(WxMiddleware::class)]
+class Task extends Base
+{
+
+
+    protected array $noNeedLogin = ["getTaskDetail","getTaskList"];
+
+
+    #[Inject]
+    protected TaskService $service;
+
+    #[Inject]
+    protected BlueTask $model;
+
+    /**
+     * 任务列表
+     * @param Request $request
+     * @return Response
+     */
+    #[Route(path: "portal",methods: "get")]
+    public function getTaskList(Request $request): Response
+    {
+        try {
+            $param = $request->all();
+            if (empty($param['size'])) return errorTrans("empty.require");
+            $param['pageSize'] = $param['size'];
+            $list = $this->service->getList($param,"id,title,product_cover_url,job_id,category,category_detail,expiration_time_end,sign_number,need_number,product_price,level");
+            $category = (new BlueCategory)->where("type",1)->field("name,icon,small_icon,sign")->append(['id'])->withAttr(['id' => function($data,$resp){
+                return $resp['sign'];
+            }])->select()->toArray();
+            return successTrans("success.data",[
+                "category"    => $category,
+                "filter"    => $this->getTaskFilter(),
+                "task"      => pageFormat($list)
+            ],200);
+        } catch (\Throwable $throwable) {
+            return error($throwable->getMessage());
+        }
+    }
+
+    protected function getTaskFilter(): array
+    {
+        return [
+            [
+                "name"      => "任务状态",
+                "children"  => [
+                    [
+                        "name"  => "不限",
+                        "field" => "status",
+                        "val"   => 0
+                    ],
+                    [
+                        "name"  => "进行中",
+                        "field" => "status",
+                        "val"   => 1
+                    ],
+                    [
+                        "name"  => "已终止",
+                        "field" => "status",
+                        "val"   => 2
+                    ]
+                ]
+            ],
+            [
+                "name"      => "平台等级",
+                "children"  => [
+                    [
+                        "name"  => "不限",
+                        "field" => "level",
+                        "val"   => 0
+                    ],
+                ]
+            ],
+            [
+                "name"      => "平台等级",
+                "children"  => [
+                    [
+                        "name"  => "不限",
+                        "field" => "sort",
+                        "val"   => 0
+                    ],
+                ]
+            ]
+        ];
+    }
+
+
+    /**
+     * 任务详情
+     * @param Request $request
+     * @return Response
+     */
+    #[Route(path: "detail",methods: "get")]
+    public function getTaskDetail(Request $request): Response
+    {
+        try {
+            $param = $this->_valid([
+                "task_sn.require"   => trans("empty.require"),
+                "id.require"        => trans("empty.require"),
+            ],$request->method());
+            if (!is_array($param)) return error($param);
+            $data = $this->service->getTaskDetail($param);
+            if (empty($data)) return errorTrans("empty.data");
+            $return = $data->toArray();
+            $content = json_decode($return['content'],true);
+            $return['content'] = $content['content_advice_v2']??[];
+            $return['need_number'] = $return['need_number']>0 ? $return['need_number'] : 999;
+            $return['field_tag'] = [
+                [
+                    "label" => "商品售价",
+                    "content" => $return['price_format']
+                ],
+                [
+                    "label" => "投放预算",
+                    "content" => $return['total_budget'] == 0 ? '不限' : $return['total_budget_format']
+                ],
+                [
+                    "label" => "商品售价",
+                    "content" => $return['price_format']
+                ],
+                [
+                    "label" => "商品售价",
+                    "content" => $return['price_format']
+                ],
+                [
+                    "label" => "商品售价",
+                    "content" => $return['price_format']
+                ]
+            ];
+            return success("ok",$return);
+        } catch (\Throwable $throwable) {
+            return error($throwable->getMessage());
+        }
+    }
+
+    /**
+     * 任务报名
+     * @param Request $request
+     * @return Response
+     */
+    #[Route(path: "sign",methods: "post")]
+    public function taskUserReg(Request $request): Response
+    {
+        try {
+            $param = $this->_valid([
+                "task_sn.require"   => trans("empty.require"),
+                "task_id.require"   => trans("empty.require"),
+            ],$request->method());
+            if (!is_array($param)) return error($param);
+            $task = $this->model->where(['job_id' => $param['task_sn'],'id' => $param['task_id']])->findOrEmpty();
+            if ($task->isEmpty()) return errorTrans("empty.data");
+            $expert = (new BlueExpert)->where(["openid" => $request->user['openid'] ])->findOrEmpty();
+            if ($expert->isEmpty()) return error("请先完成平台认证",[],2);
+            $platform = (new BlueExpertPlatform)->where(["openid" => $request->user['openid'],'source' => $task['category']])->findOrEmpty();
+            if ($platform->isEmpty()) return error("请先绑定平台账号",[],3);
+            $starId = $platform['star_id'];
+            if (empty($platform['star_id'])) {
+                [$starState,$starData] = (new XcJob)->getStarData($platform['unique_id']);
+                if (!$starState) return error($starData,[],4);
+                $platform->star_id = $starData['list'][0]['star_id']??'';
+                $platform->save();
+                $starId = $starData['list'][0]['star_id'];
+            }
+            if ($platform['jd_exist'] == 0) {
+                $resp = Http::asJson()->post("https://api.jiandaoyun.com/api/v1/automation/tenant/69dc899f71c9656940c3db33/hooks/69e07cb9d9016a50bb60ae230bb32ba47135e7e946bedb7a",[
+                    "uid"       => $platform['unique_id'],
+                    "platform"  => $task['category']
+                ])->array();
+            }
+            $taskUser = (new BlueTaskUser)->where(['openid' => $request->user['openid'],'job_id' => $param['task_sn'],'task_id' => $param['task_id']])->findOrEmpty();
+            if (!$taskUser->isEmpty()) return error("请勿重复报名");
+            $state = $taskUser->insertGetId([
+                "openid"    => $request->user['openid'],
+                "task_id"   => $param['task_id'],
+                "job_id"    => $param['task_sn'],
+                "source"    => $task['category'],
+                "start_id"  => $starId, // 星图ID
+                "status"    => 0 // 0待提交 1审核中 2审核通过 3已拒绝
+            ]);
+            if (!$state) return errorTrans("error.data");
+            return successTrans("success.data",['qrcode' => "https://work.weixin.qq.com/ca/cawcde3784d6329ab7"],5);
+//            return successTrans("success.data",['task_user_id' => $state]);
+        } catch (\Throwable $throwable) {
+            return error($throwable->getMessage());
+        }
+    }
+
+
+    /**
+     * 绑定星图ID
+     * @param Request $request
+     * @return Response
+     */
+    #[Route(path: "star",methods: "post")]
+    public function bindStarId(Request $request): Response
+    {
+        try {
+            $param = $this->_valid([
+                "star.require"      => trans("empty.require"),
+                "source.require"    => trans("empty.require")
+            ],$request->method());
+            if (!is_array($param)) return error($param);
+            $platform = (new BlueExpertPlatform)->where(["openid" => $request->user['openid'],'source' => $param['source']])->findOrEmpty();
+            if ($platform->isEmpty()) return error("未绑定该平台账号");
+            $platform->star_id = $param['star'];
+            $state = $platform->save();
+            if (!$state) return errorTrans("error.data");
+            return successTrans("success.data");
+        } catch (\Throwable $throwable) {
+            return error($throwable->getMessage());
+        }
+    }
+
+}

+ 74 - 0
app/controller/v2/Withdraw.php

@@ -0,0 +1,74 @@
+<?php
+
+namespace app\controller\v2;
+
+use app\extra\basic\Base;
+use app\middleware\WxMiddleware;
+use app\model\blue\BlueExpert;
+use app\model\blue\BlueWithdrawLog;
+use LinFly\Annotation\Route\Controller;
+use LinFly\Annotation\Route\Middleware;
+use LinFly\Annotation\Route\Route;
+use support\Request;
+use support\Response;
+
+/**
+ * 提现
+ */
+#[Controller(prefix: "/wx_v2/withdraw"),Middleware(WxMiddleware::class)]
+class Withdraw extends Base
+{
+
+    /**
+     * 获取可提现金额
+     * @param Request $request
+     * @return Response
+     */
+    #[Route(path: "balance",methods: "get")]
+    public function getBalance(Request $request): Response
+    {
+        try {
+            $balance = (new BlueExpert)->where("openid",$request->user['openid'])->value("balance");
+            if ($balance > 0) $balance = format_money($balance/100);
+            return successTrans("success.data",compact("balance"));
+        } catch (\Throwable $throwable) {
+            return error($throwable->getMessage());
+        }
+    }
+
+
+    /**
+     * 申请提现
+     * @param Request $request
+     * @return Response
+     */
+    #[Route(path: "submit",methods: "post")]
+    public function submitData(Request $request): Response
+    {
+        try {
+            $param = $this->_valid([
+                "money.require" => trans("empty.require"),
+                "bank.require"  => trans("empty.require")
+            ],$request->method());
+            if(!is_array($param)) return error($param);
+            $balance = (new BlueExpert)->where("openid",$request->user['openid'])->findOrEmpty();
+            if ($balance->isEmpty()) return error("非法操作");
+            if ($param['money'] * 100 > $balance['balance']) return error("余额不足");
+            $bankData = is_string($param['bank']) ? json_decode($param['bank'],true):$param['bank'];
+            if (!isset($bankData['bank_code'])) return error("银行卡数据错误");
+            $state = (new BlueWithdrawLog)->insertGetId([
+                "openid"    => $request->user['openid'],
+                "bank_id"   => $bankData['bank_code'],
+                "money"     => $param['money'] * 100
+            ]);
+            if (!$state) return errorTrans("error.data");
+            $balance->balance = $balance['balance'] - ($param['money'] * 100);
+            $balance->save();
+            return successTrans("success.data");
+        } catch (\Throwable $throwable) {
+            return error($throwable->getMessage());
+        }
+    }
+
+
+}

+ 58 - 0
app/extra/service/blue/ExpertPlatformService.php

@@ -0,0 +1,58 @@
+<?php
+
+namespace app\extra\service\blue;
+
+use app\extra\basic\Service;
+use app\model\blue\BlueExpertPlatform;
+
+class ExpertPlatformService extends Service
+{
+    /**
+     * 列表
+     * @param array $param
+     */
+    public function getList(array $param = [])
+    {
+        $this->mode = new BlueExpertPlatform();
+        return $this->searchVal($param,$this->searchFilter($param))->paginate([
+            "list_rows" => $param['pageSize'],
+            "page"      => $param['page']
+        ]);
+    }
+
+
+    /**
+     * 达人之家
+     * @param array $param
+     * @return mixed
+     */
+    public function getListStar(array $param = [],string $field = "*")
+    {
+        $this->mode = new BlueExpertPlatform();
+        return $this->searchVal($param,$this->searchFilter($param))->with(['job' => function($query){
+            $query->where("status","in",[0,1,2])->field("id,openid");
+        },"user" => function($query){
+            $query->field("openid,group_id")->with(['level' => function($subQue) {
+                $subQue->field("id,name,level");
+            }]);
+        }])->limit(10)->field($field)->select()->toArray();
+    }
+
+
+    /**
+     *
+     * @param array $param
+     * @return array
+     */
+    public function searchFilter(array $param = []): array
+    {
+        $filter = [];
+        !empty($param['type']) && $filter[] = ["type", '=', $param['type']];
+        !empty($param['status']) && $filter[] = ["status", '=', ($param['status']-1)];
+        !empty($param['truename']) && $filter[] = ["truename", 'like', "%{$param['truename']}%"];
+        !empty($param['nick']) && $filter[] = ["nickname", 'like', "%{$param['nick']}%"];
+        !empty($param['source']) && $filter[] = ["source", '=', $param['source']];
+        return $filter;
+    }
+
+}

+ 7 - 4
app/extra/service/blue/TaskService.php

@@ -11,8 +11,9 @@ class TaskService extends Service
     /**
      * 列表
      * @param array $param
+     * @param string $field
      */
-    public function getList(array $param = [])
+    public function getList(array $param = [],string $field = "")
     {
         $this->mode = new BlueTask();
         return $this->searchVal($param,$this->searchFilter($param))->append(['progress'])->withAttr(['progress' => function ($data,$resp) {
@@ -20,7 +21,9 @@ class TaskService extends Service
             return ceil($resp['sign_number']/$resp['need_number'] * 100);
         }])->with(['categoryJoin' => function ($query) {
             $query->field("sign,name,icon");
-        }])->paginate([
+        },'levelJoin' => function($query){
+            $query->field("id,name,level");
+        }])->field($field)->paginate([
             "list_rows" => $param['pageSize'],
             "page"      => $param['page']
         ]);
@@ -39,7 +42,7 @@ class TaskService extends Service
             $query->field("sign,name,icon,small_icon");
         },'levelJoin' => function($query){
             $query->field("id,name,level");
-        }])->field("id,title,task_sn,product_cover_url,total_budget,sign_number,need_number,category,level,sys_level,product_price")->paginate([
+        }])->field("id,title,job_id,product_cover_url,total_budget,sign_number,need_number,category,level,sys_level,product_price")->paginate([
             "list_rows" => $param['pageSize'],
             "page"      => $param['page']
         ]);
@@ -75,7 +78,7 @@ class TaskService extends Service
     {
         $filter = [];
         !empty($param['id']) && $filter[] = ["id", '=', $param['id']];
-        !empty($param['task_sn']) && $filter[] = ["task_sn", '=', $param['task_sn']];
+        !empty($param['task_sn']) && $filter[] = ["job_id", '=', $param['task_sn']];
         !empty($param['type']) && $filter[] = ["type", '=', $param['type']];
         !empty($param['category']) && $filter[] = ["category", '=', $param['category']];
         !empty($param['status']) && $filter[] = ["status", '=', $param['status']];

+ 44 - 0
app/extra/service/blue/UserBankService.php

@@ -0,0 +1,44 @@
+<?php
+
+namespace app\extra\service\blue;
+
+use app\extra\basic\Service;
+use app\model\blue\BlueUserBank;
+
+class UserBankService extends Service
+{
+
+
+    /**
+     * 列表
+     * @param array $param
+     */
+    public function getList(array $param = [])
+    {
+        $this->mode = new BlueUserBank();
+        return $this->searchVal($param,$this->searchFilter($param))->append(['bank_img'])->withAttr(['bank_img' => function($data,$resp){
+            return "https://apimg.alipay.com/combo.png?d=cashier&t={$resp['bank_code']}";
+        }])->paginate([
+            "list_rows" => $param['pageSize'],
+            "page"      => $param['page']
+        ]);
+    }
+
+
+    /**
+     *
+     * @param array $param
+     * @return array
+     */
+    public function searchFilter(array $param = []): array
+    {
+        $filter = [];
+        !empty($param['openid']) && $filter[] = ["openid", '=', $param['openid']];
+        !empty($param['status']) && $filter[] = ["status", '=', ($param['status']-1)];
+        !empty($param['truename']) && $filter[] = ["truename", 'like', "%{$param['truename']}%"];
+        !empty($param['nick']) && $filter[] = ["nickname", 'like', "%{$param['nick']}%"];
+        !empty($param['source']) && $filter[] = ["source", '=', $param['source']];
+        return $filter;
+    }
+
+}

+ 13 - 3
app/extra/tools/XcJob.php

@@ -98,7 +98,7 @@ class XcJob
                 "task_category_list" => [137],
                 "order_status"       => [],
                 "qc_metrics_time_range_param"   => [
-                    "start_time"    => strtotime(date("Y-m-d 00:00:00",strtotime("-180 day"))) * 1000,
+                    "start_time"    => strtotime(date("Y-m-d 00:00:00",strtotime("-360 day"))) * 1000,
                     "end_time"      => strtotime(date("Y-m-d 23:59:59")) * 1000,
                 ]
             ],
@@ -231,7 +231,7 @@ class XcJob
     }
 
     /**
-     * 星川任务详情
+     * 星川任务详情 - 项目
      * @param string $jobId
      * @return array
      */
@@ -240,9 +240,19 @@ class XcJob
         return Http::withHeaders($this->header)->get("https://www.xingtu.cn/gw/api/task/provider_get_project_detail",['project_id' => $jobId])->array();
     }
 
+    /**
+     * 星川任务详情 - 任务
+     * @param string $jobId
+     * @return array
+     */
+    public function getTaskDetail(string $jobId = ""): array
+    {
+        return Http::withHeaders($this->header)->get("https://www.xingtu.cn/gw/api/task/provider_get_task_detail",['task_id' => $jobId])->array();
+    }
+
 
     protected function getCookie(): string
     {
-        return "csrftoken=DiDhfVo0pz9HnEsJ3zGKA39ixm9AxA8t; tt_webid=7637854168573183526; passport_csrf_token=9510b4581fea0015ec5e3293fefb6194; passport_csrf_token_default=9510b4581fea0015ec5e3293fefb6194; is_staff_user=false; has_biz_token=false; s_v_web_id=verify_mqhwxxgj_rimh5qRs_m3VS_4oAv_8yXX_EMfuKVBYkpVW; passport_auth_status=39cd9f76ea3c8ac5c9beab7dfee4825f%2C56147e39ce55d737468b0c00fe003bc2; passport_auth_status_ss=39cd9f76ea3c8ac5c9beab7dfee4825f%2C56147e39ce55d737468b0c00fe003bc2; uid_tt=32a10b0de605d5e5e09080d5531eb77e; uid_tt_ss=32a10b0de605d5e5e09080d5531eb77e; sid_tt=528106ce020f1db0e4ca4ff7895135ef; sessionid=528106ce020f1db0e4ca4ff7895135ef; sessionid_ss=528106ce020f1db0e4ca4ff7895135ef; Hm_lvt_5d77c979053345c4bd8db63329f818ec=1781690725,1782806402; HMACCOUNT=7B24288D273CC431; csrf_session_id=7b04abc1fd6e463b4e7e191681f733da; Hm_lpvt_5d77c979053345c4bd8db63329f818ec=1783489162; sid_guard=528106ce020f1db0e4ca4ff7895135ef%7C1783489186%7C5184000%7CSun%2C+06-Sep-2026+05%3A39%3A46+GMT; session_tlb_tag=sttt%7C16%7CUoEGzgIPHbDkyk_3iVE17_________-2m7Gf0ljknGiOP6NwunArIr0uRP8Cc8jMGlCcp1XhGac%3D; sid_ucp_v1=1.0.0-KDFkMTdlODNhYTQ5NTZkMTg4YWYzZWE0OTA2OTQzOTFiMzc0MjNjNGMKFwiUv5Cvv8yyBxCixbfSBhimDDgCQPEHGgJsZiIgNTI4MTA2Y2UwMjBmMWRiMGU0Y2E0ZmY3ODk1MTM1ZWY; ssid_ucp_v1=1.0.0-KDFkMTdlODNhYTQ5NTZkMTg4YWYzZWE0OTA2OTQzOTFiMzc0MjNjNGMKFwiUv5Cvv8yyBxCixbfSBhimDDgCQPEHGgJsZiIgNTI4MTA2Y2UwMjBmMWRiMGU0Y2E0ZmY3ODk1MTM1ZWY; star_sessionid=85b9f01f4fb6e21eaaeadeb62d7b4b6c";
+        return "csrftoken=DiDhfVo0pz9HnEsJ3zGKA39ixm9AxA8t; tt_webid=7637854168573183526; is_staff_user=false; has_biz_token=false; s_v_web_id=verify_mqhwxxgj_rimh5qRs_m3VS_4oAv_8yXX_EMfuKVBYkpVW; passport_auth_status=39cd9f76ea3c8ac5c9beab7dfee4825f%2C56147e39ce55d737468b0c00fe003bc2; passport_auth_status_ss=39cd9f76ea3c8ac5c9beab7dfee4825f%2C56147e39ce55d737468b0c00fe003bc2; uid_tt=32a10b0de605d5e5e09080d5531eb77e; uid_tt_ss=32a10b0de605d5e5e09080d5531eb77e; sid_tt=528106ce020f1db0e4ca4ff7895135ef; sessionid=528106ce020f1db0e4ca4ff7895135ef; sessionid_ss=528106ce020f1db0e4ca4ff7895135ef; Hm_lvt_5d77c979053345c4bd8db63329f818ec=1781690725,1782806402; HMACCOUNT=7B24288D273CC431; csrf_session_id=7b04abc1fd6e463b4e7e191681f733da; Hm_lpvt_5d77c979053345c4bd8db63329f818ec=1783665817; passport_csrf_token=769a68a189b6cde4cf43efe68412d7cc; passport_csrf_token_default=769a68a189b6cde4cf43efe68412d7cc; sid_guard=528106ce020f1db0e4ca4ff7895135ef%7C1783665835%7C5184000%7CTue%2C+08-Sep-2026+06%3A43%3A55+GMT; session_tlb_tag=sttt%7C9%7CUoEGzgIPHbDkyk_3iVE17__________0dbcF7DEwEMKososyJJhu2QhkA2vxJQ_iQSg2uymqiXU%3D; sid_ucp_v1=1.0.0-KDhiYzQ2OGM1NTc1OWUzN2VhYmIyOWVkYTg4MmE0MTNkYTU0ZWI4MDYKFwiUv5Cvv8yyBxCrqcLSBhimDDgCQPEHGgJsZiIgNTI4MTA2Y2UwMjBmMWRiMGU0Y2E0ZmY3ODk1MTM1ZWY; ssid_ucp_v1=1.0.0-KDhiYzQ2OGM1NTc1OWUzN2VhYmIyOWVkYTg4MmE0MTNkYTU0ZWI4MDYKFwiUv5Cvv8yyBxCrqcLSBhimDDgCQPEHGgJsZiIgNTI4MTA2Y2UwMjBmMWRiMGU0Y2E0ZmY3ODk1MTM1ZWY; star_sessionid=31ef398c5df8ba8f37d006946bab5133";
     }
 }

+ 45 - 0
app/model/blue/BlueBankCompany.php

@@ -0,0 +1,45 @@
+<?php
+
+namespace app\model\blue;
+
+use app\extra\basic\Model;
+
+
+/**
+ * @property integer $id (主键)
+ * @property string $name 
+ * @property string $sub_name 
+ * @property string $bank_code
+ */
+class BlueBankCompany extends Model
+{
+    /**
+     * The connection name for the model.
+     *
+     * @var string|null
+     */
+    protected $connection = 'mysql';
+    
+    /**
+     * The table associated with the model.
+     *
+     * @var string
+     */
+    protected string $table = "blue_bank_company";
+    
+    /**
+     * The primary key associated with the table.
+     *
+     * @var string
+     */
+    protected string $primaryKey = "id";
+    
+    /**
+     * Indicates if the model should be timestamped.
+     *
+     * @var bool
+     */
+    public bool $timestamps = false;
+
+
+}

+ 13 - 2
app/model/blue/BlueExpertPlatform.php

@@ -3,11 +3,13 @@
 namespace app\model\blue;
 
 use app\extra\basic\Model;
+use think\model\relation\HasMany;
+use think\model\relation\HasOne;
 
 
 /**
- * @property integer $id (主键)
- * @property mixed $openid 
+ * @property integer $id (主键)
+ * @property mixed $openid 
  * @property mixed $source
  */
 class BlueExpertPlatform extends Model
@@ -40,5 +42,14 @@ class BlueExpertPlatform extends Model
      */
     public bool $timestamps = false;
 
+    public function user(): HasOne
+    {
+        return $this->hasOne(BlueExpert::class,"openid","openid");
+    }
+
+    public function job(): HasMany
+    {
+        return $this->hasMany(BlueTaskUser::class,"openid","openid");
+    }
 
 }

+ 10 - 0
app/model/blue/BlueTask.php

@@ -52,6 +52,16 @@ class BlueTask extends Model
         return format_money($val/100);
     }
 
+    public function getExpirationTimeEndAttr($val): int
+    {
+        return strtotime($val);
+    }
+
+    public function getNeedNumberAttr($val): int
+    {
+        return $val>0?$val:999;
+    }
+
     public function categoryJoin(): HasOne
     {
         return $this->hasOne(BlueCategory::class,'sign','category');

+ 32 - 0
app/validate/blue/BankValidate.php

@@ -0,0 +1,32 @@
+<?php
+
+namespace app\validate\blue;
+
+use think\Validate;
+
+class BankValidate extends Validate
+{
+
+    protected $rule = [
+        "truenname"     => "require",
+        "idcard"        => "require|idCard",
+        "mobile"        => "require|mobile",
+        "bank_num"      => "require",
+        "bank_code"     => "require",
+    ];
+
+
+    protected $message = [
+        "truenname.require"     => "请输入姓名",
+        "idcard.require"        => "请输入身份证号",
+        "idcard.idCard"         => "身份证号有误",
+        "mobile.require"        => "请输入手机号码",
+        "mobile.mobile"         => "手机号有误",
+        "bank_num.require"      => "请输入银行卡号",
+        "bank_code.require"     => "请选择开户行",
+    ];
+    protected $scene = [
+        'add'  =>  ['truenname','idcard','mobile','bank_num','bank_code'],
+    ];
+
+}

+ 3 - 8
app/validate/blue/ExpertValidate.php

@@ -10,30 +10,25 @@ class ExpertValidate extends Validate
 
 
     protected $rule = [
-        "truenname"     => "require",
+        "truename"     => "require",
         "idcard"        => "require|idCard",
         "mobile"        => "require|mobile",
         "city"          => "require",
         "city_path"     => "require",
-        "sex"           => "require",
-        "married"       => "require",
-        "child"         => "require",
-        "pet"           => "require",
     ];
 
 
     protected $message = [
-        "truenname.require"     => "请输入姓名",
+        "truename.require"     => "请输入姓名",
         "idcard.require"        => "请输入身份证号",
         "idcard.idCard"         => "身份证号有误",
         "mobile.require"        => "请输入手机号码",
         "mobile.mobile"         => "手机号有误",
         "city.require"          => "请选择城市",
         "city_path.require"     => "请选择城市",
-        "pet.require"           => "请选择宠物",
     ];
     protected $scene = [
-        'add'  =>  ['truenname','idcard','mobile','city','city_path','sex','married','child','pet'],
+        'add'  =>  ['truename','idcard','mobile','city','city_path'],
     ];
 
 }