Compare commits

...

4 Commits

  1. BIN
      dist.zip
  2. 0
      public/img/map/d1.png
  3. 0
      public/img/map/d2.png
  4. 0
      public/img/map/d3.png
  5. 0
      public/img/map/map.jpg
  6. BIN
      src/assets/icons/map.jpg
  7. BIN
      src/assets/icons/player-s.png
  8. BIN
      src/assets/icons/red.gif
  9. 6
      src/components/dialog.vue
  10. 15
      src/components/equip-icon.vue
  11. 8
      src/config/assets.ts
  12. 6
      src/store/action.ts
  13. 2
      src/store/mutation.ts
  14. 11
      src/store/state.ts
  15. 1
      src/tool/index.ts
  16. 4
      src/tool/mixins/popoverMenu.ts
  17. 47
      src/tool/mobile.ts
  18. 1
      src/views/backpack/backpack.vue
  19. 24
      src/views/backpack/grid.vue
  20. 30
      src/views/dungeon/battle.vue
  21. 15
      src/views/dungeon/dungeon.vue
  22. 9
      src/views/dungeon/dungeonMap.vue
  23. 3
      src/views/index.vue
  24. 33
      src/views/shop/shop.vue
  25. 4
      src/views/version/update-log.vue

BIN
dist.zip

Binary file not shown.

0
src/assets/icons/d1.png → public/img/map/d1.png

Before

Width:  |  Height:  |  Size: 611 B

After

Width:  |  Height:  |  Size: 611 B

0
src/assets/icons/d2.png → public/img/map/d2.png

Before

Width:  |  Height:  |  Size: 586 B

After

Width:  |  Height:  |  Size: 586 B

0
src/assets/icons/d3.png → public/img/map/d3.png

Before

Width:  |  Height:  |  Size: 576 B

After

Width:  |  Height:  |  Size: 576 B

0
public/img/map.jpg → public/img/map/map.jpg

Before

Width:  |  Height:  |  Size: 87 KiB

After

Width:  |  Height:  |  Size: 87 KiB

BIN
src/assets/icons/map.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 87 KiB

BIN
src/assets/icons/player-s.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

BIN
src/assets/icons/red.gif

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

6
src/components/dialog.vue

@ -1,6 +1,7 @@ @@ -1,6 +1,7 @@
<template>
<teleport to="#app">
<div class="dialog" v-show="show" @contextmenu.prevent="console.log('禁用浏览器默认右键功能')">
<div class="dialog" v-show="show" @contextmenu.prevent="console.log('禁用浏览器默认右键功能')"
@click=" commit('close_equip_tip');">
<div class="content" @click.native.stop>
<div class="title" v-if="title">
<span>{{ title }}</span>
@ -63,6 +64,9 @@ const prop = defineProps({ @@ -63,6 +64,9 @@ const prop = defineProps({
})
watch(show, (n, o) => {
emit('update:modelValue', n);
if (!n) {
commit('close_equip_tip');
}
})
watch(() => prop.modelValue, (n, o) => {
show.value = n;

15
src/components/equip-icon.vue

@ -1,6 +1,6 @@ @@ -1,6 +1,6 @@
<template>
<div class='icon' :class="{ 'red-flash': equip && isUnique(equip) }"
:style="{ 'box-shadow': 'inset 0 0 7px 2px ' + ((equip && equip.quality.color) || '#a1a1a1') }">
<div class='icon' :style="{ 'box-shadow': 'inset 0 0 7px 2px ' + ((equip && equip.quality.color) || '#a1a1a1') }">
<img v-if="equip && isUnique(equip)" class="red-flash" :src="red_icon">
<span v-if="equip">
<img :src="equips_icon_path + equip.base.icon">
<div class="lv" v-if="equip.lv">lv{{ equip.lv }}</div>
@ -12,7 +12,7 @@ @@ -12,7 +12,7 @@
import { useStore } from "vuex";
import { reactive, onMounted, ref, computed } from "vue";
import { useI18n } from "vue3-i18n";
import { qualitys, equips_icon_path } from "@/config";
import { qualitys, equips_icon_path, red_icon } from "@/config";
const { t } = useI18n();
const { state, commit, dispatch } = useStore();
@ -61,11 +61,10 @@ onMounted(() => { }); @@ -61,11 +61,10 @@ onMounted(() => { });
}
}
.red-flash.icon {
background-image: url(@/assets/icons/red.gif) !important;
background-repeat: no-repeat !important;
background-position: center !important;
background-size: contain !important;
.red-flash {
position: absolute;
width: 100%;
height: 100%;
}
@media only screen and (max-width: 768px) {

8
src/config/assets.ts

@ -1,5 +1,6 @@ @@ -1,5 +1,6 @@
// const root = 'http://assets.xumy.vip';
const root = process.env.VUE_APP_BASE_URL ? '' : 'http://assets.xumy.vip';
// const root = '.';
export const audio_mp3 = {
background: root + '/audio/backgound.mp3',
@ -40,11 +41,18 @@ export const close_icon = root + '/img/close.png'; @@ -40,11 +41,18 @@ export const close_icon = root + '/img/close.png';
export const refresh_icon = root + '/img/re.png';
export const playerImg = root + '/img/player.png';
export const playerImg2 = root + '/img/player2.png';
export const red_icon = root + '/img/red.gif';
export const warning_icon = root + '/img/tip/warning.png';
export const dungeon_icon = {
map: root + '/img/map/map.jpg',
player: root + '/img/map/player-s.png',
monster: root + '/img/map/monster.png',
boss: root + '/img/map/boss.png',
0: root + '/img/map/d1.png',
1: root + '/img/map/d1.png',
2: root + '/img/map/d2.png',
3: root + '/img/map/d3.png',
};

6
src/store/action.ts

@ -1,11 +1,11 @@ @@ -1,11 +1,11 @@
import { initialWeapon, initialArmor, initialNeck, initialRing, i18n, archive_name } from '@/config';
import { initialWeapon, initialArmor, initialNeck, initialRing, i18n, archive_name, audio_mp3 } from '@/config';
import { conisOfsell } from '@/tool';
import { Base64 } from 'js-base64';
const backgound = new Audio('/audio/backgound.mp3');
const backgound = new Audio(audio_mp3.background);
backgound.loop = true;
backgound.volume = 0.2;
const battle = new Audio('/audio/battle.mp3');
const battle = new Audio(audio_mp3.battle);
battle.loop = true;
battle.volume = 0.2;
const music = {

2
src/store/mutation.ts

@ -41,11 +41,9 @@ export const show_equip_tip = (state, data) => { @@ -41,11 +41,9 @@ export const show_equip_tip = (state, data) => {
state.equipTip.tipsStyle = styles[0];
state.equipTip.tipsStyle2 = styles[1];
state.equipTip.tipsShow = true;
console.log('show');
};
export const close_equip_tip = (state) => {
state.equipTip.tipsShow = false;
console.log('close');
};
export const clear_sys_info = (state, data) => {
state.sysInfo.splice(1, state.sysInfo.length);

11
src/store/state.ts

@ -73,10 +73,13 @@ export default { @@ -73,10 +73,13 @@ export default {
},
battle: {
timeOut: 0,
playerStyle: {
left: '0%',
backgroundPosition: '0px 96px',
},
left: '0',
imgLeft: '0px',
clip: 'rect(96px, 32px, 144px, 0px)',
// playerStyle: {
// left: '0%',
// backgroundPosition: '0px 96px',
// },
battleShow: false,
},
};

1
src/tool/index.ts

@ -2,6 +2,7 @@ export * from './caller'; @@ -2,6 +2,7 @@ export * from './caller';
export * from './formatter';
export * from './random';
export * from './mixins';
export * from './mobile';
export const getArrayEmptyIdx = (array) => {
for (let i = 0; i < array.length; i++) {

4
src/tool/mixins/popoverMenu.ts

@ -9,8 +9,8 @@ export default class PopoverMenu { @@ -9,8 +9,8 @@ export default class PopoverMenu {
open = (idx, e) => {
this.index.value = idx;
this.left.value = e.x + 20 + 'px';
this.top.value = e.y + -50 + 'px';
this.left.value = e.pageX + 20 + 'px';
this.top.value = e.pageY + -50 + 'px';
this.show.value = true;
};

47
src/tool/mobile.ts

@ -0,0 +1,47 @@ @@ -0,0 +1,47 @@
// 长按弹出上拉操作面板
class Mobile {
toucheX: number = 0;
toucheY: number = 0;
timeOutEvent: number = 0;
data?: any;
onLongTouch?: Function;
onClick?: Function;
e: any;
onTouchStart(e, data) {
this.toucheX = e.targetTouches[0].screenX;
this.toucheY = e.targetTouches[0].screenY;
this.data = data;
this.e = e;
// 开启定时器前先清除定时器,防止重复触发
this.timeOutEvent && clearTimeout(this.timeOutEvent);
// 显示上拉面板
this.timeOutEvent = setTimeout(() => {
this.onLongTouch && this.onLongTouch(e, data);
this.timeOutEvent = 0;
}, 1000);
e.preventDefault(); // 阻止系统默认事件
}
onTouchMove(e) {
const moveX = e.targetTouches[0].screenX;
const moveY = e.targetTouches[0].screenY;
// 解决vivo机型,手指没有move,touchmove事件仍然会调用而导致setTimeout被clear
if (this.toucheX !== moveX || this.toucheY !== moveY) {
// 手指滑动,清除定时器,中断长按逻辑
this.timeOutEvent && clearTimeout(this.timeOutEvent);
}
}
onTouchEnd() {
// 清除定时器,结束长按逻辑
this.timeOutEvent && clearTimeout(this.timeOutEvent);
// 若手指离开屏幕,时间小于我们设置的长按时间,则为点击事件
if (this.timeOutEvent !== 0) {
this.onClick && this.onClick(this.e, this.data);
}
}
}
export const userMobile = () => {
return new Mobile();
};

1
src/views/backpack/backpack.vue

@ -33,6 +33,7 @@ const show = computed(() => { @@ -33,6 +33,7 @@ const show = computed(() => {
const equipMenu = ref();
const openEquipMenu = (idx, event) => {
event.preventDefault();
commit('close_equip_tip');
equipMenu.value?.open(idx, event)
}

24
src/views/backpack/grid.vue

@ -2,7 +2,8 @@ @@ -2,7 +2,8 @@
<div class="body">
<span class="grid" v-for="(v, idx) in grid">
<div class="equip" v-if="v" @contextmenu.prevent.stop="emit('openEquipMenu', idx, $event)"
@dblclick="commit('close_equip_tip'); dispatch('useEquip', idx);"
@touchstart="mobile.onTouchStart($event, [v, idx])" @touchmove="mobile.onTouchMove"
@touchend="mobile.onTouchEnd" @dblclick="commit('close_equip_tip'); dispatch('useEquip', idx);"
@mouseover="commit('show_equip_tip', { equip: v, compare: true, e: $event })"
@mouseleave="commit('close_equip_tip')">
<EquipIcon :equip="v" />
@ -30,6 +31,7 @@ import { useI18n } from "vue3-i18n"; @@ -30,6 +31,7 @@ import { useI18n } from "vue3-i18n";
import EquipIcon from "@/components/equip-icon.vue";
import { lock_icon, backpack_num } from "@/config";
import AutoSell from "./auto-sell.vue";
import { userMobile } from "@/tool";
const { t } = useI18n();
const { state, commit, dispatch } = useStore();
@ -67,6 +69,14 @@ const sellAll = () => { @@ -67,6 +69,14 @@ const sellAll = () => {
})
}
const mobile = userMobile();
mobile.onLongTouch = (e, data) => {
e.touches[0].preventDefault = () => { };
emit('openEquipMenu', data[1], e.touches[0]);
}
mobile.onClick = (e, data) => {
commit('show_equip_tip', { equip: data[0], compare: true, e: e.touches[0] })
}
onMounted(() => { });
</script>
@ -95,6 +105,18 @@ onMounted(() => { }); @@ -95,6 +105,18 @@ onMounted(() => { });
width: 100%;
cursor: pointer;
position: relative;
-webkit-touch-callout: none;
/*系统默认菜单被禁用*/
-webkit-user-select: none;
/*webkit浏览器*/
-khtml-user-select: none;
/*早起浏览器*/
-moz-user-select: none;
/*火狐浏览器*/
-ms-user-select: none;
/*IE浏览器*/
user-select: none;
/*用户是否能够选中文本*/
}
.equip-lock {

30
src/views/dungeon/battle.vue

@ -1,6 +1,7 @@ @@ -1,6 +1,7 @@
<template>
<div v-if="dungeon" class="battle">
<div class="player" :style="battle.playerStyle">
<div class="player">
<img class="player-icon" :src="dungeon_icon.player">
</div>
<div class="monster" v-for="(v, k) in dungeon.monsters" :key="k"
:style="{ left: (95 / dungeon.monsters.length) * (k + 1) + '%' }">
@ -84,11 +85,11 @@ const playerMove = (monsterIdx?, playerIdx?) => { @@ -84,11 +85,11 @@ const playerMove = (monsterIdx?, playerIdx?) => {
let idx2 = playerIdx || 0;
const max = 20;
const lenght = 95 / props.dungeon?.monsters.length;
const left = monsterIdx * lenght + lenght / max * idx2;
battle.value.playerStyle = {
left: left + '%',
backgroundPosition: Math.floor(left % 4) * 32 + 'px 96px'
}
const left = monsterIdx * lenght + lenght / (max + 1) * idx2;
battle.value.left = + left + '%';
const position = Math.floor(left % 4) * 32;
battle.value.imgLeft = -1 * position + 'px';
battle.value.clip = 'rect(96px, ' + (position + 32) + 'px, 144px, ' + position + 'px)'
if (idx2 > max) {
exploreDungeon(monsterIdx);
} else {
@ -104,12 +105,6 @@ const battleWithMonster = (monster) => { @@ -104,12 +105,6 @@ const battleWithMonster = (monster) => {
return new Promise((resolve, reject) => {
const player = state.playerAttribute.attribute;
const result = callBattleResult(player, monster);
// let monsterDmg = Math.ceil(monster.atk * (1 - player.reducPercent) - player.bloc);
// monsterDmg < 1 && (monsterDmg = 1);
// const playerDeadTime = Math.ceil(player.curHp / monsterDmg);
// const monsterDeadTime = Math.ceil(monster.hp / player.dps);
// const takeDmg = monsterDeadTime * monsterDmg;
const battleTime = Math.round(player_battle_time * 100 / (100 + state.rebornAttribute.battleSpeed))
const getMsg = (i18nName) => {
@ -139,14 +134,23 @@ onMounted(() => { }); @@ -139,14 +134,23 @@ onMounted(() => { });
</script>
<style lang="scss" scoped>
.battle {
width: 100%;
.player {
overflow: hidden;
position: absolute;
z-index: 2;
top: 1.2rem;
height: 48px;
width: 32px;
background: url(@/assets/icons/player-s.png);
left: v-bind('state.battle.left');
.player-icon {
top: -96px;
left: v-bind('state.battle.imgLeft');
position: absolute;
clip: v-bind('state.battle.clip');
}
}
.monster {

15
src/views/dungeon/dungeon.vue

@ -1,7 +1,9 @@ @@ -1,7 +1,9 @@
<template>
<div :class="['dungeon', 'df' + dungeon.difficulty]" @contextmenu.prevent.stop="emit('battle')"
@dblclick="emit('battle')" @mouseover="showTips" @mouseleave="closeTips">
<div class="icon"></div>
<div class="icon">
<img class="icon-img" :src="dungeon_icon[dungeon.difficulty]">
</div>
<div class="lv">lv{{ dungeon.lv }}</div>
<!-- -->
<div class="tip" v-if="tipsShow" :style='tipsStyle'>
@ -16,6 +18,7 @@ @@ -16,6 +18,7 @@
import { useStore } from "vuex";
import { computed, onMounted, ref, watch } from "vue";
import { useI18n } from "vue3-i18n";
import { dungeon_icon } from "@/config";
const { t } = useI18n();
const { state, commit, dispatch } = useStore();
@ -43,7 +46,7 @@ watch(() => props.dungeon, () => { @@ -43,7 +46,7 @@ watch(() => props.dungeon, () => {
const ramdonPosition = () => {
if (state.mobile) {
left.value = Math.random() * 80 + 5 + 'vw';
top.value = Math.random() * 80 + 10 + 'vh';
top.value = Math.random() * 70 + 5 + 'vh';
} else {
left.value = Math.random() * 64 + 2.5 + 'rem';
top.value = Math.random() * 50 + 2.5 + 'rem';
@ -88,11 +91,15 @@ onMounted(() => { @@ -88,11 +91,15 @@ onMounted(() => {
margin-top: 0.2rem;
margin-left: 0.2rem;
border-radius: 50%;
background-image: url(@/assets/icons/d1.png);
background-color: rgba(100, 255, 36, 0.6);
background-repeat: no-repeat;
background-position: center center;
background-size: 30px 29px;
.icon-img {
width: 100%;
height: 100%;
}
}
.lv {
@ -122,7 +129,6 @@ onMounted(() => { @@ -122,7 +129,6 @@ onMounted(() => {
box-shadow: 0 0 4px 4px rgba(245, 241, 0, 0.6);
.icon {
background-image: url(@/assets/icons/d2.png);
background-color: rgba(245, 241, 0, 0.6);
}
@ -132,7 +138,6 @@ onMounted(() => { @@ -132,7 +138,6 @@ onMounted(() => {
box-shadow: 0 0 4px 4px rgba(245, 54, 54, 0.5);
.icon {
background-image: url(@/assets/icons/d3.png);
background-color: rgba(245, 54, 54, 0.6);
}

9
src/views/dungeon/dungeonMap.vue

@ -5,6 +5,7 @@ @@ -5,6 +5,7 @@
<teleport to="#main" v-if="showMap">
<div id="map" class="map">
<img class="map-img" :src="dungeon_icon.map">
<span v-if="!state.battle.battleShow">
<DungeonView v-for="item in dungeons" :dungeon="item" :key="item.lv" @battle="startBattle(item)" />
<img :src="refresh_icon" class="refresh" @click="refreshDungeons"></img>
@ -22,7 +23,7 @@ import { useStore } from "vuex"; @@ -22,7 +23,7 @@ import { useStore } from "vuex";
import { onBeforeUnmount, onMounted, ref } from "vue";
import { useI18n } from "vue3-i18n";
import { Tooltip, Dialog } from "@/components"
import { menu_icons, Dungeon, refresh_icon, close_icon } from "@/config";
import { menu_icons, Dungeon, refresh_icon, close_icon, dungeon_icon } from "@/config";
import { randomDungeonDifficulty } from "@/tool";
import DungeonView from "./dungeon.vue"
import BattleView from "./battle.vue"
@ -98,7 +99,11 @@ onBeforeUnmount(() => { @@ -98,7 +99,11 @@ onBeforeUnmount(() => {
background-repeat: no-repeat;
background-size: 100% 100%;
position: relative;
background-image: url(@/assets/icons/map.jpg);
.map-img {
width: 100%;
height: 100%;
}
* {
color: white;

3
src/views/index.vue

@ -1,5 +1,6 @@ @@ -1,5 +1,6 @@
<template>
<div id="main" class="main" @click="playBackgound" @contextmenu.prevent="playBackgound">
<div id="main" class="main" @click="playBackgound; commit('close_equip_tip')"
@contextmenu.prevent="playBackgound()">
<div class="infomation">
<Message />
</div>

33
src/views/shop/shop.vue

@ -9,7 +9,8 @@ @@ -9,7 +9,8 @@
</div>
<div class="items">
<div class="item" v-for="(v, k) in shopItems" :key="k"
@contextmenu.prevent.stop="commit('close_equip_tip'); v && open(k, $event)"
@contextmenu.prevent.stop="openPropMenu(v, k, $event)" @touchstart="mobile.onTouchStart($event, [v, k])"
@touchmove="mobile.onTouchMove" @touchend="mobile.onTouchEnd"
@mouseover="commit('show_equip_tip', { equip: v, compare: true, e: $event })"
@mouseleave="commit('close_equip_tip')">
<EquipIcon :equip="v" @dblclick="commit('close_equip_tip'); buyEquip(k);" />
@ -48,7 +49,7 @@ import { useI18n } from "vue3-i18n"; @@ -48,7 +49,7 @@ import { useI18n } from "vue3-i18n";
import { Tooltip, EquipIcon, Dialog, PopoverMenu, Confirm } from "@/components"
import { randomEquipQuality } from '@/tool';
import { menu_icons, qualitys } from '@/config';
import { usePopoverMenu, conisOfBuy, getArrayEmptyIdx } from "@/tool";
import { usePopoverMenu, conisOfBuy, getArrayEmptyIdx, userMobile } from "@/tool";
const { t } = useI18n();
const { state, commit, dispatch } = useStore();
@ -157,6 +158,22 @@ const showMenu = () => { @@ -157,6 +158,22 @@ const showMenu = () => {
state.curMenu = showShop.value ? null : 'shop';
}
const openPropMenu = (equip, idx, e) => {
e.preventDefault();
commit('close_equip_tip');
equip && open(idx, e);
}
const mobile = userMobile();
mobile.onLongTouch = (e, data) => {
commit('close_equip_tip');
data[0] && open(data[1], e.touches[0]);
}
mobile.onClick = (e, data) => {
commit('show_equip_tip', { equip: data[0], compare: true, e: e.touches[0] })
}
const keydown = (e) => {
if (e.keyCode == 83 && !e.ctrlKey) {
showMenu();
@ -203,6 +220,18 @@ onBeforeUnmount(() => { @@ -203,6 +220,18 @@ onBeforeUnmount(() => {
.item {
float: left;
margin: 1rem;
-webkit-touch-callout: none;
/*系统默认菜单被禁用*/
-webkit-user-select: none;
/*webkit浏览器*/
-khtml-user-select: none;
/*早起浏览器*/
-moz-user-select: none;
/*火狐浏览器*/
-ms-user-select: none;
/*IE浏览器*/
user-select: none;
/*用户是否能够选中文本*/
}
.icons {

4
src/views/version/update-log.vue

@ -36,6 +36,10 @@ const updateLogs: any = [{ @@ -36,6 +36,10 @@ const updateLogs: any = [{
'适配移动端',
'更新日志菜单快捷键调整为(U)',
'静态资源网络分流'
],
bug: [
'修复静态资源分流后部分图片路径不正确问题',
'修复背景音乐路径不正确问题'
]
}, {
date: '2025-04-23', version: '测试版',

Loading…
Cancel
Save