any-rule/src/App.vue

299 lines
9.1 KiB
Vue
Raw Normal View History

2019-06-25 13:30:32 +08:00
<template>
<main>
<header>
<h1>正则大全</h1>
2019-06-25 17:29:07 +08:00
<a href="https://github.com/any86/any-rule" target="_blank" class="github"><svg height="20" viewBox="0 0 16 16" version="1.1" width="20" aria-hidden="true"><path fill-rule="evenodd" d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8z"></path></svg><span> github</span></a>
<a class="btn-msg" href="https://github.com/any86/any-rule" target="_blank">留言</a>
2019-06-25 16:08:42 +08:00
<input
ref="searchInput"
v-model="keyword"
autofocus
@keyup="search"
@mouseenter="selectSearchInputText"
@focus="selectSearchInputText"
class="search-input"
placeholder="搜索关键词, 如'手机'"
type="text"
>
2019-06-25 13:30:32 +08:00
</header>
<article>
2019-06-25 16:08:42 +08:00
<ul v-if="0 < rules.length" class="list">
<li
@mouseenter="mouseenterHandler(index)"
v-for="({title, rule, events}, index) in rules"
:key="title"
class="row"
>
<i class="border"></i>
2019-06-25 13:30:32 +08:00
<h2>{{title}}</h2>
2019-06-25 16:08:42 +08:00
<p class="rule">
<span :data-clipboard-text="rule" class="btn-copy">复制</span>
{{rule}}
</p>
2019-06-25 13:30:32 +08:00
<section class="verification">
<label>
<input
2019-06-25 16:08:42 +08:00
ref="input"
2019-06-25 13:30:32 +08:00
v-model="list[index].value"
@blur="check(index, 'blur')"
@keyup="check(index, 'keyup')"
>
2019-06-25 16:08:42 +08:00
<span class="btn-clear" @click="reset(index)">清空</span>
2019-06-25 13:30:32 +08:00
</label>
2019-06-25 16:08:42 +08:00
<div class="tip">
<template v-if="undefined !== list[index].isOk">
<p v-if="list[index].isOk" class="success">通过</p>
<p v-else class="error">不通过</p>
</template>
</div>
2019-06-25 13:30:32 +08:00
</section>
<section class="trigger">
<h3>验证时机</h3>
<label>
<input v-model="list[index].events.blur" type="checkbox"> blur
</label>
<label>
<input v-model="list[index].events.keyup" type="checkbox"> keyup
</label>
</section>
</li>
</ul>
2019-06-25 16:08:42 +08:00
<p v-else align="center">无数据</p>
2019-06-25 13:30:32 +08:00
</article>
</main>
</template>
<script>
import RULES from '@/RULES';
2019-06-25 16:08:42 +08:00
import ClipboardJS from 'clipboard';
2019-06-25 13:30:32 +08:00
export default {
name: 'app',
components: {},
data() {
Object.freeze(RULES);
return {
2019-06-25 16:08:42 +08:00
keyword: '',
rules:RULES,
2019-06-25 13:30:32 +08:00
list: RULES.map(() => ({
value: '',
isOk: undefined,
events: {
blur: true,
2019-06-25 17:29:07 +08:00
keyup: true
2019-06-25 13:30:32 +08:00
}
}))
};
},
2019-06-25 16:08:42 +08:00
mounted() {
const clipboard = new ClipboardJS('.btn-copy');
this.$on('hook:destroyed', () => {
clipboard.destroy();
});
clipboard.on('success', ()=> {
alert('复制成功!');
// console.info('Action:', e.action);
// console.info('Text:', e.text);
// console.info('Trigger:', e.trigger);
// e.clearSelection();
});
},
2019-06-25 13:30:32 +08:00
methods: {
2019-06-25 16:08:42 +08:00
search() {
if ('' !== this.keyword){
this.rules = this.rules.filter(({ title }) => -1 !== title.indexOf(this.keyword.toLowerCase()));
} else {
this.rules = RULES;
}
},
selectSearchInputText() {
this.$refs.searchInput.select();
},
mouseenterHandler(index) {
this.$refs.input[index].focus();
},
2019-06-25 13:30:32 +08:00
reset(index) {
2019-06-25 16:08:42 +08:00
this.$nextTick(() => {
this.list[index].value = '';
this.list[index].isOk = undefined;
});
2019-06-25 13:30:32 +08:00
},
check(index, type) {
2019-06-25 16:08:42 +08:00
const { events, value } = this.list[index];
if ('' === value) this.reset(index);
2019-06-25 13:30:32 +08:00
if (events[type]) {
2019-06-25 16:08:42 +08:00
const { rule } = this.rules[index];
2019-06-25 13:30:32 +08:00
const row = this.list[index];
row.isOk = rule.test(row.value);
}
}
}
};
</script>
<style lang="scss" scoped>
2019-06-25 16:08:42 +08:00
$primary: rgb(139, 204, 102);
2019-06-25 13:30:32 +08:00
$radius: 4px;
2019-06-25 16:08:42 +08:00
@keyframes shrinkBorder {
from {
}
50% {
width: 30px;
opacity: 0.62;
}
to {
left: 0;
}
}
2019-06-25 13:30:32 +08:00
main {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
2019-06-25 17:29:07 +08:00
max-width: 1000px;
width:100%;
2019-06-25 16:08:42 +08:00
margin: auto;
2019-06-25 13:30:32 +08:00
header {
padding: 15px;
2019-06-25 16:08:42 +08:00
> .search-input {
margin-top: 15px;
font-size: 16px;
border: 1px solid #ddd;
width: 100%;
padding: 15px;
border-radius: $radius;
box-shadow: 1px 2px 2px rgba(0, 0, 0, 0.1);
}
2019-06-25 17:29:07 +08:00
h1{display:inline-block;}
.github{
margin-left:15px;
display:inline-flex;
width:100px;
height:30px;
>span{padding-left:5px;}
}
.btn-msg{padding:5px;background:$primary;}
2019-06-25 13:30:32 +08:00
}
ul.list {
2019-06-25 16:08:42 +08:00
padding: 15px;
2019-06-25 13:30:32 +08:00
li {
2019-06-25 16:08:42 +08:00
position: relative;
overflow: hidden;
2019-06-25 13:30:32 +08:00
border-radius: $radius;
2019-06-25 16:08:42 +08:00
margin-bottom: 15px;
2019-06-25 13:30:32 +08:00
padding: 15px;
border-color: #eee;
2019-06-25 16:08:42 +08:00
border-width: 1px;
2019-06-25 13:30:32 +08:00
border-style: solid;
2019-06-25 16:08:42 +08:00
> .border {
position: absolute;
background: $primary;
width: 4px;
height: 100%;
top: 0;
left: -4px;
}
&:hover {
background-color: #ddd;
transition: all 600ms;
2019-06-25 13:30:32 +08:00
border-radius: $radius;
border-color: #eee;
2019-06-25 16:08:42 +08:00
> .border {
animation: shrinkBorder 1s;
left: 0;
}
2019-06-25 13:30:32 +08:00
}
> p.rule {
margin-top: 15px;
padding: 5px 15px;
background: #eee;
2019-06-25 16:08:42 +08:00
color: #000;
2019-06-25 13:30:32 +08:00
border-radius: $radius;
2019-06-25 17:29:07 +08:00
line-height:2;
2019-06-25 16:08:42 +08:00
> .btn-copy {
border-radius: $radius;
margin-right: 15px;
padding: 5px;
background: $primary;
color: #fff;
font-size: 12px;
cursor: pointer;
&:active {
opacity: 0.6;
color: #444;
}
&:hover {
opacity: 0.6;
}
}
2019-06-25 13:30:32 +08:00
}
> section.verification {
margin-top: 15px;
overflow: hidden;
> label {
display: block;
> input {
2019-06-25 16:08:42 +08:00
width: 40%;
2019-06-25 13:30:32 +08:00
padding: 5px 15px;
border-radius: $radius;
border: 1px solid #ddd;
2019-06-25 16:08:42 +08:00
font-size: 16px;
& + .btn-clear {
padding: 5px;
color: #000;
display: inline-block;
}
2019-06-25 13:30:32 +08:00
}
2019-06-25 16:08:42 +08:00
}
> .tip {
height: 24px;
padding: 5px;
> p {
font-size: 14px;
2019-06-25 13:30:32 +08:00
&.success {
color: #4caf50;
}
&.error {
color: #ff5722;
}
}
}
}
2019-06-25 16:08:42 +08:00
> section.trigger {
2019-06-25 13:30:32 +08:00
display: flex;
align-items: center;
align-content: center;
2019-06-25 16:08:42 +08:00
h3 {
font-size: 14px;
}
> label {
padding: 0 10px;
}
2019-06-25 13:30:32 +08:00
}
}
}
}
</style>