diff --git a/src/css/app.css b/src/css/app.css index d133a7d..bfd5f8d 100644 --- a/src/css/app.css +++ b/src/css/app.css @@ -1 +1 @@ -html{font-size:12.8px;width:100%;height:100vh}body{display:flex;flex-direction:column;width:100%;height:100%;padding-top:.9375rem;line-height:1.25;font-size:1.09375rem;color:#f2f5fc;background:transparent}.app{position:relative;display:flex;flex-direction:column;height:100%;padding:1.25rem 0 .46875rem;border-radius:.46875rem}.app::before{position:absolute;left:12.10938rem;top:-5.46875rem;width:1.09375rem;height:1.09375rem;border-radius:.15625rem;background:linear-gradient(to bottom right, rgba(88,88,88,0.85) 50%, transparent 50%);-webkit-transform:rotate(45deg);transform:rotate(45deg);content:''}.app .option,.app .close,.app .load{position:absolute;right:.46875rem;top:.15625rem;--size: 1.09375rem;cursor:pointer;opacity:0}.app .option:hover,.app .close:hover,.app .load:hover{opacity:1}.app .close{right:auto;left:.46875rem}.app .load{right:auto;left:12.10938rem}.app .list{flex:1}.app .list .item{display:flex;align-items:center;height:4.21875rem;padding:.78125rem .9375rem;line-height:1.17188rem;border-bottom:.07812rem solid rgba(200,200,200,0.1);border-top:.07812rem solid rgba(0,0,0,0.1)}.app .list .item:first-child{border-top:0}.app .list .item:last-child{border-bottom:0}.app .list .item .info{overflow:hidden;flex:1}.app .list .item .info h3{font-size:1.09375rem}.app .list .item .info cite{color:#dae1e9}.app .list .item .last-days{display:flex;width:5rem;height:2.34375rem;margin:0 .46875rem}.app .list .item .today{width:4.0625rem;font-size:.9375rem;color:#fff;text-align:right}.app .list .item .today span{display:block;padding:0 .3125rem}.app .list .item .today .percent{border-radius:.15625rem}.app .list .item .today .percent.red{background:#ff5061}.app .list .item .today .percent.green{background:#4caf50} +html{font-size:12.8px;width:100%;height:100vh}body{overflow:hidden;display:flex;flex-direction:column;width:100%;height:100%;line-height:1.25;font-size:14px;color:var(--color-dark-1);background:rgba(255,255,255,0.3)}.app-drag{-webkit-app-region:drag;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.app-nodrag{-webkit-app-region:no-drag}.app{position:relative;display:flex;height:100%}.app .sidebar{display:flex;flex-direction:column;justify-content:space-between;width:76px;height:100%;padding:48px 22px 24px;background:var(--color-dark-1);color:var(--color-plain-1)}.app .sidebar .item{cursor:pointer}.app .sidebar .item:hover,.app .sidebar .item.active{color:var(--color-orange-1)}.app .sidebar .item:active{color:var(--color-orange-2)}.app .select-box{display:flex;flex-direction:column;width:200px;height:100%;background:rgba(255,255,255,0.5)}.app .select-box .form{display:flex;align-items:center;width:100%;height:35px;padding:0 6px;background:#fff;border-bottom:1px solid var(--color-plain-2)}.app .select-box .form wc-input{flex:1;margin-right:12px}.app .select-box .list{flex:1}.app .select-box .list .item{display:flex;flex-direction:column;justify-content:center;height:48px;padding:6px;transition:color 0.15s ease-in-out, background 0.15s ease-in-out;cursor:pointer}.app .select-box .list .item section{display:flex;justify-content:space-between;align-items:center}.app .select-box .list .item cite{color:var(--color-grey-2)}.app .select-box .list .item .percent{padding:0 4px;border-radius:2px;font-size:12px;color:#fff;background:var(--color-grey-1)}.app .select-box .list .item .percent.red{background:var(--color-red-1)}.app .select-box .list .item .percent.green{background:var(--color-green-3)}.app .select-box .list .item:hover{color:var(--color-orange-1);background:rgba(255,255,255,0.35)}.app .select-box .list .item.active{color:var(--color-orange-3);background:rgba(255,255,255,0.7)}.app .detail{flex:1;height:100%;border-left:1px solid var(--color-plain-2);background:#fff}.app .detail .title{width:100%;height:35px;padding:0 16px;line-height:35px;font-size:16px;font-weight:bold}.app .detail .card{width:96%;padding:12px 12px 16px;margin:12px 2% 24px;border:0;background:#fff;box-shadow:0 0 8px rgba(0,0,0,0.075)}.app .detail .card legend{-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;color:#64b5f6} diff --git a/src/css/app.scss b/src/css/app.scss new file mode 100644 index 0000000..de516d8 --- /dev/null +++ b/src/css/app.scss @@ -0,0 +1,164 @@ +@charset "UTF-8"; +/** + * 主窗口样式 + * @authors yutent + * @date 2018/12/16 17:15:07 + */ + +html { + font-size: 12.8px; + width: 100%; + height: 100vh; +} + +body { + overflow: hidden; + display: flex; + flex-direction: column; + width: 100%; + height: 100%; + line-height: 1.25; + font-size: 14px; + color: var(--color-dark-1); + background: rgba(255, 255, 255, 0.3); +} + +.app-drag { + -webkit-app-region: drag; + user-select: none; +} +.app-nodrag { + -webkit-app-region: no-drag; +} + +.app { + position: relative; + display: flex; + height: 100%; + + .sidebar { + display: flex; + flex-direction: column; + justify-content: space-between; + width: 76px; + height: 100%; + padding: 48px 22px 24px; + background: var(--color-dark-1); + color: var(--color-plain-1); + + .item { + cursor: pointer; + + &:hover, + &.active { + color: var(--color-orange-1); + } + &:active { + color: var(--color-orange-2); + } + } + } + + .select-box { + display: flex; + flex-direction: column; + width: 200px; + height: 100%; + background: rgba(255, 255, 255, 0.5); + + .form { + display: flex; + align-items: center; + width: 100%; + height: 35px; + padding: 0 6px; + background: #fff; + border-bottom: 1px solid var(--color-plain-2); + + wc-input { + flex: 1; + margin-right: 12px; + } + } + + .list { + flex: 1; + + .item { + display: flex; + flex-direction: column; + justify-content: center; + height: 48px; + padding: 6px; + transition: color 0.15s ease-in-out, background 0.15s ease-in-out; + cursor: pointer; + + section { + display: flex; + justify-content: space-between; + align-items: center; + } + + cite { + color: var(--color-grey-2); + } + + .percent { + padding: 0 4px; + border-radius: 2px; + font-size: 12px; + color: #fff; + background: var(--color-grey-1); + + &.red { + background: var(--color-red-1); + } + &.green { + background: var(--color-green-3); + } + } + + &:hover { + color: var(--color-orange-1); + background: rgba(255, 255, 255, 0.35); + } + + &.active { + color: var(--color-orange-3); + background: rgba(255, 255, 255, 0.7); + } + } + } + } + + .detail { + flex: 1; + height: 100%; + border-left: 1px solid var(--color-plain-2); + background: #fff; + + .title { + width: 100%; + height: 35px; + padding: 0 16px; + line-height: 35px; + font-size: 16px; + font-weight: bold; + } + + .card { + width: 96%; + padding: 12px 12px 16px; + margin: 12px 2% 24px; + border: 0; + background: #fff; + box-shadow: 0 0 8px rgba(0, 0, 0, 0.075); + + legend { + -webkit-touch-callout: none; + user-select: none; + color: #64b5f6; + } + } + } +} diff --git a/src/css/float.css b/src/css/float.css index adb80fd..49cecd4 100644 --- a/src/css/float.css +++ b/src/css/float.css @@ -1 +1 @@ -html{font-size:12.8px;width:100%;height:100vh}body{display:flex;flex-direction:column;width:100%;height:100%;line-height:1.25;font-size:14px;color:var(--color-dark-1);background:rgba(255,255,255,0.3)}.app-drag{-webkit-app-region:drag;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.app-nodrag{-webkit-app-region:no-drag}.app{position:relative;display:flex;flex-direction:column;height:100%;padding:6px 0;border-radius:6px}.app .list{flex:1}.app .list .item{display:flex;align-items:center;height:54px;padding:10px 12px;line-height:15px;border-bottom:1px solid var(--color-plain-3)}.app .list .item:last-child{border-bottom:0}.app .list .item .info{overflow:hidden;flex:1}.app .list .item .info h3{font-size:14px}.app .list .item .info cite{color:var(--color-grey-2)}.app .list .item .last-days{display:flex;width:64px;height:30px;margin:0 6px}.app .list .item .today{width:52px;font-size:12px;text-align:right}.app .list .item .today span{display:block;padding:0 4px}.app .list .item .today .percent{border-radius:2px;color:#fff}.app .list .item .today .percent.red{background:var(--color-red-1)}.app .list .item .today .percent.green{background:var(--color-green-3)} +html{font-size:12.8px;width:100%;height:100vh}body{display:flex;flex-direction:column;width:100%;height:100%;line-height:1.25;font-size:14px;color:var(--color-dark-1);background:rgba(255,255,255,0.3)}.app-drag{-webkit-app-region:drag;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.app-nodrag{-webkit-app-region:no-drag}.app{position:relative;display:flex;flex-direction:column;height:100%;padding:6px 0}.app .list{flex:1}.app .list .item{display:flex;align-items:center;height:54px;padding:10px 12px;line-height:15px;border-bottom:1px solid rgba(155,155,155,0.3)}.app .list .item:last-child{border-bottom:0}.app .list .item .info{overflow:hidden;flex:1}.app .list .item .info h3{font-size:14px}.app .list .item .info cite{color:var(--color-grey-2)}.app .list .item .last-days{display:flex;width:64px;height:30px;margin:0 6px}.app .list .item .today{width:52px;font-size:12px;text-align:right}.app .list .item .today span{display:block;padding:0 4px}.app .list .item .today .percent{border-radius:2px;color:#fff}.app .list .item .today .percent.red{background:var(--color-red-1)}.app .list .item .today .percent.green{background:var(--color-green-3)} diff --git a/src/css/float.scss b/src/css/float.scss index 3d0c792..fee5379 100644 --- a/src/css/float.scss +++ b/src/css/float.scss @@ -36,7 +36,6 @@ body { flex-direction: column; height: 100%; padding: 6px 0; - border-radius: 6px; .list { flex: 1; @@ -47,7 +46,7 @@ body { height: 54px; padding: 10px 12px; line-height: 15px; - border-bottom: 1px solid var(--color-plain-3); + border-bottom: 1px solid rgba(155, 155, 155, 0.3); &:last-child { border-bottom: 0; diff --git a/src/float.html b/src/float.html index 65554fe..35416e2 100644 --- a/src/float.html +++ b/src/float.html @@ -9,13 +9,13 @@ - +
-

+

diff --git a/src/index.html b/src/index.html index 550415d..f39978e 100644 --- a/src/index.html +++ b/src/index.html @@ -9,32 +9,56 @@ - +
- - - - -
-
-

- -
+ - - -
- - - -
+
+
+ +
- + + + +
+ + + +
+
+
+
+ + +
+
+ [{{curr.code}}] {{curr.name}} +
+ +
+ 60天红绿榜 + +
+ +
+ 单位净值走势 + +
+ +
+
diff --git a/src/js/app.js b/src/js/app.js index 2a08ad7..8f35b8a 100644 --- a/src/js/app.js +++ b/src/js/app.js @@ -9,6 +9,7 @@ import '/lib/anot.js' import '/lib/form/button.js' import '/lib/scroll/index.js' +import '/lib/chart/rank.js' import '/lib/canvas-draw.js' import layer from '/lib/layer/index.js' @@ -18,7 +19,7 @@ const log = console.log const { ipcRenderer } = require('electron') -// const WIN = remote.getCurrentWindow() +// http://fund.eastmoney.com/pingzhongdata/161725.js?v=20201209153939 const $doc = Anot(document) @@ -59,6 +60,72 @@ function getTableData(str) { Anot({ $id: 'app', state: { + curr: { + code: '161725', + name: '招商中证白酒指数分级', + last60: [ + 1.56, + 2.81, + 0.82, + -0.18, + -1.67, + -2.34, + 1.36, + -1.52, + -0.92, + -0.49, + -1.74, + 0.03, + 1.15, + -0.21, + 0.46, + 1.45, + 5.54, + 1.7, + -0.33, + -0.11, + -1.11, + -0.76, + 3.16, + 0.32, + 1.85, + -2.54, + -1.08, + 0.91, + 3.27, + 2.84, + -2.83, + 1.67, + 1.1, + 0.48, + 1.89, + -0.66, + 1.91, + 2.15, + 0.12, + 1.75, + -3.43, + 3.88, + -1.37, + -1.62, + 0.38, + 1.49, + 1.03, + 0.6, + -3.51, + 0.5, + 0.6, + -3.01, + 0.87, + -0.03, + 0.99, + 3.4, + 0.32, + 1.53, + -0.46, + 0.84 + ].join(',') + }, list: [], $dict: {} }, diff --git a/src/js/float.js b/src/js/float.js index ea8b241..97bcbdc 100644 --- a/src/js/float.js +++ b/src/js/float.js @@ -77,8 +77,14 @@ Anot({ this.$dict[it.code] = it } - app.on('float-visible', function(data) { - console.log(data) + app.on('float-visible', data => { + var time = +Anot.ss('last_update') || 0 + var now = Date.now() + // 如果离上次更新超过15分钟, 则自动更新 + if (now - time > 15 * 60 * 1000) { + this.updateGays() + Anot.ss('last_update', now) + } }) }, methods: { diff --git a/src/lib/chart/rank.js b/src/lib/chart/rank.js new file mode 100644 index 0000000..dc1939b --- /dev/null +++ b/src/lib/chart/rank.js @@ -0,0 +1,118 @@ +/** + * + * @authors yutent (yutent.io@gmail.com) + * @date 2020-12-08 11:30:52 + * @version v1.0.0 + * + */ + +const RED = '#ff5061' +const GREEN = '#4caf50' +const GREY = '#bdbdbd' +const PLAIN = '#f2f5fc' + +export default class Rank extends HTMLElement { + static get observedAttributes() { + return ['list'] + } + + props = { + list: '' + } + + constructor() { + super() + + Object.defineProperty(this, 'root', { + value: this.attachShadow({ mode: 'open' }), + writable: true, + enumerable: false, + configurable: true + }) + + this.root.innerHTML = ` + +` + + this.__SCENE__ = this.root.children[1] + this.__CTX__ = this.__SCENE__.getContext('2d') + this.__SCENE__.width = 680 + this.__SCENE__.height = 100 + } + + draw() { + var { list } = this.props + var ctx = this.__CTX__ + var x = 32 + + while (list.length < 60) { + list.unshift(0) + } + + ctx.clearRect(0, 0, 680, 101) + + ctx.font = '10px Arial' + ctx.textAlign = 'right' + ctx.fillStyle = RED + ctx.fillText('10%', 28, 10) + ctx.fillText('5%', 28, 30) + ctx.fillStyle = GREEN + ctx.fillText('-5%', 28, 80) + ctx.fillText('-10%', 28, 100) + + ctx.fillStyle = PLAIN + ctx.fillRect(28, 25, 652, 1) + ctx.fillRect(28, 75, 652, 1) + ctx.fillStyle = GREY + ctx.fillRect(28, 0, 1, 140) + ctx.fillRect(0, 50, 680, 1) + + while (list.length) { + var n = list.shift() + var y = Math.ceil(50 - (n / 10) * 50) + + ctx.fillStyle = n > 0 ? RED : GREEN + + if (y > 50) { + ctx.fillRect(x, 50, 3, y - 50) + } else { + ctx.fillRect(x, y, 3, 50 - y) + } + + x += 10 + } + } + + attributeChangedCallback(name, old, val) { + if (val === null || old === val) { + return + } + switch (name) { + case 'list': + var list = val.split(',') + this.props.list = list.map(n => +n) + this.removeAttribute('list') + this.draw() + break + } + } +} + +if (!customElements.get('wc-rank')) { + customElements.define('wc-rank', Rank) +} diff --git a/src/lib/form/button.js b/src/lib/form/button.js index 592194b..98aabd2 100644 --- a/src/lib/form/button.js +++ b/src/lib/form/button.js @@ -1,14 +1,483 @@ /** * * @authors yutent (yutent.io@gmail.com) - * @date 2020-07-22 19:57:05 - * @version v2.0.1 + * @date 2020-12-08 11:30:52 + * @version v1.0.0 * */ -'use strict' -import"../icon/index.js";import $ from"../utils.js";const IS_FIREFOX=!!window.sidebar;export default class Button extends HTMLElement{static get observedAttributes(){return["icon","autofocus","loading","disabled","lazy"]}constructor(){super(),Object.defineProperty(this,"root",{value:this.attachShadow({mode:"open"}),writable:!0,enumerable:!1,configurable:!0}),Object.defineProperty(this,"props",{value:{icon:"",autofocus:"",loading:!1,disabled:!1,lazy:0},writable:!0,enumerable:!1,configurable:!0}),this.root.innerHTML=" ",this.hasAttribute("circle")&&(this.textContent=""),this.__BTN__=this.root.children[1],this.__ICO__=this.__BTN__.children[0]}get loading(){return this.props.loading}set loading(o){var t=typeof o;o!==this.props.loading&&("boolean"===t&&o||"boolean"!==t?(this.props.loading=!0,this.__ICO__.setAttribute("is","loading"),this.setAttribute("loading","")):(this.props.loading=!1,this.__ICO__.setAttribute("is",this.props.icon),this.removeAttribute("loading")))}get disabled(){return this.props.disabled}set disabled(o){var t=typeof o;o!==this.props.disabled&&("boolean"===t&&o||"boolean"!==t?(this.props.disabled=!0,this.setAttribute("disabled","")):(this.props.disabled=!1,this.removeAttribute("disabled")))}connectedCallback(){this.stamp=0,this._handleClick=$.bind(this.__BTN__,"click",o=>{var{loading:t,disabled:e,lazy:r}=this.props,n=Date.now();return t||e?o.stopPropagation():r&&n-this.stamp{this.__BTN__.focus()},10);break;case"lazy":this.props.lazy=e>>0;break;case"loading":case"disabled":this[o]=!0}}}; +import "../icon/index.js" +import $ from "../utils.js" + +const IS_FIREFOX = !!window.sidebar + +export default class Button extends HTMLElement { + + + static get observedAttributes() { + return ["icon","autofocus","loading","disabled","lazy"] + } + + props = { + icon: '', + autofocus: '', + loading: false, + disabled: false, + lazy: 0 // 并发拦截时间, 单位毫秒 + } + + + constructor() { + super(); + + Object.defineProperty(this, 'root', { + value: this.attachShadow({ mode: 'open' }), + writable: true, + enumerable: false, + configurable: true + }) + + this.root.innerHTML = ` + +` + + + // 圆形按钮不允许文字 + if (this.hasAttribute('circle')) { + this.textContent = '' + } + + this.__BTN__ = this.root.children[1] + this.__ICO__ = this.__BTN__.children[0] + } + + get loading() { + return this.props.loading + } + + set loading(val) { + var type = typeof val + + if (val === this.props.loading) { + return + } + + if ((type === 'boolean' && val) || type !== 'boolean') { + this.props.loading = true + this.__ICO__.setAttribute('is', 'loading') + this.setAttribute('loading', '') + } else { + this.props.loading = false + this.__ICO__.setAttribute('is', this.props.icon) + this.removeAttribute('loading') + } + } + + get disabled() { + return this.props.disabled + } + + set disabled(val) { + var type = typeof val + + if (val === this.props.disabled) { + return + } + if ((type === 'boolean' && val) || type !== 'boolean') { + this.props.disabled = true + this.setAttribute('disabled', '') + } else { + this.props.disabled = false + this.removeAttribute('disabled') + } + } + + connectedCallback() { + this.stamp = 0 + + // 阻止事件冒泡, 避免用户自己绑定click事件不受这2个值的限制 + this._handleClick = $.bind(this.__BTN__, 'click', ev => { + var { loading, disabled, lazy } = this.props + var now = Date.now() + + if (loading || disabled) { + return ev.stopPropagation() + } + // 并发拦截 + if (lazy && now - this.stamp < lazy) { + return ev.stopPropagation() + } + this.stamp = now + }) + } + + disconnectedCallback() { + $.unbind(this.__BTN__, 'click', this._handleClick) + } + + attributeChangedCallback(name, old, val) { +if (val === null || old === val) {return} + switch (name) { + case 'icon': + this.props.icon = val + if (val) { + if (!this.props.loading) { + this.__ICO__.setAttribute('is', val) + } + } else { + this.removeAttribute('icon') + this.__ICO__.removeAttribute('is') + } + break + + case 'autofocus': + this.__BTN__.setAttribute('autofocus', '') + // 辣鸡火狐, 要触发一下focus, 才能聚焦 + if (IS_FIREFOX) { + setTimeout(_ => { + this.__BTN__.focus() + }, 10) + } + break + case 'lazy': + this.props.lazy = val >> 0 + break + + case 'loading': + case 'disabled': + this[name] = true + break + } + } +} + if(!customElements.get('wc-button')){ customElements.define('wc-button', Button) diff --git a/src/lib/form/checkbox-item.js b/src/lib/form/checkbox-item.js new file mode 100644 index 0000000..2154488 --- /dev/null +++ b/src/lib/form/checkbox-item.js @@ -0,0 +1,311 @@ +/** + * + * @authors yutent (yutent.io@gmail.com) + * @date 2020-12-08 11:30:52 + * @version v1.0.0 + * + */ + + +import "../icon/index.js" +import $ from "../utils.js" + +export default class CheckboxItem extends HTMLElement { + + + static get observedAttributes() { + return ["color","value","checked","readonly","disabled"] + } + + props = { + color: '', + value: '', + checked: false, + readonly: false, + disabled: false + } + + constructor() { + super(); + + Object.defineProperty(this, 'root', { + value: this.attachShadow({ mode: 'open' }), + writable: true, + enumerable: false, + configurable: true + }) + + this.root.innerHTML = ` + +` + + + this.__SWITCH__ = this.root.lastElementChild + this.__ICO__ = this.__SWITCH__.children[0] + + this._isInGroup = false + } + + _checkGroup() { + this._isInGroup = this.parentNode.tagName === 'WC-CHECKBOX' + if (this._isInGroup && this.parentNode.root) { + if (this.parentNode.value.includes(this.value)) { + this.checked = true + } + } + } + + get value() { + return this.props.value + } + + set value(val) { + this.props.value = val + } + + get checked() { + return this.props.checked + } + + set checked(val) { + this.props.checked = !!val + var { checked, color } = this.props + this.__SWITCH__.classList.toggle('checked', checked) + this.__ICO__.setAttribute('is', 'checkbox-' + (checked ? 'on' : 'off')) + + if (checked) { + this.__ICO__.setAttribute('color', color) + } else { + this.__ICO__.removeAttribute('color') + } + } + + get readOnly() { + return this.props.readonly + } + + set readOnly(val) { + var type = typeof val + + if (val === this.props.readonly) { + return + } + if ((type === 'boolean' && val) || type !== 'boolean') { + this.props.readonly = true + this.setAttribute('readonly', '') + } else { + this.props.readonly = false + this.removeAttribute('readonly') + } + } + + get disabled() { + return this.props.disabled + } + + set disabled(val) { + var type = typeof val + + if (val === this.props.disabled) { + return + } + if ((type === 'boolean' && val) || type !== 'boolean') { + this.props.disabled = true + this.setAttribute('disabled', '') + } else { + this.props.disabled = false + this.removeAttribute('disabled') + } + } + + connectedCallback() { + this._checkGroup() + + this._handlClick = $.bind(this, 'click', ev => { + ev.preventDefault() + + if (this.disabled || this.readOnly) { + return + } + + this.checked = !this.checked + + if (this._isInGroup) { + this.parentNode.dispatchEvent( + new CustomEvent('child-picked', { + detail: { value: this.value, checked: this.checked } + }) + ) + } else { + this.dispatchEvent(new CustomEvent('input')) + } + }) + } + + disconnectedCallback() { + $.unbind(this, 'click', this._handlClick) + } + + attributeChangedCallback(name, old, val) { +if (val === null || old === val) {return} + switch (name) { + case 'value': + case 'color': + this.props[name] = val + break + + case 'checked': + case 'readonly': + case 'disabled': + var k = name + if (k === 'readonly') { + k = 'readOnly' + } + this[k] = true + break + } + } +} + + +if(!customElements.get('wc-checkbox-item')){ + customElements.define('wc-checkbox-item', CheckboxItem) +} diff --git a/src/lib/form/checkbox.js b/src/lib/form/checkbox.js index 516e9ac..7e199e7 100644 --- a/src/lib/form/checkbox.js +++ b/src/lib/form/checkbox.js @@ -1,14 +1,141 @@ /** * * @authors yutent (yutent.io@gmail.com) - * @date 2020-07-22 19:57:05 - * @version v2.0.1 + * @date 2020-12-08 11:30:52 + * @version v1.0.0 * */ -'use strict' -import"../icon/index.js";import $ from"../utils.js";export default class Checkbox extends HTMLElement{static get observedAttributes(){return["label","color","value","checked","readonly","disabled"]}constructor(){super(),Object.defineProperty(this,"root",{value:this.attachShadow({mode:"open"}),writable:!0,enumerable:!1,configurable:!0}),Object.defineProperty(this,"props",{value:{label:"",color:"",value:[],checked:!1,readonly:!1,disabled:!1},writable:!0,enumerable:!1,configurable:!0}),this.root.innerHTML=" ",this.__SWITCH__=this.root.lastElementChild,this.__ICO__=this.__SWITCH__.children[0]}get value(){return this.props.value}set value(e){Array.isArray(e)?(this.props.value=e,this.checked=this.props.value.includes(this.props.label)):console.error("checkbox组件的value必须是数组, 当前为: "+typeof e)}get checked(){return this.props.checked}set checked(e){this.props.checked=!!e;var{value:o,checked:t,label:l,color:r}=this.props;this.__SWITCH__.classList.toggle("checked",t),this.__ICO__.setAttribute("is","checkbox-"+(t?"on":"off"));var c=o.indexOf(l);t?(this.__ICO__.setAttribute("color",r),c<0&&o.push(l)):(this.__ICO__.removeAttribute("color"),~c&&o.splice(c,1))}get readOnly(){return this.props.readonly}set readOnly(e){var o=typeof e;e!==this.props.readonly&&("boolean"===o&&e||"boolean"!==o?(this.props.readonly=!0,this.setAttribute("readonly","")):(this.props.readonly=!1,this.removeAttribute("readonly")))}get disabled(){return this.props.disabled}set disabled(e){var o=typeof e;e!==this.props.disabled&&("boolean"===o&&e||"boolean"!==o?(this.props.disabled=!0,this.setAttribute("disabled","")):(this.props.disabled=!1,this.removeAttribute("disabled")))}connectedCallback(){this._handlClick=$.bind(this,"click",e=>{e.preventDefault(),this.disabled||this.readOnly||(this.checked=!this.checked,this.dispatchEvent(new CustomEvent("input")))})}disconnectedCallback(){$.unbind(this,"click",this._handlClick)}attributeChangedCallback(e,o,t){if(null!==t&&o!==t)switch(e){case"label":case"color":this.props[e]=t;break;case"checked":case"readonly":case"disabled":var l=e;"readonly"===l&&(l="readOnly"),this[l]=!0}}}; +import $ from "../utils.js" +import "./checkbox-item.js" + +export default class Checkbox extends HTMLElement { + + + static get observedAttributes() { + return ["value"] + } + + props = { + value: [] + } + + + constructor() { + super(); + + Object.defineProperty(this, 'root', { + value: this.attachShadow({ mode: 'open' }), + writable: true, + enumerable: false, + configurable: true + }) + + this.root.innerHTML = ` + +` + + } + + _updateChildrenStat() { + Array.from(this.children).forEach(it => { + if (it.tagName === 'WC-CHECKBOX-ITEM' && it.root) { + if (this.value.includes(it.value)) { + it.checked = true + } else { + it.checked = false + } + } + }) + } + + get value() { + return this.props.value + } + + set value(val) { + if (val === this.props.value) { + return + } + this.props.value = val + this._updateChildrenStat() + } + + connectedCallback() { + this._pickedFn = $.bind(this, 'child-picked', ev => { + var tmp = [...this.props.value] + var idx = tmp.indexOf(ev.detail.value) + if (ev.detail.checked) { + if (idx < 0) { + tmp.push(ev.detail.value) + } + } else { + if (~idx) { + tmp.splice(idx, 1) + } + } + this.props.value = tmp + this.dispatchEvent(new CustomEvent('input')) + }) + } + + disconnectedCallback() { + $.unbind(this, 'child-picked', this._pickedFn) + } + + attributeChangedCallback(name, old, val) { +if (val === null || old === val) {return} + switch (name) { + case 'value': + if (val) { + this.value = val.split(/,\s*?/) + } + break + } + } +} + if(!customElements.get('wc-checkbox')){ customElements.define('wc-checkbox', Checkbox) diff --git a/src/lib/form/input.js b/src/lib/form/input.js index 4ac8b0e..1d232c3 100644 --- a/src/lib/form/input.js +++ b/src/lib/form/input.js @@ -1,14 +1,616 @@ /** * * @authors yutent (yutent.io@gmail.com) - * @date 2020-07-22 20:29:37 - * @version v2.0.1 + * @date 2020-12-08 11:30:52 + * @version v1.0.0 * */ -'use strict' -import"../scroll/index.js";import"../icon/index.js";import $ from"../utils.js";const TYPES=["text","textarea","password"],INPUTS={text:'',textarea:''};export default class Input extends HTMLElement{static get observedAttributes(){return["value","icon","type","label","placeholder","mvidx","autofocus","readonly","disabled"]}constructor(){super();var e,t=this.getAttribute("type");"textarea"!==t&&(t="text"),e=INPUTS[t],Object.defineProperty(this,"root",{value:this.attachShadow({mode:"open"}),writable:!0,enumerable:!1,configurable:!0}),Object.defineProperty(this,"props",{value:{value:"",icon:"",type:"text",label:"",placeholder:"",mvidx:null,autofocus:!1,readonly:!1,disabled:!1},writable:!0,enumerable:!1,configurable:!0}),this.root.innerHTML=`
${e}
    `,this.props.type=t,this.__OUTER__=this.root.children[1],this.__PREPEND__=this.__OUTER__.children[0],this.__INPUT__=this.__OUTER__.children[1],this.__ICO__=this.__OUTER__.children[2],this.__APPEND__=this.__OUTER__.children[3],this.__LIST__=this.__OUTER__.children[4]}get readOnly(){return this.props.readonly}set readOnly(e){var t=typeof e;e!==this.props.readonly&&("boolean"===t&&e||"boolean"!==t?(this.props.readonly=!0,this.setAttribute("readonly",""),this.__INPUT__.setAttribute("readonly","")):(this.props.readonly=!1,this.removeAttribute("readonly"),this.__INPUT__.removeAttribute("readonly")))}get disabled(){return this.props.disabled}set disabled(e){var t=typeof e;e!==this.props.disabled&&("boolean"===t&&e||"boolean"!==t?(this.props.disabled=!0,this.setAttribute("disabled",""),this.__INPUT__.setAttribute("disabled","")):(this.props.disabled=!1,this.removeAttribute("disabled"),this.__INPUT__.removeAttribute("disabled")))}get value(){return this.__INPUT__.value}set value(e){this.__INPUT__.value=e}get type(){return this.__INPUT__.type}set type(e){"textarea"!==e&&(this.__INPUT__.type=e)}_moveSelect(e){var{list:t}=this.props;if(t&&t.length){e.preventDefault();var i=38===e.keyCode?-1:1,s=Array.from(this.__LIST__.firstElementChild.firstElementChild.children);null===this.props.mvidx?this.props.mvidx=0:this.props.mvidx+=i,this.props.mvidx<0?this.props.mvidx=0:this.props.mvidx>s.length-1&&(this.props.mvidx=s.length-1),s.forEach((e,t)=>{t===this.props.mvidx?(this.__LIST__.firstElementChild.scrollTop=e.offsetTop-150,e.setAttribute("focus","")):e.removeAttribute("focus")})}}_fetchSelect(e,t){var i=this.props.list[e];this.value=i.value,this.dispatchEvent(new CustomEvent("select",{detail:i})),this._handleChange(t),this.__LIST__.classList.remove("show"),this.props.mvidx=null}connectedCallback(){for(var e=this.__PREPEND__.assignedNodes(),t=this.__APPEND__.assignedNodes();e.length>1;)this.removeChild(e.pop());for(;t.length>1;)this.removeChild(t.pop());e.length&&"textarea"!==this.props.type&&this.__OUTER__.setAttribute("prepend",""),t.length&&"textarea"!==this.props.type&&this.__OUTER__.setAttribute("append","");var{type:i}=this.props;this._handleSubmit=$.catch(this.__INPUT__,"keydown",e=>{if(!this.disabled&&!this.readOnly){if((38===e.keyCode||40===e.keyCode)&&"text"===this.type)return this._moveSelect(e);if(13===e.keyCode){if("text"===this.type&&null!==this.props.mvidx)return this._fetchSelect(this.props.mvidx,e);("text"===i||"textarea"===i&&(e.ctrlKey||e.metaKey))&&this.dispatchEvent(new CustomEvent("submit",{detail:this.value}))}}}),"text"===i?(this._handleChange=$.bind(this.__INPUT__,"input",e=>{e.preventDefault(),this.dispatchEvent(new CustomEvent("fetch-suggest",{detail:{value:this.value,send:e=>{this.props.list=e,this._parseSuggestion()}}}))}),this._parseSuggestion=$.bind(this.__INPUT__,"click",e=>{var{list:t}=this.props;let{x:i,y:s,width:o}=this.getBoundingClientRect();if(t&&t.length){var r=t.map((e,t)=>`
  • ${e.value}
  • `).join("");this.__LIST__.firstElementChild.firstElementChild.innerHTML=r,this.__LIST__.classList.toggle("show",!0),this.__LIST__.style.cssText=`left:${i}px;top:${s+50}px;width:${o}px;`}else this.__LIST__.classList.toggle("show",!1)}),this._inactiveFn=$.outside(this,e=>{this.__LIST__.classList.remove("show")}),this._handleSelect=$.bind(this.__LIST__,"click",e=>{"LI"===e.target.tagName&&(this._fetchSelect(e.target.dataset.idx,e),this.dispatchEvent(new CustomEvent("input")))})):this._handleWheel=$.catch(this.__INPUT__,"wheel")}disconnectedCallback(){$.unbind(this.__INPUT__,"wheel",this._handleWheel),$.unbind(this.__INPUT__,"keydown",this._handleSubmit),$.unbind(this.__INPUT__,"input",this._handleChange),$.unbind(this.__LIST__,"click",this._handleSelect),$.clearOutside(this._inactiveFn)}attributeChangedCallback(e,t,i){if(null!==i&&t!==i)switch(e){case"icon":this.props.icon=i,i?this.__ICO__.setAttribute("is",i):(this.removeAttribute("icon"),this.__ICO__.removeAttribute("is"));break;case"autofocus":this.__INPUT__.setAttribute("autofocus",""),setTimeout(e=>{this.__INPUT__.focus()},10);break;case"label":case"placeholder":this.__INPUT__.setAttribute("placeholder",i);break;case"type":~TYPES.indexOf(i)?this.type=i:this.type="text";break;case"value":this.value=i;break;case"readonly":case"disabled":var s=e;"readonly"===s&&(s="readOnly"),this[s]=!0}}}; +import "../scroll/index.js" +import "../icon/index.js" +import $ from "../utils.js" + +const TYPES = ['text', 'textarea', 'password'] +const INPUTS = { + text: '', + textarea: '' +} + +export default class Input extends HTMLElement { + + + static get observedAttributes() { + return ["value","icon","type","placeholder","maxlength","minlength","autofocus","readonly","disabled"] + } + + props = { + value: '', + icon: '', + type: 'text', + placeholder: '', + maxlength: null, + minlength: null, + autofocus: false, + readonly: false, + disabled: false + } + + + state = { + mvidx: null //下拉列表光标的索引ID + } + + constructor() { + super(); + var type = this.getAttribute('type') + var input = '' + + if (type !== 'textarea') { + type = 'text' + } + + input = INPUTS[type] + + + Object.defineProperty(this, 'root', { + value: this.attachShadow({ mode: 'open' }), + writable: true, + enumerable: false, + configurable: true + }) + + this.root.innerHTML = ` +
    + + ${input} + + + +
    + +
      +
      +
      +
      +` + + + this.props.type = type + + this.__OUTER__ = this.root.children[1] + this.__PREPEND__ = this.__OUTER__.children[0] + this.__INPUT__ = this.__OUTER__.children[1] + this.__ICO__ = this.__OUTER__.children[2] + this.__APPEND__ = this.__OUTER__.children[3] + this.__LIST__ = this.__OUTER__.children[4] + } + + get readOnly() { + return this.props.readonly + } + + set readOnly(val) { + var type = typeof val + + if (val === this.props.readonly) { + return + } + + if ((type === 'boolean' && val) || type !== 'boolean') { + this.props.readonly = true + this.setAttribute('readonly', '') + this.__INPUT__.setAttribute('readonly', '') + } else { + this.props.readonly = false + this.removeAttribute('readonly') + this.__INPUT__.removeAttribute('readonly') + } + } + + get disabled() { + return this.props.disabled + } + + set disabled(val) { + var type = typeof val + + if (val === this.props.disabled) { + return + } + if ((type === 'boolean' && val) || type !== 'boolean') { + this.props.disabled = true + this.setAttribute('disabled', '') + this.__INPUT__.setAttribute('disabled', '') + } else { + this.props.disabled = false + this.removeAttribute('disabled') + this.__INPUT__.removeAttribute('disabled') + } + } + + get value() { + return this.__INPUT__.value + } + + set value(val) { + this.__INPUT__.value = val + } + + get type() { + return this.__INPUT__.type + } + + set type(val) { + if (val !== 'textarea') { + this.__INPUT__.type = val + } + } + + // 移动光标选择下拉选项 + _moveSelect(ev) { + var { list } = this.props + if (list && list.length) { + ev.preventDefault() + var step = ev.keyCode === 38 ? -1 : 1 + var items = Array.from( + this.__LIST__.firstElementChild.firstElementChild.children + ) + if (this.state.mvidx === null) { + this.state.mvidx = 0 + } else { + this.state.mvidx += step + } + if (this.state.mvidx < 0) { + this.state.mvidx = 0 + } else if (this.state.mvidx > items.length - 1) { + this.state.mvidx = items.length - 1 + } + items.forEach((it, i) => { + if (i === this.state.mvidx) { + this.__LIST__.firstElementChild.scrollTop = it.offsetTop - 150 + it.setAttribute('focus', '') + } else { + it.removeAttribute('focus') + } + }) + } + } + + // 触发列表选择 + _fetchSelect(idx, ev) { + var item = this.props.list[idx] + this.value = item.value + this.dispatchEvent( + new CustomEvent('select', { + detail: item + }) + ) + this._handleChange(ev) + this.__LIST__.classList.remove('show') + this.state.mvidx = null + } + + _updateAttr() { + var { maxlength, minlength } = this.props + + if (maxlength && maxlength > 0) { + this.__INPUT__.setAttribute('maxlength', maxlength) + } else { + this.__INPUT__.removeAttribute('maxlength') + } + if (minlength && minlength > 0) { + this.__INPUT__.setAttribute('minlength', minlength) + } else { + this.__INPUT__.removeAttribute('minlength') + } + } + + connectedCallback() { + var prepend = this.__PREPEND__.assignedNodes() + var append = this.__APPEND__.assignedNodes() + var { type } = this.props + + // 相同插槽, 只允许1个 + while (prepend.length > 1) { + this.removeChild(prepend.pop()) + } + while (append.length > 1) { + this.removeChild(append.pop()) + } + + if (prepend.length && type !== 'textarea') { + this.__OUTER__.setAttribute('prepend', '') + } + if (append.length && type !== 'textarea') { + this.__OUTER__.setAttribute('append', '') + } + + this._updateAttr() + + // 键盘事件 + this._handleSubmit = $.catch(this.__INPUT__, 'keydown', ev => { + if (this.disabled || this.readOnly) { + return + } + // up: 38, down: 40 + if (ev.keyCode === 38 || ev.keyCode === 40) { + // 仅普通文本表单, 密码和多行文本框不做响应 + if (type === 'text') { + return this._moveSelect(ev) + } + } + // 回车触发submit事件 + // textarea 要按Ctrl Or Cmd键, 才会触发 + if (ev.keyCode === 13) { + // 如果是输入建议存在,则第1次回车的时候, 不触发提交 + if (type === 'text' && this.state.mvidx !== null) { + return this._fetchSelect(this.state.mvidx, ev) + } + + if ( + type === 'text' || + (type === 'textarea' && (ev.ctrlKey || ev.metaKey)) + ) { + this.dispatchEvent( + new CustomEvent('submit', { + detail: this.value + }) + ) + } + } + }) + + // 非textarea, 可做输入建议功能 + if (type === 'text') { + // 输入状态事件 + this._handleChange = $.bind(this.__INPUT__, 'input', ev => { + ev.preventDefault() + this.dispatchEvent( + new CustomEvent('fetch-suggest', { + detail: { + value: this.value, + send: list => { + this.props.list = list + this._parseSuggestion() + } + } + }) + ) + }) + + // 渲染建议列表 + this._parseSuggestion = $.bind(this.__INPUT__, 'click', ev => { + var { list } = this.props + let { x, y, width } = this.getBoundingClientRect() + if (list && list.length) { + var html = list + .map((it, i) => `
    • ${it.value}
    • `) + .join('') + this.__LIST__.firstElementChild.firstElementChild.innerHTML = html + this.__LIST__.classList.toggle('show', true) + this.__LIST__.style.cssText = `left:${x}px;top:${y + + 50}px;width:${width}px;` + } else { + this.__LIST__.classList.toggle('show', false) + } + }) + + this._inactiveFn = $.outside(this, ev => { + this.__LIST__.classList.remove('show') + }) + + // 选择建议 + this._handleSelect = $.bind(this.__LIST__, 'click', ev => { + if (ev.target.tagName === 'LI') { + this._fetchSelect(ev.target.dataset.idx, ev) + this.dispatchEvent(new CustomEvent('input')) + } + }) + } else { + this._handleWheel = $.catch(this.__INPUT__, 'wheel') + } + } + + disconnectedCallback() { + $.unbind(this.__INPUT__, 'wheel', this._handleWheel) + $.unbind(this.__INPUT__, 'keydown', this._handleSubmit) + $.unbind(this.__INPUT__, 'input', this._handleChange) + $.unbind(this.__LIST__, 'click', this._handleSelect) + $.clearOutside(this._inactiveFn) + } + + attributeChangedCallback(name, old, val) { +if (val === null || old === val) {return} + switch (name) { + case 'icon': + this.props.icon = val + if (val) { + this.__ICO__.setAttribute('is', val) + } else { + this.removeAttribute('icon') + this.__ICO__.removeAttribute('is') + } + break + + case 'autofocus': + this.__INPUT__.setAttribute('autofocus', '') + // 辣鸡火狐, 要触发一下focus, 才能聚焦 + setTimeout(_ => { + this.__INPUT__.focus() + }, 10) + + break + + case 'placeholder': + this.__INPUT__.setAttribute('placeholder', val) + break + + case 'type': + if (~TYPES.indexOf(val)) { + this.type = val + } else { + this.type = 'text' + } + break + + case 'value': + this.value = val + break + + case 'maxlength': + case 'minlength': + this.props[name] = val + this._updateAttr() + break + + case 'readonly': + case 'disabled': + var k = name + if (k === 'readonly') { + k = 'readOnly' + } + this[k] = true + break + } + } +} + if(!customElements.get('wc-input')){ customElements.define('wc-input', Input) diff --git a/src/lib/form/number.js b/src/lib/form/number.js index dabd15a..e6cc97a 100644 --- a/src/lib/form/number.js +++ b/src/lib/form/number.js @@ -1,14 +1,412 @@ /** * * @authors yutent (yutent.io@gmail.com) - * @date 2020-07-22 19:57:05 - * @version v2.0.1 + * @date 2020-12-08 11:30:52 + * @version v1.0.0 * */ -'use strict' -import"../scroll/index.js";import"../icon/index.js";import $ from"../utils.js";export default class Number extends HTMLElement{static get observedAttributes(){return["value","max","min","step","autofocus","readonly","disabled"]}constructor(){super(),Object.defineProperty(this,"root",{value:this.attachShadow({mode:"open"}),writable:!0,enumerable:!1,configurable:!0}),Object.defineProperty(this,"props",{value:{value:0,max:null,min:null,step:1,autofocus:!1,readonly:!1,disabled:!1},writable:!0,enumerable:!1,configurable:!0}),this.root.innerHTML="
      - \x3c!-- --\x3e + \x3c!-- --\x3e
      ",this.__OUTER__=this.root.children[1],this.__INPUT__=this.__OUTER__.children[1]}get readOnly(){return this.props.readonly}set readOnly(e){var t=typeof e;e!==this.props.readonly&&("boolean"===t&&e||"boolean"!==t?(this.props.readonly=!0,this.setAttribute("readonly",""),this.__INPUT__.setAttribute("readonly","")):(this.props.readonly=!1,this.removeAttribute("readonly"),this.__INPUT__.removeAttribute("readonly")))}get disabled(){return this.props.disabled}set disabled(e){var t=typeof e;e!==this.props.disabled&&("boolean"===t&&e||"boolean"!==t?(this.props.disabled=!0,this.setAttribute("disabled",""),this.__INPUT__.setAttribute("disabled","")):(this.props.disabled=!1,this.removeAttribute("disabled"),this.__INPUT__.removeAttribute("disabled")))}get value(){return this.props.value}set value(e){var t=+e;e=t==t?t:0,this.props.value=e,this.__INPUT__.value=e,this._checkActionEnable()}_checkActionEnable(){var{max:e,min:t,value:i}=this.props,s=i;null!==t&&(t>s&&(s=t),this.__OUTER__.children[0].classList.toggle("disabled",i<=t)),null!==e&&(e=e)),s!==i&&(this.props.value=s,this.__INPUT__.value=s,this.dispatchEvent(new CustomEvent("input")))}_updateValue(e){var{max:t,min:i,value:s,step:a}=this.props;if("+"===e){if(null!==t&&ts-a)return;s-=a}this.props.value=+s.toFixed(2),this.__INPUT__.value=this.props.value,this._checkActionEnable(),this.dispatchEvent(new CustomEvent("input"))}connectedCallback(){this._handleSubmit=$.catch(this.__INPUT__,"keydown",e=>{if(!this.disabled&&!this.readOnly)return 38===e.keyCode||40===e.keyCode?(e.preventDefault(),this._updateValue(38===e.keyCode?"+":"-")):void(13===e.keyCode&&(e.preventDefault(),this.dispatchEvent(new CustomEvent("submit",{detail:this.value}))))}),this._handleChange=$.catch(this.__INPUT__,"change",e=>{isFinite(this.__INPUT__.value)?(this.props.value=+this.__INPUT__.value,this.__INPUT__.value.endsWith(".")||(this.__INPUT__.value=this.props.value)):this.__INPUT__.value=this.props.value=0,this.dispatchEvent(new CustomEvent("input"))}),this._handleAction=$.bind(this.__OUTER__,"click",e=>{if(!this.disabled&&!this.readOnly){var t=e.target;if("SPAN"===t.tagName||"SPAN"===t.parentNode){var i=t.dataset.act||t.parentNode.dataset.act;this._updateValue(i)}}})}disconnectedCallback(){$.unbind(this.__INPUT__,"keydown",this._handleSubmit)}attributeChangedCallback(e,t,i){if(null!==i&&t!==i)switch(e){case"autofocus":this.__INPUT__.setAttribute("autofocus",""),setTimeout(e=>{this.__INPUT__.focus()},10);break;case"value":this.value=i>>0;break;case"step":case"max":case"min":var s=+i;s==s&&(this.props[e]=s),this._checkActionEnable();break;case"readonly":case"disabled":var a=e;"readonly"===a&&(a="readOnly"),this[a]=!0}}}; +import "../scroll/index.js" +import "../icon/index.js" +import $ from "../utils.js" + +export default class Number extends HTMLElement { + + + static get observedAttributes() { + return ["value","max","min","step","autofocus","readonly","disabled"] + } + + props = { + value: 0, + max: null, + min: null, + step: 1, + autofocus: false, + readonly: false, + disabled: false + } + + + constructor() { + super(); + + Object.defineProperty(this, 'root', { + value: this.attachShadow({ mode: 'open' }), + writable: true, + enumerable: false, + configurable: true + }) + + this.root.innerHTML = ` +
      + - + + + + + +
      +` + + + this.__OUTER__ = this.root.children[1] + this.__INPUT__ = this.__OUTER__.children[1] + } + + get readOnly() { + return this.props.readonly + } + + set readOnly(val) { + var type = typeof val + + if (val === this.props.readonly) { + return + } + if ((type === 'boolean' && val) || type !== 'boolean') { + this.props.readonly = true + this.setAttribute('readonly', '') + this.__INPUT__.setAttribute('readonly', '') + } else { + this.props.readonly = false + this.removeAttribute('readonly') + this.__INPUT__.removeAttribute('readonly') + } + } + + get disabled() { + return this.props.disabled + } + + set disabled(val) { + var type = typeof val + + if (val === this.props.disabled) { + return + } + if ((type === 'boolean' && val) || type !== 'boolean') { + this.props.disabled = true + this.setAttribute('disabled', '') + this.__INPUT__.setAttribute('disabled', '') + } else { + this.props.disabled = false + this.removeAttribute('disabled') + this.__INPUT__.removeAttribute('disabled') + } + } + + get value() { + return this.props.value + } + + set value(val) { + var n = +val + if (n === n) { + val = n + } else { + val = 0 + } + this.props.value = val + this.__INPUT__.value = val + + this._checkActionEnable() + } + + _checkActionEnable() { + var { max, min, value } = this.props + var n = value + + if (min !== null) { + if (min > n) { + n = min + } + this.__OUTER__.children[0].classList.toggle('disabled', value <= min) + } + if (max !== null) { + if (max < n) { + n = max + } + this.__OUTER__.children[2].classList.toggle('disabled', value >= max) + } + if (n !== value) { + this.props.value = n + this.__INPUT__.value = n + this.dispatchEvent(new CustomEvent('input')) + } + } + + _updateValue(act) { + var { max, min, value, step } = this.props + if (act === '+') { + if (max !== null && max < value + step) { + return + } + value += step + } else { + if (min !== null && min > value - step) { + return + } + value -= step + } + this.props.value = +value.toFixed(2) + this.__INPUT__.value = this.props.value + this._checkActionEnable() + this.dispatchEvent(new CustomEvent('input')) + } + + connectedCallback() { + // 键盘事件 + this._handleSubmit = $.catch(this.__INPUT__, 'keydown', ev => { + if (this.disabled || this.readOnly) { + return + } + + // up: 38, down: 40 + if (ev.keyCode === 38 || ev.keyCode === 40) { + ev.preventDefault() + return this._updateValue(ev.keyCode === 38 ? '+' : '-') + } + // 回车触发submit事件 + if (ev.keyCode === 13) { + ev.preventDefault() + this.dispatchEvent( + new CustomEvent('submit', { + detail: this.value + }) + ) + } + }) + + this._handleChange = $.catch(this.__INPUT__, 'change', ev => { + if (isFinite(this.__INPUT__.value)) { + this.props.value = +this.__INPUT__.value + if (!this.__INPUT__.value.endsWith('.')) { + this.__INPUT__.value = this.props.value + } + } else { + this.__INPUT__.value = this.props.value = 0 + } + this.dispatchEvent(new CustomEvent('input')) + }) + + this._handleAction = $.bind(this.__OUTER__, 'click', ev => { + if (this.disabled || this.readOnly) { + return + } + var target = ev.target + + if (target.tagName === 'SPAN' || target.parentNode === 'SPAN') { + var act = target.dataset.act || target.parentNode.dataset.act + + this._updateValue(act) + } + }) + } + + disconnectedCallback() { + $.unbind(this.__INPUT__, 'keydown', this._handleSubmit) + } + + attributeChangedCallback(name, old, val) { +if (val === null || old === val) {return} + switch (name) { + case 'autofocus': + this.__INPUT__.setAttribute('autofocus', '') + // 辣鸡火狐, 要触发一下focus, 才能聚焦 + setTimeout(_ => { + this.__INPUT__.focus() + }, 10) + break + + case 'value': + this.value = val >> 0 + break + + case 'step': + case 'max': + case 'min': + var n = +val + if (n === n) { + this.props[name] = n + } + this._checkActionEnable() + break + + case 'readonly': + case 'disabled': + var k = name + if (k === 'readonly') { + k = 'readOnly' + } + this[k] = true + break + } + } +} + if(!customElements.get('wc-number')){ customElements.define('wc-number', Number) diff --git a/src/lib/form/progress.js b/src/lib/form/progress.js index b36397e..7e8128a 100644 --- a/src/lib/form/progress.js +++ b/src/lib/form/progress.js @@ -1,14 +1,162 @@ /** * * @authors yutent (yutent.io@gmail.com) - * @date 2020-07-22 19:57:05 - * @version v2.0.1 + * @date 2020-12-08 11:30:52 + * @version v1.0.0 * */ -'use strict' -export default class Progress extends HTMLElement{static get observedAttributes(){return["value","max"]}constructor(){super(),Object.defineProperty(this,"root",{value:this.attachShadow({mode:"open"}),writable:!0,enumerable:!1,configurable:!0}),Object.defineProperty(this,"props",{value:{value:0,max:1},writable:!0,enumerable:!1,configurable:!0}),this.root.innerHTML=" ",this.__THUMB__=this.root.children[1].lastElementChild}get value(){return this.props.value}set value(e){this.props.value=+e,this.calculate()}calculate(){var{max:e,value:a}=this.props;this.__THUMB__.style.width=`${100*a/e}%`}connectedCallback(){this.calculate()}attributeChangedCallback(e,a,l){if(null!==l&&a!==l)switch(e){case"max":var t=+l;(t!=t||t<1)&&(t=1),this.props.max=t,this.calculate();break;case"value":var r=+l;r==r&&(this.props.value=r,this.calculate())}}}; +export default class Progress extends HTMLElement { + + + static get observedAttributes() { + return ["value","max"] + } + + props = { + value: 0, + max: 1 + } + + + constructor() { + super(); + + Object.defineProperty(this, 'root', { + value: this.attachShadow({ mode: 'open' }), + writable: true, + enumerable: false, + configurable: true + }) + + this.root.innerHTML = ` + +` + + this.__THUMB__ = this.root.children[1].lastElementChild + } + + get value() { + return this.props.value + } + + set value(val) { + this.props.value = +val + this.calculate() + } + + calculate() { + var { max, value } = this.props + this.__THUMB__.style.width = `${(100 * value) / max}%` + } + + connectedCallback() { + this.calculate() + } + + attributeChangedCallback(name, old, val) { +if (val === null || old === val) {return} + switch (name) { + case 'max': + var max = +val + if (max !== max || max < 1) { + max = 1 + } + this.props.max = max + this.calculate() + break + + case 'value': + var v = +val + if (v === v) { + this.props.value = v + this.calculate() + } + break + } + } +} + if(!customElements.get('wc-progress')){ customElements.define('wc-progress', Progress) diff --git a/src/lib/form/radio-item.js b/src/lib/form/radio-item.js new file mode 100644 index 0000000..af33309 --- /dev/null +++ b/src/lib/form/radio-item.js @@ -0,0 +1,308 @@ +/** + * + * @authors yutent (yutent.io@gmail.com) + * @date 2020-12-08 11:30:52 + * @version v1.0.0 + * + */ + + +import $ from "../utils.js" + +export default class RadioItem extends HTMLElement { + + + static get observedAttributes() { + return ["value","checked","readonly","disabled"] + } + + props = { + value: '', + checked: false, + readonly: false, + disabled: false + } + + constructor() { + super(); + + Object.defineProperty(this, 'root', { + value: this.attachShadow({ mode: 'open' }), + writable: true, + enumerable: false, + configurable: true + }) + + this.root.innerHTML = ` + +` + + + this.__SWITCH__ = this.root.lastElementChild + } + + get value() { + return this.props.value + } + + set value(val) { + this.props.value = val + } + + get checked() { + return this.props.checked + } + + set checked(val) { + this.props.checked = !!val + this.__SWITCH__.classList.toggle('checked', this.props.checked) + } + + get readOnly() { + return this.props.readonly + } + + set readOnly(val) { + var type = typeof val + + if (val === this.props.readonly) { + return + } + if ((type === 'boolean' && val) || type !== 'boolean') { + this.props.readonly = true + this.setAttribute('readonly', '') + } else { + this.props.readonly = false + this.removeAttribute('readonly') + } + } + + get disabled() { + return this.props.disabled + } + + set disabled(val) { + var type = typeof val + + if (val === this.props.disabled) { + return + } + if ((type === 'boolean' && val) || type !== 'boolean') { + this.props.disabled = true + this.setAttribute('disabled', '') + } else { + this.props.disabled = false + this.removeAttribute('disabled') + } + } + + connectedCallback() { + if (this.value === this.parentNode.value) { + this.checked = true + } + + this._handleClick = $.catch(this, 'click', ev => { + if (this.disabled || this.readOnly || this.checked) { + return + } + + this.parentNode.dispatchEvent( + new CustomEvent('child-picked', { detail: this.value }) + ) + }) + } + + disconnectedCallback() { + $.unbind(this, 'click', this._handleClick) + } + + attributeChangedCallback(name, old, val) { +if (val === null || old === val) {return} + switch (name) { + case 'value': + this.value = val + break + + case 'checked': + case 'readonly': + case 'disabled': + var k = name + if (k === 'readonly') { + k = 'readOnly' + } + this[k] = true + break + } + } +} + + +if(!customElements.get('wc-radio-item')){ + customElements.define('wc-radio-item', RadioItem) +} diff --git a/src/lib/form/radio.js b/src/lib/form/radio.js index 4369942..b541f48 100644 --- a/src/lib/form/radio.js +++ b/src/lib/form/radio.js @@ -1,14 +1,129 @@ /** * * @authors yutent (yutent.io@gmail.com) - * @date 2020-07-22 19:57:05 - * @version v2.0.1 + * @date 2020-12-08 11:30:52 + * @version v1.0.0 * */ -'use strict' -import $ from"../utils.js";export default class Radio extends HTMLElement{static get observedAttributes(){return["label","checked","readonly","disabled"]}constructor(){super(),Object.defineProperty(this,"root",{value:this.attachShadow({mode:"open"}),writable:!0,enumerable:!1,configurable:!0}),Object.defineProperty(this,"props",{value:{label:"",checked:!1,readonly:!1,disabled:!1},writable:!0,enumerable:!1,configurable:!0}),this.root.innerHTML=" ",this.__SWITCH__=this.root.lastElementChild}get value(){return this.props.label}set value(e){this.checked=this.props.label===e}get checked(){return this.props.checked}set checked(e){this.props.checked=!!e,this.__SWITCH__.classList.toggle("checked",this.props.checked)}get readOnly(){return this.props.readonly}set readOnly(e){var o=typeof e;e!==this.props.readonly&&("boolean"===o&&e||"boolean"!==o?(this.props.readonly=!0,this.setAttribute("readonly","")):(this.props.readonly=!1,this.removeAttribute("readonly")))}get disabled(){return this.props.disabled}set disabled(e){var o=typeof e;e!==this.props.disabled&&("boolean"===o&&e||"boolean"!==o?(this.props.disabled=!0,this.setAttribute("disabled","")):(this.props.disabled=!1,this.removeAttribute("disabled")))}connectedCallback(){this._handleClick=$.catch(this,"click",e=>{this.disabled||this.readOnly||this.checked||(this.checked=!0,this.dispatchEvent(new CustomEvent("input")))})}disconnectedCallback(){$.unbind(this,"click",this._handleClick)}attributeChangedCallback(e,o,t){if(null!==t&&o!==t)switch(e){case"label":this.props.label=t;break;case"checked":case"readonly":case"disabled":var l=e;"readonly"===l&&(l="readOnly"),this[l]=!0}}}; +import $ from "../utils.js" +import "./radio-item.js" + +export default class Radio extends HTMLElement { + + + static get observedAttributes() { + return ["value"] + } + + props = { + value: null + } + + + constructor() { + super(); + + Object.defineProperty(this, 'root', { + value: this.attachShadow({ mode: 'open' }), + writable: true, + enumerable: false, + configurable: true + }) + + this.root.innerHTML = ` + +` + + } + + _updateChildrenStat() { + Array.from(this.children).forEach(it => { + if (it.tagName === 'WC-RADIO-ITEM' && it.root) { + if (it.value === this.props.value) { + it.checked = true + } else { + it.checked = false + } + } + }) + } + + get value() { + return this.props.value + } + + set value(val) { + if (val === this.props.value) { + return + } + this.props.value = val + this._updateChildrenStat() + } + + connectedCallback() { + this._pickedFn = $.bind(this, 'child-picked', ev => { + log('radio picked: ', ev.detail) + this.value = ev.detail + this.dispatchEvent(new CustomEvent('input')) + }) + } + + disconnectedCallback() { + $.unbind(this, 'child-picked', this._pickedFn) + } + + attributeChangedCallback(name, old, val) { +if (val === null || old === val) {return} + switch (name) { + case 'value': + this.value = val + break + } + } +} + if(!customElements.get('wc-radio')){ customElements.define('wc-radio', Radio) diff --git a/src/lib/form/select.js b/src/lib/form/select.js index a0c547e..c411c33 100644 --- a/src/lib/form/select.js +++ b/src/lib/form/select.js @@ -1,14 +1,558 @@ /** * * @authors yutent (yutent.io@gmail.com) - * @date 2020-07-22 19:57:05 - * @version v2.0.1 + * @date 2020-12-08 11:30:52 + * @version v1.0.0 * */ -'use strict' -import"../scroll/index.js";import"../icon/index.js";import $ from"../utils.js";function parseOptions(e,t){let i="";for(let s of e)if(s.list){i+=`
      ${s.name}
      `;for(let e of s.list)t.DICT[e.value]=e,e.disabled||t.LIST.push(e),i+=`
      ${e.label}
      `}else s.disabled||t.LIST.push(s),t.DICT[s.value]=s,i+=`
      ${s.label}
      `;return i}export default class Select extends HTMLElement{static get observedAttributes(){return["label","placeholder","multi","value","options","mvidx","readonly","disabled"]}constructor(){super(),Object.defineProperty(this,"root",{value:this.attachShadow({mode:"open"}),writable:!0,enumerable:!1,configurable:!0}),Object.defineProperty(this,"props",{value:{label:"",placeholder:"",multi:"",value:"",options:"",mvidx:null,readonly:!1,disabled:!1},writable:!0,enumerable:!1,configurable:!0}),this.root.innerHTML="
      ",this.__OUTER__=this.root.children[1],this.__PREPEND__=this.__OUTER__.children[0],this.__INPUT__=this.__OUTER__.children[1],this.__APPEND__=this.__OUTER__.children[3],this.__OPTG__=this.__OUTER__.children[4]}get readOnly(){return this.props.readonly}set readOnly(e){var t=typeof e;e!==this.props.readonly&&("boolean"===t&&e||"boolean"!==t?(this.props.readonly=!0,this.setAttribute("readonly","")):(this.props.readonly=!1,this.removeAttribute("readonly")))}get disabled(){return this.props.disabled}set disabled(e){var t=typeof e;e!==this.props.disabled&&("boolean"===t&&e||"boolean"!==t?(this.props.disabled=!0,this.setAttribute("disabled",""),this.__INPUT__.setAttribute("disabled","")):(this.props.disabled=!1,this.removeAttribute("disabled"),this.__INPUT__.removeAttribute("disabled")))}get value(){return this.props.value}set value(e){var{DICT:t,active:i}=this.props;this.props.value=e,this.__INPUT__.value=t&&t[e]&&t[e].label||e,i||this._updateStyle()}_renderOptions(e){this.props.DICT={},this.props.LIST=[];var t=this.__OPTG__.firstElementChild.firstElementChild;t.innerHTML=parseOptions(e,this.props),this.props.ITEMS=Array.from(t.children).filter(e=>"DD"===e.tagName&&!e.hasAttribute("disabled")),this.value=this.props.value}_moveSelect(e){var{LIST:t,DICT:i,ITEMS:s}=this.props;if(t&&t.length){e.preventDefault();var o=38===e.keyCode?-1:1;null===this.props.mvidx?this.props.mvidx=0:this.props.mvidx+=o,this.props.mvidx<0?this.props.mvidx=0:this.props.mvidx>s.length-1&&(this.props.mvidx=s.length-1),s.forEach((e,t)=>{t===this.props.mvidx?(this.__OPTG__.firstElementChild.scrollTop=e.offsetTop-150,e.setAttribute("focus","")):e.removeAttribute("focus")})}}_updateStyle(e){var{LIST:t,ITEMS:i,value:s}=this.props;if(t&&t.length){if(void 0===e)for(let i,o=-1;i=t[++o];)if(s===i.value){e=o;break}this.props.mvidx=e,i.forEach((t,i)=>{i===e?t.setAttribute("focus",""):t.removeAttribute("focus")})}}_fetchSelect(e,t){var i=this.props.LIST[e];this.value=i.value,this.dispatchEvent(new CustomEvent("select",{detail:i})),t&&this._updateStyle(e),this.props.active=!1,this.__OPTG__.classList.remove("show")}connectedCallback(){for(var e=this.__PREPEND__.assignedNodes(),t=this.__APPEND__.assignedNodes();e.length>1;)this.removeChild(e.pop());for(;t.length>1;)this.removeChild(t.pop());function i(){var{x:e,y:t,width:i}=this.getBoundingClientRect(),s=this.getAttribute("size");this.props.active=!0,t+=s&&"mini"===s?32:50,this.__OPTG__.style.cssText=`left:${e}px;top:${t}px;width:${i}px;`}e.length&&"textarea"!==this.props.type&&this.__OUTER__.setAttribute("prepend",""),t.length&&"textarea"!==this.props.type&&this.__OUTER__.setAttribute("append",""),this._handleKeydown=$.catch(this.__INPUT__,"keydown",e=>{if(!this.disabled&&!this.readOnly)return 38===e.keyCode||40===e.keyCode?this.props.active?this._moveSelect(e):(i.call(this),void this.__OPTG__.classList.toggle("show",!0)):13===e.keyCode&&null!==this.props.mvidx&&this.props.active?this._fetchSelect(this.props.mvidx):void 0}),this._activeFn=$.bind(this.__INPUT__,"click",e=>{var{options:t}=this.props;this.disabled||this.readOnly||(i.call(this),this.__OPTG__.classList.toggle("show"))}),this._handleSelect=$.bind(this.__OPTG__,"click",e=>{"DD"!==e.target.tagName||e.target.hasAttribute("disabled")||(this._fetchSelect(+e.target.dataset.idx,!0),this.dispatchEvent(new CustomEvent("input")))}),this._inactiveFn=$.outside(this,e=>{this.__OPTG__.classList.toggle("show",!1),this.props.active=!1})}attributeChangedCallback(e,t,i){if(null!==i&&t!==i)switch(e){case"label":case"placeholder":this.__INPUT__.setAttribute("placeholder",i);break;case"options":if(i){try{this._renderOptions(JSON.parse(i))}catch(e){}this.removeAttribute("options")}break;case"value":this.value=i;break;case"readonly":case"disabled":var s=e;"readonly"===s&&(s="readOnly"),this[s]=!0}}disconnectedCallback(){$.unbind(this.__INPUT__,"keydown",this._handleKeydown),$.unbind(this.__INPUT__,"click",this._activeFn),$.unbind(this.__OPTG__,"click",this._handleSelect),$.clearOutside(this._inactiveFn)}}; +import "../scroll/index.js" +import "../icon/index.js" +import $ from "../utils.js" + +function parseOptions(arr, props) { + let html = '' + for (let it of arr) { + if (it.list) { + html += `
      ${it.name}
      ` + for (let _ of it.list) { + props.DICT[_.value] = _ + if (!_.disabled) { + props.LIST.push(_) + } + html += `
      ${_.label}
      ` + } + } else { + if (!it.disabled) { + props.LIST.push(it) + } + props.DICT[it.value] = it + html += `
      ${it.label}
      ` + } + } + return html +} + +export default class Select extends HTMLElement { + + + static get observedAttributes() { + return ["label","placeholder","multi","value","options","mvidx","readonly","disabled"] + } + + props = { + label: '', + placeholder: '', + multi: '', + value: '', + options: '', + mvidx: null, //下拉列表光标的索引ID + readonly: false, + disabled: false + } + + + constructor() { + super(); + + Object.defineProperty(this, 'root', { + value: this.attachShadow({ mode: 'open' }), + writable: true, + enumerable: false, + configurable: true + }) + + this.root.innerHTML = ` +
      + + + + +
      + +
      +
      +
      +
      +` + + + this.__OUTER__ = this.root.children[1] + this.__PREPEND__ = this.__OUTER__.children[0] + this.__INPUT__ = this.__OUTER__.children[1] + this.__APPEND__ = this.__OUTER__.children[3] + this.__OPTG__ = this.__OUTER__.children[4] + } + + get readOnly() { + return this.props.readonly + } + + set readOnly(val) { + var type = typeof val + + if (val === this.props.readonly) { + return + } + if ((type === 'boolean' && val) || type !== 'boolean') { + this.props.readonly = true + this.setAttribute('readonly', '') + } else { + this.props.readonly = false + this.removeAttribute('readonly') + } + } + + get disabled() { + return this.props.disabled + } + + set disabled(val) { + var type = typeof val + + if (val === this.props.disabled) { + return + } + if ((type === 'boolean' && val) || type !== 'boolean') { + this.props.disabled = true + this.setAttribute('disabled', '') + this.__INPUT__.setAttribute('disabled', '') + } else { + this.props.disabled = false + this.removeAttribute('disabled') + this.__INPUT__.removeAttribute('disabled') + } + } + + get value() { + return this.props.value + } + + set value(val) { + var { DICT, active } = this.props + this.props.value = val + this.__INPUT__.value = (DICT && DICT[val] && DICT[val].label) || val + if (!active) { + this._updateStyle() + } + } + + _renderOptions(options) { + this.props.DICT = {} + this.props.LIST = [] + var elem = this.__OPTG__.firstElementChild.firstElementChild + + elem.innerHTML = parseOptions(options, this.props) + this.props.ITEMS = Array.from(elem.children).filter(it => { + return it.tagName === 'DD' && !it.hasAttribute('disabled') + }) + this.value = this.props.value + } + + // 移动光标选择下拉选项 + _moveSelect(ev) { + var { LIST, DICT, ITEMS } = this.props + if (LIST && LIST.length) { + ev.preventDefault() + var step = ev.keyCode === 38 ? -1 : 1 + + if (this.props.mvidx === null) { + this.props.mvidx = 0 + } else { + this.props.mvidx += step + } + if (this.props.mvidx < 0) { + this.props.mvidx = 0 + } else if (this.props.mvidx > ITEMS.length - 1) { + this.props.mvidx = ITEMS.length - 1 + } + + ITEMS.forEach((it, i) => { + if (i === this.props.mvidx) { + this.__OPTG__.firstElementChild.scrollTop = it.offsetTop - 150 + it.setAttribute('focus', '') + } else { + it.removeAttribute('focus') + } + }) + } + } + + _updateStyle(idx) { + var { LIST, ITEMS, value } = this.props + if (LIST && LIST.length) { + if (idx === undefined) { + for (let i = -1, it; (it = LIST[++i]); ) { + if (value === it.value) { + idx = i + break + } + } + } + this.props.mvidx = idx + ITEMS.forEach((it, i) => { + if (i === idx) { + it.setAttribute('focus', '') + } else { + it.removeAttribute('focus') + } + }) + } + } + + // 触发列表选择 + _fetchSelect(idx, needUpdateStyle) { + var item = this.props.LIST[idx] + this.value = item.value + this.dispatchEvent( + new CustomEvent('select', { + detail: item + }) + ) + if (needUpdateStyle) { + this._updateStyle(idx) + } + this.props.active = false + this.__OPTG__.classList.remove('show') + } + + connectedCallback() { + var prepend = this.__PREPEND__.assignedNodes() + var append = this.__APPEND__.assignedNodes() + + // 相同插槽, 只允许1个 + while (prepend.length > 1) { + this.removeChild(prepend.pop()) + } + while (append.length > 1) { + this.removeChild(append.pop()) + } + + if (prepend.length && this.props.type !== 'textarea') { + this.__OUTER__.setAttribute('prepend', '') + } + if (append.length && this.props.type !== 'textarea') { + this.__OUTER__.setAttribute('append', '') + } + + function initPos() { + var { x, y, width } = this.getBoundingClientRect() + var size = this.getAttribute('size') + this.props.active = true + if (size && size === 'mini') { + y += 32 + } else { + y += 50 + } + this.__OPTG__.style.cssText = `left:${x}px;top:${y}px;width:${width}px;` + } + + /* ---------------------------------------------------- */ + /* ----------------- 各种事件 ------------------ */ + /* ---------------------------------------------------- */ + + // 键盘事件 + this._handleKeydown = $.catch(this.__INPUT__, 'keydown', ev => { + if (this.disabled || this.readOnly) { + return + } + // up: 38, down: 40 + if (ev.keyCode === 38 || ev.keyCode === 40) { + if (!this.props.active) { + initPos.call(this) + this.__OPTG__.classList.toggle('show', true) + return + } + return this._moveSelect(ev) + } + // 回车触发select事件 + if (ev.keyCode === 13) { + if (this.props.mvidx !== null && this.props.active) { + return this._fetchSelect(this.props.mvidx) + } + } + }) + + // 渲染列表 + this._activeFn = $.bind(this.__INPUT__, 'click', ev => { + var { options } = this.props + + if (this.disabled || this.readOnly) { + return + } + + initPos.call(this) + this.__OPTG__.classList.toggle('show') + }) + + // 选择选项 + this._handleSelect = $.bind(this.__OPTG__, 'click', ev => { + if (ev.target.tagName === 'DD' && !ev.target.hasAttribute('disabled')) { + this._fetchSelect(+ev.target.dataset.idx, true) + this.dispatchEvent(new CustomEvent('input')) + } + }) + + this._inactiveFn = $.outside(this, ev => { + this.__OPTG__.classList.toggle('show', false) + this.props.active = false + }) + } + + attributeChangedCallback(name, old, val) { +if (val === null || old === val) {return} + switch (name) { + // label和placeholder 功能相同 + case 'label': + case 'placeholder': + this.__INPUT__.setAttribute('placeholder', val) + break + + case 'options': + if (val) { + try { + this._renderOptions(JSON.parse(val)) + } catch (err) {} + this.removeAttribute('options') + } + break + + case 'value': + this.value = val + break + + case 'readonly': + case 'disabled': + var k = name + if (k === 'readonly') { + k = 'readOnly' + } + this[k] = true + break + } + } + + disconnectedCallback() { + $.unbind(this.__INPUT__, 'keydown', this._handleKeydown) + $.unbind(this.__INPUT__, 'click', this._activeFn) + $.unbind(this.__OPTG__, 'click', this._handleSelect) + $.clearOutside(this._inactiveFn) + } +} + if(!customElements.get('wc-select')){ customElements.define('wc-select', Select) diff --git a/src/lib/form/star.js b/src/lib/form/star.js index cf252ba..c9a93ac 100644 --- a/src/lib/form/star.js +++ b/src/lib/form/star.js @@ -1,14 +1,300 @@ /** * * @authors yutent (yutent.io@gmail.com) - * @date 2020-07-22 19:57:05 - * @version v2.0.1 + * @date 2020-12-08 11:30:52 + * @version v1.0.0 * */ -'use strict' -import $ from"../utils.js";export default class Star extends HTMLElement{static get observedAttributes(){return["value","text","size","color","allow-half","show-value","starSize","disabled"]}constructor(){super(),Object.defineProperty(this,"root",{value:this.attachShadow({mode:"open"}),writable:!0,enumerable:!1,configurable:!0}),Object.defineProperty(this,"props",{value:{value:0,text:[],size:"",color:"","allow-half":!1,"show-value":!1,starSize:32,disabled:!1},writable:!0,enumerable:!1,configurable:!0}),this.root.innerHTML=' ',this.__BOX__=this.root.children[1],this.__STARS__=Array.from(this.__BOX__.children),this.__TEXT__=this.__STARS__.pop()}get value(){return this.props.value}set value(t){var e=+t;(t=e==e&&e>0?e:0)>5&&(t=5),this.props.value=t,this._updateDraw(-1)}_updateDraw(t,e=0){var s="star-half",{value:o,tmp:a={i:0,f:0}}=this.props;-1===t&&(t=Math.floor(o),e=+(o%1).toFixed(1),t>0&&t===o&&(t--,e=1)),this.props["allow-half"]||(e=e>0?1:0),t===a.i&&e===a.f||(e>.5&&(s="star-full"),this.__STARS__.forEach((e,s)=>{e.setAttribute("is",s0&&(this.__STARS__[t].setAttribute("is",s),this.__STARS__[t].setAttribute("color",this.props.color)),this.props.tmp={i:t,f:e},0===t&&0===e?this.__TEXT__.textContent="":5===this.props.text.length?this.__TEXT__.textContent=this.props.text[t]:this.props["show-value"]&&(this.__TEXT__.textContent=t+e))}connectedCallback(){$.catch(this.__BOX__,"mousemove",t=>{if(!this.props.disabled&&"WC-ICON"===t.target.tagName){let e=+t.target.dataset.idx;this._updateDraw(e,+(t.offsetX/this.props.starSize).toFixed(1))}}),$.catch(this.__BOX__,"click",t=>{var{tmp:e,disabled:s}=this.props;s||"WC-ICON"===t.target.tagName&&(this.props.value=e.i+e.f,this.dispatchEvent(new CustomEvent("input")))}),$.catch(this.__BOX__,"mouseleave",t=>{this.props.disabled||this._updateDraw(-1)})}attributeChangedCallback(t,e,s){if(null!==s&&e!==s)switch(t){case"size":this.props.starSize=this.__STARS__[0].clientWidth;break;case"allow-half":case"show-value":case"disabled":this.props[t]=!0;break;case"color":s&&(this.props.color=s);break;case"text":s&&5===(s=s.split("|")).length&&(this.props.text=s.map(t=>t.trim()));break;case"value":this.value=s}}}; +import $ from "../utils.js" + +export default class Star extends HTMLElement { + + + static get observedAttributes() { + return ["value","text","size","color","'allow-half'","'show-value'","starSize","disabled"] + } + + props = { + value: 0, + text: [], + size: '', + color: '', + 'allow-half': false, + 'show-value': false, + starSize: 32, // 星星的宽度, 用于实现半星 + disabled: false + } + + constructor() { + super(); + + Object.defineProperty(this, 'root', { + value: this.attachShadow({ mode: 'open' }), + writable: true, + enumerable: false, + configurable: true + }) + + this.root.innerHTML = ` + +` + + + this.__BOX__ = this.root.children[1] + this.__STARS__ = Array.from(this.__BOX__.children) + this.__TEXT__ = this.__STARS__.pop() + } + + get value() { + return this.props.value + } + + set value(val) { + var v = +val + var tmp = val >> 0 + if (v === v && v > 0) { + val = v + } else { + val = 0 + } + + if (val > 5) { + val = 5 + } + + this.props.value = val + this._updateDraw(-1) + } + + /** + * 更新图标渲染 + * i: int + * f: float + */ + _updateDraw(i, f = 0) { + var _last = 'star-half' + var { value, tmp = { i: 0, f: 0 } } = this.props + + if (i === -1) { + i = Math.floor(value) + f = +(value % 1).toFixed(1) + if (i > 0 && i === value) { + i-- + f = 1 + } + } + + if (!this.props['allow-half']) { + f = f > 0 ? 1 : 0 + } + // 减少DOM操作 + if (i === tmp.i && f === tmp.f) { + return + } + + if (f > 0.5) { + _last = 'star-full' + } + + this.__STARS__.forEach((it, k) => { + it.setAttribute('is', k < i ? 'star-full' : 'star') + it.setAttribute('color', k < i ? this.props.color : 'grey') + }) + + if (f > 0) { + this.__STARS__[i].setAttribute('is', _last) + this.__STARS__[i].setAttribute('color', this.props.color) + } + + // 缓存结果 + this.props.tmp = { i, f } + + if (i === 0 && f === 0) { + this.__TEXT__.textContent = '' + } else { + if (this.props.text.length === 5) { + this.__TEXT__.textContent = this.props.text[i] + } else { + if (this.props['show-value']) { + this.__TEXT__.textContent = i + f + } + } + } + } + + connectedCallback() { + $.catch(this.__BOX__, 'mousemove', ev => { + if (this.props.disabled) { + return + } + if (ev.target.tagName === 'WC-ICON') { + let idx = +ev.target.dataset.idx + this._updateDraw(idx, +(ev.offsetX / this.props.starSize).toFixed(1)) + } + }) + + $.catch(this.__BOX__, 'click', ev => { + var { tmp, disabled } = this.props + if (disabled) { + return + } + if (ev.target.tagName === 'WC-ICON') { + this.props.value = tmp.i + tmp.f + this.dispatchEvent(new CustomEvent('input')) + } + }) + + $.catch(this.__BOX__, 'mouseleave', ev => { + if (this.props.disabled) { + return + } + this._updateDraw(-1) + }) + } + + attributeChangedCallback(name, old, val) { +if (val === null || old === val) {return} + switch (name) { + case 'size': + this.props.starSize = this.__STARS__[0].clientWidth + break + + case 'allow-half': + case 'show-value': + case 'disabled': + this.props[name] = true + break + + case 'color': + if (val) { + this.props.color = val + } + break + + case 'text': + if (val) { + val = val.split('|') + if (val.length === 5) { + this.props.text = val.map(it => it.trim()) + } + } + break + + case 'value': + this.value = val + break + } + } +} + if(!customElements.get('wc-star')){ customElements.define('wc-star', Star) diff --git a/src/lib/form/switch.js b/src/lib/form/switch.js index 5d2dc55..9288822 100644 --- a/src/lib/form/switch.js +++ b/src/lib/form/switch.js @@ -1,14 +1,240 @@ /** * * @authors yutent (yutent.io@gmail.com) - * @date 2020-07-22 19:57:05 - * @version v2.0.1 + * @date 2020-12-08 11:30:52 + * @version v1.0.0 * */ -'use strict' -import $ from"../utils.js";export default class Switch extends HTMLElement{static get observedAttributes(){return["active-text","inactive-text","checked","disabled"]}constructor(){super(),Object.defineProperty(this,"root",{value:this.attachShadow({mode:"open"}),writable:!0,enumerable:!1,configurable:!0}),Object.defineProperty(this,"props",{value:{"active-text":null,"inactive-text":null,checked:!1,disabled:!1},writable:!0,enumerable:!1,configurable:!0}),this.root.innerHTML="
      ",this.__SWITCH__=this.root.lastElementChild.firstElementChild}get value(){return this.props.checked}set value(e){this.checked=e}get checked(){return this.props.checked}set checked(e){this.props.checked=!!e,this.__SWITCH__.classList.toggle("checked",this.props.checked)}get disabled(){return this.props.disabled}set disabled(e){var t=typeof e;e!==this.props.disabled&&("boolean"===t&&e||"boolean"!==t?(this.props.disabled=!0,this.setAttribute("disabled","")):(this.props.disabled=!1,this.removeAttribute("disabled")))}connectedCallback(){this._handleClick=$.bind(this,"click",e=>{this.disabled||(this.checked=!this.checked,this.checked?null!==this.props["active-text"]&&(this.textContent=this.props["active-text"]):null!==this.props["inactive-text"]&&(this.textContent=this.props["inactive-text"]),this.dispatchEvent(new CustomEvent("input")))})}disconnectedCallback(){$.unbind(this,"click",this._handleClick)}attributeChangedCallback(e,t,i){if(null!==i&&t!==i)switch(e){case"checked":case"disabled":this[e]=!0;break;case"active-text":case"inactive-text":this.props[e]=i+""}}}; +import $ from "../utils.js" +export default class Switch extends HTMLElement { + + + static get observedAttributes() { + return ["'active-text'","'inactive-text'","checked","disabled"] + } + + props = { + 'active-text': null, + 'inactive-text': null, + checked: false, + disabled: false + } + + constructor() { + super(); + + Object.defineProperty(this, 'root', { + value: this.attachShadow({ mode: 'open' }), + writable: true, + enumerable: false, + configurable: true + }) + + this.root.innerHTML = ` +
      + + +
      +` + + + this.__SWITCH__ = this.root.lastElementChild.firstElementChild + } + + get value() { + return this.props.checked + } + + set value(val) { + this.checked = val + } + + get checked() { + return this.props.checked + } + + set checked(val) { + this.props.checked = !!val + this.__SWITCH__.classList.toggle('checked', this.props.checked) + } + + get disabled() { + return this.props.disabled + } + + set disabled(val) { + var type = typeof val + + if (val === this.props.disabled) { + return + } + if ((type === 'boolean' && val) || type !== 'boolean') { + this.props.disabled = true + this.setAttribute('disabled', '') + } else { + this.props.disabled = false + this.removeAttribute('disabled') + } + } + + connectedCallback() { + this._handleClick = $.bind(this, 'click', ev => { + if (this.disabled) { + return + } + this.checked = !this.checked + if (this.checked) { + if (this.props['active-text'] !== null) { + this.textContent = this.props['active-text'] + } + } else { + if (this.props['inactive-text'] !== null) { + this.textContent = this.props['inactive-text'] + } + } + this.dispatchEvent(new CustomEvent('input')) + }) + } + + disconnectedCallback() { + $.unbind(this, 'click', this._handleClick) + } + + attributeChangedCallback(name, old, val) { +if (val === null || old === val) {return} + switch (name) { + case 'checked': + case 'disabled': + this[name] = true + break + case 'active-text': + case 'inactive-text': + this.props[name] = val + '' + break + } + } +} + if(!customElements.get('wc-switch')){ customElements.define('wc-switch', Switch) diff --git a/src/tools/window.js b/src/tools/window.js index 059ac1b..e0e6148 100644 --- a/src/tools/window.js +++ b/src/tools/window.js @@ -15,8 +15,8 @@ const createTay = require('./tray') exports.createMainWindow = function(icon) { var win = new BrowserWindow({ title: '搞基数据', - width: 820, - height: 460, + width: 1024, + height: 540, frame: false, titleBarStyle: 'hiddenInset', resizable: false, @@ -44,10 +44,10 @@ exports.createMainWindow = function(icon) { createMenu(win) - // win.on('ready-to-show', _ => { - // win.show() - // win.openDevTools() - // }) + win.on('ready-to-show', _ => { + win.show() + win.openDevTools() + }) win.on('close', ev => { ev.preventDefault() diff --git a/test.js b/test.js index 1528036..d1840d5 100644 --- a/test.js +++ b/test.js @@ -1,4 +1,4 @@ -/** * 测试数据 * @type {arry} */ /*2020-12-09 15:31:17*/ var ishb = false +/** * 测试数据 * @type {arry} */ /*2020-12-11 16:09:21*/ var ishb = false /*基金或股票信息*/ var fS_name = '招商中证白酒指数分级' var fS_code = '161725' /*原费率*/ var fund_sourceRate = '1.00' @@ -30,13 +30,11 @@ var fS_code = '161725' '1.603589' ] /*基金持仓债券代码(新市场号)*/ var zqCodesNew = '1.019627,1.019640' -/*收益率*/ /*近一年收益率*/ var syl_1n = '88.41' -/*近6月收益率*/ var syl_6y = '63.33' -/*近三月收益率*/ var syl_3y = '23.86' -/*近一月收益率*/ var syl_1y = '8.48' +/*收益率*/ /*近一年收益率*/ var syl_1n = '90.15' +/*近6月收益率*/ var syl_6y = '62.1' +/*近三月收益率*/ var syl_3y = '24.91' +/*近一月收益率*/ var syl_1y = '4.61' /*股票仓位测算图*/ var Data_fundSharesPositions = [ - [1604851200000, 95.0], - [1604937600000, 95.0], [1605024000000, 95.0], [1605110400000, 95.0], [1605196800000, 95.0], @@ -56,7 +54,9 @@ var fS_code = '161725' [1606924800000, 79.06], [1607011200000, 85.65], [1607270400000, 95.75], - [1607356800000, 96.65] + [1607356800000, 96.65], + [1607443200000, 78.09], + [1607529600000, 77.79] ] /*单位净值走势 equityReturn-净值回报 unitMoney-每份派送金*/ var Data_netWorthTrend = [ { x: 1432656000000, y: 1.0, equityReturn: 0, unitMoney: '' }, @@ -1449,7 +1449,9 @@ var fS_code = '161725' { x: 1606924800000, y: 1.1684, equityReturn: 0.99, unitMoney: '' }, { x: 1607011200000, y: 1.2081, equityReturn: 3.4, unitMoney: '' }, { x: 1607270400000, y: 1.212, equityReturn: 0.32, unitMoney: '' }, - { x: 1607356800000, y: 1.2305, equityReturn: 1.53, unitMoney: '' } + { x: 1607356800000, y: 1.2305, equityReturn: 1.53, unitMoney: '' }, + { x: 1607443200000, y: 1.2249, equityReturn: -0.46, unitMoney: '' }, + { x: 1607529600000, y: 1.2352, equityReturn: 0.84, unitMoney: '' } ] /*累计净值走势*/ var Data_ACWorthTrend = [ [1432656000000, 1.0], @@ -2802,394 +2804,396 @@ var fS_code = '161725' [1606924800000, 2.7926], [1607011200000, 2.8323], [1607270400000, 2.8362], - [1607356800000, 2.8547] + [1607356800000, 2.8547], + [1607443200000, 2.8491], + [1607529600000, 2.8594] ] /*累计收益率走势*/ var Data_grandTotal = [ { name: '招商中证白酒指数分级', data: [ - [1591545600000, 0], - [1591632000000, 0.74], - [1591718400000, 1.14], - [1591804800000, -0.52], - [1591891200000, -0.22], - [1592150400000, -2.91], - [1592236800000, -1.31], - [1592323200000, -2.25], - [1592409600000, -1.97], - [1592496000000, 0.38], - [1592755200000, -0.35], - [1592841600000, 2.85], - [1592928000000, 2.67], - [1593360000000, 3.03], - [1593446400000, 4.67], - [1593532800000, 10.69], - [1593619200000, 14.54], - [1593705600000, 13.41], - [1593964800000, 16.18], - [1594051200000, 19.69], - [1594137600000, 19.54], - [1594224000000, 21.37], - [1594310400000, 22.94], - [1594569600000, 28.32], - [1594656000000, 28.66], - [1594742400000, 31.49], - [1594828800000, 20.07], - [1594915200000, 19.93], - [1595174400000, 18.59], - [1595260800000, 21.36], - [1595347200000, 22.93], - [1595433600000, 23.27], - [1595520000000, 17.68], - [1595779200000, 19.08], - [1595865600000, 22.05], - [1595952000000, 22.79], - [1596038400000, 23.66], - [1596124800000, 23.5], - [1596384000000, 23.61], - [1596470400000, 23.01], - [1596556800000, 23.33], - [1596643200000, 20.16], - [1596729600000, 18.76], - [1596988800000, 18.91], - [1597075200000, 20.0], - [1597161600000, 17.87], - [1597248000000, 18.8], - [1597334400000, 22.88], - [1597593600000, 25.72], - [1597680000000, 26.46], - [1597766400000, 26.64], - [1597852800000, 23.81], - [1597939200000, 25.5], - [1598198400000, 28.08], - [1598284800000, 33.06], - [1598371200000, 32.73], - [1598457600000, 34.3], - [1598544000000, 39.64], - [1598803200000, 40.39], - [1598889600000, 38.8], - [1598976000000, 37.74], - [1599062400000, 40.61], - [1599148800000, 37.92], - [1599408000000, 35.63], - [1599494400000, 31.87], - [1599580800000, 29.24], - [1599667200000, 31.26], - [1599753600000, 34.95], - [1600012800000, 36.05], - [1600099200000, 35.81], - [1600185600000, 33.54], - [1600272000000, 30.42], - [1600358400000, 32.2], - [1600617600000, 30.2], - [1600704000000, 29.0], - [1600790400000, 28.37], - [1600876800000, 26.14], - [1600963200000, 26.18], - [1601222400000, 27.62], - [1601308800000, 27.36], - [1601395200000, 27.94], - [1602172800000, 29.8], - [1602432000000, 37.0], - [1602518400000, 39.32], - [1602604800000, 38.85], - [1602691200000, 38.69], - [1602777600000, 37.15], - [1603036800000, 36.11], - [1603123200000, 40.41], - [1603209600000, 40.86], - [1603296000000, 43.46], - [1603382400000, 39.81], - [1603641600000, 38.3], - [1603728000000, 39.56], - [1603814400000, 44.12], - [1603900800000, 48.21], - [1603987200000, 44.02], - [1604246400000, 46.42], - [1604332800000, 48.03], - [1604419200000, 48.74], - [1604505600000, 51.56], - [1604592000000, 50.56], - [1604851200000, 53.44], - [1604937600000, 56.73], - [1605024000000, 56.92], - [1605110400000, 59.67], - [1605196800000, 54.2], - [1605456000000, 60.18], - [1605542400000, 57.99], - [1605628800000, 55.43], - [1605715200000, 56.03], - [1605801600000, 58.35], - [1606060800000, 59.98], - [1606147200000, 60.94], - [1606233600000, 55.29], - [1606320000000, 56.07], - [1606406400000, 57.01], - [1606665600000, 52.29], - [1606752000000, 53.61], - [1606838400000, 53.56], - [1606924800000, 55.09], - [1607011200000, 60.36], - [1607270400000, 60.87], - [1607356800000, 63.33] + [1591718400000, 0], + [1591804800000, -1.65], + [1591891200000, -1.35], + [1592150400000, -4.0], + [1592236800000, -2.43], + [1592323200000, -3.35], + [1592409600000, -3.07], + [1592496000000, -0.75], + [1592755200000, -1.47], + [1592841600000, 1.69], + [1592928000000, 1.51], + [1593360000000, 1.87], + [1593446400000, 3.49], + [1593532800000, 9.44], + [1593619200000, 13.24], + [1593705600000, 12.13], + [1593964800000, 14.87], + [1594051200000, 18.33], + [1594137600000, 18.19], + [1594224000000, 20.0], + [1594310400000, 21.55], + [1594569600000, 26.87], + [1594656000000, 27.21], + [1594742400000, 30.0], + [1594828800000, 18.71], + [1594915200000, 18.57], + [1595174400000, 17.25], + [1595260800000, 19.99], + [1595347200000, 21.54], + [1595433600000, 21.88], + [1595520000000, 16.35], + [1595779200000, 17.73], + [1595865600000, 20.67], + [1595952000000, 21.4], + [1596038400000, 22.26], + [1596124800000, 22.1], + [1596384000000, 22.21], + [1596470400000, 21.62], + [1596556800000, 21.93], + [1596643200000, 18.8], + [1596729600000, 17.42], + [1596988800000, 17.56], + [1597075200000, 18.64], + [1597161600000, 16.54], + [1597248000000, 17.46], + [1597334400000, 21.49], + [1597593600000, 24.3], + [1597680000000, 25.04], + [1597766400000, 25.21], + [1597852800000, 22.41], + [1597939200000, 24.08], + [1598198400000, 26.63], + [1598284800000, 31.55], + [1598371200000, 31.23], + [1598457600000, 32.78], + [1598544000000, 38.06], + [1598803200000, 38.81], + [1598889600000, 37.23], + [1598976000000, 36.18], + [1599062400000, 39.02], + [1599148800000, 36.37], + [1599408000000, 34.1], + [1599494400000, 30.38], + [1599580800000, 27.78], + [1599667200000, 29.78], + [1599753600000, 33.43], + [1600012800000, 34.52], + [1600099200000, 34.28], + [1600185600000, 32.04], + [1600272000000, 28.95], + [1600358400000, 30.71], + [1600617600000, 28.73], + [1600704000000, 27.55], + [1600790400000, 26.92], + [1600876800000, 24.71], + [1600963200000, 24.75], + [1601222400000, 26.18], + [1601308800000, 25.92], + [1601395200000, 26.5], + [1602172800000, 28.33], + [1602432000000, 35.45], + [1602518400000, 37.74], + [1602604800000, 37.28], + [1602691200000, 37.13], + [1602777600000, 35.6], + [1603036800000, 34.57], + [1603123200000, 38.82], + [1603209600000, 39.27], + [1603296000000, 41.84], + [1603382400000, 38.23], + [1603641600000, 36.73], + [1603728000000, 37.98], + [1603814400000, 42.49], + [1603900800000, 46.54], + [1603987200000, 42.39], + [1604246400000, 44.76], + [1604332800000, 46.35], + [1604419200000, 47.06], + [1604505600000, 49.84], + [1604592000000, 48.86], + [1604851200000, 51.71], + [1604937600000, 54.96], + [1605024000000, 55.15], + [1605110400000, 57.86], + [1605196800000, 52.46], + [1605456000000, 58.37], + [1605542400000, 56.21], + [1605628800000, 53.68], + [1605715200000, 54.27], + [1605801600000, 56.56], + [1606060800000, 58.18], + [1606147200000, 59.12], + [1606233600000, 53.53], + [1606320000000, 54.31], + [1606406400000, 55.24], + [1606665600000, 50.57], + [1606752000000, 51.88], + [1606838400000, 51.83], + [1606924800000, 53.33], + [1607011200000, 58.54], + [1607270400000, 59.06], + [1607356800000, 61.48], + [1607443200000, 60.75], + [1607529600000, 62.1] ] }, { name: '同类平均', data: [ - [1591545600000, 0], - [1591632000000, 0.7], - [1591718400000, 0.81], - [1591804800000, 0.11], - [1591891200000, 0.23], - [1592150400000, -0.48], - [1592236800000, 1.16], - [1592323200000, 1.47], - [1592409600000, 1.88], - [1592496000000, 3.15], - [1592755200000, 3.41], - [1592841600000, 4.0], - [1592928000000, 4.28], - [1593360000000, 3.69], - [1593446400000, 5.26], - [1593532800000, 6.42], - [1593619200000, 8.29], - [1593705600000, 10.11], - [1593964800000, 15.27], - [1594051200000, 16.25], - [1594137600000, 18.44], - [1594224000000, 20.71], - [1594310400000, 19.45], - [1594569600000, 22.35], - [1594656000000, 21.28], - [1594742400000, 19.48], - [1594828800000, 14.51], - [1594915200000, 15.22], - [1595174400000, 18.36], - [1595260800000, 18.85], - [1595347200000, 19.6], - [1595433600000, 19.75], - [1595520000000, 14.5], - [1595779200000, 14.84], - [1595865600000, 15.88], - [1595952000000, 18.73], - [1596038400000, 18.21], - [1596124800000, 19.34], - [1596384000000, 21.61], - [1596470400000, 21.39], - [1596556800000, 21.94], - [1596643200000, 21.75], - [1596729600000, 20.34], - [1596988800000, 20.74], - [1597075200000, 19.43], - [1597161600000, 18.43], - [1597248000000, 18.35], - [1597334400000, 19.88], - [1597593600000, 22.25], - [1597680000000, 22.53], - [1597766400000, 20.54], - [1597852800000, 19.22], - [1597939200000, 20.18], - [1598198400000, 21.36], - [1598284800000, 21.25], - [1598371200000, 19.55], - [1598457600000, 20.33], - [1598544000000, 22.68], - [1598803200000, 21.99], - [1598889600000, 22.7], - [1598976000000, 22.72], - [1599062400000, 21.93], - [1599148800000, 21.02], - [1599408000000, 18.49], - [1599494400000, 19.05], - [1599580800000, 16.2], - [1599667200000, 15.33], - [1599753600000, 16.54], - [1600012800000, 17.21], - [1600099200000, 18.04], - [1600185600000, 17.34], - [1600272000000, 17.11], - [1600358400000, 19.24], - [1600617600000, 18.43], - [1600704000000, 17.24], - [1600790400000, 17.79], - [1600876800000, 15.54], - [1600963200000, 15.54], - [1601222400000, 15.43], - [1601308800000, 16.03], - [1601395200000, 15.94], - [1602172800000, 18.54], - [1602432000000, 21.8], - [1602518400000, 22.14], - [1602604800000, 21.43], - [1602691200000, 20.98], - [1602777600000, 20.82], - [1603036800000, 19.85], - [1603123200000, 20.81], - [1603209600000, 20.2], - [1603296000000, 19.7], - [1603382400000, 18.13], - [1603641600000, 17.98], - [1603728000000, 18.31], - [1603814400000, 18.97], - [1603900800000, 19.68], - [1603987200000, 17.63], - [1604246400000, 18.33], - [1604332800000, 19.87], - [1604419200000, 20.35], - [1604505600000, 22.25], - [1604592000000, 21.77], - [1604851200000, 24.12], - [1604937600000, 23.15], - [1605024000000, 21.73], - [1605110400000, 21.98], - [1605196800000, 21.27], - [1605456000000, 22.3], - [1605542400000, 21.65], - [1605628800000, 21.58], - [1605715200000, 22.26], - [1605801600000, 22.9], - [1606060800000, 24.01], - [1606147200000, 23.62], - [1606233600000, 21.83], - [1606320000000, 21.84], - [1606406400000, 22.86], - [1606665600000, 22.4], - [1606752000000, 24.66], - [1606838400000, 24.66], - [1606924800000, 24.58], - [1607011200000, 24.89], - [1607270400000, 24.04], - [1607356800000, 23.95] + [1591718400000, 0], + [1591804800000, -0.69], + [1591891200000, -0.57], + [1592150400000, -1.28], + [1592236800000, 0.35], + [1592323200000, 0.65], + [1592409600000, 1.07], + [1592496000000, 2.32], + [1592755200000, 2.58], + [1592841600000, 3.16], + [1592928000000, 3.45], + [1593360000000, 2.86], + [1593446400000, 4.42], + [1593532800000, 5.57], + [1593619200000, 7.43], + [1593705600000, 9.23], + [1593964800000, 14.35], + [1594051200000, 15.32], + [1594137600000, 17.49], + [1594224000000, 19.74], + [1594310400000, 18.49], + [1594569600000, 21.37], + [1594656000000, 20.31], + [1594742400000, 18.53], + [1594828800000, 13.59], + [1594915200000, 14.3], + [1595174400000, 17.41], + [1595260800000, 17.9], + [1595347200000, 18.64], + [1595433600000, 18.79], + [1595520000000, 13.58], + [1595779200000, 13.92], + [1595865600000, 14.96], + [1595952000000, 17.78], + [1596038400000, 17.26], + [1596124800000, 18.39], + [1596384000000, 20.64], + [1596470400000, 20.41], + [1596556800000, 20.96], + [1596643200000, 20.77], + [1596729600000, 19.38], + [1596988800000, 19.78], + [1597075200000, 18.47], + [1597161600000, 17.48], + [1597248000000, 17.4], + [1597334400000, 18.91], + [1597593600000, 21.27], + [1597680000000, 21.55], + [1597766400000, 19.57], + [1597852800000, 18.26], + [1597939200000, 19.22], + [1598198400000, 20.39], + [1598284800000, 20.28], + [1598371200000, 18.6], + [1598457600000, 19.36], + [1598544000000, 21.7], + [1598803200000, 21.01], + [1598889600000, 21.72], + [1598976000000, 21.74], + [1599062400000, 20.96], + [1599148800000, 20.05], + [1599408000000, 17.54], + [1599494400000, 18.1], + [1599580800000, 15.27], + [1599667200000, 14.4], + [1599753600000, 15.61], + [1600012800000, 16.28], + [1600099200000, 17.09], + [1600185600000, 16.4], + [1600272000000, 16.17], + [1600358400000, 18.29], + [1600617600000, 17.48], + [1600704000000, 16.3], + [1600790400000, 16.85], + [1600876800000, 14.61], + [1600963200000, 14.62], + [1601222400000, 14.5], + [1601308800000, 15.1], + [1601395200000, 15.01], + [1602172800000, 17.59], + [1602432000000, 20.82], + [1602518400000, 21.16], + [1602604800000, 20.46], + [1602691200000, 20.01], + [1602777600000, 19.85], + [1603036800000, 18.89], + [1603123200000, 19.84], + [1603209600000, 19.24], + [1603296000000, 18.74], + [1603382400000, 17.19], + [1603641600000, 17.04], + [1603728000000, 17.37], + [1603814400000, 18.01], + [1603900800000, 18.72], + [1603987200000, 16.69], + [1604246400000, 17.38], + [1604332800000, 18.9], + [1604419200000, 19.38], + [1604505600000, 21.27], + [1604592000000, 20.8], + [1604851200000, 23.12], + [1604937600000, 22.16], + [1605024000000, 20.76], + [1605110400000, 21.0], + [1605196800000, 20.3], + [1605456000000, 21.32], + [1605542400000, 20.68], + [1605628800000, 20.6], + [1605715200000, 21.28], + [1605801600000, 21.91], + [1606060800000, 23.02], + [1606147200000, 22.63], + [1606233600000, 20.85], + [1606320000000, 20.87], + [1606406400000, 21.88], + [1606665600000, 21.42], + [1606752000000, 23.66], + [1606838400000, 23.66], + [1606924800000, 23.58], + [1607011200000, 23.89], + [1607270400000, 23.05], + [1607356800000, 22.95], + [1607443200000, 21.31], + [1607529600000, 21.46] ] }, { name: '沪深300', data: [ - [1591545600000, 0], - [1591632000000, 0.62], - [1591718400000, 0.44], - [1591804800000, -0.65], - [1591891200000, -0.47], - [1592150400000, -1.67], - [1592236800000, -0.18], - [1592323200000, -0.11], - [1592409600000, 0.56], - [1592496000000, 1.91], - [1592755200000, 1.99], - [1592841600000, 2.48], - [1592928000000, 2.91], - [1593360000000, 2.18], - [1593446400000, 3.53], - [1593532800000, 5.61], - [1593619200000, 7.8], - [1593705600000, 9.89], - [1593964800000, 16.12], - [1594051200000, 16.81], - [1594137600000, 18.7], - [1594224000000, 20.36], - [1594310400000, 18.18], - [1594569600000, 20.66], - [1594656000000, 19.51], - [1594742400000, 17.96], - [1594828800000, 12.29], - [1594915200000, 13.0], - [1595174400000, 16.37], - [1595260800000, 16.64], - [1595347200000, 17.22], - [1595433600000, 17.17], - [1595520000000, 12.02], - [1595779200000, 12.59], - [1595865600000, 13.58], - [1595952000000, 16.34], - [1596038400000, 15.77], - [1596124800000, 16.74], - [1596384000000, 18.63], - [1596470400000, 18.74], - [1596556800000, 18.78], - [1596643200000, 18.42], - [1596729600000, 17.06], - [1596988800000, 17.48], - [1597075200000, 16.41], - [1597161600000, 15.56], - [1597248000000, 15.26], - [1597334400000, 16.97], - [1597593600000, 19.72], - [1597680000000, 19.66], - [1597766400000, 17.87], - [1597852800000, 16.34], - [1597939200000, 17.33], - [1598198400000, 18.25], - [1598284800000, 18.4], - [1598371200000, 17.01], - [1598457600000, 17.64], - [1598544000000, 20.45], - [1598803200000, 19.75], - [1598889600000, 20.39], - [1598976000000, 20.44], - [1599062400000, 19.77], - [1599148800000, 18.6], - [1599408000000, 16.1], - [1599494400000, 16.72], - [1599580800000, 13.99], - [1599667200000, 13.92], - [1599753600000, 15.05], - [1600012800000, 15.64], - [1600099200000, 16.57], - [1600185600000, 15.8], - [1600272000000, 15.19], - [1600358400000, 17.78], - [1600617600000, 16.65], - [1600704000000, 15.26], - [1600790400000, 15.67], - [1600876800000, 13.45], - [1600963200000, 13.63], - [1601222400000, 13.92], - [1601308800000, 14.17], - [1601395200000, 14.06], - [1602172800000, 16.39], - [1602432000000, 19.92], - [1602518400000, 20.32], - [1602604800000, 19.52], - [1602691200000, 19.31], - [1602777600000, 19.14], - [1603036800000, 18.24], - [1603123200000, 19.18], - [1603209600000, 19.17], - [1603296000000, 18.8], - [1603382400000, 17.32], - [1603641600000, 16.64], - [1603728000000, 16.84], - [1603814400000, 17.79], - [1603900800000, 18.67], - [1603987200000, 16.74], - [1604246400000, 17.38], - [1604332800000, 18.79], - [1604419200000, 19.68], - [1604505600000, 21.46], - [1604592000000, 21.48], - [1604851200000, 23.85], - [1604937600000, 23.17], - [1605024000000, 21.95], - [1605110400000, 22.04], - [1605196800000, 20.76], - [1605456000000, 21.94], - [1605542400000, 21.7], - [1605628800000, 21.62], - [1605715200000, 22.53], - [1605801600000, 22.91], - [1606060800000, 24.44], - [1606147200000, 23.68], - [1606233600000, 22.1], - [1606320000000, 22.32], - [1606406400000, 23.84], - [1606665600000, 23.33], - [1606752000000, 25.99], - [1606838400000, 25.99], - [1606924800000, 25.74], - [1607011200000, 25.96], - [1607270400000, 24.87], - [1607356800000, 24.56] + [1591718400000, 0], + [1591804800000, -1.08], + [1591891200000, -0.91], + [1592150400000, -2.1], + [1592236800000, -0.62], + [1592323200000, -0.55], + [1592409600000, 0.12], + [1592496000000, 1.46], + [1592755200000, 1.54], + [1592841600000, 2.03], + [1592928000000, 2.46], + [1593360000000, 1.73], + [1593446400000, 3.08], + [1593532800000, 5.15], + [1593619200000, 7.33], + [1593705600000, 9.4], + [1593964800000, 15.6], + [1594051200000, 16.3], + [1594137600000, 18.18], + [1594224000000, 19.83], + [1594310400000, 17.66], + [1594569600000, 20.13], + [1594656000000, 18.99], + [1594742400000, 17.45], + [1594828800000, 11.8], + [1594915200000, 12.5], + [1595174400000, 15.86], + [1595260800000, 16.12], + [1595347200000, 16.7], + [1595433600000, 16.65], + [1595520000000, 11.53], + [1595779200000, 12.1], + [1595865600000, 13.08], + [1595952000000, 15.83], + [1596038400000, 15.26], + [1596124800000, 16.22], + [1596384000000, 18.11], + [1596470400000, 18.22], + [1596556800000, 18.25], + [1596643200000, 17.9], + [1596729600000, 16.54], + [1596988800000, 16.96], + [1597075200000, 15.89], + [1597161600000, 15.05], + [1597248000000, 14.75], + [1597334400000, 16.46], + [1597593600000, 19.2], + [1597680000000, 19.14], + [1597766400000, 17.35], + [1597852800000, 15.83], + [1597939200000, 16.81], + [1598198400000, 17.73], + [1598284800000, 17.88], + [1598371200000, 16.5], + [1598457600000, 17.12], + [1598544000000, 19.92], + [1598803200000, 19.22], + [1598889600000, 19.86], + [1598976000000, 19.91], + [1599062400000, 19.24], + [1599148800000, 18.08], + [1599408000000, 15.59], + [1599494400000, 16.21], + [1599580800000, 13.49], + [1599667200000, 13.42], + [1599753600000, 14.55], + [1600012800000, 15.13], + [1600099200000, 16.06], + [1600185600000, 15.29], + [1600272000000, 14.68], + [1600358400000, 17.26], + [1600617600000, 16.13], + [1600704000000, 14.75], + [1600790400000, 15.17], + [1600876800000, 12.96], + [1600963200000, 13.13], + [1601222400000, 13.42], + [1601308800000, 13.67], + [1601395200000, 13.56], + [1602172800000, 15.88], + [1602432000000, 19.39], + [1602518400000, 19.79], + [1602604800000, 19.0], + [1602691200000, 18.79], + [1602777600000, 18.61], + [1603036800000, 17.72], + [1603123200000, 18.66], + [1603209600000, 18.64], + [1603296000000, 18.28], + [1603382400000, 16.8], + [1603641600000, 16.13], + [1603728000000, 16.33], + [1603814400000, 17.27], + [1603900800000, 18.15], + [1603987200000, 16.23], + [1604246400000, 16.86], + [1604332800000, 18.27], + [1604419200000, 19.16], + [1604505600000, 20.93], + [1604592000000, 20.94], + [1604851200000, 23.31], + [1604937600000, 22.63], + [1605024000000, 21.42], + [1605110400000, 21.51], + [1605196800000, 20.23], + [1605456000000, 21.4], + [1605542400000, 21.17], + [1605628800000, 21.09], + [1605715200000, 21.99], + [1605801600000, 22.37], + [1606060800000, 23.9], + [1606147200000, 23.13], + [1606233600000, 21.56], + [1606320000000, 21.78], + [1606406400000, 23.3], + [1606665600000, 22.79], + [1606752000000, 25.43], + [1606838400000, 25.43], + [1606924800000, 25.18], + [1607011200000, 25.4], + [1607270400000, 24.32], + [1607356800000, 24.02], + [1607443200000, 22.35], + [1607529600000, 22.3] ] } ] @@ -4478,7 +4482,9 @@ var fS_code = '161725' { x: 1606924800000, y: 72, sc: '1190' }, { x: 1607011200000, y: 16, sc: '1191' }, { x: 1607270400000, y: 15, sc: '1190' }, - { x: 1607356800000, y: 14, sc: '1189' } + { x: 1607356800000, y: 14, sc: '1190' }, + { x: 1607443200000, y: 14, sc: '1189' }, + { x: 1607529600000, y: 15, sc: '1189' } ] /*同类排名百分比*/ var Data_rateInSimilarPersent = [ [1440604800000, 93.0], @@ -5765,7 +5771,9 @@ var fS_code = '161725' [1606924800000, 93.95], [1607011200000, 98.66], [1607270400000, 98.74], - [1607356800000, 98.82] + [1607356800000, 98.82], + [1607443200000, 98.82], + [1607529600000, 98.74] ] /*规模变动 mom-较上期环比*/ var Data_fluctuationScale = { categories: [ @@ -5833,7 +5841,7 @@ var fS_code = '161725' pic: 'https://pdf.dfcfw.com/pdf/H8_JPG30379533_1.jpg', name: '侯昊', star: 3, - workTime: '3年又110天', + workTime: '3年又112天', fundSize: '416.28亿(17只基金)', power: { avr: '56.39', @@ -5846,20 +5854,20 @@ var fS_code = '161725' '根据基金经理现任管理基金资产规模评分' ], data: [47.2, 76.5, 37.7, 47.4, 94.8], - jzrq: '2020-12-04' + jzrq: '2020-12-08' }, profit: { categories: ['任期收益', '同类平均', '沪深300'], series: [ { data: [ - { name: null, color: '#7cb5ec', y: 223.5091 }, - { name: null, color: '#414c7b', y: 52.32 }, - { name: null, color: '#f7a35c', y: 33.51 } + { name: null, color: '#7cb5ec', y: 224.7448 }, + { name: null, color: '#414c7b', y: 50.71 }, + { name: null, color: '#f7a35c', y: 30.31 } ] } ], - jzrq: '2020-12-04' + jzrq: '2020-12-08' } } ] @@ -5873,38 +5881,38 @@ var fS_code = '161725' } /*同类型基金涨幅榜(页面底部通栏)*/ var swithSameType = [ [ - '001838_国投瑞银国家安全混合_14.17', - '050018_博时行业轮动混合_12.19', - '519198_万家颐和灵活配置混合_11.95', - '004205_东方支柱产业灵活配置_11.76', - '161724_招商中证煤炭等权指数_11.34' + '161724_招商中证煤炭等权指数_12.58', + '001838_国投瑞银国家安全混合_11.51', + '002251_华夏军工安全混合_9.64', + '004698_博时军工主题股票_9.60', + '168501_北信瑞丰产业升级_9.55' ], [ - '003834_华夏能源革新股票_38.23', - '005939_工银新能源汽车混合A_37.46', - '400015_东方新能源汽车混合_37.40', - '005940_工银新能源汽车混合C_37.32', - '004854_广发中证全指汽车指数_36.33' + '400015_东方新能源汽车混合_41.99', + '003834_华夏能源革新股票_41.82', + '001643_汇丰晋信智造先锋股票_41.26', + '001644_汇丰晋信智造先锋股票_41.08', + '540008_汇丰晋信低碳先锋股票_40.90' ], [ - '002190_农银新能源主题_85.39', - '001606_农银工业4.0混合_80.23', - '000336_农银研究精选混合_73.68', - '004854_广发中证全指汽车指数_73.30', - '004855_广发中证全指汽车指数_73.16' + '002190_农银新能源主题_81.34', + '001606_农银工业4.0混合_75.57', + '004997_广发高端制造股票A_69.53', + '000336_农银研究精选混合_68.58', + '005968_创金合信工业周期股票_68.13' ], [ - '002190_农银新能源主题_142.15', - '004997_广发高端制造股票A_135.58', - '000336_农银研究精选混合_132.16', - '001606_农银工业4.0混合_132.16', - '001643_汇丰晋信智造先锋股票_125.33' + '002190_农银新能源主题_138.28', + '004997_广发高端制造股票A_135.79', + '001643_汇丰晋信智造先锋股票_126.15', + '001606_农银工业4.0混合_126.10', + '540008_汇丰晋信低碳先锋股票_125.42' ], [ - '001679_前海开源中国稀缺资产_225.57', - '002079_前海开源中国稀缺资产_224.94', - '001508_富国新动力灵活配置混_209.84', - '161903_万家行业优选混合(L_209.20', - '001510_富国新动力灵活配置混_205.92' + '001679_前海开源中国稀缺资产_226.05', + '002079_前海开源中国稀缺资产_225.40', + '001508_富国新动力灵活配置混_208.52', + '001510_富国新动力灵活配置混_204.58', + '161903_万家行业优选混合(L_203.41' ] ]