Browse Source

增加页面路由,增加加词功能

zhusiqing 5 years ago
parent
commit
4d28f12901
12 changed files with 340 additions and 697 deletions
  1. 0 674
      data/data.json
  2. 0 0
      data/data.txt
  3. 0 3
      data/reviewData.json
  4. 0 0
      data/reviewData.txt
  5. 82 3
      server.js
  6. 1 16
      src/App.vue
  7. 8 1
      src/components/Start.vue
  8. 2 0
      src/main.js
  9. 32 0
      src/router.js
  10. 34 0
      src/views/Main.vue
  11. 100 0
      src/views/Review.vue
  12. 81 0
      src/views/Words.vue

+ 0 - 674
data/data.json

@@ -1,674 +0,0 @@
-{
-  "data": [
-    "痤疮",
-    "英亩",
-    "附录",
-    "广告",
-    "飞机",
-    "升",
-    "鳄鱼",
-    "按字母顺序排列",
-    "美国",
-    "踝关节",
-    "冷漠",
-    "鼓掌",
-    "苹果酱",
-    "应用",
-    "考古学家",
-    "贵族",
-    "手臂",
-    "无敌舰队",
-    "睡着",
-    "宇航员",
-    "运动员",
-    "亚特兰蒂斯",
-    "阿姨",
-    "鳄梨",
-    "保姆",
-    "骨干",
-    "袋子",
-    "面包",
-    "秃头",
-    "气球",
-    "香蕉",
-    "栏杆",
-    "棒球",
-    "踢脚板",
-    "篮球",
-    "蝙蝠",
-    "电池",
-    "沙滩",
-    "豆茎",
-    "臭虫",
-    "啤酒",
-    "贝多芬",
-    "带子",
-    "围兜",
-    "单车",
-    "大",
-    "自行车",
-    "广告牌",
-    "鸟",
-    "生日",
-    "咬",
-    "铁匠",
-    "毯子",
-    "漂白剂",
-    "飞艇",
-    "开花",
-    "蓝图",
-    "钝",
-    "模糊",
-    "宝儿",
-    "舟",
-    "鲍勃",
-    "雪橇",
-    "身体",
-    "炸弹",
-    "阀盖",
-    "书",
-    "展位",
-    "领结",
-    "盒子",
-    "男孩",
-    "头脑风暴",
-    "牌子",
-    "勇敢",
-    "新娘",
-    "桥",
-    "西兰花",
-    "破坏",
-    "扫帚",
-    "挫伤",
-    "黑发",
-    "泡沫",
-    "巴迪",
-    "水牛",
-    "灯泡",
-    "兔子",
-    "巴士",
-    "买",
-    "小屋",
-    "餐厅",
-    "蛋糕",
-    "计算器",
-    "营地",
-    "可以 ",
-    "蜡烛",
-    "糖",
-    "海角",
-    "资本主义",
-    "车",
-    "纸板",
-    "制图",
-    "猫",
-    "唱片",
-    "天花板",
-    "细胞",
-    "世纪",
-    "椅子",
-    "记录",
-    "冠军",
-    "充电器",
-    "啦啦队长",
-    "厨师",
-    "象棋",
-    "咀嚼",
-    "鸡",
-    "鸣响",
-    "巧克力",
-    "教堂",
-    "圆",
-    "粘土",
-    "悬崖",
-    "斗篷",
-    "顺时针",
-    "小丑",
-    "线索",
-    "教练",
-    "煤",
-    "过山车",
-    "装配",
-    "冷",
-    "学院",
-    "舒适",
-    "计算机",
-    "圆锥",
-    "括约肌",
-    "闭联",
-    "回话",
-    "烹饪",
-    "公司",
-    "绳索",
-    "灯芯绒",
-    "简易床",
-    "咳嗽",
-    "奶牛",
-    "牛仔",
-    "蜡笔",
-    "奶油",
-    "脆",
-    "批评",
-    "乌鸦",
-    "巡航",
-    "面包屑",
-    "外壳",
-    "袖口",
-    "窗帘",
-    "角质层",
-    "沙皇",
-    "爸爸",
-    "投掷",
-    "黎明",
-    "白天",
-    "深",
-    "缺点",
-    "齿",
-    "牙医",
-    "书桌",
-    "字典",
-    "酒窝",
-    "脏",
-    "拆除",
-    "挖沟",
-    "潜水者",
-    "医生",
-    "狗",
-    "狗窝",
-    "洋娃娃",
-    "多米诺骨",
-    "门",
-    "圆点",
-    "排水",
-    "抓",
-    "梦",
-    "裙子",
-    "喝",
-    "滴",
-    "鼓",
-    "烘干机",
-    "鸭子",
-    "倾倒",
-    "灌篮",
-    "垃圾",
-    "耳",
-    "吃",
-    "木制",
-    "肘部",
-    "电气",
-    "大象",
-    "电梯",
-    "精灵",
-    "榆木",
-    "引擎",
-    "人类工程学",
-    "扶梯",
-    "有了",
-    "进化",
-    "延长",
-    "眉毛",
-    "粉丝",
-    "幻想",
-    "快",
-    "宴请",
-    "栅栏",
-    "封建",
-    "小提琴",
-    "虚构",
-    "手指",
-    "火",
-    "第一",
-    "钓鱼",
-    "修",
-    "兴奋",
-    "旗杆",
-    "法兰绒",
-    "火光",
-    "聚集",
-    "废料",
-    "花",
-    "流感",
-    "激动",
-    "飘动",
-    "雾",
-    "衬托",
-    "足球",
-    "前额",
-    "永远",
-    "两周",
-    "雀斑",
-    "运送",
-    "边缘",
-    "蛙",
-    "蛙",
-    "皱眉",
-    "疾驰",
-    "游戏",
-    "垃圾袋",
-    "花园",
-    "汽油",
-    "宝石",
-    "姜",
-    "姜饼",
-    "女孩",
-    "眼镜",
-    "地精",
-    "金",
-    "再见",
-    "奶奶",
-    "葡萄",
-    "草",
-    "感激",
-    "灰",
-    "绿",
-    "吉他",
-    "口香糖",
-    "橡皮",
-    "头发",
-    "半",
-    "掌控",
-    "手写",
-    "挂",
-    "高兴",
-    "帽子",
-    "孵化",
-    "头痛",
-    "心",
-    "基金",
-    "直升机",
-    "边",
-    "藏",
-    "山",
-    "冰球",
-    "作业",
-    "喇叭声",
-    "跳房子",
-    "马",
-    "软管",
-    "热",
-    "房",
-    "游艇",
-    "拥抱",
-    "加湿器",
-    "饿",
-    "障碍",
-    "伤害",
-    "笼子",
-    "冰",
-    "内爆",
-    "墨水",
-    "调查",
-    "内部",
-    "网络",
-    "引诱",
-    "讽刺",
-    "象牙",
-    "常青藤",
-    "翡翠",
-    "牛仔裤",
-    "果冻",
-    "喷气",
-    "抖动",
-    "慢跑",
-    "杂志",
-    "跳",
-    "钥匙",
-    "杀手",
-    "公斤",
-    "国王",
-    "厨房",
-    "风筝",
-    "膝盖",
-    "下跪",
-    "刀",
-    "骑士",
-    "考拉",
-    "花边",
-    "梯子",
-    "瓢虫",
-    "拖延",
-    "垃圾堆",
-    "一圈",
-    "笑",
-    "洗衣店",
-    "法",
-    "草地",
-    "剪草机",
-    "泄露",
-    "腿",
-    "字母",
-    "等级",
-    "生活方式",
-    "韧带",
-    "光",
-    "光剑",
-    "石灰",
-    "狮子",
-    "蜥蜴",
-    "伐木",
-    "虚度",
-    "棒棒糖",
-    "双人沙发",
-    "忠诚",
-    "午餐",
-    "午餐盒",
-    "歌词",
-    "机器",
-    "男子气概",
-    "信箱",
-    "长毛象",
-    "记号",
-    "吉祥物",
-    "桅杆",
-    "火柴棍",
-    "大副",
-    "床垫",
-    "混乱",
-    "仲夏",
-    "矿",
-    "错误",
-    "现代",
-    "塑造",
-    "妈",
-    "周一",
-    "猴子",
-    "监视器",
-    "怪物",
-    "偷",
-    "月",
-    "擦",
-    "蛾",
-    "摩托车",
-    "山脉",
-    "鼠",
-    "割草机",
-    "泥巴",
-    "音乐",
-    "静音",
-    "自然",
-    "协商",
-    "邻居",
-    "鸟巢",
-    "中子",
-    "侄女",
-    "夜",
-    "噩梦",
-    "鼻",
-    "桨",
-    "天文台",
-    "办公室",
-    "油",
-    "老",
-    "威严",
-    "不透明",
-    "瓶撬",
-    "轨道",
-    "器官",
-    "组织",
-    "外面",
-    "外部",
-    "欢迎",
-    "序幕",
-    "桶",
-    "画",
-    "睡衣",
-    "宫殿",
-    "裤子",
-    "纸",
-    "纸",
-    "公园",
-    "山寨",
-    "聚会",
-    "密码",
-    "糕饼",
-    "卒",
-    "梨子",
-    "笔",
-    "铅笔",
-    "钟摆",
-    "阳物",
-    "便士",
-    "辣椒",
-    "个人",
-    "哲人",
-    "手机",
-    "照片",
-    "钢琴",
-    "野餐",
-    "猪舍",
-    "枕头",
-    "飞行员",
-    "勒索",
-    "乒",
-    "纸风车",
-    "海盗",
-    "格子",
-    "计划",
-    "厚木板",
-    "平",
-    "鸭嘴兽",
-    "操场",
-    "犁田",
-    "水管工",
-    "口袋",
-    "诗",
-    "点",
-    "极点",
-    "浮华",
-    "乓",
-    "水池",
-    "冰棒",
-    "人口",
-    "公文包",
-    "积极",
-    "寄",
-    "公主",
-    "耽搁",
-    "抗议",
-    "心理学家",
-    "出版商",
-    "废物",
-    "木偶",
-    "小狗",
-    "推",
-    "谜题",
-    "检疫",
-    "皇后",
-    "流沙",
-    "安静",
-    "赛",
-    "收音机",
-    "筏",
-    "破布",
-    "彩虹",
-    "雨水",
-    "区域",
-    "射线",
-    "回收",
-    "红",
-    "遗憾",
-    "退还",
-    "报复",
-    "肋骨",
-    "谜语",
-    "边缘",
-    "溜冰场",
-    "滚筒",
-    "房间",
-    "玫瑰",
-    "轮",
-    "迂回",
-    "横木",
-    "小牛",
-    "发情期",
-    "忧伤",
-    "安全",
-    "鲑鱼",
-    "盐",
-    "沙盒",
-    "沙堡",
-    "三明治",
-    "腰带",
-    "卫星",
-    "恐惧",
-    "刀疤",
-    "学校",
-    "卑鄙",
-    "攀登",
-    "磨损",
-    "海贝",
-    "季节",
-    "句子",
-    "亮片",
-    "设置",
-    "轴",
-    "影子 ",
-    "香波",
-    "鲨鱼",
-    "绵羊",
-    "被单",
-    "警官",
-    "海难",
-    "衬衫",
-    "鞋带",
-    "短",
-    "喷头",
-    "收缩",
-    "病",
-    "午睡",
-    "侧影",
-    "歌手",
-    "抿",
-    "滑冰",
-    "溜冰",
-    "划水",
-    "扣篮",
-    "睡",
-    "吊索",
-    "慢",
-    "下降",
-    "史密斯",
-    "打喷嚏",
-    "雪",
-    "紧抱",
-    "歌",
-    "太空",
-    "节约",
-    "演讲者",
-    "蜘蛛",
-    "吐痰",
-    "抹掉",
-    "缠绕",
-    "勺子",
-    "春",
-    "洒水车",
-    "间谍",
-    "广场",
-    "斜视",
-    "楼梯",
-    "长期",
-    "星",
-    "州",
-    "棍子",
-    "隔板",
-    "红灯",
-    "结实",
-    "火炉",
-    "匿身处",
-    "稻草",
-    "蒸汽",
-    "流线型",
-    "条纹",
-    "学生",
-    "日",
-    "日出",
-    "寿司",
-    "沼泽",
-    "群集",
-    "毛衣",
-    "游泳",
-    "摇摆",
-    "转速",
-    "说",
-    "出租车",
-    "老师",
-    "茶壶",
-    "青少年",
-    "电话",
-    "十",
-    "网球",
-    "贼",
-    "思考",
-    "王座",
-    "穿越",
-    "雷",
-    "潮水",
-    "虎",
-    "时间",
-    "着色",
-    "脚尖",
-    "绝顶",
-    "疲倦",
-    "纸巾",
-    "面包",
-    "厕所",
-    "工具",
-    "牙刷",
-    "龙卷风",
-    "锦标赛",
-    "拖拉机",
-    "火车",
-    "销毁",
-    "财宝",
-    "树",
-    "三角",
-    "旅程",
-    "卡车",
-    "浴盆",
-    "大号",
-    "辅导",
-    "电视",
-    "鼻音",
-    "理解",
-    "推特",
-    "类型",
-    "失业",
-    "升级",
-    "背心",
-    "视野",
-    "饶舌",
-    "水",
-    "西瓜",
-    "蜡",
-    "婚礼",
-    "除草",
-    "焊接工",
-    "无论如何",
-    "轮椅",
-    "鞭打",
-    "搅拌",
-    "口哨",
-    "白",
-    "假发",
-    "意愿",
-    "风车",
-    "冬天",
-    "愿望",
-    "狼",
-    "羊毛",
-    "世界",
-    "蠕虫",
-    "手表",
-    "码尺",
-    "磨冰机",
-    "禅",
-    "零",
-    "拉链",
-    "区域",
-    "动物园",
-    "橡皮糖",
-    "PM2.5",
-    "书包",
-    "口红"
-  ]
-}

File diff suppressed because it is too large
+ 0 - 0
data/data.txt


+ 0 - 3
data/reviewData.json

@@ -1,3 +0,0 @@
-{
-  "data": []
-}

+ 0 - 0
data/reviewData.txt


+ 82 - 3
server.js

@@ -14,7 +14,11 @@ const lruOptions = {
   max: 50,
   maxAge: 1000 * 60 * 60 * 24
 }
-const dataPath = './data/data.json'
+const watchFileOptions = {
+  interval: 60 * 10e2
+}
+const dataPath = './data/data.txt'
+const reviewDataPath = './data/reviewData.txt'
 const staticPath = './dist'
 
 const router = new Router(routerOptions)
@@ -26,7 +30,20 @@ fs.readFile(dataPath, (err, buf) => {
     console.error(err)
     return
   }
-  STATIC_DATA = buf.toString()
+  STATIC_DATA = buf.toString().replace('\n', '')
+})
+
+fs.watchFile(dataPath, watchFileOptions, (curr, prev) => {
+  if (curr.mtime !== prev.mtime) {
+    STATIC_DATA = ''
+    fs.readFile(dataPath, (err, buf) => {
+      if (err) {
+        console.error(err)
+        return
+      }
+      STATIC_DATA = buf.toString().split(',')
+    })
+  }
 })
 
 const app = new Koa()
@@ -78,7 +95,7 @@ router.get('/list', (ctx, next) => {
   if (cache.has(code)) {
     data = cache.get(code)
   } else {
-    const jsonData = JSON.parse(STATIC_DATA).data || []
+    const jsonData = STATIC_DATA || []
     const len = 25
     const sum = jsonData.length - len
     const arr = new Array(25).fill(1).map(el => Math.floor(Math.random() * sum))
@@ -117,6 +134,68 @@ router.put('/status/:code', ctx => {
   ctx.body = { success: true, msg: '更新成功', data: list[index] }
 })
 
+router.post('/words', ctx => {
+  const { request } = ctx
+  const { words = '' } = request.body
+  const wordsList = words.split(',')
+  const noExist = []
+  const exist = wordsList.filter(el => {
+    if (STATIC_DATA.indexOf(el) !== -1) {
+      return true
+    }
+    noExist.push(el)
+    return false
+  })
+  const pushNewWords = noExist.join(',')
+  fs.appendFile(reviewDataPath, pushNewWords, (err) => {
+    if (err) {
+      console.error('appendFile error:', err)
+    }
+  })
+  let body = {}
+  if (exist.length) {
+    body = { success: false, exist }
+  } else {
+    body = { success: true }
+  }
+  ctx.body = body
+})
+router.get('/reviews', ctx => {
+  console.log(ctx.url)
+  const buf = fs.readFileSync(reviewDataPath)
+  const list = buf.toString().split(',')
+  ctx.body = { success: true, list }
+})
+router.post('/reviews', ctx => {
+  const { request } = ctx
+  const { words = '' } = request.body
+  const wordsList = words.split(',')
+  const noExist = []
+  const exist = wordsList.filter(el => {
+    if (STATIC_DATA.indexOf(el) !== -1) {
+      return true
+    }
+    noExist.push(el)
+    return false
+  })
+  try {
+    fs.appendFileSync(dataPath, `,${noExist.join(',')}`)
+    fs.writeFile(reviewDataPath, '', err => {
+      if (err) {
+        return console.error('clear reviewData error:', err)
+      }
+    })
+    if (exist.length) {
+      ctx.body = { success: true, msg: `${exist.join(',')} 添加失败,词已存在` }
+    } else {
+      ctx.body = { success: true, msg: '添加成功' }
+    }
+  } catch (error) {
+    console.error('appendFile error:', error)
+    ctx.body = { success: false, msg: JSON.stringify(error) }
+  }
+})
+
 app.use(router.routes()).use(router.allowedMethods())
 
 app.on('error', err => console.error(err))

+ 1 - 16
src/App.vue

@@ -1,13 +1,10 @@
 <template>
   <div id="app">
-    <Game v-if="selectMode === 'game'"></Game>
-    <Start v-else @game="onStartGame"></Start>
+    <router-view></router-view>
   </div>
 </template>
 
 <script>
-import Game from '@/components/Game'
-import Start from '@/components/Start'
 
 const orientationchangeHandle = () => {
   const orientation = window.orientation
@@ -19,24 +16,12 @@ const orientationchangeHandle = () => {
 }
 export default {
   name: 'app',
-  components: {
-    Game,
-    Start
-  },
-  data() {
-    return {
-      selectMode: 'code'
-    }
-  },
   mounted() {
     this.rotateDevice()
   },
   methods: {
     rotateDevice() {
       window.addEventListener('orientationchange', orientationchangeHandle, false)
-    },
-    onStartGame() {
-      this.selectMode = 'game'
     }
   }
 }

+ 8 - 1
src/components/Start.vue

@@ -3,7 +3,10 @@
     <form>
       <FormInput class="start-input" v-model="code" placeholder="房间密码"></FormInput>
       <FormRadio class="start-radio" v-model="identity" :list="list"></FormRadio>
-      <button class="start-button" @click.prevent="onSubmit">进入房间</button>
+      <div>
+        <button class="start-button" @click.prevent="onSubmit">进入房间</button>
+        <button class="start-button" @click.prevent="onToWords">添加新词</button>
+      </div>
     </form>
   </div>
 </template>
@@ -49,6 +52,9 @@ export default {
       this.$store.commit('SET_CODE', code)
       this.$store.commit('SET_IDENTITY', identity)
       this.$emit('game')
+    },
+    onToWords() {
+      this.$router.push('/words')
     }
   }
 }
@@ -86,6 +92,7 @@ export default {
     border-radius: 5px;
     padding: 5px 15px;
     font-size: 16px;
+    margin: 0 10px;
   }
 }
 </style>

+ 2 - 0
src/main.js

@@ -1,4 +1,5 @@
 import Vue from 'vue'
+import router from './router'
 import App from './App.vue'
 import store from './store'
 
@@ -6,5 +7,6 @@ Vue.config.productionTip = false
 
 new Vue({
   store,
+  router,
   render: h => h(App)
 }).$mount('#app')

+ 32 - 0
src/router.js

@@ -0,0 +1,32 @@
+import Vue from 'vue'
+import Router from 'vue-router'
+import Main from '@/views/Main'
+import Words from '@/views/Words'
+import Review from '@/views/Review'
+
+Vue.use(Router)
+
+const routes = [
+  {
+    path: '/',
+    component: Main
+  },
+  {
+    path: '/words',
+    component: Words
+  },
+  {
+    path: '/review',
+    component: Review
+  },
+  {
+    path: '*',
+    redirect: '/'
+  }
+]
+
+const router = new Router({
+  routes
+})
+
+export default router

+ 34 - 0
src/views/Main.vue

@@ -0,0 +1,34 @@
+<template>
+  <div class="main">
+    <Game v-if="selectMode === 'game'"></Game>
+    <Start v-else @game="onStartGame"></Start>
+  </div>
+</template>
+
+<script>
+import Game from '@/components/Game'
+import Start from '@/components/Start'
+
+export default {
+  name: 'main',
+  components: {
+    Game,
+    Start
+  },
+  data() {
+    return {
+      selectMode: 'code'
+    }
+  },
+  methods: {
+    onStartGame() {
+      this.selectMode = 'game'
+    }
+  }
+}
+</script>
+<style lang="scss" scoped>
+.main {
+  height: 100%;
+}
+</style>

+ 100 - 0
src/views/Review.vue

@@ -0,0 +1,100 @@
+<template>
+  <div class="review">
+    <ul>
+      <li v-for="(word, i) in list" :key="i">
+        <label>
+          <input type="checkbox" :value="word" @change="(e) => { onChange(e, word) }">
+          <span>{{word}}</span>
+        </label>
+      </li>
+    </ul>
+    <p><span>选中的词:</span>{{checkedList.join(',')}}</p>
+    <button class="review-button" :class="{ disabled: disabled }" :disabled="disabled" @click.prevent="onAddWords">添加新词</button>
+  </div>
+</template>
+
+<script>
+import http from '@/http'
+export default {
+  name: 'review',
+  data() {
+    return {
+      list: [],
+      checkedList: [],
+      loading: false
+    }
+  },
+  computed: {
+    disabled() {
+      return this.checkedList.length === 0
+    }
+  },
+  created() {
+    this.getWords()
+  },
+  methods: {
+    onChange(e, word) {
+      const checked = e.target.checked
+      if (checked) {
+        this.checkedList.push(word)
+      } else {
+        this.checkedList.splice(this.checkedList.indexOf(word), 1)
+      }
+    },
+    async getWords() {
+      const { success, list = [] } = await http.get('/api/reviews')
+      if (success) {
+        this.list = list
+      }
+    },
+    async onAddWords() {
+      if (!this.checkedList.length) {
+        return
+      }
+      this.loading = true
+      const words = this.checkedList.join(',')
+      const { success, msg } = await http.post('/api/reviews', { words })
+      alert(msg)
+      if (success) {
+        this.$router.push('/')
+      }
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.review {
+  text-align: left;
+  ul {
+    display: flex;
+    flex-wrap: wrap;
+    list-style: none;
+    padding: 0;
+    margin: 20px 0;
+    li {
+      text-align: left;
+      padding: 10px 20px;
+      input {
+        margin-right: 10px;
+      }
+    }
+  }
+  > p {
+    margin-left: 20px;
+  }
+  .review-button {
+    outline: none;
+    border: none;
+    background-color: #409EFF;
+    color: #fff;
+    border-radius: 5px;
+    padding: 5px 15px;
+    font-size: 16px;
+    margin: 0 20px;
+    &.disabled {
+      cursor: not-allowed
+    }
+  }
+}
+</style>

+ 81 - 0
src/views/Words.vue

@@ -0,0 +1,81 @@
+<template>
+  <div class="words">
+    <form>
+      <FormInput class="words-input" v-model="words" :disabled="loading" placeholder="添加新词语(多个词用,<英文逗号>隔开)"></FormInput>
+      <button class="words-button" @click.prevent="onSubmit">添加新词语</button>
+    </form>
+  </div>
+</template>
+
+<script>
+import FormInput from '@/components/FormInput'
+import http from '@/http'
+export default {
+  name: 'words',
+  components: {
+    FormInput
+  },
+  data() {
+    return {
+      words: '',
+      loading: false
+    }
+  },
+  methods: {
+    async onSubmit() {
+      const { words } = this
+      if (!words) {
+        alert('请输入添加的词语')
+        return
+      }
+      this.loading = true
+      try {
+        const { success, exist = [] } = await http.post('/api/words', { words })
+        this.loading = false
+        if (success) {
+          alert('添加到后台词库,等待同步')
+          this.$router.push('/')
+        } else {
+          const msg = exist.join(',')
+          alert(`${msg} 这些词已存在,添加失败`)
+        }
+      } catch (err) {
+        console.error(err)
+      }
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.words {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  height: 100%;
+  form {
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    flex-direction: column;
+    width: 90%;
+    min-width: 300px;
+    max-width: 800px;
+    margin-top: -50px;
+  }
+  .words-input {
+    width: 80%;
+    max-width: 400px;
+    margin-bottom: 20px;
+  }
+  .words-button {
+    outline: none;
+    border: none;
+    background-color: #409EFF;
+    color: #fff;
+    border-radius: 5px;
+    padding: 5px 15px;
+    font-size: 16px;
+  }
+}
+</style>

Some files were not shown because too many files changed in this diff