完成2.0版
parent
e51c15db73
commit
1fb6b67fa8
|
@ -1,7 +1,9 @@
|
|||
## 摸鱼搞基小工具
|
||||
> 搞基专用, 你懂的。
|
||||
## 搞基爱啪啪
|
||||
> “搞基爱啪啪” 是一款开源的, 非专业的搞基软件, 上面的数据全来自网络, 不对准确性作任何保证.
|
||||
|
||||
|
||||
搞基有风险, 入行需谨慎. 你亏了别找我, 赚了可以给我发红包.
|
||||
|
||||
## 编译
|
||||
|
||||
```bash
|
||||
|
@ -10,4 +12,4 @@ npm run pack
|
|||
```
|
||||
|
||||
|
||||
![preview](./preview.jpg)
|
||||
![preview](./preview.png)
|
BIN
preview.jpg
BIN
preview.jpg
Binary file not shown.
Before Width: | Height: | Size: 38 KiB |
Binary file not shown.
After Width: | Height: | Size: 99 KiB |
|
@ -1 +1 @@
|
|||
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}
|
||||
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}.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;font-weight:bold;color:var(--color-grey-1)}.app .select-box .list .item .percent.red{color:var(--color-red-1)}.app .select-box .list .item .percent.green{color:var(--color-green-3)}.app .select-box .list .item:nth-child(odd){background:rgba(255,255,255,0.35)}.app .select-box .list .item:hover{color:var(--color-blue-1);background:rgba(255,255,255,0.35)}.app .select-box .list .item.active{color:var(--color-blue-3);background:rgba(255,255,255,0.7)}.app .detail{position:relative;flex:1;height:100%;border-left:1px solid var(--color-plain-2);background:#fff}.app .detail .title{display:flex;justify-content:space-between;align-items:center;width:100%;height:35px;padding:0 16px;font-size:16px;font-weight:bold}.app .detail .title span{display:inline-flex}.app .detail .title wc-button{margin:0 6px}.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}.app .detail.blur::after{position:absolute;left:0;top:0;z-index:999;width:100%;height:100%;content:'';background:rgba(255,255,255,0.75);-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px)}.app .preferences{width:640px;height:360px;border-radius:10px}.app .preferences .titlebar{width:100%;height:72px;border-bottom:1px solid var(--color-plain-3);background:var(--color-plain-1)}.app .preferences .titlebar .title{width:100%;height:24px;line-height:24px;text-align:center}.app .preferences .titlebar nav{display:flex;width:100%;height:40px;padding:0 16px;--size: 18px}.app .preferences .titlebar nav span{display:flex;flex-direction:column;align-items:center;justify-content:center;width:52px;height:40px;margin:0 6px;border-radius:6px;font-size:12px}.app .preferences .titlebar nav span.active{background:var(--color-plain-2);color:var(--color-blue-1)}.app .preferences .titlebar nav span:hover{background:var(--color-plain-2)}.app .preferences .tab-panel{padding:64px}.app .preferences .tab-panel p{margin-bottom:16px}.app .preferences .tab-panel .field{display:flex;align-items:center;height:64px}.app .preferences .tab-panel .field .label{width:200px;color:var(--color-grey-1)}
|
||||
|
|
110
src/css/app.scss
110
src/css/app.scss
|
@ -77,7 +77,6 @@ body {
|
|||
|
||||
wc-input {
|
||||
flex: 1;
|
||||
margin-right: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -107,24 +106,28 @@ body {
|
|||
padding: 0 4px;
|
||||
border-radius: 2px;
|
||||
font-size: 12px;
|
||||
color: #fff;
|
||||
background: var(--color-grey-1);
|
||||
font-weight: bold;
|
||||
color: var(--color-grey-1);
|
||||
|
||||
&.red {
|
||||
background: var(--color-red-1);
|
||||
color: var(--color-red-1);
|
||||
}
|
||||
&.green {
|
||||
background: var(--color-green-3);
|
||||
color: var(--color-green-3);
|
||||
}
|
||||
}
|
||||
|
||||
&:nth-child(odd) {
|
||||
background: rgba(255, 255, 255, 0.35);
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: var(--color-orange-1);
|
||||
color: var(--color-blue-1);
|
||||
background: rgba(255, 255, 255, 0.35);
|
||||
}
|
||||
|
||||
&.active {
|
||||
color: var(--color-orange-3);
|
||||
color: var(--color-blue-3);
|
||||
background: rgba(255, 255, 255, 0.7);
|
||||
}
|
||||
}
|
||||
|
@ -132,18 +135,28 @@ body {
|
|||
}
|
||||
|
||||
.detail {
|
||||
position: relative;
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
border-left: 1px solid var(--color-plain-2);
|
||||
background: #fff;
|
||||
|
||||
.title {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
height: 35px;
|
||||
padding: 0 16px;
|
||||
line-height: 35px;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
|
||||
span {
|
||||
display: inline-flex;
|
||||
}
|
||||
wc-button {
|
||||
margin: 0 6px;
|
||||
}
|
||||
}
|
||||
|
||||
.card {
|
||||
|
@ -160,5 +173,86 @@ body {
|
|||
color: #64b5f6;
|
||||
}
|
||||
}
|
||||
|
||||
&.blur {
|
||||
&::after {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
z-index: 999;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
content: '';
|
||||
background: rgba(255, 255, 255, 0.75);
|
||||
backdrop-filter: blur(10px);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.preferences {
|
||||
width: 640px;
|
||||
height: 360px;
|
||||
border-radius: 10px;
|
||||
|
||||
.titlebar {
|
||||
width: 100%;
|
||||
height: 72px;
|
||||
border-bottom: 1px solid var(--color-plain-3);
|
||||
background: var(--color-plain-1);
|
||||
|
||||
.title {
|
||||
width: 100%;
|
||||
height: 24px;
|
||||
line-height: 24px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
nav {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
padding: 0 16px;
|
||||
|
||||
span {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 52px;
|
||||
height: 40px;
|
||||
margin: 0 6px;
|
||||
border-radius: 6px;
|
||||
font-size: 12px;
|
||||
|
||||
&.active {
|
||||
background: var(--color-plain-2);
|
||||
color: var(--color-blue-1);
|
||||
}
|
||||
&:hover {
|
||||
background: var(--color-plain-2);
|
||||
}
|
||||
}
|
||||
--size: 18px;
|
||||
}
|
||||
}
|
||||
|
||||
.tab-panel {
|
||||
padding: 64px;
|
||||
|
||||
p {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.field {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 64px;
|
||||
|
||||
.label {
|
||||
width: 200px;
|
||||
color: var(--color-grey-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,17 +19,16 @@
|
|||
<cite :text="it.code"></cite>
|
||||
</div>
|
||||
|
||||
<canvas class="last-days" width="128" height="60" :draw="it.last"></canvas>
|
||||
|
||||
<div class="today">
|
||||
<span class="money" :text="it.curr"></span>
|
||||
<span class="money" :text="'¥' + it.cm"></span>
|
||||
<span
|
||||
class="percent"
|
||||
:class="{red: it.percent > 0, green: it.percent < 0}"
|
||||
:text="it.percent + '%'">
|
||||
:class="{red: it.cp > 0, green: it.cp < 0}"
|
||||
:text="it.cp + '%'">
|
||||
</span>
|
||||
</div>
|
||||
</section>
|
||||
<section :if="list.length === 0" class="item">啥基都没有...</section>
|
||||
</wc-scroll>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -15,26 +15,33 @@
|
|||
|
||||
<aside class="sidebar app-drag">
|
||||
<wc-icon class="app-nodrag item stat active" is="chart"></wc-icon>
|
||||
<wc-icon class="app-nodrag item opt" is="menu-dot"></wc-icon>
|
||||
<wc-icon class="app-nodrag item opt" is="menu-dot" @click="showPreferencesPanel"></wc-icon>
|
||||
</aside>
|
||||
|
||||
<div class="select-box">
|
||||
<section class="form">
|
||||
<wc-input maxlength="6" placeholder="输入编号搞新基" round size="mini"></wc-input>
|
||||
<wc-button circle size="mini" color="orange" icon="plus"></wc-button>
|
||||
<wc-input
|
||||
maxlength="6"
|
||||
placeholder="输入编号搞新基"
|
||||
round
|
||||
@submit="addGay"
|
||||
:duplex="input"
|
||||
size="mini">
|
||||
</wc-input>
|
||||
</section>
|
||||
<wc-scroll class="list">
|
||||
<item
|
||||
class="item"
|
||||
:class="{active: curr.code === it.code}"
|
||||
@click="viewGay(it)"
|
||||
:for="it in list">
|
||||
<strong class="text-ell" :text="it.name"></strong>
|
||||
<section>
|
||||
<cite :text="it.code"></cite>
|
||||
<span
|
||||
class="percent"
|
||||
:class="{red: it.percent > 0, green: it.percent < 0}"
|
||||
:text="it.percent + '%'">
|
||||
:class="{red: it.cp > 0, green: it.cp < 0}"
|
||||
:text="it.cp + '%'">
|
||||
</span>
|
||||
</section>
|
||||
</item>
|
||||
|
@ -42,23 +49,70 @@
|
|||
</div>
|
||||
|
||||
|
||||
<div class="detail">
|
||||
<div class="detail" :class="{blur: !curr.code}">
|
||||
<section class="title app-drag">
|
||||
[{{curr.code}}] {{curr.name}}
|
||||
<span>[{{curr.code}}] {{curr.name}}</span>
|
||||
<span>
|
||||
<wc-button
|
||||
circle
|
||||
size="mini"
|
||||
@click="removeGay"
|
||||
icon="trash">
|
||||
</wc-button>
|
||||
<wc-button
|
||||
circle
|
||||
color="red"
|
||||
size="mini"
|
||||
@click="updateGay"
|
||||
icon="eye">
|
||||
</wc-button>
|
||||
</span>
|
||||
</section>
|
||||
|
||||
<fieldset class="card">
|
||||
<legend>60天红绿榜</legend>
|
||||
<wc-rank :attr-list="curr.last60"></wc-rank>
|
||||
<legend>实时数据</legend>
|
||||
<wc-rank :attr-stat="curr.stat"></wc-rank>
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="card">
|
||||
<legend>单位净值走势</legend>
|
||||
<wc-rank :attr-list="curr.last60"></wc-rank>
|
||||
<wc-line :attr-list="curr.line"></wc-line>
|
||||
</fieldset>
|
||||
|
||||
</div>
|
||||
|
||||
<wc-layer ref="pre" mask mask-close radius="10px" >
|
||||
<div class="preferences">
|
||||
<div class="titlebar">
|
||||
<div class="title">hello</div>
|
||||
<nav>
|
||||
<span :class="{active: preferences.tab === 1}" @click="switchTab(1)">
|
||||
<wc-icon is="setting"></wc-icon>
|
||||
常规
|
||||
</span>
|
||||
<span :class="{active: preferences.tab === 2}" @click="switchTab(2)">
|
||||
<wc-icon is="info"></wc-icon>
|
||||
关于
|
||||
</span>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
<div class="tab-panel" :visible="preferences.tab === 1">
|
||||
<section class="field">
|
||||
<span class="label">神奇的2点半提醒</span>
|
||||
<wc-switch :duplex="preferences.notify"></wc-switch>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div class="tab-panel" :visible="preferences.tab === 2">
|
||||
<p>“搞基爱啪啪” 是一款开源的, 非专业的搞基软件, 上面的数据全来自网络, 不对准确性作任何保证. </p>
|
||||
<p>搞基有风险, 入行需谨慎. 你亏了别找我, 赚了可以给我发红包.</p>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</wc-layer>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
|
388
src/js/app.js
388
src/js/app.js
|
@ -8,21 +8,18 @@
|
|||
|
||||
import '/lib/anot.js'
|
||||
import '/lib/form/button.js'
|
||||
import '/lib/form/switch.js'
|
||||
import '/lib/scroll/index.js'
|
||||
import '/lib/chart/rank.js'
|
||||
import '/lib/canvas-draw.js'
|
||||
import '/lib/chart/line.js'
|
||||
|
||||
import layer from '/lib/layer/index.js'
|
||||
import Utils from '/lib/utils.js'
|
||||
|
||||
import app from '/lib/socket.js'
|
||||
|
||||
const log = console.log
|
||||
|
||||
const { ipcRenderer } = require('electron')
|
||||
|
||||
// http://fund.eastmoney.com/pingzhongdata/161725.js?v=20201209153939
|
||||
|
||||
const $doc = Anot(document)
|
||||
|
||||
function getJsonp(str) {
|
||||
if (~str.indexOf('jsonpgz')) {
|
||||
return new Function(`function jsonpgz(d){return d}; return ${str}`)()
|
||||
|
@ -30,216 +27,255 @@ function getJsonp(str) {
|
|||
return false
|
||||
}
|
||||
|
||||
function getTableData(str) {
|
||||
var match = str.match(/<tbody[^]*?>.*?<\/tbody>/)
|
||||
var table = document.createElement('table')
|
||||
var list = []
|
||||
var max = 0
|
||||
var min = 99
|
||||
|
||||
table.innerHTML = match[0]
|
||||
list = Array.from(table.children[0].children)
|
||||
.map(it => {
|
||||
let m = +it.children[2].textContent
|
||||
if (m > max) {
|
||||
max = m
|
||||
}
|
||||
if (m < min) {
|
||||
min = m
|
||||
}
|
||||
return { m }
|
||||
})
|
||||
.reverse()
|
||||
|
||||
list.forEach(it => {
|
||||
it.h = +(((it.m - min) * 60) / (max - min)).toFixed(2)
|
||||
})
|
||||
return list
|
||||
function getLineStat(str) {
|
||||
return new Function(`${str}; return {line: Data_netWorthTrend.map(it => ({
|
||||
x: ~~(it.x/1000),
|
||||
y: +(it.y * 10000).toFixed(0),
|
||||
p: it.equityReturn
|
||||
})), e1: +syl_1y, e3: +syl_3y, e6: +syl_6y, e12: +syl_1n}`)()
|
||||
}
|
||||
|
||||
Anot({
|
||||
$id: 'app',
|
||||
state: {
|
||||
input: '',
|
||||
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(',')
|
||||
code: '',
|
||||
name: '',
|
||||
stat: '',
|
||||
line: ''
|
||||
},
|
||||
list: [],
|
||||
$dict: {}
|
||||
$dict: {},
|
||||
preferences: {
|
||||
tab: 1,
|
||||
notify: Anot.ls('notify') === '1'
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
'chapter.content'() {
|
||||
this.calcuteWords = this.chapter.content.length
|
||||
},
|
||||
currCate() {
|
||||
this.renderChapterList()
|
||||
'preferences.notify'(v) {
|
||||
Anot.ls('notify', v ^ 0)
|
||||
if (v) {
|
||||
app.dispatch('notify')
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
// WIN.on('blur', _ => {
|
||||
// WIN.hide()
|
||||
// })
|
||||
var gays = Anot.ls('gays') || '{}'
|
||||
var list = []
|
||||
var old = this.syncOldStat()
|
||||
|
||||
var watch_list = Anot.ls('watch_list') || '[]'
|
||||
if (old === false) {
|
||||
gays = JSON.parse(gays)
|
||||
|
||||
watch_list = JSON.parse(watch_list)
|
||||
for (let code in gays) {
|
||||
let { name, cm, cp, t } = gays[code]
|
||||
list.push({ code, name, cm, cp, t })
|
||||
this.$dict[code] = 1
|
||||
}
|
||||
list.sort((a, b) => b.cp - a.cp)
|
||||
|
||||
this.list = watch_list
|
||||
this.list = list
|
||||
}
|
||||
|
||||
for (let it of this.list) {
|
||||
this.$dict[it.code] = it
|
||||
if (this.preferences.notify) {
|
||||
app.dispatch('notify')
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
close() {
|
||||
// WIN.close()
|
||||
syncOldStat() {
|
||||
var old = Anot.ls('watch_list')
|
||||
var list = []
|
||||
var dict = {}
|
||||
|
||||
if (old) {
|
||||
old = JSON.parse(old)
|
||||
for (let it of old) {
|
||||
dict[it.code] = {
|
||||
name: it.name,
|
||||
cm: +it.curr,
|
||||
cp: it.percent,
|
||||
t: Date.now()
|
||||
}
|
||||
list.push({ code: it.code, ...dict[it.code] })
|
||||
}
|
||||
|
||||
list.sort((a, b) => b.cp - a.cp)
|
||||
this.list = list
|
||||
|
||||
Anot.ls('gays', dict)
|
||||
Anot.ls('watch_list', null)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
},
|
||||
getTodayStat(id) {
|
||||
var res = ipcRenderer.sendSync(
|
||||
'net',
|
||||
|
||||
showPreferencesPanel() {
|
||||
this.$refs.pre.show()
|
||||
},
|
||||
|
||||
switchTab(n) {
|
||||
this.preferences.tab = n
|
||||
},
|
||||
|
||||
getGayStat(id) {
|
||||
var res = app.dispatch(
|
||||
'fetch',
|
||||
`https://fundgz.1234567.com.cn/js/${id}.js`
|
||||
)
|
||||
|
||||
return getJsonp(res)
|
||||
},
|
||||
|
||||
getLastMonth(id) {
|
||||
var res = ipcRenderer.sendSync(
|
||||
'net',
|
||||
`https://fund.eastmoney.com/f10/F10DataApi.aspx?type=lsjz&per=42&code=${id}`
|
||||
)
|
||||
return getTableData(res)
|
||||
},
|
||||
|
||||
addGay() {
|
||||
layer
|
||||
.prompt('请输入鸡精代号', (val, done) => {
|
||||
if (val.trim()) {
|
||||
done()
|
||||
}
|
||||
})
|
||||
.then(id => {
|
||||
if (this.$dict[id]) {
|
||||
var code = this.input
|
||||
var gay
|
||||
|
||||
if (this.$dict[code]) {
|
||||
layer.toast('这个鸡精在列表呢~~~', 'warn')
|
||||
this.input = ''
|
||||
return
|
||||
}
|
||||
Anot.nextTick(_ => {
|
||||
var info = this.getTodayStat(id)
|
||||
var last
|
||||
if (info) {
|
||||
last = this.getLastMonth(id)
|
||||
var tmp = {
|
||||
code: info.fundcode,
|
||||
name: info.name,
|
||||
yesterday: info.dwjz,
|
||||
curr: info.gsz,
|
||||
percent: +info.gszzl,
|
||||
last
|
||||
|
||||
if (code.length < 6) {
|
||||
return
|
||||
}
|
||||
this.list.unshift(tmp)
|
||||
this.$dict[tmp.code] = this.list[0]
|
||||
Anot.ls('watch_list', this.list.$model)
|
||||
|
||||
if (/[^\d]/.test(code)) {
|
||||
layer.toast('只能通过鸡精编号添加', 'error')
|
||||
this.input = ''
|
||||
return
|
||||
}
|
||||
|
||||
gay = this.getGayStat(code)
|
||||
|
||||
if (gay) {
|
||||
let tmp = {
|
||||
code: gay.fundcode,
|
||||
name: gay.name,
|
||||
cm: +gay.gsz,
|
||||
cp: +gay.gszzl,
|
||||
t: Date.now()
|
||||
}
|
||||
this.input = ''
|
||||
this.list.push(tmp)
|
||||
this.$dict[tmp.code] = 1
|
||||
this.list.sort((a, b) => b.cp - a.cp)
|
||||
this.saveCache()
|
||||
} else {
|
||||
layer.toast('鸡精不存在', 'error')
|
||||
}
|
||||
})
|
||||
})
|
||||
.catch(Anot.noop)
|
||||
},
|
||||
|
||||
updateGay(item) {
|
||||
var info = this.getTodayStat(item.code)
|
||||
if (info.dwjz !== item.yesterday) {
|
||||
item.yesterday = info.dwjz
|
||||
item.last = this.getLastMonth(item.code)
|
||||
}
|
||||
item.curr = info.gsz
|
||||
item.percent = +info.gszzl
|
||||
},
|
||||
updateGay() {
|
||||
var { code, stat } = this.curr
|
||||
var info = this.getGayStat(code)
|
||||
|
||||
removeGay(item) {
|
||||
layer
|
||||
.confirm(`是否移除[${item.name.slice(0, 5)}...]?`)
|
||||
.then(_ => {
|
||||
item.$ups.it.$remove()
|
||||
delete this.$dict[item.code]
|
||||
Anot.ls('watch_list', this.list.$model)
|
||||
})
|
||||
.catch(Anot.noop)
|
||||
},
|
||||
|
||||
updateGays() {
|
||||
for (let it of this.list) {
|
||||
this.updateGay(it)
|
||||
if (it.code === code) {
|
||||
let d
|
||||
|
||||
it.cm = +info.gsz
|
||||
it.cp = +info.gszzl
|
||||
|
||||
this.list.sort((a, b) => b.cp - a.cp)
|
||||
|
||||
d = new Date(info.gztime.slice(0, 10) + ' 00:00:00')
|
||||
d = ~~(d.getTime() / 1000) - 24 * 3600
|
||||
|
||||
// 如果走势最后的日期比当前最新的小, 则全量更新
|
||||
if (it.t < d) {
|
||||
Anot.ls(code, null)
|
||||
this.viewGay(it)
|
||||
console.log('update all stat...')
|
||||
return
|
||||
}
|
||||
|
||||
this.list.sort((a, b) => {
|
||||
return b.percent - a.percent
|
||||
})
|
||||
stat = JSON.parse(stat)
|
||||
stat.cm = it.cm
|
||||
stat.cp = it.cp
|
||||
this.curr.stat = JSON.stringify(stat)
|
||||
|
||||
Anot.ls('watch_list', this.list.$model)
|
||||
this.saveCache()
|
||||
layer.toast('数据更新成功', 'success')
|
||||
Anot.ss('last_update', Date.now())
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
removeGay() {
|
||||
var { code, name } = this.curr
|
||||
layer
|
||||
.confirm(`是否移除「${name}」?`)
|
||||
.then(_ => {
|
||||
for (let it of this.list) {
|
||||
if (it.code === code) {
|
||||
this.list.remove(it)
|
||||
delete this.$dict[code]
|
||||
Anot.ls(code, null)
|
||||
this.saveCache()
|
||||
break
|
||||
}
|
||||
}
|
||||
this.viewGay(this.list[0])
|
||||
})
|
||||
.catch(Anot.noop)
|
||||
},
|
||||
|
||||
saveCache() {
|
||||
var dict = {}
|
||||
for (let it of this.list) {
|
||||
var { code, name, cm, cp, t } = it
|
||||
dict[code] = { name, cm, cp, t }
|
||||
}
|
||||
Anot.ls('gays', dict)
|
||||
},
|
||||
|
||||
viewGay(item) {
|
||||
var gay = Anot.ls(item.code)
|
||||
var rank, line
|
||||
var { cm, cp, t } = item
|
||||
|
||||
this.curr.code = item.code
|
||||
this.curr.name = item.name
|
||||
|
||||
if (gay) {
|
||||
gay = JSON.parse(gay)
|
||||
var last = gay.line[gay.line.length - 1].x
|
||||
if (last < t) {
|
||||
gay = null
|
||||
}
|
||||
}
|
||||
|
||||
if (!gay) {
|
||||
gay = app.dispatch(
|
||||
'fetch',
|
||||
`http://fund.eastmoney.com/pingzhongdata/${
|
||||
item.code
|
||||
}.js?v=${Date.now()}`
|
||||
)
|
||||
gay = getLineStat(gay)
|
||||
item.t = gay.line[gay.line.length - 1].x
|
||||
this.saveCache()
|
||||
Anot.ls(item.code, JSON.stringify(gay))
|
||||
}
|
||||
|
||||
rank = gay.line.slice(-60).map(_ => _.p)
|
||||
line = JSON.stringify(gay.line)
|
||||
|
||||
this.curr.stat = JSON.stringify({
|
||||
rank,
|
||||
e1: gay.e1,
|
||||
e3: gay.e3,
|
||||
e6: gay.e6,
|
||||
e12: gay.e12,
|
||||
cm,
|
||||
cp
|
||||
})
|
||||
this.curr.line = line
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
160
src/js/float.js
160
src/js/float.js
|
@ -5,18 +5,11 @@
|
|||
*/
|
||||
|
||||
import '/lib/anot.js'
|
||||
import '/lib/form/button.js'
|
||||
|
||||
import '/lib/scroll/index.js'
|
||||
import '/lib/canvas-draw.js'
|
||||
|
||||
import layer from '/lib/layer/index.js'
|
||||
import Utils from '/lib/utils.js'
|
||||
import app from '/lib/socket.js'
|
||||
|
||||
const log = console.log
|
||||
|
||||
const $doc = Anot(document)
|
||||
|
||||
function getJsonp(str) {
|
||||
if (~str.indexOf('jsonpgz')) {
|
||||
return new Function(`function jsonpgz(d){return d}; return ${str}`)()
|
||||
|
@ -24,156 +17,71 @@ function getJsonp(str) {
|
|||
return false
|
||||
}
|
||||
|
||||
function getTableData(str) {
|
||||
var match = str.match(/<tbody[^]*?>.*?<\/tbody>/)
|
||||
var table = document.createElement('table')
|
||||
var list = []
|
||||
var max = 0
|
||||
var min = 99
|
||||
|
||||
table.innerHTML = match[0]
|
||||
list = Array.from(table.children[0].children)
|
||||
.map(it => {
|
||||
let m = +it.children[2].textContent
|
||||
if (m > max) {
|
||||
max = m
|
||||
}
|
||||
if (m < min) {
|
||||
min = m
|
||||
}
|
||||
return { m }
|
||||
})
|
||||
.reverse()
|
||||
|
||||
list.forEach(it => {
|
||||
it.h = +(((it.m - min) * 60) / (max - min)).toFixed(2)
|
||||
})
|
||||
return list
|
||||
}
|
||||
|
||||
Anot({
|
||||
$id: 'app',
|
||||
state: {
|
||||
list: [],
|
||||
$dict: {}
|
||||
},
|
||||
|
||||
watch: {
|
||||
'chapter.content'() {
|
||||
this.calcuteWords = this.chapter.content.length
|
||||
},
|
||||
currCate() {
|
||||
this.renderChapterList()
|
||||
}
|
||||
list: []
|
||||
},
|
||||
mounted() {
|
||||
var watch_list = Anot.ls('watch_list') || '[]'
|
||||
|
||||
watch_list = JSON.parse(watch_list)
|
||||
|
||||
this.list = watch_list
|
||||
|
||||
for (let it of this.list) {
|
||||
this.$dict[it.code] = it
|
||||
}
|
||||
this.reloadGays()
|
||||
|
||||
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)
|
||||
} else {
|
||||
this.reloadGays()
|
||||
}
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
close() {
|
||||
// WIN.close()
|
||||
reloadGays() {
|
||||
var gays = Anot.ls('gays') || '{}'
|
||||
var list = []
|
||||
|
||||
gays = JSON.parse(gays)
|
||||
|
||||
for (let code in gays) {
|
||||
let { name, cm, cp, t } = gays[code]
|
||||
list.push({ code, name, cm, cp, t })
|
||||
}
|
||||
list.sort((a, b) => b.cp - a.cp)
|
||||
|
||||
this.list = list
|
||||
},
|
||||
getTodayStat(id) {
|
||||
|
||||
getGayStat(id) {
|
||||
var res = app.dispatch(
|
||||
'fetch',
|
||||
`https://fundgz.1234567.com.cn/js/${id}.js`
|
||||
)
|
||||
|
||||
return getJsonp(res)
|
||||
},
|
||||
|
||||
getLastMonth(id) {
|
||||
var res = app.dispatch(
|
||||
'fetch',
|
||||
`https://fund.eastmoney.com/f10/F10DataApi.aspx?type=lsjz&per=42&code=${id}`
|
||||
)
|
||||
return getTableData(res)
|
||||
},
|
||||
|
||||
addGay() {
|
||||
layer
|
||||
.prompt('请输入鸡精代号', (val, done) => {
|
||||
if (val.trim()) {
|
||||
done()
|
||||
}
|
||||
})
|
||||
.then(id => {
|
||||
if (this.$dict[id]) {
|
||||
return
|
||||
}
|
||||
Anot.nextTick(_ => {
|
||||
var info = this.getTodayStat(id)
|
||||
var last
|
||||
if (info) {
|
||||
last = this.getLastMonth(id)
|
||||
var tmp = {
|
||||
code: info.fundcode,
|
||||
name: info.name,
|
||||
yesterday: info.dwjz,
|
||||
curr: info.gsz,
|
||||
percent: +info.gszzl,
|
||||
last
|
||||
}
|
||||
this.list.unshift(tmp)
|
||||
this.$dict[tmp.code] = this.list[0]
|
||||
Anot.ls('watch_list', this.list.$model)
|
||||
} else {
|
||||
layer.toast('鸡精不存在', 'error')
|
||||
}
|
||||
})
|
||||
})
|
||||
.catch(Anot.noop)
|
||||
},
|
||||
|
||||
updateGay(item) {
|
||||
var info = this.getTodayStat(item.code)
|
||||
if (info.dwjz !== item.yesterday) {
|
||||
item.yesterday = info.dwjz
|
||||
item.last = this.getLastMonth(item.code)
|
||||
}
|
||||
item.curr = info.gsz
|
||||
item.percent = +info.gszzl
|
||||
},
|
||||
|
||||
removeGay(item) {
|
||||
layer
|
||||
.confirm(`是否移除[${item.name.slice(0, 5)}...]?`)
|
||||
.then(_ => {
|
||||
item.$ups.it.$remove()
|
||||
delete this.$dict[item.code]
|
||||
Anot.ls('watch_list', this.list.$model)
|
||||
})
|
||||
.catch(Anot.noop)
|
||||
var info = this.getGayStat(item.code)
|
||||
item.cm = +info.gsz
|
||||
item.cp = +info.gszzl
|
||||
},
|
||||
|
||||
updateGays() {
|
||||
for (let it of this.list) {
|
||||
this.updateGay(it)
|
||||
}
|
||||
|
||||
this.list.sort((a, b) => {
|
||||
return b.percent - a.percent
|
||||
})
|
||||
|
||||
Anot.ls('watch_list', this.list.$model)
|
||||
this.list.sort((a, b) => b.cp - a.cp)
|
||||
this.saveCache()
|
||||
},
|
||||
saveCache() {
|
||||
var dict = {}
|
||||
for (let it of this.list) {
|
||||
var { code, name, cm, cp, t } = it
|
||||
dict[code] = { name, cm, cp, t }
|
||||
}
|
||||
Anot.ls('gays', dict)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
|
@ -1,44 +0,0 @@
|
|||
/**
|
||||
* canvas渲染
|
||||
* @author yutent<yutent.io@gmail.com>
|
||||
* @date 2020/07/27 11:34:59
|
||||
*/
|
||||
|
||||
'use strict'
|
||||
|
||||
const log = console.log
|
||||
|
||||
const RED = '#ff5061'
|
||||
const GREEN = '#4caf50'
|
||||
|
||||
Anot.directive('draw', {
|
||||
priority: 1500,
|
||||
init(binding) {
|
||||
var elem = binding.element
|
||||
var ctx = elem.getContext('2d')
|
||||
binding.$ctx = ctx
|
||||
},
|
||||
update: function(val) {
|
||||
var list = val.$model
|
||||
var start = list.shift()
|
||||
var end = list[list.length - 1]
|
||||
var x = 0
|
||||
|
||||
this.$ctx.clearRect(0, 0, 128, 60)
|
||||
|
||||
this.$ctx.fillStyle = '#a7a8ab'
|
||||
this.$ctx.fillRect(0, 29, 128, 1)
|
||||
|
||||
this.$ctx.beginPath()
|
||||
this.$ctx.strokeStyle = start.m < end.m ? RED : GREEN
|
||||
this.$ctx.lineWidth = 2
|
||||
this.$ctx.moveTo(0, 60 - start.h)
|
||||
|
||||
while (list.length) {
|
||||
start = list.shift()
|
||||
x += 3
|
||||
this.$ctx.lineTo(x, 60 - start.h)
|
||||
}
|
||||
this.$ctx.stroke()
|
||||
}
|
||||
})
|
|
@ -0,0 +1,253 @@
|
|||
/**
|
||||
*
|
||||
* @authors yutent (yutent.io@gmail.com)
|
||||
* @date 2020-12-08 11:30:52
|
||||
* @version v1.0.0
|
||||
*
|
||||
*/
|
||||
|
||||
import $ from '../utils.js'
|
||||
import '../form/button.js'
|
||||
|
||||
const DARK = '#62778d'
|
||||
const BLUE = '#64b5f6'
|
||||
const PLAIN = '#f2f5fc'
|
||||
|
||||
export default class Line extends HTMLElement {
|
||||
static get observedAttributes() {
|
||||
return ['list']
|
||||
}
|
||||
|
||||
props = {
|
||||
list: []
|
||||
}
|
||||
|
||||
state = {
|
||||
key: 1,
|
||||
list: []
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super()
|
||||
|
||||
Object.defineProperty(this, 'root', {
|
||||
value: this.attachShadow({ mode: 'open' }),
|
||||
writable: true,
|
||||
enumerable: false,
|
||||
configurable: true
|
||||
})
|
||||
|
||||
this.root.innerHTML = `<style>* {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
padding: 0; }
|
||||
|
||||
::before,
|
||||
::after {
|
||||
box-sizing: border-box; }
|
||||
|
||||
:host {
|
||||
display: flex;
|
||||
width: 680px; }
|
||||
|
||||
.container {
|
||||
position: relative;
|
||||
padding: 24px 0 0; }
|
||||
|
||||
canvas {
|
||||
width: 680px;
|
||||
height: 230px; }
|
||||
|
||||
section {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0; }
|
||||
</style>
|
||||
<div class="container">
|
||||
<canvas></canvas>
|
||||
<section>
|
||||
<wc-button color="blue" data-key="1" size="mini">1月</wc-button>
|
||||
<wc-button data-key="3" size="mini">3月</wc-button>
|
||||
<wc-button data-key="6" size="mini">半年</wc-button>
|
||||
<wc-button data-key="12" size="mini">1年</wc-button>
|
||||
<wc-button data-key="36" size="mini">3年</wc-button>
|
||||
<wc-button data-key="999" size="mini">所有</wc-button>
|
||||
</section>
|
||||
</div>
|
||||
`
|
||||
|
||||
var elem = this.root.children[1]
|
||||
this.__SCENE__ = elem.firstElementChild
|
||||
this.__FILTER__ = elem.lastElementChild
|
||||
this.__CTX__ = this.__SCENE__.getContext('2d')
|
||||
this.__SCENE__.width = 680
|
||||
this.__SCENE__.height = 230
|
||||
}
|
||||
|
||||
_getTime(n) {
|
||||
var now = new Date()
|
||||
var time = { getTime: _ => 0 }
|
||||
var Y = now.getFullYear()
|
||||
var m = now.getMonth()
|
||||
var d = now.getDate()
|
||||
|
||||
switch (n) {
|
||||
case 1:
|
||||
time = new Date(Y, m - 1, d, 0, 0, 0)
|
||||
break
|
||||
case 3:
|
||||
time = new Date(Y, m - 3, d, 0, 0, 0)
|
||||
break
|
||||
case 6:
|
||||
time = new Date(Y, m - 6, d, 0, 0, 0)
|
||||
break
|
||||
case 12:
|
||||
time = new Date(Y - 1, m, d, 0, 0, 0)
|
||||
break
|
||||
case 36:
|
||||
time = new Date(Y - 3, m, d, 0, 0, 0)
|
||||
break
|
||||
}
|
||||
return time.getTime()
|
||||
}
|
||||
|
||||
_filter(n) {
|
||||
if (n < 999) {
|
||||
var time = this._getTime(n)
|
||||
this.state.list = this.props.list.filter(it => it.x >= time)
|
||||
} else {
|
||||
this.state.list = this.props.list.concat()
|
||||
}
|
||||
}
|
||||
|
||||
draw() {
|
||||
var { list, key } = this.state
|
||||
var ctx = this.__CTX__
|
||||
var x = 36
|
||||
var max = 0
|
||||
var min = Number.MAX_SAFE_INTEGER
|
||||
var step = 0 // 纵坐标间隔
|
||||
var dis = +(640 / list.length).toFixed(2) || 1 // 横坐标间隔
|
||||
var point
|
||||
var p1, p2, p3, p4
|
||||
var format = key > 12 ? 'Y/m' : 'm/d'
|
||||
|
||||
for (let it of list) {
|
||||
if (max < it.y) {
|
||||
max = it.y
|
||||
}
|
||||
if (min > it.y) {
|
||||
min = it.y
|
||||
}
|
||||
}
|
||||
|
||||
min = ~~(min / 100)
|
||||
max = Math.ceil(max / 100)
|
||||
step = ~~((max - min) / 3)
|
||||
|
||||
p1 = Math.floor(list.length / 4)
|
||||
p2 = Math.floor(list.length / 2)
|
||||
p3 = Math.floor((list.length * 3) / 4)
|
||||
p4 = list.length - 1
|
||||
|
||||
ctx.clearRect(0, 0, 680, 230)
|
||||
|
||||
// 纵坐标数值
|
||||
ctx.font = '12px Arial'
|
||||
ctx.textAlign = 'right'
|
||||
ctx.fillStyle = DARK
|
||||
ctx.fillText(min / 100, 32, 205)
|
||||
ctx.fillText((min + step) / 100, 32, 155)
|
||||
ctx.fillText((min + step + step) / 100, 32, 105)
|
||||
ctx.fillText((min + step + step + step) / 100, 32, 55)
|
||||
|
||||
ctx.font = '10px Arial'
|
||||
ctx.textAlign = 'left'
|
||||
ctx.fillText(new Date(list[0].x).format(format), x - 12, 225)
|
||||
ctx.fillText(new Date(list[p1].x).format(format), x + dis * p1 - 12, 225)
|
||||
ctx.fillText(new Date(list[p2].x).format(format), x + dis * p2 - 12, 225)
|
||||
ctx.fillText(new Date(list[p3].x).format(format), x + dis * p3 - 12, 225)
|
||||
ctx.fillText(
|
||||
new Date(list[p4].x).format(format),
|
||||
x + dis * p4 - 12 - (key > 12 ? 24 : 4),
|
||||
225
|
||||
)
|
||||
|
||||
// x轴参考线
|
||||
ctx.fillStyle = PLAIN
|
||||
ctx.fillRect(x, 50, 648, 1)
|
||||
ctx.fillRect(x, 100, 648, 1)
|
||||
ctx.fillRect(x, 150, 648, 1)
|
||||
ctx.fillRect(x, 200, 648, 1)
|
||||
|
||||
// y轴参考 线
|
||||
ctx.fillRect(x, 0, 1, 210)
|
||||
ctx.fillRect(x + dis * p1, 0, 1, 210)
|
||||
ctx.fillRect(x + dis * p2, 0, 1, 210)
|
||||
ctx.fillRect(x + dis * p3, 0, 1, 210)
|
||||
ctx.fillRect(x + dis * p4, 0, 1, 210)
|
||||
|
||||
point = list.shift()
|
||||
|
||||
// 曲线
|
||||
ctx.beginPath()
|
||||
ctx.strokeStyle = BLUE
|
||||
ctx.lineWidth = 1
|
||||
ctx.moveTo(x, 200 - (((point.y / 100 - min) / step) * 50).toFixed(0))
|
||||
|
||||
while (list.length) {
|
||||
let y
|
||||
|
||||
point = list.shift()
|
||||
|
||||
y = 200 - (((point.y / 100 - min) / step) * 50).toFixed(0)
|
||||
x += dis
|
||||
|
||||
ctx.lineTo(x, y)
|
||||
}
|
||||
ctx.stroke()
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
$.bind(this.__FILTER__, 'click', ev => {
|
||||
var el = ev.target
|
||||
if (this.props.list.length < 1) {
|
||||
return
|
||||
}
|
||||
if (el.tagName === 'WC-BUTTON') {
|
||||
var k = +el.dataset.key
|
||||
|
||||
$.each(this.__FILTER__.children, function(it) {
|
||||
it.removeAttribute('color')
|
||||
})
|
||||
el.setAttribute('color', 'blue')
|
||||
|
||||
this.state.key = k
|
||||
this._filter(k)
|
||||
this.draw()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
attributeChangedCallback(name, old, val) {
|
||||
if (val === null || old === val) {
|
||||
return
|
||||
}
|
||||
switch (name) {
|
||||
case 'list':
|
||||
try {
|
||||
var list = JSON.parse(val)
|
||||
list.forEach(it => (it.x = it.x * 1000))
|
||||
this.props.list = list
|
||||
this._filter(this.state.key)
|
||||
this.removeAttribute('list')
|
||||
this.draw()
|
||||
} catch (e) {}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!customElements.get('wc-line')) {
|
||||
customElements.define('wc-line', Line)
|
||||
}
|
|
@ -8,16 +8,18 @@
|
|||
|
||||
const RED = '#ff5061'
|
||||
const GREEN = '#4caf50'
|
||||
const BLUE = '#64b5f6'
|
||||
const GREY = '#bdbdbd'
|
||||
const PLAIN = '#f2f5fc'
|
||||
const DARK = '#62778d'
|
||||
|
||||
export default class Rank extends HTMLElement {
|
||||
static get observedAttributes() {
|
||||
return ['list']
|
||||
return ['stat']
|
||||
}
|
||||
|
||||
props = {
|
||||
list: ''
|
||||
stat: {}
|
||||
}
|
||||
|
||||
constructor() {
|
||||
|
@ -56,12 +58,12 @@ canvas {
|
|||
}
|
||||
|
||||
draw() {
|
||||
var { list } = this.props
|
||||
var { rank, e1, e3, e6, e12, cm, cp } = this.props.stat
|
||||
var ctx = this.__CTX__
|
||||
var x = 32
|
||||
|
||||
while (list.length < 60) {
|
||||
list.unshift(0)
|
||||
while (rank.length < 60) {
|
||||
rank.unshift(0)
|
||||
}
|
||||
|
||||
ctx.clearRect(0, 0, 680, 101)
|
||||
|
@ -75,15 +77,34 @@ canvas {
|
|||
ctx.fillText('-5%', 28, 80)
|
||||
ctx.fillText('-10%', 28, 100)
|
||||
|
||||
ctx.font = '10px menlo,Hiragino Sans GB'
|
||||
ctx.textAlign = 'left'
|
||||
ctx.fillStyle = DARK
|
||||
ctx.fillText('60天红绿榜', 160, 10)
|
||||
|
||||
ctx.font = '12px menlo,Hiragino Sans GB'
|
||||
ctx.fillText(`最近1个月收益: ${e1}%`, 360, 25)
|
||||
ctx.fillText(`最近3个月收益: ${e3}%`, 360, 45)
|
||||
ctx.fillText(`最近半年收益: ${e6}%`, 528, 25)
|
||||
ctx.fillText(`最近一年收益: ${e12}%`, 528, 45)
|
||||
|
||||
ctx.fillStyle = cp > 0 ? RED : cp === 0 ? GREY : GREEN
|
||||
ctx.fillRect(360, 65, 140, 20)
|
||||
ctx.fillRect(526, 65, 140, 20)
|
||||
ctx.fillStyle = '#fff'
|
||||
ctx.font = 'bold 14px menlo,Hiragino Sans GB'
|
||||
ctx.fillText(`实时净值: ¥${cm}`, 364, 80)
|
||||
ctx.fillText(`实时涨跌: ${cp}%`, 532, 80)
|
||||
|
||||
ctx.fillStyle = PLAIN
|
||||
ctx.fillRect(28, 25, 652, 1)
|
||||
ctx.fillRect(28, 75, 652, 1)
|
||||
ctx.fillRect(28, 25, 320, 1)
|
||||
ctx.fillRect(28, 75, 320, 1)
|
||||
ctx.fillStyle = GREY
|
||||
ctx.fillRect(28, 0, 1, 140)
|
||||
ctx.fillRect(0, 50, 680, 1)
|
||||
ctx.fillRect(0, 50, 348, 1)
|
||||
|
||||
while (list.length) {
|
||||
var n = list.shift()
|
||||
while (rank.length) {
|
||||
var n = rank.shift()
|
||||
var y = Math.ceil(50 - (n / 10) * 50)
|
||||
|
||||
ctx.fillStyle = n > 0 ? RED : GREEN
|
||||
|
@ -94,7 +115,7 @@ canvas {
|
|||
ctx.fillRect(x, y, 3, 50 - y)
|
||||
}
|
||||
|
||||
x += 10
|
||||
x += 5
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -103,11 +124,13 @@ canvas {
|
|||
return
|
||||
}
|
||||
switch (name) {
|
||||
case 'list':
|
||||
var list = val.split(',')
|
||||
this.props.list = list.map(n => +n)
|
||||
this.removeAttribute('list')
|
||||
case 'stat':
|
||||
try {
|
||||
var stat = JSON.parse(val)
|
||||
this.props.stat = stat
|
||||
this.removeAttribute('stat')
|
||||
this.draw()
|
||||
} catch (e) {}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
|
40
src/main.js
40
src/main.js
|
@ -4,7 +4,14 @@
|
|||
* @date 2019/09/16 20:51:19
|
||||
*/
|
||||
|
||||
const { app, BrowserWindow, protocol, ipcMain, net } = require('electron')
|
||||
const {
|
||||
app,
|
||||
BrowserWindow,
|
||||
protocol,
|
||||
ipcMain,
|
||||
net,
|
||||
Notification
|
||||
} = require('electron')
|
||||
const path = require('path')
|
||||
const fs = require('iofs')
|
||||
|
||||
|
@ -24,6 +31,8 @@ const MIME_TYPES = {
|
|||
|
||||
const ROOT = __dirname
|
||||
|
||||
var timer
|
||||
|
||||
function fetch(url) {
|
||||
return new Promise((y, n) => {
|
||||
var conn = net.request(url)
|
||||
|
@ -47,6 +56,22 @@ function fetch(url) {
|
|||
})
|
||||
}
|
||||
|
||||
function ring() {
|
||||
var n = 5
|
||||
var t = setInterval(() => {
|
||||
var notify = new Notification({
|
||||
title: '搞基⏰',
|
||||
subtitle: '神奇的2点半到啦',
|
||||
body: '神奇的2点半到啦, 该加仓的加仓, 该卖的卖啦'
|
||||
})
|
||||
notify.show()
|
||||
n--
|
||||
if (n === 0) {
|
||||
clearInterval(t)
|
||||
}
|
||||
}, 1000)
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------- */
|
||||
app.commandLine.appendSwitch('--lang', 'zh-CN')
|
||||
app.commandLine.appendSwitch('--autoplay-policy', 'no-user-gesture-required')
|
||||
|
@ -85,5 +110,18 @@ ipcMain.on('app', (ev, conn) => {
|
|||
fetch(conn.data).then(r => {
|
||||
ev.returnValue = r
|
||||
})
|
||||
} else if (conn.type === 'notify') {
|
||||
clearTimeout(timer)
|
||||
var t1 = Date.now()
|
||||
var t2 = new Date()
|
||||
t2.setHours(14)
|
||||
t2.setMinutes(0)
|
||||
t2.setSeconds(0)
|
||||
|
||||
if (t2.getTime() - t1 > 0) {
|
||||
timer = setTimeout(ring, t2.getTime() - t1)
|
||||
}
|
||||
|
||||
ev.returnValue = true
|
||||
}
|
||||
})
|
||||
|
|
|
@ -13,7 +13,7 @@ module.exports = function(win) {
|
|||
|
||||
win.__TRAY__.on('click', _ => {
|
||||
var b = win.__TRAY__.getBounds()
|
||||
win.setBounds({ x: b.x - 145, y: b.y + b.height })
|
||||
win.setBounds({ x: b.x - 120, y: b.y + b.height })
|
||||
win.show()
|
||||
win.focus()
|
||||
win.webContents.send('app', { type: 'float-visible', data: null })
|
||||
|
|
|
@ -34,19 +34,13 @@ exports.createMainWindow = function(icon) {
|
|||
show: false
|
||||
})
|
||||
|
||||
// 然后加载应用的 index.html。
|
||||
|
||||
win.loadURL('app://local/index.html')
|
||||
|
||||
// createAppTray(win)
|
||||
// ctrlTrayBtn(win)
|
||||
// createLrcTray(win)
|
||||
|
||||
createMenu(win)
|
||||
|
||||
win.on('ready-to-show', _ => {
|
||||
win.show()
|
||||
win.openDevTools()
|
||||
// win.openDevTools()
|
||||
})
|
||||
|
||||
win.on('close', ev => {
|
||||
|
@ -60,18 +54,15 @@ exports.createMainWindow = function(icon) {
|
|||
// 创建悬浮窗口
|
||||
exports.createFloatWindow = function() {
|
||||
var win = new BrowserWindow({
|
||||
width: 320,
|
||||
width: 280,
|
||||
height: 360,
|
||||
resizable: false,
|
||||
maximizable: false,
|
||||
frame: false,
|
||||
// transparent: true,
|
||||
// hasShadow: false,
|
||||
show: false,
|
||||
vibrancy: 'hud',
|
||||
visualEffectState: 'active',
|
||||
webPreferences: {
|
||||
// webSecurity: false,
|
||||
experimentalFeatures: true,
|
||||
nodeIntegration: true,
|
||||
spellcheck: false
|
||||
|
|
Loading…
Reference in New Issue