master
宇天 2020-07-23 19:15:46 +08:00
commit 96c8c55c87
40 changed files with 635 additions and 0 deletions

16
.gitignore vendored Normal file
View File

@ -0,0 +1,16 @@
.DS_Store
.AppleDouble
.LSOverride
.idea
._*
.Spotlight-V100
.Trashes
build
build/**
node_modules
node_modules/**
package-lock.json

16
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,16 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "Debug Main Process",
"type": "node",
"request": "launch",
"cwd": "${workspaceRoot}",
"runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron",
"windows": {
"runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron.cmd"
},
"args": ["."]
}
]
}

21
LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2018
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

9
README.md Normal file
View File

@ -0,0 +1,9 @@
# 小说编辑器
> 小说编辑器。
## Update Logs
# v0.0.1 - 2020-06-01
- 立项

BIN
icons/128x128.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

BIN
icons/256x256.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

BIN
icons/512x512.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
icons/512x512.psd Normal file

Binary file not shown.

BIN
icons/app.icns Normal file

Binary file not shown.

40
package.json Normal file
View File

@ -0,0 +1,40 @@
{
"name": "io.yutent.gaystat",
"version": "0.0.1",
"description": "搞基数据",
"main": "src/main.js",
"scripts": {
"start": "electron .",
"pack": "electron-builder",
"pack:mac": "electron-builder --mac"
},
"author": {
"name": "yutent",
"email": "yutent.io@gmail.com"
},
"homepage": "https://yutent.me",
"license": "MIT",
"build": {
"appId": "cc.yutent.typec",
"productName": "typec",
"copyright": "Copyright © 2019 ${author}",
"directories": {
"buildResources": "icons",
"output": "build"
},
"files": ["src/**/*", "node_modules/iofs/*"],
"mac": {
"category": "public.app-category.developer-tools",
"target": "dmg",
"icon": "icons/app.icns",
"darkModeSupport": false
}
},
"devDependencies": {
"electron": "^9.0.0",
"electron-builder": "^22.0.0"
},
"dependencies": {
"iofs": "^1.3.2"
}
}

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

@ -0,0 +1 @@
html{font-size:12.8px;width:100%;height:100vh}body{display:flex;flex-direction:column;width:100%;height:100%;line-height:1.5;font-size:1.09375rem;color:#62778d;background:rgba(0,0,0,0.75)}

19
src/css/app.scss Normal file
View File

@ -0,0 +1,19 @@
@charset "UTF-8";
/**
*
* @authors yutent<yutent@doui.cc>
* @date 2018/12/16 17:15:07
*/
@import "./var.scss";
html {font-size:12.8px;width:100%;height:100vh;}
body {
display:flex;flex-direction: column;
width:100%;height:100%;line-height:1.5;
font-size:px(14);color:nth($cd, 1);
background:rgba(0, 0, 0, .75);
}

18
src/css/var.scss Normal file
View File

@ -0,0 +1,18 @@
$ct: #4db6ac #26a69a #009688;
$cg: #81c784 #66bb6a #4caf50;
$cpp: #ba68c8 #ba68c8 #9c27b0;
$cb: #64b5f6 #42a5f5 #2196f3;
$cr: #ff5061 #eb3b48 #ce3742;
$co: #ffb618 #f39c12 #e67e22;
$cp: #f2f5fc #e8ebf4 #dae1e9;
$cgr: #bdbdbd #9e9e9e #757575;
$cd: #62778d #526273 #425064;
@mixin ts($c: all, $t: .1s, $m: ease-in-out){
transition:$c $t $m;
}
@function px($n: 1) {
@return ($n / 12.8) + rem;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

BIN
src/images/app.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

BIN
src/images/tray@1x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 257 B

BIN
src/images/tray@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 229 B

17
src/index.html Normal file
View File

@ -0,0 +1,17 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<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/app.css" rel="stylesheet">
<script src="/js/app.js" type="module"></script>
</head>
<body anot="app" class="do-fn-noselect">
</body>
</html>

64
src/js/app.js Normal file
View File

@ -0,0 +1,64 @@
/**
* {sonist app}
*
* @format
* @author yutent<yutent@doui.cc>
* @date 2018/12/16 17:15:57
*/
import '/lib/anot.js'
// import '/lib/request/index.js'
import layer from '/lib/layer/index.js'
import Utils from '/lib/utils.js'
const log = console.log
const { remote, ipcRenderer } = require('electron')
const WIN = remote.getCurrentWindow()
const $doc = Anot(document)
Anot({
$id: 'app',
state: {
list: []
},
watch: {
'chapter.content'() {
this.calcuteWords = this.chapter.content.length
},
currCate() {
this.renderChapterList()
}
},
mounted() {
WIN.on('blur', _ => {
// this.focus = false
// this.btns.min = this.btns.close = BTNS_DICT.grey
})
// WIN.on('focus', _ => {
// this.focus = true
// this.btns.min = BTNS_DICT.min
// this.btns.close = BTNS_DICT.close
// })
this.getTodayStat('006736')
},
methods: {
getTodayStat(id) {
var res = ipcRenderer.sendSync(
'net',
`https://fundgz.1234567.com.cn/js/${id}.js`
)
// `http://fund.eastmoney.com/f10/F10DataApi.aspx?type=lsjz&code=006736`
log(res)
// fetch(`https://fundgz.1234567.com.cn/js/${id}.js`).then(res => {
// log(res)
// })
}
}
})

8
src/lib/anot.js Normal file

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,60 @@
@charset "UTF-8";
/**
*
* @authors yutent (yutent@doui.cc)
* @date 2014-10-10 00:45:09
*
* douiCSS
*
* ,
* do-st-*
* do-fn-*
* do-mod-modname
* UIdo-uiname, .do-uiname
* .do-layer .body { ... }
*
*
* 1 display float position overflow z-index /
* 2 width height margin padding border
* 3 line-height font-size vertical-align text-align user-select outline ....
* 4 color background opacity cursor ...
* 5 content list-style quotes ...
*
*/
* {margin: 0;padding: 0;vertical-align: baseline;box-sizing:border-box;}
::before,::after {box-sizing:border-box;}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section,content {display: block;}
img {border:0;display:inline-block;}
ol, ul {list-style: none;}
blockquote, q {quotes: none;}
blockquote::before, blockquote::after,
q::before, q::after {content: '';content: none;}
table {border-collapse: collapse;border-spacing: 0;}
a:focus,input,textarea,button:focus,input:focus,textarea:focus {outline:none;}
::-moz-focus-inner {
border:none;outline:none;
}
body {font-family:Helvetica, Arial,"WenQuanYi Micro Hei","PingFang SC","Hiragino Sans GB","Segoe UI", "Microsoft Yahei", sans-serif;-webkit-font-smoothing: antialiased;text-size-adjust: 100%;-webkit-tap-highlight-color: transparent;}
code,pre,samp {font-family:Menlo,Monaco,Consolas,"Courier New",monospace;}
[anot],[\:repeat],[\:if],[is-widget],slot {visibility:hidden;}
.do-fn-cl { *zoom: 1; }
.do-fn-cl::after { content: "."; display: block; height: 0; clear: both; visibility: hidden; overflow:hidden;}
.do-fn-clear {clear:both;display:inline;}
.do-fn-show{display:block;}
.do-fn-hide{display:none;}
.do-fn-fl{float:left;}
.do-fn-fr{float:right;}
.do-fn-noselect {-webkit-touch-callout: none;-webkit-user-select: none;-moz-user-select: none;user-select: none;}
.do-fn-noselect img, .do-fn-noselect a {-webkit-user-drag:none;}
.do-fn-ell {overflow:hidden; white-space:nowrap; text-overflow:ellipsis }
.do-st-thin {-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;}
.do-st-hand {cursor:pointer;}
[class^="do-icon-"], [class*=" do-icon-"] {display:inline-block;font-family:"uifont" !important;font-style:normal;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;}

1
src/lib/drag/core.js Normal file
View File

@ -0,0 +1 @@
"use strict";import $ from"../utils.js";const DEF_OPT={axis:"",limit:!1,overflow:!0};export default class Drag{constructor(t){this.$elem=t,this._init()}_init(){this.$elem.style.transform="";var{x:t,y:s}=this.$elem.getBoundingClientRect();this.pos={x:t,y:s,_x:0,_y:0}}by(t,s={}){return this.$drag=t,this.opt=Object.assign(Object.create(null),DEF_OPT,s),!1!==this.opt.limit&&(this.opt.overflow=!1),t.style.cursor="move",this._handleResize=$.bind(window,"resize",this._init.bind(this)),this._handleMousedown=$.bind(t,"mousedown",t=>{if(this.disabled)return;var s=this.$elem.getBoundingClientRect();s.x-this.pos._x!==this.pos.x&&(this.pos.x=s.x-this.pos._x),s.y-this.pos._y!==this.pos.y&&(this.pos.y=s.y-this.pos._y);let e=t.pageX,i=t.pageY,o=document.documentElement.clientWidth,n=document.documentElement.clientHeight,h=s.width,p=s.height,d=[0,o-h,n-p,0];if("parent"===this.opt.limit){let t=this.$elem.parentNode.getBoundingClientRect();d=[t.top,t.right-h,t.bottom-p,t.left]}let l=$.bind(document,"mousemove",t=>{t.preventDefault();let o=t.pageX-e+(s.x-this.pos.x),n=t.pageY-i+(s.y-this.pos.y);"x"===this.opt.axis&&(n=0),"y"===this.opt.axis&&(o=0),!1===this.opt.overflow&&(o<d[3]-this.pos.x?o=d[3]-this.pos.x:o>d[1]-this.pos.x&&(o=d[1]-this.pos.x),n<d[0]-this.pos.y?n=d[0]-this.pos.y:n>d[2]-this.pos.y&&(n=d[2]-this.pos.y)),this.pos._x=o,this.pos._y=n,this.$elem.dispatchEvent(new CustomEvent("dragging",{detail:{offset:{x:this.pos.x+o,y:this.pos.y+n},move:{x:o,y:n}}})),this.$elem.style.transform=`translate(${o}px, ${n}px)`}),m=$.bind(document,"mouseup",t=>{this.$elem.dispatchEvent(new CustomEvent("dragged",{detail:{offset:{x:this.pos.x+this.pos._x,y:this.pos.y+this.pos._y},move:{x:this.pos._x,y:this.pos._y}}})),$.unbind(document,"mousemove",l),$.unbind(document,"mouseup",m)})}),this}on(t,s){if(t&&"function"==typeof s)return $.bind(this,t,s)}off(t,s){$.unbind(this,t,s)}destroy(){$.unbind(window,"resize",this._handleResize),$.unbind(this.$drag,"mousedown",this._handleMousedown),delete this.$elem,delete this.$drag}};

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

@ -0,0 +1 @@
"use strict";import Drag from"./core.js";Anot.directive("drag",{priority:1500,init:function(e){e.expr='"'+e.expr+'"',e.overflow=!0,e.axis="xy",e.element.dataset.axis&&(e.axis=e.element.dataset.axis,delete e.element.dataset.axis),e.limit=!1,e.element.dataset.limit&&(e.limit=e.element.dataset.limit,e.overflow=!1,delete e.element.dataset.limit)},update:function(e){var t=this.element;if(e)for(t=this.element.parentNode;t;){if(t.classList||Anot.error(`${this.name}=${this.expr}, 解析异常[元素不存在]`),"WC-LAYER"===t.tagName&&"layer"===e){t=t.root.children[1];break}if(t.classList.contains(e)||t.id===e)break;t=t.parentNode}new Drag(t).by(this.element,{limit:this.limit,axis:this.axis,overflow:this.overflow})}});

15
src/lib/form/button.js Normal file

File diff suppressed because one or more lines are too long

15
src/lib/form/checkbox.js Normal file
View File

@ -0,0 +1,15 @@
/**
*
* @authors yutent (yutent.io@gmail.com)
* @date 2020-07-22 19:57:05
* @version v2.0.1
*
*/
'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="<style>*{box-sizing:border-box;margin:0;padding:0}::before,::after{box-sizing:border-box}:host{display:inline-block;line-height:1;font-size:14px}:host label{display:flex;justify-content:center;align-items:center;min-width:32px;height:32px;padding:0 5px;line-height:0;-moz-user-select:none;user-select:none;white-space:nowrap;cursor:inherit;color:#757575}:host .dot{--size: 18px;padding:2px;margin-right:3px}:host([readonly]){opacity:0.8}:host([disabled]){cursor:not-allowed;opacity:0.6}:host([size='large']){font-size:16px}:host([size='large']) label{height:42px}:host([size='large']) .dot{--size: 22px}:host([size='medium']) label{height:38px}:host([size='medium']) .dot{--size: 20px}:host([size='mini']){font-size:12px}:host([size='mini']) label{height:20px}:host([size='mini']) .dot{--size: 14px}:host([color='red']) label.checked{color:#ff5061}:host([color='red']) label.checked .dot{border-color:#ff5061}:host([color='red']) label.checked .dot::after{background:#ff5061}:host([color='blue']) label.checked{color:#64b5f6}:host([color='blue']) label.checked .dot{border-color:#64b5f6}:host([color='blue']) label.checked .dot::after{background:#64b5f6}:host([color='green']) label.checked{color:#81c784}:host([color='green']) label.checked .dot{border-color:#81c784}:host([color='green']) label.checked .dot::after{background:#81c784}:host([color='teal']) label.checked{color:#4db6ac}:host([color='teal']) label.checked .dot{border-color:#4db6ac}:host([color='teal']) label.checked .dot::after{background:#4db6ac}:host([color='orange']) label.checked{color:#ffb618}:host([color='orange']) label.checked .dot{border-color:#ffb618}:host([color='orange']) label.checked .dot::after{background:#ffb618}:host([color='dark']) label.checked{color:#62778d}:host([color='dark']) label.checked .dot{border-color:#62778d}:host([color='dark']) label.checked .dot::after{background:#62778d}:host([color='purple']) label.checked{color:#9575cd}:host([color='purple']) label.checked .dot{border-color:#9575cd}:host([color='purple']) label.checked .dot::after{background:#9575cd}</style> <label> <wc-icon class=\"dot\" is=\"checkbox-off\"></wc-icon> <slot></slot> </label> ",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}}};
if(!customElements.get('wc-checkbox')){
customElements.define('wc-checkbox', Checkbox)
}

15
src/lib/form/input.js Normal file

File diff suppressed because one or more lines are too long

15
src/lib/form/number.js Normal file

File diff suppressed because one or more lines are too long

15
src/lib/form/progress.js Normal file
View File

@ -0,0 +1,15 @@
/**
*
* @authors yutent (yutent.io@gmail.com)
* @date 2020-07-22 19:57:05
* @version v2.0.1
*
*/
'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="<style>*{box-sizing:border-box;margin:0;padding:0}::before,::after{box-sizing:border-box}:host{display:flex;align-items:center}:host label{flex:1;height:var(--size, 10px);border-radius:9px;background:#e8ebf4}:host label span{display:block;width:0;height:100%;border-radius:9px;background:#4db6ac}:host([size='large']) label{height:18px}:host([size='medium']) label{height:14px}:host([size='mini']) label{height:6px}:host([color='red']) label span{background:#ff5061}:host([color='blue']) label span{background:#64b5f6}:host([color='green']) label span{background:#81c784}:host([color='orange']) label span{background:#ffb618}:host([color='dark']) label span{background:#62778d}:host([color='purple']) label span{background:#9575cd}</style> <label><span></span></label> ",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())}}};
if(!customElements.get('wc-progress')){
customElements.define('wc-progress', Progress)
}

15
src/lib/form/radio.js Normal file
View File

@ -0,0 +1,15 @@
/**
*
* @authors yutent (yutent.io@gmail.com)
* @date 2020-07-22 19:57:05
* @version v2.0.1
*
*/
'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="<style>*{box-sizing:border-box;margin:0;padding:0}::before,::after{box-sizing:border-box}:host{display:inline-block;line-height:1;font-size:14px}:host label{display:flex;justify-content:center;align-items:center;min-width:32px;height:32px;padding:0 5px;line-height:0;-moz-user-select:none;user-select:none;white-space:nowrap;cursor:inherit;color:#757575}:host label.checked .dot::after{content:''}:host .dot{display:flex;justify-content:center;align-items:center;width:18px;height:18px;padding:2px;margin-right:3px;border:1px solid #bdbdbd;border-radius:50%;background:#fff}:host .dot::after{display:block;width:12px;height:12px;border-radius:50%;background:#bdbdbd}:host([readonly]){opacity:0.8}:host([disabled]){cursor:not-allowed;opacity:0.6}:host([size='large']) label{min-width:58px;height:32px}:host([size='large']) .dot{width:26px;height:26px}:host([size='large']) .dot::after{width:18px;height:18px}:host([size='medium']) label{min-width:50px;height:28px}:host([size='medium']) .dot{width:22px;height:22px}:host([size='medium']) .dot::after{width:14px;height:14px}:host([size='mini']) label{height:14px}:host([size='mini']) .dot{width:14px;height:14px}:host([size='mini']) .dot::after{width:8px;height:8px}:host([color='red']) label.checked{color:#ff5061}:host([color='red']) label.checked .dot{border-color:#ff5061}:host([color='red']) label.checked .dot::after{background:#ff5061}:host([color='blue']) label.checked{color:#64b5f6}:host([color='blue']) label.checked .dot{border-color:#64b5f6}:host([color='blue']) label.checked .dot::after{background:#64b5f6}:host([color='green']) label.checked{color:#81c784}:host([color='green']) label.checked .dot{border-color:#81c784}:host([color='green']) label.checked .dot::after{background:#81c784}:host([color='teal']) label.checked{color:#4db6ac}:host([color='teal']) label.checked .dot{border-color:#4db6ac}:host([color='teal']) label.checked .dot::after{background:#4db6ac}:host([color='orange']) label.checked{color:#ffb618}:host([color='orange']) label.checked .dot{border-color:#ffb618}:host([color='orange']) label.checked .dot::after{background:#ffb618}:host([color='dark']) label.checked{color:#62778d}:host([color='dark']) label.checked .dot{border-color:#62778d}:host([color='dark']) label.checked .dot::after{background:#62778d}:host([color='purple']) label.checked{color:#9575cd}:host([color='purple']) label.checked .dot{border-color:#9575cd}:host([color='purple']) label.checked .dot::after{background:#9575cd}</style> <label> <span class=\"dot\"></span> <slot></slot> </label> ",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}}};
if(!customElements.get('wc-radio')){
customElements.define('wc-radio', Radio)
}

15
src/lib/form/select.js Normal file

File diff suppressed because one or more lines are too long

15
src/lib/form/star.js Normal file
View File

@ -0,0 +1,15 @@
/**
*
* @authors yutent (yutent.io@gmail.com)
* @date 2020-07-22 19:57:05
* @version v2.0.1
*
*/
'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='<style>*{box-sizing:border-box;margin:0;padding:0}::before,::after{box-sizing:border-box}:host{display:flex;-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;user-select:none;cursor:pointer;font-size:14px;--size: 24px}label{display:flex;align-items:center;line-height:0;cursor:inherit}label wc-icon{margin:0 3px;transition:transform .1s ease-in-out}label wc-icon:hover{transform:scale(1.05)}label span{padding:0 8px;margin:0 3px}:host([size=\'large\']){font-size:16px;--size: 36px}:host([size=\'medium\']){--size: 30px}:host([size=\'mini\']){font-size:12px;--size: 20px}:host([color=\'red\']) label span{color:#ff5061}:host([color=\'teal\']) label span{color:#4db6ac}:host([color=\'green\']) label span{color:#81c784}:host([color=\'grey\']) label span{color:#bdbdbd}:host([color=\'blue\']) label span{color:#64b5f6}:host([color=\'purple\']) label span{color:#9575cd}:host([color=\'orange\']) label span{color:#ffb618}:host([disabled]){cursor:default;opacity:0.6}:host([disabled]) label wc-icon:hover{transform:none}</style> <label> <wc-icon data-idx="0" is="star" color="grey"></wc-icon> <wc-icon data-idx="1" is="star" color="grey"></wc-icon> <wc-icon data-idx="2" is="star" color="grey"></wc-icon> <wc-icon data-idx="3" is="star" color="grey"></wc-icon> <wc-icon data-idx="4" is="star" color="grey"></wc-icon> <span class="text"></span> </label> ',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",s<t?"star-full":"star"),e.setAttribute("color",s<t?this.props.color:"grey")}),e>0&&(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}}};
if(!customElements.get('wc-star')){
customElements.define('wc-star', Star)
}

15
src/lib/form/switch.js Normal file
View File

@ -0,0 +1,15 @@
/**
*
* @authors yutent (yutent.io@gmail.com)
* @date 2020-07-22 19:57:05
* @version v2.0.1
*
*/
'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="<style>*{box-sizing:border-box;margin:0;padding:0}::before,::after{box-sizing:border-box}:host{display:inline-block}:host section{display:flex;justify-content:center;align-items:center;line-height:0;white-space:nowrap}:host label{display:flex;align-items:center;width:32px;height:18px;padding:3px;margin:5px;border-radius:21px;background:#dae1e9;cursor:inherit}:host label.checked{flex-direction:row-reverse;background:#757575}:host .dot{width:12px;height:12px;border-radius:50%;background:#fff}:host([disabled]){cursor:not-allowed;opacity:0.6}:host([size='large']) label{width:46px;height:26px;padding:3px 5px}:host([size='large']) .dot{width:18px;height:18px}:host([size='medium']) label{width:38px;height:22px;padding:3px 4px}:host([size='medium']) .dot{width:16px;height:16px}:host([size='mini']) label{width:22px;height:14px;padding:2px}:host([size='mini']) .dot{width:10px;height:10px}:host([color='red']) label.checked{background:#ff5061}:host([color='blue']) label.checked{background:#64b5f6}:host([color='green']) label.checked{background:#81c784}:host([color='teal']) label.checked{background:#4db6ac}:host([color='orange']) label.checked{background:#ffb618}:host([color='dark']) label.checked{background:#62778d}:host([color='purple']) label.checked{background:#9575cd}</style> <section> <label> <span class=\"dot\"></span> </label> <slot></slot> </section> ",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+""}}};
if(!customElements.get('wc-switch')){
customElements.define('wc-switch', Switch)
}

15
src/lib/icon/index.js Normal file
View File

@ -0,0 +1,15 @@
/**
*
* @authors yutent (yutent@doui.cc)
* @date 2020-07-07 16:27:17
* @version v2.0.1
*
*/
'use strict'
import SVG_DICT from"./svg.js";let dict=SVG_DICT;window.EXT_SVG_DICT&&Object.assign(dict,EXT_SVG_DICT);export default class Icon extends HTMLElement{static get observedAttributes(){return["is"]}constructor(){super(),Object.defineProperty(this,"root",{value:this.attachShadow({mode:"open"}),writable:!0,enumerable:!1,configurable:!0}),Object.defineProperty(this,"props",{value:{is:""},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{display:inline-block;color:inherit}:host(:not([is])){display:none}.icon{display:block;width:var(--size, 32px);height:var(--size, 32px);margin:var(--pad, auto);fill:currentColor}.icon.load{animation:load 1.5s linear infinite}.icon circle{stroke:currentColor;animation:circle 1.5s ease-in-out infinite}:host([size='large']) .icon{width:42px;height:42px}:host([size='medium']) .icon{width:38px;height:38px}:host([size='mini']) .icon{width:20px;height:20px}:host([color='red']){color:#ff5061}:host([color='blue']){color:#64b5f6}:host([color='green']){color:#81c784}:host([color='teal']){color:#4db6ac}:host([color='orange']){color:#ffb618}:host([color='dark']){color:#62778d}:host([color='purple']){color:#9575cd}:host([color='grey']){color:#bdbdbd}@keyframes circle{0%{stroke-dasharray:0, 3812px;stroke-dashoffset:0}50%{stroke-dasharray:1906px, 3812px;stroke-dashoffset:-287px}100%{stroke-dasharray:1906px, 3812px;stroke-dashoffset:-2393px}}@keyframes load{to{transform:rotate(360deg)}}</style> <svg class=\"icon\" viewBox=\"0 0 1024 1024\"></svg> ",this.__ICO__=this.root.lastElementChild,this.drawPath()}get is(){return this.props.is}set is(o){o&&this.setAttribute("is",o)}drawPath(){var{is:o}=this.props,t=dict[o];this.__ICO__&&o&&t&&(this.__ICO__.innerHTML="loading"===o?t:`<path d="${t}" />`,this.__ICO__.classList.toggle("load","loading"===o))}attributeChangedCallback(o,t,e){if(null!==e&&t!==e)switch(o){case"is":this.props.is=e,e?this.drawPath():this.removeAttribute("is")}}};
if(!customElements.get('wc-icon')){
customElements.define('wc-icon', Icon)
}

1
src/lib/icon/svg.js Normal file

File diff suppressed because one or more lines are too long

15
src/lib/layer/index.js Normal file

File diff suppressed because one or more lines are too long

15
src/lib/scroll/index.js Normal file

File diff suppressed because one or more lines are too long

1
src/lib/utils.js Normal file
View File

@ -0,0 +1 @@
function noop(){}export default{nextTick:function(){let t=[];let e=document.createTextNode("\x3c!-- --\x3e");new MutationObserver(function(){let e=t.length;for(let n=0;n<e;n++)t[n]();t=t.slice(e)}).observe(e,{characterData:!0});let n=!1;return function(i){t.push(i),n=!n,e.data=n}}(),each(t,e){if(t)if(Array.isArray(t))for(let n,i=0;(n=t[i++])&&!1!==e(n,i-1););else for(let n in t)if(t.hasOwnProperty(n)&&!1===e(t[n],n))break},bind(t,e,n=noop,i=!1){let o=e.split(",");return this.each(o,function(e){e=e.trim(),t.addEventListener(e,n,i)}),n},catch(t,e,n,i){return this.bind(t,e,function(t){t.stopPropagation(),n&&n(t)},i)},unbind(t,e,n=noop,i=!1){let o=e.split(",");this.each(o,function(e){e=e.trim(),t.removeEventListener(e,n,i)})},outside(t,e=noop){return this.bind(document,"mousedown",n=>{if(n)if(n.path){for(var i=n.path.concat();i.length>3;)if(i.shift()===t)return}else{var o=n.explicitOriginalTarget||n.target;if(t===o||t.contains(o)||t.root&&t.root.contains(o))return}e(n)})},clearOutside(t=noop){this.unbind(document,"mousedown",t)}};

109
src/main.js Normal file
View File

@ -0,0 +1,109 @@
/**
*
* @author yutent<yutent@doui.cc>
* @date 2019/09/16 20:51:19
*/
const { app, BrowserWindow, protocol, ipcMain, net } = require('electron')
const path = require('path')
const fs = require('iofs')
const createMenu = require('./tools/menu')
const createTay = require('./tools/tray')
const log = console.log
const MIME_TYPES = {
'.js': 'text/javascript',
'.html': 'text/html',
'.htm': 'text/plain',
'.css': 'text/css',
'.jpg': 'image/jpg',
'.png': 'image/png',
'.gif': 'image/gif',
'.svg': 'image/svg+xml',
'.ico': 'image/ico'
}
const ROOT = __dirname
function fetch(url) {
return new Promise((y, n) => {
var conn = net.request(url)
var r = []
conn.on('response', res => {
res.on('data', c => {
r.push(c)
})
res.on('end', _ => {
y(Buffer.concat(r).toString())
})
})
conn.on('error', e => {
n(e)
})
conn.end()
})
}
/* ----------------------------------------------------- */
app.commandLine.appendSwitch('--lang', 'zh-CN')
app.commandLine.appendSwitch('--autoplay-policy', 'no-user-gesture-required')
protocol.registerSchemesAsPrivileged([
{ scheme: 'app', privileges: { secure: true, standard: true } }
])
/* ----------------------------------------------------- */
// app.dock.hide()
// 初始化应用
app.once('ready', () => {
// 注册协议
protocol.registerBufferProtocol('app', (req, cb) => {
let file = req.url.replace(/^app:\/\/local\//, '')
let ext = path.extname(req.url)
let buff = fs.cat(path.resolve(ROOT, file))
cb({ data: buff, mimeType: MIME_TYPES[ext] })
})
// 创建浏览器窗口
let win = new BrowserWindow({
title: '',
width: 375,
height: 360,
resizable: false,
maximizable: false,
frame: false,
transparent: true,
show: false,
icon: path.resolve(ROOT, './images/app.png'),
webPreferences: {
webSecurity: false,
experimentalFeatures: true,
nodeIntegration: true
}
})
win.on('closed', () => {
app.exit()
win = null
})
win.openDevTools()
// 然后加载应用的 index.html
win.loadURL('app://local/index.html')
createMenu(win)
createTay(win)
})
ipcMain.on('net', (ev, url) => {
fetch(url).then(r => {
ev.returnValue = r
})
})

32
src/tools/menu.js Normal file
View File

@ -0,0 +1,32 @@
/**
* 菜单项
* @author yutent<yutent@doui.cc>
* @date 2019/01/21 20:34:04
*/
'use strict'
const { Menu } = require('electron')
module.exports = function(win) {
let menuList = Menu.buildFromTemplate([
{
label: '搞基数据',
submenu: [
{ role: 'about', label: '关于搞基数据' },
{ type: 'separator' },
{ role: 'quit', label: '退出' }
]
},
{
label: '编辑',
submenu: [
{ role: 'cut', label: '剪切' },
{ role: 'copy', label: '复制' },
{ role: 'paste', label: '粘贴' },
{ role: 'selectall', label: '全选' }
]
}
])
Menu.setApplicationMenu(menuList)
}

21
src/tools/tray.js Normal file
View File

@ -0,0 +1,21 @@
/**
* 托盘
* @author yutent<yutent.io@gmail.com>
* @date 2019/01/21 20:42:07
*/
'use strict'
const { app, Tray } = require('electron')
const path = require('path')
const ROOT = __dirname
module.exports = function(win) {
app.__TRAY__ = new Tray(path.join(ROOT, '../images/tray.png'))
app.__TRAY__.on('click', _ => {
var b = app.__TRAY__.getBounds()
win.setBounds({ x: b.x - 185, y: b.y + b.height + 4 })
win.show()
})
}