No puede seleccionar más de 25 temas
Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.
287 líneas
11 KiB
287 líneas
11 KiB
{{template "header" .}}
|
|
<meta name="keywords" content="码农随笔,个人随笔,博客,个人博客,个人笔记,技术博客,免费云笔记,云笔记,随笔,IT博客,谷歌地图,码农笔录,aiprose">
|
|
<script src="https://cdn.bootcdn.net/ajax/libs/three.js/r128/three.min.js"></script>
|
|
|
|
<title>登录 - 码农随笔</title>
|
|
<style>
|
|
.login-form {
|
|
background: #55555555;
|
|
padding: 18px;
|
|
border-radius: 8px;
|
|
position: fixed;
|
|
left: 25%;
|
|
top: 20%;
|
|
width: 350px;
|
|
margin: auto;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="root-container">
|
|
{{template "nav" .}}
|
|
<div class="login-root">
|
|
<script type="x-shader/x-vertex" id="vertexshader">
|
|
attribute float scale;
|
|
void main() {
|
|
vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
|
|
gl_PointSize = scale * ( 300.0 / - mvPosition.z );
|
|
gl_Position = projectionMatrix * mvPosition;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
</script>
|
|
<script type="x-shader/x-fragment" id="fragmentshader">
|
|
uniform vec3 color;
|
|
void main() {
|
|
if ( length( gl_PointCoord - vec2( 0.5, 0.5 ) ) > 0.475 ) discard;
|
|
gl_FragColor = vec4( color, 1.0 );
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
</script>
|
|
<div id="threeContainer" class="threeContainer" ref="threeContainer"></div>
|
|
<div class="login-form" :style="mstyle">
|
|
<el-form :model="loginForm" :rules="rules" ref="loginForm" label-width="0px" class="loginForm">
|
|
<el-form-item prop="username">
|
|
<el-input v-model="loginForm.username" placeholder="请输入用户名">
|
|
<i slot="prefix" class="el-input__icon el-icon-user-solid"></i>
|
|
</el-input>
|
|
</el-form-item>
|
|
<el-form-item prop="userpwd">
|
|
<el-input type="password" v-model="loginForm.userpwd" placeholder="请输入密码" show-password>
|
|
<i slot="prefix" class="el-input__icon el-icon-user-solid"></i>
|
|
</el-input>
|
|
</el-form-item>
|
|
<el-form-item prop="captcha">
|
|
<div style="display: flex">
|
|
<el-input v-model="loginForm.captcha" placeholder="请输入验证码">
|
|
<i slot="prefix" class="el-input__icon el-icon-user-solid"></i>
|
|
</el-input>
|
|
<img :src="captcha" width="150px" @click="getCaptcha"/>
|
|
</div>
|
|
</el-form-item>
|
|
<div>
|
|
<el-button type="primary" @click="loginHandler" :loading="loading" style="width: 48%">登陆</el-button>
|
|
<el-button type="primary" @click="registHandler" :loading="loading" style="width: 48%">注册
|
|
</el-button>
|
|
</div>
|
|
</el-form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</body>
|
|
<script>
|
|
var windowHalfX = 0
|
|
var windowHalfY = 0
|
|
var camera = null
|
|
var renderer = null
|
|
var scene = null
|
|
var count = 0
|
|
var mouseX = 145
|
|
var mouseY = -322
|
|
var particles = null
|
|
var AMOUNTX = 50
|
|
var AMOUNTY = 50
|
|
var app = new Vue({
|
|
el: ".root-container",
|
|
delimiters: ['${', '}'],
|
|
data: {
|
|
captcha: '',
|
|
loading: false,
|
|
loginForm: {
|
|
username: '',
|
|
userpwd: '',
|
|
captchaId: ''
|
|
},
|
|
rules: {
|
|
username: [
|
|
{
|
|
required: true,
|
|
message: '请输入用户名',
|
|
trigger: 'blur'
|
|
},
|
|
{
|
|
min: 5,
|
|
message: '长度最少5个字符',
|
|
trigger: 'blur'
|
|
}
|
|
],
|
|
userpwd: [
|
|
{
|
|
required: true,
|
|
message: '请输入密码',
|
|
trigger: 'blur'
|
|
},
|
|
{
|
|
min: 6,
|
|
message: '长度最少6个字符',
|
|
trigger: 'blur'
|
|
}
|
|
],
|
|
captcha: [
|
|
{
|
|
required: true,
|
|
message: '请输入验证码',
|
|
trigger: 'blur'
|
|
}
|
|
]
|
|
},
|
|
mstyle: {
|
|
left: window.innerWidth / 2 - 175 + 'px'
|
|
}
|
|
},
|
|
created() {
|
|
this.getCaptcha()
|
|
},
|
|
mounted() {
|
|
const SEPARATION = 100
|
|
windowHalfX = window.innerWidth / 2
|
|
windowHalfY = window.innerHeight / 2
|
|
const container = this.$refs.threeContainer
|
|
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 10000)
|
|
camera.position.z = 1000
|
|
scene = new THREE.Scene()
|
|
const numParticles = AMOUNTX * AMOUNTY
|
|
const positions = new Float32Array(numParticles * 3)
|
|
const scales = new Float32Array(numParticles)
|
|
let i = 0;
|
|
let j = 0
|
|
for (let ix = 0; ix < AMOUNTX; ix++) {
|
|
for (let iy = 0; iy < AMOUNTY; iy++) {
|
|
positions[i] = ix * SEPARATION - ((AMOUNTX * SEPARATION) / 2) // x
|
|
positions[i + 1] = 0 // y
|
|
positions[i + 2] = iy * SEPARATION - ((AMOUNTY * SEPARATION) / 2) // z
|
|
|
|
scales[j] = 1
|
|
|
|
i += 3
|
|
j++
|
|
}
|
|
}
|
|
const geometry = new THREE.BufferGeometry()
|
|
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3))
|
|
geometry.setAttribute('scale', new THREE.BufferAttribute(scales, 1))
|
|
const material = new THREE.ShaderMaterial({
|
|
uniforms: {
|
|
color: {value: new THREE.Color(0.0, 1.0, 1.0, 1.0)}
|
|
},
|
|
vertexShader: document.getElementById('vertexshader').textContent,
|
|
fragmentShader: document.getElementById('fragmentshader').textContent
|
|
})
|
|
particles = new THREE.Points(geometry, material)
|
|
scene.add(particles)
|
|
renderer = new THREE.WebGLRenderer({antialias: true})
|
|
|
|
renderer.setPixelRatio(window.devicePixelRatio)
|
|
renderer.setSize(window.innerWidth, window.innerHeight)
|
|
container.appendChild(renderer.domElement)
|
|
// containerParent.append(container)
|
|
container.style.touchAction = 'none'
|
|
container.addEventListener('pointermove', this.onPointerMove)
|
|
window.addEventListener('resize', this.onWindowResize)
|
|
this.animate()
|
|
},
|
|
methods: {
|
|
animate() {
|
|
requestAnimationFrame(this.animate)
|
|
this.render()
|
|
},
|
|
getCaptcha() {
|
|
const _this = this
|
|
$.get('/api/authc/captcha',
|
|
function (resp) {
|
|
if (resp.Status === 0) {
|
|
_this.loginForm.captchaId = resp.Data.captchaId
|
|
_this.captcha = resp.Data.img
|
|
}
|
|
}, 'json')
|
|
},
|
|
render() {
|
|
camera.position.x += (mouseX - camera.position.x) * 0.05
|
|
camera.position.y += (-mouseY - camera.position.y) * 0.05
|
|
camera.lookAt(scene.position)
|
|
const positions = particles.geometry.attributes.position.array
|
|
const scales = particles.geometry.attributes.scale.array
|
|
let i = 0;
|
|
let j = 0
|
|
for (let ix = 0; ix < AMOUNTX; ix++) {
|
|
for (let iy = 0; iy < AMOUNTY; iy++) {
|
|
positions[i + 1] = (Math.sin((ix + count) * 0.3) * 50) +
|
|
(Math.sin((iy + count) * 0.5) * 50)
|
|
|
|
scales[j] = (Math.sin((ix + count) * 0.3) + 1) * 5 +
|
|
(Math.sin((iy + count) * 0.5) + 1) * 5
|
|
i += 3
|
|
j++
|
|
}
|
|
}
|
|
particles.geometry.attributes.position.needsUpdate = true
|
|
particles.geometry.attributes.scale.needsUpdate = true
|
|
renderer.render(scene, camera)
|
|
count += 0.08
|
|
},
|
|
onWindowResize() {
|
|
this.mstyle.left = window.innerWidth / 2 - 175 + 'px'
|
|
windowHalfX = window.innerWidth / 2
|
|
windowHalfY = window.innerHeight / 2
|
|
camera.aspect = window.innerWidth / window.innerHeight
|
|
camera.updateProjectionMatrix()
|
|
renderer.setSize(window.innerWidth, window.innerHeight)
|
|
},
|
|
onPointerMove(event) {
|
|
if (event.isPrimary === false) return
|
|
mouseX = event.clientX - windowHalfX
|
|
// mouseY = event.clientY - windowHalfY
|
|
},
|
|
loginHandler() {
|
|
const _this = this
|
|
this.loading = true
|
|
this.$refs.loginForm.validate(valid => {
|
|
if (valid) {
|
|
$.post('/api/login', this.loginForm,
|
|
function (data) {
|
|
_this.loading = false
|
|
if (data.Status == 1) {
|
|
_this.getCaptcha()
|
|
_this.$message.warning(data.Msg);
|
|
} else {
|
|
_this.$message.success("登录成功");
|
|
window.location.href = "/"
|
|
}
|
|
}, 'json')
|
|
} else {
|
|
this.loading = false
|
|
}
|
|
})
|
|
},
|
|
registHandler() {
|
|
const _this = this
|
|
this.loading = true
|
|
this.$refs.loginForm.validate(valid => {
|
|
if (valid) {
|
|
$.post('/api/regist', this.loginForm,
|
|
function (data) {
|
|
_this.loading = false
|
|
_this.getCaptcha()
|
|
if (data.Status == 1) {
|
|
_this.$message.warning(data.Msg);
|
|
} else {
|
|
_this.$message.success("注册成功,请登陆");
|
|
}
|
|
}, 'json')
|
|
} else {
|
|
this.loading = false
|
|
}
|
|
})
|
|
}
|
|
}
|
|
})
|
|
</script>
|
|
<script type="text/javascript" src="/static/js/seo.js"></script>
|
|
</html>
|