+ * @date 2023/04/18 09:38:01
+ */
+
+import { css, html, Component, bind, styleMap } from '@bd/core'
+import '../form/button.js'
+
+const LAYOUT_DICT = {
+ home: e =>
+ html``,
+ end: e =>
+ html``,
+ prev: e =>
+ html``,
+ next: e =>
+ html``,
+ curr: n => html`${n}`,
+ info: (t, p) => html`共 ${t}条, ${p}页`,
+ jump(n) {
+ return html``
+ }
+}
+
+// 计算页码
+function calculate(curr, total) {
+ var arr = []
+ var fixed = 0
+ var half = curr < 3 ? 6 - curr : 2 // 中间页码
+
+ // 总页码小于2
+ if (total < 2) {
+ arr.push({ to: curr, txt: curr })
+ return arr
+ }
+
+ // 当前页面比半数多时, 前面的用省略号代替
+ if (curr - half > 1 && total > 5) {
+ var to = curr - 2 * half
+ to = to < 1 ? 1 : to
+ arr.push({ to, txt: '...' })
+ }
+
+ if (total - curr < half) {
+ fixed = half - total + curr
+ }
+
+ // 把页码拆成2部分来
+ for (var i = curr - half - fixed; i < curr + half + 1 && i <= total; i++) {
+ if (i > 0) {
+ arr.push({ to: i, txt: i })
+ }
+ }
+
+ // 总页码太多时, 以省略号代替
+ if (curr + half < total) {
+ var to = curr + 2 * half
+ to = to > total ? total : to
+ arr.push({ to, txt: '...' })
+ }
+
+ return arr
+}
+
+class Pager extends Component {
+ static props = {
+ layout: {
+ type: String,
+ default: 'home, prev, pages, next, end',
+ attribute: false
+ },
+ total: {
+ type: Number,
+ default: 0,
+ attribute: false,
+ observer(v) {
+ if (this.#mounted) {
+ this.totalpage = Math.ceil(v / this.pagesize)
+ }
+ }
+ },
+ totalpage: {
+ type: Number,
+ default: 1,
+ attribute: false,
+ observer(v) {
+ if (this.page > v) {
+ this.page = v
+ }
+ }
+ },
+ page: {
+ type: Number,
+ default: 1,
+ attribute: false,
+ observer(v) {
+ if (v > this.totalpage) {
+ this.page = this.totalpage
+ } else if (v < 1) {
+ this.page = 1
+ }
+ }
+ },
+ pagesize: {
+ type: Number,
+ default: 20,
+ attribute: false,
+ observer(v) {
+ if (this.total > 0) {
+ this.totalpage = Math.ceil(this.total / v)
+ }
+ }
+ }
+ }
+
+ static styles = [
+ css`
+ :host {
+ display: block;
+ line-height: 1;
+ font-size: 14px;
+ user-select: none;
+ -moz-user-select: none;
+ color: var(--color-dark-1);
+
+ .layout {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ margin: 10px auto;
+ }
+
+ .item {
+ min-width: 32px;
+ width: auto;
+ --padding: 0;
+ margin: 0 5px;
+ --icon-size: 12px;
+ border-radius: 4px;
+
+ &.curr {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ height: 32px;
+ background: var(--color-teal-1);
+ color: #fff;
+ }
+
+ &.jump {
+ display: flex;
+ align-items: center;
+ }
+
+ &[size='l'] {
+ --icon-size: 12px;
+ }
+ }
+
+ input {
+ width: 48px;
+ height: 24px;
+ padding: 0 4px;
+ margin-left: 4px;
+ border: 1px solid var(--color-grey-2);
+ border-radius: 3px;
+ text-align: center;
+ outline: none;
+ transition: box-shadow 0.15s linear;
+
+ &:focus {
+ box-shadow: 0 0 0 2px var(--color-plain-a);
+ }
+ }
+ }
+ `,
+
+ css``
+ ]
+
+ #mounted = false
+
+ handleBtnClick(ev) {
+ let elem = ev.target
+ if (elem.tagName === 'WC-BUTTON') {
+ let { page, totalpage } = this
+ let num = elem.dataset.act
+
+ if (elem.disabled) {
+ return
+ }
+
+ switch (num) {
+ case 'prev':
+ num = page - 1
+ break
+
+ case 'next':
+ console.log(num, page)
+ num = page + 1
+ break
+
+ case 'end':
+ num = totalpage
+ break
+ }
+
+ if (+num === page) {
+ return
+ }
+
+ this.page = num
+
+ this.$emit('page-changed', { data: num })
+ }
+ }
+
+ gotoPage(ev) {
+ if (ev.keyCode === 13) {
+ let n = +ev.target.value
+ if (n === n) {
+ this.page = n
+ this.$emit('page-changed', { data: this.page })
+ }
+ ev.target.value = this.page
+ }
+ }
+
+ mounted() {
+ this.#mounted = true
+ }
+
+ render() {
+ let layout = this.layout.split(',').map(s => s.trim())
+ let { page, total, totalpage } = this
+
+ return html`
+
+ ${layout.map(n => {
+ switch (n) {
+ case 'pages':
+ return calculate(page, totalpage).map(it =>
+ page === it.to
+ ? LAYOUT_DICT.curr(page)
+ : html`${it.txt}`
+ )
+
+ case 'home':
+ return LAYOUT_DICT.home(page === 1)
+
+ case 'prev':
+ return LAYOUT_DICT.prev(page === 1)
+
+ case 'next':
+ return LAYOUT_DICT.next(page >= totalpage)
+
+ case 'end':
+ return LAYOUT_DICT.end(page >= totalpage)
+
+ case 'curr':
+ return LAYOUT_DICT.curr(page)
+
+ case 'info':
+ return LAYOUT_DICT.info(total, totalpage)
+
+ case 'jump':
+ return LAYOUT_DICT.jump.call(this, page)
+
+ default:
+ return ''
+ }
+ })}
+
+ `
+ }
+}
+
+Pager.reg('pager')