支持水印排列
御魂2,4,6属性简称 修正截图大小 式神,御魂信息更新
BIN
public/assets/Shikigami/l/563.png
Normal file
After Width: | Height: | Size: 31 KiB |
BIN
public/assets/Shikigami/l/564.png
Normal file
After Width: | Height: | Size: 26 KiB |
BIN
public/assets/Shikigami/l/567.png
Normal file
After Width: | Height: | Size: 22 KiB |
BIN
public/assets/Shikigami/l/576.png
Normal file
After Width: | Height: | Size: 20 KiB |
BIN
public/assets/Shikigami/sp/566.png
Normal file
After Width: | Height: | Size: 27 KiB |
BIN
public/assets/Shikigami/sp/568.png
Normal file
After Width: | Height: | Size: 30 KiB |
BIN
public/assets/Shikigami/sp/572.png
Normal file
After Width: | Height: | Size: 31 KiB |
BIN
public/assets/Shikigami/sp/574.png
Normal file
After Width: | Height: | Size: 29 KiB |
BIN
public/assets/Shikigami/sp/578.png
Normal file
After Width: | Height: | Size: 27 KiB |
BIN
public/assets/Shikigami/sp/579.png
Normal file
After Width: | Height: | Size: 32 KiB |
BIN
public/assets/Shikigami/sp/580.png
Normal file
After Width: | Height: | Size: 29 KiB |
BIN
public/assets/Shikigami/ssr/569.png
Normal file
After Width: | Height: | Size: 35 KiB |
BIN
public/assets/Shikigami/ssr/570.png
Normal file
After Width: | Height: | Size: 24 KiB |
BIN
public/assets/Shikigami/ssr/573.png
Normal file
After Width: | Height: | Size: 30 KiB |
BIN
public/assets/Shikigami/ssr/575.png
Normal file
After Width: | Height: | Size: 29 KiB |
BIN
public/assets/Shikigami/ssr/577.png
Normal file
After Width: | Height: | Size: 23 KiB |
BIN
public/assets/Shikigami/ssr/581.png
Normal file
After Width: | Height: | Size: 28 KiB |
BIN
public/assets/Yuhun/夜荒魂.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
public/assets/Yuhun/奉海图.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
public/assets/Yuhun/散件.png
Normal file
After Width: | Height: | Size: 28 KiB |
BIN
public/assets/Yuhun/无刀取.png
Normal file
After Width: | Height: | Size: 16 KiB |
21
src/App.vue
@ -1,16 +1,25 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import Yys from './components/Yys.vue'
|
import Yys from './components/Yys.vue'
|
||||||
import Watermark from './components/Watermark.vue' // 引入 Watermark 组件
|
|
||||||
import Toolbar from './components/Toolbar.vue'
|
import Toolbar from './components/Toolbar.vue'
|
||||||
|
import {ref} from "vue";
|
||||||
|
|
||||||
|
const yysRef = ref(null);
|
||||||
|
|
||||||
|
const onHandleInport = (file) => {
|
||||||
|
yysRef.value.importGroups(file);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onHandleExport = () => {
|
||||||
|
yysRef.value.exportGroups();
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<main id="main-container">
|
<main id="main-container">
|
||||||
<!-- 添加工具栏 -->
|
<!-- 添加工具栏 -->
|
||||||
<Toolbar title="我的应用" username="示例用户" data-html2canvas-ignore="true"/>
|
<Toolbar title="yys-editor" username="示例用户" data-html2canvas-ignore="true" @handleExport="onHandleExport" @handleImport="onHandleInport"/>
|
||||||
<!-- 添加 Watermark 组件 -->
|
<!-- 添加 Watermark 组件 -->
|
||||||
<Yys/>
|
<Yys ref="yysRef"/>
|
||||||
|
|
||||||
</main>
|
</main>
|
||||||
</template>
|
</template>
|
||||||
@ -20,9 +29,11 @@ import Toolbar from './components/Toolbar.vue'
|
|||||||
#main-container {
|
#main-container {
|
||||||
margin-top: 48px; /* 与工具栏高度相同 */
|
margin-top: 48px; /* 与工具栏高度相同 */
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 100%;
|
|
||||||
min-height: 100vh; /* 允许容器扩展 */
|
min-height: 100vh; /* 允许容器扩展 */
|
||||||
//position: relative;
|
display: inline-block;
|
||||||
|
max-width: 100%;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 如果 Yys 组件需要特定的高度或布局,可以根据需要调整 */
|
/* 如果 Yys 组件需要特定的高度或布局,可以根据需要调整 */
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
<div v-if="shikigami.skillRequiredMode === 'custom'" style="display: flex; flex-direction: row; width: 100%;">
|
<div v-if="shikigami.skillRequiredMode === 'custom'" style="display: flex; flex-direction: row; width: 100%;">
|
||||||
<el-select v-for="(value, key, index) in shikigami.skillRequired" :placeholder="value"
|
<el-select v-for="(value, key, index) in shikigami.skillRequired" :placeholder="value"
|
||||||
style="margin-bottom: 10px;" @change="updateSkillRequired(key, $event)">
|
style="margin-bottom: 10px;" @change="updateSkillRequired(key, $event)">
|
||||||
<el-option label="*" value="*"/>
|
<el-option label="*" value="X"/>
|
||||||
<el-option label="1" value="1"/>
|
<el-option label="1" value="1"/>
|
||||||
<el-option label="2" value="2"/>
|
<el-option label="2" value="2"/>
|
||||||
<el-option label="3" value="3"/>
|
<el-option label="3" value="3"/>
|
||||||
@ -67,20 +67,9 @@
|
|||||||
|
|
||||||
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="效果指标">
|
<el-form-item :label="t('yuhunTarget')">
|
||||||
<el-select placeholder="1" v-model="shikigami.yuhun.target">
|
<el-select v-model="yuhunTarget">
|
||||||
<el-option label="伤害输出" value="1"/>
|
<el-option v-for="option in yuhunTargetOptions" :key="option.value" :label="t(option.label)" :value="option.value"/>
|
||||||
<el-option label="效果命中" value="2"/>
|
|
||||||
<el-option label="效果抵抗" value="3"/>
|
|
||||||
<el-option label="生命" value="4"/>
|
|
||||||
<el-option label="攻击" value="5"/>
|
|
||||||
<el-option label="防御" value="6"/>
|
|
||||||
<el-option label="速度" value="7"/>
|
|
||||||
<el-option label="暴击" value="8"/>
|
|
||||||
<el-option label="暴击伤害" value="9"/>
|
|
||||||
<el-option label="治疗量" value="10"/>
|
|
||||||
<el-option label="命抗双修" value="11"/>
|
|
||||||
<el-option label="防御输出" value="12"/>
|
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="2号位主属性">
|
<el-form-item label="2号位主属性">
|
||||||
@ -122,7 +111,7 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<el-form-item label="Activity form">
|
<el-form-item label="额外描述">
|
||||||
<el-input v-model="shikigami.desc" type="textarea"/>
|
<el-input v-model="shikigami.desc" type="textarea"/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
@ -138,8 +127,12 @@ import propertyData from "../data/property.json";
|
|||||||
import {ref, watch, computed} from 'vue'
|
import {ref, watch, computed} from 'vue'
|
||||||
import ShikigamiSelect from "@/components/ShikigamiSelect.vue";
|
import ShikigamiSelect from "@/components/ShikigamiSelect.vue";
|
||||||
import YuhunSelect from "@/components/YuhunSelect.vue";
|
import YuhunSelect from "@/components/YuhunSelect.vue";
|
||||||
|
import {useI18n} from 'vue-i18n'
|
||||||
// import YuhunSelect from "./YuhunSelect.vue";
|
// import YuhunSelect from "./YuhunSelect.vue";
|
||||||
|
|
||||||
|
// 获取当前的 i18n 实例
|
||||||
|
const {t} = useI18n()
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
currentShikigami: {
|
currentShikigami: {
|
||||||
type: Object,
|
type: Object,
|
||||||
@ -152,8 +145,9 @@ const props = defineProps({
|
|||||||
|
|
||||||
const emit = defineEmits(['closeProperty', 'updateProperty'])
|
const emit = defineEmits(['closeProperty', 'updateProperty'])
|
||||||
|
|
||||||
let showYuhunSelect = ref(false)
|
const showYuhunSelect = ref(false)
|
||||||
let shikigami = ref({
|
const yuhunTarget = ref('1')
|
||||||
|
const shikigami = ref({
|
||||||
edit: false,
|
edit: false,
|
||||||
yuhun: {
|
yuhun: {
|
||||||
yuhunSetEffect: [],
|
yuhunSetEffect: [],
|
||||||
@ -165,11 +159,27 @@ let shikigami = ref({
|
|||||||
levelRequired: "40",
|
levelRequired: "40",
|
||||||
speed: "",
|
speed: "",
|
||||||
skillRequiredMode: "all",
|
skillRequiredMode: "all",
|
||||||
skillRequired: ["技能一", "技能二", "技能三"]
|
skillRequired: ["5", "5", "5"]
|
||||||
})
|
})
|
||||||
let yuhunIndex = ref(-1)
|
const yuhunIndex = ref(-1)
|
||||||
let current = ref({})
|
const current = ref({})
|
||||||
let show = ref(props.showProperty)
|
const show = ref(props.showProperty)
|
||||||
|
const yuhunTargetOptions = [
|
||||||
|
{ label: 'yuhun_target.fullName.0', value: '0' },
|
||||||
|
{ label: 'yuhun_target.fullName.1', value: '1' },
|
||||||
|
{ label: 'yuhun_target.fullName.2', value: '2' },
|
||||||
|
{ label: 'yuhun_target.fullName.3', value: '3' },
|
||||||
|
{ label: 'yuhun_target.fullName.4', value: '4' },
|
||||||
|
{ label: 'yuhun_target.fullName.5', value: '5' },
|
||||||
|
{ label: 'yuhun_target.fullName.6', value: '6' },
|
||||||
|
{ label: 'yuhun_target.fullName.7', value: '7' },
|
||||||
|
{ label: 'yuhun_target.fullName.8', value: '8' },
|
||||||
|
{ label: 'yuhun_target.fullName.9', value: '9' },
|
||||||
|
{ label: 'yuhun_target.fullName.10', value: '10' },
|
||||||
|
{ label: 'yuhun_target.fullName.11', value: '11' },
|
||||||
|
{ label: 'yuhun_target.fullName.12', value: '12' },
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
watch(() => props.currentShikigami, (newVal) => {
|
watch(() => props.currentShikigami, (newVal) => {
|
||||||
if (newVal.properties != undefined && newVal.properties.edit == true) {
|
if (newVal.properties != undefined && newVal.properties.edit == true) {
|
||||||
@ -184,10 +194,20 @@ watch(() => props.showProperty, (newVal) => {
|
|||||||
show.value = newVal;
|
show.value = newVal;
|
||||||
})
|
})
|
||||||
|
|
||||||
watch(() => shikigami.value.yuhun.target, (newVal) => {
|
watch(() => shikigami.value.skillRequiredMode, (newVal) => {
|
||||||
|
if(newVal == "all") {
|
||||||
|
shikigami.value.skillRequired = ["5", "5", "5"]
|
||||||
|
}
|
||||||
|
else if (newVal == "111") {
|
||||||
|
shikigami.value.skillRequired = ["1", "1", "1"]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
watch(() => yuhunTarget.value, (newVal) => {
|
||||||
switch (newVal) {
|
switch (newVal) {
|
||||||
//<el-option label="伤害输出" value="1"/>
|
//<el-option label="伤害输出" value="1"/>
|
||||||
case "1": {
|
case "1": {
|
||||||
|
shikigami.value.yuhun.target = 1
|
||||||
shikigami.value.yuhun.property2 = ["Attack"];
|
shikigami.value.yuhun.property2 = ["Attack"];
|
||||||
shikigami.value.yuhun.property4 = ["Attack"];
|
shikigami.value.yuhun.property4 = ["Attack"];
|
||||||
shikigami.value.yuhun.property6 = ["Crit", "CritDamage"];
|
shikigami.value.yuhun.property6 = ["Crit", "CritDamage"];
|
||||||
@ -195,6 +215,7 @@ watch(() => shikigami.value.yuhun.target, (newVal) => {
|
|||||||
}
|
}
|
||||||
//<el-option label="效果命中" value="2"/>
|
//<el-option label="效果命中" value="2"/>
|
||||||
case "2": {
|
case "2": {
|
||||||
|
shikigami.value.yuhun.target = 2
|
||||||
shikigami.value.yuhun.property2 = ["Speed"];
|
shikigami.value.yuhun.property2 = ["Speed"];
|
||||||
shikigami.value.yuhun.property4 = ["ControlHit"];
|
shikigami.value.yuhun.property4 = ["ControlHit"];
|
||||||
shikigami.value.yuhun.property6 = ["Attack", "Defense", "Health", "Crit", "CritDamage"];
|
shikigami.value.yuhun.property6 = ["Attack", "Defense", "Health", "Crit", "CritDamage"];
|
||||||
@ -202,6 +223,7 @@ watch(() => shikigami.value.yuhun.target, (newVal) => {
|
|||||||
}
|
}
|
||||||
//<el-option label="效果抵抗" value="3"/>
|
//<el-option label="效果抵抗" value="3"/>
|
||||||
case "3": {
|
case "3": {
|
||||||
|
shikigami.value.yuhun.target = 3
|
||||||
shikigami.value.yuhun.property2 = ["Speed"];
|
shikigami.value.yuhun.property2 = ["Speed"];
|
||||||
shikigami.value.yuhun.property4 = ["ControlMiss"];
|
shikigami.value.yuhun.property4 = ["ControlMiss"];
|
||||||
shikigami.value.yuhun.property6 = ["Attack", "Defense", "Health", "Crit", "CritDamage"];
|
shikigami.value.yuhun.property6 = ["Attack", "Defense", "Health", "Crit", "CritDamage"];
|
||||||
@ -209,6 +231,7 @@ watch(() => shikigami.value.yuhun.target, (newVal) => {
|
|||||||
}
|
}
|
||||||
//<el-option label="生命" value="4"/>
|
//<el-option label="生命" value="4"/>
|
||||||
case "4": {
|
case "4": {
|
||||||
|
shikigami.value.yuhun.target = 4
|
||||||
shikigami.value.yuhun.property2 = ["Health"];
|
shikigami.value.yuhun.property2 = ["Health"];
|
||||||
shikigami.value.yuhun.property4 = ["Health"];
|
shikigami.value.yuhun.property4 = ["Health"];
|
||||||
shikigami.value.yuhun.property6 = ["Health"];
|
shikigami.value.yuhun.property6 = ["Health"];
|
||||||
@ -216,6 +239,7 @@ watch(() => shikigami.value.yuhun.target, (newVal) => {
|
|||||||
}
|
}
|
||||||
//<el-option label="攻击" value="5"/>
|
//<el-option label="攻击" value="5"/>
|
||||||
case "5": {
|
case "5": {
|
||||||
|
shikigami.value.yuhun.target = 5
|
||||||
shikigami.value.yuhun.property2 = ["Attack"];
|
shikigami.value.yuhun.property2 = ["Attack"];
|
||||||
shikigami.value.yuhun.property4 = ["Attack"];
|
shikigami.value.yuhun.property4 = ["Attack"];
|
||||||
shikigami.value.yuhun.property6 = ["Attack"];
|
shikigami.value.yuhun.property6 = ["Attack"];
|
||||||
@ -223,6 +247,7 @@ watch(() => shikigami.value.yuhun.target, (newVal) => {
|
|||||||
}
|
}
|
||||||
//<el-option label="防御" value="6"/>
|
//<el-option label="防御" value="6"/>
|
||||||
case "6": {
|
case "6": {
|
||||||
|
shikigami.value.yuhun.target = 6
|
||||||
shikigami.value.yuhun.property2 = ["Defense"];
|
shikigami.value.yuhun.property2 = ["Defense"];
|
||||||
shikigami.value.yuhun.property4 = ["Defense"];
|
shikigami.value.yuhun.property4 = ["Defense"];
|
||||||
shikigami.value.yuhun.property6 = ["Defense"];
|
shikigami.value.yuhun.property6 = ["Defense"];
|
||||||
@ -230,6 +255,7 @@ watch(() => shikigami.value.yuhun.target, (newVal) => {
|
|||||||
}
|
}
|
||||||
//<el-option label="速度" value="7"/>
|
//<el-option label="速度" value="7"/>
|
||||||
case "7": {
|
case "7": {
|
||||||
|
shikigami.value.yuhun.target = 7
|
||||||
shikigami.value.yuhun.property2 = ["Speed"];
|
shikigami.value.yuhun.property2 = ["Speed"];
|
||||||
shikigami.value.yuhun.property4 = ["Attack", "Defense", "Health", "ControlHit", "ControlMiss"];
|
shikigami.value.yuhun.property4 = ["Attack", "Defense", "Health", "ControlHit", "ControlMiss"];
|
||||||
shikigami.value.yuhun.property6 = ["Attack", "Defense", "Health", "Crit", "CritDamage"];
|
shikigami.value.yuhun.property6 = ["Attack", "Defense", "Health", "Crit", "CritDamage"];
|
||||||
@ -237,6 +263,7 @@ watch(() => shikigami.value.yuhun.target, (newVal) => {
|
|||||||
}
|
}
|
||||||
//<el-option label="暴击" value="8"/>
|
//<el-option label="暴击" value="8"/>
|
||||||
case "8": {
|
case "8": {
|
||||||
|
shikigami.value.yuhun.target = 8
|
||||||
shikigami.value.yuhun.property2 = ["Attack", "Defense", "Health", "Speed"];
|
shikigami.value.yuhun.property2 = ["Attack", "Defense", "Health", "Speed"];
|
||||||
shikigami.value.yuhun.property4 = ["Attack", "Defense", "Health", "ControlHit", "ControlMiss"];
|
shikigami.value.yuhun.property4 = ["Attack", "Defense", "Health", "ControlHit", "ControlMiss"];
|
||||||
shikigami.value.yuhun.property6 = ["Crit"];
|
shikigami.value.yuhun.property6 = ["Crit"];
|
||||||
@ -244,6 +271,7 @@ watch(() => shikigami.value.yuhun.target, (newVal) => {
|
|||||||
}
|
}
|
||||||
//<el-option label="暴击伤害" value="9"/>
|
//<el-option label="暴击伤害" value="9"/>
|
||||||
case "9": {
|
case "9": {
|
||||||
|
shikigami.value.yuhun.target = 9
|
||||||
shikigami.value.yuhun.property2 = ["Attack", "Defense", "Health", "Speed"];
|
shikigami.value.yuhun.property2 = ["Attack", "Defense", "Health", "Speed"];
|
||||||
shikigami.value.yuhun.property4 = ["Attack", "Defense", "Health", "ControlHit", "ControlMiss"];
|
shikigami.value.yuhun.property4 = ["Attack", "Defense", "Health", "ControlHit", "ControlMiss"];
|
||||||
shikigami.value.yuhun.property6 = ["CritDamage"];
|
shikigami.value.yuhun.property6 = ["CritDamage"];
|
||||||
@ -251,6 +279,7 @@ watch(() => shikigami.value.yuhun.target, (newVal) => {
|
|||||||
}
|
}
|
||||||
//<el-option label="治疗量" value="10"/>
|
//<el-option label="治疗量" value="10"/>
|
||||||
case "10": {
|
case "10": {
|
||||||
|
shikigami.value.yuhun.target = 10
|
||||||
shikigami.value.yuhun.property2 = ["Speed"];
|
shikigami.value.yuhun.property2 = ["Speed"];
|
||||||
shikigami.value.yuhun.property4 = ["Health"];
|
shikigami.value.yuhun.property4 = ["Health"];
|
||||||
shikigami.value.yuhun.property6 = ["Crit", "CritDamage"];
|
shikigami.value.yuhun.property6 = ["Crit", "CritDamage"];
|
||||||
@ -258,6 +287,7 @@ watch(() => shikigami.value.yuhun.target, (newVal) => {
|
|||||||
}
|
}
|
||||||
//<el-option label="命抗双修" value="11"/>
|
//<el-option label="命抗双修" value="11"/>
|
||||||
case "11": {
|
case "11": {
|
||||||
|
shikigami.value.yuhun.target = 11
|
||||||
shikigami.value.yuhun.property2 = ["Speed"];
|
shikigami.value.yuhun.property2 = ["Speed"];
|
||||||
shikigami.value.yuhun.property4 = ["ControlHit", "ControlMiss"];
|
shikigami.value.yuhun.property4 = ["ControlHit", "ControlMiss"];
|
||||||
shikigami.value.yuhun.property6 = ["Attack", "Defense", "Health", "Crit", "CritDamage"];
|
shikigami.value.yuhun.property6 = ["Attack", "Defense", "Health", "Crit", "CritDamage"];
|
||||||
@ -265,6 +295,7 @@ watch(() => shikigami.value.yuhun.target, (newVal) => {
|
|||||||
}
|
}
|
||||||
//<el-option label="防御输出" value="12"/>
|
//<el-option label="防御输出" value="12"/>
|
||||||
case "12": {
|
case "12": {
|
||||||
|
shikigami.value.yuhun.target = 12
|
||||||
shikigami.value.yuhun.property2 = ["Defense"];
|
shikigami.value.yuhun.property2 = ["Defense"];
|
||||||
shikigami.value.yuhun.property4 = ["Defense"];
|
shikigami.value.yuhun.property4 = ["Defense"];
|
||||||
shikigami.value.yuhun.property6 = ["Crit", "CritDamage"];
|
shikigami.value.yuhun.property6 = ["Crit", "CritDamage"];
|
||||||
@ -313,11 +344,12 @@ const confirm = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const resetData = () => {
|
const resetData = () => {
|
||||||
|
yuhunTarget.value = '1'
|
||||||
shikigami.value = {
|
shikigami.value = {
|
||||||
edit: false,
|
edit: false,
|
||||||
yuhun: {
|
yuhun: {
|
||||||
yuhunSetEffect: [],
|
yuhunSetEffect: [],
|
||||||
target: "伤害输出",
|
target: "0",
|
||||||
property2: ["Attack"],
|
property2: ["Attack"],
|
||||||
property4: ["Attack"],
|
property4: ["Attack"],
|
||||||
property6: ["Crit", "CritDamage"],
|
property6: ["Crit", "CritDamage"],
|
||||||
@ -325,7 +357,11 @@ const resetData = () => {
|
|||||||
levelRequired: "40",
|
levelRequired: "40",
|
||||||
speed: "",
|
speed: "",
|
||||||
skillRequiredMode: "all",
|
skillRequiredMode: "all",
|
||||||
skillRequired: ["技能一", "技能二", "技能三"]
|
skillRequired: ["5", "5", "5"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const updateSkillRequired = (index, value) => {
|
||||||
|
shikigami.value.skillRequired[index] = value;
|
||||||
|
}
|
||||||
</script>
|
</script>
|
@ -1,19 +1,19 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="toolbar">
|
<div class="toolbar">
|
||||||
<div data-html2canvas-ignore="true">
|
<div>
|
||||||
<el-button icon="Upload" type="primary" @click="prepareCapture">{{ t('import') }}</el-button>
|
<el-button icon="Upload" type="primary" @click="handleImport">{{ t('import') }}</el-button>
|
||||||
<el-button icon="Download" type="primary" @click="prepareCapture">{{ t('export') }}</el-button>
|
<el-button icon="Download" type="primary" @click="handleExport">{{ t('export') }}</el-button>
|
||||||
<el-button icon="Share" type="primary" @click="prepareCapture">{{ t('prepareCapture') }}</el-button>
|
<el-button icon="Share" type="primary" @click="prepareCapture">{{ t('prepareCapture') }}</el-button>
|
||||||
<el-button icon="Setting" type="primary" @click="prepareCapture">{{ t('setWatermark') }}</el-button>
|
<el-button icon="Setting" type="primary" @click="state.showWatermarkDialog = true">{{
|
||||||
|
t('setWatermark')
|
||||||
|
}}
|
||||||
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 预览弹窗 -->
|
<!-- 预览弹窗 -->
|
||||||
<el-dialog id="preview-container" v-model="state.previewVisible" width="80%" :before-close="handleClose">
|
<el-dialog id="preview-container" v-model="state.previewVisible" width="80%" height="80%" :before-close="handleClose">
|
||||||
<div style="max-height: 500px; overflow-y: auto;">
|
<div style="max-height: 500px; overflow-y: auto;">
|
||||||
<Watermark text="示例水印" font="30px Arial" color="rgba(184, 184, 184, 0.3)" angle=-20>
|
<img v-if="state.previewImage" :src="state.previewImage" alt="Preview" style="width: 100%; display: block;"/>
|
||||||
|
|
||||||
<img v-if="state.previewImage" :src="state.previewImage" alt="Preview" style="width: 100%; display: block;"/>
|
|
||||||
</Watermark>
|
|
||||||
</div>
|
</div>
|
||||||
<!-- <img v-if="state.previewImage" :src="state.previewImage" alt="Preview" style="width: 100%; height: auto;" />-->
|
<!-- <img v-if="state.previewImage" :src="state.previewImage" alt="Preview" style="width: 100%; height: auto;" />-->
|
||||||
<span slot="footer" class="dialog-footer">
|
<span slot="footer" class="dialog-footer">
|
||||||
@ -21,77 +21,212 @@
|
|||||||
<el-button type="primary" @click="downloadImage">下 载</el-button>
|
<el-button type="primary" @click="downloadImage">下 载</el-button>
|
||||||
</span>
|
</span>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
|
<!-- 水印设置弹窗 -->
|
||||||
|
<el-dialog v-model="state.showWatermarkDialog" title="设置水印" width="30%">
|
||||||
|
<el-form>
|
||||||
|
<el-form-item label="水印文字">
|
||||||
|
<el-input v-model="watermark.text"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="字体大小">
|
||||||
|
<el-input-number v-model="watermark.fontSize" :min="10" :max="100"></el-input-number>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="颜色">
|
||||||
|
<el-color-picker v-model="watermark.color"></el-color-picker>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="水印行数">
|
||||||
|
<el-input-number v-model="watermark.rows" :min="1" :max="10"></el-input-number>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="水印列数">
|
||||||
|
<el-input-number v-model="watermark.cols" :min="1" :max="10"></el-input-number>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="角度">
|
||||||
|
<el-input-number v-model="watermark.angle" :min="-90" :max="90"></el-input-number>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<span class="dialog-footer">
|
||||||
|
<el-button @click="state.showWatermarkDialog = false">取消</el-button>
|
||||||
|
<el-button type="primary" @click="applyWatermarkSettings">确认</el-button>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import {inject, nextTick} from 'vue';
|
import {ref, reactive} from 'vue';
|
||||||
import html2canvas from "html2canvas";
|
import html2canvas from "html2canvas";
|
||||||
import {useI18n} from 'vue-i18n'
|
import {useI18n} from 'vue-i18n';
|
||||||
import Watermark from './Watermark.vue' // 引入 Watermark 组件
|
|
||||||
|
|
||||||
// 获取当前的 i18n 实例
|
// 获取当前的 i18n 实例
|
||||||
const {t} = useI18n()
|
const {t} = useI18n();
|
||||||
|
const emit = defineEmits(['handleExport', 'handleImport'])
|
||||||
// 注入水印控制方法
|
|
||||||
const watermarkControl = inject('watermarkControl');
|
|
||||||
|
|
||||||
defineProps({
|
|
||||||
title: {
|
|
||||||
type: String,
|
|
||||||
default: '默认标题'
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
import {ref, reactive, toRefs} from 'vue';
|
|
||||||
|
|
||||||
// 定义响应式数据
|
// 定义响应式数据
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
previewImage: null, // 用于存储预览图像的数据URL
|
previewImage: null, // 用于存储预览图像的数据URL
|
||||||
previewVisible: false, // 控制预览弹窗的显示状态
|
previewVisible: false, // 控制预览弹窗的显示状态
|
||||||
|
showWatermarkDialog: false, // 控制水印设置弹窗的显示状态
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const handleExport = () => {
|
||||||
|
emit('handleExport');
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleImport = () => {
|
||||||
|
const input = document.createElement('input');
|
||||||
|
input.type = 'file';
|
||||||
|
input.accept = '.json';
|
||||||
|
input.onchange = (e) => {
|
||||||
|
const file = e.target.files[0];
|
||||||
|
if (file) emit('handleImport', file);
|
||||||
|
};
|
||||||
|
input.click();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const watermark = reactive({
|
||||||
|
text: '示例水印',
|
||||||
|
fontSize: 30,
|
||||||
|
color: 'rgba(184, 184, 184, 0.3)',
|
||||||
|
angle: -20,
|
||||||
|
rows: 1, // 新增行数
|
||||||
|
cols: 1 // 新增列数
|
||||||
|
});
|
||||||
|
|
||||||
|
const applyWatermarkSettings = () => {
|
||||||
|
state.showWatermarkDialog = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 计算视觉总高度
|
||||||
|
function calculateVisualHeight(selector) {
|
||||||
|
// 1. 获取所有目标元素
|
||||||
|
const elements = Array.from(document.querySelectorAll(selector));
|
||||||
|
|
||||||
|
// 2. 获取元素位置信息并排序
|
||||||
|
const rects = elements.map(el => {
|
||||||
|
const rect = el.getBoundingClientRect();
|
||||||
|
return {
|
||||||
|
el,
|
||||||
|
top: rect.top,
|
||||||
|
bottom: rect.bottom,
|
||||||
|
height: rect.height
|
||||||
|
};
|
||||||
|
}).sort((a, b) => a.top - b.top); // 按垂直位置排序
|
||||||
|
|
||||||
|
// 3. 动态分组同行元素
|
||||||
|
const rows = [];
|
||||||
|
rects.forEach(rect => {
|
||||||
|
let placed = false;
|
||||||
|
|
||||||
|
// 尝试将元素加入已有行
|
||||||
|
for (const row of rows) {
|
||||||
|
if (
|
||||||
|
rect.top < row.bottom && // 元素顶部在行底部上方
|
||||||
|
rect.bottom > row.top // 元素底部在行顶部下方
|
||||||
|
) {
|
||||||
|
row.elements.push(rect);
|
||||||
|
row.bottom = Math.max(row.bottom, rect.bottom); // 扩展行底部
|
||||||
|
row.maxHeight = Math.max(row.maxHeight, rect.height);
|
||||||
|
placed = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 未加入则创建新行
|
||||||
|
if (!placed) {
|
||||||
|
rows.push({
|
||||||
|
elements: [rect],
|
||||||
|
top: rect.top,
|
||||||
|
bottom: rect.bottom,
|
||||||
|
maxHeight: rect.height
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 4. 累加每行最大高度
|
||||||
|
return rows.reduce((sum, row) => sum + row.maxHeight, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const ignoreElements = (element) => {
|
const ignoreElements = (element) => {
|
||||||
return element.classList.contains('ql-toolbar');
|
return element.classList.contains('ql-toolbar');
|
||||||
}
|
};
|
||||||
|
|
||||||
const prepareCapture = async () => {
|
const prepareCapture = async () => {
|
||||||
state.previewVisible = true; // 显示预览弹窗
|
state.previewVisible = true;
|
||||||
|
|
||||||
// 创建临时样式
|
// 创建临时样式
|
||||||
const style = document.createElement('style')
|
const style = document.createElement('style');
|
||||||
style.id = 'capture-style'
|
style.textContent = `.ql-container.ql-snow { border: none !important; }`;
|
||||||
style.textContent = `
|
document.head.appendChild(style);
|
||||||
.ql-container.ql-snow {
|
|
||||||
border: none !important;
|
|
||||||
}
|
|
||||||
`
|
|
||||||
document.head.appendChild(style)
|
|
||||||
// 捕获页面元素并生成图片
|
|
||||||
try {
|
try {
|
||||||
const element = document.querySelector('#main-container'); // 替换为要捕获的元素选择器
|
const element = document.querySelector('#main-container');
|
||||||
|
let totalHeight = calculateVisualHeight('[data-html2canvas-ignore]') + calculateVisualHeight('.ql-toolbar');
|
||||||
|
console.log('所有携带指定属性的元素高度之和:', totalHeight);
|
||||||
if (!element) {
|
if (!element) {
|
||||||
console.error('Element with ID "main-container" not found.');
|
console.error('Element not found');
|
||||||
state.previewVisible = false;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 1. 生成原始截图
|
||||||
const canvas = await html2canvas(element, {
|
const canvas = await html2canvas(element, {
|
||||||
ignoreElements: ignoreElements,
|
ignoreElements: ignoreElements,
|
||||||
height: element.scrollHeight,
|
height: element.scrollHeight - totalHeight
|
||||||
}
|
});
|
||||||
);
|
|
||||||
state.previewImage = canvas.toDataURL();
|
// 2. 创建新Canvas添加水印
|
||||||
if (!state.previewImage) {
|
const watermarkedCanvas = document.createElement('canvas');
|
||||||
console.error('Failed to generate image data URL.');
|
const ctx = watermarkedCanvas.getContext('2d');
|
||||||
state.previewVisible = false;
|
|
||||||
state.previewVisible = false;
|
// 设置新Canvas尺寸
|
||||||
|
watermarkedCanvas.width = canvas.width;
|
||||||
|
watermarkedCanvas.height = canvas.height;
|
||||||
|
|
||||||
|
// 绘制原始截图
|
||||||
|
ctx.drawImage(canvas, 0, 0);
|
||||||
|
|
||||||
|
// 添加水印
|
||||||
|
ctx.font = `${watermark.fontSize}px Arial`;
|
||||||
|
ctx.fillStyle = watermark.color;
|
||||||
|
ctx.textAlign = 'center';
|
||||||
|
ctx.textBaseline = 'middle';
|
||||||
|
|
||||||
|
// 计算每个水印的位置间隔
|
||||||
|
const colSpace = watermarkedCanvas.width / (watermark.cols + 1);
|
||||||
|
const rowSpace = watermarkedCanvas.height / (watermark.rows + 1);
|
||||||
|
|
||||||
|
// 保存原始画布状态
|
||||||
|
ctx.save();
|
||||||
|
|
||||||
|
// 循环绘制多个水印
|
||||||
|
for (let row = 1; row <= watermark.rows; row++) {
|
||||||
|
for (let col = 1; col <= watermark.cols; col++) {
|
||||||
|
ctx.save(); // 保存当前状态
|
||||||
|
const x = col * colSpace;
|
||||||
|
const y = row * rowSpace;
|
||||||
|
|
||||||
|
// 移动到目标位置并旋转
|
||||||
|
ctx.translate(x, y);
|
||||||
|
ctx.rotate((watermark.angle * Math.PI) / 180);
|
||||||
|
|
||||||
|
// 绘制水印文字
|
||||||
|
ctx.fillText(watermark.text, 0, 0);
|
||||||
|
ctx.restore(); // 恢复状态
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ctx.restore(); // 恢复原始状态
|
||||||
|
// 3. 存储带水印的图片
|
||||||
|
state.previewImage = watermarkedCanvas.toDataURL();
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to capture screenshot', error);
|
console.error('Capture failed', error);
|
||||||
state.previewVisible = false;
|
|
||||||
} finally {
|
} finally {
|
||||||
// 清除临时样式
|
document.head.removeChild(style);
|
||||||
document.getElementById('capture-style')?.remove()
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -119,7 +254,7 @@ const handleClose = (done) => {
|
|||||||
right: 0;
|
right: 0;
|
||||||
height: 48px;
|
height: 48px;
|
||||||
background: #f8f8f8;
|
background: #f8f8f8;
|
||||||
//border-bottom: 1px solid #eee; display: flex;
|
//border-bottom: 1px solid #eee; display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 0 8px;
|
padding: 0 8px;
|
||||||
z-index: 100;
|
z-index: 100;
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { onMounted, ref } from 'vue';
|
import { onMounted,watch, ref } from 'vue';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
text: {
|
text: {
|
||||||
@ -31,6 +31,8 @@ onMounted(() => {
|
|||||||
createWatermark();
|
createWatermark();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const createWatermark = () => {
|
const createWatermark = () => {
|
||||||
const canvas = document.createElement('canvas');
|
const canvas = document.createElement('canvas');
|
||||||
const ctx = canvas.getContext('2d');
|
const ctx = canvas.getContext('2d');
|
||||||
@ -78,6 +80,9 @@ const createWatermark = () => {
|
|||||||
// });
|
// });
|
||||||
// observer.observe(container);
|
// observer.observe(container);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 响应props变化
|
||||||
|
watch(() => [props.text, props.font, props.color, props.angle], createWatermark);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
@ -6,13 +6,15 @@
|
|||||||
</div>
|
</div>
|
||||||
<el-tabs v-model="activeName" type="card" class="demo-tabs" @tab-click="handleTabClick">
|
<el-tabs v-model="activeName" type="card" class="demo-tabs" @tab-click="handleTabClick">
|
||||||
<el-tab-pane v-for="type in yuhunTypes" :key="type.name" :label="type.label" :name="type.name">
|
<el-tab-pane v-for="type in yuhunTypes" :key="type.name" :label="type.label" :name="type.name">
|
||||||
<el-space wrap size="large">
|
<div style="max-height: 500px; overflow-y: auto;">
|
||||||
|
<el-space wrap size="large" style="">
|
||||||
<div v-for="yuhun in filterYuhunByType(activeName)" :key="yuhun.name">
|
<div v-for="yuhun in filterYuhunByType(activeName)" :key="yuhun.name">
|
||||||
<el-button style="width: 100px; height: 100px;" @click="confirm(yuhun)">
|
<el-button style="width: 100px; height: 100px;" @click="confirm(yuhun)">
|
||||||
<img :src="yuhun.avatar" style="width: 99px; height: 99px;">
|
<img :src="yuhun.avatar" style="width: 99px; height: 99px;">
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
</el-space>
|
</el-space>
|
||||||
|
</div>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
</el-tabs>
|
</el-tabs>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
@ -48,6 +50,7 @@ const yuhunTypes = [
|
|||||||
{label: '防御加成', name: 'Defense'},
|
{label: '防御加成', name: 'Defense'},
|
||||||
{label: '效果命中', name: 'ControlHit'},
|
{label: '效果命中', name: 'ControlHit'},
|
||||||
{label: '效果抵抗', name: 'ControlMiss'},
|
{label: '效果抵抗', name: 'ControlMiss'},
|
||||||
|
{label: '暴击伤害', name: 'CritDamage'},
|
||||||
{label: '首领御魂', name: 'PVE'}
|
{label: '首领御魂', name: 'PVE'}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -40,11 +40,6 @@
|
|||||||
<QuillEditor v-model:content="group.shortDescription" contentType="html" theme="snow"
|
<QuillEditor v-model:content="group.shortDescription" contentType="html" theme="snow"
|
||||||
:toolbar="toolbarOptions"/>
|
:toolbar="toolbarOptions"/>
|
||||||
</div>
|
</div>
|
||||||
<!-- <div style="display: flex; justify-content: flex-end;" data-html2canvas-ignore="true">-->
|
|
||||||
<!-- <el-button class="drag-handle" type="primary" icon="Rank" circle></el-button>-->
|
|
||||||
<!-- <el-button type="danger" icon="Delete" circle @click="removeGroup(groupIndex)"></el-button>-->
|
|
||||||
<!-- <el-button type="primary" icon="Plus" circle @click="addGroup"></el-button>-->
|
|
||||||
<!-- </div>-->
|
|
||||||
<div>
|
<div>
|
||||||
<draggable :list="group.groupInfo" item-key="name" style="display: flex; flex-direction: row; width: 20%;">
|
<draggable :list="group.groupInfo" item-key="name" style="display: flex; flex-direction: row; width: 20%;">
|
||||||
<template #item="{element : position, index:positionIndex}">
|
<template #item="{element : position, index:positionIndex}">
|
||||||
@ -53,41 +48,49 @@
|
|||||||
<el-card shadow="never"
|
<el-card shadow="never"
|
||||||
:body-style="{ display: 'flex', 'flex-direction': 'column', 'justify-content': 'center', 'align-items': 'center' }">
|
:body-style="{ display: 'flex', 'flex-direction': 'column', 'justify-content': 'center', 'align-items': 'center' }">
|
||||||
|
|
||||||
<div>
|
<div data-html2canvas-ignore="true">
|
||||||
<!-- Add delete button here -->
|
<!-- Add delete button here -->
|
||||||
<el-button type="danger" icon="Delete" circle
|
<el-button type="danger" icon="Delete" circle @click="removeGroupElement(groupIndex, positionIndex)"/>
|
||||||
@click="removeGroupElement(groupIndex, positionIndex)"
|
<el-button type="primary" icon="Plus" circle @click="addGroupElement(groupIndex)"/>
|
||||||
data-html2canvas-ignore="true"></el-button>
|
|
||||||
<el-button type="primary" icon="Plus" circle @click="addGroupElement(groupIndex)"
|
|
||||||
data-html2canvas-ignore="true"></el-button>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="avatar-wrapper">
|
<div style="position: relative; display: inline-block;">
|
||||||
|
<!-- 头像图片 -->
|
||||||
<img :src="position.avatar || '/assets/Shikigami/default.png'"
|
<img :src="position.avatar || '/assets/Shikigami/default.png'"
|
||||||
|
style="cursor: pointer; vertical-align: bottom;"
|
||||||
class="avatar-image"
|
class="avatar-image"
|
||||||
@click="editShikigami(groupIndex,positionIndex)"/>
|
@click="editShikigami(groupIndex, positionIndex)"/>
|
||||||
</div>
|
|
||||||
<div style="padding: 14px; width: 95px">
|
|
||||||
|
|
||||||
<span>{{ position.name || "" }}</span>
|
<!-- 文字图层 -->
|
||||||
<div class="bottom" data-html2canvas-ignore="true">
|
<span v-if="position.properties"
|
||||||
|
style="position: absolute; bottom: 0; left: 50%; transform: translateX(-50%) translateY(50%);
|
||||||
|
font-size: 24px; color: white; text-shadow: -1px -1px 0 black, 1px -1px 0 black, -1px 1px 0 black, 1px 1px 0 black;
|
||||||
|
white-space: nowrap; padding: 0 8px; margin: 0; display: flex; align-items: center; justify-content: center;">
|
||||||
|
{{ position.properties.levelRequired }}级 {{ position.properties.skillRequired.join('') }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div style="padding: 14px; width: 120px;">
|
||||||
|
|
||||||
|
<div style="display: flex; justify-content: center;" data-html2canvas-ignore="true">
|
||||||
|
<span>{{ position.name || "" }}</span>
|
||||||
|
</div>
|
||||||
|
<div style="display: flex; justify-content: center;" class="bottom" data-html2canvas-ignore="true">
|
||||||
<el-button @click="editProperty(groupIndex,positionIndex)">{{ t('editProperties') }}
|
<el-button @click="editProperty(groupIndex,positionIndex)">{{ t('editProperties') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
<!-- properties-->
|
|
||||||
<!-- {"edit":true,"yuhun":{"yuhunSetEffect":[{"name":"狰","type":"attack","avatar":"/assets/Yuhun/狰.png"}],"target":"伤害输出","property2":["Attack"],"property4":["Attack"],"property6":["Crit","CritDamage"]},"levelRequired":"40","speed":"","skillRequiredMode":"all","skillRequired":["技能一","技能二","技能三"]}-->
|
|
||||||
<div v-if="position.properties">
|
<div v-if="position.properties">
|
||||||
<div>
|
<div style="display: flex; justify-content: center;">
|
||||||
<span
|
<span
|
||||||
style="display: inline-block; width: 100px; height: 25px; background-color: #666; border-top-left-radius: 5px; border-top-right-radius: 5px; margin-right: 5px; color: white; text-align: center; white-space: pre-wrap ">
|
style="width: 100px;height: 50px;background-color: #666;
|
||||||
{{ position.properties.yuhun.yuhunSetEffect.map(item => item.name).join(' ') }}
|
border-radius: 5px; margin-right: 5px; color: white;
|
||||||
</span>
|
text-align: center; white-space: pre-wrap; display: flex; align-items: center; justify-content: center; flex-direction: column ">
|
||||||
<span
|
{{getYuhunNames(position.properties.yuhun.yuhunSetEffect)}}<br/>{{ t('yuhun_target.shortName.' + position.properties.yuhun.target) }}·{{ getYuhunPropertyNames(position.properties.yuhun) }}
|
||||||
style="display: inline-block; width: 100px; height: 25px; background-color: #666; border-bottom-left-radius: 5px; border-bottom-right-radius: 5px; margin-right: 5px; color: white; text-align: center; white-space: pre-wrap ">
|
|
||||||
{{ t('yuhun_target.' + position.properties.yuhun.target) }}·
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div v-for="(value, key, index) in position.properties" data-html2canvas-ignore="true">
|
<div>
|
||||||
<span>{{ key }}</span> : <span>{{ value || '-' }}</span>
|
<span
|
||||||
|
style="display: inline-block; width: 100px; height: 30px; border-radius: 5px; margin-right: 5px; color: red; text-align: center; white-space: pre-wrap; display: flex; align-items: center; justify-content: center; flex-direction: column ">
|
||||||
|
{{ position.properties.desc }}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -120,9 +123,6 @@
|
|||||||
<div style="margin: 20px">
|
<div style="margin: 20px">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -227,7 +227,6 @@ const editProperty = (groupIndex, positionIndex) => {
|
|||||||
state.groupIndex = groupIndex;
|
state.groupIndex = groupIndex;
|
||||||
state.positionIndex = positionIndex;
|
state.positionIndex = positionIndex;
|
||||||
state.currentShikigami = state.groups[groupIndex].groupInfo[positionIndex];
|
state.currentShikigami = state.groups[groupIndex].groupInfo[positionIndex];
|
||||||
console.log("currentShikigami", JSON.stringify(state.currentShikigami));
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const closeProperty = () => {
|
const closeProperty = () => {
|
||||||
@ -262,9 +261,72 @@ const addGroupElement = (groupIndex) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const exportGroups = () => {
|
||||||
|
const dataStr = JSON.stringify(state.groups, null, 2);
|
||||||
|
const blob = new Blob([dataStr], {type: 'application/json'});
|
||||||
|
const url = URL.createObjectURL(blob);
|
||||||
|
const link = document.createElement('a');
|
||||||
|
link.href = url;
|
||||||
|
link.download = `yys-export-${Date.now()}.json`;
|
||||||
|
link.click();
|
||||||
|
URL.revokeObjectURL(url);
|
||||||
|
};
|
||||||
|
|
||||||
|
const getYuhunNames =(yuhunSetEffect) =>{
|
||||||
|
const names = yuhunSetEffect.map(item => item.name).join('');
|
||||||
|
if (names.length <= 6) {
|
||||||
|
return names;
|
||||||
|
} else {
|
||||||
|
return yuhunSetEffect.map(item => item.shortName || item.name).join('');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const getYuhunPropertyNames = (yuhun) =>{
|
||||||
|
// 根据条件处理 yuhun.property2
|
||||||
|
let property2Value,property4Value,property6Value;
|
||||||
|
if (yuhun.property2.length >= 4) {
|
||||||
|
property2Value = 'X';
|
||||||
|
} else {
|
||||||
|
property2Value = t('yuhun_property.shortName.' + yuhun.property2[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (yuhun.property4.length >= 5) {
|
||||||
|
property4Value = 'X';
|
||||||
|
} else {
|
||||||
|
property4Value = t('yuhun_property.shortName.' + yuhun.property4[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (yuhun.property6.length >= 5) {
|
||||||
|
property6Value = 'X';
|
||||||
|
} else {
|
||||||
|
property6Value = t('yuhun_property.shortName.' + yuhun.property6[0]);
|
||||||
|
}
|
||||||
|
// 构建 propertyNames 字符串
|
||||||
|
const propertyNames =
|
||||||
|
property2Value + property4Value + property6Value
|
||||||
|
|
||||||
|
return propertyNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
const importGroups = (file) => {
|
||||||
|
const reader = new FileReader();
|
||||||
|
reader.onload = (e) => {
|
||||||
|
try {
|
||||||
|
const importedData = JSON.parse(e.target.result);
|
||||||
|
state.groups = importedData;
|
||||||
|
ElMessage.success('导入成功');
|
||||||
|
} catch (error) {
|
||||||
|
ElMessage.error('文件格式错误');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
reader.readAsText(file);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 暴露方法给父组件
|
||||||
|
defineExpose({
|
||||||
|
exportGroups,
|
||||||
|
importGroups
|
||||||
|
});
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@ -288,7 +350,7 @@ const addGroupElement = (groupIndex) => {
|
|||||||
position: relative;
|
position: relative;
|
||||||
overflow: hidden; /* 隐藏超出部分 */
|
overflow: hidden; /* 隐藏超出部分 */
|
||||||
border-radius: 50%; /* 圆形裁剪 */
|
border-radius: 50%; /* 圆形裁剪 */
|
||||||
//border: 2px solid #fff; /* 可选:添加边框 */ //box-shadow: 0 2px 8px rgba(0,0,0,0.1); /* 可选:添加阴影 */
|
//border: 2px solid #fff; /* 可选:添加边框 */ //box-shadow: 0 2px 8px rgba(0,0,0,0.1); /* 可选:添加阴影 */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 图片样式 */
|
/* 图片样式 */
|
||||||
@ -302,8 +364,6 @@ const addGroupElement = (groupIndex) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.el-card {
|
.el-card {
|
||||||
border: 0;
|
border: 0;
|
||||||
}
|
}
|
||||||
|
@ -1,111 +1,139 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"name": "散件",
|
||||||
|
"shortName": "散件",
|
||||||
|
"type": "attack",
|
||||||
|
"avatar": "/assets/Yuhun/散件.png"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "隐念",
|
"name": "隐念",
|
||||||
|
"shortName": "隐",
|
||||||
"type": "attack",
|
"type": "attack",
|
||||||
"avatar": "/assets/Yuhun/隐念.png"
|
"avatar": "/assets/Yuhun/隐念.png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "贝吹坊",
|
"name": "贝吹坊",
|
||||||
|
"shortName": "贝",
|
||||||
"type": "attack",
|
"type": "attack",
|
||||||
"avatar": "/assets/Yuhun/贝吹坊.png"
|
"avatar": "/assets/Yuhun/贝吹坊.png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "兵主部",
|
"name": "兵主部",
|
||||||
|
"shortName": "兵",
|
||||||
"type": "attack",
|
"type": "attack",
|
||||||
"avatar": "/assets/Yuhun/兵主部.png"
|
"avatar": "/assets/Yuhun/兵主部.png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "狂骨",
|
"name": "狂骨",
|
||||||
|
"shortName": "狂",
|
||||||
"type": "attack",
|
"type": "attack",
|
||||||
"avatar": "/assets/Yuhun/狂骨.png"
|
"avatar": "/assets/Yuhun/狂骨.png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "阴摩罗",
|
"name": "阴摩罗",
|
||||||
|
"shortName": "阴",
|
||||||
"type": "attack",
|
"type": "attack",
|
||||||
"avatar": "/assets/Yuhun/阴摩罗.png"
|
"avatar": "/assets/Yuhun/阴摩罗.png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "心眼",
|
"name": "心眼",
|
||||||
|
"shortName": "心",
|
||||||
"type": "attack",
|
"type": "attack",
|
||||||
"avatar": "/assets/Yuhun/心眼.png"
|
"avatar": "/assets/Yuhun/心眼.png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "鸣屋",
|
"name": "鸣屋",
|
||||||
|
"shortName": "鸣",
|
||||||
"type": "attack",
|
"type": "attack",
|
||||||
"avatar": "/assets/Yuhun/鸣屋.png"
|
"avatar": "/assets/Yuhun/鸣屋.png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "狰",
|
"name": "狰",
|
||||||
|
"shortName": "狰",
|
||||||
"type": "attack",
|
"type": "attack",
|
||||||
"avatar": "/assets/Yuhun/狰.png"
|
"avatar": "/assets/Yuhun/狰.png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "轮入道",
|
"name": "轮入道",
|
||||||
|
"shortName": "轮",
|
||||||
"type": "attack",
|
"type": "attack",
|
||||||
"avatar": "/assets/Yuhun/轮入道.png"
|
"avatar": "/assets/Yuhun/轮入道.png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "蝠翼",
|
"name": "蝠翼",
|
||||||
|
"shortName": "蝠",
|
||||||
"type": "attack",
|
"type": "attack",
|
||||||
"avatar": "/assets/Yuhun/蝠翼.png"
|
"avatar": "/assets/Yuhun/蝠翼.png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "应声虫",
|
"name": "应声虫",
|
||||||
|
"shortName": "应",
|
||||||
"type": "Crit",
|
"type": "Crit",
|
||||||
"avatar": "/assets/Yuhun/应声虫.png"
|
"avatar": "/assets/Yuhun/应声虫.png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "海月火玉",
|
"name": "海月火玉",
|
||||||
|
"shortName": "海",
|
||||||
"type": "Crit",
|
"type": "Crit",
|
||||||
"avatar": "/assets/Yuhun/海月火玉.png"
|
"avatar": "/assets/Yuhun/海月火玉.png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "青女房",
|
"name": "青女房",
|
||||||
|
"shortName": "房",
|
||||||
"type": "Crit",
|
"type": "Crit",
|
||||||
"avatar": "/assets/Yuhun/青女房.png"
|
"avatar": "/assets/Yuhun/青女房.png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "针女",
|
"name": "针女",
|
||||||
|
"shortName": "针",
|
||||||
"type": "Crit",
|
"type": "Crit",
|
||||||
"avatar": "/assets/Yuhun/针女.png"
|
"avatar": "/assets/Yuhun/针女.png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "镇墓兽",
|
"name": "镇墓兽",
|
||||||
|
"shortName": "镇",
|
||||||
"type": "Crit",
|
"type": "Crit",
|
||||||
"avatar": "/assets/Yuhun/镇墓兽.png"
|
"avatar": "/assets/Yuhun/镇墓兽.png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "破势",
|
"name": "破势",
|
||||||
|
"shortName": "破",
|
||||||
"type": "Crit",
|
"type": "Crit",
|
||||||
"avatar": "/assets/Yuhun/破势.png"
|
"avatar": "/assets/Yuhun/破势.png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "伤魂鸟",
|
"name": "伤魂鸟",
|
||||||
|
"shortName": "伤",
|
||||||
"type": "Crit",
|
"type": "Crit",
|
||||||
"avatar": "/assets/Yuhun/伤魂鸟.png"
|
"avatar": "/assets/Yuhun/伤魂鸟.png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "网切",
|
"name": "网切",
|
||||||
|
"shortName": "网",
|
||||||
"type": "Crit",
|
"type": "Crit",
|
||||||
"avatar": "/assets/Yuhun/网切.png"
|
"avatar": "/assets/Yuhun/网切.png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "三味",
|
"name": "三味",
|
||||||
|
"shortName": "三",
|
||||||
"type": "Crit",
|
"type": "Crit",
|
||||||
"avatar": "/assets/Yuhun/三味.png"
|
"avatar": "/assets/Yuhun/三味.png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "叠叩",
|
"name": "叠叩",
|
||||||
|
"shortName": "叠",
|
||||||
"type": "Health",
|
"type": "Health",
|
||||||
"avatar": "/assets/Yuhun/叠叩.png"
|
"avatar": "/assets/Yuhun/叠叩.png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "恶楼",
|
"name": "恶楼",
|
||||||
|
"shortName": "恶",
|
||||||
"type": "Health",
|
"type": "Health",
|
||||||
"avatar": "/assets/Yuhun/恶楼.png"
|
"avatar": "/assets/Yuhun/恶楼.png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "涂佛",
|
"name": "涂佛",
|
||||||
|
"shortName": "涂",
|
||||||
"type": "Health",
|
"type": "Health",
|
||||||
"avatar": "/assets/Yuhun/涂佛.png"
|
"avatar": "/assets/Yuhun/涂佛.png"
|
||||||
},
|
},
|
||||||
@ -136,11 +164,13 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "涅槃之火",
|
"name": "涅槃之火",
|
||||||
|
"shortName": "涅槃火",
|
||||||
"type": "Health",
|
"type": "Health",
|
||||||
"avatar": "/assets/Yuhun/涅槃之火.png"
|
"avatar": "/assets/Yuhun/涅槃之火.png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "地藏像",
|
"name": "地藏像",
|
||||||
|
"shortName": "地藏",
|
||||||
"type": "Health",
|
"type": "Health",
|
||||||
"avatar": "/assets/Yuhun/地藏像.png"
|
"avatar": "/assets/Yuhun/地藏像.png"
|
||||||
},
|
},
|
||||||
@ -171,6 +201,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "日女巳时",
|
"name": "日女巳时",
|
||||||
|
"shortName": "日女",
|
||||||
"type": "Defense",
|
"type": "Defense",
|
||||||
"avatar": "/assets/Yuhun/日女巳时.png"
|
"avatar": "/assets/Yuhun/日女巳时.png"
|
||||||
},
|
},
|
||||||
@ -181,6 +212,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "招财猫",
|
"name": "招财猫",
|
||||||
|
"shortName": "招财",
|
||||||
"type": "Defense",
|
"type": "Defense",
|
||||||
"avatar": "/assets/Yuhun/招财猫.png"
|
"avatar": "/assets/Yuhun/招财猫.png"
|
||||||
},
|
},
|
||||||
@ -241,16 +273,19 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "魍魉之匣",
|
"name": "魍魉之匣",
|
||||||
|
"shortName": "魍魉",
|
||||||
"type": "ControlMiss",
|
"type": "ControlMiss",
|
||||||
"avatar": "/assets/Yuhun/魍魉之匣.png"
|
"avatar": "/assets/Yuhun/魍魉之匣.png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "鬼灵歌伎",
|
"name": "鬼灵歌伎",
|
||||||
|
"shortName": "歌伎",
|
||||||
"type": "PVE",
|
"type": "PVE",
|
||||||
"avatar": "/assets/Yuhun/鬼灵歌伎.png"
|
"avatar": "/assets/Yuhun/鬼灵歌伎.png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "蜃气楼",
|
"name": "蜃气楼",
|
||||||
|
"shortName": "蜃",
|
||||||
"type": "PVE",
|
"type": "PVE",
|
||||||
"avatar": "/assets/Yuhun/蜃气楼.png"
|
"avatar": "/assets/Yuhun/蜃气楼.png"
|
||||||
},
|
},
|
||||||
@ -261,16 +296,35 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "荒骷髅",
|
"name": "荒骷髅",
|
||||||
|
"shortName": "荒",
|
||||||
"type": "PVE",
|
"type": "PVE",
|
||||||
"avatar": "/assets/Yuhun/荒骷髅.png"
|
"avatar": "/assets/Yuhun/荒骷髅.png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "胧车",
|
"name": "胧车",
|
||||||
|
"shortName": "胧",
|
||||||
"type": "PVE",
|
"type": "PVE",
|
||||||
"avatar": "/assets/Yuhun/胧车.png"
|
"avatar": "/assets/Yuhun/胧车.png"
|
||||||
},{
|
},
|
||||||
"name": "土蜘蛛",
|
{
|
||||||
"type": "PVE",
|
"name": "土蜘蛛",
|
||||||
"avatar": "/assets/Yuhun/土蜘蛛.png"
|
"shortName": "土",
|
||||||
}
|
"type": "PVE",
|
||||||
|
"avatar": "/assets/Yuhun/土蜘蛛.png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "夜荒魂",
|
||||||
|
"type": "PVE",
|
||||||
|
"avatar": "/assets/Yuhun/夜荒魂.png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "奉海图",
|
||||||
|
"type": "Defense",
|
||||||
|
"avatar": "/assets/Yuhun/奉海图.png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "无刀取",
|
||||||
|
"type": "CritDamage",
|
||||||
|
"avatar": "/assets/Yuhun/无刀取.png"
|
||||||
|
}
|
||||||
]
|
]
|
@ -6,19 +6,60 @@
|
|||||||
"Paste": "粘贴",
|
"Paste": "粘贴",
|
||||||
"editProperties": "配置属性",
|
"editProperties": "配置属性",
|
||||||
"prepareCapture": "生成截图",
|
"prepareCapture": "生成截图",
|
||||||
|
"yuhunSelect": "请选择御魂",
|
||||||
|
"yuhunTarget": "效果指标",
|
||||||
"yuhun_target": {
|
"yuhun_target": {
|
||||||
"1": "伤害",
|
"shortName": {
|
||||||
"2": "命中",
|
"0": "任意",
|
||||||
"3": "抵抗",
|
"1": "伤害",
|
||||||
"4": "生命",
|
"2": "命中",
|
||||||
"5": "攻击",
|
"3": "抵抗",
|
||||||
"6": "防御",
|
"4": "生命",
|
||||||
"7": "速度",
|
"5": "攻击",
|
||||||
"8": "暴击",
|
"6": "防御",
|
||||||
"9": "爆伤",
|
"7": "速度",
|
||||||
"10": "治疗量",
|
"8": "暴击",
|
||||||
"11": "命抗",
|
"9": "爆伤",
|
||||||
"12": "防御输出"
|
"10": "治疗量",
|
||||||
|
"11": "命抗",
|
||||||
|
"12": "防御输出"
|
||||||
|
},
|
||||||
|
"fullName": {
|
||||||
|
"0": "任意",
|
||||||
|
"1": "伤害输出",
|
||||||
|
"2": "效果命中",
|
||||||
|
"3": "效果抵抗",
|
||||||
|
"4": "生命",
|
||||||
|
"5": "攻击",
|
||||||
|
"6": "防御",
|
||||||
|
"7": "速度",
|
||||||
|
"8": "暴击",
|
||||||
|
"9": "暴击伤害",
|
||||||
|
"10": "治疗量",
|
||||||
|
"11": "命抗双修",
|
||||||
|
"12": "防御输出"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"yuhunSelect": "请选择御魂"
|
"yuhun_property": {
|
||||||
|
"shortName": {
|
||||||
|
"Attack": "攻",
|
||||||
|
"Defense": "防",
|
||||||
|
"Health": "生",
|
||||||
|
"Speed": "速",
|
||||||
|
"ControlHit": "命",
|
||||||
|
"ControlMiss": "抵",
|
||||||
|
"Crit": "暴",
|
||||||
|
"CritDamage": "爆"
|
||||||
|
},
|
||||||
|
"fullName": {
|
||||||
|
"Attack": "攻击加成",
|
||||||
|
"Defense": "防御加成",
|
||||||
|
"Health": "生命加成",
|
||||||
|
"Speed": "速度",
|
||||||
|
"ControlHit": "效果命中",
|
||||||
|
"ControlMiss": "效果抵抗",
|
||||||
|
"Crit": "暴击",
|
||||||
|
"CritDamage": "暴击伤害"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|