心理咨询网
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398
  1. <?php
  2. /**
  3. * @copyright (C)2016-2099 Hnaoyun Inc.
  4. * @author XingMeng
  5. * @email hnxsh@foxmail.com
  6. * @date 2016年11月6日
  7. * 分页控制类
  8. */
  9. namespace core\view;
  10. use core\basic\Config;
  11. class Paging
  12. {
  13. // 每页数量
  14. public $pageSize;
  15. // 当前页码
  16. public $page;
  17. // 数字条数量
  18. public $num = 5;
  19. // 调整数量
  20. public $start = 1;
  21. // 总记录
  22. private $rowTotal = 0;
  23. // 页面数量
  24. private $pageCount;
  25. // 存储前置URL
  26. private $preUrl;
  27. // 分页实例
  28. private static $paging;
  29. private function __construct()
  30. {
  31. // 禁用类new实例化
  32. }
  33. // 获取单一实例
  34. public static function getInstance()
  35. {
  36. if (! self::$paging) {
  37. self::$paging = new self();
  38. }
  39. return self::$paging;
  40. }
  41. // 限制语句
  42. public function limit($total = null, $morePageStr = false)
  43. {
  44. // 起始数据调整
  45. if (! is_numeric($this->start) || $this->start < 1) {
  46. $this->start = 1;
  47. }
  48. if ($this->start > $total) {
  49. $this->start = $total + 1;
  50. }
  51. // 设置总数
  52. if ($total) {
  53. $this->rowTotal = $total - ($this->start - 1);
  54. }
  55. // 设置分页大小
  56. if (! isset($this->pageSize)) {
  57. $this->pageSize = get('pagesize') ?: Config::get('pagesize') ?: 15;
  58. }
  59. // 分页数字条数量
  60. $this->num = Config::get('pagenum') ?: 5;
  61. // 计算页数
  62. $this->pageCount = @ceil($this->rowTotal / $this->pageSize);
  63. // 获取当前页面
  64. $this->page = $this->page();
  65. // 定义相关常量,用于方便模板引擎解析序号等计算和调用
  66. define('ROWTOTAL', $this->rowTotal);
  67. define('PAGECOUNT', $this->pageCount);
  68. define('PAGE', $this->page);
  69. define('PAGESIZE', $this->pageSize);
  70. // 注入分页模板变量
  71. $this->assign($morePageStr);
  72. // 返回限制语句
  73. return ($this->page - 1) * $this->pageSize + ($this->start - 1) . ",$this->pageSize";
  74. }
  75. // 快速分页字符代码
  76. public function quikLimit()
  77. {
  78. $page = get('page', 'int') ?: 1;
  79. if ($page < 1) {
  80. $page = 0;
  81. }
  82. $pagesize = config::get('pagesize') ?: 15;
  83. return ($page - 1) * $pagesize . ",$pagesize";
  84. }
  85. // 注入页面相关信息,用于模板调用,如:{$pagebar}调用分页条
  86. private function assign($morePageStr = false)
  87. {
  88. assign('pagebar', $this->pageBar());
  89. if ($morePageStr) {
  90. assign('pagecurrent', $this->page()); // 注入当前页
  91. assign('pagecount', $this->pageCount); // 注入总页数
  92. assign('pagerows', $this->rowTotal); // 注入总数据
  93. assign('pageindex', $this->pageIndex()); // 注入首页链接
  94. assign('pagepre', $this->pagePre()); // 注入前一页链接
  95. assign('pagenext', $this->pageNext()); // 注入后一页链接
  96. assign('pagelast', $this->pageLast()); // 注入最后一页链接
  97. assign('pagestatus', $this->pageStatus()); // 注入分页状态
  98. assign('pagenumbar', $this->pageNumBar()); // 注入数字
  99. assign('pageselectbar', $this->pageSelectBar()); // 注入选择栏
  100. }
  101. }
  102. // 当前页码容错处理
  103. private function page()
  104. {
  105. $page = get('page', 'int') ?: $this->page;
  106. if (is_numeric($page) && $page > 1) {
  107. if ($page > $this->pageCount && $this->pageCount) {
  108. return $this->pageCount;
  109. } else {
  110. return $page;
  111. }
  112. } else {
  113. return 1;
  114. }
  115. }
  116. // 过滤pathinfo中分页参数
  117. private function getPreUrl()
  118. {
  119. if (! isset($this->preUrl) && URL) {
  120. $url = parse_url(URL);
  121. $path = preg_replace('/\/page\/[0-9]+/i', '', $url['path']);
  122. if (defined('CMS_PAGE') && CMS_PAGE == true) { // 使用CMS分页时去除扩展
  123. $url_rule_suffix = Config::get('url_rule_suffix');
  124. if (! ! $pos = strripos($path, $url_rule_suffix)) {
  125. $path = substr($path, 0, $pos);
  126. }
  127. }
  128. $this->preUrl = $path;
  129. }
  130. return $this->preUrl;
  131. }
  132. // 构建链接地址
  133. private function buildPath($page)
  134. {
  135. if ($page) {
  136. if (defined('CMS_PAGE') && CMS_PAGE == true) {
  137. $url_rule_type = Config::get('url_rule_type') ?: 3;
  138. $url_rule_suffix = Config::get('url_rule_suffix') ?: '.html';
  139. $url_break_char = Config::get('url_break_char') ?: '_';
  140. $url_rule_sort_suffix = '/';
  141. if ($url_rule_type == 1 || $url_rule_type == 2) {
  142. if (defined('CMS_PAGE_CUSTOM')) { // 去分页参数
  143. $prepath = preg_replace('/(.*)' . $url_break_char . '[0-9]+$/', '$1', rtrim($this->getPreUrl(), '/'));
  144. } else {
  145. $prepath = preg_replace('/(.*)(' . $url_break_char . '[0-9]+)' . $url_break_char . '[0-9]+$/', '$1$2', rtrim($this->getPreUrl(), '/'));
  146. }
  147. if ($prepath) { // 非首页分页
  148. if ($page == 1) { // 第一页处理
  149. $path = $prepath . $url_rule_sort_suffix . query_string('p,s');
  150. } else {
  151. $path = $prepath . $url_break_char . $page . $url_rule_sort_suffix . query_string('p,s');
  152. }
  153. } else { // 首页分页
  154. $path = ($page == 1) ? SITE_INDEX_DIR . '/' : '?page=' . $page;
  155. }
  156. } else {
  157. if ($url_rule_type == 3 && isset($_SERVER["QUERY_STRING"]) && $qs = $_SERVER["QUERY_STRING"]) {
  158. parse_str($qs, $output);
  159. unset($output['page']);
  160. if ($output && ! current($output)) {
  161. $path_qs = key($output); // 第一个参数为路径信息,注意PHP数组会自动将点转换下划线
  162. unset($output[$path_qs]); // 去除路径参数
  163. // 去后缀扩展
  164. $temp_suffix = substr($url_rule_suffix, 1);
  165. if (! ! $pos = strripos($path_qs, '_' . $temp_suffix)) {
  166. $path = substr($path_qs, 0, $pos); // 去扩展
  167. } else {
  168. $path = $path_qs;
  169. }
  170. // 去除原分页参数
  171. if (defined('CMS_PAGE_CUSTOM')) {
  172. $path = preg_replace('/(.*)' . $url_break_char . '[0-9]+$/', "$1", rtrim($path, '/'));
  173. } else {
  174. $path = preg_replace('/(.*)(' . $url_break_char . '[0-9]+)' . $url_break_char . '[0-9]+$/', "$1$2", rtrim($path, '/'));
  175. }
  176. // 第一页链接处理
  177. if ($page == 1) {
  178. $path = SITE_INDEX_DIR . '/?' . $path . $url_rule_sort_suffix;
  179. } else {
  180. $path = SITE_INDEX_DIR . '/?' . $path . $url_break_char . $page . $url_rule_sort_suffix;
  181. }
  182. // 附加参数
  183. if (! ! $qs = http_build_query($output)) {
  184. $path = rtrim($path, '/') . '&' . $qs;
  185. }
  186. }
  187. }
  188. if (! $path) { // 转基本分页模式
  189. return $this->buildBasicPage($page);
  190. }
  191. }
  192. return $path;
  193. } else {
  194. return $this->buildBasicPage($page);
  195. }
  196. } else {
  197. return 'javascript:;';
  198. }
  199. }
  200. // 构建基本分页
  201. private function buildBasicPage($page)
  202. {
  203. // 对于路径保留变量给予去除
  204. $qs = $_SERVER["QUERY_STRING"];
  205. if ((M == 'home' && Config::get('url_rule_type') == 2) || (M != 'home' && Config::get('app_url_type') == 2)) {
  206. $qs = preg_replace('/[&\?]?p=([\w\/\.]+)?&?/i', '', $qs);
  207. $qs = preg_replace('/[&\?]?s=([\w\/\.]+)?&?/i', '', $qs);
  208. }
  209. $qs = preg_replace('/[&\?]?page=([0-9]+)?/i', '', $qs);
  210. if (C == 'Tag') {
  211. $qs = false;
  212. }
  213. if ($page == 1) {
  214. if ($qs) {
  215. return $this->getPreUrl() . '?' . $qs;
  216. } else {
  217. return $this->getPreUrl();
  218. }
  219. } else {
  220. if ($qs) {
  221. return $this->getPreUrl() . '?' . $qs . '&page=' . $page;
  222. } else {
  223. return $this->getPreUrl() . '?page=' . $page;
  224. }
  225. }
  226. }
  227. // 分页条
  228. private function pageBar()
  229. {
  230. if (! $this->pageCount)
  231. return "<span class='page-none' style='color:#999'>未查询到任何数据!</span>";
  232. $string = "<span class='page-status'>{$this->pageStatus()}</span>";
  233. $string .= "<span class='page-index'><a href='" . $this->pageIndex() . "'>首页</a></span>";
  234. $string .= "<span class='page-pre'><a href='" . $this->pagePre() . "'>前一页</a></span>";
  235. $string .= "<span class='page-numbar'>{$this->pageNumBar()}</span>";
  236. $string .= "<span class='page-next'><a href='" . $this->pageNext() . "'>后一页</a></span>";
  237. $string .= "<span class='page-last'><a href='" . $this->pageLast() . "'>尾页</a></span>";
  238. // $string .= "<span class='page-select'>{$this->pageSelectBar()}</span>";
  239. return $string;
  240. }
  241. // 当前页面情况
  242. private function pageStatus()
  243. {
  244. if (! $this->pageCount)
  245. return;
  246. return "共" . $this->rowTotal . "条 当前" . $this->page . "/" . $this->pageCount . "页";
  247. }
  248. // 首页链接
  249. private function pageIndex()
  250. {
  251. if (! $this->pageCount)
  252. return $this->buildPath('');
  253. return $this->buildPath(1);
  254. }
  255. // 上一页链接
  256. private function pagePre()
  257. {
  258. if (! $this->pageCount)
  259. return $this->buildPath('');
  260. if ($this->page > 1) {
  261. $pre_page = $this->buildPath($this->page - 1);
  262. } else {
  263. $pre_page = $this->buildPath('');
  264. }
  265. return $pre_page;
  266. }
  267. // 下一页链接
  268. private function pageNext()
  269. {
  270. if (! $this->pageCount)
  271. return $this->buildPath('');
  272. if ($this->page < $this->pageCount) {
  273. $next_page = $this->buildPath($this->page + 1);
  274. } else {
  275. $next_page = $this->buildPath('');
  276. }
  277. return $next_page;
  278. }
  279. // 尾页
  280. private function pageLast()
  281. {
  282. if (! $this->pageCount)
  283. return $this->buildPath('');
  284. return $this->buildPath($this->pageCount);
  285. }
  286. // 数字分页,要修改数字显示的条数,请修改类头部num属性值
  287. private function pageNumBar()
  288. {
  289. if (! $this->pageCount)
  290. return;
  291. if (M == 'admin') {
  292. $total = 5;
  293. } else {
  294. $total = $this->num;
  295. }
  296. $halfl = intval($total / 2);
  297. $halfu = ceil($total / 2);
  298. $num_html = '';
  299. if ($this->page > $halfu) {
  300. $num_html .= '<span class="page-num">···</span>';
  301. }
  302. if ($this->page <= $halfl || $this->pageCount < $total) { // 当前页小于一半或页数小于总数
  303. for ($i = 1; $i <= $total; $i ++) {
  304. if ($i > $this->pageCount)
  305. break;
  306. if ($this->page == $i) {
  307. $num_html .= '<a href="' . $this->buildPath($i) . '" class="page-num page-num-current">' . $i . '</a>';
  308. } else {
  309. $num_html .= '<a href="' . $this->buildPath($i) . '" class="page-num">' . $i . '</a>';
  310. }
  311. }
  312. } elseif ($this->page + $halfl >= $this->pageCount) { // 当前页为倒数页以内
  313. for ($i = $this->pageCount - $total + 1; $i <= $this->pageCount; $i ++) {
  314. if ($this->page == $i) {
  315. $num_html .= '<a href="' . $this->buildPath($i) . '" class="page-num page-num-current">' . $i . '</a>';
  316. } else {
  317. $num_html .= '<a href="' . $this->buildPath($i) . '" class="page-num">' . $i . '</a>';
  318. }
  319. }
  320. } else { // 正常的前后各5页
  321. for ($i = $this->page - $halfl; $i <= $this->page + $halfl; $i ++) {
  322. if ($this->page == $i) {
  323. $num_html .= '<a href="' . $this->buildPath($i) . '" class="page-num page-num-current">' . $i . '</a>';
  324. } else {
  325. $num_html .= '<a href="' . $this->buildPath($i) . '" class="page-num">' . $i . '</a>';
  326. }
  327. }
  328. }
  329. if ($this->pageCount > $total && $this->page < $this->pageCount - $halfl) {
  330. $num_html .= '<span class="page-num">···</span>';
  331. }
  332. return $num_html;
  333. }
  334. // 跳转分页
  335. private function pageSelectBar()
  336. {
  337. if (! $this->pageCount)
  338. return;
  339. $select_html = '<select onchange="changepage(this)" lay-ignore>';
  340. for ($i = 1; $i <= $this->pageCount; $i ++) {
  341. if ($i == $this->page) {
  342. $select_html .= '<option value="' . $i . '" selected="selected">跳到' . $i . '页</option>';
  343. } else {
  344. $select_html .= '<option value="' . $i . '">跳到' . $i . '页</option>';
  345. }
  346. }
  347. $select_html .= '</select><script>function changepage(tag){window.location.href="' . $this->buildPath('"+tag.value+"') . '";}</script>';
  348. return $select_html;
  349. }
  350. }