Merge remote-tracking branch 'origin/dev_vite' into StableVersion
9
package-lock.json
generated
@@ -35,7 +35,8 @@
|
||||
"vue-i18n": "^9.6.1",
|
||||
"vue-router": "^4.0.3",
|
||||
"vuedraggable": "^4.1.0",
|
||||
"vuex": "^4.0.0"
|
||||
"vuex": "^4.0.0",
|
||||
"x-sender": "^1.1.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/three": "^0.174.0",
|
||||
@@ -10106,6 +10107,12 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/x-sender": {
|
||||
"version": "1.1.6",
|
||||
"resolved": "https://registry.npmjs.org/x-sender/-/x-sender-1.1.6.tgz",
|
||||
"integrity": "sha512-es24YnTY1+g3TdDVrEgRVW8uW2nYPyHjQveBgZxk8JrB7809yd8AkYptrLgqL1trpUZtMILVW+2GIoB0V5HfVQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/xml-name-validator": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmmirror.com/xml-name-validator/-/xml-name-validator-4.0.0.tgz",
|
||||
|
||||
@@ -41,7 +41,8 @@
|
||||
"vue-i18n": "^9.6.1",
|
||||
"vue-router": "^4.0.3",
|
||||
"vuedraggable": "^4.1.0",
|
||||
"vuex": "^4.0.0"
|
||||
"vuex": "^4.0.0",
|
||||
"x-sender": "^1.1.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/three": "^0.174.0",
|
||||
@@ -105,4 +106,4 @@
|
||||
"not dead",
|
||||
"not ie 11"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
427
public/sketch_bar_chart.html
Normal file
@@ -0,0 +1,427 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>style category</title>
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.1/dist/chart.umd.min.js"></script>
|
||||
<style>
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-family: sans-serif;
|
||||
box-sizing: border-box;
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
.viewport {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
overflow: auto;
|
||||
background-color: #f9f9f9;
|
||||
cursor: grab;
|
||||
scrollbar-width: thick;
|
||||
scrollbar-color: #666 #eee;
|
||||
}
|
||||
.viewport::-webkit-scrollbar {
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
}
|
||||
.viewport::-webkit-scrollbar-track {
|
||||
background: #eee;
|
||||
border-radius: 8px;
|
||||
}
|
||||
.viewport::-webkit-scrollbar-thumb {
|
||||
background: #666;
|
||||
border-radius: 8px;
|
||||
border: 3px solid #eee;
|
||||
}
|
||||
.viewport::-webkit-scrollbar-thumb:hover {
|
||||
background: #333;
|
||||
}
|
||||
.content-size {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.content {
|
||||
padding: 30px;
|
||||
transform-origin: top left;
|
||||
width: max-content;
|
||||
min-width: 100%;
|
||||
}
|
||||
h1 {
|
||||
text-align: center;
|
||||
font-size: 100px;
|
||||
margin: 40px 0 60px;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
}
|
||||
.chart-section {
|
||||
margin-bottom: 80px;
|
||||
background: #fff;
|
||||
border-radius: 16px;
|
||||
padding: 30px;
|
||||
box-shadow: 0 6px 20px rgba(0,0,0,0.08);
|
||||
}
|
||||
h2 {
|
||||
text-align: center;
|
||||
font-size: 80px;
|
||||
margin: 0 0 40px;
|
||||
font-weight: bold;
|
||||
color: #444;
|
||||
}
|
||||
.chart-container {
|
||||
overflow-x: auto;
|
||||
width: 100%;
|
||||
min-width: 8000px; /* 适配20倍组间空隙,大幅扩大容器宽度 */
|
||||
min-height: 1900px;
|
||||
scrollbar-width: thick;
|
||||
scrollbar-color: #666 #eee;
|
||||
padding-bottom: 100px;
|
||||
}
|
||||
/* 自定义滚动条 */
|
||||
.chart-container::-webkit-scrollbar {
|
||||
height: 16px;
|
||||
}
|
||||
.chart-container::-webkit-scrollbar-track {
|
||||
background: #eee;
|
||||
border-radius: 8px;
|
||||
}
|
||||
.chart-container::-webkit-scrollbar-thumb {
|
||||
background: #666;
|
||||
border-radius: 8px;
|
||||
border: 3px solid #eee;
|
||||
}
|
||||
.chart-container::-webkit-scrollbar-thumb:hover {
|
||||
background: #333;
|
||||
}
|
||||
canvas {
|
||||
width: 100%;
|
||||
height: 1800px !important;
|
||||
background: #fff;
|
||||
border: 2px solid #ddd;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 4px 16px rgba(0,0,0,0.1);
|
||||
}
|
||||
/* 响应式调整:保持默认缩放30%,不额外调整 */
|
||||
@media (max-width: 1200px) {
|
||||
.chart-container {
|
||||
min-height: 1900px;
|
||||
}
|
||||
canvas {
|
||||
height: 1800px !important;
|
||||
}
|
||||
h1 {
|
||||
font-size: 48px;
|
||||
}
|
||||
h2 {
|
||||
font-size: 36px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<!-- 禁止页面缩放的meta标签 -->
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
|
||||
</head>
|
||||
<body>
|
||||
<div id="viewport" class="viewport">
|
||||
<div id="content-size" class="content-size">
|
||||
<div id="content" class="content">
|
||||
<h1>style category</h1>
|
||||
|
||||
<div class="chart-section">
|
||||
<h2>1. ALL </h2>
|
||||
<div class="chart-container">
|
||||
<canvas id="chartAll"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="chart-section">
|
||||
<h2>2. Male </h2>
|
||||
<div class="chart-container">
|
||||
<canvas id="chartMale"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="chart-section">
|
||||
<h2>3. Female </h2>
|
||||
<div class="chart-container">
|
||||
<canvas id="chartFemale"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const viewport = document.getElementById('viewport');
|
||||
const content = document.getElementById('content');
|
||||
const contentSize = document.getElementById('content-size');
|
||||
let MIN_SCALE = 1;
|
||||
const MAX_SCALE = 3;
|
||||
let scale = 1;
|
||||
function computeMinScale() {
|
||||
const cw = content.offsetWidth;
|
||||
const vw = viewport.clientWidth;
|
||||
if (!cw || !vw) return 1;
|
||||
return Math.min(MAX_SCALE, Math.max(0.2, vw / cw));
|
||||
}
|
||||
function updateWrapperSize() {
|
||||
const w = content.offsetWidth * scale;
|
||||
const h = content.offsetHeight * scale;
|
||||
contentSize.style.width = w + 'px';
|
||||
contentSize.style.height = h + 'px';
|
||||
}
|
||||
function applyScale(newScale, ax, ay) {
|
||||
const prev = scale;
|
||||
const target = Math.max(MIN_SCALE, Math.min(MAX_SCALE, newScale));
|
||||
if (target === prev) return;
|
||||
const ratio = target / prev;
|
||||
const rect = viewport.getBoundingClientRect();
|
||||
const anchorX = ax != null ? ax : viewport.scrollLeft + viewport.clientWidth / 2;
|
||||
const anchorY = ay != null ? ay : viewport.scrollTop + viewport.clientHeight / 2;
|
||||
scale = target;
|
||||
content.style.transform = 'scale(' + scale + ')';
|
||||
updateWrapperSize();
|
||||
let newLeft = anchorX * ratio - viewport.clientWidth / 2;
|
||||
let newTop = anchorY * ratio - viewport.clientHeight / 2;
|
||||
const maxLeft = Math.max(0, contentSize.scrollWidth - viewport.clientWidth);
|
||||
const maxTop = Math.max(0, contentSize.scrollHeight - viewport.clientHeight);
|
||||
viewport.scrollLeft = Math.max(0, Math.min(maxLeft, newLeft));
|
||||
viewport.scrollTop = Math.max(0, Math.min(maxTop, newTop));
|
||||
}
|
||||
function initScale() {
|
||||
MIN_SCALE = computeMinScale();
|
||||
scale = MIN_SCALE;
|
||||
content.style.transform = 'scale(' + scale + ')';
|
||||
updateWrapperSize();
|
||||
}
|
||||
initScale();
|
||||
|
||||
let dragging = false;
|
||||
let sx = 0, sy = 0, sl = 0, st = 0;
|
||||
viewport.addEventListener('mousedown', function(e) {
|
||||
if (e.button !== 0) return;
|
||||
dragging = true;
|
||||
viewport.style.cursor = 'grabbing';
|
||||
sx = e.clientX;
|
||||
sy = e.clientY;
|
||||
sl = viewport.scrollLeft;
|
||||
st = viewport.scrollTop;
|
||||
});
|
||||
window.addEventListener('mousemove', function(e) {
|
||||
if (!dragging) return;
|
||||
viewport.scrollLeft = sl - (e.clientX - sx);
|
||||
viewport.scrollTop = st - (e.clientY - sy);
|
||||
});
|
||||
window.addEventListener('mouseup', function() {
|
||||
dragging = false;
|
||||
viewport.style.cursor = '';
|
||||
});
|
||||
|
||||
viewport.addEventListener('wheel', function(e) {
|
||||
if (e.ctrlKey || e.metaKey) {
|
||||
e.preventDefault();
|
||||
const factor = e.deltaY < 0 ? 1.1 : 0.9;
|
||||
const rect = viewport.getBoundingClientRect();
|
||||
const ax = viewport.scrollLeft + (e.clientX - rect.left);
|
||||
const ay = viewport.scrollTop + (e.clientY - rect.top);
|
||||
const next = scale * factor;
|
||||
applyScale(next < MIN_SCALE ? MIN_SCALE : next, ax, ay);
|
||||
}
|
||||
}, { passive: false });
|
||||
|
||||
window.addEventListener('resize', function() {
|
||||
const prevMin = MIN_SCALE;
|
||||
MIN_SCALE = computeMinScale();
|
||||
if (scale < MIN_SCALE) {
|
||||
applyScale(MIN_SCALE);
|
||||
} else {
|
||||
updateWrapperSize();
|
||||
}
|
||||
});
|
||||
window.addEventListener('load', function() {
|
||||
initScale();
|
||||
});
|
||||
});
|
||||
|
||||
// 共用配置 - 保持原有标签处理逻辑(下划线换行)
|
||||
const labels = [
|
||||
'ACADEMIC','BUSINESS','CASUAL','COUNTRY_STYLE','DOPAMINE','ETHNIC','FUTURISM',
|
||||
'GOTHIC','LOLITA','MERLAD','MINIMALISM','NEW_CHINESE','OUTDOOR_FUNCTIONAL',
|
||||
'POST_APOCALYPTIC','PREPPY','ROCK','ROMANTIC','SEXY','SWEET','WABI_SABI','Y2K','民族风'
|
||||
].map(label => label.replace('_', '\n'));
|
||||
|
||||
// 所有数据(保持更新后的数值)
|
||||
const allData = {
|
||||
male_tops: [0,686,638,491,128,11,366,35,0,20,313,126,359,166,385,187,6,3,3,219,282,0],
|
||||
male_bottoms: [0,280,199,141,132,1,43,49,0,13,178,93,279,10,96,25,0,5,0,163,239,0],
|
||||
male_outwear: [0,2442,2147,1245,161,19,671,216,0,58,471,168,1001,319,803,367,11,1,1,278,631,0],
|
||||
female_dress: [260,1030,4322,1158,256,0,397,340,488,279,1104,312,215,170,0,223,990,607,1438,293,292,159],
|
||||
female_skirt: [408,662,1177,633,214,0,381,280,278,308,358,200,297,209,0,231,584,233,714,246,385,95],
|
||||
female_blouse: [618,1275,3786,710,385,0,533,412,454,453,616,221,852,181,0,437,869,533,899,336,991,169],
|
||||
female_outwear: [267,1255,740,453,178,0,418,160,101,301,273,172,712,172,0,245,198,13,159,280,500,76],
|
||||
female_trousers: [171,782,1899,391,232,0,267,64,137,293,351,141,865,101,0,189,654,137,319,299,427,96]
|
||||
};
|
||||
|
||||
// 颜色配置(保持原有颜色)
|
||||
const colors = {
|
||||
male_tops: '#1f77b4',
|
||||
male_bottoms: '#ff7f0e',
|
||||
male_outwear: '#2ca02c',
|
||||
female_dress: '#d62728',
|
||||
female_skirt: '#9467bd',
|
||||
female_blouse: '#8c564b',
|
||||
female_outwear: '#e377c2',
|
||||
female_trousers: '#7f7f7f'
|
||||
};
|
||||
|
||||
// 图表基础配置 - 核心修改:categoryPercentage设为0.04(原0.8的1/20),扩大组间空隙20倍
|
||||
const baseChartConfig = {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
plugins: {
|
||||
legend: {
|
||||
position: 'top',
|
||||
labels: {
|
||||
font: { size: 60, weight: 'bold' },
|
||||
padding: 60,
|
||||
boxWidth: 60
|
||||
},
|
||||
padding: { bottom: 60 }
|
||||
},
|
||||
tooltip: {
|
||||
mode: 'index',
|
||||
intersect: false,
|
||||
padding: 30,
|
||||
titleFont: { size: 60 },
|
||||
bodyFont: { size: 42 },
|
||||
boxPadding: 20,
|
||||
cornerRadius: 12
|
||||
}
|
||||
},
|
||||
scales: {
|
||||
x: {
|
||||
stacked: false,
|
||||
title: {
|
||||
display: true,
|
||||
text: '',
|
||||
font: { size: 1, weight: 'bold' },
|
||||
padding: { top: 1, bottom: 1 }
|
||||
},
|
||||
ticks: {
|
||||
maxRotation: 0, // 保持原有斜放角度(向左下45度)
|
||||
minRotation: 0, // 强制固定角度
|
||||
autoSkip: false,
|
||||
font: { size: 28, weight: 'bold' },
|
||||
padding: 150,
|
||||
color: '#333',
|
||||
lineHeight: 1.3,
|
||||
align: 'right' // 斜放标签右对齐,提升可读性
|
||||
},
|
||||
grid: { display: false },
|
||||
border: { width: 3 },
|
||||
categoryPercentage: 0.5, // 核心修改:原0.8 → 0.04,组间空隙扩大20倍
|
||||
barPercentage: 0.8, // 保持组内柱子宽度不变
|
||||
},
|
||||
y: {
|
||||
beginAtZero: true,
|
||||
title: {
|
||||
display: true,
|
||||
text: '',
|
||||
font: { size: 1, weight: 'bold' },
|
||||
padding: { right: 1 }
|
||||
},
|
||||
ticks: {
|
||||
font: { size: 33, weight: 'bold' },
|
||||
padding: 30,
|
||||
color: '#333',
|
||||
stepSize: 500 // 适配更大数值范围
|
||||
},
|
||||
grid: { color: '#e0e0e0', lineWidth: 3 },
|
||||
border: { width: 3 }
|
||||
}
|
||||
},
|
||||
layout: {
|
||||
padding: { top: 60, right: 90, bottom: 100, left: 90 }
|
||||
},
|
||||
animation: { duration: 1500, easing: 'easeOutQuart' },
|
||||
barThickness: 'flex',
|
||||
maxBarThickness: 70,
|
||||
minBarLength: 5
|
||||
};
|
||||
|
||||
// 1. 创建综合图表
|
||||
new Chart(document.getElementById('chartAll'), {
|
||||
type: 'bar',
|
||||
data: {
|
||||
labels: labels,
|
||||
datasets: Object.keys(allData).map(key => ({
|
||||
label: key,
|
||||
data: allData[key],
|
||||
backgroundColor: colors[key]
|
||||
}))
|
||||
},
|
||||
options: { ...baseChartConfig }
|
||||
});
|
||||
|
||||
// 2. 创建男性分类图表
|
||||
new Chart(document.getElementById('chartMale'), {
|
||||
type: 'bar',
|
||||
data: {
|
||||
labels: labels,
|
||||
datasets: [
|
||||
{ label: 'male_tops', data: allData.male_tops, backgroundColor: colors.male_tops },
|
||||
{ label: 'male_bottoms', data: allData.male_bottoms, backgroundColor: colors.male_bottoms },
|
||||
{ label: 'male_outwear', data: allData.male_outwear, backgroundColor: colors.male_outwear }
|
||||
]
|
||||
},
|
||||
options: {
|
||||
...baseChartConfig,
|
||||
scales: {
|
||||
...baseChartConfig.scales,
|
||||
x: {
|
||||
...baseChartConfig.scales.x,
|
||||
categoryPercentage: 0.35
|
||||
},
|
||||
y: {
|
||||
...baseChartConfig.scales.y,
|
||||
stepSize: 800 // 适配男性外套最大值2442
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 3. 创建女性分类图表
|
||||
new Chart(document.getElementById('chartFemale'), {
|
||||
type: 'bar',
|
||||
data: {
|
||||
labels: labels,
|
||||
datasets: [
|
||||
{ label: 'female_dress', data: allData.female_dress, backgroundColor: colors.female_dress },
|
||||
{ label: 'female_skirt', data: allData.female_skirt, backgroundColor: colors.female_skirt },
|
||||
{ label: 'female_blouse', data: allData.female_blouse, backgroundColor: colors.female_blouse },
|
||||
{ label: 'female_outwear', data: allData.female_outwear, backgroundColor: colors.female_outwear },
|
||||
{ label: 'female_trousers', data: allData.female_trousers, backgroundColor: colors.female_trousers }
|
||||
]
|
||||
},
|
||||
options: {
|
||||
...baseChartConfig,
|
||||
scales: {
|
||||
...baseChartConfig.scales,
|
||||
x: {
|
||||
...baseChartConfig.scales.x,
|
||||
categoryPercentage: 0.28
|
||||
},
|
||||
y: {
|
||||
...baseChartConfig.scales.y,
|
||||
stepSize: 1000 // 适配女性连衣裙最大值4322
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
539
src/assets/iconfont2/demo.css
Normal file
@@ -0,0 +1,539 @@
|
||||
/* Logo 字体 */
|
||||
@font-face {
|
||||
font-family: "iconfont logo";
|
||||
src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834');
|
||||
src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834#iefix') format('embedded-opentype'),
|
||||
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.woff?t=1545807318834') format('woff'),
|
||||
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.ttf?t=1545807318834') format('truetype'),
|
||||
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.svg?t=1545807318834#iconfont') format('svg');
|
||||
}
|
||||
|
||||
.logo {
|
||||
font-family: "iconfont logo";
|
||||
font-size: 160px;
|
||||
font-style: normal;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
/* tabs */
|
||||
.nav-tabs {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.nav-tabs .nav-more {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
height: 42px;
|
||||
line-height: 42px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
#tabs {
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
|
||||
#tabs li {
|
||||
cursor: pointer;
|
||||
width: 100px;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
text-align: center;
|
||||
font-size: 16px;
|
||||
border-bottom: 2px solid transparent;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
margin-bottom: -1px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
|
||||
#tabs .active {
|
||||
border-bottom-color: #f00;
|
||||
color: #222;
|
||||
}
|
||||
|
||||
.tab-container .content {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* 页面布局 */
|
||||
.main {
|
||||
padding: 30px 100px;
|
||||
width: 960px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.main .logo {
|
||||
color: #333;
|
||||
text-align: left;
|
||||
margin-bottom: 30px;
|
||||
line-height: 1;
|
||||
height: 110px;
|
||||
margin-top: -50px;
|
||||
overflow: hidden;
|
||||
*zoom: 1;
|
||||
}
|
||||
|
||||
.main .logo a {
|
||||
font-size: 160px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.helps {
|
||||
margin-top: 40px;
|
||||
}
|
||||
|
||||
.helps pre {
|
||||
padding: 20px;
|
||||
margin: 10px 0;
|
||||
border: solid 1px #e7e1cd;
|
||||
background-color: #fffdef;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.icon_lists {
|
||||
width: 100% !important;
|
||||
overflow: hidden;
|
||||
*zoom: 1;
|
||||
}
|
||||
|
||||
.icon_lists li {
|
||||
width: 100px;
|
||||
margin-bottom: 10px;
|
||||
margin-right: 20px;
|
||||
text-align: center;
|
||||
list-style: none !important;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.icon_lists li .code-name {
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.icon_lists .icon {
|
||||
display: block;
|
||||
height: 100px;
|
||||
line-height: 100px;
|
||||
font-size: 42px;
|
||||
margin: 10px auto;
|
||||
color: #333;
|
||||
-webkit-transition: font-size 0.25s linear, width 0.25s linear;
|
||||
-moz-transition: font-size 0.25s linear, width 0.25s linear;
|
||||
transition: font-size 0.25s linear, width 0.25s linear;
|
||||
}
|
||||
|
||||
.icon_lists .icon:hover {
|
||||
font-size: 100px;
|
||||
}
|
||||
|
||||
.icon_lists .svg-icon {
|
||||
/* 通过设置 font-size 来改变图标大小 */
|
||||
width: 1em;
|
||||
/* 图标和文字相邻时,垂直对齐 */
|
||||
vertical-align: -0.15em;
|
||||
/* 通过设置 color 来改变 SVG 的颜色/fill */
|
||||
fill: currentColor;
|
||||
/* path 和 stroke 溢出 viewBox 部分在 IE 下会显示
|
||||
normalize.css 中也包含这行 */
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.icon_lists li .name,
|
||||
.icon_lists li .code-name {
|
||||
color: #666;
|
||||
}
|
||||
|
||||
/* markdown 样式 */
|
||||
.markdown {
|
||||
color: #666;
|
||||
font-size: 14px;
|
||||
line-height: 1.8;
|
||||
}
|
||||
|
||||
.highlight {
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.markdown img {
|
||||
vertical-align: middle;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.markdown h1 {
|
||||
color: #404040;
|
||||
font-weight: 500;
|
||||
line-height: 40px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.markdown h2,
|
||||
.markdown h3,
|
||||
.markdown h4,
|
||||
.markdown h5,
|
||||
.markdown h6 {
|
||||
color: #404040;
|
||||
margin: 1.6em 0 0.6em 0;
|
||||
font-weight: 500;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.markdown h1 {
|
||||
font-size: 28px;
|
||||
}
|
||||
|
||||
.markdown h2 {
|
||||
font-size: 22px;
|
||||
}
|
||||
|
||||
.markdown h3 {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.markdown h4 {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.markdown h5 {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.markdown h6 {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.markdown hr {
|
||||
height: 1px;
|
||||
border: 0;
|
||||
background: #e9e9e9;
|
||||
margin: 16px 0;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.markdown p {
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
.markdown>p,
|
||||
.markdown>blockquote,
|
||||
.markdown>.highlight,
|
||||
.markdown>ol,
|
||||
.markdown>ul {
|
||||
width: 80%;
|
||||
}
|
||||
|
||||
.markdown ul>li {
|
||||
list-style: circle;
|
||||
}
|
||||
|
||||
.markdown>ul li,
|
||||
.markdown blockquote ul>li {
|
||||
margin-left: 20px;
|
||||
padding-left: 4px;
|
||||
}
|
||||
|
||||
.markdown>ul li p,
|
||||
.markdown>ol li p {
|
||||
margin: 0.6em 0;
|
||||
}
|
||||
|
||||
.markdown ol>li {
|
||||
list-style: decimal;
|
||||
}
|
||||
|
||||
.markdown>ol li,
|
||||
.markdown blockquote ol>li {
|
||||
margin-left: 20px;
|
||||
padding-left: 4px;
|
||||
}
|
||||
|
||||
.markdown code {
|
||||
margin: 0 3px;
|
||||
padding: 0 5px;
|
||||
background: #eee;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.markdown strong,
|
||||
.markdown b {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.markdown>table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0px;
|
||||
empty-cells: show;
|
||||
border: 1px solid #e9e9e9;
|
||||
width: 95%;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.markdown>table th {
|
||||
white-space: nowrap;
|
||||
color: #333;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.markdown>table th,
|
||||
.markdown>table td {
|
||||
border: 1px solid #e9e9e9;
|
||||
padding: 8px 16px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.markdown>table th {
|
||||
background: #F7F7F7;
|
||||
}
|
||||
|
||||
.markdown blockquote {
|
||||
font-size: 90%;
|
||||
color: #999;
|
||||
border-left: 4px solid #e9e9e9;
|
||||
padding-left: 0.8em;
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
.markdown blockquote p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.markdown .anchor {
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s ease;
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.markdown .waiting {
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.markdown h1:hover .anchor,
|
||||
.markdown h2:hover .anchor,
|
||||
.markdown h3:hover .anchor,
|
||||
.markdown h4:hover .anchor,
|
||||
.markdown h5:hover .anchor,
|
||||
.markdown h6:hover .anchor {
|
||||
opacity: 1;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.markdown>br,
|
||||
.markdown>p>br {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
|
||||
.hljs {
|
||||
display: block;
|
||||
background: white;
|
||||
padding: 0.5em;
|
||||
color: #333333;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.hljs-comment,
|
||||
.hljs-meta {
|
||||
color: #969896;
|
||||
}
|
||||
|
||||
.hljs-string,
|
||||
.hljs-variable,
|
||||
.hljs-template-variable,
|
||||
.hljs-strong,
|
||||
.hljs-emphasis,
|
||||
.hljs-quote {
|
||||
color: #df5000;
|
||||
}
|
||||
|
||||
.hljs-keyword,
|
||||
.hljs-selector-tag,
|
||||
.hljs-type {
|
||||
color: #a71d5d;
|
||||
}
|
||||
|
||||
.hljs-literal,
|
||||
.hljs-symbol,
|
||||
.hljs-bullet,
|
||||
.hljs-attribute {
|
||||
color: #0086b3;
|
||||
}
|
||||
|
||||
.hljs-section,
|
||||
.hljs-name {
|
||||
color: #63a35c;
|
||||
}
|
||||
|
||||
.hljs-tag {
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.hljs-title,
|
||||
.hljs-attr,
|
||||
.hljs-selector-id,
|
||||
.hljs-selector-class,
|
||||
.hljs-selector-attr,
|
||||
.hljs-selector-pseudo {
|
||||
color: #795da3;
|
||||
}
|
||||
|
||||
.hljs-addition {
|
||||
color: #55a532;
|
||||
background-color: #eaffea;
|
||||
}
|
||||
|
||||
.hljs-deletion {
|
||||
color: #bd2c00;
|
||||
background-color: #ffecec;
|
||||
}
|
||||
|
||||
.hljs-link {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
/* 代码高亮 */
|
||||
/* PrismJS 1.15.0
|
||||
https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript */
|
||||
/**
|
||||
* prism.js default theme for JavaScript, CSS and HTML
|
||||
* Based on dabblet (http://dabblet.com)
|
||||
* @author Lea Verou
|
||||
*/
|
||||
code[class*="language-"],
|
||||
pre[class*="language-"] {
|
||||
color: black;
|
||||
background: none;
|
||||
text-shadow: 0 1px white;
|
||||
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
|
||||
text-align: left;
|
||||
white-space: pre;
|
||||
word-spacing: normal;
|
||||
word-break: normal;
|
||||
word-wrap: normal;
|
||||
line-height: 1.5;
|
||||
|
||||
-moz-tab-size: 4;
|
||||
-o-tab-size: 4;
|
||||
tab-size: 4;
|
||||
|
||||
-webkit-hyphens: none;
|
||||
-moz-hyphens: none;
|
||||
-ms-hyphens: none;
|
||||
hyphens: none;
|
||||
}
|
||||
|
||||
pre[class*="language-"]::-moz-selection,
|
||||
pre[class*="language-"] ::-moz-selection,
|
||||
code[class*="language-"]::-moz-selection,
|
||||
code[class*="language-"] ::-moz-selection {
|
||||
text-shadow: none;
|
||||
background: #b3d4fc;
|
||||
}
|
||||
|
||||
pre[class*="language-"]::selection,
|
||||
pre[class*="language-"] ::selection,
|
||||
code[class*="language-"]::selection,
|
||||
code[class*="language-"] ::selection {
|
||||
text-shadow: none;
|
||||
background: #b3d4fc;
|
||||
}
|
||||
|
||||
@media print {
|
||||
|
||||
code[class*="language-"],
|
||||
pre[class*="language-"] {
|
||||
text-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* Code blocks */
|
||||
pre[class*="language-"] {
|
||||
padding: 1em;
|
||||
margin: .5em 0;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
:not(pre)>code[class*="language-"],
|
||||
pre[class*="language-"] {
|
||||
background: #f5f2f0;
|
||||
}
|
||||
|
||||
/* Inline code */
|
||||
:not(pre)>code[class*="language-"] {
|
||||
padding: .1em;
|
||||
border-radius: .3em;
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
.token.comment,
|
||||
.token.prolog,
|
||||
.token.doctype,
|
||||
.token.cdata {
|
||||
color: slategray;
|
||||
}
|
||||
|
||||
.token.punctuation {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.namespace {
|
||||
opacity: .7;
|
||||
}
|
||||
|
||||
.token.property,
|
||||
.token.tag,
|
||||
.token.boolean,
|
||||
.token.number,
|
||||
.token.constant,
|
||||
.token.symbol,
|
||||
.token.deleted {
|
||||
color: #905;
|
||||
}
|
||||
|
||||
.token.selector,
|
||||
.token.attr-name,
|
||||
.token.string,
|
||||
.token.char,
|
||||
.token.builtin,
|
||||
.token.inserted {
|
||||
color: #690;
|
||||
}
|
||||
|
||||
.token.operator,
|
||||
.token.entity,
|
||||
.token.url,
|
||||
.language-css .token.string,
|
||||
.style .token.string {
|
||||
color: #9a6e3a;
|
||||
background: hsla(0, 0%, 100%, .5);
|
||||
}
|
||||
|
||||
.token.atrule,
|
||||
.token.attr-value,
|
||||
.token.keyword {
|
||||
color: #07a;
|
||||
}
|
||||
|
||||
.token.function,
|
||||
.token.class-name {
|
||||
color: #DD4A68;
|
||||
}
|
||||
|
||||
.token.regex,
|
||||
.token.important,
|
||||
.token.variable {
|
||||
color: #e90;
|
||||
}
|
||||
|
||||
.token.important,
|
||||
.token.bold {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.token.italic {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.token.entity {
|
||||
cursor: help;
|
||||
}
|
||||
970
src/assets/iconfont2/demo_index.html
Normal file
@@ -0,0 +1,970 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<title>iconfont Demo</title>
|
||||
<link rel="shortcut icon" href="//img.alicdn.com/imgextra/i4/O1CN01Z5paLz1O0zuCC7osS_!!6000000001644-55-tps-83-82.svg" type="image/x-icon"/>
|
||||
<link rel="icon" type="image/svg+xml" href="//img.alicdn.com/imgextra/i4/O1CN01Z5paLz1O0zuCC7osS_!!6000000001644-55-tps-83-82.svg"/>
|
||||
<link rel="stylesheet" href="https://g.alicdn.com/thx/cube/1.3.2/cube.min.css">
|
||||
<link rel="stylesheet" href="demo.css">
|
||||
<link rel="stylesheet" href="iconfont.css">
|
||||
<script src="iconfont.js"></script>
|
||||
<!-- jQuery -->
|
||||
<script src="https://a1.alicdn.com/oss/uploads/2018/12/26/7bfddb60-08e8-11e9-9b04-53e73bb6408b.js"></script>
|
||||
<!-- 代码高亮 -->
|
||||
<script src="https://a1.alicdn.com/oss/uploads/2018/12/26/a3f714d0-08e6-11e9-8a15-ebf944d7534c.js"></script>
|
||||
<style>
|
||||
.main .logo {
|
||||
margin-top: 0;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.main .logo a {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.main .logo .sub-title {
|
||||
margin-left: 0.5em;
|
||||
font-size: 22px;
|
||||
color: #fff;
|
||||
background: linear-gradient(-45deg, #3967FF, #B500FE);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="main">
|
||||
<h1 class="logo"><a href="https://www.iconfont.cn/" title="iconfont 首页" target="_blank">
|
||||
<img width="200" src="https://img.alicdn.com/imgextra/i3/O1CN01Mn65HV1FfSEzR6DKv_!!6000000000514-55-tps-228-59.svg">
|
||||
|
||||
</a></h1>
|
||||
<div class="nav-tabs">
|
||||
<ul id="tabs" class="dib-box">
|
||||
<li class="dib active"><span>Unicode</span></li>
|
||||
<li class="dib"><span>Font class</span></li>
|
||||
<li class="dib"><span>Symbol</span></li>
|
||||
</ul>
|
||||
|
||||
<a href="https://www.iconfont.cn/manage/index?manage_type=myprojects&projectId=4292253" target="_blank" class="nav-more">查看项目</a>
|
||||
|
||||
</div>
|
||||
<div class="tab-container">
|
||||
<div class="content unicode" style="display: block;">
|
||||
<ul class="icon_lists dib-box">
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">裁剪</div>
|
||||
<div class="code-name">&#xe650;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">角度</div>
|
||||
<div class="code-name">&#xe60a;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">水平翻转</div>
|
||||
<div class="code-name">&#xe69e;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">垂直翻转</div>
|
||||
<div class="code-name">&#xec60;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">clothes</div>
|
||||
<div class="code-name">&#xe8d1;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">材质</div>
|
||||
<div class="code-name">&#xe647;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">IC-液化</div>
|
||||
<div class="code-name">&#xe61b;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">上一层</div>
|
||||
<div class="code-name">&#xe751;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">上一层</div>
|
||||
<div class="code-name">&#xe604;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">下一层</div>
|
||||
<div class="code-name">&#xe68a;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">上一层</div>
|
||||
<div class="code-name">&#xe68b;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">审批</div>
|
||||
<div class="code-name">&#xe6a1;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">用户</div>
|
||||
<div class="code-name">&#xe617;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">使用次数</div>
|
||||
<div class="code-name">&#xe601;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">下拉</div>
|
||||
<div class="code-name">&#xe634;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">编辑</div>
|
||||
<div class="code-name">&#xe600;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">圆形</div>
|
||||
<div class="code-name">&#xe64f;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">三角形</div>
|
||||
<div class="code-name">&#xe615;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">图层</div>
|
||||
<div class="code-name">&#xe632;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">平移</div>
|
||||
<div class="code-name">&#xe616;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">橡皮</div>
|
||||
<div class="code-name">&#xe67b;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">tx-fill-椭圆形</div>
|
||||
<div class="code-name">&#xe64c;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">直线</div>
|
||||
<div class="code-name">&#xe602;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">线</div>
|
||||
<div class="code-name">&#xec5f;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">正方形</div>
|
||||
<div class="code-name">&#xea6f;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">图层</div>
|
||||
<div class="code-name">&#xe62d;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">点位</div>
|
||||
<div class="code-name">&#xe685;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">并集</div>
|
||||
<div class="code-name">&#xe620;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">并集</div>
|
||||
<div class="code-name">&#xe668;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">标签</div>
|
||||
<div class="code-name">&#xe603;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">语言</div>
|
||||
<div class="code-name">&#xe85f;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">撤销 返回 撤回 上一步</div>
|
||||
<div class="code-name">&#xe626;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">撤销 返回 撤回 上一步</div>
|
||||
<div class="code-name">&#xe609;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">外套_长款外套1@1x</div>
|
||||
<div class="code-name">&#xe66c;</div>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
<div class="article markdown">
|
||||
<h2 id="unicode-">Unicode 引用</h2>
|
||||
<hr>
|
||||
|
||||
<p>Unicode 是字体在网页端最原始的应用方式,特点是:</p>
|
||||
<ul>
|
||||
<li>支持按字体的方式去动态调整图标大小,颜色等等。</li>
|
||||
<li>默认情况下不支持多色,直接添加多色图标会自动去色。</li>
|
||||
</ul>
|
||||
<blockquote>
|
||||
<p>注意:新版 iconfont 支持两种方式引用多色图标:SVG symbol 引用方式和彩色字体图标模式。(使用彩色字体图标需要在「编辑项目」中开启「彩色」选项后并重新生成。)</p>
|
||||
</blockquote>
|
||||
<p>Unicode 使用步骤如下:</p>
|
||||
<h3 id="-font-face">第一步:拷贝项目下面生成的 <code>@font-face</code></h3>
|
||||
<pre><code class="language-css"
|
||||
>@font-face {
|
||||
font-family: 'iconfont';
|
||||
src: url('iconfont.woff2?t=1762934152017') format('woff2'),
|
||||
url('iconfont.woff?t=1762934152017') format('woff'),
|
||||
url('iconfont.ttf?t=1762934152017') format('truetype');
|
||||
}
|
||||
</code></pre>
|
||||
<h3 id="-iconfont-">第二步:定义使用 iconfont 的样式</h3>
|
||||
<pre><code class="language-css"
|
||||
>.iconfont {
|
||||
font-family: "iconfont" !important;
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
</code></pre>
|
||||
<h3 id="-">第三步:挑选相应图标并获取字体编码,应用于页面</h3>
|
||||
<pre>
|
||||
<code class="language-html"
|
||||
><span class="iconfont">&#x33;</span>
|
||||
</code></pre>
|
||||
<blockquote>
|
||||
<p>"iconfont" 是你项目下的 font-family。可以通过编辑项目查看,默认是 "iconfont"。</p>
|
||||
</blockquote>
|
||||
</div>
|
||||
</div>
|
||||
<div class="content font-class">
|
||||
<ul class="icon_lists dib-box">
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont icon-caijian"></span>
|
||||
<div class="name">
|
||||
裁剪
|
||||
</div>
|
||||
<div class="code-name">.icon-caijian
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont icon-angle"></span>
|
||||
<div class="name">
|
||||
角度
|
||||
</div>
|
||||
<div class="code-name">.icon-angle
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont icon-flip-horizontal"></span>
|
||||
<div class="name">
|
||||
水平翻转
|
||||
</div>
|
||||
<div class="code-name">.icon-flip-horizontal
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont icon-flip-vertical"></span>
|
||||
<div class="name">
|
||||
垂直翻转
|
||||
</div>
|
||||
<div class="code-name">.icon-flip-vertical
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont icon-clothes"></span>
|
||||
<div class="name">
|
||||
clothes
|
||||
</div>
|
||||
<div class="code-name">.icon-clothes
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont icon-caizhi"></span>
|
||||
<div class="name">
|
||||
材质
|
||||
</div>
|
||||
<div class="code-name">.icon-caizhi
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont icon-IC-yehua"></span>
|
||||
<div class="name">
|
||||
IC-液化
|
||||
</div>
|
||||
<div class="code-name">.icon-IC-yehua
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont icon-shangyiceng"></span>
|
||||
<div class="name">
|
||||
上一层
|
||||
</div>
|
||||
<div class="code-name">.icon-shangyiceng
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont icon-shangyiceng1"></span>
|
||||
<div class="name">
|
||||
上一层
|
||||
</div>
|
||||
<div class="code-name">.icon-shangyiceng1
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont icon-xiayiceng"></span>
|
||||
<div class="name">
|
||||
下一层
|
||||
</div>
|
||||
<div class="code-name">.icon-xiayiceng
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont icon-shangyiceng2"></span>
|
||||
<div class="name">
|
||||
上一层
|
||||
</div>
|
||||
<div class="code-name">.icon-shangyiceng2
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont icon-shenpi"></span>
|
||||
<div class="name">
|
||||
审批
|
||||
</div>
|
||||
<div class="code-name">.icon-shenpi
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont icon-yonghu"></span>
|
||||
<div class="name">
|
||||
用户
|
||||
</div>
|
||||
<div class="code-name">.icon-yonghu
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont icon-usetime"></span>
|
||||
<div class="name">
|
||||
使用次数
|
||||
</div>
|
||||
<div class="code-name">.icon-usetime
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont icon-xiala"></span>
|
||||
<div class="name">
|
||||
下拉
|
||||
</div>
|
||||
<div class="code-name">.icon-xiala
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont icon-bianji"></span>
|
||||
<div class="name">
|
||||
编辑
|
||||
</div>
|
||||
<div class="code-name">.icon-bianji
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont icon-circle"></span>
|
||||
<div class="name">
|
||||
圆形
|
||||
</div>
|
||||
<div class="code-name">.icon-circle
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont icon-sanjiaoxing"></span>
|
||||
<div class="name">
|
||||
三角形
|
||||
</div>
|
||||
<div class="code-name">.icon-sanjiaoxing
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont icon-tuceng"></span>
|
||||
<div class="name">
|
||||
图层
|
||||
</div>
|
||||
<div class="code-name">.icon-tuceng
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont icon-move"></span>
|
||||
<div class="name">
|
||||
平移
|
||||
</div>
|
||||
<div class="code-name">.icon-move
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont icon-xiangpi_huaban1"></span>
|
||||
<div class="name">
|
||||
橡皮
|
||||
</div>
|
||||
<div class="code-name">.icon-xiangpi_huaban1
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont icon-tx-fill-tuoyuanxing"></span>
|
||||
<div class="name">
|
||||
tx-fill-椭圆形
|
||||
</div>
|
||||
<div class="code-name">.icon-tx-fill-tuoyuanxing
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont icon-zhixian"></span>
|
||||
<div class="name">
|
||||
直线
|
||||
</div>
|
||||
<div class="code-name">.icon-zhixian
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont icon-xian"></span>
|
||||
<div class="name">
|
||||
线
|
||||
</div>
|
||||
<div class="code-name">.icon-xian
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont icon-checkbox-full"></span>
|
||||
<div class="name">
|
||||
正方形
|
||||
</div>
|
||||
<div class="code-name">.icon-checkbox-full
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont icon-tuceng1"></span>
|
||||
<div class="name">
|
||||
图层
|
||||
</div>
|
||||
<div class="code-name">.icon-tuceng1
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont icon-dianwei"></span>
|
||||
<div class="name">
|
||||
点位
|
||||
</div>
|
||||
<div class="code-name">.icon-dianwei
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont icon-bingji"></span>
|
||||
<div class="name">
|
||||
并集
|
||||
</div>
|
||||
<div class="code-name">.icon-bingji
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont icon-bingji1"></span>
|
||||
<div class="name">
|
||||
并集
|
||||
</div>
|
||||
<div class="code-name">.icon-bingji1
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont icon-biaoqian"></span>
|
||||
<div class="name">
|
||||
标签
|
||||
</div>
|
||||
<div class="code-name">.icon-biaoqian
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont icon-yuyan"></span>
|
||||
<div class="name">
|
||||
语言
|
||||
</div>
|
||||
<div class="code-name">.icon-yuyan
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont icon-fanchehui"></span>
|
||||
<div class="name">
|
||||
撤销 返回 撤回 上一步
|
||||
</div>
|
||||
<div class="code-name">.icon-fanchehui
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont icon-chehui"></span>
|
||||
<div class="name">
|
||||
撤销 返回 撤回 上一步
|
||||
</div>
|
||||
<div class="code-name">.icon-chehui
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont icon-a-waitao_changkuanwaitao11x"></span>
|
||||
<div class="name">
|
||||
外套_长款外套1@1x
|
||||
</div>
|
||||
<div class="code-name">.icon-a-waitao_changkuanwaitao11x
|
||||
</div>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
<div class="article markdown">
|
||||
<h2 id="font-class-">font-class 引用</h2>
|
||||
<hr>
|
||||
|
||||
<p>font-class 是 Unicode 使用方式的一种变种,主要是解决 Unicode 书写不直观,语意不明确的问题。</p>
|
||||
<p>与 Unicode 使用方式相比,具有如下特点:</p>
|
||||
<ul>
|
||||
<li>相比于 Unicode 语意明确,书写更直观。可以很容易分辨这个 icon 是什么。</li>
|
||||
<li>因为使用 class 来定义图标,所以当要替换图标时,只需要修改 class 里面的 Unicode 引用。</li>
|
||||
</ul>
|
||||
<p>使用步骤如下:</p>
|
||||
<h3 id="-fontclass-">第一步:引入项目下面生成的 fontclass 代码:</h3>
|
||||
<pre><code class="language-html"><link rel="stylesheet" href="./iconfont.css">
|
||||
</code></pre>
|
||||
<h3 id="-">第二步:挑选相应图标并获取类名,应用于页面:</h3>
|
||||
<pre><code class="language-html"><span class="iconfont icon-xxx"></span>
|
||||
</code></pre>
|
||||
<blockquote>
|
||||
<p>"
|
||||
iconfont" 是你项目下的 font-family。可以通过编辑项目查看,默认是 "iconfont"。</p>
|
||||
</blockquote>
|
||||
</div>
|
||||
</div>
|
||||
<div class="content symbol">
|
||||
<ul class="icon_lists dib-box">
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#icon-caijian"></use>
|
||||
</svg>
|
||||
<div class="name">裁剪</div>
|
||||
<div class="code-name">#icon-caijian</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#icon-angle"></use>
|
||||
</svg>
|
||||
<div class="name">角度</div>
|
||||
<div class="code-name">#icon-angle</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#icon-flip-horizontal"></use>
|
||||
</svg>
|
||||
<div class="name">水平翻转</div>
|
||||
<div class="code-name">#icon-flip-horizontal</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#icon-flip-vertical"></use>
|
||||
</svg>
|
||||
<div class="name">垂直翻转</div>
|
||||
<div class="code-name">#icon-flip-vertical</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#icon-clothes"></use>
|
||||
</svg>
|
||||
<div class="name">clothes</div>
|
||||
<div class="code-name">#icon-clothes</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#icon-caizhi"></use>
|
||||
</svg>
|
||||
<div class="name">材质</div>
|
||||
<div class="code-name">#icon-caizhi</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#icon-IC-yehua"></use>
|
||||
</svg>
|
||||
<div class="name">IC-液化</div>
|
||||
<div class="code-name">#icon-IC-yehua</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#icon-shangyiceng"></use>
|
||||
</svg>
|
||||
<div class="name">上一层</div>
|
||||
<div class="code-name">#icon-shangyiceng</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#icon-shangyiceng1"></use>
|
||||
</svg>
|
||||
<div class="name">上一层</div>
|
||||
<div class="code-name">#icon-shangyiceng1</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#icon-xiayiceng"></use>
|
||||
</svg>
|
||||
<div class="name">下一层</div>
|
||||
<div class="code-name">#icon-xiayiceng</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#icon-shangyiceng2"></use>
|
||||
</svg>
|
||||
<div class="name">上一层</div>
|
||||
<div class="code-name">#icon-shangyiceng2</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#icon-shenpi"></use>
|
||||
</svg>
|
||||
<div class="name">审批</div>
|
||||
<div class="code-name">#icon-shenpi</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#icon-yonghu"></use>
|
||||
</svg>
|
||||
<div class="name">用户</div>
|
||||
<div class="code-name">#icon-yonghu</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#icon-usetime"></use>
|
||||
</svg>
|
||||
<div class="name">使用次数</div>
|
||||
<div class="code-name">#icon-usetime</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#icon-xiala"></use>
|
||||
</svg>
|
||||
<div class="name">下拉</div>
|
||||
<div class="code-name">#icon-xiala</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#icon-bianji"></use>
|
||||
</svg>
|
||||
<div class="name">编辑</div>
|
||||
<div class="code-name">#icon-bianji</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#icon-circle"></use>
|
||||
</svg>
|
||||
<div class="name">圆形</div>
|
||||
<div class="code-name">#icon-circle</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#icon-sanjiaoxing"></use>
|
||||
</svg>
|
||||
<div class="name">三角形</div>
|
||||
<div class="code-name">#icon-sanjiaoxing</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#icon-tuceng"></use>
|
||||
</svg>
|
||||
<div class="name">图层</div>
|
||||
<div class="code-name">#icon-tuceng</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#icon-move"></use>
|
||||
</svg>
|
||||
<div class="name">平移</div>
|
||||
<div class="code-name">#icon-move</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#icon-xiangpi_huaban1"></use>
|
||||
</svg>
|
||||
<div class="name">橡皮</div>
|
||||
<div class="code-name">#icon-xiangpi_huaban1</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#icon-tx-fill-tuoyuanxing"></use>
|
||||
</svg>
|
||||
<div class="name">tx-fill-椭圆形</div>
|
||||
<div class="code-name">#icon-tx-fill-tuoyuanxing</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#icon-zhixian"></use>
|
||||
</svg>
|
||||
<div class="name">直线</div>
|
||||
<div class="code-name">#icon-zhixian</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#icon-xian"></use>
|
||||
</svg>
|
||||
<div class="name">线</div>
|
||||
<div class="code-name">#icon-xian</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#icon-checkbox-full"></use>
|
||||
</svg>
|
||||
<div class="name">正方形</div>
|
||||
<div class="code-name">#icon-checkbox-full</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#icon-tuceng1"></use>
|
||||
</svg>
|
||||
<div class="name">图层</div>
|
||||
<div class="code-name">#icon-tuceng1</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#icon-dianwei"></use>
|
||||
</svg>
|
||||
<div class="name">点位</div>
|
||||
<div class="code-name">#icon-dianwei</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#icon-bingji"></use>
|
||||
</svg>
|
||||
<div class="name">并集</div>
|
||||
<div class="code-name">#icon-bingji</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#icon-bingji1"></use>
|
||||
</svg>
|
||||
<div class="name">并集</div>
|
||||
<div class="code-name">#icon-bingji1</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#icon-biaoqian"></use>
|
||||
</svg>
|
||||
<div class="name">标签</div>
|
||||
<div class="code-name">#icon-biaoqian</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#icon-yuyan"></use>
|
||||
</svg>
|
||||
<div class="name">语言</div>
|
||||
<div class="code-name">#icon-yuyan</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#icon-fanchehui"></use>
|
||||
</svg>
|
||||
<div class="name">撤销 返回 撤回 上一步</div>
|
||||
<div class="code-name">#icon-fanchehui</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#icon-chehui"></use>
|
||||
</svg>
|
||||
<div class="name">撤销 返回 撤回 上一步</div>
|
||||
<div class="code-name">#icon-chehui</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#icon-a-waitao_changkuanwaitao11x"></use>
|
||||
</svg>
|
||||
<div class="name">外套_长款外套1@1x</div>
|
||||
<div class="code-name">#icon-a-waitao_changkuanwaitao11x</div>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
<div class="article markdown">
|
||||
<h2 id="symbol-">Symbol 引用</h2>
|
||||
<hr>
|
||||
|
||||
<p>这是一种全新的使用方式,应该说这才是未来的主流,也是平台目前推荐的用法。相关介绍可以参考这篇<a href="">文章</a>
|
||||
这种用法其实是做了一个 SVG 的集合,与另外两种相比具有如下特点:</p>
|
||||
<ul>
|
||||
<li>支持多色图标了,不再受单色限制。</li>
|
||||
<li>通过一些技巧,支持像字体那样,通过 <code>font-size</code>, <code>color</code> 来调整样式。</li>
|
||||
<li>兼容性较差,支持 IE9+,及现代浏览器。</li>
|
||||
<li>浏览器渲染 SVG 的性能一般,还不如 png。</li>
|
||||
</ul>
|
||||
<p>使用步骤如下:</p>
|
||||
<h3 id="-symbol-">第一步:引入项目下面生成的 symbol 代码:</h3>
|
||||
<pre><code class="language-html"><script src="./iconfont.js"></script>
|
||||
</code></pre>
|
||||
<h3 id="-css-">第二步:加入通用 CSS 代码(引入一次就行):</h3>
|
||||
<pre><code class="language-html"><style>
|
||||
.icon {
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
vertical-align: -0.15em;
|
||||
fill: currentColor;
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
||||
</code></pre>
|
||||
<h3 id="-">第三步:挑选相应图标并获取类名,应用于页面:</h3>
|
||||
<pre><code class="language-html"><svg class="icon" aria-hidden="true">
|
||||
<use xlink:href="#icon-xxx"></use>
|
||||
</svg>
|
||||
</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
$(document).ready(function () {
|
||||
$('.tab-container .content:first').show()
|
||||
|
||||
$('#tabs li').click(function (e) {
|
||||
var tabContent = $('.tab-container .content')
|
||||
var index = $(this).index()
|
||||
|
||||
if ($(this).hasClass('active')) {
|
||||
return
|
||||
} else {
|
||||
$('#tabs li').removeClass('active')
|
||||
$(this).addClass('active')
|
||||
|
||||
tabContent.hide().eq(index).fadeIn()
|
||||
}
|
||||
})
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,18 +1,34 @@
|
||||
@font-face {
|
||||
font-family: "iconfont"; /* Project id 4292253 */
|
||||
src: url('iconfont.woff2?t=1759888699816') format('woff2'),
|
||||
url('iconfont.woff?t=1759888699816') format('woff'),
|
||||
url('iconfont.ttf?t=1759888699816') format('truetype');
|
||||
src: url('iconfont.woff2?t=1762934152017') format('woff2'),
|
||||
url('iconfont.woff?t=1762934152017') format('woff'),
|
||||
url('iconfont.ttf?t=1762934152017') format('truetype');
|
||||
}
|
||||
|
||||
.iconfont {
|
||||
font-family: "iconfont" !important;
|
||||
font-size: 1.6rem;
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.icon-caijian:before {
|
||||
content: "\e650";
|
||||
}
|
||||
|
||||
.icon-angle:before {
|
||||
content: "\e60a";
|
||||
}
|
||||
|
||||
.icon-flip-horizontal:before {
|
||||
content: "\e69e";
|
||||
}
|
||||
|
||||
.icon-flip-vertical:before {
|
||||
content: "\ec60";
|
||||
}
|
||||
|
||||
.icon-clothes:before {
|
||||
content: "\e8d1";
|
||||
}
|
||||
|
||||
1
src/assets/iconfont2/iconfont.js
Normal file
@@ -5,6 +5,34 @@
|
||||
"css_prefix_text": "icon-",
|
||||
"description": "",
|
||||
"glyphs": [
|
||||
{
|
||||
"icon_id": "22138606",
|
||||
"name": "裁剪",
|
||||
"font_class": "caijian",
|
||||
"unicode": "e650",
|
||||
"unicode_decimal": 58960
|
||||
},
|
||||
{
|
||||
"icon_id": "8875396",
|
||||
"name": "角度",
|
||||
"font_class": "angle",
|
||||
"unicode": "e60a",
|
||||
"unicode_decimal": 58890
|
||||
},
|
||||
{
|
||||
"icon_id": "15551512",
|
||||
"name": "水平翻转",
|
||||
"font_class": "flip-horizontal",
|
||||
"unicode": "e69e",
|
||||
"unicode_decimal": 59038
|
||||
},
|
||||
{
|
||||
"icon_id": "46016160",
|
||||
"name": "垂直翻转",
|
||||
"font_class": "flip-vertical",
|
||||
"unicode": "ec60",
|
||||
"unicode_decimal": 60512
|
||||
},
|
||||
{
|
||||
"icon_id": "20183053",
|
||||
"name": "clothes",
|
||||
|
||||
1
src/assets/icons/CCheck.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg t="1763432312095" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4678" width="200" height="200"><path d="M509.92 176C325.504 176 176 325.504 176 509.92c0 184.416 149.504 333.92 333.92 333.92 184.416 0 333.92-149.504 333.92-333.92C843.84 325.504 694.32 176 509.92 176z m166.64 214.848a16 16 0 0 1 22.624 0l11.328 11.312a16 16 0 0 1 0 22.624l-254.08 254.08a16 16 0 0 1-22.624 0l-159.616-159.632a16 16 0 0 1 0-22.624l11.312-11.312a16 16 0 0 1 22.624 0l136.992 136.992z" fill="currentColor" p-id="4679"></path></svg>
|
||||
|
After Width: | Height: | Size: 562 B |
2
src/assets/icons/CCopy.svg
Normal file
@@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" id="Layer_1" data-name="Layer 1" viewBox="0 0 24 24" width="512" height="512"><path d="m16,18.5v1c0,2.481-2.019,4.5-4.5,4.5h-7c-2.481,0-4.5-2.019-4.5-4.5v-7c0-2.481,2.019-4.5,4.5-4.5h1c.276,0,.5.224.5.5s-.224.5-.5.5h-1c-1.93,0-3.5,1.57-3.5,3.5v7c0,1.93,1.57,3.5,3.5,3.5h7c1.93,0,3.5-1.57,3.5-3.5v-1c0-.276.224-.5.5-.5s.5.224.5.5Zm8-14v7c0,2.481-2.019,4.5-4.5,4.5h-7c-2.481,0-4.5-2.019-4.5-4.5v-7c0-2.481,2.019-4.5,4.5-4.5h7c2.481,0,4.5,2.019,4.5,4.5Zm-1,0c0-1.93-1.57-3.5-3.5-3.5h-7c-1.93,0-3.5,1.57-3.5,3.5v7c0,1.93,1.57,3.5,3.5,3.5h7c1.93,0,3.5-1.57,3.5-3.5v-7Z"/></svg>
|
||||
|
After Width: | Height: | Size: 652 B |
2
src/assets/icons/CDownload.svg
Normal file
@@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" id="Layer_1" data-name="Layer 1" viewBox="0 0 24 24" width="512" height="512"><path d="M23.5,24H.5c-.28,0-.5-.22-.5-.5s.22-.5,.5-.5H23.5c.28,0,.5,.22,.5,.5s-.22,.5-.5,.5Zm-8.83-4.09l6.56-7.35c.77-.77,.98-1.88,.57-2.88-.42-1.01-1.36-1.65-2.45-1.65h-2.34V3.47c0-1.92-1.57-3.47-3.51-3.47h-2.99c-1.93,0-3.51,1.56-3.51,3.47v4.55s-2.33,0-2.33,0c-1.1,0-2.04,.64-2.45,1.65s-.19,2.12,.56,2.88l6.59,7.38c.73,.73,1.68,1.09,2.64,1.09s1.93-.37,2.67-1.11ZM7.5,9.03c.13,0,.26-.05,.35-.15s.15-.22,.15-.35V3.47c0-1.36,1.12-2.47,2.5-2.47h2.99c1.38,0,2.51,1.11,2.51,2.47v5.05c0,.28,.22,.5,.5,.5h2.84c.82,0,1.33,.54,1.53,1.03,.2,.5,.21,1.23-.36,1.81,0,0-.01,.01-.02,.02l-6.55,7.34c-1.07,1.07-2.81,1.07-3.86,.02L3.49,11.86c-.58-.58-.57-1.31-.36-1.81,.2-.5,.71-1.03,1.53-1.03h2.84Z"/></svg>
|
||||
|
After Width: | Height: | Size: 848 B |
9
src/assets/icons/CHelpFlip.svg
Normal file
@@ -0,0 +1,9 @@
|
||||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<rect width="20" height="20" fill="url(#pattern0_2040_2152)"/>
|
||||
<defs>
|
||||
<pattern id="pattern0_2040_2152" patternContentUnits="objectBoundingBox" width="1" height="1">
|
||||
<use xlink:href="#image0_2040_2152" transform="scale(0.015625)"/>
|
||||
</pattern>
|
||||
<image id="image0_2040_2152" width="64" height="64" preserveAspectRatio="none" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAACXBIWXMAAAHYAAAB2AH6XKZyAAAAGXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAABVhJREFUeJztm11sFUUUx3/XoFSQ0goJivjZKKmASPUqRsTvqjEqNaKRaOKT0ahRY4I+qFEBDT6oiS/65osPNn5ECdCgEGpoxSKJYv2oiLYRio1KsFYC1N7rw7m32Xtmdm93dvYS4/6TSZgy/Z//zO6ec+bMFDJkyJAhw/8XuRrZaQIuAy4CzgXOAmYAk0v/P1xq+4BdQC/QBfxUI32poBlYC3wPFB3bt8DLwPk11p4INwGf4j5pWysAHwM313AesZEHPsPvxG1tE/J2eYEPH1CHvOoPA8eFjCkAXwKdwHZgP/B7qf0D1AMNwFxgAbAYWAqcEMI3CrwKPAMc9TAHZ5yDOK2o13YF0OjAPQ24C9gawl8EtgGnJJlAErQgT9Im7H1goUdbC4GOEFt7gUs82poQrkfClhazG7g2RbvLgJ8tdoep4SLkgUMWEW8jr23aaADWW+z/gfiPVDEHGLQYX0PtkioQZ7vGomM/cFpaRuuAncpgAfH+xwrPYi7CZsKjUSKsshhblYahmFiLqWulbyPNwBFl5F1q+9qHIQdsoFLbETwmS2DG4l9wc3jTgfuBjUA/cADoA9qBewhPfKphFjCkNL7nyGXgasxXrM2B507gTwtXsA0gIdYFbYqrgKfQ+JEiXufAsZLoiQfbGHCfo9ZtimuDI884zisJCpIujslxJZLvx9nwHEVqB3GxBHMxT3fgGcdqRdjtwNGjOEaQTcwFSMxeAryJTDo4bouj5m7F86QjDyA7uCDZipi/vwjziVwVMrYN+W6D4+fEVgwPKI5eBw4oGQ8KGkXS0Dh4SIlprzJ+hxp/S0x7ACcDhxXP7LDBURlTK5Vxvgs4GFNMJxKTQfzAa1XGD6p+XUx7IKG1R/3s0rDBUQug63CbHcT0IsXQp5BvPcqHzMT8PPodbIIUXYIIXYAo6PC33FHMRDAVM9kaBCY58t2huDpcSHQ112eBI4hp2IuoTyTg1M53pwvJAUXiUtaqhgbgc8zJd+L+9AHOUHz9LiQHFclJCQTZcDxSM9ST/wLx5EkwVXH+5UKiS15TEorSeBpz8tuRDVNSTFG8Iy4kegHqPQgrYxbyVIL8O4ifZ4ThVMW9L2xgVBjUMfnM5LrGsZzKT2oQuIH4eUYY9CcUyhu1APpgsslZjokW1X8dcbq+oIshA2EDoxZgj+rPdZZjQn9OP3jkBpiv+l+HDYxagG9U32e9/8fAv4vIeYJPLFV9pw3R2VQ6ksP4C4WNwDvAd8BjnjjLmI65tXb2X32K6HYPAtPGvVRq/ipqcLX6+UbVf8RdlxWTqw+JjQdV36WEN44FmEUK7cFd0IS8XWPAW/grr+cxCzCJo9cmRfphUkLgDcV5uQdOgE8U73ofpDcq0iJwW0LO4GlOAT+Hmrdi6rzOAy85zO3qAMlOgoNR4PGkApEbZ3up1Ji4JB7EPMzQ8gEpHULGRA65kBHUNkoKN8tewnzFVvs24gDbMfnzaRg6EbPGXyBZ5SYpHsWcfDfJiimRmI1sLbXRF6ntSXEOeMGiYwi5hZoq8sDfFuPtJK/kTAT1yHUcbX8Yt+M0J1yBWTIrIp64NUW7rcg2XdsdId3LWVZcCPxqEVNEUuiLPdpahCRgNltDHINrcmU0Ya/qlh1kB3LxwSVnqAfuRrI7nY6X2y78FmqcMAkJO6PYRRaRa3XrgOeQ875mpG5Xh2yIZiDZ4DLkdngP0UfqY8AruB2dpYY8cqQdJtpX68LPhiw1XIN5U8NH60T2Jf8ZzEcyxT24T7qPlP9golbJyzwkKrQg0WMmsiFqLGk4BPyGHGHtRnxAN5W1wwwZMmTIkMEz/gUzEqIONKOEMwAAAABJRU5ErkJggg=="/>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.4 KiB |
4
src/assets/icons/CPause.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
|
||||
<path fill="currentColor" d="M14 10h-2v12h2zm6 0h-2v12h2z" />
|
||||
<path fill="currentColor" d="M16 4A12 12 0 1 1 4 16A12 12 0 0 1 16 4m0-2a14 14 0 1 0 14 14A14 14 0 0 0 16 2" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 266 B |
1
src/assets/icons/CPlay.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg t="1762937400333" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4603" width="200" height="200"><path d="M817.088 484.96l-512-323.744C295.232 154.976 282.752 154.592 272.576 160.224 262.336 165.856 256 176.608 256 188.256l0 647.328c0 11.648 6.336 22.4 16.576 28.032 4.8 2.656 10.112 3.968 15.424 3.968 5.952 0 11.904-1.664 17.088-4.928l512-323.616C826.368 533.184 832 522.976 832 512 832 501.024 826.368 490.816 817.088 484.96z" fill="currentColor" p-id="4604"></path></svg>
|
||||
|
After Width: | Height: | Size: 524 B |
1
src/assets/icons/CSearch.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg t="1761795702180" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5928" width="200" height="200"><path d="M433.505 126.568c174.435 0 316.207 141.805 316.207 316.486 0 75.209-26.384 144.234-69.824 198.526l209.166 209.1c12.849 13.148 12.849 34.459 0 47.582-13.177 13.148-34.692 13.148-47.904 0l-209.166-209.1c-54.203 43.843-123.131 70.111-198.373 70.111-174.987 0-316.682-141.627-316.682-316.434 0-174.724 141.826-316.486 316.682-316.486zM433.505 710.778c147.649 0 267.808-120.113 267.808-267.647 0-147.741-120.204-267.712-267.808-267.712-147.649 0-267.808 120.099-267.808 267.712 0 147.649 120.204 267.647 267.808 267.647z" fill="currentColor" p-id="5929"></path></svg>
|
||||
|
After Width: | Height: | Size: 717 B |
3
src/assets/icons/promptEditProductNo.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg width="50" height="50" viewBox="0 0 50 50" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M25 0C20.0555 0 15.222 1.46622 11.1108 4.21326C6.99953 6.9603 3.79521 10.8648 1.90302 15.4329C0.0108322 20.0011 -0.484251 25.0277 0.480379 29.8773C1.44501 34.7268 3.82603 39.1814 7.32234 42.6777C10.8187 46.174 15.2732 48.555 20.1228 49.5196C24.9723 50.4843 29.9989 49.9892 34.5671 48.097C39.1353 46.2048 43.0397 43.0005 45.7867 38.8893C48.5338 34.778 50 29.9445 50 25C50 18.3696 47.3661 12.0107 42.6777 7.32233C37.9893 2.63392 31.6304 0 25 0ZM34.8063 31.8604L31.8604 34.8063L25 27.9458L18.1396 34.8063L15.1938 31.8604L22.0542 25L15.1938 18.1396L18.1396 15.1938L25 22.0542L31.8604 15.1938L34.8063 18.1396L27.9458 25L34.8063 31.8604Z" fill="black"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 760 B |
3
src/assets/icons/promptEditProductYes.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg width="50" height="50" viewBox="0 0 50 50" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M25 0C11.2146 0 0 11.2146 0 25C0 38.7854 11.2146 50 25 50C38.7854 50 50 38.7854 50 25C50 11.2146 38.7854 0 25 0ZM24.8104 32.1229C24.0042 32.9292 22.9437 33.3312 21.8792 33.3312C20.8146 33.3312 19.7437 32.925 18.9292 32.1125L13.1333 26.4958L16.0354 23.5021L21.8542 29.1417L33.9562 17.2646L36.8812 20.2333L24.8104 32.1229Z" fill="black"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 449 B |
BIN
src/assets/images/editProduct/PromptEditProduct_edited1.png
Normal file
|
After Width: | Height: | Size: 88 KiB |
BIN
src/assets/images/editProduct/PromptEditProduct_edited2.png
Normal file
|
After Width: | Height: | Size: 144 KiB |
BIN
src/assets/images/editProduct/PromptEditProduct_edited3.png
Normal file
|
After Width: | Height: | Size: 196 KiB |
BIN
src/assets/images/editProduct/PromptEditProduct_list1.png
Normal file
|
After Width: | Height: | Size: 79 KiB |
BIN
src/assets/images/editProduct/PromptEditProduct_list10.png
Normal file
|
After Width: | Height: | Size: 152 KiB |
BIN
src/assets/images/editProduct/PromptEditProduct_list11.png
Normal file
|
After Width: | Height: | Size: 196 KiB |
BIN
src/assets/images/editProduct/PromptEditProduct_list2.png
Normal file
|
After Width: | Height: | Size: 94 KiB |
BIN
src/assets/images/editProduct/PromptEditProduct_list3.png
Normal file
|
After Width: | Height: | Size: 80 KiB |
BIN
src/assets/images/editProduct/PromptEditProduct_list4.png
Normal file
|
After Width: | Height: | Size: 98 KiB |
BIN
src/assets/images/editProduct/PromptEditProduct_list5.png
Normal file
|
After Width: | Height: | Size: 101 KiB |
BIN
src/assets/images/editProduct/PromptEditProduct_list6.png
Normal file
|
After Width: | Height: | Size: 88 KiB |
BIN
src/assets/images/editProduct/PromptEditProduct_list7.png
Normal file
|
After Width: | Height: | Size: 86 KiB |
BIN
src/assets/images/editProduct/PromptEditProduct_list8.png
Normal file
|
After Width: | Height: | Size: 94 KiB |
BIN
src/assets/images/editProduct/PromptEditProduct_list9.png
Normal file
|
After Width: | Height: | Size: 182 KiB |
BIN
src/assets/images/editProduct/PromptEditProduct_listOriginal.png
Normal file
|
After Width: | Height: | Size: 88 KiB |
BIN
src/assets/images/homePage/designTutorial_CN.png
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
src/assets/images/homePage/designTutorial_EN.png
Normal file
|
After Width: | Height: | Size: 27 KiB |
BIN
src/assets/images/product/add.png
Normal file
|
After Width: | Height: | Size: 5.7 KiB |
BIN
src/assets/images/product/first_frame.png
Normal file
|
After Width: | Height: | Size: 1.1 MiB |
BIN
src/assets/images/product/geneated_dress.png
Normal file
|
After Width: | Height: | Size: 58 KiB |
BIN
src/assets/images/product/generated_model.png
Normal file
|
After Width: | Height: | Size: 101 KiB |
BIN
src/assets/images/product/generated_sketch.png
Normal file
|
After Width: | Height: | Size: 101 KiB |
BIN
src/assets/images/product/last_frame.png
Normal file
|
After Width: | Height: | Size: 1.2 MiB |
BIN
src/assets/images/product/male_single_garment_model_result.png
Normal file
|
After Width: | Height: | Size: 1.7 MiB |
BIN
src/assets/images/product/male_single_garment_model_sketch.png
Normal file
|
After Width: | Height: | Size: 404 KiB |
BIN
src/assets/images/product/male_single_garment_result.png
Normal file
|
After Width: | Height: | Size: 1.3 MiB |
BIN
src/assets/images/product/male_single_garment_sketch.png
Normal file
|
After Width: | Height: | Size: 709 KiB |
BIN
src/assets/images/product/original_dress.png
Normal file
|
After Width: | Height: | Size: 52 KiB |
BIN
src/assets/images/product/original_model.png
Normal file
|
After Width: | Height: | Size: 49 KiB |
BIN
src/assets/images/product/single_female_child_model_result.png
Normal file
|
After Width: | Height: | Size: 1.7 MiB |
BIN
src/assets/images/product/single_male_child_model_result.png
Normal file
|
After Width: | Height: | Size: 1.3 MiB |
BIN
src/assets/images/product/single_male_child_model_sketch.png
Normal file
|
After Width: | Height: | Size: 521 KiB |
@@ -1250,7 +1250,9 @@ tr > .ant-picker-cell-in-view.ant-picker-cell-range-hover-start:last-child::afte
|
||||
border-color: #000 !important;
|
||||
}
|
||||
.ant-spin-dot-item {
|
||||
background-color: #000000;
|
||||
background-color: #000000 !important;
|
||||
width: 9px !important;
|
||||
height: 9px !important;
|
||||
}
|
||||
.ant-spin {
|
||||
color: #000;
|
||||
@@ -1376,7 +1378,7 @@ tr > .ant-picker-cell-in-view.ant-picker-cell-range-hover-start:last-child::afte
|
||||
}
|
||||
.admin_page .admin_state_item .active {
|
||||
cursor: no-drop;
|
||||
background-color: #f5f5f5;
|
||||
background-color: #F9FAFA;
|
||||
}
|
||||
.admin_page .admin_search_item {
|
||||
height: 4rem;
|
||||
@@ -1710,7 +1712,7 @@ textarea:focus {
|
||||
display: inline-block;
|
||||
width: calc(25% - 2rem);
|
||||
aspect-ratio: 1 / 1;
|
||||
border: 1px solid #f5f5f5;
|
||||
border: 1px solid #F9FAFA;
|
||||
vertical-align: top;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
|
||||
@@ -1378,7 +1378,9 @@ tr > .ant-picker-cell-in-view.ant-picker-cell-range-hover-start:last-child::afte
|
||||
}
|
||||
//loding样式
|
||||
.ant-spin-dot-item{
|
||||
background-color: #000000;
|
||||
background-color: #000000 !important;
|
||||
width: 9px !important;
|
||||
height: 9px !important;
|
||||
}
|
||||
.ant-spin{
|
||||
color: #000;
|
||||
@@ -1510,7 +1512,7 @@ tr > .ant-picker-cell-in-view.ant-picker-cell-range-hover-start:last-child::afte
|
||||
}
|
||||
.active{
|
||||
cursor: no-drop;
|
||||
background-color: #f5f5f5;
|
||||
background-color: #F9FAFA;
|
||||
}
|
||||
}
|
||||
.admin_search_item{
|
||||
@@ -1865,7 +1867,7 @@ textarea:focus{
|
||||
// height: calc(10rem);
|
||||
width: calc(25% - 2rem);
|
||||
aspect-ratio: 1 / 1;
|
||||
border: 1px solid #f5f5f5;
|
||||
border: 1px solid #F9FAFA;
|
||||
vertical-align: top;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<bind v-if="item.key == 'bind' && activeKey == 'bind'" :ref="item.key"></bind>
|
||||
<cancelRenewal v-if="item.key == 'cancelRenewal' && activeKey == 'cancelRenewal'" :ref="item.key"></cancelRenewal>
|
||||
<template #tab>
|
||||
<a-badge :count="0" >
|
||||
<a-badge :count="0" v-if="!(item.key == 'cancelRenewal' && [5,6,7,8].includes(userDetail.systemUser))">
|
||||
<span>{{item.title}}</span>
|
||||
</a-badge>
|
||||
</template>
|
||||
@@ -104,6 +104,12 @@ export default defineComponent({
|
||||
let key = accountfrontPage.frontPageList[0].key
|
||||
accountfrontPage.activeKey = key
|
||||
const data = route.query
|
||||
if(!!data.subscribe){
|
||||
accountfrontPage.activeKey = 'cancelRenewal'
|
||||
nextTick(()=>{
|
||||
domRefs.cancelRenewal[0].subscribe()
|
||||
})
|
||||
}
|
||||
if(data?.state == 'weiXin'){
|
||||
accountfrontPage.activeKey = 'bind'
|
||||
wechatLogin(data)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="account_systemMessage">
|
||||
<div class="account_systemMessage">'"
|
||||
<div class="account_generalMessage_title modal_title_text">
|
||||
<!-- <span>系统消息</span> -->
|
||||
<div class="account_generalMessage_title_setting" @click="allRead">{{$t('account.AllRead')}}</div>
|
||||
|
||||
@@ -324,7 +324,11 @@ export default defineComponent({
|
||||
filterData.orderBy = 'credits'
|
||||
}
|
||||
}
|
||||
filterData.order = sorter.order == "descend" ? "Descending" : "Ascending";
|
||||
if(sorter.order){
|
||||
filterData.order = sorter.order == "descend" ? "Descending" : "Ascending";
|
||||
}else{
|
||||
filterData.order = ''
|
||||
}
|
||||
|
||||
gettrialList();
|
||||
};
|
||||
|
||||
@@ -97,7 +97,7 @@
|
||||
></a-select>
|
||||
</div>
|
||||
<div class="admin_state_item">
|
||||
<span>Total Amount:</span>
|
||||
<span>Total Amount: {{ totalPayer }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="admin_search">
|
||||
@@ -210,6 +210,8 @@ export default defineComponent({
|
||||
orderBy:'',
|
||||
status: "",
|
||||
type: "",
|
||||
totalPayer:0,
|
||||
|
||||
});
|
||||
let selectList=reactive({
|
||||
platformList:[
|
||||
@@ -405,8 +407,11 @@ export default defineComponent({
|
||||
filterData.orderBy = 'credits'
|
||||
}
|
||||
}
|
||||
filterData.order = sorter.order == "descend" ? "DESC" : "ASC";
|
||||
|
||||
if(sorter.order){
|
||||
filterData.order = sorter.order == "descend" ? "DESC" : "ASC";
|
||||
}else{
|
||||
filterData.order = ''
|
||||
}
|
||||
gettrialList();
|
||||
};
|
||||
|
||||
@@ -466,6 +471,9 @@ export default defineComponent({
|
||||
filter.dataList = rv.content;
|
||||
filterData.total = rv.total;
|
||||
filter.tableLoading = false;
|
||||
rv.content.forEach((item: any) => {
|
||||
filterData.totalPayer += Number(item.payerTotal)
|
||||
})
|
||||
|
||||
// this.workspaceItem.position = this.singleTypeList[0].label
|
||||
}
|
||||
|
||||
@@ -115,6 +115,13 @@ export default defineComponent({
|
||||
width: 100,
|
||||
dataIndex: "status",
|
||||
key: "status",
|
||||
},{
|
||||
title: 'Visits',
|
||||
align: "center",
|
||||
ellipsis: true,
|
||||
width: 100,
|
||||
dataIndex: "visits",
|
||||
key: "visits",
|
||||
},{
|
||||
title: 'Commission Percent',
|
||||
align: "center",
|
||||
|
||||
@@ -57,6 +57,11 @@
|
||||
style="width: 250px"
|
||||
/>
|
||||
</div>
|
||||
{{ currentState }}
|
||||
<div class="admin_state_item">
|
||||
<span>State:</span>
|
||||
<a-select v-model:value="currentState" style="width:250px" optionFilterProp="label" :options="state" placeholder="Please select" allowClear show-search></a-select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="allUserPoeration_btn admin_page">
|
||||
<div class="admin_search_item" @click="cancelDsign">Close</div>
|
||||
@@ -96,14 +101,29 @@ export default defineComponent({
|
||||
id: "",
|
||||
commission: "",
|
||||
});
|
||||
let currentState = ref('')
|
||||
let state = ref([
|
||||
{
|
||||
label:'Active',
|
||||
value:'Active',
|
||||
},
|
||||
{
|
||||
label:'Delete',
|
||||
value:'Delete',
|
||||
},
|
||||
{
|
||||
label:'Inactive',
|
||||
value:'Inactive',
|
||||
},
|
||||
])
|
||||
let init = (data) => {
|
||||
let funStr = 'Edit'
|
||||
console.log(data)
|
||||
operations.operationsModal = true;
|
||||
operations.title = funStr;
|
||||
if (funStr == "Edit") {
|
||||
operationsData.id = data.id;
|
||||
operationsData.commission = data.commissionPercent;
|
||||
currentState.value = data.status;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -111,11 +131,13 @@ export default defineComponent({
|
||||
return {
|
||||
id: operationsData.id,
|
||||
commission: operationsData.commission,
|
||||
operationType: currentState.value,
|
||||
};
|
||||
};
|
||||
let cancelDsign = () => {
|
||||
operationsData.id = "";
|
||||
operationsData.commission = "";
|
||||
currentState.value = "";
|
||||
operations.operationsModal = false;
|
||||
};
|
||||
let setOk = () => {
|
||||
@@ -125,7 +147,7 @@ export default defineComponent({
|
||||
!data.commission
|
||||
)
|
||||
return message.warning("Please check the input box marked with *");
|
||||
Https.axiosGet(Https.httpUrls.updateCommission, {params:data}).then(
|
||||
Https.axiosGet(Https.httpUrls.editAffiliate, {params:data}).then(
|
||||
(rv) => {
|
||||
if (rv) {
|
||||
cancelDsign();
|
||||
@@ -139,6 +161,8 @@ export default defineComponent({
|
||||
...toRefs(operationsData),
|
||||
cancelDsign,
|
||||
init,
|
||||
state,
|
||||
currentState,
|
||||
setOk,
|
||||
};
|
||||
},
|
||||
|
||||
@@ -394,8 +394,11 @@ export default defineComponent({
|
||||
filterData.orderBy = 'credits'
|
||||
}
|
||||
}
|
||||
filterData.order = sorter.order == "descend" ? "Descending" : "Ascending";
|
||||
|
||||
if(sorter.order){
|
||||
filterData.order = sorter.order == "descend" ? "Descending" : "Ascending";
|
||||
}else{
|
||||
filterData.order = ''
|
||||
}
|
||||
gettrialList();
|
||||
};
|
||||
|
||||
|
||||
@@ -242,7 +242,11 @@ export default defineComponent({
|
||||
filterData.orderBy = 'credits'
|
||||
}
|
||||
}
|
||||
filterData.order = sorter.order == "descend" ? "Descending" : "Ascending";
|
||||
if(sorter.order){
|
||||
filterData.order = sorter.order == "descend" ? "Descending" : "Ascending";
|
||||
}else{
|
||||
filterData.order = ''
|
||||
}
|
||||
gettrialList();
|
||||
}
|
||||
|
||||
|
||||
@@ -268,7 +268,11 @@ export default defineComponent({
|
||||
filterData.orderBy = 'credits'
|
||||
}
|
||||
}
|
||||
filterData.order = sorter.order == "descend" ? "Descending" : "Ascending";
|
||||
if(sorter.order){
|
||||
filterData.order = sorter.order == "descend" ? "Descending" : "Ascending";
|
||||
}else{
|
||||
filterData.order = ''
|
||||
}
|
||||
gettrialList();
|
||||
}
|
||||
|
||||
|
||||
@@ -201,7 +201,11 @@ export default defineComponent({
|
||||
filterData.orderBy = 'time'
|
||||
}
|
||||
}
|
||||
filterData.order = sorter.order == "descend" ? "Descending" : "Ascending";
|
||||
if(sorter.order){
|
||||
filterData.order = sorter.order == "descend" ? "Descending" : "Ascending";
|
||||
}else{
|
||||
filterData.order = ''
|
||||
}
|
||||
gettrialList();
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ export class FillGroupLayerBackgroundCommand extends Command {
|
||||
this.canvas = options.canvas;
|
||||
this.layers = options.layers;
|
||||
this.canvasManager = options.canvasManager;
|
||||
this.layerManager = options.layerManager;
|
||||
this.layerId = options.layerId;
|
||||
this.fillColor = options.fillColor;
|
||||
this.oldFill = null;
|
||||
@@ -211,6 +212,7 @@ export class FillGroupLayerBackgroundCommand extends Command {
|
||||
this.group.set({
|
||||
id: layerObjects[0]?.id || generateId("group-"),
|
||||
layerId: this.layer?.id,
|
||||
layerName: this.layer?.name,
|
||||
});
|
||||
// this.group.setCoords();
|
||||
// this.group.setObjectsCoords();
|
||||
@@ -225,7 +227,7 @@ export class FillGroupLayerBackgroundCommand extends Command {
|
||||
this.group.clipPath = clipPath;
|
||||
}
|
||||
layer.fabricObjects = [
|
||||
this.group.toObject(["id", "layerId"]) || this.group,
|
||||
this.group.toObject(["id", "layerId", "layerName"]) || this.group,
|
||||
];
|
||||
// removeCanvasObjectByObject(this.canvas, layerObjects?.[0]);
|
||||
insertObjectAtZIndex(this.canvas, this.group, insertIndex, false, true);
|
||||
|
||||
@@ -528,6 +528,7 @@ export class RemoveLayerCommand extends Command {
|
||||
this.layerIndex = this.layers.value.findIndex(
|
||||
(layer) => layer.id === this.layerId
|
||||
);
|
||||
|
||||
this.removedLayer = this.layers.value[this.layerIndex];
|
||||
this.isActiveLayer = this.layerId === this.activeLayerId.value;
|
||||
|
||||
@@ -593,6 +594,9 @@ export class RemoveLayerCommand extends Command {
|
||||
}
|
||||
});
|
||||
|
||||
this.layerIndex = this.layers.value.findIndex(
|
||||
(layer) => layer.id === this.layerId
|
||||
);
|
||||
// 从图层列表中删除
|
||||
this.layers.value.splice(this.layerIndex, 1);
|
||||
|
||||
@@ -604,6 +608,9 @@ export class RemoveLayerCommand extends Command {
|
||||
);
|
||||
if (newActiveLayer) {
|
||||
this.activeLayerId.value = newActiveLayer.id;
|
||||
if(this.canvas.toolId === OperationType.SELECT){
|
||||
this.layerManager.selectLayerObjects(newActiveLayer.id);
|
||||
}
|
||||
} else {
|
||||
this.activeLayerId.value = null;
|
||||
}
|
||||
@@ -2595,7 +2602,7 @@ export class CreateImageLayerCommand extends Command {
|
||||
|
||||
// 生成图层名称
|
||||
const fileName =
|
||||
this.layerName || `图片 ${new Date().toLocaleTimeString()}`;
|
||||
this.layerName || `${new Date().toLocaleTimeString()}`;
|
||||
|
||||
this.fabricImage.set({
|
||||
id: this.imageId,
|
||||
|
||||
@@ -15,6 +15,8 @@ import {
|
||||
import { createRasterizedImage } from "../utils/rasterizedImage";
|
||||
import { message } from "ant-design-vue";
|
||||
import { restoreFabricObject } from "../utils/objectHelper";
|
||||
import i18n from "@/lang/index.ts";
|
||||
const { t } = i18n.global;
|
||||
|
||||
/**
|
||||
* 组合图层命令
|
||||
@@ -338,7 +340,7 @@ export class RasterizeLayerCommand extends Command {
|
||||
// 创建新的组合图层
|
||||
this.rasterizedLayer = createLayer({
|
||||
id: this.rasterizedLayerId,
|
||||
name: `${this.layer.name} (组合)`,
|
||||
name: `${this.layer.name} (${t('Canvas.group')})`,
|
||||
type: LayerType.BITMAP,
|
||||
visible: this.layer.visible,
|
||||
locked: this.layer.locked,
|
||||
@@ -491,7 +493,7 @@ export class ExportLayerToImageCommand extends Command {
|
||||
this._collectLayersAndObjects();
|
||||
}
|
||||
|
||||
async execute() {
|
||||
async execute(isDownload = true) {
|
||||
if (!this.layer) {
|
||||
throw new Error(`图层 ${this.layerId} 不存在`);
|
||||
}
|
||||
@@ -530,18 +532,21 @@ export class ExportLayerToImageCommand extends Command {
|
||||
fabricObjects: this.objectsToRasterize,
|
||||
isReturenDataURL: true,
|
||||
maskObject: clippingMaskFabricObject || null, // 不处理遮罩
|
||||
scaleFactor: isDownload ? 2 : 1,
|
||||
});
|
||||
|
||||
|
||||
// 模拟浏览器下载
|
||||
const link = document.createElement("a");
|
||||
link.href = imageBase64;
|
||||
link.download = `${this.layer.name}.png`;
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
document.body.removeChild(link);
|
||||
|
||||
if (isDownload) {
|
||||
const link = document.createElement("a");
|
||||
link.href = imageBase64;
|
||||
link.download = `${this.layer.name}.png`;
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
document.body.removeChild(link);
|
||||
}
|
||||
console.log(`✅ 图层 ${this.layer.name} 导出完成`);
|
||||
return true;
|
||||
return imageBase64;
|
||||
} catch (error) {
|
||||
console.error("导出图层失败:", error);
|
||||
throw error;
|
||||
|
||||
@@ -321,6 +321,7 @@ export class CreateTextCommand extends Command {
|
||||
this.x = options.x;
|
||||
this.y = options.y;
|
||||
this.textOptions = options.textOptions || {};
|
||||
this.options = options;
|
||||
// 生成唯一ID
|
||||
this.textId = options?.textId || generateId("text_");
|
||||
this.layerId = options?.layerId || generateId("text_layer_");
|
||||
@@ -331,7 +332,7 @@ export class CreateTextCommand extends Command {
|
||||
|
||||
// 默认文本属性
|
||||
this.defaultOptions = {
|
||||
text: t('Canvas.DoubleClickText'),
|
||||
text: options.text || t('Canvas.DoubleClickText'),
|
||||
fontFamily: "Arial",
|
||||
fontSize: 24,
|
||||
fontWeight: "normal",
|
||||
@@ -373,8 +374,8 @@ export class CreateTextCommand extends Command {
|
||||
originY: "center",
|
||||
});
|
||||
|
||||
// 创建文本图层
|
||||
const layerName = this.textOptions.layerName || "文本图层";
|
||||
// 创建文本图层 取15
|
||||
const layerName = this.options.text?.substring(0, 25) || t('Canvas.TextLayer');
|
||||
const layer = createLayer({
|
||||
id: this.layerId,
|
||||
name: layerName,
|
||||
|
||||
695
src/component/Canvas/CanvasEditor/components/CropImage.vue
Normal file
@@ -0,0 +1,695 @@
|
||||
<template>
|
||||
<!-- 图片列表面板 -->
|
||||
<div v-if="showPanel" class="crop-image-overlay" @click.self="close">
|
||||
<div class="crop-image-modal">
|
||||
<div class="modal-header">
|
||||
<h3>{{ $t("Canvas.cropImage") }}</h3>
|
||||
<button class="close-btn" @click="close">×</button>
|
||||
</div>
|
||||
|
||||
<div class="modal-content">
|
||||
<!-- 图片剪切 -->
|
||||
<div class="image-clip" ref="el" v-if="data.url">
|
||||
<div
|
||||
class="box"
|
||||
ref="box"
|
||||
:style="{
|
||||
width: clipData.img_width + 'px',
|
||||
height: clipData.img_height + 'px',
|
||||
}"
|
||||
>
|
||||
<img :src="data.url" />
|
||||
<div class="shade"></div>
|
||||
<div
|
||||
ref="clipRef"
|
||||
class="clip"
|
||||
:style="{
|
||||
top: clipData.top + 'px',
|
||||
left: clipData.left + 'px',
|
||||
width: clipData.width + 'px',
|
||||
height: clipData.height + 'px',
|
||||
}"
|
||||
@mousedown.stop="clipMousedown"
|
||||
@touchstart.stop="clipMousedown"
|
||||
>
|
||||
<div class="img">
|
||||
<img
|
||||
:src="data.url"
|
||||
:style="{
|
||||
width: clipData.img_width + 'px',
|
||||
height: clipData.img_height + 'px',
|
||||
top: -clipData.top + 'px',
|
||||
left: -clipData.left + 'px',
|
||||
}"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="top"
|
||||
@mousedown.stop="topMousedown"
|
||||
@touchstart.stop="topMousedown"
|
||||
></div>
|
||||
<div
|
||||
class="right"
|
||||
@mousedown.stop="rightMousedown"
|
||||
@touchstart.stop="rightMousedown"
|
||||
></div>
|
||||
<div
|
||||
class="bottom"
|
||||
@mousedown.stop="bottomMousedown"
|
||||
@touchstart.stop="bottomMousedown"
|
||||
></div>
|
||||
<div
|
||||
class="left"
|
||||
@mousedown.stop="leftMousedown"
|
||||
@touchstart.stop="leftMousedown"
|
||||
></div>
|
||||
<span
|
||||
class="top"
|
||||
@mousedown.stop="topMousedown"
|
||||
@touchstart.stop="topMousedown"
|
||||
></span>
|
||||
<span
|
||||
class="right"
|
||||
@mousedown.stop="rightMousedown"
|
||||
@touchstart.stop="rightMousedown"
|
||||
></span>
|
||||
<span
|
||||
class="bottom"
|
||||
@mousedown.stop="bottomMousedown"
|
||||
@touchstart.stop="bottomMousedown"
|
||||
></span>
|
||||
<span
|
||||
class="left"
|
||||
@mousedown.stop="leftMousedown"
|
||||
@touchstart.stop="leftMousedown"
|
||||
></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 空状态 -->
|
||||
<div class="empty-state" v-else>
|
||||
<div class="empty-icon">📷</div>
|
||||
<p>{{ $t("Canvas.NoPicture") }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<div class="image-count"></div>
|
||||
<div class="image-submit gallery_btn" @click="confirm">
|
||||
{{ $t("Canvas.confirm") }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import {
|
||||
ref,
|
||||
computed,
|
||||
defineProps,
|
||||
onDeactivated,
|
||||
reactive,
|
||||
onMounted,
|
||||
defineExpose,
|
||||
} from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
|
||||
// Props
|
||||
const props = defineProps([]);
|
||||
const { t } = useI18n();
|
||||
var resolveFn: (value: string | PromiseLike<string>) => void;
|
||||
const showPanel = ref(false);
|
||||
const open = (url: string) => {
|
||||
showPanel.value = true;
|
||||
setImgage(url);
|
||||
return new Promise((resolve) => (resolveFn = resolve));
|
||||
};
|
||||
const close = () => {
|
||||
showPanel.value = false;
|
||||
};
|
||||
//提交选中的T图片
|
||||
const confirm = () => {
|
||||
close();
|
||||
const base64 = getImageBase64();
|
||||
resolveFn && resolveFn(base64);
|
||||
};
|
||||
|
||||
const data = reactive({
|
||||
url: "",
|
||||
});
|
||||
const el = ref();
|
||||
const box = ref();
|
||||
const clipRef = ref();
|
||||
const clipData = reactive({
|
||||
top: 0,
|
||||
left: 0,
|
||||
width: 0,
|
||||
height: 0,
|
||||
img_width: 0,
|
||||
img_height: 0,
|
||||
});
|
||||
const canvas = document.createElement("canvas");
|
||||
const ctx = canvas.getContext("2d");
|
||||
const reload = () => {
|
||||
if (!el.value) return;
|
||||
const size = Math.min(
|
||||
1,
|
||||
el.value.offsetWidth / canvas.width,
|
||||
el.value.offsetHeight / canvas.height
|
||||
);
|
||||
const width = size * canvas.width;
|
||||
const height = size * canvas.height;
|
||||
clipData.left = 0;
|
||||
clipData.top = 0;
|
||||
clipData.width = width;
|
||||
clipData.height = height;
|
||||
clipData.img_width = width;
|
||||
clipData.img_height = height;
|
||||
};
|
||||
window.addEventListener("resize", reload);
|
||||
onDeactivated(() => {
|
||||
window.removeEventListener("resize", reload);
|
||||
});
|
||||
|
||||
const setImgage = (url: string) => {
|
||||
if (!url) return;
|
||||
const img = new Image();
|
||||
img.src = url;
|
||||
data.url = url;
|
||||
img.onload = () => {
|
||||
const width = img.width;
|
||||
const height = img.height;
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
ctx?.clearRect(0, 0, width, height);
|
||||
ctx?.drawImage(img, 0, 0, width, height);
|
||||
nextTick(() => reload());
|
||||
};
|
||||
};
|
||||
const canvasImageDataToBase64 = (imageData: any) => {
|
||||
// 创建一个临时的canvas元素
|
||||
const canvas = document.createElement("canvas");
|
||||
canvas.width = imageData.width;
|
||||
canvas.height = imageData.height;
|
||||
const ctx = canvas.getContext("2d");
|
||||
ctx?.putImageData(imageData, 0, 0);
|
||||
const dataURL = canvas.toDataURL("image/png");
|
||||
return dataURL;
|
||||
};
|
||||
const base64toFile = (dataurl, filename = "file") => {
|
||||
//转换base64
|
||||
let arr = dataurl.split(",");
|
||||
let mime = arr[0].match(/:(.*?);/)[1];
|
||||
let suffix = mime.split("/")[1];
|
||||
let bstr = atob(arr[1]);
|
||||
let n = bstr.length;
|
||||
let u8arr = new Uint8Array(n);
|
||||
while (n--) {
|
||||
u8arr[n] = bstr.charCodeAt(n);
|
||||
}
|
||||
return new File([u8arr], `${filename}.${suffix}`, {
|
||||
type: mime,
|
||||
});
|
||||
};
|
||||
const getImageBase64 = () => {
|
||||
const scale = canvas.width / clipData.img_width;
|
||||
const imageData = ctx?.getImageData(
|
||||
clipData.left * scale,
|
||||
clipData.top * scale,
|
||||
clipData.width * scale,
|
||||
clipData.height * scale
|
||||
);
|
||||
const base64 = canvasImageDataToBase64(imageData);
|
||||
return base64;
|
||||
};
|
||||
const getImageFile = () => {
|
||||
const base64 = getImageBase64();
|
||||
const file = base64toFile(base64, "image.png");
|
||||
return file;
|
||||
};
|
||||
|
||||
// 移动裁剪框
|
||||
const clipMousedown = (e: MouseEvent | TouchEvent) => {
|
||||
e.preventDefault();
|
||||
var pageX = 0;
|
||||
var pageY = 0;
|
||||
if (e.type == "touchstart") {
|
||||
const touch = e["touches"][0];
|
||||
pageX = touch.pageX;
|
||||
pageY = touch.pageY;
|
||||
} else {
|
||||
pageX = e["pageX"];
|
||||
pageY = e["pageY"];
|
||||
}
|
||||
const elInfo = box.value.getBoundingClientRect();
|
||||
const clipInfo = clipRef.value.getBoundingClientRect();
|
||||
// 鼠标相对元素的位置
|
||||
const CX = pageX - clipInfo.x;
|
||||
const CY = pageY - clipInfo.y;
|
||||
|
||||
const mousemove = (e: MouseEvent | TouchEvent) => {
|
||||
e.preventDefault();
|
||||
var pageX = 0;
|
||||
var pageY = 0;
|
||||
if (e.type == "touchmove") {
|
||||
const touch = e["touches"][0];
|
||||
pageX = touch.pageX;
|
||||
pageY = touch.pageY;
|
||||
} else {
|
||||
pageX = e["pageX"];
|
||||
pageY = e["pageY"];
|
||||
}
|
||||
let x = pageX - elInfo.x - CX;
|
||||
let y = pageY - elInfo.y - CY;
|
||||
if (x < 0) {
|
||||
x = 0;
|
||||
} else if (x > elInfo.width - clipInfo.width) {
|
||||
x = elInfo.width - clipInfo.width;
|
||||
}
|
||||
if (y < 0) {
|
||||
y = 0;
|
||||
} else if (y > elInfo.height - clipInfo.height) {
|
||||
y = elInfo.height - clipInfo.height;
|
||||
}
|
||||
|
||||
clipData.top = y;
|
||||
clipData.left = x;
|
||||
clipData.img_width = elInfo.width;
|
||||
clipData.img_height = elInfo.height;
|
||||
};
|
||||
const mouseup = () => {
|
||||
window.removeEventListener("mousemove", mousemove);
|
||||
window.removeEventListener("mouseup", mouseup);
|
||||
window.removeEventListener("touchmove", mousemove);
|
||||
window.removeEventListener("touchend", mouseup);
|
||||
};
|
||||
if (e.type == "touchstart") {
|
||||
window.addEventListener("touchmove", mousemove);
|
||||
window.addEventListener("touchend", mouseup);
|
||||
} else {
|
||||
window.addEventListener("mousemove", mousemove);
|
||||
window.addEventListener("mouseup", mouseup);
|
||||
}
|
||||
};
|
||||
|
||||
// 移动裁剪框的四个边框
|
||||
const mousedown = (
|
||||
e: MouseEvent | TouchEvent,
|
||||
type: "top" | "bottom" | "right" | "left"
|
||||
) => {
|
||||
const minWidth = 20;
|
||||
const minHeight = 20;
|
||||
const elInfo = box.value.getBoundingClientRect();
|
||||
const R = elInfo.width - clipData.left - clipData.width;
|
||||
const B = elInfo.height - clipData.top - clipData.height;
|
||||
|
||||
const mousemove = (e: MouseEvent | TouchEvent) => {
|
||||
var x = 0;
|
||||
var y = 0;
|
||||
if (e.type == "touchmove") {
|
||||
const touch = e["touches"][0];
|
||||
x = touch.pageX - elInfo.x;
|
||||
y = touch.pageY - elInfo.y;
|
||||
} else {
|
||||
x = e["pageX"] - elInfo.x;
|
||||
y = e["pageY"] - elInfo.y;
|
||||
}
|
||||
|
||||
if (type == "right") {
|
||||
let width = x - clipData.left;
|
||||
if (width + clipData.left > elInfo.width) {
|
||||
width = elInfo.width - clipData.left;
|
||||
}
|
||||
if (width < minWidth) width = minWidth;
|
||||
clipData.width = width;
|
||||
} else if (type == "bottom") {
|
||||
let height = y - clipData.top;
|
||||
if (height + clipData.top > elInfo.height) {
|
||||
height = elInfo.height - clipData.top;
|
||||
}
|
||||
if (height < minHeight) height = minHeight;
|
||||
clipData.height = height;
|
||||
} else if (type == "left") {
|
||||
let left = x;
|
||||
let width = clipData.width;
|
||||
if (left < 0) {
|
||||
left = 0;
|
||||
} else if (left > elInfo.width - R - minWidth) {
|
||||
left = elInfo.width - R - minWidth;
|
||||
}
|
||||
width = elInfo.width - R - left;
|
||||
clipData.left = left;
|
||||
clipData.width = width;
|
||||
clipData.img_width = elInfo.width;
|
||||
clipData.img_height = elInfo.height;
|
||||
} else if (type == "top") {
|
||||
let top = y;
|
||||
let height = clipData.height;
|
||||
if (top < 0) {
|
||||
top = 0;
|
||||
} else if (top > elInfo.height - B - minHeight) {
|
||||
top = elInfo.height - B - minHeight;
|
||||
}
|
||||
height = elInfo.height - B - top;
|
||||
clipData.top = top;
|
||||
clipData.height = height;
|
||||
clipData.img_height = elInfo.height;
|
||||
}
|
||||
};
|
||||
const mouseup = () => {
|
||||
window.removeEventListener("mousemove", mousemove);
|
||||
window.removeEventListener("mouseup", mouseup);
|
||||
window.removeEventListener("touchmove", mousemove);
|
||||
window.removeEventListener("touchend", mouseup);
|
||||
};
|
||||
if (e.type == "touchstart") {
|
||||
window.addEventListener("touchmove", mousemove);
|
||||
window.addEventListener("touchend", mouseup);
|
||||
} else {
|
||||
window.addEventListener("mousemove", mousemove);
|
||||
window.addEventListener("mouseup", mouseup);
|
||||
}
|
||||
};
|
||||
const topMousedown = (e: MouseEvent | TouchEvent) => {
|
||||
mousedown(e, "top");
|
||||
};
|
||||
const rightMousedown = (e: MouseEvent | TouchEvent) => {
|
||||
mousedown(e, "right");
|
||||
};
|
||||
const bottomMousedown = (e: MouseEvent | TouchEvent) => {
|
||||
mousedown(e, "bottom");
|
||||
};
|
||||
const leftMousedown = (e: MouseEvent | TouchEvent) => {
|
||||
mousedown(e, "left");
|
||||
};
|
||||
defineExpose({
|
||||
open,
|
||||
close,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
/* 弹窗遮罩层 */
|
||||
.crop-image-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: rgba(255, 255, 255, 0.5);
|
||||
backdrop-filter: blur(5px);
|
||||
-webkit-backdrop-filter: blur(5px);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 1001;
|
||||
animation: fadeIn 0.3s ease;
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* 弹窗主体 */
|
||||
.crop-image-modal {
|
||||
background-color: #fff;
|
||||
border-radius: 12px;
|
||||
width: 80%;
|
||||
height: 80%;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1), 0 0 0 1px rgba(0, 0, 0, 0.05);
|
||||
animation: modalSlideUp 0.3s ease;
|
||||
}
|
||||
|
||||
@keyframes modalSlideUp {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(20px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* 弹窗头部 */
|
||||
.modal-header {
|
||||
padding: 16px 20px;
|
||||
background-color: rgba(255, 255, 255, 0.8);
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.05);
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
flex-shrink: 0;
|
||||
|
||||
h3 {
|
||||
margin: 0;
|
||||
font-size: 18px;
|
||||
color: #333;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
||||
.close-btn {
|
||||
background: none;
|
||||
border: none;
|
||||
font-size: 24px;
|
||||
cursor: pointer;
|
||||
color: #666;
|
||||
padding: 0;
|
||||
line-height: 1;
|
||||
opacity: 0.7;
|
||||
transition: all 0.2s;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
color: #333;
|
||||
transform: scale(1.1);
|
||||
}
|
||||
}
|
||||
|
||||
/* 弹窗内容 */
|
||||
.modal-content {
|
||||
// padding: 20px;
|
||||
overflow: hidden;
|
||||
flex: 1;
|
||||
background-color: #fff;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
display: flex;
|
||||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKAQMAAAC3/F3+AAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAGUExURf///9ra2sgNdccAAAARSURBVAjXY2A/wICMfjAgIwB8gwi84a8abQAAAABJRU5ErkJggg==);
|
||||
}
|
||||
|
||||
.image-clip {
|
||||
user-select: none;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
> .box {
|
||||
position: relative;
|
||||
> img {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
> .shade {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
> .clip {
|
||||
position: absolute;
|
||||
cursor: move;
|
||||
outline: 1px solid #39f;
|
||||
|
||||
> * {
|
||||
position: absolute;
|
||||
}
|
||||
> .img {
|
||||
pointer-events: none;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
> img {
|
||||
position: absolute;
|
||||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKAQMAAAC3/F3+AAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAGUExURf///9ra2sgNdccAAAARSURBVAjXY2A/wICMfjAgIwB8gwi84a8abQAAAABJRU5ErkJggg==);
|
||||
}
|
||||
}
|
||||
|
||||
> .top {
|
||||
cursor: n-resize;
|
||||
}
|
||||
> .bottom {
|
||||
cursor: s-resize;
|
||||
}
|
||||
> .right {
|
||||
cursor: e-resize;
|
||||
}
|
||||
> .left {
|
||||
cursor: w-resize;
|
||||
}
|
||||
|
||||
--border: 4px;
|
||||
--trbl: calc(0px - var(--border) / 2);
|
||||
--ball-size: 8px;
|
||||
--ball-trbl: calc(0px - var(--ball-size) / 2);
|
||||
> div.top {
|
||||
top: var(--trbl);
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: var(--border);
|
||||
}
|
||||
|
||||
> div.bottom {
|
||||
bottom: var(--trbl);
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: var(--border);
|
||||
}
|
||||
> div.left {
|
||||
top: 0;
|
||||
left: var(--trbl);
|
||||
bottom: 0;
|
||||
width: var(--border);
|
||||
}
|
||||
> div.right {
|
||||
top: 0;
|
||||
right: var(--trbl);
|
||||
bottom: 0;
|
||||
width: var(--border);
|
||||
}
|
||||
> span {
|
||||
position: absolute;
|
||||
width: var(--ball-size);
|
||||
height: var(--ball-size);
|
||||
border-radius: 50%;
|
||||
background-color: #39f;
|
||||
}
|
||||
> span.top {
|
||||
top: var(--ball-trbl);
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
> span.right {
|
||||
right: var(--ball-trbl);
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
> span.bottom {
|
||||
bottom: var(--ball-trbl);
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
> span.left {
|
||||
left: var(--ball-trbl);
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 空状态 */
|
||||
.empty-state {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 60px 20px;
|
||||
color: #666;
|
||||
min-height: 300px;
|
||||
|
||||
.empty-icon {
|
||||
font-size: 48px;
|
||||
margin-bottom: 16px;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: 16px;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* 弹窗底部 */
|
||||
.modal-footer {
|
||||
padding: 16px 20px;
|
||||
background-color: rgba(255, 255, 255, 0.8);
|
||||
border-top: 1px solid rgba(0, 0, 0, 0.05);
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
flex-shrink: 0;
|
||||
> .image-submit {
|
||||
font-size: 1.2rem;
|
||||
line-height: 4rem;
|
||||
}
|
||||
}
|
||||
|
||||
.image-count {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* 响应式设计 */
|
||||
@media screen and (max-width: 1024px) {
|
||||
.crop-image-modal {
|
||||
width: 95%;
|
||||
max-width: 900px;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.modal-header,
|
||||
.modal-footer {
|
||||
padding: 14px 16px;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 640px) {
|
||||
.crop-image-modal {
|
||||
width: 98%;
|
||||
margin: 10px;
|
||||
max-height: 90vh;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
padding: 12px;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.modal-header h3 {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.image-categories {
|
||||
gap: 8px;
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
|
||||
.category-btn {
|
||||
padding: 6px 12px;
|
||||
font-size: 13px;
|
||||
height: 32px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -21,6 +21,7 @@ const props = defineProps({
|
||||
type: Boolean,
|
||||
default: true, // 是否显示图层面板
|
||||
},
|
||||
isBackgroundChangeable: Boolean,
|
||||
});
|
||||
|
||||
const emit = defineEmits([
|
||||
@@ -312,7 +313,7 @@ onMounted(() => {
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
<div class="setting-group">
|
||||
<div class="setting-group" v-if="isBackgroundChangeable">
|
||||
<span class="setting-label">{{ $t("Canvas.color") }}</span>
|
||||
<div class="color-picker-wrapper">
|
||||
<input
|
||||
|
||||
@@ -1667,6 +1667,7 @@ function stopPressTimer() {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 22px;
|
||||
|
||||
> i{
|
||||
font-size: 1.4rem;
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
v-for="v in activeObjects"
|
||||
:key="v.id"
|
||||
>
|
||||
<div class="title">图层1</div>
|
||||
<div class="title">{{ v.layer?.name }}</div>
|
||||
<div class="list">
|
||||
<div>
|
||||
<span class="label">W</span>
|
||||
@@ -52,17 +52,27 @@
|
||||
<span class="label iconfont icon-angle"></span>
|
||||
<input
|
||||
type="number"
|
||||
:value="v.angle"
|
||||
disabled
|
||||
:value="Number(Number(v.angle).toFixed(3))"
|
||||
@change="(e) => changeAngle(e, v)"
|
||||
/>
|
||||
</div>
|
||||
<div class="btn" @click="clickflipHorizontal">
|
||||
<div class="btn" @click="clickflipHorizontal(v)">
|
||||
<i class="iconfont icon-flip-horizontal"></i>
|
||||
<p class="tip">水平翻转</p>
|
||||
<p class="tip">
|
||||
{{ t("Canvas.flipHorizontal") }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="btn" @click="clickflipVertical">
|
||||
<div class="btn" @click="clickflipVertical(v)">
|
||||
<i class="iconfont icon-flip-vertical"></i>
|
||||
<p class="tip">垂直翻转</p>
|
||||
<p class="tip">
|
||||
{{ t("Canvas.flipVertical") }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="btn" @click="clickCropImage(v)">
|
||||
<i class="iconfont icon-caijian"></i>
|
||||
<p class="tip">
|
||||
{{ t("Canvas.cropAndAdd") }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -73,10 +83,13 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import showViewVideo from "@/tool/mount";
|
||||
import { ref, onMounted, watch, onUnmounted } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { ToolCommand } from "../commands/ToolCommands";
|
||||
import { OperationType } from "../utils/layerHelper";
|
||||
import { loadImageUrlToLayer } from "../utils/imageHelper";
|
||||
import { TransformCommand } from "../commands/StateCommands";
|
||||
const props = defineProps({
|
||||
canvas: {
|
||||
type: Object,
|
||||
@@ -140,7 +153,7 @@
|
||||
* 显示面板
|
||||
*/
|
||||
function show() {
|
||||
if(activeObjects.value.length === 0) return;
|
||||
if (activeObjects.value.length === 0) return;
|
||||
visible.value = true;
|
||||
closePanel.value = true;
|
||||
}
|
||||
@@ -155,20 +168,141 @@
|
||||
const activeObjects = ref([]);
|
||||
const getActiveObject = (e) => {
|
||||
console.log("==========切换激活对象", e);
|
||||
activeObjects.value = e.selected.map((v) => v.toObject());
|
||||
activeObjects.value = e.selected.map((v) => v);
|
||||
activeObjects.value.forEach((v) => {
|
||||
v.layer = props.layerManager.getLayerById(v.layerId);
|
||||
});
|
||||
if (activeObjects.value.length === 0) {
|
||||
close();
|
||||
} else {
|
||||
show(false);
|
||||
}
|
||||
};
|
||||
const clickflipHorizontal = () => {
|
||||
console.log("水平翻转");
|
||||
};
|
||||
const clickflipVertical = () => {
|
||||
console.log("垂直翻转");
|
||||
const lastSelectLayerId = inject("lastSelectLayerId");
|
||||
const layers = inject("layers");
|
||||
const transformObject = (activeObj, initialState, finalState) => {
|
||||
const transformCmd = new TransformCommand({
|
||||
canvas: props.canvas,
|
||||
objectId: activeObj.id,
|
||||
initialState,
|
||||
finalState,
|
||||
objectType: activeObj.type,
|
||||
name: `变换 ${activeObj.type || "对象"}`,
|
||||
layerManager: props.layerManager,
|
||||
layers: layers,
|
||||
lastSelectLayerId: lastSelectLayerId,
|
||||
});
|
||||
props.layerManager.commandManager.execute(transformCmd, {
|
||||
name: "对象修改",
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 根据左上角坐标计算旋转后的新坐标
|
||||
* @param {number} W - 宽度
|
||||
* @param {number} H - 高度
|
||||
* @param {number} currentX - 当前左上角x坐标
|
||||
* @param {number} currentY - 当前左上角y坐标
|
||||
* @param {number} currentAngleDeg - 当前角度(度)
|
||||
* @param {number} newAngleDeg - 新角度(度)
|
||||
* @returns {Object} 旋转后的左上角坐标 {x, y}
|
||||
*/
|
||||
function calculateRotatedTopLeftDeg(
|
||||
W,
|
||||
H,
|
||||
currentX,
|
||||
currentY,
|
||||
currentAngleDeg,
|
||||
newAngleDeg
|
||||
) {
|
||||
const currentAngle = (currentAngleDeg * Math.PI) / 180;
|
||||
const newAngle = (newAngleDeg * Math.PI) / 180;
|
||||
// 1. 用当前角度计算中心点位置
|
||||
const cosCurrent = Math.cos(currentAngle);
|
||||
const sinCurrent = Math.sin(currentAngle);
|
||||
const Cx = currentX + (W / 2) * cosCurrent - (H / 2) * sinCurrent;
|
||||
const Cy = currentY + (W / 2) * sinCurrent + (H / 2) * cosCurrent;
|
||||
|
||||
// 2. 用新角度计算旋转后的左上角位置
|
||||
const cosNew = Math.cos(newAngle);
|
||||
const sinNew = Math.sin(newAngle);
|
||||
const newX = Cx + (-W / 2) * cosNew - (-H / 2) * sinNew;
|
||||
const newY = Cy + (-W / 2) * sinNew + (-H / 2) * cosNew;
|
||||
|
||||
return { x: newX, y: newY };
|
||||
}
|
||||
// 改变角度
|
||||
const changeAngle = (e, obj) => {
|
||||
const initialState = TransformCommand.captureTransformState(obj);
|
||||
const finalState = { ...initialState };
|
||||
const angle = e.target.value;
|
||||
if (obj.originX === "left" && obj.originY === "top") {
|
||||
const width = obj.width * obj.scaleX;
|
||||
const height = obj.height * obj.scaleY;
|
||||
const left = obj.left;
|
||||
const top = obj.top;
|
||||
const { x, y } = calculateRotatedTopLeftDeg(
|
||||
width,
|
||||
height,
|
||||
left,
|
||||
top,
|
||||
obj.angle,
|
||||
angle
|
||||
);
|
||||
finalState.left = x;
|
||||
finalState.top = y;
|
||||
}
|
||||
finalState.angle = angle;
|
||||
transformObject(obj, initialState, finalState);
|
||||
};
|
||||
// 水平翻转
|
||||
const clickflipHorizontal = (obj) => {
|
||||
const initialState = TransformCommand.captureTransformState(obj);
|
||||
const finalState = { ...initialState };
|
||||
finalState.flipX = !finalState.flipX;
|
||||
transformObject(obj, initialState, finalState);
|
||||
};
|
||||
// 垂直翻转
|
||||
const clickflipVertical = (obj) => {
|
||||
const initialState = TransformCommand.captureTransformState(obj);
|
||||
const finalState = { ...initialState };
|
||||
finalState.flipY = !finalState.flipY;
|
||||
transformObject(obj, initialState, finalState);
|
||||
};
|
||||
// 裁剪图片
|
||||
const cropImage = inject("cropImage");
|
||||
const clickCropImage = async (obj) => {
|
||||
const base64 = await props.layerManager.getLayerToBase64(obj.layerId);
|
||||
if(base64) cropImage(base64).then((res) => {
|
||||
loadImageUrlToLayer({
|
||||
imageUrl: res,
|
||||
layerManager: props.layerManager,
|
||||
canvas: props.canvas,
|
||||
toolManager: props.toolManager,
|
||||
})
|
||||
});
|
||||
};
|
||||
|
||||
const updateActiveObjects = (arrs, keys) => {
|
||||
arrs.forEach((v) => {
|
||||
activeObjects.value.forEach((item) => {
|
||||
if (item.id === v.id) {
|
||||
keys.forEach((key) => (item[key] = v[key]));
|
||||
}
|
||||
});
|
||||
activeObjects.value = [...activeObjects.value];
|
||||
});
|
||||
};
|
||||
|
||||
const objectRotatingChange = (e) => {
|
||||
const arrs = [];
|
||||
if (e.target._objects) {
|
||||
e.target._objects.forEach((v) => arrs.push(v));
|
||||
} else {
|
||||
arrs.push(e.target);
|
||||
}
|
||||
updateActiveObjects(arrs, ["angle"]);
|
||||
};
|
||||
|
||||
/**
|
||||
* 设置画布事件监听
|
||||
@@ -178,8 +312,8 @@
|
||||
// 鼠标事件
|
||||
props.canvas.on("selection:created", getActiveObject);
|
||||
props.canvas.on("selection:updated", getActiveObject);
|
||||
// props.canvas.on("selection:cleared", () => console.log("selection:cleared"));
|
||||
props.canvas.on("selection:cleared", close);
|
||||
props.canvas.on("object:rotating", objectRotatingChange);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -191,7 +325,8 @@
|
||||
// 移除鼠标事件
|
||||
props.canvas.off("selection:created", getActiveObject);
|
||||
props.canvas.off("selection:updated", getActiveObject);
|
||||
// props.canvas.off("selection:cleared");
|
||||
props.canvas.off("selection:cleared", close);
|
||||
props.canvas.off("object:rotating", objectRotatingChange);
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -531,10 +531,13 @@ function confirmColorPicker() {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 22px;
|
||||
|
||||
> i{
|
||||
font-size: 1.4rem;
|
||||
display: block;
|
||||
transform: rotate(270deg);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -619,10 +619,20 @@ export default {
|
||||
onMounted(() => {
|
||||
// 监听显示文本编辑面板事件
|
||||
document.addEventListener("showTextEditor", showEditor);
|
||||
document.addEventListener("hideTextEditor", close);
|
||||
if(props.canvas) {
|
||||
// props.canvas.on("text:editing:entered", showEditor);
|
||||
props.canvas.on("text:editing:exited", close);
|
||||
}
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
document.removeEventListener("showTextEditor", showEditor);
|
||||
document.removeEventListener("hideTextEditor", close);
|
||||
if(props.canvas) {
|
||||
// props.canvas.off("text:editing:entered", showEditor);
|
||||
props.canvas.off("text:editing:exited", close);
|
||||
}
|
||||
});
|
||||
|
||||
// 返回所有需要在模板中使用的数据和方法
|
||||
@@ -715,7 +725,10 @@ export default {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 22px;
|
||||
> i{
|
||||
font-size: 1.4rem;
|
||||
display: block;
|
||||
|
||||
@@ -395,9 +395,15 @@ const handleToolClick = (tool) => {
|
||||
height: 100%;
|
||||
padding-top: .5rem;
|
||||
padding-bottom: 4rem;
|
||||
position: relative;
|
||||
/* overflow-y: auto; */
|
||||
/* overflow-x: hidden; */
|
||||
}
|
||||
.fillColor-input{
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
}
|
||||
.tools-list{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
31
src/component/Canvas/CanvasEditor/fabric-canvas-events.md
Normal file
@@ -0,0 +1,31 @@
|
||||
### 鼠标事件
|
||||
|
||||
- `mouse:down`:鼠标按下时触发
|
||||
- `mouse:up`:鼠标释放时触发
|
||||
- `mouse:move`:鼠标移动时触发
|
||||
- `mouse:over`:鼠标移入画布时触发
|
||||
- `mouse:out`:鼠标移出画布时触发
|
||||
|
||||
### 对象交互事件
|
||||
|
||||
- `object:selected`:对象被选中时触发
|
||||
- `object:modified`:对象属性(如位置、大小)修改后触发
|
||||
- `object:rotating`:对象旋转过程中触发
|
||||
- `object:scaling`:对象缩放过程中触发
|
||||
- `object:skewing`:对象倾斜过程中触发
|
||||
|
||||
### 画布操作事件
|
||||
|
||||
- `before:render`:画布即将重绘前触发
|
||||
- `after:render`:画布重绘完成后触发
|
||||
- `selection:created`:选中对象集合创建时触发
|
||||
- `selection:updated`:选中对象集合更新时触发
|
||||
- `selection:cleared`:选中对象集合清除时触发
|
||||
|
||||
### 其他事件
|
||||
|
||||
- `object:added`:对象添加到画布时触发
|
||||
- `object:removed`:对象从画布移除时触发
|
||||
- `object:rotated`:对象旋转完成时触发
|
||||
- `object:scaled`:对象缩放完成时触发
|
||||
- `object:skewed`:对象倾斜完成时触发
|
||||
@@ -23,6 +23,7 @@ import { BrushStore } from "./store/BrushStore";
|
||||
import cuowuImg from "@/assets/images/homePage/cuowu.svg";
|
||||
import { Https } from "@/tool/https";
|
||||
import SelectImages from "@/component/common/SelectImages.vue";
|
||||
import CropImage from "./components/CropImage.vue";
|
||||
import { UrlToFile } from "@/tool/util";
|
||||
|
||||
// import { MinimapManager } from "./managers/minimap/MinimapManager";
|
||||
@@ -100,7 +101,10 @@ const props = defineProps({
|
||||
type: Boolean,
|
||||
default: false, // 是否允许擦除背景图层
|
||||
},
|
||||
|
||||
isBackgroundChangeable: {
|
||||
type: Boolean,
|
||||
default: true, // 是否允许修改背景图层
|
||||
},
|
||||
showFixedLayer: {
|
||||
type: Boolean,
|
||||
default: false, // 是否显示固定图层
|
||||
@@ -126,6 +130,7 @@ const canvasRef = ref(null);
|
||||
const canvasContainerRef = shallowRef(null);
|
||||
const imageUploadRef = ref(null);
|
||||
const currentZoom = ref(100);
|
||||
const appContainerRef = ref(null);
|
||||
|
||||
// 画布设置
|
||||
const canvasWidth = ref(props.config.width);
|
||||
@@ -303,6 +308,20 @@ onMounted(async () => {
|
||||
commandManager,
|
||||
layerManager,
|
||||
toolManager,
|
||||
isRedGreenMode,
|
||||
pasteText: (text) => {
|
||||
// console.log("粘贴的文本:", text);
|
||||
handleAddText(text);
|
||||
},
|
||||
pasteImage: (file) => {
|
||||
// console.log("粘贴的图片:", file);
|
||||
uploadImageAndCreateLayer({
|
||||
file,
|
||||
layerManager,
|
||||
toolManager,
|
||||
canvas: canvasManager.canvas,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
// 绑定快捷键事件
|
||||
@@ -515,15 +534,15 @@ onBeforeUnmount(() => {
|
||||
// return; // 开发环境下不卸载组件
|
||||
// }
|
||||
console.log("onBeforeUnmount 组件卸载,清理资源...");
|
||||
// canvasManager?.dispose?.();
|
||||
// commandManager?.dispose?.();
|
||||
// layerManager?.dispose?.();
|
||||
// keyboardManager?.dispose?.();
|
||||
// toolManager?.dispose?.();
|
||||
// liquifyManager?.dispose?.();
|
||||
// selectionManager?.dispose?.();
|
||||
// redGreenModeManager?.dispose?.();
|
||||
// minimapManager?.dispose?.();
|
||||
canvasManager?.dispose?.();
|
||||
commandManager?.dispose?.();
|
||||
layerManager?.dispose?.();
|
||||
keyboardManager?.dispose?.();
|
||||
toolManager?.dispose?.();
|
||||
liquifyManager?.dispose?.();
|
||||
selectionManager?.dispose?.();
|
||||
redGreenModeManager?.dispose?.();
|
||||
// minimapManager?.dispose?.();
|
||||
canvasManager = null;
|
||||
commandManager = null;
|
||||
layerManager = null;
|
||||
@@ -786,11 +805,11 @@ function triggerLibrary() {
|
||||
}
|
||||
}
|
||||
|
||||
function handleAddText() {
|
||||
function handleAddText(text) {
|
||||
if (toolManager && canvasManager && canvasManager.canvas) {
|
||||
// 在画布中央创建文本
|
||||
const canvasCenter = canvasManager.canvas.getCenter();
|
||||
toolManager.createText(canvasCenter.left, canvasCenter.top);
|
||||
toolManager.createText(canvasCenter.left, canvasCenter.top, text);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -894,6 +913,41 @@ const changeCanvas = async (command) => {
|
||||
}
|
||||
};
|
||||
|
||||
const cropImageRef = ref(null);
|
||||
const cropImage = (url) => {
|
||||
return cropImageRef.value.open(url)
|
||||
};
|
||||
provide("cropImage", cropImage); // 提供给子组件使用
|
||||
|
||||
// 处理画布容器的拖放事件
|
||||
const isDragOver = ref(false);
|
||||
const canvasDragover = (e) => {
|
||||
e.preventDefault();
|
||||
if (isRedGreenMode.value) return;
|
||||
const types = e.dataTransfer.types;
|
||||
isDragOver.value = types.includes("Files");
|
||||
};
|
||||
|
||||
// 处理画布容器的拖离事件
|
||||
const canvasDragleave = (e) => {
|
||||
e.preventDefault();
|
||||
if (isRedGreenMode.value) return;
|
||||
isDragOver.value = false;
|
||||
};
|
||||
|
||||
// 处理画布容器的拖放事件
|
||||
const canvasDragdrop = (e) => {
|
||||
e.preventDefault();
|
||||
if (isRedGreenMode.value) return;
|
||||
isDragOver.value = false;
|
||||
const files = e.dataTransfer.files;
|
||||
for (const file of files) {
|
||||
if (file.type.startsWith("image/")) {
|
||||
handleImageUpload({ target: { files: [file] } });
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 提供外部ref实例方法
|
||||
defineExpose({
|
||||
layers, // 图层数据
|
||||
@@ -1084,7 +1138,13 @@ defineExpose({
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<div
|
||||
ref="appContainerRef"
|
||||
class="app-container"
|
||||
@dragover.stop="canvasDragover"
|
||||
@dragleave.stop="canvasDragleave"
|
||||
@drop.stop="canvasDragdrop"
|
||||
>
|
||||
<!-- 头部菜单组件 -->
|
||||
<div class="header-menu">
|
||||
<HeaderMenu
|
||||
@@ -1096,6 +1156,7 @@ defineExpose({
|
||||
:brushSize="brushSize"
|
||||
:enabledRedGreenMode="enabledRedGreenMode"
|
||||
:showLayersPanel="showLayersPanel"
|
||||
:isBackgroundChangeable="isBackgroundChangeable"
|
||||
@update:canvasWidth="canvasWidth = $event"
|
||||
@update:canvasHeight="canvasHeight = $event"
|
||||
@update:canvasColor="canvasColor = $event"
|
||||
@@ -1156,13 +1217,6 @@ defineExpose({
|
||||
:activeTool="activeTool"
|
||||
/>
|
||||
|
||||
<!-- 文本编辑面板 -->
|
||||
<TextEditorPanel
|
||||
v-if="canvasManagerLoaded && !enabledRedGreenMode"
|
||||
:canvas="canvasManager && canvasManager.canvas"
|
||||
:commandManager="commandManager"
|
||||
/>
|
||||
|
||||
<!-- 液化编辑面板 -->
|
||||
<LiquifyPanel
|
||||
v-if="canvasManagerLoaded && !enabledRedGreenMode"
|
||||
@@ -1185,7 +1239,7 @@ defineExpose({
|
||||
/>
|
||||
|
||||
<!-- 选择工具菜单组件 -->
|
||||
<!-- <SelectMenuPanel
|
||||
<SelectMenuPanel
|
||||
v-if="canvasManagerLoaded && !enabledRedGreenMode"
|
||||
:canvas="canvasManager && canvasManager.canvas"
|
||||
:commandManager="commandManager"
|
||||
@@ -1193,7 +1247,14 @@ defineExpose({
|
||||
:layerManager="layerManager"
|
||||
:toolManager="toolManager"
|
||||
:activeTool="activeTool"
|
||||
/> -->
|
||||
/>
|
||||
|
||||
<!-- 文本编辑面板 -->
|
||||
<TextEditorPanel
|
||||
v-if="canvasManagerLoaded && !enabledRedGreenMode"
|
||||
:canvas="canvasManager && canvasManager.canvas"
|
||||
:commandManager="commandManager"
|
||||
/>
|
||||
|
||||
<div class="zoom-info">
|
||||
{{ t("Canvas.Scale") }}: {{ currentZoom }}%
|
||||
@@ -1236,6 +1297,9 @@ defineExpose({
|
||||
/>
|
||||
</div>
|
||||
</transition>
|
||||
|
||||
<!-- 裁剪图片组件 -->
|
||||
<CropImage ref="cropImageRef" />
|
||||
</div>
|
||||
|
||||
<!-- <div class="footer-actions">
|
||||
@@ -1270,6 +1334,8 @@ defineExpose({
|
||||
:api="Https.httpUrls.queryLibraryPage"
|
||||
isLibrary
|
||||
/>
|
||||
<!-- 上传图片遮罩 -->
|
||||
<div v-show="isDragOver" class="dragover-tip"></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -1302,6 +1368,21 @@ defineExpose({
|
||||
border-bottom: 1px solid #e0e0e0;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
>.dragover-tip{
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #fff;
|
||||
font-size: 1.6rem;
|
||||
z-index: 9999;
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
|
||||
.main-content {
|
||||
|
||||
@@ -2,11 +2,12 @@ import { FillGroupLayerBackgroundCommand } from "../commands/FillGroupLayerBackg
|
||||
import { FillLayerBackgroundCommand } from "../commands/FillLayerBackgroundCommand";
|
||||
|
||||
export class BackgroundFillManager {
|
||||
constructor({ canvas, layers, commandManager, canvasManager }) {
|
||||
constructor({ canvas, layers, commandManager, canvasManager, layerManager }) {
|
||||
this.canvas = canvas;
|
||||
this.layers = layers;
|
||||
this.commandManager = commandManager;
|
||||
this.canvasManager = canvasManager;
|
||||
this.layerManager = layerManager;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -28,6 +29,7 @@ export class BackgroundFillManager {
|
||||
layerId,
|
||||
fillColor,
|
||||
canvasManager: this.canvasManager,
|
||||
layerManager: this.layerManager,
|
||||
// 是否实时更新
|
||||
isRetimeUpdate: !undoable,
|
||||
});
|
||||
|
||||
@@ -406,7 +406,8 @@ export class BrushIndicator {
|
||||
this._mouseMoveHandler = (e) => {
|
||||
if (this._shouldShowIndicator()) {
|
||||
if (!this.isVisible) {
|
||||
this.show(e.e);
|
||||
// this.show(e.e);
|
||||
this._mouseEnterHandler && this._mouseEnterHandler(e)
|
||||
} else {
|
||||
// requestIdleCallback(() => {
|
||||
// this.updatePosition(e.e);
|
||||
@@ -433,7 +434,6 @@ export class BrushIndicator {
|
||||
*/
|
||||
_unbindEvents() {
|
||||
if (!this.canvas) return;
|
||||
|
||||
// 解绑鼠标事件
|
||||
if (this._mouseEnterHandler) {
|
||||
this.canvas.off("mouse:over", this._mouseEnterHandler);
|
||||
|
||||
@@ -109,6 +109,7 @@ export class LayerManager {
|
||||
layers: this.layers,
|
||||
commandManager: this.commandManager,
|
||||
canvasManager: this.canvasManager,
|
||||
layerManager: this,
|
||||
});
|
||||
|
||||
// 编辑器模式:draw(绘画)、select(选择)、pan(拖拽)
|
||||
@@ -1194,7 +1195,7 @@ export class LayerManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* 选择图层下的所有对象
|
||||
* 选择图层下的所有画布对象
|
||||
* @param {string} layerId 图层ID
|
||||
* @returns {fabric.ActiveSelection|null} 返回活动选择组或null
|
||||
*/
|
||||
@@ -1219,6 +1220,10 @@ export class LayerManager {
|
||||
}
|
||||
// 切换到选择模式
|
||||
this?.toolManager?.setTool(OperationType.SELECT);
|
||||
if(objects.length === 1) {
|
||||
this.canvas.setActiveObject(objects[0]);
|
||||
return objects[0];
|
||||
}
|
||||
// 创建一个新的活动选择组
|
||||
const activeSelection = new fabric.ActiveSelection(objects, {
|
||||
canvas: this.canvas,
|
||||
@@ -1813,7 +1818,12 @@ export class LayerManager {
|
||||
|
||||
// 存储到剪贴板
|
||||
this.clipboardData = layerCopy;
|
||||
|
||||
const input = document.createElement("input");
|
||||
input.value = "aida_copy_canvas_layer: " + layer.name;
|
||||
document.body.appendChild(input);
|
||||
input.select();
|
||||
document.execCommand("copy");
|
||||
document.body.removeChild(input);
|
||||
console.log(`已复制图层:${layer.name}`);
|
||||
|
||||
return this.clipboardData;
|
||||
@@ -1912,7 +1922,8 @@ export class LayerManager {
|
||||
* 粘贴图层
|
||||
* @returns {string} 新创建的图层ID
|
||||
*/
|
||||
async pasteLayer() {
|
||||
async pasteLayer(event) {
|
||||
console.log("剪贴板数据:", this.clipboardData,event);
|
||||
if (!this.clipboardData) {
|
||||
console.error("剪贴板中没有图层数据");
|
||||
return null;
|
||||
@@ -2292,9 +2303,9 @@ export class LayerManager {
|
||||
*/
|
||||
dispose() {
|
||||
// 清空画布
|
||||
if (this.canvas) {
|
||||
this.canvas.clear();
|
||||
}
|
||||
// if (this.canvas) {
|
||||
// this.canvas.clear();
|
||||
// }
|
||||
|
||||
// 清空图层数据
|
||||
if (this.layers && this.layers.value) {
|
||||
@@ -3189,6 +3200,49 @@ export class LayerManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 栅格化图层并返回Base64编码
|
||||
* @param {string} layerId 图层ID,默认使用当前活动图层
|
||||
* @returns {Promise<string|null>} Base64编码的图像字符串,失败时返回null
|
||||
*/
|
||||
async getLayerToBase64(layerId = null) {
|
||||
const targetLayerId = layerId || this.activeLayerId.value;
|
||||
if (!targetLayerId) {
|
||||
console.warn(this.t("没有指定要栅格化的图层"));
|
||||
return null;
|
||||
}
|
||||
|
||||
// 查找目标图层
|
||||
// const targetLayer = this.getLayerById(targetLayerId);
|
||||
const { layer: targetLayer } = findLayerRecursively(
|
||||
this.layers.value,
|
||||
targetLayerId
|
||||
);
|
||||
|
||||
if (!targetLayer) {
|
||||
console.error(this.t("图层不存在", { layerId: targetLayerId }));
|
||||
return null;
|
||||
}
|
||||
|
||||
// 直接创建和执行导出命令
|
||||
const command = new ExportLayerToImageCommand({
|
||||
canvas: this.canvas,
|
||||
layers: this.layers,
|
||||
layerId: targetLayerId,
|
||||
activeLayerId: this.activeLayerId,
|
||||
layerManager: this,
|
||||
});
|
||||
|
||||
command.undoable = false; // 导出操作通常不需要撤销
|
||||
|
||||
// 执行命令
|
||||
const result = await command.execute(false);
|
||||
if (result) {
|
||||
console.log(`✅ 成功导出图层: ${targetLayer.name}`);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 为组图层的活动选择组设置遮罩移动同步(修复版)
|
||||
* @param {fabric.ActiveSelection} activeSelection 活动选择组
|
||||
|
||||
@@ -357,6 +357,9 @@ export class ToolManager {
|
||||
this.canvasManager?.layerManager?.updateLayersObjectsInteractivity?.();
|
||||
this.canvas?.renderAll();
|
||||
|
||||
// 隐藏文本编辑面板
|
||||
this.hideTextEditor();
|
||||
|
||||
// 如果切换到非画笔工具,禁用笔刷指示器
|
||||
if (!this._shouldShowBrushIndicator(toolId)) {
|
||||
this._disableBrushIndicator();
|
||||
@@ -1014,9 +1017,10 @@ export class ToolManager {
|
||||
* 创建文字对象并添加到画布
|
||||
* @param {Number} x 文本位置x坐标
|
||||
* @param {Number} y 文本位置y坐标
|
||||
* @param {Object} options 文本选项
|
||||
* @param {String} [text] 文本内容
|
||||
* @param {Object} [options] 文本选项
|
||||
*/
|
||||
async createText(x, y, options = {}) {
|
||||
async createText(x, y, text, options = {}) {
|
||||
// 使用命令模式创建文本
|
||||
if (!this.canvas || !this.layerManager) return null;
|
||||
if (this.commandManager) {
|
||||
@@ -1025,6 +1029,7 @@ export class ToolManager {
|
||||
layerManager: this.layerManager,
|
||||
x,
|
||||
y,
|
||||
text,
|
||||
textOptions: options,
|
||||
});
|
||||
// 执行命令
|
||||
@@ -1179,6 +1184,19 @@ export class ToolManager {
|
||||
})
|
||||
);
|
||||
}
|
||||
/**
|
||||
* 隐藏文本编辑面板
|
||||
*/
|
||||
hideTextEditor() {
|
||||
// 这个方法将在TextEditorPanel组件实现后调用
|
||||
console.log("隐藏文本编辑面板");
|
||||
// 将发出一个事件,让Vue组件捕获并隐藏编辑面板
|
||||
document.dispatchEvent(
|
||||
new CustomEvent("hideTextEditor", {
|
||||
detail: {},
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理资源
|
||||
|
||||
@@ -65,7 +65,7 @@ export class BrushManager {
|
||||
description: "基础铅笔工具,适合精细线条绘制",
|
||||
t:this.t,
|
||||
category: this.t('Canvas.BasicBrushes'),
|
||||
imgUrl:'./image/brush/pencil.jpg',
|
||||
imgUrl:'/image/brush/pencil.jpg',
|
||||
});
|
||||
|
||||
// 注册材质笔刷
|
||||
@@ -74,7 +74,7 @@ export class BrushManager {
|
||||
description: "使用纹理图片作为笔刷,支持缩放和透明度",
|
||||
t:this.t,
|
||||
category: this.t('Canvas.BasicBrushes'),
|
||||
imgUrl:'./image/brush/texture.jpg',
|
||||
imgUrl:'/image/brush/texture.jpg',
|
||||
});
|
||||
|
||||
// 注册集成的笔刷类型
|
||||
@@ -83,63 +83,63 @@ export class BrushManager {
|
||||
description: "使用纹理图片作为笔刷,支持缩放和透明度",
|
||||
t:this.t,
|
||||
category: this.t('Canvas.BasicBrushes'),
|
||||
imgUrl:'./image/brush/crayon.jpg',
|
||||
imgUrl:'/image/brush/crayon.jpg',
|
||||
});
|
||||
brushRegistry.register("fur", FurBrush, {
|
||||
name: this.t("Canvas.Fur"),
|
||||
description: "使用纹理图片作为笔刷,支持缩放和透明度",
|
||||
t:this.t,
|
||||
category: this.t('Canvas.BasicBrushes'),
|
||||
imgUrl:'./image/brush/fur.jpg',
|
||||
imgUrl:'/image/brush/fur.jpg',
|
||||
});
|
||||
brushRegistry.register("ink", InkBrush, {
|
||||
name: this.t("Canvas.Ink"),
|
||||
description: "墨水笔刷,适合书写和绘图",
|
||||
t:this.t,
|
||||
category: this.t('Canvas.BasicBrushes'),
|
||||
imgUrl:'./image/brush/ink.jpg',
|
||||
imgUrl:'/image/brush/ink.jpg',
|
||||
});
|
||||
brushRegistry.register("", LongfurBrush, {
|
||||
name: this.t("Canvas.Longfur"),
|
||||
description: "长毛发笔刷,适合绘制动物毛皮、草或头发",
|
||||
t:this.t,
|
||||
category: this.t('Canvas.BasicBrushes'),
|
||||
imgUrl:'./image/brush/longFur.jpg',
|
||||
imgUrl:'/image/brush/longFur.jpg',
|
||||
});
|
||||
brushRegistry.register("writing", WritingBrush, {
|
||||
name: this.t("Canvas.Writing"),
|
||||
description: "书法笔刷,模拟中国传统书法毛笔效果,具有笔锋和墨色变化",
|
||||
t:this.t,
|
||||
category: this.t('Canvas.BasicBrushes'),
|
||||
imgUrl:'./image/brush/writing.jpg',
|
||||
imgUrl:'/image/brush/writing.jpg',
|
||||
});
|
||||
brushRegistry.register("marker", MarkerBrush, {
|
||||
name: this.t("Canvas.Marker"),
|
||||
description: "马克笔笔刷,适合粗线条和填充",
|
||||
t:this.t,
|
||||
category: this.t('Canvas.BasicBrushes'),
|
||||
imgUrl:'./image/brush/marker.jpg',
|
||||
imgUrl:'/image/brush/marker.jpg',
|
||||
});
|
||||
brushRegistry.register("pen", CustomPenBrush, {
|
||||
name: this.t("Canvas.Pen"),
|
||||
description: "自定义钢笔笔刷,适合书写和绘图",
|
||||
t:this.t,
|
||||
category: this.t('Canvas.BasicBrushes'),
|
||||
imgUrl:'./image/brush/pen.jpg',
|
||||
imgUrl:'/image/brush/pen.jpg',
|
||||
});
|
||||
brushRegistry.register("ribbon", RibbonBrush, {
|
||||
name: this.t("Canvas.Ribbon"),
|
||||
description: "丝带笔刷,适合创建流动的丝带效果",
|
||||
t:this.t,
|
||||
category: this.t('Canvas.BasicBrushes'),
|
||||
imgUrl:'./image/brush/ribbon.jpg',
|
||||
imgUrl:'/image/brush/ribbon.jpg',
|
||||
});
|
||||
brushRegistry.register("shaded", ShadedBrush, {
|
||||
name: this.t("Canvas.Shaded"),
|
||||
description: "阴影笔刷,适合创建渐变和阴影效果",
|
||||
t:this.t,
|
||||
category: this.t('Canvas.BasicBrushes'),
|
||||
imgUrl:'./image/brush/shaded.jpg',
|
||||
imgUrl:'/image/brush/shaded.jpg',
|
||||
});
|
||||
|
||||
brushRegistry.register("spray", SprayBrush, {
|
||||
@@ -147,7 +147,7 @@ export class BrushManager {
|
||||
description: "模拟喷枪效果,创建散点效果",
|
||||
t:this.t,
|
||||
category: this.t('Canvas.BasicBrushes'),
|
||||
imgUrl:'./image/brush/spray.jpg',
|
||||
imgUrl:'/image/brush/spray.jpg',
|
||||
});
|
||||
|
||||
// brushRegistry.register("sketchy", SketchyBrush);
|
||||
|
||||
@@ -10,6 +10,9 @@ export class KeyboardManager {
|
||||
* @param {Object} options.toolManager 工具管理器实例
|
||||
* @param {Object} options.commandManager 命令管理器实例
|
||||
* @param {Object} options.layerManager 图层管理器实例
|
||||
* @param {Function} options.pasteText 粘贴文本回调函数
|
||||
* @param {Function} options.pasteImage 粘贴图片回调函数
|
||||
* @param {Ref<Boolean>} options.isRedGreenMode 是否为红绿模式
|
||||
* @param {HTMLElement} options.container 容器元素,用于添加事件监听
|
||||
*/
|
||||
constructor(options = {}) {
|
||||
@@ -17,6 +20,9 @@ export class KeyboardManager {
|
||||
this.commandManager = options.commandManager;
|
||||
this.layerManager = options.layerManager;
|
||||
this.container = options.container || document;
|
||||
this.pasteText = options.pasteText || (() => {});
|
||||
this.pasteImage = options.pasteImage || (() => {});
|
||||
this.isRedGreenMode = options.isRedGreenMode;
|
||||
|
||||
// 检测平台类型
|
||||
this.platform = this.detectPlatform();
|
||||
@@ -63,6 +69,7 @@ export class KeyboardManager {
|
||||
// 事件绑定
|
||||
this._handleKeyDown = this.handleKeyDown.bind(this);
|
||||
this._handleKeyUp = this.handleKeyUp.bind(this);
|
||||
this._handlePaste = this.handlePaste.bind(this);
|
||||
this._handleTouchStart = this.handleTouchStart.bind(this);
|
||||
this._handleTouchMove = this.handleTouchMove.bind(this);
|
||||
this._handleTouchEnd = this.handleTouchEnd.bind(this);
|
||||
@@ -112,7 +119,7 @@ export class KeyboardManager {
|
||||
|
||||
// 复制/粘贴
|
||||
[`${cmdOrCtrl}+c`]: { action: "copy", description: "复制" },
|
||||
[`${cmdOrCtrl}+v`]: { action: "paste", description: "粘贴" },
|
||||
[`${cmdOrCtrl}+v`]: { action: "paste", description: "粘贴", noStop: true },
|
||||
[`${cmdOrCtrl}+x`]: { action: "cut", description: "剪切" },
|
||||
|
||||
// 删除
|
||||
@@ -196,6 +203,29 @@ export class KeyboardManager {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理粘贴事件
|
||||
* @param {ClipboardEvent} event 粘贴事件
|
||||
*/
|
||||
handlePaste(event) {
|
||||
event.preventDefault(); // 阻止默认粘贴行为
|
||||
if(this.isRedGreenMode.value) return;
|
||||
const text = event.clipboardData?.getData("text/plain") || "";
|
||||
if(/^aida_copy_canvas_layer/.test(text)) return;
|
||||
const items = event.clipboardData?.items || [];
|
||||
console.log(this);
|
||||
for (const item of items) {
|
||||
if (item.type.indexOf("text/plain") !== -1) {
|
||||
item.getAsString((text) => {
|
||||
this.pasteText(text);
|
||||
});
|
||||
} else if (item.type.indexOf("image") !== -1) {
|
||||
const blob = item.getAsFile();
|
||||
this.pasteImage(blob);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化并开始监听键盘事件
|
||||
*/
|
||||
@@ -203,6 +233,7 @@ export class KeyboardManager {
|
||||
// 添加键盘事件监听
|
||||
this.container.addEventListener("keydown", this._handleKeyDown);
|
||||
this.container.addEventListener("keyup", this._handleKeyUp);
|
||||
this.container.addEventListener("paste", this._handlePaste);
|
||||
|
||||
// 如果是触摸设备,添加触摸事件监听
|
||||
if (this.isTouchDevice) {
|
||||
@@ -222,6 +253,7 @@ export class KeyboardManager {
|
||||
// 移除键盘事件监听
|
||||
this.container.removeEventListener("keydown", this._handleKeyDown);
|
||||
this.container.removeEventListener("keyup", this._handleKeyUp);
|
||||
this.container.removeEventListener("paste", this._handlePaste);
|
||||
|
||||
// 如果是触摸设备,移除触摸事件监听
|
||||
if (this.isTouchDevice) {
|
||||
@@ -251,7 +283,7 @@ export class KeyboardManager {
|
||||
const shortcut = this.shortcuts[shortcutKey];
|
||||
if (shortcut) {
|
||||
// 阻止默认行为,例如浏览器的保存对话框等
|
||||
if (shortcutKey.includes(`${this.modifierKeys.cmdOrCtrl}+`)) {
|
||||
if (shortcutKey.includes(`${this.modifierKeys.cmdOrCtrl}+`) && !shortcut.noStop) {
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
@@ -400,30 +432,35 @@ export class KeyboardManager {
|
||||
case "copy":
|
||||
// 复制逻辑
|
||||
console.log("复制当前选中图层");
|
||||
if(this.isRedGreenMode.value) return;
|
||||
this.layerManager.copyLayer(this.layerManager.activeLayerId.value);
|
||||
break;
|
||||
|
||||
case "paste":
|
||||
// 粘贴逻辑
|
||||
console.log("粘贴");
|
||||
if(this.isRedGreenMode.value) return;
|
||||
this.layerManager.pasteLayer();
|
||||
break;
|
||||
|
||||
case "cut":
|
||||
// 剪切逻辑
|
||||
console.log("剪切");
|
||||
if(this.isRedGreenMode.value) return;
|
||||
this.layerManager.cutLayer(this.layerManager.activeLayerId.value);
|
||||
break;
|
||||
|
||||
case "delete":
|
||||
// 删除逻辑
|
||||
console.log("删除");
|
||||
if(this.isRedGreenMode.value) return;
|
||||
this.layerManager.removeLayer(this.layerManager.activeLayerId.value);
|
||||
break;
|
||||
|
||||
case "selectAll":
|
||||
// 全选逻辑
|
||||
console.log("全选");
|
||||
if(this.isRedGreenMode.value) return;
|
||||
// 这里需要实现全选逻辑 TODO: 是否在选择模式下才可以全选?
|
||||
if (this.layerManager) {
|
||||
this.layerManager.selectAll();
|
||||
@@ -699,17 +736,7 @@ export class KeyboardManager {
|
||||
*/
|
||||
dispose() {
|
||||
// 移除事件监听
|
||||
this.container.removeEventListener("keydown", this._handleKeyDown);
|
||||
this.container.removeEventListener("keyup", this._handleKeyUp);
|
||||
|
||||
// 如果有触摸事件,也移除它们
|
||||
if (this.isTouchDevice) {
|
||||
this.container.removeEventListener("touchstart", this._handleTouchStart);
|
||||
this.container.removeEventListener("touchmove", this._handleTouchMove);
|
||||
this.container.removeEventListener("touchend", this._handleTouchEnd);
|
||||
this.container.removeEventListener("touchcancel", this._handleTouchEnd);
|
||||
}
|
||||
|
||||
this.removeEvents();
|
||||
// 清除引用
|
||||
this.toolManager = null;
|
||||
this.commandManager = null;
|
||||
|
||||
@@ -44,16 +44,17 @@
|
||||
:key="index"
|
||||
class="image-item"
|
||||
@click="handleImageClick(item)"
|
||||
@dblclick="handleImageDoubleClick(item)"
|
||||
>
|
||||
<div class="image-wrapper">
|
||||
<img
|
||||
:src="item.url"
|
||||
:alt="item.name || '图片'"
|
||||
:alt="item.name"
|
||||
@error="handleImageError"
|
||||
loading="lazy"
|
||||
/>
|
||||
<div class="image-overlay">
|
||||
<span class="image-name">{{ item.name || "未命名" }}</span>
|
||||
<span class="image-name">{{ item.name }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <div class="image-select" v-show="selectList.includes(item.url)">
|
||||
@@ -169,7 +170,11 @@ const handleImageClick = (item) => {
|
||||
selectList.value.push(item.url)
|
||||
}
|
||||
};
|
||||
|
||||
// 处理图片双击
|
||||
const handleImageDoubleClick = (item) => {
|
||||
selectList.value = [item.url];
|
||||
confirm();
|
||||
}
|
||||
// 处理图片加载错误
|
||||
const handleImageError = (event) => {
|
||||
event.target.src =
|
||||
|
||||
@@ -278,14 +278,6 @@ const isShowLeft = ref(true);
|
||||
<span>更</span>
|
||||
<div class="tool-tooltip">更换底图</div>
|
||||
</div>
|
||||
<div class="custom-tool-btn" @click="saveCanvas">
|
||||
<span>保</span>
|
||||
<div class="tool-tooltip">保存画布</div>
|
||||
</div>
|
||||
<div class="custom-tool-btn" @click="canvasProject">
|
||||
<span>读</span>
|
||||
<div class="tool-tooltip">读取画布</div>
|
||||
</div>
|
||||
<div class="custom-tool-btn" @click="exportJSON">
|
||||
<span>导</span>
|
||||
<div class="tool-tooltip">导出JSON</div>
|
||||
|
||||
@@ -39,6 +39,10 @@
|
||||
<img src="@/assets/images/icon/details_elements.png" alt="">
|
||||
<div class="detailText">{{$t('DesignPrintOperation.Elements')}}</div>
|
||||
</div>
|
||||
<!-- <div class="nav_item" :class="{active:currentDetailType == 'accessory'}" @click="setCurrentDetail('accessory')">
|
||||
<img src="@/assets/images/icon/details_elements.png" alt="">
|
||||
<div class="detailText">{{$t('DesignPrintOperation.Accessory')}}</div>
|
||||
</div> -->
|
||||
<div class="nav_item" v-if="selectObject.type == 'seriesDesign'" :class="{active:currentDetailType == 'models'}" @click="setCurrentDetail('models')">
|
||||
<img src="@/assets/images/icon/details_model.svg" alt="">
|
||||
<div class="detailText">{{$t('DesignPrintOperation.Model')}}</div>
|
||||
@@ -46,7 +50,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="item detailLeft" :class="{isEditPattern:isEditPattern.value}">
|
||||
<detailLeft v-if="currentDetailType"></detailLeft>
|
||||
<detailLeft v-if="currentDetailType" ref="detailLeft"></detailLeft>
|
||||
<!-- <detailLeft v-if="selectDetail && selectDetail.id && currentDetailType"></detailLeft> -->
|
||||
<div class="btn" style="margin: 0;" v-show="currentDetailType == 'color'">
|
||||
<div class="gallery_btn" @click="previwe">{{$t('DesignPrintOperation.Preview')}}</div>
|
||||
@@ -57,12 +61,14 @@
|
||||
<model
|
||||
ref="model"
|
||||
:key="positionKey"
|
||||
|
||||
@canvasReload="canvasReload"
|
||||
@detailEdit="detailEdit"
|
||||
@addSketch="()=>isEditPattern.value = ''"
|
||||
@revocation="revocation"
|
||||
@oppositeRevocation="oppositeRevocation"
|
||||
@modelOnLoad="modelOnLoad"
|
||||
@sketchSysToLibrary="sketchSysToLibrary"
|
||||
></model>
|
||||
<div class="btn">
|
||||
<div class="gallery_btn" style="margin-right: 0;" @click="submit">{{$t('DesignPrintOperation.Submit')}}</div>
|
||||
@@ -78,6 +84,7 @@
|
||||
v-show="
|
||||
currentDetailType !== 'color' &&
|
||||
(currentDetailType === 'element' ||
|
||||
currentDetailType === 'accessory' ||
|
||||
currentDetailType === 'print' ||
|
||||
(currentDetailType === 'sketch' && selectDetail?.newDetail?.[currentDetailType])||
|
||||
(currentDetailType === 'sketch' && selectDetail?.sketchString)||
|
||||
@@ -131,6 +138,7 @@ export default defineComponent({
|
||||
model:null,
|
||||
canvasBox,
|
||||
detailRight,
|
||||
detailLeft:null as any,
|
||||
})
|
||||
const userDetail = computed(()=>{
|
||||
return store.state.UserHabit.userDetail
|
||||
@@ -248,15 +256,13 @@ export default defineComponent({
|
||||
const setRevocation = ()=>{//设置撤销
|
||||
let itemDetail = JSON.parse(JSON.stringify(detailData.designDetail))
|
||||
let revocation:any = JSON.parse((sessionStorage.getItem("revocation") as any))
|
||||
if(!revocation)revocation = []
|
||||
// let oppositeRevocation = JSON.parse((sessionStorage.getItem("oppositeRevocation") as any))
|
||||
if(revocation?.[0]?.designItemId != itemDetail.designItemId || revocation?.[0]?.designItemId == undefined){
|
||||
// sessionStorage.setItem('revocation', JSON.stringify([]));
|
||||
// sessionStorage.setItem('oppositeRevocation',JSON.stringify([]));
|
||||
revocation = []
|
||||
}
|
||||
revocation.push(itemDetail)
|
||||
// if(revocation?.[0]?.designItemId != itemDetail.designItemId || revocation?.[0]?.designItemId == undefined){
|
||||
// revocation = []
|
||||
// }
|
||||
revocation.push({designData:itemDetail,position:null})
|
||||
detailData.revocationShow = revocation?.length
|
||||
detailData.oppositeRevocationShow = 0
|
||||
sessionStorage.setItem('revocation', JSON.stringify(revocation));
|
||||
sessionStorage.setItem('oppositeRevocation',JSON.stringify([]));
|
||||
}
|
||||
@@ -265,13 +271,16 @@ export default defineComponent({
|
||||
const revocation = ()=>{//撤回
|
||||
let oppositeRevocation = JSON.parse((sessionStorage.getItem("oppositeRevocation") as any))
|
||||
let revocation = JSON.parse((sessionStorage.getItem("revocation") as any))
|
||||
if(detailData.revocationShow <= 1)return
|
||||
if(revocation.length <= 1)return
|
||||
oppositeRevocation.push(revocation[revocation.length-1])
|
||||
detailData.oppositeRevocationShow = oppositeRevocation.length
|
||||
revocation.splice(revocation.length-1,1)
|
||||
detailData.revocationShow = revocation.length
|
||||
// store.commit("DesignDetail/setDesignDetail", revocation[revocation.length-1]);
|
||||
store.commit('DesignDetail/setDesignDetail',revocation[revocation.length-1])
|
||||
if(revocation[revocation.length-1].designData){
|
||||
store.commit('DesignDetail/setDesignDetail',revocation[revocation.length-1].designData)
|
||||
}else{
|
||||
store.commit('DesignDetail/setFrontBack',revocation[revocation.length-1].position)
|
||||
}
|
||||
store.commit('DesignDetail/setDesignColthes',detailData.selectDetail.id)
|
||||
sessionStorage.setItem('oppositeRevocation', JSON.stringify(oppositeRevocation));
|
||||
sessionStorage.setItem('revocation', JSON.stringify(revocation));
|
||||
@@ -281,8 +290,13 @@ export default defineComponent({
|
||||
const oppositeRevocation = ()=>{//反撤回
|
||||
let oppositeRevocation = JSON.parse((sessionStorage.getItem("oppositeRevocation") as any))
|
||||
let revocation = JSON.parse((sessionStorage.getItem("revocation") as any))
|
||||
if(!oppositeRevocation[oppositeRevocation.length-1])return
|
||||
store.commit("DesignDetail/setDesignDetail", oppositeRevocation[oppositeRevocation.length-1]);
|
||||
// if(!oppositeRevocation[oppositeRevocation.length-1].designData)return
|
||||
if(oppositeRevocation.length < 1)return
|
||||
if(oppositeRevocation[oppositeRevocation.length-1]?.designData){
|
||||
store.commit('DesignDetail/setDesignDetail',oppositeRevocation[oppositeRevocation.length-1].designData)
|
||||
}else if(oppositeRevocation[oppositeRevocation.length-1]?.position){
|
||||
store.commit('DesignDetail/setFrontBack',oppositeRevocation[oppositeRevocation.length-1].position)
|
||||
}
|
||||
store.commit('DesignDetail/setDesignColthes',detailData.selectDetail.id)
|
||||
revocation.push(oppositeRevocation[oppositeRevocation.length-1])
|
||||
detailData.revocationShow = revocation.length
|
||||
@@ -351,6 +365,7 @@ export default defineComponent({
|
||||
type:(newData && detailData.currentDetailType == 'sketch' && isCurrent && !detailData.isEditPattern.value)?newData.level2Type || newData.categoryValue:list[i].type,
|
||||
sketchString:list[i].sketchString?list[i].sketchString:'',
|
||||
trims:(newData && detailData.currentDetailType == 'element' && isCurrent && !detailData.isEditPattern.value)?{prints:newData}:list[i].trims?.prints?list[i].trims:{prints:[]},
|
||||
accessory:(newData && detailData.currentDetailType == 'accessory' && isCurrent && !detailData.isEditPattern.value)?{prints:newData}:list[i].trims?.prints?list[i].trims:{prints:[]},
|
||||
}
|
||||
if((detailData.isEditPattern.value && list[i].color?.gradient) || (!detailData.isEditPattern.value && (list[i].newDetail?.color?.gradient || list[i].color?.gradient))){
|
||||
gradient = list[i].newDetail?.color?.gradient || list[i].color.gradient
|
||||
@@ -374,7 +389,7 @@ export default defineComponent({
|
||||
let data = {
|
||||
designItemId:detailData.designDetail.designItemId,
|
||||
designSingleItemDTOList:clothes,
|
||||
isPreview:true,
|
||||
isPreview:str == 'sub'?false:true,
|
||||
// ifSubmit:designItemDetail.isPreview,
|
||||
gender:workspace?.sex,
|
||||
sketchString:'',
|
||||
@@ -448,7 +463,8 @@ export default defineComponent({
|
||||
const modelOnLoad = ()=>{
|
||||
if(!detailData.isUndividedLayerWithSinglePrint)return
|
||||
setTimeout(()=>{
|
||||
previwe()
|
||||
let data = getSubmitData('sub')
|
||||
store.dispatch('DesignDetail/setSubmit',data)
|
||||
})
|
||||
}
|
||||
const detailEdit = async (str:any)=>{
|
||||
@@ -479,6 +495,17 @@ export default defineComponent({
|
||||
store.commit('DesignDetail/setDesignDetail',detailData.designDetail)
|
||||
},1000)
|
||||
}
|
||||
const sketchSysToLibrary = ()=>{//系统sketch添加到library更新library
|
||||
coverRevocation()
|
||||
detailDom.detailLeft.sketchSysToLibrary()
|
||||
}
|
||||
const coverRevocation = ()=>{
|
||||
let itemDetail = JSON.parse(JSON.stringify(detailData.designDetail))
|
||||
let revocation = JSON.parse((sessionStorage.getItem("revocation") as any))
|
||||
revocation.splice(revocation.length-1,1,{designData:itemDetail,position:null})
|
||||
sessionStorage.setItem('revocation', JSON.stringify(revocation));
|
||||
sessionStorage.setItem('oppositeRevocation',JSON.stringify([]));
|
||||
}
|
||||
onMounted(()=>{
|
||||
window.addEventListener('resize', handleResize);
|
||||
})
|
||||
@@ -503,6 +530,7 @@ export default defineComponent({
|
||||
detailEdit,
|
||||
canvasReload,
|
||||
modelOnLoad,
|
||||
sketchSysToLibrary,
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
:clothing-image-opts="{
|
||||
imageMode:'contains',
|
||||
}"
|
||||
:hideCanvas="hideCanvas"
|
||||
ref="editCanvas">
|
||||
</editCanvas>
|
||||
<!-- <canvasContent ref="canvasContent"></canvasContent> -->
|
||||
@@ -37,6 +38,7 @@
|
||||
:clothing-image-opts="{
|
||||
imageMode:'contains',
|
||||
}"
|
||||
:hideCanvas="hideCanvas"
|
||||
ref="editCanvasBackFront">
|
||||
</editCanvas>
|
||||
</div>
|
||||
@@ -63,6 +65,7 @@ import { useStore } from "vuex";
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import editCanvas from "@/component/Canvas/CanvasEditor/index.vue";
|
||||
import { formatTime,segmentImage,getMinioUrl } from "@/tool/util";
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
|
||||
export default defineComponent({
|
||||
components:{
|
||||
@@ -77,7 +80,7 @@ export default defineComponent({
|
||||
setup(props,{emit}) {
|
||||
const store = useStore();
|
||||
const {t} = useI18n();
|
||||
|
||||
const route = useRoute()
|
||||
const detailDom = reactive({
|
||||
editFrontBack:null as any,
|
||||
model:null,
|
||||
@@ -104,6 +107,7 @@ export default defineComponent({
|
||||
getCanvasIfEdit:inject('getCanvasIfEdit')as any,
|
||||
canvasInstance:null as any,
|
||||
canvasJSON:'',
|
||||
hideCanvas: computed(()=>store.state.Workspace.projectPath !== route.fullPath),
|
||||
})
|
||||
watch(()=>detailData.selectDetail,(newValue,oldValue)=>{
|
||||
detailData.imgDomIndex = detailData.frontBack.front.findIndex((item:any)=>item.id == newValue.id)
|
||||
|
||||
163
src/component/Detail/detailLeft/accessory.vue
Normal file
@@ -0,0 +1,163 @@
|
||||
<template>
|
||||
<div class="element">
|
||||
<div class="detailText">{{$t('DesignPrintOperation.CurrentAccessory')}}</div>
|
||||
<div class="select_element">
|
||||
<img :class="{active:elementList.length == 1}" v-for="item in elementList" @click="addElement(item)" :src="item.path" alt="">
|
||||
<!-- <img :src="selectDetail.path" alt="">
|
||||
{{ selectDetail }} -->
|
||||
<div v-if="elementList.length == 0">
|
||||
<i class="fi fi-rr-picture centent"></i>
|
||||
</div>
|
||||
</div>
|
||||
<selectList @selectImgItem="selectImgItem" level1Type="DesignElements" type="accessory" :catecoryList="printCatecoryList"></selectList>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent,computed,ref,watch,nextTick,createVNode,toRefs, reactive} from 'vue'
|
||||
// import setDesignItem from '@/component/Detail/setDesignItem2.vue'
|
||||
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
|
||||
import { Https } from "@/tool/https";
|
||||
import { useStore } from "vuex";
|
||||
import { useI18n } from 'vue-i18n'
|
||||
// import sketchCategory from "@/component/HomePage/sketchCategory.vue";
|
||||
import selectList from './module/selectList.vue'
|
||||
export default defineComponent({
|
||||
components:{
|
||||
selectList,
|
||||
},
|
||||
setup(props,{emit}) {
|
||||
const store = useStore();
|
||||
const detailData = reactive({
|
||||
selectTitle:'current',
|
||||
selectDetail:computed(()=>store.state.DesignDetail.selectDetail),
|
||||
printCatecoryList:computed(()=>{
|
||||
return store.state.UserHabit.designElementsType
|
||||
}),
|
||||
elementList:[],
|
||||
currentDetailType:computed(()=>store.state.DesignDetail.currentDetailType)
|
||||
})
|
||||
watch(()=>detailData?.selectDetail?.trims?.prints,(newVal,oldVal)=>{
|
||||
if(!newVal)return
|
||||
detailData.elementList = newVal.reduce((acc:any, curr:any) => {
|
||||
if (!acc.some((item:any) => item.minIOPath === curr.minIOPath)) {
|
||||
acc.push(curr);
|
||||
}
|
||||
return acc;
|
||||
}, []);
|
||||
|
||||
},{immediate: true})
|
||||
const getDetailListData = reactive({
|
||||
total:0,
|
||||
pageSize:10,
|
||||
currentPage:1,
|
||||
})
|
||||
const getDetailListDom = reactive({
|
||||
libraryList:null as any,
|
||||
})
|
||||
const openCurrent = ()=>{
|
||||
detailData.selectTitle = 'current'
|
||||
}
|
||||
const openUpload = ()=>{
|
||||
detailData.selectTitle = 'upload'
|
||||
}
|
||||
const openLibrary = ()=>{
|
||||
detailData.selectTitle = 'library'
|
||||
getDetailListDom.libraryList.init()
|
||||
}
|
||||
const addElement = (data:any)=>{
|
||||
let value = {
|
||||
designType:data.designType,
|
||||
level2Type:data.level2Type,
|
||||
minIOPath:data.minIOPath,
|
||||
url:data.path,
|
||||
}
|
||||
store.commit('DesignDetail/setCurrentPrintElement',value)
|
||||
}
|
||||
const selectImgItem = (data:any)=>{
|
||||
let value = {
|
||||
data,
|
||||
}
|
||||
if(detailData.currentDetailType != 'print' && detailData.currentDetailType != 'element'){
|
||||
store.commit('DesignDetail/setNewDetail',value)
|
||||
}else{
|
||||
store.commit('DesignDetail/setCurrentPrintElement',null)
|
||||
store.commit('DesignDetail/setCurrentPrintElement',data)
|
||||
}
|
||||
}
|
||||
|
||||
return{
|
||||
...toRefs(detailData),
|
||||
...toRefs(getDetailListData),
|
||||
...toRefs(getDetailListDom),
|
||||
|
||||
openCurrent,
|
||||
openUpload,
|
||||
openLibrary,
|
||||
selectImgItem,
|
||||
addElement,
|
||||
}
|
||||
},
|
||||
|
||||
provide() {
|
||||
return {
|
||||
}
|
||||
},
|
||||
|
||||
})
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.element{
|
||||
// width: 34rem;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
> .detailText{
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
> .select_element{
|
||||
width: 100%;
|
||||
height: 23.5rem;
|
||||
padding: 1rem;
|
||||
text-align: center;
|
||||
border-radius: .5rem;
|
||||
border: 1px solid #000;
|
||||
// border: 1px dashed transparent;
|
||||
border-radius: 1.5rem;
|
||||
background: linear-gradient(#fff, #fff) padding-box,repeating-linear-gradient(-45deg,#fff 0,#fff 0.3em, #000 0,#000 0.6em);
|
||||
margin-bottom: 1.4rem;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
overflow: hidden;
|
||||
justify-content: space-between;
|
||||
overflow-y: auto;
|
||||
justify-content: flex-start;
|
||||
> img{
|
||||
object-fit: contain;
|
||||
height: 9rem;
|
||||
width: 9rem;
|
||||
overflow-y: auto;
|
||||
margin-bottom: 1rem;
|
||||
margin: 1rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
> .active{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
> div{
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
> i{
|
||||
font-size: 10rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,9 +1,10 @@
|
||||
<template>
|
||||
<div class="detailLeft">
|
||||
<sketch v-show="currentDetailType == 'sketch'" @addDetail="addDetail"></sketch>
|
||||
<sketch v-show="currentDetailType == 'sketch'" ref="sketch" @addDetail="addDetail"></sketch>
|
||||
<print v-show="currentDetailType == 'print'"></print>
|
||||
<color v-if="currentDetailType == 'color'"></color>
|
||||
<element v-show="currentDetailType == 'element'"></element>
|
||||
<accessory v-show="currentDetailType == 'accessory'"></accessory>
|
||||
<models v-show="currentDetailType == 'models'"></models>
|
||||
<addDetails ref="addDetails" @setSloganData="setSloganData"></addDetails>
|
||||
</div>
|
||||
@@ -19,12 +20,13 @@ import sketch from './sketch.vue'
|
||||
import print from './print.vue'
|
||||
import color from './colorBox/index.vue'
|
||||
import element from './element.vue'
|
||||
import accessory from './accessory.vue'
|
||||
import models from './models.vue'
|
||||
import addDetails from '@/component/Detail/addDetails.vue'
|
||||
|
||||
export default defineComponent({
|
||||
components:{
|
||||
sketch,print,color,addDetails,element,models
|
||||
sketch,print,color,addDetails,element,models,accessory
|
||||
},
|
||||
setup(props,{emit}) {
|
||||
const store = useStore();
|
||||
@@ -40,6 +42,7 @@ export default defineComponent({
|
||||
})
|
||||
const getDetailListDom = reactive({
|
||||
addDetails:null as any,
|
||||
sketch:null as any,
|
||||
})
|
||||
const addDetail = () =>{
|
||||
let addDetails:any = getDetailListDom.addDetails
|
||||
@@ -51,6 +54,9 @@ export default defineComponent({
|
||||
detailData.selectDetail.newDetail.sketch = null
|
||||
}
|
||||
}
|
||||
const sketchSysToLibrary = ()=>{//系统sketch添加到library更新library
|
||||
getDetailListDom.sketch.sketchSysToLibrary()
|
||||
}
|
||||
|
||||
return{
|
||||
...toRefs(detailData),
|
||||
@@ -58,6 +64,7 @@ export default defineComponent({
|
||||
...toRefs(getDetailListDom),
|
||||
addDetail,
|
||||
setSloganData,
|
||||
sketchSysToLibrary,
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<div class="content_img_item" v-for="(file) in currentList[type]" :key="file.id">
|
||||
<div class="content_img_item_block" :class="{active:file?.checked}">
|
||||
<img :src="file.imgUrl?file.imgUrl:file.url" :key="file.imgUrl || file.url" :alt="file.name" @click.stop="selectImgItem(file)"/>
|
||||
<sketchCategory v-if="type != 'models'" v-model:disignTypeList="catecoryList" :generateList="allBoardData.sketchboardFiles" :item="file" :isSpread="true"></sketchCategory>
|
||||
<sketchCategory v-if="type != 'models'" v-model:disignTypeList="catecoryList" :generateList="allBoardData.sketchboardFiles" :allCategory="sketchCatecoryAllList" :item="file" :isSpread="true"></sketchCategory>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -48,6 +48,9 @@ export default defineComponent({
|
||||
color:computed(()=>store.state.UploadFilesModule.allBoardData.colorBoards),
|
||||
models:computed(()=>store.state.Workspace.probjects.model),
|
||||
},
|
||||
sketchCatecoryAllList:computed(()=>{
|
||||
return store.state.Workspace.workspaceAllPosition
|
||||
}),
|
||||
currentDetailType:computed(()=>store.state.DesignDetail.currentDetailType),
|
||||
|
||||
})
|
||||
|
||||
@@ -118,6 +118,7 @@ export default defineComponent({
|
||||
detailData.selectTitle = 'upload'
|
||||
}
|
||||
const openLibrary = ()=>{
|
||||
if(detailData.selectTitle == 'library')return
|
||||
detailData.selectTitle = 'library'
|
||||
getDetailListDom.libraryList.init()
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<i class="fi fi-rr-picture centent"></i>
|
||||
</div>
|
||||
</div>
|
||||
<selectList @selectImgItem="selectImgItem" source="detail" level1Type="Sketchboard" type="sketch" :catecoryList="sketchCatecoryList"></selectList>
|
||||
<selectList @selectImgItem="selectImgItem" source="detail" ref="selectList" level1Type="Sketchboard" type="sketch" :catecoryList="sketchCatecoryList"></selectList>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
@@ -47,7 +47,7 @@ export default defineComponent({
|
||||
currentPage:1,
|
||||
})
|
||||
const getDetailListDom = reactive({
|
||||
libraryList:null as any,
|
||||
selectList:null as any,
|
||||
})
|
||||
const openCurrent = ()=>{
|
||||
detailData.selectTitle = 'current'
|
||||
@@ -55,9 +55,8 @@ export default defineComponent({
|
||||
const openUpload = ()=>{
|
||||
detailData.selectTitle = 'upload'
|
||||
}
|
||||
const openLibrary = ()=>{
|
||||
detailData.selectTitle = 'library'
|
||||
getDetailListDom.libraryList.init()
|
||||
const sketchSysToLibrary = ()=>{
|
||||
getDetailListDom.selectList.openLibrary()
|
||||
}
|
||||
const hasDuplicateId = (id:any)=>{
|
||||
let arr = detailData.designDetail.clothes
|
||||
@@ -96,7 +95,7 @@ export default defineComponent({
|
||||
|
||||
openCurrent,
|
||||
openUpload,
|
||||
openLibrary,
|
||||
sketchSysToLibrary,
|
||||
selectImgItem,
|
||||
openAddDetail,
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<div class="back" v-show="isEditPattern.value">
|
||||
<i class="fi fi-br-angle-left" @click="setBack"></i>
|
||||
</div>
|
||||
<modelNav @canvasReload="()=>$emit('canvasReload')" @addSketch="()=>$emit('addSketch')" @deleteItem="deleteItem"></modelNav>
|
||||
<modelNav @canvasReload="()=>$emit('canvasReload')" @addSketch="()=>$emit('addSketch')" @sketchSysToLibrary="()=>$emit('sketchSysToLibrary')" @deleteItem="deleteItem"></modelNav>
|
||||
</div>
|
||||
<div class="modelindex_right">
|
||||
<div class="detail_btn">
|
||||
@@ -26,7 +26,7 @@
|
||||
<i v-show="!body && deleteShow" class="fi fi-br-check" @click="deleteNav(1)"></i> -->
|
||||
|
||||
<!-- 层 -->
|
||||
<i :title="$t('DesignDetail.compareTitle')" @mousedown="mousedownDesignImg" @mouseup="mousedownDesignImg" @touchstart="mousedownDesignImg" @touchend="mousedownDesignImg">
|
||||
<i :title="$t('DesignDetail.compareTitle')" @mousedown="mousedownDesignImg" @mouseup="mousedownDesignImg" @touchstart.passive="mousedownDesignImg" @touchend.passive="mousedownDesignImg">
|
||||
<SvgIcon name="DetailCompare" size="30" />
|
||||
</i>
|
||||
|
||||
@@ -50,7 +50,7 @@ export default defineComponent({
|
||||
components:{
|
||||
position,modelNav
|
||||
},
|
||||
emits:['detailEdit','canvasReload','addSketch','revocation','oppositeRevocation','modelOnLoad'],
|
||||
emits:['detailEdit','canvasReload','addSketch','revocation','oppositeRevocation','modelOnLoad','sketchSysToLibrary'],
|
||||
setup(props,{emit}) {
|
||||
const {t} = useI18n()
|
||||
const store = useStore();
|
||||
|
||||
@@ -7,8 +7,12 @@
|
||||
@mousedown.stop="designMousedown(getMousePosition($event,false),item.uniqueId,'disLike')"
|
||||
@touchstart.passive="designMousedown(getMousePosition($event,true),item.uniqueId,'disLike')"
|
||||
@click="selectDetailItem(item,index)">
|
||||
<i v-if="item?.id != selectDetail?.id" class="fi fi-rr-trash" @click.stop="deleteDetailItem(item?.id)"></i>
|
||||
<div class="iconList">
|
||||
<i class="fi fi-rr-add" :class="{ active:item.scope == 'sys'}" @click.stop="sketchSystemToLibrary(item)"></i>
|
||||
<i class="fi fi-rr-trash" @click.stop="deleteDetailItem(item?.id)"></i>
|
||||
</div>
|
||||
<img :src="item.path" alt="">
|
||||
<div class="type">{{ getTypeLang(item.type) }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-show="singleOveral.value == 'overall'" v-if="(currentDetailType == 'sketch' || currentDetailType == '') && designDetail.clothes.length < 5 && !isEditPattern.value" :class="{active:!selectDetail?.id && currentDetailType == 'sketch'}" class="add" @click="addSketch">
|
||||
@@ -30,7 +34,7 @@ export default defineComponent({
|
||||
components:{
|
||||
position,
|
||||
},
|
||||
emits:['canvasReload','addSketch','deleteItem'],
|
||||
emits:['canvasReload','addSketch','deleteItem','sketchSysToLibrary'],
|
||||
props:{
|
||||
},
|
||||
setup(props,{emit}) {
|
||||
@@ -104,6 +108,16 @@ export default defineComponent({
|
||||
detailData.designDetail.clothes = detailData.designDetail.clothes.filter((item:any)=>item.id != id)
|
||||
detailData.frontBack_.back = detailData.frontBack_.back.filter((item:any)=>item.id != id)
|
||||
detailData.frontBack_.front = detailData.frontBack_.front.filter((item:any)=>item.id != id)
|
||||
//判断删除后是否还有服装
|
||||
if(detailData.designDetail.clothes.length == 0){
|
||||
addSketch()
|
||||
}else{
|
||||
//获取当前最大的priority值
|
||||
const maxValue = Math.max(...detailData.designDetail.clothes.map(item => item.priority));
|
||||
const maxObj = detailData.designDetail.clothes.find(item => item.priority === maxValue);
|
||||
store.commit('DesignDetail/setDesignColthes',maxObj.id)
|
||||
}
|
||||
emit('canvasReload')
|
||||
emit('deleteItem')
|
||||
}
|
||||
const addSketch = ()=>{
|
||||
@@ -238,6 +252,22 @@ export default defineComponent({
|
||||
collItemSize.prentHeight = (collItemSize.padding + remValue) * elArr.length + 'px'
|
||||
moveItem()
|
||||
}
|
||||
const sketchSystemToLibrary = (item)=>{
|
||||
let value = {
|
||||
clothId:item.id,
|
||||
path:item.minIOPath
|
||||
}
|
||||
Https.axiosGet(Https.httpUrls.addSysSketchToLibrary,{params:value})
|
||||
.then((rv:any)=>{
|
||||
item.scope = 'user'
|
||||
emit('sketchSysToLibrary')
|
||||
})
|
||||
}
|
||||
const getTypeLang = (type:any)=>{
|
||||
// return navTypeList.find((item:any)=>item.value == type)?.label || type
|
||||
let allPostition = store.state.Workspace.workspaceAllPosition
|
||||
return allPostition.find(item => item.value === type)?.name
|
||||
}
|
||||
let observers = null as any
|
||||
onMounted(()=>{
|
||||
observers = new ResizeObserver(entries => {
|
||||
@@ -258,6 +288,8 @@ export default defineComponent({
|
||||
designMousedown,
|
||||
addSketch,
|
||||
getMousePosition,
|
||||
sketchSystemToLibrary,
|
||||
getTypeLang,
|
||||
}
|
||||
},
|
||||
|
||||
@@ -284,17 +316,48 @@ export default defineComponent({
|
||||
position: absolute;
|
||||
background: #fff;
|
||||
transition: top .3s;
|
||||
> i:not(.fi-bs-plus){
|
||||
display: none;
|
||||
overflow: hidden;
|
||||
> .type{
|
||||
position: absolute;
|
||||
right: 1rem;
|
||||
top: 1rem;
|
||||
cursor: pointer;
|
||||
font-size: 2rem;
|
||||
bottom: 0rem;
|
||||
left: 0rem;
|
||||
font-size: 1.2rem;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
line-height: 2.4rem;
|
||||
font-size: 1.4rem;
|
||||
color: #fff;
|
||||
background: #666666CC;
|
||||
}
|
||||
&:hover{
|
||||
> .iconList{
|
||||
position: absolute;
|
||||
top: 1rem;
|
||||
right: 1rem;
|
||||
display: none;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
> i{
|
||||
display: block;
|
||||
margin-bottom: .2rem;
|
||||
font-size: 1.8rem;
|
||||
}
|
||||
> .fi-rr-add{
|
||||
pointer-events: none;
|
||||
color: #acacac;
|
||||
&.active{
|
||||
pointer-events: auto;
|
||||
color: #000;
|
||||
}
|
||||
}
|
||||
>i:not(.fi-rr-add){
|
||||
font-size: 2rem;
|
||||
}
|
||||
}
|
||||
i:not(.fi-bs-plus){
|
||||
}
|
||||
|
||||
&:hover{
|
||||
> .iconList{
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
&:last-child{
|
||||
@@ -333,6 +396,5 @@ export default defineComponent({
|
||||
.modelNav{
|
||||
position: relative;
|
||||
width: 12rem;
|
||||
|
||||
}
|
||||
</style>
|
||||
@@ -179,6 +179,7 @@ export default defineComponent({
|
||||
const sizeTouchmove = (event:any)=>{
|
||||
let e = getMousePosition(event,true)
|
||||
sizeMouseMoveOperation(e)
|
||||
|
||||
}
|
||||
const sizeMouseup = (e:any)=>{
|
||||
detailData.frontBack.front[selectItem.imgDomIndex].style={
|
||||
@@ -196,8 +197,22 @@ export default defineComponent({
|
||||
document.removeEventListener('touchmove',sizeTouchmove)
|
||||
document.removeEventListener('mouseup',sizeMouseup)
|
||||
document.removeEventListener('touchend',sizeMouseup)
|
||||
//鼠标抬起
|
||||
setRevocation()
|
||||
}
|
||||
let isMove = false//表示是否移动,是否需要在鼠标抬起的时候保存数据
|
||||
const setRevocation = ()=>{
|
||||
if(!isMove)return
|
||||
isMove = false
|
||||
let frontBack = JSON.parse(JSON.stringify(detailData.frontBack))
|
||||
console.log(frontBack)
|
||||
let revocation:any = JSON.parse((sessionStorage.getItem("revocation") as any))
|
||||
revocation.push({designData:null,position:frontBack})
|
||||
sessionStorage.setItem('revocation', JSON.stringify(revocation));
|
||||
|
||||
}
|
||||
const sizeMouseMoveOperation = (e:any)=> {
|
||||
isMove = true
|
||||
let imgDomWH = selectItem.imgDom.getBoundingClientRect()
|
||||
let parentNode =selectItem.imgDom.parentNode
|
||||
let width = imgDomWH.width
|
||||
@@ -251,8 +266,11 @@ export default defineComponent({
|
||||
document.removeEventListener('touchmove',touchmove)
|
||||
document.removeEventListener('mouseup',mouseup)
|
||||
document.removeEventListener('touchend',mouseup)
|
||||
///鼠标抬起
|
||||
setRevocation()
|
||||
}
|
||||
const mouseMoveOperation = (e:any)=>{
|
||||
isMove = true
|
||||
let imgDomWH = selectItem.imgDom.getBoundingClientRect()
|
||||
let parentNode = document.getElementsByClassName('molepositon')[0].getElementsByClassName("designOpenrtion_imgMask")[0].getBoundingClientRect()
|
||||
let x = (e.clientX - detailData.frontBack.front[selectItem.imgDomIndex].centers.left)+'px'
|
||||
|
||||
@@ -964,7 +964,7 @@ export default defineComponent({
|
||||
// height: 16.5rem;
|
||||
width: calc(12rem*1.2);
|
||||
height: calc(12rem*1.2);
|
||||
border: 1px solid #F5F5F5;
|
||||
border: 1px solid #F9FAFA;
|
||||
vertical-align: top;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -1434,7 +1434,7 @@ export default defineComponent({
|
||||
display: inline-block;
|
||||
width: calc(12rem*1.2);
|
||||
height: calc(12rem*1.2);
|
||||
border: 1px solid #F5F5F5;
|
||||
border: 1px solid #F9FAFA;
|
||||
vertical-align: top;
|
||||
i{
|
||||
zoom: 4;
|
||||
|
||||
@@ -724,8 +724,9 @@ export default defineComponent({
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
generageAdd(data: any) {
|
||||
if (!data?.imgUrl) return
|
||||
generageAdd(value: any) {
|
||||
if (!value?.imgUrl) return
|
||||
const data = JSON.parse(JSON.stringify(value))
|
||||
data.type_ = this.type_
|
||||
data.type_.type1 = data.designType ? data.designType : this.type_.type1
|
||||
data.resData = JSON.parse(JSON.stringify(data))
|
||||
@@ -1198,18 +1199,20 @@ export default defineComponent({
|
||||
level1Type: this.type_.type2,
|
||||
level2Type: level2Type,
|
||||
gender: this.workspace.sex,
|
||||
ageGroup: this.workspace.ageGroup,
|
||||
timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone
|
||||
}
|
||||
Https.axiosPost(Https.httpUrls.generateLike, data)
|
||||
.then(rv => {
|
||||
item.like = true
|
||||
item.libraryId = rv.libraryId
|
||||
})
|
||||
.catch(res => {})
|
||||
this.fileList[index].state = ''
|
||||
this.generageAdd(item)
|
||||
} else {
|
||||
this.fileList[index].state = 'delete'
|
||||
this.generageAdd(item)
|
||||
// this.generageAdd(item)
|
||||
let data = {
|
||||
generateDetailId: item.id,
|
||||
timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone
|
||||
@@ -1217,6 +1220,7 @@ export default defineComponent({
|
||||
Https.axiosGet(Https.httpUrls.generateDislike, { params: data })
|
||||
.then(rv => {
|
||||
item.like = false
|
||||
item.libraryId = null
|
||||
})
|
||||
.catch(res => {})
|
||||
}
|
||||
@@ -1415,6 +1419,7 @@ export default defineComponent({
|
||||
display: block;
|
||||
max-height: 100%;
|
||||
max-width: 100%;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.delete_file_block {
|
||||
@@ -1489,7 +1494,7 @@ export default defineComponent({
|
||||
}
|
||||
.fi-br-upload {
|
||||
&:hover {
|
||||
background-color: #f5f5f5;
|
||||
background-color: #F9FAFA;
|
||||
border-radius: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -214,7 +214,7 @@ export default defineComponent({
|
||||
display: inline-block;
|
||||
width: 16.5rem;
|
||||
height: 16.5rem;
|
||||
border: 1px solid #F5F5F5;
|
||||
border: 1px solid #F9FAFA;
|
||||
vertical-align: top;
|
||||
|
||||
&.upload_component{
|
||||
|
||||
@@ -597,7 +597,7 @@ export default defineComponent({
|
||||
// height: calc(10rem);
|
||||
width: calc(25% - 2rem);
|
||||
aspect-ratio: 1 / 1;
|
||||
border: 1px solid #f5f5f5;
|
||||
border: 1px solid #F9FAFA;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
padding: 0;
|
||||
|
||||
@@ -116,7 +116,7 @@ import { Https } from "@/tool/https";
|
||||
import { useStore } from "vuex";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import payMethod from "@/component/Pay/payMethod.vue";
|
||||
import { compute } from "three/tsl";
|
||||
// import { compute } from "three/tsl";
|
||||
// import { forEach } from "jszip";
|
||||
export default defineComponent({
|
||||
components: {
|
||||
|
||||