完成书本解析

master
宇天 2021-01-07 19:46:23 +08:00
parent 4b4ef306c2
commit 71aebe5cbd
19 changed files with 445 additions and 703 deletions

View File

@ -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 .category{width:200px;height:100%;background:#fff}.app .category .item{display:flex;justify-content:space-between;align-items:center;height:54px;padding:8px;border-bottom:1px solid var(--color-plain-1);background:#fff;transition:background 0.2s ease-in-out, color 0.2s ease-in-out;cursor:pointer}.app .category .item strong{max-width:150px}.app .category .item .num{display:flex;justify-content:center;align-items:center;min-width:16px;height:16px;padding:2px;line-height:1;border-radius:50%;font-size:12px;background:var(--color-grey-1);color:#fff}.app .category .item:last-child{border-bottom:0}.app .category .item:hover{color:var(--color-blue-1);background:var(--color-plain-1)}.app .category .item.active{color:var(--color-plain-1);background:var(--color-blue-1)}.app .category .item.active .num{background:#fff;color:var(--color-blue-1)}.app .detail{position:relative;flex:1;height:100%;border-left:1px solid var(--color-plain-2);background:rgba(255,255,255,0.5)}.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 .drag-mask{display:flex;align-items:center;position:fixed;left:0;top:0;z-index:9999;width:100%;height:100%;background:linear-gradient(to right, transparent, transparent 200px, #fff3e3 200px)}.app .drag-mask::after{font-size:46px;text-indent:300px;content:'Drop epub file here...';color:var(--color-grey-1)}.app .book-loading{display:flex;align-items:center;justify-content:center;position:fixed;left:0;top:0;z-index:9999;width:100%;height:100%;font-size:20px;background:rgba(255,255,255,0.01);-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px)}.app .book-loading .loading{display:flex;flex-direction:column;align-items:center;justify-content:center}.app .book-loading .loading::before{content:'🌑';font-size:36px;-webkit-animation:loading 1s infinite;animation:loading 1s infinite}@-webkit-keyframes loading{1%,100%{content:'🌑'}12.5%{content:'🌒'}25%{content:'🌓'}37.5%{content:'🌔'}50%{content:'🌕'}62.5%{content:'🌖'}75%{content:'🌗'}87.5%{content:'🌘'}}@keyframes loading{1%,100%{content:'🌑'}12.5%{content:'🌒'}25%{content:'🌓'}37.5%{content:'🌔'}50%{content:'🌕'}62.5%{content:'🌖'}75%{content:'🌗'}87.5%{content:'🌘'}}
html{width:100%;height:100vh}body{overflow:hidden;display:flex;width:100%;height:100%;line-height:1.25;font-size:14px;color:var(--color-dark-1);background:rgba(255,255,255,0.3)}.app{position:relative;display:flex;height:100%}.app .category{width:200px;height:100%;background:#fff}.app .category .item{display:flex;justify-content:space-between;align-items:center;height:54px;padding:8px;border-bottom:1px solid var(--color-plain-1);background:#fff;transition:background 0.2s ease-in-out, color 0.2s ease-in-out;cursor:pointer}.app .category .item strong{max-width:150px}.app .category .item .num{display:flex;justify-content:center;align-items:center;min-width:16px;height:16px;padding:2px;line-height:1;border-radius:50%;font-size:12px;background:var(--color-grey-1);color:#fff}.app .category .item:last-child{border-bottom:0}.app .category .item:hover{color:var(--color-blue-1);background:var(--color-plain-1)}.app .category .item.active{color:var(--color-plain-1);background:var(--color-blue-1)}.app .category .item.active .num{background:#fff;color:var(--color-blue-1)}.app .books-scroll{flex:1;height:100%;border-left:1px solid var(--color-plain-2)}.app .books{display:flex;flex-wrap:wrap}.app .books .book{display:flex;flex-direction:column;width:128px;margin:24px;background:#fff;box-shadow:0 0 12px rgba(0,0,0,0.15);transition:box-shadow 0.1s ease-in;cursor:pointer}.app .books .book img{width:100%;height:160px;-o-object-fit:fill;object-fit:fill}.app .books .book:hover{box-shadow:0 0 12px rgba(0,0,0,0.35)}.app .drag-mask{display:flex;align-items:center;position:fixed;left:0;top:0;z-index:9999;width:100%;height:100%;background:linear-gradient(to right, transparent, transparent 200px, rgba(252,232,207,0.6) 200px)}.app .drag-mask::after{font-size:46px;text-indent:360px;content:'Drop epub file here...';color:var(--color-grey-1)}.app .book-loading{display:flex;align-items:center;justify-content:center;position:fixed;left:0;top:0;z-index:9999;width:100%;height:100%;font-size:20px;background:rgba(255,255,255,0.01);-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px)}.app .book-loading .loading{display:flex;flex-direction:column;align-items:center;justify-content:center}.app .book-loading .loading::before{content:'🌑';font-size:36px;-webkit-animation:loading 1s infinite;animation:loading 1s infinite}@-webkit-keyframes loading{1%,100%{content:'🌑'}12.5%{content:'🌒'}25%{content:'🌓'}37.5%{content:'🌔'}50%{content:'🌕'}62.5%{content:'🌖'}75%{content:'🌗'}87.5%{content:'🌘'}}@keyframes loading{1%,100%{content:'🌑'}12.5%{content:'🌒'}25%{content:'🌓'}37.5%{content:'🌔'}50%{content:'🌕'}62.5%{content:'🌖'}75%{content:'🌗'}87.5%{content:'🌘'}}

View File

@ -6,7 +6,6 @@
*/
html {
font-size: 12.8px;
width: 100%;
height: 100vh;
}
@ -14,7 +13,6 @@ html {
body {
overflow: hidden;
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
line-height: 1.25;
@ -23,14 +21,6 @@ body {
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;
@ -90,43 +80,34 @@ body {
}
}
.detail {
position: relative;
.books-scroll {
flex: 1;
height: 100%;
border-left: 1px solid var(--color-plain-2);
background: rgba(255, 255, 255, 0.5);
}
.title {
.books {
display: flex;
flex-wrap: wrap;
.book {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
height: 35px;
padding: 0 16px;
font-size: 16px;
font-weight: bold;
span {
display: inline-flex;
}
wc-button {
margin: 0 6px;
}
}
.card {
width: 96%;
padding: 12px 12px 16px;
margin: 12px 2% 24px;
border: 0;
flex-direction: column;
width: 128px;
margin: 24px;
background: #fff;
box-shadow: 0 0 8px rgba(0, 0, 0, 0.075);
box-shadow: 0 0 12px rgba(0, 0, 0, 0.15);
transition: box-shadow 0.1s ease-in;
cursor: pointer;
legend {
-webkit-touch-callout: none;
user-select: none;
color: #64b5f6;
img {
width: 100%;
height: 160px;
object-fit: fill;
}
&:hover {
box-shadow: 0 0 12px rgba(0, 0, 0, 0.35);
}
}
}
@ -144,12 +125,12 @@ body {
to right,
transparent,
transparent 200px,
#fff3e3 200px
rgba(252, 232, 207, 0.6) 200px
);
&::after {
font-size: 46px;
text-indent: 300px;
text-indent: 360px;
content: 'Drop epub file here...';
color: var(--color-grey-1);
}

View File

@ -1 +0,0 @@
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)}

View File

@ -1,97 +0,0 @@
@charset "UTF-8";
/**
*
* @authors yutent<yutent@doui.cc>
* @date 2018/12/16 17:15:07
*/
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;
user-select: none;
}
.app-nodrag {
-webkit-app-region: no-drag;
}
.app {
position: relative;
display: flex;
flex-direction: column;
height: 100%;
padding: 6px 0;
.list {
flex: 1;
.item {
display: flex;
align-items: center;
height: 54px;
padding: 10px 12px;
line-height: 15px;
border-bottom: 1px solid rgba(155, 155, 155, 0.3);
&:last-child {
border-bottom: 0;
}
.info {
overflow: hidden;
flex: 1;
h3 {
font-size: 14px;
}
cite {
color: var(--color-grey-2);
}
}
.last-days {
display: flex;
width: 64px;
height: 30px;
margin: 0 6px;
}
.today {
width: 52px;
font-size: 12px;
text-align: right;
span {
display: block;
padding: 0 4px;
}
.percent {
border-radius: 2px;
color: #fff;
&.red {
background: var(--color-red-1);
}
&.green {
background: var(--color-green-3);
}
}
}
}
}
}

1
src/css/view.css Normal file
View File

@ -0,0 +1 @@
html{width:100%;height:100vh}body{display:flex;width:100%;height:100%;line-height:1.25;font-size:14px;color:var(--color-dark-1);background:rgba(255,255,255,0.3)}.app{position:relative;display:flex;width:100%;height:100%}.app .toc{width:260px;height:100%}.app .toc item{display:flex;align-items:center;height:36px;padding:0 12px;border-bottom:1px solid var(--color-plain-1);cursor:pointer}.app .toc item.lev-0{font-weight:bold}.app .toc item.lev-1{padding-left:24px;font-weight:bold}.app .toc item.lev-2{padding-left:36px}.app .toc item.lev-3{padding-left:48px}.app .toc item:hover{color:var(--color-blue-1)}.app .toc item.active{color:#fff;background:var(--color-blue-1)}.app .toc item:last-child{border-bottom:0}.app .chapter-box{flex:1;height:100%;border-left:1px solid var(--color-plain-2)}.app .chapter{display:flex;justify-content:center;padding:8px 24px}.app .chapter .detail{max-width:768px;line-height:1.5;font-size:14px}.app .chapter .detail a{text-decoration:underline;color:var(--color-teal-2)}.app .chapter .detail a:hover{color:var(--color-teal-1);text-decoration:none}.app .chapter .detail em,.app .chapter .detail del{color:var(--color-grey-2)}.app .chapter .detail strong,.app .chapter .detail strong em,.app .chapter .detail strong{color:var(--color-dark-3)}.app .chapter .detail a strong,.app .chapter .detail a em{color:inherit}.app .chapter .detail em,.app .chapter .detail strong,.app .chapter .detail del{padding:0 2px}.app .chapter .detail img{max-width:100%}.app .chapter .detail blockquote{margin:10px 0;padding:5px 10px;line-height:1.5;border-left:5px solid var(--color-teal-1);background:#f2faf7;color:var(--color-grey-2)}.app .chapter .detail blockquote p{margin:0}.app .chapter .detail>p{margin:12px 0}.app .chapter .detail ol{margin-left:1em;list-style:decimal outside none}.app .chapter .detail ul{margin-left:1em;list-style:disc outside none}.app .chapter .detail li{margin:0.5em 0}.app .chapter .detail li ol{margin-left:1em}.app .chapter .detail li ul{margin-left:1em;list-style-type:circle}.app .chapter .detail li ol ul,.app .chapter .detail li ul ul{list-style-type:square}.app .chapter .detail h1,.app .chapter .detail h2,.app .chapter .detail h3,.app .chapter .detail h4,.app .chapter .detail h5,.app .chapter .detail h6{margin:15px 0;line-height:2;font-weight:bold;font-size:16px}.app .chapter .detail h1 code.inline,.app .chapter .detail h2 code.inline,.app .chapter .detail h3 code.inline,.app .chapter .detail h4 code.inline,.app .chapter .detail h5 code.inline,.app .chapter .detail h6 code.inline{background:none}.app .chapter .detail h1 a,.app .chapter .detail h2 a,.app .chapter .detail h3 a,.app .chapter .detail h4 a,.app .chapter .detail h5 a,.app .chapter .detail h6 a{text-decoration:none;color:#333}.app .chapter .detail h3 a::before,.app .chapter .detail h4 a::before,.app .chapter .detail h5 a::before,.app .chapter .detail h6 a::before{content:'∮ ';color:var(--color-teal-1);font-weight:normal}.app .chapter .detail h1{margin:0 0 30px;font-size:24px;text-align:center}.app .chapter .detail h2{margin:20px 0;font-size:22px;border-bottom:1px solid var(--color-plain-2)}.app .chapter .detail h3{margin:20px 0 15px;font-size:20px}.app .chapter .detail h4{font-size:18px}.app .chapter .detail table{width:100%;border-spacing:0;border-collapse:collapse}.app .chapter .detail table tr{background-color:#fff}.app .chapter .detail table thead tr{background:var(--color-plain-1)}.app .chapter .detail table th,.app .chapter .detail table td{padding:6px 13px;border:1px solid var(--color-plain-2)}.app .chapter .detail table th{font-weight:bold}.app .chapter .detail table tr:nth-child(2n){background-color:#fcfdff}

233
src/css/view.scss Normal file
View File

@ -0,0 +1,233 @@
@charset "UTF-8";
/**
*
* @authors yutent<yutent@doui.cc>
* @date 2018/12/16 17:15:07
*/
html {
width: 100%;
height: 100vh;
}
body {
display: flex;
width: 100%;
height: 100%;
line-height: 1.25;
font-size: 14px;
color: var(--color-dark-1);
background: rgba(255, 255, 255, 0.3);
}
.app {
position: relative;
display: flex;
width: 100%;
height: 100%;
.toc {
width: 260px;
height: 100%;
item {
display: flex;
align-items: center;
height: 36px;
padding: 0 12px;
border-bottom: 1px solid var(--color-plain-1);
cursor: pointer;
&.lev-0 {
font-weight: bold;
}
&.lev-1 {
padding-left: 24px;
font-weight: bold;
}
&.lev-2 {
padding-left: 36px;
}
&.lev-3 {
padding-left: 48px;
}
&:hover {
color: var(--color-blue-1);
}
&.active {
color: #fff;
background: var(--color-blue-1);
}
&:last-child {
border-bottom: 0;
}
}
}
.chapter-box {
flex: 1;
height: 100%;
border-left: 1px solid var(--color-plain-2);
}
.chapter {
display: flex;
justify-content: center;
padding: 8px 24px;
.detail {
max-width: 768px;
line-height: 1.5;
font-size: 14px;
a {
text-decoration: underline;
color: var(--color-teal-2);
}
a:hover {
color: var(--color-teal-1);
text-decoration: none;
}
em,
del {
color: var(--color-grey-2);
}
strong,
strong em,
strong {
color: var(--color-dark-3);
}
a {
strong,
em {
color: inherit;
}
}
em,
strong,
del {
padding: 0 2px;
}
img {
max-width: 100%;
}
blockquote {
margin: 10px 0;
padding: 5px 10px;
line-height: 1.5;
border-left: 5px solid var(--color-teal-1);
background: #f2faf7;
color: var(--color-grey-2);
p {
margin: 0;
}
}
> p {
margin: 12px 0;
// text-indent: 2em;
}
ol {
margin-left: 1em;
list-style: decimal outside none;
}
ul {
margin-left: 1em;
list-style: disc outside none;
}
li {
margin: 0.5em 0;
}
li ol {
margin-left: 1em;
}
li ul {
margin-left: 1em;
list-style-type: circle;
}
li ol ul,
li ul ul {
list-style-type: square;
}
h1,
h2,
h3,
h4,
h5,
h6 {
margin: 15px 0;
line-height: 2;
font-weight: bold;
font-size: 16px;
code.inline {
background: none;
}
a {
text-decoration: none;
color: #333;
}
}
h3,
h4,
h5,
h6 {
a {
&::before {
content: '';
color: var(--color-teal-1);
font-weight: normal;
}
}
}
h1 {
margin: 0 0 30px;
font-size: 24px;
text-align: center;
}
h2 {
margin: 20px 0;
font-size: 22px;
border-bottom: 1px solid var(--color-plain-2);
}
h3 {
margin: 20px 0 15px;
font-size: 20px;
}
h4 {
font-size: 18px;
}
table {
width: 100%;
border-spacing: 0;
border-collapse: collapse;
tr {
background-color: #fff;
}
thead tr {
background: var(--color-plain-1);
}
th,
td {
padding: 6px 13px;
border: 1px solid var(--color-plain-2);
}
th {
font-weight: bold;
}
tr:nth-child(2n) {
background-color: #fcfdff;
}
}
}
}
}

View File

@ -25,16 +25,16 @@
<div class="detail" :class="{blur: !curr.code}">
<book :for="it in books">
<img :src="'book://cache/' + it.title + '/' + it.cover">
{{it.title}}
</book>
<wc-scroll class="books-scroll">
<list class="books">
<book class="book" :for="it in books">
<img :src="'book://cache/' + it.title + '/' + it.cover">
</book>
</list>
</wc-scroll>
</div>
<div class="drag-mask" ref="mask" :visible="isDragIn"></div>

View File

@ -7,14 +7,9 @@
*/
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/chart/line.js'
import layer from '/lib/layer/index.js'
import Utils from '/lib/utils.js'
import app from '/lib/socket.js'
@ -37,14 +32,14 @@ Anot({
load: {
num: 0,
curr: 0
}
},
$db: {}
},
watch: {},
mounted() {
$doc.bind('dragover', ev => {
ev.stopPropagation()
ev.preventDefault()
this.isDragIn = true
@ -56,9 +51,8 @@ Anot({
})
$doc.bind('drop', ev => {
ev.stopPropagation()
ev.preventDefault()
// clearTimeout(this.timer)
this.isDragIn = false
let files = Array.from(ev.dataTransfer.files)
@ -73,20 +67,34 @@ Anot({
this.load.curr = 0
this.loading = true
console.time(1)
while (this.load.curr < this.load.num) {
this.load.curr++
let book = files.pop()
let res = app.dispatch('parse-book', { book, cate: this.curr })
console.log(res)
if (res) {
this.books.push(res)
}
}
console.timeEnd(1)
this.loading = false
})
let db = app.dispatch('get-books')
let cates = [],
books
for (let k in db) {
cates.push({ name: k, num: db[k].length })
// 默认选中第一个
if (!books) {
this.curr = k
books = db[k]
}
}
// books = books.concat(books, books, books, books, books, books)
this.$db = db
this.cates = cates
this.books = books
},
methods: {}
})

View File

@ -1,94 +0,0 @@
/**
*
* @author yutent<yutent.io@gmail.com>
* @date 2020/12/10 19:53:05
*/
import '/lib/anot.js'
import '/lib/scroll/index.js'
import layer from '/lib/layer/index.js'
import app from '/lib/socket.js'
function getJsonp(str) {
if (~str.indexOf('jsonpgz')) {
return new Function(`function jsonpgz(d){return d}; return ${str}`)()
}
return false
}
Anot({
$id: 'app',
state: {
list: []
},
mounted() {
this.reloadGays()
app.on('float-visible', data => {
var time = +Anot.ss('last_update') || 0
var now = Date.now()
// 有触发小窗口显示时, 更新通知提醒
if (Anot.ls('notify') === '1') {
app.dispatch('notify')
}
this.reloadGays()
setTimeout(() => {
// 如果离上次更新超过15分钟, 则自动更新
if (now - time > 15 * 60 * 1000) {
this.updateGays()
Anot.ss('last_update', now)
}
}, 500)
})
},
methods: {
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
},
getGayStat(id) {
var res = app.dispatch(
'fetch',
`https://fundgz.1234567.com.cn/js/${id}.js`
)
return getJsonp(res)
},
updateGay(item) {
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) => b.cp - a.cp)
this.saveCache()
app.dispatch('data-reload')
},
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)
}
}
})

84
src/js/view.js Normal file
View File

@ -0,0 +1,84 @@
/**
*
* @author yutent<yutent.io@gmail.com>
* @date 2020/12/10 19:53:05
*/
import '/lib/anot.js'
import '/lib/scroll/index.js'
import '/lib/code/index.js'
import layer from '/lib/layer/index.js'
import fetch from '/lib/fetch/index.js'
import app from '/lib/socket.js'
Anot({
$id: 'app',
state: {
toc: [],
title: 'HTML5 canvas开发详解(第2版) (无)',
curr: '',
file: '',
chapter: ''
},
mounted() {
// app.on('float-visible', data => {})
document.title = this.title
this.getToc()
},
methods: {
getToc() {
fetch('book://cache/HTML5 canvas开发详解(第2版) (无)/toc.json')
.then(r => r.json())
.then(list => {
for (let it of list) {
delete it.id
delete it.order
}
this.toc = list
this.viewChapter(list[23])
})
},
viewChapter(item) {
let pathes = item.href.split('#')
let file = pathes.shift()
let hash = pathes.shift()
this.curr = item.title
if (this.file === file) {
if (hash) {
location.hash = hash
} else {
location.hash = ''
this.$refs.chapter.scrollTop = 0
}
} else {
this.file = file
fetch('book://cache/HTML5 canvas开发详解(第2版) (无)/' + file)
.then(r => r.text())
.then(txt => {
this.chapter = txt.replace(
/<img[^>]*?src="(.*?)"[^>]*?\/?>/g,
(m, s1) => {
s1 = s1.replace('../', '')
return `<img src="book://cache/${this.title}/${s1}">`
}
)
setTimeout(() => {
if (hash) {
location.hash = hash
} else {
location.hash = ''
this.$refs.chapter.scrollTop = 0
}
}, 100)
})
}
}
}
})

View File

@ -1,253 +0,0 @@
/**
*
* @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)
}

View File

@ -1,141 +0,0 @@
/**
*
* @authors yutent (yutent.io@gmail.com)
* @date 2020-12-08 11:30:52
* @version v1.0.0
*
*/
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 ['stat']
}
props = {
stat: {}
}
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; }
canvas {
width: 680px;
height: 100px; }
</style>
<canvas></canvas>
`
this.__SCENE__ = this.root.children[1]
this.__CTX__ = this.__SCENE__.getContext('2d')
this.__SCENE__.width = 680
this.__SCENE__.height = 100
}
draw() {
var { rank, e1, e3, e6, e12, cm, cp } = this.props.stat
var ctx = this.__CTX__
var x = 32
while (rank.length < 60) {
rank.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.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, 320, 1)
ctx.fillRect(28, 75, 320, 1)
ctx.fillStyle = GREY
ctx.fillRect(28, 0, 1, 140)
ctx.fillRect(0, 50, 348, 1)
while (rank.length) {
var n = rank.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 += 5
}
}
attributeChangedCallback(name, old, val) {
if (val === null || old === val) {
return
}
switch (name) {
case 'stat':
try {
var stat = JSON.parse(val)
this.props.stat = stat
this.removeAttribute('stat')
this.draw()
} catch (e) {}
break
}
}
}
if (!customElements.get('wc-rank')) {
customElements.define('wc-rank', Rank)
}

13
src/lib/code/index.js Normal file
View File

@ -0,0 +1,13 @@
/**
*
* @authors yutent (yutent.io@gmail.com)
* @date 2020-12-23 15:31:02
* @version v1.0.0
*
*/
import"../scroll/index.js";import"../layer/index.js";import $ from"../utils.js";export default class Code extends HTMLElement{static get observedAttributes(){return["dark","lang"]}props={dark:"",lang:""};constructor(){super(),Object.defineProperty(this,"root",{value:this.attachShadow({mode:"open"}),writable:!0,enumerable:!1,configurable:!0}),this.root.innerHTML='<style>*{box-sizing:border-box;margin:0;padding:0}::before,::after{box-sizing:border-box}:host{--color-teal-1: #4db6ac;--color-teal-2: #26a69a;--color-teal-3: #009688;--color-green-1: #81c784;--color-green-2: #66bb6a;--color-green-3: #4caf50;--color-purple-1: #9575cd;--color-purple-2: #9575cd;--color-purple-3: #673ab7;--color-blue-1: #64b5f6;--color-blue-2: #42a5f5;--color-blue-3: #2196f3;--color-red-1: #ff5061;--color-red-2: #eb3b48;--color-red-3: #ce3742;--color-orange-1: #ffb618;--color-orange-2: #f39c12;--color-orange-3: #e67e22;--color-plain-1: #f2f5fc;--color-plain-2: #e8ebf4;--color-plain-3: #dae1e9;--color-grey-1: #bdbdbd;--color-grey-2: #9e9e9e;--color-grey-3: #757575;--color-dark-1: #62778d;--color-dark-2: #526273;--color-dark-3: #425064}:host{display:flex}.code-box{display:flex;flex-direction:column;position:relative;width:100%;max-height:610px;margin:10px 0;border:1px solid var(--color-plain-2);border-radius:2px}.code-box .title{display:flex;justify-content:space-between;align-items:center;width:100%;height:24px;padding:0 12px;line-height:1;font-size:12px;background:var(--color-plain-2);user-select:none}.code-box .title i{display:inline-block;width:10px;height:10px;margin-right:6px;border-radius:50%;background:var(--color-red-1)}.code-box .title i:nth-child(2){background:var(--color-orange-1)}.code-box .title i:nth-child(3){background:var(--color-green-1)}.code-box .title .act{--size: 16px;margin:0 2px;color:var(--color-grey-2);cursor:pointer}.code-box .title .act:hover{color:var(--color-grey-3)}.code-box .title .act.run{display:none}.code-box .code{flex:1;padding:5px 0;line-height:18px;font-family:Menlo, Monaco, Consolas, \'Courier New\', monospace;font-size:13px;background:linear-gradient(to right, var(--color-plain-1) 40px, #fff 40px);color:var(--color-dark-1);cursor:text;counter-reset:code}.code-box .code p{display:flex;position:relative;min-height:18px;padding:0 8px 0 45px;white-space:pre-wrap;word-wrap:break-word}.code-box .code p::before{position:absolute;left:0;width:40px;height:100%;padding-right:5px;text-align:right;color:var(--color-grey-1);content:counter(code);counter-increment:code}:host([exec]) .title .run{display:inline-block}:host([dark]) .code-box{border-color:var(--color-dark-2)}:host([dark]) .code-box .title{background:var(--color-dark-2)}:host([dark]) .code-box .code{background:linear-gradient(to right, #596b7f 40px, var(--color-dark-1) 40px);color:var(--color-plain-3)}:host([dark]) .code-box .code p::before{color:var(--color-grey-3)}</style> <div class="code-box"> <header class="title"> <span><i></i><i></i><i></i></span> <span></span> <span> <wc-icon title="运行" class="act run" is="live"></wc-icon> <wc-icon title="复制" class="act cp" is="doc"></wc-icon> </span> </header> <wc-scroll axis="y" class="code"></wc-scroll> </div> ';var e=this.root.children[1],o=e.children[0];this.__CODE__=e.children[1],this.__LANG__=o.children[1],this.__RUN__=o.children[2].firstElementChild,this.__CP__=o.children[2].lastElementChild}get value(){return this.props.content}set value(e){this.props.content=e.replace(/&amp;/g,"&").replace(/&lt;/g,"<").replace(/&gt;/g,">"),e=(e=e.replace(/</g,"&lt;").replace(/>/g,"&gt;").split("\n")).map(e=>`<p>${e}</p>`).join(""),this.__CODE__.innerHTML=e}connectedCallback(){var e=this.innerHTML||this.textContent;this.value=e.replace(/^[\r\n]|\s{2,}$/g,""),this.textContent="",this._cpFN=$.bind(this.__CP__,"click",e=>{try{navigator.clipboard.writeText(this.value),layer.toast("复制到粘贴板成功","success")}catch(e){layer.toast("复制到粘贴板失败","error")}}),this._runFN=$.bind(this.__RUN__,"click",e=>{this.dispatchEvent(new CustomEvent("run",{detail:this.value}))})}unmounted(){$.unbind(this.__CP__,"click",this._cpFN),$.unbind(this.__RUN__,"click",this._runFN)}attributeChangedCallback(e,o,r){if(null!==r&&o!==r)switch(e){case"lang":this.props.lang=r.toLowerCase(),this.__LANG__.textContent=this.props.lang;break;case"value":this.value=r,this.removeAttribute("value")}}}
if(!customElements.get('wc-code')){
customElements.define('wc-code', Code)
}

1
src/lib/fetch/index.js Normal file
View File

@ -0,0 +1 @@
import{Format,toS}from"./lib/format.js";const noop=function(e,t){this.defer.resolve(t)},NOBODY_METHODS=["GET","HEAD"],FORM_TYPES={form:"application/x-www-form-urlencoded; charset=UTF-8",json:"application/json; charset=UTF-8",text:"text/plain; charset=UTF-8"},ERRORS={10001:"Argument url is required",10012:"Parse error",10100:"Request canceled",10104:"Request pending...",10200:"Ok",10204:"No content",10304:"Not modified",10500:"Internal Server Error",10504:"Connected timeout"};Promise.defer=function(){var e={};return e.promise=new Promise(function(t,s){e.resolve=t,e.reject=s}),e};class _Request{constructor(e="",t={},{BASE_URL:s,__INIT__:r}){if(!e)throw new Error(ERRORS[10001]);if(e=e.replace(/#.*$/,""),s&&(/^([a-z]+:|\/\/)/.test(e)||(e=s+e)),t.method=(t.method||"get").toUpperCase(),this.xhr=new XMLHttpRequest,this.defer=Promise.defer(),this.options={headers:{"X-Requested-With":"XMLHttpRequest","content-type":FORM_TYPES.form},body:null,cache:"default",credentials:!1,signal:null,timeout:3e4},!t.signal){var o=new AbortController;t.signal=o.signal}this.defer.promise.abort=function(){o.abort()};var i=this.options.headers;return r.headers&&Object.assign(i,r.headers),t.headers&&(Object.assign(i,t.headers),delete t.headers),Object.assign(this.options,r,t,{url:e,headers:i}),this.__next__(),this.defer.promise}__next__(){var e=this.options,t=null,s=!1,r=!1,o=NOBODY_METHODS.includes(e.method);if(e.signal.onabort=(e=>{this.cancel=!0,this.xhr.abort()}),e.body)switch(typeof e.body){case"number":case"string":this.__type__("text"),t=e.body;break;case"object":if("FORM"===e.body.nodeName)e.method=e.body.method.toUpperCase()||"POST",s=(t=Format.parseForm(e.body)).constructor===FormData;else if(e.body.constructor===FormData)s=!0,o&&(e.method="POST"),t=e.body;else{for(let t in e.body)if("[object File]"===toS.call(e.body[t])){s=!0;break}s?(o&&(e.method="POST"),t=Format.mkFormData(e.body)):t=e.body}}s&&delete e.headers["content-type"];try{let t=document.createElement("a");t.href=e.url,r=location.protocol!==t.protocol||location.host!==t.host}catch(e){}r&&(e.credentials?this.xhr.withCredentials=!0:delete e.headers["X-Requested-With"]),o?((t=Format.param(t))&&(e.url+=(~e.url.indexOf("?")?"&":"?")+t),"no-store"===e.cache&&(e.url+=(~e.url.indexOf("?")?"&":"?")+"_t_="+Date.now())):s||(t=~e.headers["content-type"].indexOf("json")?JSON.stringify(t):Format.param(t)),this.xhr.responseType="blob",this.xhr.onreadystatechange=(t=>{e.timeout>0&&(e["time"+this.xhr.readyState]=t.timeStamp,4===this.xhr.readyState&&(e.isTimeout=e.time4-e.time1>e.timeout)),4===this.xhr.readyState&&this.__dispatch__(e.isTimeout)}),this.xhr.open(e.method,e.url);for(let t in e.headers)this.xhr.setRequestHeader(t,e.headers[t]);this.xhr.send(t),e.timeout&&e.timeout>0&&(this.xhr.timeout=e.timeout)}__type__(e){this.options.headers["content-type"]=FORM_TYPES[e]}__dispatch__(e){let t={status:200,statusText:"ok",body:"",headers:Object.create(null)};if(this.cancel)return this.__cancel__();if(e)return this.__timeout__();let s=this.xhr.status>=200&&this.xhr.status<400,r=this.xhr.getAllResponseHeaders().split("\n")||[];for(let e of r)if(e=e.trim()){let s=(e=e.split(":")).shift().toLowerCase();e=e.join(":").trim(),t.headers[s]=e}s?(t.status=this.xhr.status,204===t.status?t.statusText=ERRORS[10204]:304===t.status&&(t.statusText=ERRORS[10304])):(t.status=this.xhr.status||500,t.statusText=this.xhr.statusText||ERRORS[10500]),t.body=this.xhr.response,this.__success__(s,t)}__success__(e,t){var s=new _Response(t.status,t.statusText,t.body,t.headers);e?this.defer.resolve(s):this.defer.reject(s),delete this.xhr,delete this.options,delete this.defer}__cancel__(e){var t=new _Response(0,ERRORS[10100],Object.create(null));this.defer.reject(t),delete this.xhr,delete this.options,delete this.defer}__timeout__(e){var t=new _Response(504,ERRORS[10504],Object.create(null));this.defer.reject(t),delete this.xhr,delete this.options,delete this.defer}}class _Response{constructor(e=200,t="OK",s=null,r={}){this.status=e,this.statusText=t,this.ok=e>=200&&e<400,this.headers=r,Object.defineProperty(this,"__R__",{value:s,writable:!0,enumerable:!1,configurable:!0})}text(){return this.__R__.text()}json(){return this.__R__.text().then(e=>JSON.parse(e))}blob(){return this.__R__}arrayBuffer(){return this.__R__.arrayBuffer()}}const _fetch=function(e,t){return new _Request(e,t,{BASE_URL:_fetch.BASE_URL,__INIT__:_fetch.__INIT__||Object.create(null)})};_fetch.create=function(e,t=Object.create(null)){return function(s,r){return new _Request(s,r,{BASE_URL:e,__INIT__:t})}};export default _fetch;

View File

@ -0,0 +1 @@
export const toS=Object.prototype.toString;export const encode=encodeURIComponent;export const decode=decodeURIComponent;function serialize(e,t,o){var a;if(Array.isArray(t))t.forEach(function(t,r){a=e?`${e}[${Array.isArray(t)?r:""}]`:r,"object"==typeof t?serialize(a,t,o):o(a,t)});else for(let r in t)a=e?`${e}[${r}]`:r,"object"==typeof t[r]?serialize(a,t[r],o):o(a,t[r])}export const Format={parseForm(e){let t={},o=!1;for(let a,r=0;a=e.elements[r++];)switch(a.type){case"select-one":case"select-multiple":if(a.name.length&&!a.disabled)for(let e,o=0;e=a.options[o++];)e.selected&&(t[a.name]=e.value||e.text);break;case"file":a.name.length&&!a.disabled&&(t[a.name]=a.files[0],o=!0);break;case void 0:case"submit":case"reset":case"button":break;case"radio":case"checkbox":if(!a.checked)break;default:a.name.length&&!a.disabled&&(t[a.name]=a.value)}return o?this.mkFormData(t):t},mkFormData(e){let t=new FormData;for(let o in e){let a=e[o];Array.isArray(a)?a.forEach(function(e){t.append(o+"[]",e)}):t.append(o,e[o])}return t},param(e){if(!e||"string"==typeof e||"number"==typeof e)return e;let t=[];return"object"==typeof e&&serialize("",e,function(e,o){/native code/.test(o)||(o="function"==typeof o?o():o,o="[object File]"===toS.call(o)?o:encode(o),t.push(encode(e)+"="+o))}),t.join("&")}};

View File

@ -9,7 +9,7 @@ const path = require('path')
const fs = require('iofs')
require('./tools/init')
const { createMainWindow, createFloatWindow } = require('./tools/window')
const { createMainWindow, createViewWindow } = require('./tools/window')
const createMenu = require('./tools/menu')
const Socket = require('./tools/socket')
@ -50,7 +50,9 @@ protocol.registerSchemesAsPrivileged([
app.once('ready', () => {
// 注册协议
protocol.registerStreamProtocol('app', function(req, cb) {
var file = decodeURIComponent(req.url.replace(/^app:\/\/local\//, ''))
var file = decodeURIComponent(
req.url.replace(/^app:\/\/local\//, '')
).replace(/\#.*$/, '')
var ext = path.extname(file)
file = path.resolve(ROOT, file)
@ -69,7 +71,6 @@ app.once('ready', () => {
var ext = path.extname(file)
file = path.resolve(CACHE_DIR, file)
console.log(file)
cb({
data: fs.origin.createReadStream(file),
mimeType: MIME_TYPES[ext] || MIME_TYPES.all,
@ -81,14 +82,14 @@ app.once('ready', () => {
// 创建浏览器窗口
app.__main__ = createMainWindow(path.resolve(ROOT, './images/app.png'))
// app.__float__ = createFloatWindow()
app.__view__ = createViewWindow()
createMenu(app.__main__)
Socket(app)
app.__main__.on('closed', () => {
app.__main__ = null
app.__float__ = null
app.__view__ = null
app.exit()
})

View File

@ -45,13 +45,18 @@ module.exports = function(app) {
})
break
case 'get-books':
ev.returnValue = JSON.parse(fs.cat(DB_FILE))
break
case 'parse-book':
let { book, cate } = conn.data
let eb = new Epub(book.path)
let cache = JSON.parse(fs.cat(DB_FILE))
eb.on('end', async _ => {
let { title, cover } = eb.metadata
let { title } = eb.metadata
let cover = 'cover'
let dir = path.join(CACHE_DIR, title)
function saveImage(id, name) {
@ -65,12 +70,21 @@ module.exports = function(app) {
function saveHtml(id, name) {
return new Promise(done => {
eb.getChapter(id, (err, txt) => {
// txt = (txt + '').replace(
// /<(?!img|image)([\w\-]+)[^>]*>/g,
// '<$1>'
// )
fs.echo(txt, path.join(dir, name.replace('.xhtml', '.html')))
eb.getChapterRaw(id, (err, txt) => {
let m = (txt + '').match(/<body[^>]*?>([\w\W]+)<\/body>/)
if (m) {
let htm = m[1]
.replace(
/<(?!img|image)([\w\-]+)[^>]*?( id="[^\s]*?")?[^>]*?>/g,
'<$1$2>'
)
.replace(/<pre><code>/g, '<wc-code>')
.replace(/<\/code><\/pre>/g, '</wc-code>')
fs.echo(htm, path.join(dir, name.replace('.xhtml', '.html')))
} else {
console.log(id, name, txt)
}
done()
})
})

View File

@ -27,10 +27,10 @@ exports.createMainWindow = function(icon) {
win.loadURL('app://local/index.html')
win.on('ready-to-show', _ => {
win.show()
win.openDevTools()
})
// win.on('ready-to-show', _ => {
// win.show()
// win.openDevTools()
// })
win.on('close', ev => {
ev.preventDefault()
@ -41,16 +41,14 @@ exports.createMainWindow = function(icon) {
}
// 创建悬浮窗口
exports.createFloatWindow = function() {
exports.createViewWindow = function() {
var win = new BrowserWindow({
width: 280,
height: 360,
resizable: false,
maximizable: false,
frame: false,
show: false,
vibrancy: 'hud',
visualEffectState: 'active',
width: 1024,
height: 768,
minWidth: 1024,
minHeight: 768,
// show: false,
title: 'E-pub Reader',
webPreferences: {
experimentalFeatures: true,
nodeIntegration: true,
@ -58,13 +56,9 @@ exports.createFloatWindow = function() {
}
})
// win.openDevTools()
win.openDevTools()
win.on('blur', ev => {
win.hide()
})
win.loadURL('app://local/float.html')
win.loadURL('app://local/view.html')
return win
}

View File

@ -6,31 +6,28 @@
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
<title></title>
<link href="/lib/css/reset-basic.css" rel="stylesheet">
<link href="/css/float.css" rel="stylesheet">
<script src="/js/float.js" type="module"></script>
<link href="/css/view.css" rel="stylesheet">
<script src="/js/view.js" type="module"></script>
</head>
<body class="noselect">
<body>
<div class="app" anot="app">
<wc-scroll class="list">
<section class="item" :for="it in list">
<div class="info">
<h3 class="text-ell" :text="it.name"></h3>
<cite :text="it.code"></cite>
</div>
<div class="app" anot="app">
<wc-scroll class="toc noselect">
<item
:for="it in toc"
:class="{['lev-' + it.level]: 1, active: it.title === curr}"
@click="viewChapter(it)"
>
<span class="text-ell" :attr-title="it.title" :text="it.title"></span>
</item>
</wc-scroll>
<div class="today">
<span class="money" :text="'¥' + it.cm"></span>
<span
class="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>
<wc-scroll class="chapter-box" ref="chapter">
<div class="chapter">
<article class="detail" :html="chapter"></article>
</div>
</wc-scroll>
</div>
</body>