Referral.php 58 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465
  1. <?php
  2. namespace app\admin\controller\referral;
  3. use app\admin\library\ShortUrl;
  4. use app\common\constants\ErrorCodeConstants;
  5. use app\common\controller\Backend;
  6. use app\common\library\Redis;
  7. use app\common\service\ImageService;
  8. use app\common\service\ReferralService;
  9. use app\common\service\ResourceService;
  10. use app\common\utility\DiyQRCode;
  11. use app\main\constants\CacheConstants;
  12. use app\main\helper\StringHelper;
  13. use app\main\service\AdminService;
  14. use app\main\service\BookService;
  15. use app\main\service\VisitLimitService;
  16. use Endroid\QrCode\QrCode;
  17. use think\Config;
  18. use think\Exception;
  19. use think\exception\HttpException;
  20. use think\Url;
  21. /**
  22. * 导粉推广文案
  23. *
  24. * @icon fa fa-circle-o
  25. */
  26. class Referral extends Backend
  27. {
  28. /**
  29. * @var \app\common\model\Referral
  30. */
  31. protected $model = null;
  32. protected $dayCollectModel = null;
  33. protected $relationSearch = true;
  34. /**
  35. * 无需鉴权的方法,但需要登录
  36. * @var array
  37. */
  38. protected $noNeedRight = ['ajaxgetrandomtitle','daily','collection', 'merge_image', 'ajaxgetshare','show_tpl'];
  39. /**
  40. * 是否开启数据限制
  41. * 支持auth/personal
  42. * 表示按权限判断/仅限个人
  43. * 默认为禁用,若启用请务必保证表中存在admin_id字段
  44. */
  45. public function _initialize()
  46. {
  47. parent::_initialize();
  48. $this->model = model('Referral');
  49. $this->dayCollectModel = model('ReferralDayCollect');
  50. $this->view->assign("wxTypeList", $this->model->getWxTypeList());
  51. $this->view->assign("typeList", $this->model->getTypeList());
  52. $groupId = $this->auth->getGroupIds()[0];
  53. if($groupId == 4){
  54. $this->bookAgentId = $this->auth->id;
  55. if($this->auth->channel_id){
  56. $this->bookChannelId = $this->auth->channel_id;
  57. }else{
  58. $aeInfo = model('AdminExtend')->getInfo($this->auth->id);
  59. $this->bookChannelId = $aeInfo['create_by'];
  60. }
  61. }elseif($groupId == 3){
  62. $this->bookAgentId = 0;
  63. $this->bookChannelId = $this->auth->id;
  64. }else{
  65. $this->bookAgentId = 0;
  66. $this->bookChannelId = 0;
  67. }
  68. $this->view->assign("sexList", $this->model->getGuideSexList());
  69. }
  70. public function collection()
  71. {
  72. $ids = $this->request->param('ids');
  73. if($ids){
  74. $update = model("Referral")
  75. ->wherein('id', $ids)
  76. ->exp('is_collect', 'abs(is_collect -1)')
  77. ->update();
  78. if($update !== false){
  79. $this->success("操作成功");
  80. }else{
  81. $this->error("操作失败");
  82. }
  83. }else{
  84. $this->error("没有找到这条推广链接");
  85. }
  86. }
  87. /**
  88. * 查看
  89. */
  90. public function daily()
  91. {
  92. $params_arr = [];
  93. if ($this->auth->agent_id) { //配号代理商
  94. $params_arr['channel_id'] = $this->auth->agent_id;
  95. $params_arr['agent_id'] = $this->auth->id;
  96. } elseif ($this->group == 4) { //代理商
  97. $params_arr['agent_id'] = $this->auth->id;
  98. $params_arr['channel_id'] = $this->auth->channel_id;
  99. } elseif ($this->group == 3) { //渠道商
  100. $params_arr['channel_id'] = $this->auth->channel_id;
  101. }
  102. $adminConfig = AdminService::instance()->getAdminConfigModel()->getAdminInfoAll($params_arr['channel_id']);
  103. $configChannelIds = Config::get('site.smallpay_channel_id') ?? '';
  104. if ($configChannelIds == '*') {
  105. $open = true;
  106. } else {
  107. $list = explode(',', $configChannelIds);
  108. $open = in_array($this->auth->id, $list);
  109. }
  110. if ($open) {
  111. $adminConfig['small_goods_id'] = Config::get('site.smallpay_goods_id');
  112. }
  113. $this->assign('adminconfig', $adminConfig);
  114. $this->assign('param', $params_arr);
  115. return $this->view->fetch();
  116. }
  117. /**
  118. * 每日数据
  119. *
  120. * @param string $ids
  121. * @return string|\think\response\Json
  122. * @throws Exception
  123. */
  124. public function daydata($ids ='')
  125. {
  126. if (empty($ids)) {
  127. $this->error('缺少参数');
  128. }
  129. //设置过滤方法
  130. $this->request->filter(['strip_tags']);
  131. if ($this->request->isAjax()) {
  132. //如果发送的来源是Selectpage,则转发到Selectpage
  133. /*if ($this->request->request('pkey_name')) {
  134. return $this->selectpage();
  135. }*/
  136. //list($where, $sort, $order, $offset, $limit) = $this->buildparams();
  137. if (VisitLimitService::instance()->checkMigratedV2()) {
  138. $list = \app\main\service\ReferralService::instance()->getMigrateReferralDayCollect($ids)->data;
  139. $total = count($list);
  140. } else {
  141. $map = [
  142. //'createdate' => ['<', date("Ymd")],
  143. 'createdate' => ['between', [date("Ymd", strtotime("-31 days")), date("Ymd", strtotime("-1 days"))]],
  144. 'referral_id' => $ids,
  145. ];
  146. $total = $this->dayCollectModel
  147. ->where($map)
  148. ->count();
  149. $list = $this->dayCollectModel
  150. ->where($map)
  151. ->order('createdate', 'desc')
  152. ->select();
  153. }
  154. if (!empty($list)) {
  155. $cost = model("Referral")->where('id', 'eq', $ids)->value('cost');
  156. foreach ($list as &$row) {
  157. $row['recharge_money'] = StringHelper::moneyFormat($row['recharge_money']);
  158. $row['all_recharge_money'] = StringHelper::moneyFormat($row['all_recharge_money']);
  159. $row['cost'] = $cost;
  160. }
  161. }
  162. $result = array("total" => $total, "rows" => $list);
  163. return json($result);
  164. }
  165. $this->assignconfig('referral_id', $ids);
  166. return $this->view->fetch();
  167. }
  168. private function getChannelOphost($channel_id){
  169. $adminConfig = model('adminConfig')->getAdminInfoAll($channel_id);
  170. $url_referral = Config::get('site.scheme').'://'.$adminConfig['appid'].'.'.$adminConfig['ophost_host'];
  171. return $url_referral;
  172. }
  173. private function index_ajax($ophost_url,$admin_id = null,$push = null,$collect = null,$disable = null){
  174. //如果发送的来源是Selectpage,则转发到Selectpage
  175. if ($this->request->request('pkey_name')) {
  176. return $this->selectpage();
  177. }
  178. [$where, $sort, $order, $offset, $limit] = $this->buildparams();
  179. $limit = 10;
  180. $condition = [];
  181. if($admin_id){
  182. $condition['admin_id'] = $admin_id;
  183. }else{
  184. $condition['admin_id'] = $this->auth->id;
  185. }
  186. if($push !== null){
  187. $condition['push'] = $push ?? '0';
  188. }
  189. if($collect !== null){
  190. $condition['is_collect'] = 1;
  191. }
  192. if($disable !== null){
  193. $condition['referral.state'] = '0';
  194. } else {
  195. $condition['referral.state'] = '1';
  196. }
  197. if (strstr($push, ',')){
  198. $condition['push'] = ['in', explode(',', $push)];
  199. }
  200. $filter = \json_decode($this->request->param('filter'), true);
  201. if(isset($filter['book_id']) || isset($filter['book.name'])){
  202. $total = $this->model
  203. ->with('book')
  204. ->where($where)
  205. ->where($condition)
  206. ->count();
  207. $list = $this->model
  208. ->with('book')
  209. ->where($where)
  210. ->where($condition)
  211. ->order($sort, $order)
  212. ->limit($offset, $limit)
  213. ->select();
  214. } else {
  215. $total = $this->model
  216. ->where($where)
  217. ->where($condition)
  218. ->count();
  219. $list = $this->model
  220. ->where($where)
  221. ->where($condition)
  222. ->order($sort, $order)
  223. ->limit($offset, $limit)
  224. ->select();
  225. $book_list = BookService::instance()->getBookModel()->getBooksInfo(array_column($list, 'book_id'));
  226. foreach ($list as $index=>$ref) {
  227. if (array_key_exists($ref['book_id'], $book_list)) {
  228. $list[$index]['book'] = $book_list[$ref['book_id']];
  229. }
  230. }
  231. }
  232. $migrateCollectList = [];
  233. $migrate = VisitLimitService::instance()->checkMigratedV2();
  234. if ($migrate) {
  235. $referralIds = array_column($list, 'id');
  236. $migrateCollectList = \app\main\service\ReferralService::instance()->getReferralCollectFromApi($referralIds)->data;
  237. }
  238. foreach ($list as $k=>$v){
  239. //获取当前书籍的默认关注章节
  240. if(empty($v['guide_chapter_idx']) && !empty($v['book_id'])){
  241. $default_chapter_idx = 0;
  242. if($this->group == 4 || $this->group == 3){
  243. $default_chapter_idx = model('Guide')->getGuideChapter($this->auth->id,$v['book_id'],0,$this->auth->channel_id);
  244. }else if($this->group == 2){
  245. $group = model('AuthGroupAccess')->getGroupId($condition['admin_id']);
  246. if($group == 3){
  247. $default_chapter_idx = model('Guide')->getGuideChapter($condition['admin_id'],$v['book_id'],0,$condition['admin_id']);
  248. }else if($group == 4){
  249. if($adminExtend = model('AdminExtend')->getInfo($condition['admin_id'])){
  250. $default_chapter_idx = model('Guide')->getGuideChapter($condition['admin_id'],$v['book_id'],0,$adminExtend['create_by']);
  251. }
  252. }
  253. }
  254. $list[$k]['guide_chapter_idx'] = $default_chapter_idx;
  255. }
  256. $list[$k]['url_referral'] = $ophost_url.'/t/'.$v['id'];
  257. $list[$k]['skin_url'] = ReferralService::instance()->getSkinUrl($v['id'], $v['source_url']);
  258. if ($migrate) {
  259. if (array_key_exists($v['id'], $migrateCollectList)) {
  260. foreach ($migrateCollectList[$v['id']] as $key=>$value) {
  261. $list[$k][$key] = $value;
  262. }
  263. }
  264. } else {
  265. $dayMTkey = "M-T:".$v['id'].":".date("d"); //今日充值金额key
  266. $list[$k]['dayuv'] = (int)Redis::instance()->get(CacheConstants::getReadOfReferralIdKey($v['id']));
  267. $list[$k]['dayut'] = (int)Redis::instance()->get(CacheConstants::getSubscribeOfReferralIdKey($v['id'])); //今日关注人数
  268. $list[$k]['daymt'] = (int)Redis::instance()->get($dayMTkey)? round(Redis::instance()->get($dayMTkey) / 100, 2) :0; //今日充值金额
  269. $list[$k]['dayjt'] = (int)Redis::instance()->get(CacheConstants::getSubscribeOfPureReferralIdKey($v['id'])); //今日净关注人数
  270. $list[$k]['dayqt'] = (int)Redis::instance()->get(CacheConstants::getUnsubscribeOfReferralIdKey($v['id'])); //今日取消关注人数
  271. $list[$k]['net_follow_num'] = (int)$list[$k]['net_follow_num'];
  272. if ($list[$k]['uv'] < $list[$k]['dayuv']) {
  273. $list[$k]['uv'] = $list[$k]['dayuv'];
  274. }
  275. if ($list[$k]['follow'] < $list[$k]['dayut']) {
  276. $list[$k]['follow'] = $list[$k]['dayut'];
  277. }
  278. if ($list[$k]['net_follow_num'] < $list[$k]['dayjt']) {
  279. $list[$k]['net_follow_num'] = $list[$k]['dayjt'];
  280. }
  281. $dayMTNkey = "M-T-N:".$v['id'].":".date("d"); //今日充值笔数key
  282. $list[$k]['order_nums'] = (int)$list[$k]['orders_num'];
  283. $list[$k]['day_order_nums'] = (int)Redis::instance()->get($dayMTNkey);
  284. }
  285. if(!empty($v['book_id'])){
  286. $isLimited = model('BookLimit')->backendHasLimit($this->bookAgentId,$this->bookChannelId,$v['book_id']);
  287. if($isLimited){
  288. $list[$k]['limited'] = 1;
  289. }else{
  290. $list[$k]['limited'] = 0;
  291. }
  292. }else{
  293. $list[$k]['limited'] = 0;
  294. }
  295. $list[$k]['short_url'] = replaceShortDomain($list[$k]['url_referral'], $v['short_id']);
  296. }
  297. $result = array("total" => $total, "rows" => $list);
  298. return json($result);
  299. }
  300. public function admin_index()
  301. {
  302. [$where, $sort, $order, $offset, $limit] = $this->buildparams();
  303. $push = $this->request->param('push') ?? '0';
  304. $this->assign('push', $push);
  305. $this->assignconfig('push', $push);
  306. if ($this->request->isAjax()) {
  307. $list = \app\main\service\ReferralService::instance()->getAdminReferralList($this->auth->id, $push, $where, $sort, $order, $offset, $limit)->data;
  308. return $list;
  309. }
  310. return $this->view->fetch();
  311. }
  312. /**
  313. * 查看
  314. */
  315. public function index()
  316. {
  317. $base_url_params = [];
  318. $channel_url_path = null;
  319. // 是否开启微信分享开关
  320. $open_wechat_share = Config::get('site.open_wechat_share') ?? 0;
  321. //禁用
  322. $disable = $this->request->param('disable') ?? null;
  323. if($disable){
  324. $base_url_params['disable'] = 1;
  325. }
  326. //收藏
  327. $collection = $this->request->param('collection') ?? null;
  328. if($collection){
  329. $base_url_params['collection'] = 1;
  330. }
  331. //内推外派
  332. $push = null;
  333. if(!$disable && !$collection){
  334. $push = $this->request->param('push') ?? '0';
  335. }
  336. $base_url_params['push'] = $push;
  337. //被查看的渠道ID
  338. $lock_id = $_GET['ids'] ?? 0;
  339. //查看渠道
  340. if($lock_id){
  341. $base_url_params['ids'] = $_GET['ids'];
  342. $this->assign('type',1);
  343. $this->assignconfig('rtype',1);
  344. if ($this->group == 2) {
  345. $channel_url_path = $this->getChannelOphost($_GET['ids']);
  346. }
  347. }
  348. //渠道本身
  349. if(!$lock_id){
  350. if ($collection == 1 || $disable == 1) {
  351. $this->assign('type', 1);
  352. } else {
  353. $this->assign('type', 0);
  354. }
  355. $this->assignconfig('rtype',0);
  356. $channel_id = $this->auth->agent_id ? $this->auth->agent_id : $this->auth->channel_id;
  357. if($this->group == 4 || $this->group == 3){
  358. $channel_url_path = $this->getChannelOphost($channel_id);
  359. }
  360. if($this->auth->agent_id || $this->group == 3){
  361. if(!model('AdminConfig')->checkWechatConfig($this->auth->id)){
  362. $this->error('请先授权微信服务号给本系统,正在跳转授权设置页面~', url('admin/config'));
  363. }
  364. }
  365. }
  366. $this->assign('push', $push);
  367. $this->assign('collection',$collection);
  368. $this->assign('disable',$disable);
  369. $this->assignconfig('push',$push);
  370. $this->assignconfig('collection',$collection);
  371. $this->assignconfig('url_referral', $channel_url_path);
  372. $this->assignconfig('open_wechat_share', $open_wechat_share);
  373. $this->assignconfig('authGroupId', $this->group);
  374. $this->assignconfig('referralUrl',Url::build('admin/referral.referral/index',$base_url_params));
  375. $adminExtendInfo = model('AdminExtend')->getInfo($this->auth->id);
  376. $this->assignconfig('authDistribute', $adminExtendInfo['distribute']);
  377. if($this->request->isAjax()){
  378. return $this->index_ajax($channel_url_path,$lock_id,$push,$collection,$disable);
  379. }
  380. return $this->view->fetch();
  381. }
  382. public function lookAgentReferral(){
  383. $base_url_params = [];
  384. //禁用
  385. $disable = $this->request->param('disable') ?? null;
  386. if($disable){
  387. $base_url_params['disable'] = 1;
  388. }
  389. //收藏
  390. $collection = $this->request->param('collection') ?? null;
  391. if($collection){
  392. $base_url_params['collection'] = 1;
  393. }
  394. //内推外派
  395. $push = null;
  396. if(!$disable && !$collection){
  397. $push = $this->request->param('push') ?? '0';
  398. $base_url_params['push'] = $push;
  399. }
  400. $dls = model("AdminExtend")->join('admin',' `admin_extend`.`admin_id` = `admin`.`id`')->where(['create_by'=> $this->auth->id])->select();
  401. if ($this->request->isAjax()) {
  402. //如果发送的来源是Selectpage,则转发到Selectpage
  403. if ($this->request->request('pkey_name')) {
  404. return $this->selectpage();
  405. }
  406. [$where, $sort, $order, $offset, $limit] = $this->buildparams();
  407. //$map['admin_id'] = array('in', $this->auth->id);
  408. if($dls){
  409. $map['admin_id'] = array('in',implode(',',array_column($dls, 'admin_id')));
  410. } else {
  411. $result = array("total" => 0, "rows" => []);
  412. return json($result);
  413. }
  414. $common = [];
  415. if($push !== null){
  416. $common['referral.push'] = $push ?? '0';
  417. }
  418. if($collection !== null){
  419. $common['referral.is_collect'] = 1;
  420. }
  421. if($disable !== null){
  422. $common['referral.state'] = '0';
  423. } else {
  424. $common['referral.state'] = '1';
  425. }
  426. $total = $this->model
  427. ->with('book')
  428. ->where($where)
  429. ->where($map)
  430. ->where($common)
  431. ->order($sort, $order)
  432. ->count();
  433. //dump($this->model->getLastSql());die;
  434. $list = $this->model
  435. ->with('book')
  436. ->where($where)
  437. ->where($map)
  438. ->where($common)
  439. ->order($sort, $order)
  440. ->limit($offset, $limit)
  441. ->select();
  442. $adminExtend = model('AdminExtend')->where($map)->select();
  443. $migrateCollectList = [];
  444. $migrate = VisitLimitService::instance()->checkMigratedV2();
  445. if ($migrate) {
  446. $referralIds = array_column($list, 'id');
  447. $migrateCollectList = \app\main\service\ReferralService::instance()->getReferralCollectFromApi($referralIds)->data;
  448. }
  449. foreach($list as $k => $v){
  450. $url_referral = '';
  451. foreach($adminExtend as $val){
  452. if($v['admin_id'] == $val['admin_id']){
  453. if($val['distribute']){
  454. $info = model('AdminConfig')->getAdminInfoAll($val['admin_id']);
  455. if(isset($info['entry_host']) && !empty($info['entry_host'])){
  456. $url_referral = Config::get('site.scheme').'://'.$info['entry_host'];
  457. }else{
  458. if(isset($info['ophost_host']) && isset($info['appid'])){
  459. $url_referral = Config::get('site.scheme').'://'.$info['appid'].'.'.$info['ophost_host'];
  460. }
  461. }
  462. }else{
  463. $info = model('AdminConfig')->getAdminInfoAll($this->auth->id);
  464. if(isset($info['entry_host']) && !empty($info['entry_host'])){
  465. $url_referral = Config::get('site.scheme').'://'.$info['entry_host'];
  466. }else{
  467. if(isset($info['ophost_host']) && isset($info['appid'])){
  468. $url_referral = Config::get('site.scheme').'://'.$info['appid'].'.'.$info['ophost_host'];
  469. }
  470. }
  471. }
  472. }
  473. }
  474. $list[$k]['url_referral'] = $url_referral.'/t/'.$v['id'];
  475. $list[$k]['short_url'] = replaceShortDomain($list[$k]['url_referral'], $v['short_id']);
  476. $list[$k]['url_referral'] = $url_referral.'/t/'.$v['id'];
  477. if ($migrate) {
  478. if (array_key_exists($v['id'], $migrateCollectList)) {
  479. $list[$k] = array_merge($list[$k]->getData(), $migrateCollectList[$v['id']]);
  480. }
  481. } else {
  482. $dayMTkey = "M-T:".$v['id'].":".date("d"); //今日充值金额key
  483. $list[$k]['dayuv'] = (int)Redis::instance()->get(CacheConstants::getReadOfReferralIdKey($v['id']));
  484. $list[$k]['dayut'] = (int)Redis::instance()->get(CacheConstants::getSubscribeOfReferralIdKey($v['id'])); //今日关注人数
  485. $list[$k]['daymt'] = (int)Redis::instance()->get($dayMTkey)? round(Redis::instance()->get($dayMTkey) / 100, 2) :0; //今日充值金额
  486. $list[$k]['dayjt'] = (int)Redis::instance()->get(CacheConstants::getSubscribeOfPureReferralIdKey($v['id'])); //今日净关注人数
  487. $list[$k]['dayqt'] = (int)Redis::instance()->get(CacheConstants::getUnsubscribeOfReferralIdKey($v['id'])); //今日取消关注人数
  488. $list[$k]['net_follow_num'] = (int)$list[$k]['net_follow_num'];
  489. if ($list[$k]['uv'] < $list[$k]['dayuv']) {
  490. $list[$k]['uv'] = $list[$k]['dayuv'];
  491. }
  492. if ($list[$k]['follow'] < $list[$k]['dayut']) {
  493. $list[$k]['follow'] = $list[$k]['dayut'];
  494. }
  495. if ($list[$k]['net_follow_num'] < $list[$k]['dayjt']) {
  496. $list[$k]['net_follow_num'] = $list[$k]['dayjt'];
  497. }
  498. $dayMTNkey = "M-T-N:".$v['id'].":".date("d"); //今日充值笔数key
  499. $list[$k]['order_nums'] = (int)$list[$k]['orders_num'];
  500. $list[$k]['day_order_nums'] = (int)Redis::instance()->get($dayMTNkey);
  501. }
  502. }
  503. $result = array("total" => $total, "rows" => $list);
  504. return json($result);
  505. }
  506. $this->assign('push', $push);
  507. $this->assign('collection',$collection);
  508. $this->assign('disable',$disable);
  509. $this->assignconfig('push',$push);
  510. $this->assignconfig('collection',$collection);
  511. $this->assignconfig('adminExtend',$dls);
  512. $this->assignconfig('look_url',Url::build('admin/referral.referral/lookAgentReferral',$base_url_params));
  513. return $this->view->fetch();
  514. }
  515. /**
  516. * 添加
  517. */
  518. public function add()
  519. {
  520. $isLimited = false;
  521. if ($this->request->isPost()) {
  522. $params = $this->request->post("row/a");
  523. if ($params) {
  524. $params['admin_id'] = $this->auth->id;
  525. $params['createtime'] = time();
  526. if ($this->dataLimit) {
  527. $params[$this->dataLimitField] = $this->auth->id;
  528. }
  529. try
  530. {
  531. //是否采用模型验证
  532. if ($this->modelValidate) {
  533. $name = basename(str_replace('\\', '/', get_class($this->model)));
  534. $validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.add' : true) : $this->modelValidate;
  535. $this->model->validate($validate);
  536. }
  537. if(isset($params['book_id'])){
  538. if(empty($params['book_id'])){
  539. $this->error('获取书籍信息失败');
  540. }
  541. $bookInfo = model('book')->get($params['book_id']);
  542. if ($bookInfo['state'] == 0 || $bookInfo['cansee'] == 0) {
  543. $this->error('抱歉,本书已下架,无法生成推广链接~');
  544. }
  545. }
  546. //获取当前书籍的默认关注章节
  547. $default_chapter_idx = $params['guide_chapter_idx'] ?? 0;
  548. if(isset($params['guide_chapter_idx']) && empty($params['guide_chapter_idx']) && isset($params['book_id']) && !empty($params['book_id'])){
  549. if($this->group == 4){
  550. $default_chapter_idx = model('Guide')->getGuideChapter($this->auth->id,$params['book_id'],0,$this->auth->channel_id);
  551. }else{
  552. if (in_array($this->group, [7, 8])) {
  553. //vip和vip运营者
  554. //弹出警告 必填项
  555. $this->error('导粉章节数必填');
  556. //$default_chapter_idx = model('Guide')->getGuideChapter(0,$params['book_id'],0,0);
  557. } else {
  558. $default_chapter_idx = model('Guide')->getGuideChapter($this->auth->id,$params['book_id'],0,$this->auth->channel_id);
  559. }
  560. }
  561. }
  562. //导粉章节小于收费章节
  563. if(isset($params['book_id'])){
  564. if($default_chapter_idx > $this->bookPayChapterIdex($params['book_id'])){
  565. $this->error('导粉章节数必须小于收费章节数');
  566. }
  567. }
  568. //落地页推广
  569. if($params['type'] == 3){
  570. if(!$params['guide_idx']){
  571. $this->error('落地页章节数必填');
  572. }
  573. if($params['guide_idx'] > $default_chapter_idx){
  574. $this->error('落地页章节数必须小于导粉章节数');
  575. }
  576. if($params['guide_idx'] > $this->bookReferralNumber($params['book_id'])){
  577. $this->error('落地页章节数必须小于推广文案数量');
  578. }
  579. }
  580. if(!$this->request->has('push') && !isset($params['push'])){
  581. $params['push'] = 0;
  582. }
  583. if($this->request->has('push')){
  584. $params['push'] = $this->request->param('push');
  585. }
  586. $params['share_image'] = ResourceService::instance()->getRandomImage()->data;
  587. $params['share_title'] = ResourceService::instance()->getRandomTitle()->data;
  588. $insertId = $this->model->allowField(true)->insertGetId($params);
  589. if($insertId === false){
  590. $this->error($this->model->getError());
  591. }
  592. $params['closeTip'] = 0;
  593. //vip和vip运营创建分流链接
  594. if (in_array($this->group, [7, 8])) {
  595. //生成VIP推广链接信息
  596. $vipReferralParams = [
  597. 'admin_id' => $this->auth->id,
  598. 'createtime' => time(),
  599. 'referral_id' => $insertId,
  600. 'push' => $params['push'],
  601. //'short_url' => Config::get('site.short_url_host').'/v/'.$id,
  602. ];
  603. $vipReferralId = model('ReferralLibrary')->allowField(true)->insertGetId($vipReferralParams);
  604. $params['closeTip'] = 1;
  605. $this->success('', null, $params);
  606. }
  607. //
  608. $channel_id = $this->auth->agent_id ? $this->auth->agent_id : $this->auth->channel_id;
  609. $params['url_referral'] = $this->getChannelOphost($channel_id) . '/t/' . $insertId;
  610. $source_url = '';
  611. $params['id'] = $insertId;
  612. //首页
  613. if ($params['type'] == 2) {
  614. $source_url .= '?referral_id='.$insertId;
  615. } else {
  616. $source_url .= '/index/book/chapter?book_id=' . $params['book_id'] . '&sid=' . $params['chapter_id'] . '&referral_id=' . $insertId;
  617. }
  618. if ($this->group == 4) {
  619. $source_url .= '&agent_id='.$this->auth->id;
  620. }
  621. $params['source_url'] =getCurrentDomain($channel_id,$source_url);
  622. $params['jmp_url'] = getCurrentDomain($channel_id,'/t/'.$insertId);
  623. //绑定域名短链ID及重置生成短链接的源地址,代理商使用渠道的短链域名池
  624. $short = model('ShortRelation')->getRandShort($channel_id);
  625. if($short){
  626. $params['short_id'] = $short->id;
  627. $short_source_url = replaceShortDomain($params['jmp_url'], $short->id);
  628. $params['jmp_url'] = $short_source_url;
  629. }else{
  630. $short_source_url = $params['source_url'];
  631. }
  632. $shoturl = new ShortUrl();
  633. //生成腾讯短链
  634. $params['short_url_qq'] = $shoturl->tencent($channel_id, $short_source_url);
  635. //生成sina短链
  636. $params['short_url_weibo'] = $shoturl->sina($short_source_url);
  637. $this->model->save($params, ['id' => $insertId]);
  638. //删除Redis缓存
  639. $redis = Redis::instance();
  640. $redis->del('RI:N:'.$insertId);
  641. } catch (Exception $e) {
  642. $this->error($e->getMessage());
  643. }
  644. $this->success('', null, $params);
  645. }
  646. $this->error(__('Parameter %s can not be empty', ''));
  647. }
  648. if (!$this->request->has('type') || $this->request->get('type') != 2) {
  649. if (!$this->request->has('book_id') || !$this->request->has('chapter_id')) {
  650. $this->error('参数错误!');
  651. }
  652. $book_id = $this->request->get('book_id');
  653. $chapter_id = $this->request->get('chapter_id');
  654. $book = model('Book')::get($book_id);
  655. $this->assign('book', $book);
  656. $data = model('Book')::getChapterInfo($book_id, $chapter_id);
  657. if ($data['code']) {
  658. $this->error($data['msg']);
  659. }
  660. $isLimited = model('BookLimit')->backendHasLimit($this->bookAgentId,$this->bookChannelId,$book_id);
  661. $this->assign('chapter', $data['data']);
  662. }
  663. $this->assign('limited',$isLimited);
  664. if($this->request->get('type') == 3)
  665. {
  666. //表单默认值
  667. $guide_title = model('ManageTitle')->getRandTitle(['1','2']);
  668. $guide_image = model('ManageCover')->getRandImage(['1','2']);
  669. $def = ['guide_title' => $guide_title, 'guide_image' => $guide_image];
  670. $this->assign('def', $def);
  671. }
  672. $channel_id = $this->auth->agent_id ?? $this->auth->channel_id;
  673. $adminConfig = model('AdminConfig')->getAdminInfoAll($channel_id);
  674. $this->assign('ref_out_push',intval($adminConfig['ref_out_push'] ?? 0));
  675. $this->assign('type',intval($this->request->get('type')));
  676. $this->assign('chapter_idx',intval($this->request->param('chapter_idx')) ?? 0);
  677. return $this->view->fetch();
  678. }
  679. /**
  680. * 书收费章节
  681. * @param $book_id
  682. * @return bool
  683. */
  684. private function bookPayChapterIdex($book_id){
  685. //获取书籍信息
  686. $book = model('Book')->BookInfo($book_id);
  687. //全局免费章节数
  688. $free_chapter_idx = config('site.book_free_chapter_num');
  689. //如果本书籍设置了免费章节数,以本书籍的免费章节数为准
  690. if(isset($book['free_chapter_num']) && intval($book['free_chapter_num'])>0){
  691. $free_chapter_idx = $book['free_chapter_num'];
  692. }
  693. return $free_chapter_idx;
  694. }
  695. /**
  696. * 书推广文案数量
  697. * @param $book_id
  698. * @return bool
  699. */
  700. private function bookReferralNumber($book_id){
  701. //获取书籍信息
  702. $book = model('Book')->BookInfo($book_id);
  703. return $book['referral_num'] ?? 10;
  704. }
  705. /**
  706. * 二维码模板
  707. * @param $url
  708. * @param $source_url
  709. * @param null $tpl_id
  710. * @return mixed
  711. * @throws Exception
  712. */
  713. public function show_tpl($url,$source_url = null,$tpl_id = null){
  714. if(!intval($tpl_id)){
  715. $current_url = DiyQRCode::createQRCodeByUrl($url,220);
  716. $source_url = $current_url;
  717. $qrcode_list = DiyQRCode::getTplPath($source_url);
  718. }else{
  719. $source_url = DiyQRCode::createQRCodeByUrl($url,220);
  720. $current_url = DiyQRCode::createTplQRCode($source_url,$tpl_id);
  721. $qrcode_list = DiyQRCode::getTplPath($source_url);
  722. }
  723. $this->assign('source_url',$source_url);
  724. $this->assign('current_url',$current_url);
  725. $this->assign('url',$url);
  726. $this->assign('tpl_id',intval($tpl_id));
  727. $this->assign('qrcode_list',$qrcode_list);
  728. return $this->view->fetch();
  729. }
  730. /**
  731. * 图文推广链接
  732. * @param null|int $book_id
  733. * @param null|int $chapter_idx
  734. * @param null|int $referral_id
  735. * @return string
  736. */
  737. public function essay($book_id = null, $chapter_idx = null, $referral_id = null)
  738. {
  739. if ($referral_id) {
  740. $row = $this->model->get($referral_id);
  741. $book_id = $row['book_id'];
  742. } else {
  743. $row = [
  744. 'book_id' => $book_id,
  745. 'chapter_idx' => intval($chapter_idx),
  746. ];
  747. }
  748. //书籍信息
  749. $book = model('book')::get($book_id);
  750. $isLimited = model('BookLimit')->backendHasLimit($this->bookAgentId,$this->bookChannelId,$book_id);
  751. $this->assign('limited',$isLimited);
  752. $this->assign('book', $book);
  753. $this->assign('row', $row);
  754. $this->view->engine->layout(false);
  755. return $this->view->fetch();
  756. }
  757. /**
  758. * 编辑
  759. */
  760. public function edit($ids = null)
  761. {
  762. $row = $this->model->get($ids);
  763. if (!$row) {
  764. $this->error(__('No Results were found'));
  765. }
  766. $editFrom = $this->request->get('from', '');
  767. $adminIds = $this->getDataLimitAdminIds();
  768. if (is_array($adminIds)) {
  769. if (!in_array($row[$this->dataLimitField], $adminIds)) {
  770. $this->error(__('You have no permission'));
  771. }
  772. }
  773. if ($this->request->isPost()) {
  774. $params = $this->request->post("row/a");
  775. $params['share_image'] = ResourceService::instance()->getRandomImage()->data;
  776. $params['share_title'] = ResourceService::instance()->getRandomTitle()->data;
  777. if ($params) {
  778. try
  779. {
  780. //是否采用模型验证
  781. if ($this->modelValidate) {
  782. $name = basename(str_replace('\\', '/', get_class($this->model)));
  783. $validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.edit' : true) : $this->modelValidate;
  784. $row->validate($validate);
  785. }
  786. //获取当前书籍的默认关注章节
  787. $default_chapter_idx = $params['guide_chapter_idx'] ?? 0;
  788. if(isset($params['guide_chapter_idx']) && empty($params['guide_chapter_idx']) && !empty($row['book_id'])){
  789. if($this->group == 4){
  790. $default_chapter_idx = model('Guide')->getGuideChapter($this->auth->id,$row['book_id'],0,$this->auth->channel_id);
  791. }else{
  792. if (in_array($this->group, [7, 8])) {
  793. //vip和vip运营者
  794. $default_chapter_idx = model('Guide')->getGuideChapter(0,$row['book_id'],0,0);
  795. } else {
  796. $default_chapter_idx = model('Guide')->getGuideChapter($this->auth->id,$row['book_id'],0,$this->auth->channel_id);
  797. }
  798. }
  799. }
  800. if ($row['type'] != 2) { // 修改推广链接
  801. $source_url = '/index/book/chapter?book_id=' . $row['book_id'] . '&sid=' . $params['chapter_id'] . '&referral_id=' . $row['id'];
  802. if ($this->group == 4) {
  803. $source_url .= '&agent_id=' . $this->auth->id;
  804. }
  805. $channel_id = $this->auth->agent_id ? $this->auth->agent_id : $this->auth->channel_id;
  806. $params['source_url'] = getCurrentDomain($channel_id,
  807. $source_url);
  808. }
  809. //导粉章节小于收费章节
  810. if(!empty($row['book_id'])){
  811. if($default_chapter_idx > $this->bookPayChapterIdex($row['book_id'])){
  812. $this->error('导粉章节数必须小于收费章节数');
  813. }
  814. }
  815. //落地页推广
  816. if($row['type'] == 3 && isset($params['guide_idx'])){
  817. if(!$params['guide_idx']){
  818. $this->error('落地页章节数必填');
  819. }
  820. if($params['guide_idx'] > $this->bookReferralNumber($row['book_id'])){
  821. $this->error('落地页章节数必须小于推广文案数量');
  822. }
  823. if($params['guide_idx'] > $default_chapter_idx){
  824. $this->error('落地页章节数必须小于导粉章节数');
  825. }
  826. }
  827. $result = $row->allowField(true)->save($params);
  828. if ($result !== false) {
  829. $redis = Redis::instance();
  830. $key = 'RI:N:' . $row['id'];
  831. $redis->del($key);
  832. //@todo vip 批量修改
  833. if ($params['edit_from'] == 'vipreferral') {
  834. $library = model("ReferralLibrary")->where('referral_id', 'eq', $ids)->find();
  835. $children = model("ReferralSlave")->where('library_id', 'eq', $library->id)->field('referral_id')->select();
  836. if (isset($params['cost'])) {
  837. unset($params['cost']);
  838. }
  839. if (!empty($children)) {
  840. $referralIds = array_map(function ($v) { return $v->referral_id;}, $children);
  841. model('referral')->allowField(true)->save($params, ['id' => ['in', $referralIds]]);
  842. foreach ($referralIds as $referralId) {
  843. $redis = Redis::instance();
  844. $key = 'RI:N:' . $referralId;
  845. $redis->del($key);
  846. }
  847. }
  848. }
  849. $this->success();
  850. } else {
  851. $this->error($row->getError());
  852. }
  853. } catch (\think\exception\PDOException $e) {
  854. $this->error($e->getMessage());
  855. }
  856. }
  857. $this->error(__('Parameter %s can not be empty', ''));
  858. }
  859. $this->view->assign("row", $row);
  860. $this->view->assign("edit_from", $editFrom);
  861. if ($row['type'] == 1 || $row['type'] == 3) {
  862. $book = model('Book')::get($row['book_id']);
  863. $this->assign('book', $book);
  864. }
  865. if (!empty($row['book_id'])) {
  866. $freeChapterIds = $this->bookPayChapterIdex($row['book_id']);
  867. if ($freeChapterIds > 0) {
  868. $chapters = model("Book")::getChapterList($row['book_id'], 1, $freeChapterIds);
  869. if ($chapters['code'] == 100){
  870. throw new HttpException(400, '异常错误,请重试');
  871. }
  872. }
  873. }
  874. $this->assign('chapters', $chapters['data']['data'] ?? []);
  875. return $this->view->fetch();
  876. }
  877. /**
  878. * 选择(多选)
  879. * @return string|\think\response\Json
  880. */
  881. public function select()
  882. {
  883. $base_url_params = [];
  884. $channel_url_path = null;
  885. // 是否开启微信分享开关
  886. $open_wechat_share = Config::get('site.open_wechat_share') ?? 0;
  887. //内推外派
  888. $push = $this->request->param('push') ?? 0;
  889. $base_url_params['push'] = $push;
  890. //被查看的渠道ID
  891. $lock_id = $_GET['ids'] ?? 0;
  892. //查看渠道
  893. if($lock_id){
  894. $base_url_params['ids'] = $_GET['ids'];
  895. $this->assign('type',1);
  896. $this->assignconfig('rtype',1);
  897. if ($this->group == 2) {
  898. $channel_url_path = $this->getChannelOphost($_GET['ids']);
  899. }
  900. }
  901. //渠道本身
  902. if(!$lock_id){
  903. $this->assign('type',0);
  904. $this->assignconfig('rtype',0);
  905. $channel_id = $this->auth->agent_id ? $this->auth->agent_id : $this->auth->channel_id;
  906. if($this->group == 4 || $this->group == 3){
  907. $channel_url_path = $this->getChannelOphost($channel_id);
  908. }
  909. if($this->auth->agent_id || $this->group == 3){
  910. if(!model('AdminConfig')->checkWechatConfig($this->auth->id)){
  911. $this->error('请先授权微信服务号给本系统,正在跳转授权设置页面~', url('admin/config'));
  912. }
  913. }
  914. }
  915. $this->assign('push', $push);
  916. $this->assignconfig('push',$push);
  917. $this->assignconfig('url_referral', $channel_url_path);
  918. $this->assignconfig('open_wechat_share', $open_wechat_share);
  919. $this->assignconfig('authGroupId', $this->group);
  920. $this->assignconfig('referralUrl',Url::build('admin/referral.referral/index',$base_url_params));
  921. $adminExtendInfo = model('AdminExtend')->getInfo($this->auth->id);
  922. $this->assignconfig('authDistribute', $adminExtendInfo['distribute']);
  923. if ($this->request->isAjax()) {
  924. if($this->request->has('push')){
  925. return $this->index_ajax($channel_url_path,$lock_id,$push);
  926. }else{
  927. return $this->index_ajax($channel_url_path,$lock_id,null);
  928. }
  929. }
  930. return $this->view->fetch();
  931. }
  932. /**
  933. * 删除
  934. */
  935. public function del($ids = "")
  936. {
  937. if ($ids)
  938. {
  939. $pk = $this->model->getPk();
  940. $adminIds = $this->getDataLimitAdminIds();
  941. if (is_array($adminIds))
  942. {
  943. $count = $this->model->where($this->dataLimitField, 'in', $adminIds);
  944. }
  945. $list = $this->model->where($pk, 'in', $ids)->select();
  946. $count = 0;
  947. $redis = Redis::instance();
  948. foreach ($list as $k => $v)
  949. {
  950. $id = $v->id;
  951. $count += $v->delete();
  952. // $redis->hdel('T:',$id); //清除redis缓存
  953. $redis->del('RI:N:' . $id); //清除redis缓存
  954. }
  955. if ($count)
  956. {
  957. $this->success();
  958. }
  959. else
  960. {
  961. $this->error(__('No rows were deleted'));
  962. }
  963. }
  964. $this->error(__('Parameter %s can not be empty', 'ids'));
  965. }
  966. /**
  967. * 生成图片章节
  968. */
  969. public function image()
  970. {
  971. $bookId = $this->request->get('book_id');
  972. $head = $this->request->get('head');
  973. if (!$bookId || !$head) {
  974. $this->error('缺少参数!');
  975. }
  976. $imgPath = ROOT_PATH . 'public/uploads/chapter/' . $bookId . '/'; //图片保存路径
  977. $imgIndexPath = ROOT_PATH . 'public/uploads/chapter_index/' . $bookId . '/'; //图片索引文件路径
  978. $cdnPath = Config::get('upload.cdnurl') . '/uploads/chapter/' . $bookId . '/'; //cdn路径
  979. if (!is_dir(ROOT_PATH . 'public/uploads/chapter_index/' . $bookId)) {
  980. mkdir(ROOT_PATH . 'public/uploads/chapter_index/' . $bookId, 0777, true);
  981. }
  982. if (!file_exists($imgPath)) { //创建文件夹
  983. mkdir($imgPath, 0700,true);
  984. clearstatcache();
  985. }
  986. $data = model('Book')::getHeadChapters($bookId, $head);
  987. if ($data['code']) {
  988. $this->error($data['msg']);
  989. }
  990. $font = [
  991. // 'path' => ROOT_PATH . 'public/assets/fonts/SourceHanSans-Light.otf', //思源黑体
  992. 'path' => ROOT_PATH . 'public/assets/fonts/PingFang-Regular.ttf', //苹方
  993. 'size' => 32
  994. ];
  995. $box = imageftbbox($font['size'], 0, $font['path'], '字'); //测算单个汉字宽高
  996. $font['width'] = max($box[2], $box[4]) - min($box[0], $box[6]);
  997. $font['height'] = max($box[3], $box[5]) - min($box[1], $box[7]);
  998. $lineSpacing = 24; //行间距
  999. $cosSpacing = 10; //列间距
  1000. $paragraphSpacing = 40; //段间距
  1001. $maxLen = 240; //最大文字,超过就新开一页
  1002. $maxPage = 634; //页面最大宽度
  1003. foreach ($data['data'] as &$chapter) {
  1004. $page = 1; //当前第几页
  1005. $strLen = 0; //当前汉字数
  1006. $pageLine = 0; //当前页面第几行
  1007. $paragraphNum = 0; //当前页面共几段
  1008. $arr = [];
  1009. foreach ($chapter['content'] as $key=>$line) {
  1010. if ($key == 0 || !$line) {
  1011. continue;
  1012. }
  1013. $lineLen = mb_strlen($line);
  1014. if (($strLen + $lineLen + 2) > $maxLen && $strLen > 0) { //换页
  1015. $strLen = $lineLen;
  1016. $page++;
  1017. $pageLine = 0;
  1018. $paragraphNum = 0;
  1019. } else {
  1020. $strLen = $strLen + $lineLen;
  1021. }
  1022. $pageLine++;
  1023. $lineWidth = ($font['width'] + $cosSpacing) * 2; //开头空2个汉字位置
  1024. for ($i = 0; $i < mb_strlen($line); $i++) {
  1025. $text = mb_substr($line, $i, 1, 'UTF-8');
  1026. $nextCN = true; //下一个字符 中文true 符号false
  1027. if((($lineWidth + $font['width'] * 2) > $maxPage) && $i < (mb_strlen($line) - 1)){ //具有下一个字符
  1028. $nextText = mb_substr($line, $i + 1, 1, 'UTF-8'); //下一个字符
  1029. if (!preg_match("/^[\x{4e00}-\x{9fa5}]+$/u", $nextText)) { //下一个字符不是是中文
  1030. $nextCN = false;
  1031. }
  1032. }
  1033. if (!$nextCN || (($lineWidth + $font['width']) > $maxPage)) { //下一个不是中文或者宽度超出换行
  1034. $lineWidth = 0;
  1035. $pageLine++;
  1036. }
  1037. $arr[$page]['page'][$pageLine][] = [
  1038. 'x' => $lineWidth,
  1039. 'y' => $cosSpacing + $pageLine * $font['height'] + ($pageLine-1) * $lineSpacing + $paragraphNum * $paragraphSpacing,
  1040. 'text' => $text
  1041. ];
  1042. $lineWidth = $lineWidth + $font['width'] + $cosSpacing;
  1043. }
  1044. $paragraphNum++;
  1045. $arr[$page]['paragraphNum'] = $paragraphNum;
  1046. }
  1047. $version = md5(implode('', $chapter['content']));
  1048. $index_file = $imgIndexPath . $chapter['id'] . '-' . $version . '.txt';
  1049. if (file_exists($index_file)) {
  1050. $chapter['content'] = json_decode(file_get_contents($index_file), true);
  1051. } else {
  1052. $imgArr = [];
  1053. foreach ($arr as $key => $page) {
  1054. $lineNum = count($page['page']);
  1055. $height = $lineNum * $font['height'] + ($lineNum - 1) * $lineSpacing + $page['paragraphNum'] * $paragraphSpacing + $cosSpacing * 2;
  1056. $image = imagecreatetruecolor($maxPage, $height);
  1057. $black = imagecolorallocate($image, 0, 0, 0);
  1058. $white = imagecolorallocate($image, 255, 255, 255);
  1059. imagefilledrectangle($image, 0, 0, $maxPage, $height, $white);
  1060. foreach ($page['page'] as $line) {
  1061. foreach ($line as $str) {
  1062. imagefttext($image, $font['size'], 0, $str['x'], $str['y'], $black, $font['path'],
  1063. $str['text']);
  1064. }
  1065. }
  1066. $file_name = $chapter['id'] . '-' . $key . substr($version, 0, 5) . '.jpg';
  1067. imagejpeg($image, $imgPath . $file_name);
  1068. imagedestroy($image);
  1069. $img_info = getimagesize($imgPath . $file_name);
  1070. $imgArr[] = ['imgurl' => $cdnPath.$file_name, 'width' => $img_info[0] ?? 0, 'height' => $img_info[1] ?? 0];
  1071. }
  1072. if ($imgArr) {
  1073. file_put_contents($index_file, json_encode($imgArr));
  1074. $chapter['content'] = $imgArr;
  1075. }
  1076. }
  1077. // break;
  1078. }
  1079. exit(json_encode($data['data']));
  1080. // $this->success('图片生成成功!', null, $imgArr);
  1081. }
  1082. public function essayimage($book_id = null, $chapter_idx = null, $referral_id = null)
  1083. {
  1084. if ($referral_id) {
  1085. $row = $this->model->get($referral_id);
  1086. $book_id = $row['book_id'];
  1087. } else {
  1088. $row = [
  1089. 'book_id' => $book_id,
  1090. 'chapter_idx' => $chapter_idx,
  1091. ];
  1092. }
  1093. //书籍信息
  1094. $isLimited = model('BookLimit')->backendHasLimit($this->bookAgentId,$this->bookChannelId,$book_id);
  1095. $this->assign('limited',$isLimited);
  1096. $book = model('book')->BookInfo($book_id);
  1097. $this->assign('book', $book);
  1098. $this->assign('row', $row);
  1099. $this->view->engine->layout(false);
  1100. return $this->view->fetch();
  1101. }
  1102. /**
  1103. * 背景图模式
  1104. * @param null $book_id
  1105. * @param null $chapter_idx
  1106. * @param null $referral_id
  1107. * @return string
  1108. * @throws Exception
  1109. */
  1110. public function background($book_id = null, $chapter_idx = null, $referral_id = null){
  1111. if ($referral_id) {
  1112. $row = $this->model->get($referral_id);
  1113. $book_id = $row['book_id'];
  1114. } else {
  1115. $row = [
  1116. 'book_id' => $book_id,
  1117. 'chapter_idx' => $chapter_idx,
  1118. ];
  1119. }
  1120. //书籍信息
  1121. $book = model('book')->BookInfo($book_id);
  1122. $this->assign('book', $book);
  1123. $this->assign('row', $row);
  1124. $this->view->engine->layout(false);
  1125. return $this->view->fetch();
  1126. }
  1127. /**
  1128. * 生成推广文案底部二维码
  1129. *
  1130. * @param int $referral_id 推广链接id
  1131. * @param int $idx 推广图片序号
  1132. */
  1133. public function qrcode()
  1134. {
  1135. $referral_id = $this->request->get('referral_id');
  1136. if (!$referral_id) {
  1137. $this->error('参数错误!');
  1138. }
  1139. $idx = $this->request->get('idx', 1);
  1140. /**
  1141. * 图片序号的生成格式
  1142. */
  1143. $imgSize = [
  1144. 1 => [
  1145. 'size' => 164, //二维码宽度
  1146. 'x' => 376, //水印x
  1147. 'y' => 35 //水印y
  1148. ],
  1149. 2 => [
  1150. 'size' => 168, //二维码宽度
  1151. 'x' => 374, //水印x
  1152. 'y' => 33 //水印y
  1153. ],
  1154. 3 => [
  1155. 'size' => 156, //二维码宽度
  1156. 'x' => 372, //水印x
  1157. 'y' => 46 //水印y
  1158. ],
  1159. 4 => [
  1160. 'size' => 200, //二维码宽度
  1161. 'x' => 356, //水印x
  1162. 'y' => 15 //水印y
  1163. ],
  1164. 5 => [
  1165. 'size' => 200, //二维码宽度
  1166. 'x' => 356, //水印x
  1167. 'y' => 15 //水印y
  1168. ],
  1169. 6 => [
  1170. 'size' => 200, //二维码宽度
  1171. 'x' => 356, //水印x
  1172. 'y' => 15 //水印y
  1173. ]
  1174. ];
  1175. /**
  1176. * 跳转短链生成格式
  1177. */
  1178. $channel_id = $this->auth->agent_id ? $this->auth->agent_id : $this->auth->channel_id;
  1179. $jmp_url = getCurrentDomain($channel_id,'/t/' . $referral_id);
  1180. /**
  1181. * 生成二维码
  1182. */
  1183. $qrCode = new QrCode($jmp_url);
  1184. $qrCode->setSize($imgSize[$idx]['size']); //二维码尺寸
  1185. $qrCode->setWriterByName('png');
  1186. $qrCode->setEncoding('UTF-8');
  1187. $qrCode->setMargin(10);
  1188. $tmpPath = sys_get_temp_dir();
  1189. if (substr($tmpPath, -1, 1) == '/') {
  1190. $tmpPath = $tmpPath . uniqid() . '.png';
  1191. } else {
  1192. $tmpPath = $tmpPath . '/' . uniqid() . '.png';
  1193. }
  1194. $qrCode->writeFile($tmpPath);
  1195. /**
  1196. * 二维码合并
  1197. */
  1198. $image_1 = imagecreatefrompng(ROOT_PATH . "public/assets/img/essay/qrcode_{$idx}.png"); //底图
  1199. $image_2 = imagecreatefrompng($tmpPath); //二维码图片
  1200. $images_qrcode = imagecreatetruecolor($imgSize[$idx]['size'], $imgSize[$idx]['size']); //建立一个图片
  1201. $images_qrcode_info = getimagesize($tmpPath);
  1202. imagecopyresampled($images_qrcode, $image_2, 0, 0, 0, 0, $imgSize[$idx]['size'],$imgSize[$idx]['size'], $images_qrcode_info[0],$images_qrcode_info[1]);
  1203. imagecopymerge($image_1, $images_qrcode, $imgSize[$idx]['x'], $imgSize[$idx]['y'], 0, 0, $imgSize[$idx]['size'],
  1204. $imgSize[$idx]['size'], 100);
  1205. $imgPath = ROOT_PATH . 'public/uploads/qrcode/'; //图片保存路径
  1206. if (!file_exists($imgPath)) { //创建文件夹
  1207. mkdir($imgPath, 0700, true);
  1208. clearstatcache();
  1209. }
  1210. $imgPath = $imgPath . $referral_id . '_' . $idx . '.png';
  1211. $imgUrl = cdnurl("/uploads/qrcode/" . $referral_id . '_' . $idx . '.png');
  1212. $res = imagepng($image_1, $imgPath);
  1213. unlink($tmpPath);
  1214. imagedestroy($image_1);
  1215. imagedestroy($image_2);
  1216. if ($res) {
  1217. $data = [
  1218. 'url' => $imgUrl
  1219. ];
  1220. $this->success('', null, $data);
  1221. }
  1222. $this->error('二维码生成失败!', null);
  1223. }
  1224. /**
  1225. * 禁用或解禁 根据当前状态进行切换
  1226. * @param null $ids
  1227. */
  1228. public function disable($ids = null){
  1229. if ($ids)
  1230. {
  1231. $isVip = $this->request->param('isVip') ?? 0;
  1232. $pk = $this->model->getPk();
  1233. $adminIds = $this->getDataLimitAdminIds();
  1234. if (is_array($adminIds))
  1235. {
  1236. $count = $this->model->where($this->dataLimitField, 'in', $adminIds);
  1237. }
  1238. $list = $this->model->where($pk, 'in', $ids)->select();
  1239. $count = 0;
  1240. $redis = Redis::instance();
  1241. foreach ($list as $k => $v)
  1242. {
  1243. $state = '0';
  1244. if($v['state'] == '0') {
  1245. $state = '1';
  1246. }
  1247. $count += $v->where('id', $v['id'])->update(['state'=> $state]);
  1248. $redis->del('RI:N:'.$v['id']);
  1249. if ($isVip) {
  1250. //VIP分流链接
  1251. $library = model("ReferralLibrary")->where('referral_id', 'eq', $v['id'])->find();
  1252. $vipKey = 'RIV:'.$library['id'];
  1253. $redis->del($vipKey);
  1254. }
  1255. }
  1256. if ($count)
  1257. {
  1258. $this->success();
  1259. }
  1260. else
  1261. {
  1262. $this->error(__('No rows were updated'));
  1263. }
  1264. }
  1265. $this->error(__('Parameter %s can not be empty', 'ids'));
  1266. }
  1267. /**
  1268. * @param $id
  1269. */
  1270. public function merge_image($id)
  1271. {
  1272. if ($this->request->isPost()) {
  1273. $channel_id = $this->auth->agent_id ? $this->auth->agent_id : $this->auth->channel_id;
  1274. $mergeImage = ImageService::instance()->getReferralImage($id, $channel_id);
  1275. if ($mergeImage->code != ErrorCodeConstants::SUCCESS) {
  1276. $this->error($mergeImage->msg);
  1277. } else {
  1278. $this->success("", null, ["path" => $mergeImage->data]);
  1279. }
  1280. }
  1281. }
  1282. /**
  1283. * 获取分享的信息
  1284. * @param $id
  1285. * @param string $type
  1286. * @return \think\response\Json
  1287. */
  1288. public function ajaxGetShare($id, $type='s_chat')
  1289. {
  1290. $data = $this->model->where('id', '=', $id)->find() ->toarray();
  1291. $channel_id = $this->auth->agent_id ? $this->auth->agent_id : $this->auth->channel_id;
  1292. $shareLink = $data['short_url_qq'] ? $data['short_url_qq'] : getCurrentDomain($channel_id,$data['source_url']);
  1293. //$shareLink = ReferralService::instance()->get189Url($id, $shareLink)->data;
  1294. $shareLink = ReferralService::instance()->get189Urlv3($id, $shareLink)->data;
  1295. if($data['share_image']){
  1296. $shareIcon = $data['share_image'];
  1297. }else{
  1298. $shareIcon = ResourceService::instance()->getRandomCover()->data;
  1299. }
  1300. if($data['share_title']){
  1301. $shareTitle = $data['share_title'];
  1302. }else{
  1303. $shareTitle = ResourceService::instance()->getRandomTitle()->data;
  1304. }
  1305. $shareDesc = ResourceService::instance()->getRandomDesc()->data;
  1306. if(!$shareDesc){
  1307. $shareDesc = $shareTitle;
  1308. }
  1309. $this->assign('type', $type);
  1310. $this->assign('data', $data);
  1311. $this->assign('shareLink', $shareLink);
  1312. $this->assign('shareIcon', $shareIcon);
  1313. $this->assign('shareTitle', $shareTitle);
  1314. $this->assign('shareDesc', $shareDesc);
  1315. if($type == 's_friends'){
  1316. $shareType = 8;
  1317. }else{
  1318. $shareType = 1;
  1319. }
  1320. $result = [
  1321. 'shareLink' => $shareLink,
  1322. 'shareIcon' => $shareIcon,
  1323. 'shareTitle' => $shareTitle,
  1324. 'shareType' => $shareType,
  1325. 'shareDesc' => $shareDesc
  1326. ];
  1327. return json($result);
  1328. }
  1329. public function ajaxGetRandomTitle()
  1330. {
  1331. $shareTitle = ResourceService::instance()->getRandomTitle()->data;
  1332. return json([
  1333. 'data' => $shareTitle
  1334. ]);
  1335. }
  1336. }