水印调整,增加工具栏

pull/4/head
rookie4show 1 month ago
parent 8ebf9b5390
commit b869d5263c
  1. 12
      src/App.vue
  2. 4
      src/components/ShikigamiProperty.vue
  3. 181
      src/components/ShikigamiSelect.vue
  4. 139
      src/components/Toolbar.vue
  5. 77
      src/components/Yys.vue
  6. 3
      src/locales/zh.json

@ -1,24 +1,28 @@
<script setup>
import Yys from './components/Yys.vue'
import Watermark from './components/Watermark.vue' // Watermark
import Toolbar from './components/Toolbar.vue'
</script>
<template>
<main id="main-container">
<!-- 添加工具栏 -->
<Toolbar title="我的应用" username="示例用户" data-html2canvas-ignore="true"/>
<!-- 添加 Watermark 组件 -->
<Watermark text="示例水印" font="30px Arial" color="rgba(184, 184, 184, 0.3)" angle=-20 >
<Yys />
</Watermark>
<Yys/>
</main>
</template>
<style scoped>
/* 确保 #main-container 具有相对定位 */
#main-container {
margin-top: 48px; /* 与工具栏高度相同 */
position: relative;
width: 100%;
min-height: 100vh; /* 允许容器扩展 */
//position: relative;
//position: relative;
}
/* 如果 Yys 组件需要特定的高度或布局,可以根据需要调整 */

@ -157,7 +157,7 @@ let shikigami = ref({
edit: false,
yuhun: {
yuhunSetEffect: [],
target: "伤害输出",
target: "1",
property2: ["Attack"],
property4: ["Attack"],
property6: ["Crit", "CritDamage"],
@ -175,7 +175,9 @@ watch(() => props.currentShikigami, (newVal) => {
if (newVal.properties != undefined && newVal.properties.edit == true) {
shikigami.value = newVal.properties
}
console.log("ShikigamiProperty.vue" + current.value.name)
current.value = newVal
console.log("ShikigamiProperty.vue" + current.value.name)
}, {deep: true})
watch(() => props.showProperty, (newVal) => {

@ -1,6 +1,11 @@
<template>
<el-dialog v-model="show" :visable.sync="show" title="请选择式神" @cancel="cancel" :before-close="cancel">
<span>当前选择{{current.name}}</span>
<el-dialog
v-model="show"
title="请选择式神"
@close="cancel"
:before-close="cancel"
>
<span>当前选择式神{{ current.name }}</span>
<el-tabs
v-model="activeName"
type="card"
@ -13,127 +18,91 @@
:label="rarity.label"
:name="rarity.name"
>
<div v-if="rarityLevels.includes(rarity)"> <!-- 只在这些级别中显示内容 -->
<div style="max-height: 600px; overflow-y: auto;">
<el-space wrap size="large">
<div v-for="i in filterShikigamiByRarity(rarity.name)" :key="i.name">
<el-button style="width: 100px; height: 100px;" @click.stop="confirm(i)">
<el-button
style="width: 100px; height: 100px;"
@click.stop="confirm(i)"
>
<img :src="i.avatar" style="width: 99px; height: 99px;">
</el-button>
</div>
</el-space>
</div>
</el-tab-pane>
</el-tabs>
<!-- <template #footer>-->
<!-- <span class="dialog-footer">-->
<!-- <el-button @click.stop="cancel">Cancel</el-button>-->
<!-- <el-button type="primary" @click.stop="confirm"> Confirm </el-button>-->
<!-- </span>-->
<!-- </template>-->
</el-dialog>
</template>
<script lang="ts">
import shikigamiData from "../data/Shikigami.json";
import { ref } from "vue";
<script setup lang="ts">
import { ref, watch, computed } from 'vue'
import type { TabsPaneContext } from 'element-plus'
import shikigamiData from "../data/Shikigami.json"
interface Shikigami {
name: string
avatar: string
rarity: string
}
const props = defineProps({
currentShikigami: {
type: Object as () => Shikigami,
default: () => ({ name: '' })
},
showSelectShikigami: {
type: Boolean,
default: false
}
})
const emit = defineEmits(['closeSelectShikigami', 'updateShikigami'])
const activeName = ref('ALL')
let current = ref({name:''})
const show = ref(false)
const rarityLevels = [
{ label: "全部", name: "ALL" },
{ label: "SP", name: "SP" },
{ label: "SSR", name: "SSR" },
{ label: "SR", name: "SR" },
{ label: "R", name: "R" },
{ label: "N", name: "N" },
{ label: "联动", name: "L" },
{ label: "呱太", name: "G" },
]
watch(() => props.showSelectShikigami, (newVal) => {
show.value = newVal
})
watch(() => props.currentShikigami, (newVal) => {
console.log("ShikigamiSelect.vue" + current.value.name)
current.value = newVal
console.log("ShikigamiSelect.vue" + current.value.name)
}, {deep: true})
const handleClick = (tab: TabsPaneContext, event: Event) => {
console.log(tab, event)
const handleClick = (tab: TabsPaneContext) => {
console.log('Tab clicked:', tab)
}
export default {
props: {
currentShikigami: {
type: Object,
default: {},
},
showSelectShikigami: {
type: Boolean,
},
},
data() {
return {
activeName:activeName,
shikigamiData: shikigamiData,
selected: null,
current: {},
show: false,
rarityLevels: [
{
"label":"全部",
"name":"ALL"
},
{
"label":"SP",
"name":"SP"
},
{
"label":"SSR",
"name":"SSR"
},
{
"label":"SR",
"name":"SR"
},
{
"label":"R",
"name":"R"
},
{
"label":"N",
"name":"N"
},
{
"label":"联动",
"name":"L"
},
{
"label":"呱太",
"name":"G"
},
],
};
},
watch: {
showSelectShikigami(newVal, oldVal) {
console.log("=======>>>> ", newVal, oldVal);
this.show = newVal;
},
currentShikigami(newVal, oldVal) {
console.log("===item====>>>> ", newVal, oldVal);
this.current = newVal;
},
const cancel = () => {
emit('closeSelectShikigami')
show.value = false
}
},
methods: {
select(item) {
this.current = item;
},
cancel() {
console.log("cancel====");
this.$emit("closeSelectShikigami");
},
confirm(i) {
console.log("confirm====");
this.$emit("updateShikigami", JSON.parse(JSON.stringify(i)))
// this.current = {};
},
filterShikigamiByRarity(rarity) {
if(rarity.toLowerCase() == "all")
return this.shikigamiData
// rarity
const lowerCaseRarity = rarity.toLowerCase();
return this.shikigamiData.filter(shikigami =>
// shikigamirarity
shikigami.rarity.toLowerCase() === lowerCaseRarity
);
},
},
};
</script>
const confirm = (shikigami: Shikigami) => {
emit('updateShikigami', shikigami)
// cancel()
}
const filterShikigamiByRarity = (rarity: string) => {
if (rarity.toLowerCase() === 'all') return shikigamiData
return shikigamiData.filter(item =>
item.rarity.toLowerCase() === rarity.toLowerCase()
)
}
</script>

@ -0,0 +1,139 @@
<template>
<div class="toolbar">
<div data-html2canvas-ignore="true">
<el-button icon="Upload" type="primary" @click="prepareCapture">{{ t('import') }}</el-button>
<el-button icon="Download" type="primary" @click="prepareCapture">{{ t('export') }}</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>
</div>
<!-- 预览弹窗 -->
<el-dialog id="preview-container" v-model="state.previewVisible" width="80%" :before-close="handleClose">
<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;"/>
</Watermark>
</div>
<!-- <img v-if="state.previewImage" :src="state.previewImage" alt="Preview" style="width: 100%; height: auto;" />-->
<span slot="footer" class="dialog-footer">
<el-button @click="state.previewVisible = false"> </el-button>
<el-button type="primary" @click="downloadImage"> </el-button>
</span>
</el-dialog>
</div>
</template>
<script setup>
import {inject, nextTick} from 'vue';
import html2canvas from "html2canvas";
import {useI18n} from 'vue-i18n'
import Watermark from './Watermark.vue' // Watermark
// i18n
const {t} = useI18n()
//
const watermarkControl = inject('watermarkControl');
defineProps({
title: {
type: String,
default: '默认标题'
}
})
import {ref, reactive, toRefs} from 'vue';
//
const state = reactive({
previewImage: null, // URL
previewVisible: false, //
});
const ignoreElements = (element) => {
return element.classList.contains('ql-toolbar');
}
const prepareCapture = async () => {
state.previewVisible = true; //
//
const style = document.createElement('style')
style.id = 'capture-style'
style.textContent = `
.ql-container.ql-snow {
border: none !important;
}
`
document.head.appendChild(style)
//
try {
const element = document.querySelector('#main-container'); //
if (!element) {
console.error('Element with ID "main-container" not found.');
state.previewVisible = false;
return;
}
const canvas = await html2canvas(element, {
ignoreElements: ignoreElements,
height: element.scrollHeight,
}
);
state.previewImage = canvas.toDataURL();
if (!state.previewImage) {
console.error('Failed to generate image data URL.');
state.previewVisible = false;
state.previewVisible = false;
}
} catch (error) {
console.error('Failed to capture screenshot', error);
state.previewVisible = false;
} finally {
//
document.getElementById('capture-style')?.remove()
}
};
const downloadImage = () => {
if (state.previewImage) {
const link = document.createElement('a');
link.href = state.previewImage;
link.download = 'screenshot.png'; //
link.click();
state.previewVisible = false; //
}
};
const handleClose = (done) => {
state.previewImage = null; //
done(); //
};
</script>
<style scoped>
.toolbar {
position: fixed;
top: 0;
left: 0;
right: 0;
height: 48px;
background: #f8f8f8;
//border-bottom: 1px solid #eee; display: flex;
align-items: center;
padding: 0 8px;
z-index: 100;
}
.title {
flex-grow: 1;
text-align: center;
font-size: 16px;
}
.left, .right {
flex-basis: 120px;
display: flex;
gap: 8px;
}
</style>

@ -12,11 +12,7 @@
@closeProperty="closeProperty"
@updateProperty="updateProperty"
/>
<!-- 现有的代码 -->
<div style="margin: 20px" data-html2canvas-ignore="true">
<!-- 触发截图的按钮 -->
<el-button type="primary" @click="prepareCapture">{{ t('prepareCapture') }}</el-button>
</div>
<draggable :list="state.groups" item-key="group" style="display: flex; flex-direction: column; width: 100%;"
handle=".drag-handle">
@ -125,17 +121,7 @@
<!-- 预览弹窗 -->
<el-dialog id="preview-container" v-model="state.previewVisible" width="80%" :before-close="handleClose">
<div style="max-height: 500px; overflow-y: auto;">
<img v-if="state.previewImage" :src="state.previewImage" alt="Preview" style="width: 100%; display: block;"/>
</div>
<!-- <img v-if="state.previewImage" :src="state.previewImage" alt="Preview" style="width: 100%; height: auto;" />-->
<span slot="footer" class="dialog-footer">
<el-button @click="state.previewVisible = false"> </el-button>
<el-button type="primary" @click="downloadImage"> </el-button>
</span>
</el-dialog>
</div>
</template>
@ -224,6 +210,7 @@ const editShikigami = (groupIndex, positionIndex) => {
state.showSelectShikigami = true;
state.groupIndex = groupIndex;
state.positionIndex = positionIndex;
state.currentShikigami = state.groups[groupIndex].groupInfo[positionIndex];
};
const updateShikigami = (shikigami) => {
@ -274,65 +261,11 @@ const addGroupElement = (groupIndex) => {
state.groups[groupIndex].groupInfo.push({});
};
const ignoreElements = (element) => {
return element.classList.contains('ql-toolbar');
}
const prepareCapture = async () => {
state.previewVisible = true; //
//
const style = document.createElement('style')
style.id = 'capture-style'
style.textContent = `
.ql-container.ql-snow {
border: none !important;
}
`
document.head.appendChild(style)
//
try {
const element = document.querySelector('#main-container'); //
if (!element) {
console.error('Element with ID "main-container" not found.');
state.previewVisible = false;
return;
}
const canvas = await html2canvas(element, {
ignoreElements: ignoreElements,
height: element.scrollHeight,
}
);
state.previewImage = canvas.toDataURL();
if (!state.previewImage) {
console.error('Failed to generate image data URL.');
state.previewVisible = false;
state.previewVisible = false;
}
} catch (error) {
console.error('Failed to capture screenshot', error);
state.previewVisible = false;
}finally {
//
document.getElementById('capture-style')?.remove()
}
};
const downloadImage = () => {
if (state.previewImage) {
const link = document.createElement('a');
link.href = state.previewImage;
link.download = 'screenshot.png'; //
link.click();
state.previewVisible = false; //
}
};
const handleClose = (done) => {
state.previewImage = null; //
done(); //
};
</script>
<style scoped>

@ -1,4 +1,7 @@
{
"import": "导入",
"export": "导出",
"setWatermark": "设置水印",
"Copy": "复制",
"Paste": "粘贴",
"editProperties": "配置属性",

Loading…
Cancel
Save