Browse Source

11.28

master
lichong 4 months ago
commit
5bdc3a8991
  1. 9
      .editorconfig
  2. 4
      .gitignore
  3. 1
      .npmrc
  4. 6
      .prettierignore
  5. 6
      .prettierrc
  6. 34
      README.md
  7. 12
      build/entitlements.mac.plist
  8. BIN
      build/icon.icns
  9. BIN
      build/icon.ico
  10. 36
      build/notarize.js
  11. 43
      electron-builder.yml
  12. 28
      electron.vite.config.js
  13. 6
      jsconfig.json
  14. 41
      package.json
  15. BIN
      public/icon/icon.jpg
  16. BIN
      public/static/template.docx
  17. 70
      src/main/index.js
  18. 21
      src/preload/dl.js
  19. 21
      src/preload/index.js
  20. 21
      src/renderer/index.html
  21. BIN
      src/renderer/public/error.wav
  22. BIN
      src/renderer/public/play.mp3
  23. BIN
      src/renderer/public/right.wav
  24. 658
      src/renderer/src/App.vue
  25. BIN
      src/renderer/src/assets/bgimg/bgimg.gif
  26. 53
      src/renderer/src/assets/css/base.css
  27. BIN
      src/renderer/src/assets/imgs/chouni.jpg
  28. BIN
      src/renderer/src/assets/imgs/fugu.png
  29. BIN
      src/renderer/src/assets/imgs/ganfanren.jpg
  30. BIN
      src/renderer/src/assets/imgs/luobo.jpg
  31. BIN
      src/renderer/src/assets/imgs/paopao.jpg
  32. BIN
      src/renderer/src/assets/imgs/shuimian.jpg
  33. BIN
      src/renderer/src/assets/imgs/sou.jpg
  34. BIN
      src/renderer/src/assets/imgs/tuzi.jpg
  35. BIN
      src/renderer/src/assets/imgs/xiaoxi.jpg
  36. BIN
      src/renderer/src/assets/imgs/xiaozhu.jpeg
  37. BIN
      src/renderer/src/assets/imgs/yuanbao.jpeg
  38. BIN
      src/renderer/src/assets/imgs/zhangcao.jpg
  39. BIN
      src/renderer/src/assets/imgs/zhaocai.jpg
  40. BIN
      src/renderer/src/assets/imgs/zhenxiang.jpg
  41. BIN
      src/renderer/src/assets/mp3/play.mp3
  42. 30
      src/renderer/src/config.js
  43. 23
      src/renderer/src/main.js
  44. 27
      src/renderer/src/stores/config.js
  45. 5
      src/renderer/src/stores/index.js
  46. BIN
      src/renderer/src/template.docx
  47. 2986
      yarn.lock

9
.editorconfig

@ -0,0 +1,9 @@
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true

4
.gitignore

@ -0,0 +1,4 @@
node_modules
dist
out
*.log*

1
.npmrc

@ -0,0 +1 @@
ELECTRON_MIRROR=https://npmmirror.com/mirrors/electron/

6
.prettierignore

@ -0,0 +1,6 @@
out
dist
pnpm-lock.yaml
LICENSE.md
tsconfig.json
tsconfig.*.json

6
.prettierrc

@ -0,0 +1,6 @@
{
"singleQuote": true,
"semi": false,
"printWidth": 100,
"trailingComma": "none"
}

34
README.md

@ -0,0 +1,34 @@
# my-app
An Electron application with Vue
## Recommended IDE Setup
- [VSCode](https://code.visualstudio.com/) + [ESLint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) + [Prettier](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode)
## Project Setup
### Install(node 16.20.1)
```bash
$ npm install
```
### Development
```bash
$ npm run dev
```
### Build
```bash
# For windows
$ npm run build:win
# For macOS
$ npm run build:mac
# For Linux
$ npm run build:linux
```

12
build/entitlements.mac.plist

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
<key>com.apple.security.cs.allow-dyld-environment-variables</key>
<true/>
</dict>
</plist>

BIN
build/icon.icns

Binary file not shown.

BIN
build/icon.ico

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

36
build/notarize.js

@ -0,0 +1,36 @@
const { notarize } = require('electron-notarize')
module.exports = async (context) => {
if (process.platform !== 'darwin') return
console.log('aftersign hook triggered, start to notarize app.')
if (!process.env.CI) {
console.log(`skipping notarizing, not in CI.`)
return
}
if (!('APPLE_ID' in process.env && 'APPLE_ID_PASS' in process.env)) {
console.warn('skipping notarizing, APPLE_ID and APPLE_ID_PASS env variables must be set.')
return
}
const appId = 'com.electron.app'
const { appOutDir } = context
const appName = context.packager.appInfo.productFilename
try {
await notarize({
appBundleId: appId,
appPath: `${appOutDir}/${appName}.app`,
appleId: process.env.APPLE_ID,
appleIdPassword: process.env.APPLEIDPASS
})
} catch (error) {
console.error(error)
}
console.log(`done notarizing ${appId}.`)
}

43
electron-builder.yml

@ -0,0 +1,43 @@
appId: com.electron.lichong
productName: 桌面应用
directories:
buildResources: build
files:
- '!**/.vscode/*'
- '!src/*'
- '!electron.vite.config.{js,ts,mjs,cjs}'
- '!{.eslintignore,.eslintrc.cjs,.prettierignore,.prettierrc.yaml,dev-app-update.yml,CHANGELOG.md,README.md}'
asarUnpack:
- '**/*.{node,dll}'
afterSign: build/notarize.js
win:
executableName: lichong-app
nsis:
oneClick: false
artifactName: ${name}-${version}-setup.${ext}
allowToChangeInstallationDirectory: true
shortcutName: ${productName}
uninstallDisplayName: ${productName}
createDesktopShortcut: always
mac:
entitlementsInherit: build/entitlements.mac.plist
extendInfo:
- NSCameraUsageDescription: Application requests access to the device's camera.
- NSMicrophoneUsageDescription: Application requests access to the device's microphone.
- NSDocumentsFolderUsageDescription: Application requests access to the user's Documents folder.
- NSDownloadsFolderUsageDescription: Application requests access to the user's Downloads folder.
dmg:
artifactName: ${name}-${version}.${ext}
linux:
target:
- AppImage
- snap
- deb
maintainer: electronjs.org
category: Utility
appImage:
artifactName: ${name}-${version}.${ext}
npmRebuild: false
publish:
provider: generic
url: https://example.com/auto-updates

28
electron.vite.config.js

@ -0,0 +1,28 @@
import { resolve } from 'path'
import { defineConfig, externalizeDepsPlugin } from 'electron-vite'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
main: {
plugins: [externalizeDepsPlugin()]
},
preload: {
plugins: [externalizeDepsPlugin()],
build: {
rollupOptions: {
input: {
dl: resolve(__dirname, 'src/preload/dl.js'),
index: resolve(__dirname, 'src/preload/index.js')
}
}
}
},
renderer: {
resolve: {
alias: {
'@renderer': resolve('src/renderer/src')
}
},
plugins: [vue()]
}
})

6
jsconfig.json

@ -0,0 +1,6 @@
{
"exclude": [
"node_modules",
"public"
]
}

41
package.json

@ -0,0 +1,41 @@
{
"name": "electron",
"version": "1.0.0",
"description": "An Electron application with Vue",
"main": "./out/main/index.js",
"author": "lichong",
"homepage": "https://www.electronjs.org",
"scripts": {
"format": "prettier --write .",
"lint": "eslint . --ext .js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix",
"start": "electron-vite preview",
"dev": "electron-vite dev",
"build": "electron-vite build",
"postinstall": "electron-builder install-app-deps",
"build:win": "npm run build && electron-builder --win --config",
"build:mac": "npm run build && electron-builder --mac --config",
"build:linux": "npm run build && electron-builder --linux --config"
},
"dependencies": {
"@electron-toolkit/preload": "^1.0.2",
"@electron-toolkit/utils": "^1.0.2",
"dayjs": "^1.11.11",
"element-plus": "^2.7.1",
"lodash": "^4.17.21",
"pinia": "^2.1.7",
"pinia-plugin-persist": "^1.0.0"
},
"devDependencies": {
"@rushstack/eslint-patch": "^1.2.0",
"@vitejs/plugin-vue": "^3.1.2",
"@vue/eslint-config-prettier": "^7.0.0",
"electron": "^20.3.2",
"electron-builder": "^23.6.0",
"electron-notarize": "^1.2.1",
"electron-vite": "^1.0.11",
"less": "^4.1.3",
"prettier": "^2.7.1",
"vite": "^3.1.8",
"vue": "^3.2.41"
}
}

BIN
public/icon/icon.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
public/static/template.docx

Binary file not shown.

70
src/main/index.js

@ -0,0 +1,70 @@
import { app, shell, BrowserWindow, nativeImage } from 'electron'
import * as path from 'path'
import { electronApp, optimizer, is } from '@electron-toolkit/utils'
// logo
const logoIcon = nativeImage.createFromPath(path.join(__dirname, '../../public/icon/icon.jpg'))
console.log(process.versions.node)
// 主窗口
let mainWindow
function createWindow() {
mainWindow = new BrowserWindow({
// fullscreen: true,
// fullscreenable: true,
minWidth: 1366,
minHeight: 768,
show: false,
autoHideMenuBar: true,
icon: logoIcon,
webPreferences: {
preload: path.resolve(__dirname, '../preload/index.js'),
sandbox: false
}
})
mainWindow.on('ready-to-show', () => {
mainWindow.show()
// mainWindow.webContents.openDevTools()
})
mainWindow.webContents.setWindowOpenHandler((details) => {
shell.openExternal(details.url)
return { action: 'deny' }
})
// mainWindow.loadURL('http://localhost:5173/')
mainWindow.on('close', () => {
app.exit()
})
if (is.dev && process.env['ELECTRON_RENDERER_URL']) {
mainWindow.loadURL(process.env['ELECTRON_RENDERER_URL'])
} else {
mainWindow.loadFile(path.join(__dirname, '../renderer/index.html'))
}
}
app.whenReady().then(() => {
electronApp.setAppUserModelId('com.electron')
// Default open or close DevTools by F12 in development
// and ignore CommandOrControl + R in production.
// see https://github.com/alex8088/electron-toolkit/tree/master/packages/utils
app.on('browser-window-created', (_, window) => {
optimizer.watchWindowShortcuts(window)
})
createWindow()
app.on('activate', function () {
// On macOS it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
})
app.commandLine.appendSwitch('autoplay-policy', 'no-user-gesture-required');
// Quit when all windows are closed, except on macOS. There, it's common
// for applications and their menu bar to stay active until the user quits
// explicitly with Cmd + Q.
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
// In this file you can include the rest of your app"s specific main process
// code. You can also put them in separate files and require them here.

21
src/preload/dl.js

@ -0,0 +1,21 @@
import { contextBridge, clipboard } from 'electron'
import { electronAPI } from '@electron-toolkit/preload'
// Custom APIs for renderer
const api = {}
// Use `contextBridge` APIs to expose Electron APIs to
// renderer only if context isolation is enabled, otherwise
// just add to the DOM global.
if (process.contextIsolated) {
try {
contextBridge.exposeInMainWorld('electron', electronAPI)
contextBridge.exposeInMainWorld('api', api)
contextBridge.exposeInMainWorld('elecClipboard', clipboard)
} catch (error) {
console.error(error)
}
} else {
window.electron = electronAPI
window.api = api
}

21
src/preload/index.js

@ -0,0 +1,21 @@
import { contextBridge, clipboard } from 'electron'
import { electronAPI } from '@electron-toolkit/preload'
// Custom APIs for renderer
const api = {}
// Use `contextBridge` APIs to expose Electron APIs to
// renderer only if context isolation is enabled, otherwise
// just add to the DOM global.
if (process.contextIsolated) {
try {
contextBridge.exposeInMainWorld('electron', electronAPI)
contextBridge.exposeInMainWorld('api', api)
contextBridge.exposeInMainWorld('elecClipboard', clipboard)
} catch (error) {
console.error(error)
}
} else {
window.electron = electronAPI
window.api = api
}

21
src/renderer/index.html

@ -0,0 +1,21 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>桌面应用</title>
<!-- <link rel="icon" href="/icon/icon.jpg" /> -->
<!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
<meta
http-equiv="Content-Security-Policy"
content="default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'"
/>
</head>
<body>
<div id="app"></div>
<audio src="./play.mp3" autoplay id="myAudio1" loop></audio>
<audio src="./right.wav" id="right"></audio>
<audio src="./error.wav" id="error"></audio>
<script type="module" src="/src/main.js"></script>
</body>
</html>

BIN
src/renderer/public/error.wav

Binary file not shown.

BIN
src/renderer/public/play.mp3

Binary file not shown.

BIN
src/renderer/public/right.wav

Binary file not shown.

658
src/renderer/src/App.vue

@ -0,0 +1,658 @@
<template>
<div class="appClass" v-if="isVip">
<template v-for="(perItem, perIndex) in personList" :key="perIndex">
<div :class="`parent${perIndex}`">
<div :class="`avatar${perIndex}`">
<el-avatar size="large" shape="square">
<img :src="perItem.ava" alt="头像" />
</el-avatar>
</div>
<div :class="`usetime${perIndex}`" style="display: inline-block">
<el-progress type="circle" striped striped-flow :stroke-width="10" :color="colors" :width="80"
:percentage="timeObj[`time${perIndex}`]">
<span style="color: #000; font-size: 3em">{{ timeObj[`time${perIndex}`] }}</span>
</el-progress>
</div>
<div :class="`result${perIndex}`" style="display: inline-block">
<span v-if="perItem.time">
耗时 {{ perItem.time / 100 }}答对
<el-text :type="type[_.compact(perItem.sure).length]" style="font-size: 1.2em">
{{ _.compact(perItem.sure).length }}
</el-text>
道题
</span>
<span v-else>{{ perItem.currentTi + 1 }}</span>
</div>
<div :id="`yanmo${perIndex}`"></div>
<template v-for="(item, index) in perItem.questionList" :key="index">
<template v-if="perItem.currentTi === index">
<div :class="`question${perIndex}`">
<div class="title">
{{ item.title }}
</div>
</div>
<div class="options">
<div v-for="(optionItem, optionIndex) in item.options" :class="`option${perIndex}`" :key="optionIndex">
<el-tag v-if="optionItem.disabled" :type="optionItem.type" effect="dark">
{{ optionItem.text }}
</el-tag>
<el-check-tag :checked="optionItem.checked" :type="optionItem.type" v-else
@change="onChange1(optionItem, optionIndex, item, perItem, perIndex)" effect="dark">
{{ optionItem.text }}
</el-check-tag>
</div>
</div>
</template>
</template>
<div :class="`next${perIndex}`">
<div>
<el-button size="large" type="primary" v-if="!perItem.time" @click="nextTi(perItem, perIndex)" :disabled="perItem.questionList[perItem.currentTi].answer === -1 || perItem.clickDisable
">
<span style="font-size: 2em; margin: 18px 8px"> 确定 </span>
</el-button>
<el-button size="large" type="primary" v-else @click="submit(perItem, perIndex)" :disabled="!!perItem.time">
<span style="font-size: 2em; padding: 8px"> 已结束 </span>
</el-button>
</div>
</div>
</div>
</template>
</div>
<div v-else class="noVip">
<h3>
<el-tag type="danger" class="noVipTag">体验已过期请联系管理员</el-tag>
</h3>
</div>
<el-dialog v-model="dialogInfo.show" :title="dialogInfo.title" width="80%" center :before-close="handleClose">
<div>
<el-row>
<el-col :span="12" v-for="(perItem, perIndex) in personList" :key="perIndex" style="text-align: center">
<div class="mt-10">
<el-avatar size="large" shape="square">
<img :src="perItem.ava" alt="头像" />
</el-avatar>
</div>
<div class="mt-20">
<span style="font-size: 3em">
您一共耗时 {{ perItem.time / 100 }}答对
<el-text :type="type[_.compact(perItem.sure).length]">
<span style="font-size: 3em">
{{ _.compact(perItem.sure).length }}
</span>
</el-text>
道题
</span>
</div>
<div class="mt-20">
<el-progress type="circle" v-if="dialogInfo.winIndex === perIndex" :percentage="100" status="success">
<span style="color: #000;font-size: 3em;"></span>
</el-progress>
<el-progress type="circle" v-else :percentage="100" status="exception">
<span style="color: #000;font-size: 3em;"></span>
</el-progress>
</div>
</el-col>
</el-row>
</div>
<template #footer>
<div class="dialogFooter">
<el-button type="primary" @click="continuePk" style="font-size: 2.5em;height: 2em;"> 继续比赛 </el-button>
</div>
</template>
</el-dialog>
<div v-if="diolag" class="el-overlay-dialog" @click="handleCloseDialog"
style="text-align: center; align-content: center">
<div><img src="/src/assets/bgimg/bgimg.gif" alt="pk" style="margin-top: 25vh" /></div>
</div>
</template>
<script>
import config from './config.js'
import _ from 'lodash'
import useConfigStore from './stores/config.js'
import dayjs from 'dayjs'
import { ElMessage, ElMessageBox } from 'element-plus'
export default {
name: 'app',
data() {
return {
_: _,
ava0: '',
ava1: '',
timeObj: {
timer0: null,
timer1: null,
time0: 100,
time1: 100
},
personList: [],
colors: [
{ color: '#ff0000', percentage: 3 },
{ color: '#c45656', percentage: 10 },
{ color: '#F56C6C', percentage: 20 },
{ color: '#f89898', percentage: 30 },
{ color: '#fab6b6', percentage: 40 },
{ color: '#fde2e2', percentage: 50 },
{ color: '#f3d19e', percentage: 60 },
{ color: '#eebe77', percentage: 70 },
{ color: '#95d475', percentage: 80 },
{ color: '#67C23A', percentage: 90 },
{ color: '#529b2e', percentage: 100 }
],
type: ['danger', 'warning', 'info', 'primary', 'success'],
isVip: true,
configStore: useConfigStore(),
dialogInfo: {
show: false,
title: '比赛结果',
winIndex: -1
},
diolag: true,
clickCount: 0,
avaList: []
}
},
methods: {
init(isc = false) {
this.dealData()
this.setTime('timer0', 'time0', isc)
this.setTime('timer1', 'time1', isc)
},
setTime(name, time, isGo = true) {
this.timeObj[time] = 100
if (this.timeObj[name]) {
clearInterval(this.timeObj[name])
}
if (isGo) {
this.timeObj[name] = setInterval(() => {
this.timeObj[time] -= 1
this.timeObj[time] = _.max([this.timeObj[time], 0])
}, 1000)
}
},
getAva() {
this.clickCount++
console.log(777, this.clickCount, this.avaList)
if (this.clickCount % 2) {
let arr = _.values(config)
let random = _.shuffle(arr)
this.avaList = [random[0], random[1]]
}
},
dealData() {
this.getAva()
this.personList = []
for (let i = 0; i < 2; i++) {
let item = {
ava: this.avaList[i],
questionList: [
{
title: '衣服可以保暖,体现了产品层次模型中的哪一层次产品?',
options: [
{
text: 'A 核心产品',
checked: false,
type: 'info',
disabled: false
},
{
text: 'B 形式产品',
checked: false,
type: 'info',
disabled: false
},
{
text: 'C 期望产品',
checked: false,
type: 'info',
disabled: false
},
{
text: 'D 附加产品',
checked: false,
type: 'info',
disabled: false
}
],
answer: -1,
trueAnswer: 0,
startTime: parseInt(dayjs().valueOf() / 10),
endTime: 0
},
{
title: '产品的五层次中,____是指产品的品质、样式、包装和商标等。',
options: [
{
text: 'A 核心产品',
checked: false,
type: 'info',
disabled: false
},
{
text: 'B 形式产品',
checked: false,
type: 'info',
disabled: false
},
{
text: 'C 延伸产品',
checked: false,
type: 'info',
disabled: false
},
{
text: 'D 潜在产品',
checked: false,
type: 'info',
disabled: false
}
],
answer: -1,
trueAnswer: 1,
startTime: 0,
endTime: 0
},
{
title:
'顾客希望旅游景区能够呈现丰富的旅游资源、干净整洁的游园环境、完善的基础设施设备,体现了产品层次模型中的哪一层次产品?',
options: [
{
text: 'A 核心产品',
checked: false,
type: 'info',
disabled: false
},
{
text: 'B 期望产品',
checked: false,
type: 'info',
disabled: false
},
{
text: 'C 形式产品',
checked: false,
type: 'info',
disabled: false
},
{
text: 'D 潜在产品',
checked: false,
type: 'info',
disabled: false
}
],
answer: -1,
trueAnswer: 1,
startTime: 0,
endTime: 0
},
{
title:
'在传统村落白虎村旅游地可以购买纪念品、旅游保险、拍摄个人照片等,增强了游客的旅游体验,这属于哪一层次产品?',
options: [
{
text: 'A 核心产品',
checked: false,
type: 'info',
disabled: false
},
{
text: 'B 形式产品',
checked: false,
type: 'info',
disabled: false
},
{
text: 'C 延伸产品',
checked: false,
type: 'info',
disabled: false
},
{
text: 'D 潜在产品',
checked: false,
type: 'info',
disabled: false
}
],
answer: -1,
trueAnswer: 2,
startTime: 0,
endTime: 0
},
{
title: '传统皮影面临困境,正在向数字皮影转型,体现了产品五层次模型中的哪一层次产品?',
options: [
{
text: 'A 核心产品',
checked: false,
type: 'info',
disabled: false
},
{
text: 'B 形式产品',
checked: false,
type: 'info',
disabled: false
},
{
text: 'C 期望产品',
checked: false,
type: 'info',
disabled: false
},
{
text: 'D 潜在产品',
checked: false,
type: 'info',
disabled: false
}
],
answer: -1,
trueAnswer: 3,
startTime: 0,
endTime: 0
}
],
currentTi: 0,
clickDisable: false, //
time: 0,
sure: []
}
this.personList.push(_.cloneDeep(item))
}
},
onChange1(optionItem, optionIndex, item, perItem, perIndex) {
optionItem.checked = true
item.answer = optionIndex
for (let i = 0; i < item.options.length; i++) {
if (optionIndex !== i) {
item.options[i].checked = false
}
item.options[i].type = 'info'
}
optionItem.type = 'success'
},
nextTi(perItem, perIndex) {
let duration = 1500
perItem.clickDisable = true
let item = perItem.questionList[perItem.currentTi]
if (item.answer !== item.trueAnswer) {
item.options[item.answer].type = 'danger'
item.options[item.trueAnswer].type = 'success'
} else {
item.options[item.trueAnswer].type = 'success'
}
perItem.questionList[perItem.currentTi].endTime = parseInt(dayjs().valueOf() / 10)
for (let i = 0; i < perItem.questionList[perItem.currentTi].options.length; i++) {
let ele = perItem.questionList[perItem.currentTi].options[i]
ele.disabled = true
}
let _msg = -1
if (
perItem.questionList[perItem.currentTi].answer ===
perItem.questionList[perItem.currentTi].trueAnswer
) {
_msg = ElMessage({
type: 'info',
duration: duration - 500,
customClass: 'yanmo',
icon: 'check',
message: '恭喜你,答对了!',
appendTo: document.getElementById(`yanmo${perIndex}`)
})
let rightAudio = document.getElementById('right')
rightAudio.play()
} else {
_msg = ElMessage({
type: 'info',
duration: duration - 500,
customClass: 'yanmo',
icon: 'close',
message: '很遗憾,打错了!',
appendTo: document.getElementById(`yanmo${perIndex}`)
})
let errorAudio = document.getElementById('error')
errorAudio.play()
}
setTimeout(() => {
if (_msg !== -1) {
_msg.close()
}
//
if (perItem.currentTi == perItem.questionList.length - 1) {
this.submit(perItem, perIndex)
}
let count = perItem.questionList.length
perItem.currentTi += 1
perItem.currentTi %= count
//
perItem.questionList[perItem.currentTi].startTime = parseInt(dayjs().valueOf() / 10)
this.setTime(`timer${perIndex}`, `time${perIndex}`)
perItem.clickDisable = false
}, duration)
},
//
submit(perItem, perIndex) {
perItem.time = 0
perItem.sure = []
for (let i = 0; i < perItem.questionList.length; i++) {
let element = perItem.questionList[i]
perItem.time += element.endTime - element.startTime
perItem.sure.push(element.trueAnswer === element.answer)
}
let pass = true
let sure = []
let time = []
for (let i = 0; i < JSON.parse(JSON.stringify(this.personList)).length; i++) {
let ele = this.personList[i]
sure.push(_.compact(ele.sure))
time.push(ele.time)
if (!ele.time) {
pass = false
break
}
}
if (_.compact(sure[0]).length > _.compact(sure[1]).length) {
this.dialogInfo.winIndex = 0
} else if (_.compact(sure[0]).length === _.compact(sure[1]).length) {
if (time[0] > time[1]) {
this.dialogInfo.winIndex = 1
} else {
this.dialogInfo.winIndex = 0
}
} else {
this.dialogInfo.winIndex = 1
}
if (pass) {
this.dialogInfo.show = true
}
this.setTime(`timer${perIndex}`, `time${perIndex}`, false)
},
handleClose(done) {
done()
this.continuePk()
},
continuePk() {
this.dialogInfo.show = false
this.diolag = true
this.init()
},
handleCloseDialog() {
this.diolag = false
this.init(true)
}
},
async mounted() {
let audio = document.getElementById('myAudio1')
audio.addEventListener('canplay', function () {
audio.volume = 0.1
})
let fiveDay = dayjs('2024-05-21T00:00:00').valueOf()
if (!this.isVip) {
if (dayjs().valueOf() > fiveDay) {
this.isVip = false
return
} else {
this.isVip = true
}
}
this.dealData()
},
watch: {},
computed: {}
}
</script>
<style scoped>
.appClass {
width: 100vw;
height: 100vh;
color: #000;
background-color: #d9ecff;
}
.parent0 {
border-right: 20vw solid #fff;
display: inline-block;
width: 40vw;
height: 100vh;
}
.parent1 {
display: inline-block;
width: 40vw;
height: 100vh;
}
.avatar0 {
text-align: left;
margin: 6px 0 0 6px;
min-height: 10vh;
width: 100%;
}
.avatar1 {
text-align: right;
margin: 6px 16px 0 0;
min-height: 10vh;
width: 99%;
}
.usetime0 {
text-align: center;
height: 0;
position: relative;
top: -10vh;
width: 100%;
}
.usetime1 {
text-align: center;
height: 0;
position: relative;
top: -10vh;
width: 100%;
}
.result0 {
text-align: center;
position: relative;
top: -10vh;
min-height: 8vh;
width: 100%;
font-size: 2em;
}
.result1 {
text-align: center;
position: relative;
top: -10vh;
min-height: 8vh;
width: 100%;
font-size: 2em;
}
.question0 {
height: 20vh;
text-align: center;
position: relative;
top: -10vh;
}
.question1 {
height: 20vh;
text-align: center;
position: relative;
top: -10vh;
}
.title {
text-indent: 2em;
width: 76%;
margin-left: 10%;
height: 31vh;
color: #000;
padding: 1% 2% 0 2%;
font-size: 2.3em;
border-radius: 10px;
text-align: left;
align-content: center;
background-color: #4bc1ed;
}
.options {
width: 80%;
border-radius: 30px;
margin-left: 10%;
height: 34vh;
color: #fff;
text-align: center;
padding-top: 1vh;
margin-top: 3vh;
background-color: #4bc1ed;
}
.option0 {
height: calc(9vh - 12px);
margin-top: 6px;
}
.option1 {
height: calc(9vh - 12px);
margin-top: 6px;
}
.next0 {
padding-top: 4vh;
min-height: 5vh;
width: 100%;
text-align: center;
}
.next1 {
padding-top: 4vh;
min-height: 5vh;
width: 100%;
text-align: center;
}
.mt-10 {
margin-top: 20px;
}
.mt-20 {
margin: 40px 0;
}
.noVip {
text-align: center;
margin-top: 40vh;
}
.noVipTag {
font-size: 3em;
line-height: 1.6em;
height: 1.6em;
}
</style>

BIN
src/renderer/src/assets/bgimg/bgimg.gif

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

53
src/renderer/src/assets/css/base.css

@ -0,0 +1,53 @@
html,
body {
margin: 0;
padding: 0;
}
.option0 .el-check-tag {
padding: 20px 60px;
font-size: 2em;
padding: 13px 60px;
}
.option1 .el-check-tag {
padding: 20px 60px;
font-size: 2em;
padding: 13px 60px;
}
.option0 .el-tag {
padding: 20px 60px;
font-size: 2em;
}
.option1 .el-tag {
padding: 20px 60px;
font-size: 2em;
}
.yanmo {
position: relative;
height: 35vh;
width: 24vw;
top: 20vh !important;
background-color: #83838399;
border: none;
}
.yanmo .el-icon {
position: relative;
left: 6vw;
font-size: 20vh;
top: -5vh;
color: #fff;
}
.yanmo .el-message__content {
position: relative;
left: -4vw;
width: 248px;
font-size: 1em;
top: 5vh;
color: #fff;
}
#yanmo0 {
height: 0px;
}
#yanmo1 {
height: 0px;
}

BIN
src/renderer/src/assets/imgs/chouni.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

BIN
src/renderer/src/assets/imgs/fugu.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 608 KiB

BIN
src/renderer/src/assets/imgs/ganfanren.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

BIN
src/renderer/src/assets/imgs/luobo.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

BIN
src/renderer/src/assets/imgs/paopao.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 164 KiB

BIN
src/renderer/src/assets/imgs/shuimian.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

BIN
src/renderer/src/assets/imgs/sou.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

BIN
src/renderer/src/assets/imgs/tuzi.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

BIN
src/renderer/src/assets/imgs/xiaoxi.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 138 KiB

BIN
src/renderer/src/assets/imgs/xiaozhu.jpeg

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
src/renderer/src/assets/imgs/yuanbao.jpeg

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

BIN
src/renderer/src/assets/imgs/zhangcao.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

BIN
src/renderer/src/assets/imgs/zhaocai.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

BIN
src/renderer/src/assets/imgs/zhenxiang.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

BIN
src/renderer/src/assets/mp3/play.mp3

Binary file not shown.

30
src/renderer/src/config.js

@ -0,0 +1,30 @@
import chouni from "./assets/imgs/chouni.jpg"
import fugu from "./assets/imgs/fugu.png"
import ganfanren from "./assets/imgs/ganfanren.jpg"
import luobo from "./assets/imgs/luobo.jpg"
import paopao from "./assets/imgs/paopao.jpg"
import shuimian from "./assets/imgs/sou.jpg"
import sou from "./assets/imgs/tuzi.jpg"
import tuzi from "./assets/imgs/xiaoxi.jpg"
import xiaoxi from "./assets/imgs/xiaozhu.jpeg"
import yuanbao from "./assets/imgs/yuanbao.jpeg"
import zhangcao from "./assets/imgs/zhangcao.jpg"
import zhaocai from "./assets/imgs/zhaocai.jpg"
import zhenxiang from "./assets/imgs/zhenxiang.jpg"
export default
{
chouni,
fugu,
ganfanren,
luobo,
paopao,
shuimian,
sou,
tuzi,
xiaoxi,
yuanbao,
zhangcao,
zhaocai,
zhenxiang
}

23
src/renderer/src/main.js

@ -0,0 +1,23 @@
// main.ts
import { createApp } from 'vue'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import App from './App.vue'
import './assets/css/base.css'
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
const app = createApp(App)
import pinia from './stores'
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
app.component(key, component)
}
app.use(ElementPlus)
app.use(pinia)
app.mount('#app')
document.addEventListener('keydown', (event) => {
const { ctrlKey, shiftKey, key } = event
if ((ctrlKey && shiftKey && key === 'I') || key === 'F12') {
return event.preventDefault()
}
})

27
src/renderer/src/stores/config.js

@ -0,0 +1,27 @@
import { defineStore } from 'pinia'
const useConfigStore = defineStore('config', {
state: () => {
return {
tableData: []
}
},
actions: {
setTableData(Data = []) {
console.log(999, Data)
this.tableData = Data
},
getTableData() {
return this.tableData
},
},
//整个仓库持久化存储
persist: {
enabled: true,
//指定字段存储,并且指定存储方式:
strategies: [
{ storage: sessionStorage, paths: ['tableData'] }, // tableData字段用sessionStorage存储
{ storage: localStorage, paths: ['tableData'] }, // accessToken字段用 localstorage存储
],
},
})
export default useConfigStore

5
src/renderer/src/stores/index.js

@ -0,0 +1,5 @@
import { createPinia } from "pinia";
import piniaPluginPersist from "pinia-plugin-persist"
const pinia = createPinia();
pinia.use(piniaPluginPersist)
export default pinia;

BIN
src/renderer/src/template.docx

Binary file not shown.

2986
yarn.lock

File diff suppressed because it is too large
Loading…
Cancel
Save