提交 5440a353 编写于 作者: R res

init

上级
> 1%
last 2 versions
not dead
NODE_ENV='development'
VUE_APP_MODEL_SERVER_URL='https://project-iprj6567f5516c04c6761f8e8e5e-5000.preview.node01.inscode.run/image/generations'
VUE_APP_MODEL_STEPS=25
VUE_APP_MODEL_SIZE='768x768'
VUE_APP_MODEL_N=1
\ No newline at end of file
module.exports = {
root: true,
env: {
node: true
},
'extends': [
'plugin:vue/essential',
'eslint:recommended'
],
parserOptions: {
parser: 'babel-eslint'
},
rules: {
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off'
}
}
.DS_Store
node_modules
/dist
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
run = "npm i && npm run serve"
language = "node"
[env]
PATH = "/root/${PROJECT_DIR}/.config/npm/node_global/bin:/root/${PROJECT_DIR}/node_modules/.bin:${PATH}"
XDG_CONFIG_HOME = "/root/.config"
npm_config_prefix = "/root/${PROJECT_DIR}/.config/npm/node_global"
[debugger]
program = "main.js"
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
]
}
此差异已折叠。
{
"name": "game",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
"dependencies": {
"core-js": "^3.6.5",
"vant": "^2.10.2",
"vue": "^2.6.11",
"vue-router": "^3.2.0",
"vuex": "^3.4.0"
},
"devDependencies": {
"@vue/cli-plugin-babel": "^4.5.0",
"@vue/cli-plugin-eslint": "^4.5.0",
"@vue/cli-service": "^4.5.0",
"babel-eslint": "^10.1.0",
"eslint": "^6.7.2",
"eslint-plugin-vue": "^6.2.2",
"node-sass": "^4.12.0",
"sass-loader": "^8.0.2",
"vue-template-compiler": "^2.6.11"
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title>看图猜成语</title>
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>
<template>
<div id="app">
<router-view/>
</div>
</template>
<style lang="scss">
</style>
[
{
"id": 1,
"word": "对牛弹琴",
"picture": "https://image.aoppp.com/loading.gif",
"prompt": "一个人在对着牛弹钢琴",
"mean": "形容对于没有共同语言或共同兴趣的人讲述某种知识或技能,而对方却无法理解或欣赏。",
"story": "它源于战国时期的故事,故事的主人公是一个名叫钟子期的人。钟子期非常喜欢音乐,但他的朋友都对音乐没有兴趣,所以他只好对着牛弹琴。这个故事告诉我们,如果我们不能找到合适的受众,我们的努力可能会被浪费。"
},
{
"id": 2,
"word": "虎头蛇尾",
"picture": "https://image.aoppp.com/loading.gif",
"prompt": "虎头蛇尾,有一个动物有老虎的脑袋和蛇的尾巴",
"mean": "形容开始时势头很猛,后来却变得懈怠或失去了动力。",
"story": "它源于古代传说,描述了一只追逐猎物的虎,一开始虎势头很猛,但追得久了,虎头疲惫,尾巴却还在摇摆。这个成语常用来批评那些开始时有很大热情,但后来缺乏坚持和毅力的人。"
},
{
"id": 3,
"word": "鹤立鸡群",
"picture": "https://image.aoppp.com/loading.gif",
"prompt": "鹤立鸡群,一群鸡中有一只鹤",
"mean": "形容某人在众人中显得与众不同,独立出众。",
"story": "鹤是高贵的象征,群中的鸡与之相比显得平凡。这个成语常用来赞美那些在才能、品德或地位上超越他人的人。"
},
{
"id": 4,
"word": "鸡同鸭讲",
"picture": "https://image.aoppp.com/loading.gif",
"prompt": "鸡,鸭,对话",
"mean": "形容彼此之间完全听不懂对方说的话,无法进行有效沟通。",
"story": "它源于唐代的一则寓言故事,讲述了一只鸡和一只鸭子争论谁的声音更好听的故事。由于鸡和鸭的声音不同,彼此无法理解对方的优点,最终无法达成共识。"
},
{
"id": 5,
"word": "鸡飞狗跳",
"picture": "https://image.aoppp.com/loading.gif",
"prompt": "鸡,狗,跳跃,Chaos",
"mean": "形容场面混乱、非常喧闹或混乱不堪的情景。",
"story": "它源于明代小说《西游记》,形容了孙悟空大闹天宫的场景。在故事中,孙悟空闹得天翻地覆,众神仙都被他惊慌失措地追逐。这个成语通常用来形容某种混乱或骚动的场面。"
},
{
"id": 6,
"word": "守株待兔",
"picture": "https://image.aoppp.com/loading.gif",
"prompt": "庭院,人坐在树边睡觉,疾速逃离的兔子",
"mean": "形容等待机会主动送上门来,而不主动去创造机会。",
"story": "它源于战国时期的故事,故事的主人公是一个农民,他在田地里砍倒了一棵树,正准备把树根挖掉时,一只兔子从旁边跑过,撞到了树根上摔死了。这个故事告诉我们,有时候机会会主动来到我们身边,但我们不能仅仅依赖运气,还需要主动去争取。"
},
{
"id": 7,
"word": "飞蛾扑火",
"picture": "https://image.aoppp.com/loading.gif",
"prompt": "飞蛾扑火 - 飞蛾,扑向火焰",
"mean": "形容自取灭亡或不自量力的行为。",
"story": "它源于古希腊神话中的故事,描述了飞蛾被火光吸引而不顾自身安危,最终被火烧死的情景。这个成语常用来警示人们不要盲目追求,以免自食恶果。"
},
{
"id": 8,
"word": "蜻蜓点水",
"picture": "https://image.aoppp.com/loading.gif",
"prompt": "蜻蜓点水:蜻蜓,水面",
"mean": "形容事物只是稍作触碰或涉及表面,而没有深入研究或投入太多精力。",
"story": "它源于蜻蜓在水面上轻轻触碰水花的形象。这个成语常用来形容对某个问题或领域的涉猎不深,只是浅尝辄止。"
},
{
"id": 9,
"word": "羊入虎口",
"picture": "https://image.aoppp.com/loading.gif",
"prompt": "一只羊、一群老虎",
"mean": "形容自愿或被迫陷入危险或困境中",
"story": "它源于一则古代寓言故事,讲述了一只羊被老虎追逐,并最终被老虎吃掉的情景。这个成语常用来形容自己陷入危险、无法摆脱的境地。"
},
{
"id": 10,
"word": "坐井观天",
"picture": "https://image.aoppp.com/loading.gif",
"prompt": "一只青蛙坐在深井里,仰望天空",
"mean": "形容见识狭窄、眼界短浅的人。",
"story": "它源于古代寓言故事,讲述了一只住在井里的青蛙,它只能看到井口的一片天空,以为那就是整个世界。这个成语常用来批评那些对外界知识、观念或事物缺乏了解,只局限于自己狭窄的经验和见识的人。"
}
]
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<p>
For a guide and recipes on how to configure / customize this project,<br>
check out the
<a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
</p>
<h3>Installed CLI Plugins</h3>
<ul>
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" target="_blank" rel="noopener">babel</a></li>
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint" target="_blank" rel="noopener">eslint</a></li>
</ul>
<h3>Essential Links</h3>
<ul>
<li><a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a></li>
<li><a href="https://forum.vuejs.org" target="_blank" rel="noopener">Forum</a></li>
<li><a href="https://chat.vuejs.org" target="_blank" rel="noopener">Community Chat</a></li>
<li><a href="https://twitter.com/vuejs" target="_blank" rel="noopener">Twitter</a></li>
<li><a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a></li>
</ul>
<h3>Ecosystem</h3>
<ul>
<li><a href="https://router.vuejs.org" target="_blank" rel="noopener">vue-router</a></li>
<li><a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a></li>
<li><a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" rel="noopener">vue-devtools</a></li>
<li><a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a></li>
<li><a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a></li>
</ul>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
props: {
msg: String
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="scss">
h3 {
margin: 40px 0 0;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import Vant from 'vant';
import 'vant/lib/index.css';
Vue.config.productionTip = false
Vue.use(Vant)
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'
Vue.use(VueRouter)
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
]
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
})
export default router
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
},
mutations: {
},
actions: {
},
modules: {
}
})
<template>
<div class="container">
<van-nav-bar
style="background-color:#ffffff"
>
<span slot="title" style="color:black">{{ id }} / {{ array.length }}</span>
<span slot="right" style="color:black">{{ score }}</span>
</van-nav-bar>
<div class="picture">
<van-image :src="obj.picture" class="img"/>
</div>
<div class="tips">
<van-button type="info" size="small" @click="jumpLevel(id-1)" :disabled="!showPrev">上一关</van-button>
<van-button type="info" size="small" @click="checkLevel" style="margin: 0 10px 0 20px">选 关</van-button>
<span style="color:#fff">{{ time + 1 }}</span>
<van-button type="primary" size="small" @click="handlePrompt" style="margin: 0 20px 0 10px">提 示</van-button>
<van-button type="info" size="small" @click="jumpLevel(id+1)" :disabled="!showNext">下一关</van-button>
</div>
<div class="result">
<div v-for="(item,i) in choiced" :key="i">
<span @click="handleCancel(i)" class="choiced-text">{{ item }}</span>
</div>
</div>
<div class="choice">
<div v-for="(item,i) in choices.slice(0,8)" :key="i">
<span @click="handleChoice(item,i)" class="choice-text">{{ item }}</span>
</div>
</div>
<div class="choice">
<div v-for="(item,i) in choices.slice(8,16)" :key="i">
<span @click="handleChoice(item,i+8)" class="choice-text">{{ item }}</span>
</div>
</div>
<div class="choice">
<div v-for="(item,i) in choices.slice(16,24)" :key="i">
<span @click="handleChoice(item,i+16)" class="choice-text">{{ item }}</span>
</div>
</div>
<div style="width:100%;text-align:center;display:flex;">
<van-button type="info" size="small" style="margin: 20px auto" @click="clearGame">重置记录</van-button>
<van-button type="info" size="small" style="margin: 20px auto" @click="reGenImage">重新生成图片</van-button>
</div>
<van-popup v-model="showLevel" position="bottom" style="height:40%">
<div class="levels">
<div v-for="(item,i) in array" :key="i"
:class="['level-item',id==item.id ? 'active':'',item.played?'played':'']" @click="handleClickLevel(item)">
<p>{{ i + 1 }}</p>
<p>
<van-rate :value="item.star" count="3" size="16px" color="#FFD21E" readonly/>
</p>
</div>
</div>
</van-popup>
<div :class="['music-btn',isPlay == '0'? 'bgm':'']" @click="handleClickBgm()" ref="playbtn">
<van-icon name="music-o" size="36px"/>
<div v-if="isPlay=='1'" class="stop-play"></div>
</div>
<audio src="../assets/music/bgm.mp3" controls="true" ref="bgm" style="display:none" loop="loop"></audio>
<audio src="../assets/music/error.wav" controls="true" ref="error" style="display:none"></audio>
</div>
</template>
<script>
import {Dialog, Toast} from 'vant';
export default {
components: {
[Dialog.Component.name]: Dialog.Component,
[Toast.Component]: Toast.Component
},
data() {
return {
id: null,
score: 100,
data: require('../assets/word'),
array: [],
obj: {},
choices: [],
choiced: [],
showPrev: false,
showNext: false,
showLevel: false,
star: 0,
time: 1,
timer: null,
prompt: 0,
isPlay: "0",
}
},
watch: {
id(val) {
this.updateStep(val);
this.updateLocalStorage('level', val);
this.updatePrevButton(val);
this.updateNextButton();
},
score(val) {
this.updateLocalStorage('score', val);
},
choiced(val) {
if (val.join('').length == 4) {
this.checkWordMatch(val);
}
}
},
mounted() {
this.loadLocalStorage();
this.jumpLevel(this.id);
this.$refs.bgm.play();
},
methods: {
updateStep(val) {
if (val <= 10) {
this.step = 2;
} else if (val > 10 && val < 20) {
this.step = 5;
}
},
updateLocalStorage(key, value) {
localStorage.setItem(key, value);
},
updatePrevButton(val) {
this.showPrev = val >= 2;
},
updateNextButton() {
const playedArr = this.array.filter(it => it.id > this.id && it.played);
this.showNext = playedArr.length > 0 || this.obj.played;
},
loadLocalStorage() {
if (localStorage.getItem('level')) {
this.id = parseInt(localStorage.getItem('level'));
}
if (localStorage.getItem('score')) {
this.score = parseInt(localStorage.getItem('score'));
}
if (localStorage.getItem('array')) {
this.array = JSON.parse(localStorage.getItem('array'));
} else {
this.array = this.data;
}
if (localStorage.getItem('bgm')) {
this.isPlay = localStorage.getItem('bgm');
}
},
checkWordMatch(val) {
const wordArr = this.obj.word.split('');
const doms = document.getElementsByClassName('choiced-text');
let count = 0;
wordArr.forEach((a, i) => {
if (a != val[i]) {
doms[i].style.color = 'red';
count++;
} else {
doms[i].style.color = '#E3D479';
}
});
if (count > 0) {
this.handleGameError();
}
},
handleGameError() {
this.$refs.error.play();
if (this.isPlay == '0') {
this.$refs.bgm.pause();
this.$refs.error.addEventListener('ended', () => {
this.$refs.bgm.play();
});
}
},
jumpLevel(id) {
if (id != null) {
this.id = id;
} else {
if (this.id) {
this.id = this.id + 1;
} else {
this.id = 1;
}
}
this.time = 0;
this.prompt = 0;
let d = this.array[this.id - 1];
let model_prompt = d.prompt
this.obj = this.array[this.id - 1];
this.fetchData(model_prompt).then(res => res.json() ).then(data => {
if (data && data.data && data.data.length > 0) {
this.obj.picture = 'data:image/png;base64,' + data.data[0].b64_image;
} else {
// 处理数据不存在的情况
}
})
this.choiced = ['', '', '', ''];
this.getChoice();
if (this.timer) {
window.clearInterval(this.timer);
}
this.timer = window.setInterval(() => {
let time = this.time + 1;
this.time = time;
}, 1000)
},
getChoice() {
let arr = this.obj.word.split('');
while (arr.length < 24) {
let index = Math.floor(Math.random() * (this.array.length));
let wordArr = this.array[index].word.split('');
let w = wordArr[Math.floor(Math.random() * 4)];
if (arr.indexOf(w) < 0) {
arr.push(w)
}
}
this.choices = this.shuffle(arr);
},
shuffle(a) {
a.sort(function () {
return Math.random() - 0.5 // 随机返回正或负值 达到排序的目的
})
return a;
},
//点击下面选项
handleChoice(item, index) {
if (!item) {
return;
}
let result = this.choiced.join('');
if (result.length == 4) {
return;
} else {
for (let i = 0; i < this.choiced.length; i++) {
if (this.choiced[i] == '') {
this.$set(this.choiced, i, item)
this.$set(this.choices, index, '')
event.target.setAttribute('text', item)
break;
}
}
result = this.choiced.join('');
if (result == this.obj.word) {
Dialog.alert({
title: this.id == this.array.length ? '恭喜您已通关' : '恭喜您已过关',
message: '[词义]:' + this.obj.mean + (this.obj.story ? ('\n\n[故事]:' + this.obj.story) : ''),
confirmButtonText: this.id == this.array.length ? "通关" : "下一关"
}).then(() => {
window.clearInterval(this.timer);
this.timer = null;
if (this.time <= 10) {
this.star = 3;
} else if (this.time <= 20) {
this.star = 2
} else if (this.time <= 30) {
this.star = 1;
} else {
this.star = 0;
}
let s = this.star - this.prompt < 0 ? 0 : this.star - this.prompt
this.array.map(a => {
a.picture = 'https://image.aoppp.com/loading.gif'
if (a.id == this.id) {
a.played = true;
a.star = (a.star && s <= a.star) ? a.star : s;
}
})
console.log(this.array);
localStorage.setItem('array', JSON.stringify(this.array));
this.jumpLevel(this.id == this.array.length ? 1 : null);
this.score = this.score + this.step * (this.star == 0 ? 1 : this.star);
});
}
}
},
//点击上面系选择的
handleCancel(index) {
if (this.choiced[index]) {
let text = this.choiced[index];
this.$set(this.choiced, index, '')
let doms = document.getElementsByClassName('choice-text');
for (let i = 0; i < doms.length; i++) {
let dom = doms[i];
if (dom.getAttribute('text') && dom.getAttribute('text') == text) {
dom.removeAttribute('text')
this.$set(this.choices, i, text);
}
}
}
},
//选关
checkLevel() {
this.showLevel = true;
},
//bgm
handleClickBgm() {
if (this.isPlay == '0') {
this.$refs.bgm.pause();
this.$refs.playbtn.classList.remove('bgm')
this.isPlay = '1';
} else {
this.$refs.bgm.play();
this.$refs.playbtn.classList.add('bgm');
this.isPlay = '0';
}
localStorage.setItem('bgm', this.isPlay);
},
clearGame() {
Dialog.confirm({
title: '提示',
message: '确认清空游戏记录?\n清空后从第一关开始哟~',
})
.then(() => {
this.array = this.data;
this.score = 100;
this.id = 1;
localStorage.clear();
this.jumpLevel(1);
this.isPlay = '0';
this.$refs.bgm.play();
})
.catch(() => {
// on cancel
});
},
reGenImage(){
console.log(111)
let model_prompt = this.obj.prompt
this.obj.picture = 'https://image.aoppp.com/loading.gif'
this.fetchData(model_prompt).then(res => res.json() ).then(data => {
if (data && data.data && data.data.length > 0) {
this.obj.picture = 'data:image/png;base64,' + data.data[0].b64_image;
} else {
// 处理数据不存在的情况
}
})
},
//提示
handlePrompt() {
let score = this.score;
if (score < 10) {
Toast('分数不够,继续闯关吧~');
} else if (this.prompt >= 3) {
Toast('已经提示了三次了哟,还不会吗~');
} else {
let doms = document.getElementsByClassName('choice-text');
for (let i = 0; i < doms.length; i++) {
let dom = doms[i];
let arr = this.obj.word.split('');
this.score = score - 10;
this.prompt = this.prompt + 1;
arr.map(a => {
if (dom.innerHTML && dom.innerHTML == a) {
dom.style.color = 'red'
window.setTimeout(function () {
dom.style.color = '#E3D479'
}, 10000)
}
})
}
}
},
handleClickLevel(item) {
this.showLevel = false;
console.log(this.id);
console.log(item);
if (item.id == this.id || !item.played) {
if (!item.played && item.id != this.id) {
Toast('通关后才可以挑战此关哟~');
}
return;
}
this.jumpLevel(item.id)
},
fetchData(prompt) {
console.log(prompt)
const url = process.env.VUE_APP_MODEL_SERVER_URL;
console.log(process.env)
const data = {
'n': process.env.VUE_APP_MODEL_N,
'prompt': prompt,
'size': process.env.VUE_APP_MODEL_SIZE,
'steps': process.env.VUE_APP_MODEL_STEPS
};
var cookie = document.cookie;
const headers = new Headers({
'Content-Type': 'application/json',
'Cookie': cookie
});
return fetch(url, {
method: 'POST',
headers: headers,
body: JSON.stringify(data)
})
},
}
}
</script>
<style lang="scss" scoped>
.container {
background-color: #44b4ae;
height: 100vh;
}
.picture {
margin: 20px auto;
width: calc(100% - 100px);
border-radius: 8px;
overflow: hidden;
border: 0px solid #ffffff;
.img {
width: 100%;
height: 160px;
}
}
.tips {
text-align: center;
display: flex;
align-items:center;
justify-content:center;
}
.result {
margin-top: 10px;
padding: 10px 80px;
display: flex;
flex-flow: row;
justify-content: space-between;
div {
width: 30px;
height: 30px;
border-radius: 4px;
text-align: center;
line-height: 30px;
cursor: pointer;
background-color: #643D12;
color: #FFFFFF;
}
}
.choice {
display: flex;
margin-top: 10px;
justify-content: space-between;
padding: 0 20px;
div {
width: 30px;
height: 30px;
border-radius: 5px;
margin: 2px;
text-align: center;
line-height: 30px;
cursor: pointer;
background-color: #FFFFFF;
color: black;
}
}
.music-btn {
position: fixed;
width: 36px;
height: 36px;
top: 50px;
right: 5px;
text-align: center;
line-height: 34px;
overflow: hidden;
.stop-play {
width: 28px;
height: 0;
border: 1px solid red;
position: absolute;
top: 50%;
left: calc(50% - 14px);
transform: rotate(-45deg);
}
}
.bgm {
animation: bgm 5s infinite linear;
}
@keyframes bgm {
to {
transform: rotate(0);
}
from {
transform: rotate(360deg);
}
}
.levels {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
grid-gap: 10px;
padding: 10px;
.level-item {
height: 80px;
border: 1px solid #e0e0e0;
text-align: center;
border-radius: 5px;
&.active {
background-color: rgba(153, 153, 153, .3);
}
&.played {
background-color: rgba(158, 234, 106, .3);
}
}
}
</style>
module.exports = {
devServer: {
disableHostCheck: true
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册