Browse Source

浮雕挂饰

main
Linzm 2 months ago
parent
commit
8ae713aef9
  1. 7
      src/lang/data/en.ts
  2. 7
      src/lang/data/ko.ts
  3. 7
      src/lang/data/zh-CN.ts
  4. 7
      src/lang/data/zh-TW.ts
  5. 586
      src/utils/textHelper.ts
  6. 47
      src/views/badge/index.vue
  7. 47
      src/views/badge/orderDetail.vue
  8. 337
      src/views/badge/preview.vue

7
src/lang/data/en.ts

@ -149,5 +149,12 @@ const en = {
"日漫3D": "Japanese 3D", "日漫3D": "Japanese 3D",
"迪斯尼皮克斯": "Disney Pixar", "迪斯尼皮克斯": "Disney Pixar",
"潮玩IP": "IP Toy", "潮玩IP": "IP Toy",
"浮雕挂饰": "Relief Pendant",
"人物浮雕挂饰": "Character Relief Pendant",
"宠物浮雕挂饰": "Pet Relief Pendant",
"浮雕挂饰-正面": "Relief Pendant-Front",
"浮雕挂饰-背面": "Relief Pendant-Back",
"请输入正面文字": "Please enter front text",
"请输入背面文字": "Please enter back text",
} }
export default en export default en

7
src/lang/data/ko.ts

@ -149,5 +149,12 @@ const ko = {
"日漫3D": "일본 3D", "日漫3D": "일본 3D",
"迪斯尼皮克斯": "디즈니 픽사", "迪斯尼皮克斯": "디즈니 픽사",
"潮玩IP": "IP 토이", "潮玩IP": "IP 토이",
"浮雕挂饰": "부조 걸이",
"人物浮雕挂饰": "캐릭터 부조 걸이",
"宠物浮雕挂饰": "애완동물 부조 걸이",
"浮雕挂饰-正面": "부조 걸이-정면",
"浮雕挂饰-背面": "부조 걸이-뒷면",
"请输入正面文字": "정면 텍스트를 입력하세요",
"请输入背面文字": "뒷면 텍스트를 입력하세요",
} }
export default ko export default ko

7
src/lang/data/zh-CN.ts

@ -149,5 +149,12 @@ const zhCN = {
"日漫3D": "日漫3D", "日漫3D": "日漫3D",
"迪斯尼皮克斯": "迪斯尼皮克斯", "迪斯尼皮克斯": "迪斯尼皮克斯",
"潮玩IP": "潮玩IP", "潮玩IP": "潮玩IP",
"浮雕挂饰": "浮雕挂饰",
"人物浮雕挂饰": "人物浮雕挂饰",
"宠物浮雕挂饰": "宠物浮雕挂饰",
"浮雕挂饰-正面": "浮雕挂饰-正面",
"浮雕挂饰-背面": "浮雕挂饰-背面",
"请输入正面文字": "请输入正面文字",
"请输入背面文字": "请输入背面文字",
} }
export default zhCN export default zhCN

7
src/lang/data/zh-TW.ts

@ -149,5 +149,12 @@ const zhCT = {
"日漫3D": "日漫3D", "日漫3D": "日漫3D",
"迪斯尼皮克斯": "迪士尼皮克斯", "迪斯尼皮克斯": "迪士尼皮克斯",
"潮玩IP": "潮玩IP", "潮玩IP": "潮玩IP",
"浮雕挂饰": "浮雕掛飾",
"人物浮雕挂饰": "人物浮雕掛飾",
"宠物浮雕挂饰": "寵物浮雕掛飾",
"浮雕挂饰-正面": "浮雕掛飾-正面",
"浮雕挂饰-背面": "浮雕掛飾-背面",
"请输入正面文字": "請輸入正面文字",
"请输入背面文字": "請輸入背面文字",
} }
export default zhCT export default zhCT

586
src/utils/textHelper.ts

@ -0,0 +1,586 @@
// textHelper.ts
/**
*
* @module TextPosition
*/
/**
*
* @param {Object} options -
* @param {Function} options.setData -
* @returns {Object} renderText方法的对象
*/
export function createTextPosition({ setData }) {
if (!setData) {
throw new Error('setData is required');
}
// 默认样式配置
const defaultStyle = {
fontSize: 16, // 字体大小(px)
fontFamily: 'Arial', // 字体
color: '#000000', // 文字颜色
textAlign: 'left', // 文本对齐方式: left, center, right
fontWeight: 'normal', // 字体粗细: normal, bold
lineHeight: 1.5, // 行高
opacity: 1, // 透明度
backgroundColor: 'transparent', // 背景颜色
padding: 0, // 内边距(px)
borderRadius: 0, // 边框圆角(px)
};
/**
*
* @param {Object} options -
* @param {string} options.text -
* @param {number} options.x - X坐标()
* @param {number} options.y - Y坐标()
* @param {number} [options.width] - ()
* @param {number} [options.height] - ()
* @param {Object} [options.style] -
* @param {string} [options.bindKey] -
*/
function roundText({ shapeImage, x, y, width, height, radius, style = {}, bindKey = 'roundTextConfig', text = '', isFront = true, cachedImageInfo = null, onImageInfoCached = null }) {
// 合并默认样式和用户自定义样式
const mergedStyle = { ...defaultStyle, ...style };
// 获取设备信息,计算缩放比例
const screenWidth = 320;
// 计算宽度和高度的缩放比例
const scale = 0.6;
// 计算字符位置的函数
const calculateTextPosition = (imageInfo) => {
// 计算图片宽高比
const imageRatio = imageInfo.width / imageInfo.height;
const containerRatio = 1; // 容器是正方形,宽高比为1
let ratio;
// 根据图片和容器的比例关系决定如何缩放
if (imageRatio > containerRatio) {
// 图片更宽,以宽度为基准缩放
ratio = screenWidth / imageInfo.width;
} else {
// 图片更高或等比,以高度为基准缩放
ratio = screenWidth / imageInfo.height;
}
// 计算缩放后的参数
const scaledX = x * ratio * scale;
const scaledY = y * ratio * scale;
const scaledWidth = width * ratio * scale;
const scaledHeight = height * ratio * scale;
const scaledRadius = radius * ratio * scale;
const scaledFontSize = mergedStyle.fontSize * ratio * scale;
// 计算圆心位置(基于容器的中心点)
const centerX = scaledX + scaledWidth / 2;
const centerY = scaledY + scaledHeight / 2;
// 计算每个字符的位置信息
// 根据正面/背面使用不同的计算方法,互不影响
const charList = isFront
? calculateFrontRoundTextChars({
text: text,
centerX: scaledWidth / 2, // 相对于容器的中心
centerY: scaledHeight / 2,
radius: scaledRadius,
fontSize: scaledFontSize,
fontWeight: mergedStyle.fontWeight || 'normal',
color: mergedStyle.color || '#000000'
})
: calculateBackRoundTextChars({
text: text,
centerX: scaledWidth / 2, // 相对于容器的中心
centerY: scaledHeight / 2,
radius: scaledRadius,
fontSize: scaledFontSize,
fontWeight: mergedStyle.fontWeight || 'normal',
color: mergedStyle.color || '#000000'
});
// 构建圆形文字配置对象
const roundTextConfig = {
x: scaledX,
y: scaledY,
width: scaledWidth,
height: scaledHeight,
centerX: centerX,
centerY: centerY,
radius: scaledRadius,
text: text,
charList: charList, // 字符位置列表
style: {
...mergedStyle,
fontSize: scaledFontSize,
}
};
console.log('roundTextConfig===>', roundTextConfig);
// 更新页面数据
setData({
[bindKey]: roundTextConfig
});
// 返回配置对象,以便后续使用
return roundTextConfig;
};
// 如果已有缓存的图片信息,直接使用
if (cachedImageInfo && cachedImageInfo.src === shapeImage) {
calculateTextPosition(cachedImageInfo);
return;
}
// 否则获取图片信息
const img = new Image();
img.onload = () => {
const res = {
width: img.width,
height: img.height,
path: shapeImage,
src: shapeImage
};
// 如果提供了缓存回调,调用它
if (typeof onImageInfoCached === 'function') {
onImageInfoCached(res);
}
calculateTextPosition(res);
};
img.onerror = (err) => {
console.error('Failed to get image info:', err);
};
img.src = shapeImage;
}
/**
*
* @param {Object} options -
* @param {string} options.text -
* @param {number} options.centerX - X坐标
* @param {number} options.centerY - Y坐标
* @param {number} options.radius -
* @param {number} options.fontSize -
* @param {string} options.fontWeight -
* @param {string} options.color -
* @returns {Array}
*/
function calculateFrontRoundTextChars({ text, centerX, centerY, radius, fontSize, fontWeight, color }) {
if (!text) {
return [];
}
// 计算字符宽度
// 使用更精确的估算方法
const charWidths = [];
let totalWidth = 0;
for (let i = 0; i < text.length; i++) {
const char = text[i];
let charWidth;
// 判断字符类型,使用不同的宽度估算
if (/[\u4e00-\u9fa5]/.test(char)) {
// 中文字符:宽度约为 fontSize
charWidth = fontSize;
} else if (/[0-9]/.test(char)) {
// 数字:宽度约为 fontSize * 0.6
charWidth = fontSize * 0.6;
} else if (/[a-zA-Z]/.test(char)) {
// 英文字母:宽度约为 fontSize * 0.6(大写)或 0.5(小写)
charWidth = /[A-Z]/.test(char) ? fontSize * 0.65 : fontSize * 0.5;
} else if (/[\u3000-\u303f\uff00-\uffef]/.test(char)) {
// 全角符号:宽度约为 fontSize
charWidth = fontSize;
} else {
// 其他字符(半角符号等):宽度约为 fontSize * 0.4
charWidth = fontSize * 0.4;
}
// 如果字体是粗体,稍微增加宽度
if (fontWeight === 'bold' || fontWeight === '700') {
charWidth *= 1.1;
}
charWidths.push(charWidth);
totalWidth += charWidth;
}
// 为文字之间添加2px间距(除了最后一个字符)
const spacing = 2;
const totalSpacing = (text.length > 1) ? (text.length - 1) * spacing : 0;
const totalWidthWithSpacing = totalWidth + totalSpacing;
// 计算文字总弧长和每个字符的角度(正面使用原始半径)
const circumference = 2 * Math.PI * radius;
const arcLength = totalWidthWithSpacing;
const totalAngle = (arcLength / circumference) * 2 * Math.PI;
// 计算起始角度(使文字居中于底部)
// 从底部中心开始,顺时针排列,起始角度 = 底部中心 + 总角度的一半
const startAngle = Math.PI / 2 + totalAngle / 2;
// 创建并定位每个字符(逆时针排列,所以角度递减)
let currentAngle = startAngle;
const charList = [];
for (let i = 0; i < text.length; i++) {
const char = text[i];
const charWidth = charWidths[i];
// 计算字符角度增量(包括字符宽度和间距)
// 最后一个字符不需要添加后面的间距
const spacingAfter = (i < text.length - 1) ? spacing : 0;
const charAngleIncrement = ((charWidth + spacingAfter) / circumference) * 2 * Math.PI;
// 计算字符角度位置(逆时针排列,所以角度递减)
// 字符中心位置 = 当前角度 - 字符宽度的一半对应的角度
const charWidthAngle = (charWidth / circumference) * 2 * Math.PI;
const charAngle = currentAngle - charWidthAngle / 2;
// 计算字符位置(正面使用原始半径)
const x = centerX + radius * Math.cos(charAngle);
const y = centerY + radius * Math.sin(charAngle) - fontSize / 3;
// 计算旋转角度(正面:文字底部向外,顶部朝向圆心)
const rotateAngle = charAngle + Math.PI * 1.5;
// 转换为度数(用于CSS transform)
const rotateDeg = (rotateAngle * 180) / Math.PI;
charList.push({
char: char,
x: x,
y: y,
rotate: rotateAngle,
rotateDeg: rotateDeg, // 度数版本
fontSize: fontSize,
fontWeight: fontWeight,
color: color
});
// 更新当前角度(逆时针排列,所以角度递减)
currentAngle -= charAngleIncrement;
}
return charList;
}
/**
*
* @param {Object} options -
* @param {string} options.text -
* @param {number} options.centerX - X坐标
* @param {number} options.centerY - Y坐标
* @param {number} options.radius -
* @param {number} options.fontSize -
* @param {string} options.fontWeight -
* @param {string} options.color -
* @returns {Array}
*/
function calculateBackRoundTextChars({ text, centerX, centerY, radius, fontSize, fontWeight, color }) {
if (!text) {
return [];
}
// 计算字符宽度
// 使用更精确的估算方法
const charWidths = [];
let totalWidth = 0;
for (let i = 0; i < text.length; i++) {
const char = text[i];
let charWidth;
// 判断字符类型,使用不同的宽度估算
if (/[\u4e00-\u9fa5]/.test(char)) {
// 中文字符:宽度约为 fontSize
charWidth = fontSize;
} else if (/[0-9]/.test(char)) {
// 数字:宽度约为 fontSize * 0.6
charWidth = fontSize * 0.6;
} else if (/[a-zA-Z]/.test(char)) {
// 英文字母:宽度约为 fontSize * 0.6(大写)或 0.5(小写)
charWidth = /[A-Z]/.test(char) ? fontSize * 0.65 : fontSize * 0.5;
} else if (/[\u3000-\u303f\uff00-\uffef]/.test(char)) {
// 全角符号:宽度约为 fontSize
charWidth = fontSize;
} else {
// 其他字符(半角符号等):宽度约为 fontSize * 0.4
charWidth = fontSize * 0.4;
}
// 如果字体是粗体,稍微增加宽度
if (fontWeight === 'bold' || fontWeight === '700') {
charWidth *= 1.1;
}
charWidths.push(charWidth);
totalWidth += charWidth;
}
// 为文字之间添加2px间距(除了最后一个字符)
const spacing = 1;
const totalSpacing = (text.length > 1) ? (text.length - 1) * spacing : 0;
const totalWidthWithSpacing = totalWidth + totalSpacing;
// 计算文字总弧长和每个字符的角度
// 背面:文字到圆心的距离 = 半径 + 文字高度的一半
const adjustedRadius = radius + fontSize / 2;
const circumference = 2 * Math.PI * adjustedRadius;
const arcLength = totalWidthWithSpacing;
const totalAngle = (arcLength / circumference) * 2 * Math.PI;
// 计算起始角度(使文字居中于底部)
// 从底部中心开始,顺时针排列,起始角度 = 底部中心 - 总角度的一半
const startAngle = Math.PI / 2 - totalAngle / 2;
// 创建并定位每个字符(顺时针排列,所以角度递增)
let currentAngle = startAngle;
const charList = [];
for (let i = 0; i < text.length; i++) {
const char = text[i];
const charWidth = charWidths[i];
// 计算字符角度增量(包括字符宽度和间距)
// 最后一个字符不需要添加后面的间距
const spacingAfter = (i < text.length - 1) ? spacing : 0;
const charAngleIncrement = ((charWidth + spacingAfter) / circumference) * 2 * Math.PI;
// 计算字符角度位置(顺时针排列,所以角度递增)
// 字符中心位置 = 当前角度 + 字符宽度的一半对应的角度
const charWidthAngle = (charWidth / circumference) * 2 * Math.PI;
const charAngle = currentAngle + charWidthAngle / 2;
// 计算字符位置(背面:文字到圆心的距离 = 半径 + 文字高度的一半)
const x = centerX + adjustedRadius * Math.cos(charAngle);
const y = centerY + adjustedRadius * Math.sin(charAngle);
// 计算旋转角度(背面:文字底部朝向圆心,顶部向外)
const rotateAngle = charAngle + Math.PI * 0.5;
// 转换为度数(用于CSS transform)
const rotateDeg = (rotateAngle * 180) / Math.PI;
charList.push({
char: char,
x: x,
y: y,
rotate: rotateAngle,
rotateDeg: rotateDeg, // 度数版本
fontSize: fontSize,
fontWeight: fontWeight,
color: color
});
// 更新当前角度(顺时针排列,所以角度递增)
currentAngle += charAngleIncrement;
}
return charList;
}
/**
* Canvas
* @param {string} canvasId - Canvas ID
* @param {Object} config - width height
* @returns {Promise} canvas ctx
*/
function initRoundTextCanvas(canvasId, config) {
return new Promise((resolve) => {
const tryInit = () => {
// 如果是选择器字符串,去掉 # 或 . 前缀
const selector = canvasId.startsWith('#') ? canvasId.slice(1) :
canvasId.startsWith('.') ? canvasId.slice(1) : canvasId;
// 尝试通过 ID 查找
let canvasElement: HTMLCanvasElement | null = document.getElementById(selector) as HTMLCanvasElement | null;
// 如果找不到,尝试通过类名查找(取第一个)
if (!canvasElement && canvasId.startsWith('.')) {
const elements = document.getElementsByClassName(selector);
if (elements.length > 0) {
canvasElement = elements[0] as HTMLCanvasElement;
}
}
// 如果还是找不到,尝试直接使用 canvasId 作为选择器
if (!canvasElement) {
canvasElement = document.querySelector(canvasId) as HTMLCanvasElement | null;
}
if (canvasElement && canvasElement instanceof HTMLCanvasElement) {
const canvas = canvasElement;
const ctx = canvas.getContext('2d');
if (!ctx) {
throw new Error('无法获取 Canvas 2D 上下文');
}
const dpr = window.devicePixelRatio || 1;
// 使用配置中的尺寸,如果没有则使用 Canvas 的实际尺寸或默认值
const width = (config && config.width) || canvas.offsetWidth || 700;
const height = (config && config.height) || canvas.offsetHeight || 700;
canvas.width = width * dpr;
canvas.height = height * dpr;
ctx.scale(dpr, dpr);
resolve({ canvas, ctx });
} else {
// 如果 Canvas 还未渲染,延迟重试
setTimeout(() => {
tryInit();
}, 100);
}
};
tryInit();
});
}
/**
* Canvas
* @param {Object} options -
* @param {Object} options.ctx - Canvas 2D
* @param {Object} options.config -
* @param {Function} options.setData -
* @param {HTMLCanvasElement} options.canvas - Canvas
* @param {string} options.imageKey -
* @returns {Promise} Data URL
*/
function drawRoundTextOnCanvas({ ctx, config, setData, canvas, imageKey = 'roundTextImage' }) {
return new Promise((resolve, reject) => {
if (!ctx || !config) {
console.log('drawRoundTextOnCanvas: ctx 或 config 不存在', { ctx: !!ctx, config: !!config });
if (setData) {
setData({
[imageKey]: ''
});
}
resolve('');
return;
}
const text = config.text;
if (!text) {
console.log('drawRoundTextOnCanvas: 文字为空');
// 如果没有文字,清空图片
if (setData) {
setData({
[imageKey]: ''
});
}
resolve('');
return;
}
console.log('drawRoundTextOnCanvas: 开始绘制文字', { text, config });
// 使用配置中的宽高
const canvasWidth = config.width || 700;
const canvasHeight = config.height || 700;
// 圆心位置:根据需求,圆心应该在容器的中心
// 由于容器就是 Canvas,所以圆心就是 Canvas 的中心
const centerX = canvasWidth / 2;
const centerY = canvasHeight / 2;
const radius = config.radius;
const fontSize = config.style.fontSize;
const color = config.style.color || '#000000';
const fontWeight = config.style.fontWeight || 'normal';
// 清空画布(注意:Canvas 的实际尺寸已经乘以了 dpr,但绘制时使用的是逻辑尺寸)
ctx.clearRect(0, 0, canvasWidth, canvasHeight);
// 设置字体样式
ctx.font = `${fontWeight} ${fontSize}px sans-serif`;
ctx.fillStyle = color;
ctx.textAlign = 'center';
ctx.textBaseline = 'middle'; // 使用 middle 基线,文字中心对齐,更适合圆形排列
// 计算每个字符的角度
const circumference = 2 * Math.PI * radius;
const charWidths = [];
let totalWidth = 0;
// 测量每个字符的宽度
for (let i = 0; i < text.length; i++) {
const char = text[i];
const metrics = ctx.measureText(char);
const width = metrics.width;
charWidths.push(width);
totalWidth += width;
}
// 计算文字总弧长和每个字符的角度
const arcLength = totalWidth;
const totalAngle = (arcLength / circumference) * 2 * Math.PI;
// 计算起始角度(使文字居中于底部)
// 从底部中心开始,顺时针排列,起始角度 = 底部中心 + 总角度的一半
const startAngle = Math.PI / 2 + totalAngle / 2;
// 创建并定位每个字符(逆时针排列,所以角度递减)
let currentAngle = startAngle;
for (let i = 0; i < text.length; i++) {
const char = text[i];
const charWidth = charWidths[i];
// 计算字符角度增量
const charAngleIncrement = (charWidth / circumference) * 2 * Math.PI;
// 计算字符角度位置(逆时针排列,所以角度递减)
const charAngle = currentAngle - charAngleIncrement / 2;
// 计算字符位置
const x = centerX + radius * Math.cos(charAngle);
const y = centerY + radius * Math.sin(charAngle);
// 保存上下文
ctx.save();
// 移动到字符位置
ctx.translate(x, y);
// 旋转文字,使其沿着圆形路径排列
// 文字底部向外,顶部朝向圆心,所以旋转角度为字符角度 + π * 1.5
ctx.rotate(charAngle + Math.PI * 1.5);
// 绘制文字(使用 0, 0 作为中心点,因为已经 translate 到字符位置)
ctx.fillText(char, 0, 0);
// 恢复上下文
ctx.restore();
// 更新当前角度(逆时针排列,所以角度递减)
currentAngle -= charAngleIncrement;
}
// 将 Canvas 转换为图片(Data URL)
try {
const dataURL = canvas.toDataURL('image/png');
if (setData) {
setData({
[imageKey]: dataURL
});
}
resolve(dataURL);
} catch (err) {
console.error('Canvas 转图片失败:', err);
reject(err);
}
});
}
return {
roundText,
initRoundTextCanvas,
drawRoundTextOnCanvas,
calculateFrontRoundTextChars,
calculateBackRoundTextChars
};
}

47
src/views/badge/index.vue

@ -27,6 +27,9 @@
<div class="order-type-item-title" v-if="typeId == 4"> <div class="order-type-item-title" v-if="typeId == 4">
{{ toValueWithout("3D卡通手办") }} {{ toValueWithout("3D卡通手办") }}
</div> </div>
<div class="order-type-item-title" v-if="typeId == 6">
{{ toValueWithout("浮雕挂饰") }}
</div>
</div> </div>
</div> </div>
<div class="size-title"> <div class="size-title">
@ -76,11 +79,11 @@
<p style="font-size: 12px; color: #000; margin-left: 16px;">{{ toValueWithout("注:需要先输入手机号才可体验徽章设计") }}</p> <p style="font-size: 12px; color: #000; margin-left: 16px;">{{ toValueWithout("注:需要先输入手机号才可体验徽章设计") }}</p>
<div class="style-box"> <div class="style-box">
<div class="style-box-item"> <div class="style-box-item">
<div class="style-item-title" :class="{ styleActive: prodId == 7 || prodId == 1 }" @click="styleChange(7)"> <div class="style-item-title" :class="{ styleActive: prodId == 7 || prodId == 1 || prodId == 25 }" @click="styleChange(7)">
{{ prop == '3D真人肖像' ? toValueWithout('3D真人肖像') : toValueWithout('人物立体徽章') }} {{ prop == '3D真人肖像' ? toValueWithout('3D真人肖像') : toValueWithout('人物主体') }}
</div> </div>
<div class="style-item-title" :class="{ styleActive: prodId == 8 || prodId == 2 }" @click="styleChange(8)"> <div class="style-item-title" :class="{ styleActive: prodId == 8 || prodId == 2 || prodId == 24 }" @click="styleChange(8)">
{{ toValueWithout("宠物立体徽章") }} {{ toValueWithout("宠物主体") }}
</div> </div>
</div> </div>
</div> </div>
@ -116,10 +119,10 @@
</div> </div>
<div class="tag-change-box" v-if="trialCode == false"> <div class="tag-change-box" v-if="trialCode == false">
<div class="tag-change-item"> <div class="tag-change-item">
<div class="tag-change-item-title" :class="{ tagActive: prodId == 7 || prodId == 1 }" @click="prodChange(7)"> <div class="tag-change-item-title" :class="{ tagActive: prodId == 7 || prodId == 1 || prodId == 25 }" @click="prodChange(7)">
{{ toValueWithout("人物主体") }} {{ toValueWithout("人物主体") }}
</div> </div>
<div class="tag-change-item-title" :class="{ tagActive: prodId == 8 || prodId == 19 }" @click="prodChange(8)"> <div class="tag-change-item-title" :class="{ tagActive: prodId == 8 || prodId == 19 || prodId == 24 }" @click="prodChange(8)">
{{ toValueWithout("宠物主体") }} {{ toValueWithout("宠物主体") }}
</div> </div>
</div> </div>
@ -194,8 +197,8 @@
</div> </div>
</div> </div>
<div v-if="typeId != 4"> <div v-if="typeId != 4">
<div style="font-size: 12px; color: red; margin-top: 16px; text-align: center;" v-if="prodId == 7 || prodId == 1">{{ toValueWithout("温馨提示请上传只有") }}{{ prop == '3D真人肖像' ? '1' : '1-3' }}{{ toValueWithout("人的照片") }}</div> <div style="font-size: 12px; color: red; margin-top: 16px; text-align: center;" v-if="prodId == 7 || prodId == 1 || prodId == 25">{{ toValueWithout("温馨提示请上传只有") }}{{ prop == '3D真人肖像' ? '1' : '1-3' }}{{ toValueWithout("人的照片") }}</div>
<div style="font-size: 12px; color: red; margin-top: 16px; text-align: center;" v-if="prodId == 8 || prodId == 2">{{ toValueWithout("温馨提示请上传只有") }}1-3{{ toValueWithout("只宠物的照片") }}</div> <div style="font-size: 12px; color: red; margin-top: 16px; text-align: center;" v-if="prodId == 8 || prodId == 2 || prodId == 24">{{ toValueWithout("温馨提示请上传只有") }}1-3{{ toValueWithout("只宠物的照片") }}</div>
</div> </div>
<div style="height: 120px;"></div> <div style="height: 120px;"></div>
<div class="design-action-bar"> <div class="design-action-bar">
@ -356,11 +359,9 @@ const typeId = ref(0)
const getOrderStat = () => { const getOrderStat = () => {
badgeApi.getOrderStat({}).then((res: any) => { badgeApi.getOrderStat({}).then((res: any) => {
orderStat.value = res orderStat.value = res
prodId.value = res.prod_id
if (res.type_id == 4) { if (res.type_id == 4) {
prodId.value = res.prod_id == 1 ? 1 : 19
getKindList() getKindList()
} else {
prodId.value = res.type_id == 3 ? 8 : res.prod_id
} }
prop.value = res.prop prop.value = res.prop
typeId.value = res.type_id typeId.value = res.type_id
@ -371,7 +372,7 @@ const getOrderStat = () => {
const kindList = ref([]) const kindList = ref([])
const getKindList = () => { const getKindList = () => {
badgeApi.getKindList({ badgeApi.getKindList({
support_subject: prodId.value == 19 ? 2 : 1, support_subject: getSupportSubject(),
type_id: 4 type_id: 4
}).then((res: any) => { }).then((res: any) => {
kindList.value = res.list kindList.value = res.list
@ -380,8 +381,15 @@ const getKindList = () => {
}) })
} }
const getSupportSubject = () => {
if (prodId.value == 19 || prodId.value == 24 || prodId.value == 8) {
return 2
} else {
return 1
}
}
const prodChange = (id: number) => { const prodChange = (id: number) => {
console.log('prodChange', id)
if (typeId.value == 3 && id == 7) { if (typeId.value == 3 && id == 7) {
showToast(toValueWithout('人物3D冰箱贴暂未开放')) showToast(toValueWithout('人物3D冰箱贴暂未开放'))
return return
@ -396,7 +404,14 @@ const prodChange = (id: number) => {
return return
} }
} }
prodId.value = typeId.value == 4 ? id == 8 ? 19 : 1 : id == 7 ? 7 : 8 if (typeId.value == 6) {
prodId.value = id == 8 ? 24 : 25
} else if (typeId.value == 4) {
prodId.value = id == 8 ? 19 : 1
} else {
prodId.value = id == 7 ? 7 : 8
}
console.log('prodChange', prodId.value)
picture.value = null picture.value = null
kindId.value = 0 kindId.value = 0
} }
@ -489,7 +504,7 @@ function getbase64Data(data) {
return false; return false;
} }
imgurl.value = blob; imgurl.value = blob;
if (prodId.value == 7 || prodId.value == 1) { if (prodId.value == 7 || prodId.value == 1 || prodId.value == 25) {
getUploadUrl() getUploadUrl()
} }
} }
@ -815,7 +830,7 @@ const getSundryList = () => {
badgeApi.getSundryList({ badgeApi.getSundryList({
page: 1, page: 1,
size: 6, size: 6,
group: prodId.value == 7 || prodId.value == 1 ? 'gp' : 'pet', group: prodId.value == 7 || prodId.value == 1 || prodId.value == 25 ? 'gp' : 'pet',
}).then((res: any) => { }).then((res: any) => {
const data = res || [] const data = res || []
sundryList.value = data.list sundryList.value = data.list

47
src/views/badge/orderDetail.vue

@ -6,9 +6,13 @@
<div class="order-status"> <div class="order-status">
<div class="avatar-wrapper"> <div class="avatar-wrapper">
<!-- <img v-if="shapeImage" class="avatar-back-img" :src="shapeImage" alt=""> --> <!-- <img v-if="shapeImage" class="avatar-back-img" :src="shapeImage" alt=""> -->
<div class="avatar-front-box"> <div class="avatar-front-box" v-if="order.type_id != 6">
<img class="avatar-font-img" :src="imageUrl" :alt="order.kind_name" /> <img class="avatar-font-img" :src="imageUrl" :alt="order.kind_name" />
</div> </div>
<div class="avatar-front-box-double" v-if="order.type_id == 6">
<img class="avatar-font-img" :src="imageUrl" />
<img class="avatar-font-img" :src="backImageUrl" />
</div>
</div> </div>
</div> </div>
<div class="status-info"> <div class="status-info">
@ -45,12 +49,13 @@
<span class="product-value" v-if="order.type_id == 2">{{ order.prod_id == 7 ? toValueWithout('人物浮雕相框') : toValueWithout('宠物浮雕相框') }}</span> <span class="product-value" v-if="order.type_id == 2">{{ order.prod_id == 7 ? toValueWithout('人物浮雕相框') : toValueWithout('宠物浮雕相框') }}</span>
<span class="product-value" v-if="order.type_id == 3">{{ order.prod_id == 7 ? toValueWithout('人物冰箱贴') : toValueWithout('宠物冰箱贴') }}</span> <span class="product-value" v-if="order.type_id == 3">{{ order.prod_id == 7 ? toValueWithout('人物冰箱贴') : toValueWithout('宠物冰箱贴') }}</span>
<span class="product-value" v-if="order.type_id == 4">{{ order.prod_id == 1 ? toValueWithout('人物卡通手办') : toValueWithout('宠物卡通手办') }}</span> <span class="product-value" v-if="order.type_id == 4">{{ order.prod_id == 1 ? toValueWithout('人物卡通手办') : toValueWithout('宠物卡通手办') }}</span>
<span class="product-value" v-if="order.type_id == 6">{{ order.prod_id == 25 ? toValueWithout('人物浮雕挂饰') : toValueWithout('宠物浮雕挂饰') }}</span>
</div> </div>
<div class="product-row"> <div class="product-row">
<span class="product-label">{{ toValueWithout("尺寸") }}</span> <span class="product-label">{{ toValueWithout("尺寸") }}</span>
<span class="product-value">{{order.model_size}}</span> <span class="product-value">{{order.model_size}}</span>
</div> </div>
<div class="product-row" v-if="shape_name"> <div class="product-row" v-if="shape_name && order.type_id != 6">
<span class="product-label">{{ toValueWithout("形状") }}</span> <span class="product-label">{{ toValueWithout("形状") }}</span>
<span class="product-value">{{ toValueWithout(shape_name) }}</span> <span class="product-value">{{ toValueWithout(shape_name) }}</span>
</div> </div>
@ -60,20 +65,6 @@
</div> </div>
</div> </div>
</div> </div>
<!-- <div style="padding: 0 16px;">
<van-divider />
</div> -->
<!-- <div class="address-info" style="padding: 0 16px;">
<div class="address-title">收货信息</div>
<div class="address-row">
<img class="address-img" src="@/assets/badge/location.png" alt="" >
<span class="address-name">张先生</span>
<span class="address-phone">136****0731</span>
</div>
<div class="address-detail">
详细地址详细地址详细地址详细地址详细地址详细地址
</div>
</div> -->
<div style="padding: 0 16px;"> <div style="padding: 0 16px;">
<van-divider /> <van-divider />
</div> </div>
@ -99,6 +90,7 @@ import * as badgeApi from '@/api/badge';
import { onMounted, ref } from 'vue'; import { onMounted, ref } from 'vue';
import { useRoute } from 'vue-router'; import { useRoute } from 'vue-router';
import { toValueWithout } from '@/lang/utils'; import { toValueWithout } from '@/lang/utils';
const route = useRoute(); const route = useRoute();
const order = ref({}) const order = ref({})
const id = ref(0) const id = ref(0)
@ -109,17 +101,24 @@ onMounted(() => {
const shapeImage = ref('') const shapeImage = ref('')
const imageUrl = ref('') const imageUrl = ref('')
const backImageUrl = ref('')
const getStyle = ref('') const getStyle = ref('')
const shape_name = ref('') const shape_name = ref('')
const imageList = ref([])
function getOrderDetail() { function getOrderDetail() {
badgeApi.getOrderDetail({ badgeApi.getOrderDetail({
id: id.value, id: id.value,
}).then(res => { }).then(res => {
order.value = res order.value = res;
imageUrl.value = res.path imageUrl.value = res.path;
shapeImage.value = res.shape_details.frame_path backImageUrl.value = res.back_path;
shape_name.value = res.shape_details.name shapeImage.value = res.shape_details.frame_path;
shape_name.value = res.shape_details.name;
imageList.value = [
res.path,
res.back_path,
];
// if (res.shape_details) { // if (res.shape_details) {
// ImageShow(res.shape_details) // ImageShow(res.shape_details)
// } // }
@ -209,6 +208,14 @@ function getStatus(status: number) {
max-height: 320px; max-height: 320px;
border-radius: 10px; border-radius: 10px;
} }
.avatar-front-box-double {
display: flex;
flex-direction: row;
gap: 10px;
overflow-x: auto;
white-space: nowrap;
-webkit-overflow-scrolling: touch;
}
.progress-image-item-shadow { .progress-image-item-shadow {
position: absolute; position: absolute;
top: 0; top: 0;

337
src/views/badge/preview.vue

@ -35,6 +35,18 @@
<!-- <div class="box1-round-shadow" v-if="shapeId == 1 && shapeImage == ''" style="width: 320px;height: 320px;"></div> --> <!-- <div class="box1-round-shadow" v-if="shapeId == 1 && shapeImage == ''" style="width: 320px;height: 320px;"></div> -->
</div> </div>
<div class="shape-text" :style="shapeTextStyle" v-if="shapeText">{{shapeText}}</div> <div class="shape-text" :style="shapeTextStyle" v-if="shapeText">{{shapeText}}</div>
<!-- <div class="shape-text" :style="frontTextStyle" v-if="frontText">{{frontText}}</div>
<div class="shape-text" :style="backTextStyle" v-if="backText">{{backText}}</div> -->
<div v-if="badgeTypeId == 6 && axisz == 1 && roundTextConfigFront.width && roundTextConfigFront.charList" class="roundText font-chinese" :style="`left: ${roundTextConfigFront.x}px;top: ${roundTextConfigFront.y}px;width: ${roundTextConfigFront.width}px;height: ${roundTextConfigFront.height}px;position: absolute;pointer-events: none;z-index: 10;`">
<div v-for="item in roundTextConfigFront.charList" :key="item.char" class="round-text-char" :style="`position: absolute;left: ${item.x}px;top: ${item.y}px;font-size: ${item.fontSize}px;font-weight: ${item.fontWeight};color: ${item.color};transform: translate(-50%, -50%) rotate(${item.rotateDeg}deg);transform-origin: center;white-space: nowrap;`">
<span>{{item.char}}</span>
</div>
</div>
<div v-if="badgeTypeId == 6 && axisz == -1 && roundTextConfigBack.width && roundTextConfigBack.charList" class="roundText font-chinese" :style="`left: ${roundTextConfigBack.x}px;top: ${roundTextConfigBack.y}px;width: ${roundTextConfigBack.width}px;height: ${roundTextConfigBack.height}px;position: absolute;pointer-events: none;z-index: 10;`">
<div v-for="(item, index) in roundTextConfigBack.charList" :key="index" class="round-text-char" :style="`position: absolute;left: ${item.x}px;top: ${item.y}px;font-size: ${item.fontSize}px;font-weight: ${item.fontWeight};color: ${item.color};transform: translate(-50%, -50%) rotate(${item.rotateDeg}deg);transform-origin: center;white-space: nowrap;`">
<span>{{item.char}}</span>
</div>
</div>
</div> </div>
</div> </div>
<div class="image-list-box" v-if="imageList.length > 1"> <div class="image-list-box" v-if="imageList.length > 1">
@ -54,6 +66,7 @@
<div class="info-title" v-if="typeId == 2">{{ prodId == 7 ? toValueWithout('人物浮雕相框') : toValueWithout('宠物浮雕相框') }}</div> <div class="info-title" v-if="typeId == 2">{{ prodId == 7 ? toValueWithout('人物浮雕相框') : toValueWithout('宠物浮雕相框') }}</div>
<div class="info-title" v-if="typeId == 3">{{ prodId == 7 ? toValueWithout('人物3D冰箱贴') : toValueWithout('宠物3D冰箱贴') }}</div> <div class="info-title" v-if="typeId == 3">{{ prodId == 7 ? toValueWithout('人物3D冰箱贴') : toValueWithout('宠物3D冰箱贴') }}</div>
<div class="info-title" v-if="typeId == 4">{{ prodId == 1 ? toValueWithout('人物卡通手办') : toValueWithout('宠物卡通手办') }}</div> <div class="info-title" v-if="typeId == 4">{{ prodId == 1 ? toValueWithout('人物卡通手办') : toValueWithout('宠物卡通手办') }}</div>
<div class="info-title" v-if="typeId == 6">{{ prodId == 25 ? toValueWithout('人物浮雕挂饰') : toValueWithout('宠物浮雕挂饰') }}</div>
<div class="info-content">{{ toValueWithout("产品类型") }}</div> <div class="info-content">{{ toValueWithout("产品类型") }}</div>
</div> </div>
<div class="info-item"> <div class="info-item">
@ -80,9 +93,13 @@
</div> </div>
</block> </block>
</div> </div>
<div class="shape-box-input" v-if="imageUrl && custom_switch == 1"> <div class="shape-box-input" v-if="imageUrl && custom_switch == 1 && typeId == 2">
<input class="shape-box-input-text" type="text" :placeholder="toValueWithout('请输入文字')" v-model="shapeText" @change="changeShapeText" @input="changeShapeText" @onBlur="changeShapeText" /> <input class="shape-box-input-text" type="text" :placeholder="toValueWithout('请输入文字')" v-model="shapeText" @change="changeShapeText" @input="changeShapeText" @onBlur="changeShapeText" />
</div> </div>
<div class="shape-box-input-box" v-if="imageUrl && custom_switch == 1 && typeId == 6">
<input class="shape-box-input-text" v-if="axisz == 1" type="text" :placeholder="toValueWithout('请输入正面文字')" v-model="frontText" @change="changeFrontText" @input="changeFrontText" @onBlur="changeFrontText" />
<input class="shape-box-input-text" v-if="axisz == -1" type="text" :placeholder="toValueWithout('请输入背面文字')" v-model="backText" @change="changeBackText" @input="changeBackText" @onBlur="changeBackText" />
</div>
</div> </div>
<!-- <div class="info-desc"> <!-- <div class="info-desc">
下单后预计需要7天完成生产发货<br> 下单后预计需要7天完成生产发货<br>
@ -103,15 +120,6 @@
</div> </div>
</div> </div>
</block> </block>
<!-- <block v-if="orderStat.use_type == 2">
<div class="order-item">
<span class="order-size">{{ item.size }}</span>
<span class="order-free">({{ toValueWithout("剩余兑换") }}{{ item.remaining }})</span>
<div class="order-ctrl">
<van-stepper v-model="item.count" :min="0" :max="item.remaining" @change="changeValue" />
</div>
</div>
</block> -->
</block> </block>
</div> </div>
<div class="address-box" v-if="orderStat.use_type == 2 && imageUrl && code == 'ACAYOAAC3PFCPO3CD6DVM1'"> <div class="address-box" v-if="orderStat.use_type == 2 && imageUrl && code == 'ACAYOAAC3PFCPO3CD6DVM1'">
@ -193,13 +201,15 @@
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { onMounted, ref, onUnmounted } from 'vue'; import { onMounted, ref, onUnmounted, nextTick } from 'vue';
import { useRouter, useRoute } from 'vue-router'; import { useRouter, useRoute } from 'vue-router';
import { showSuccessToast, showToast, showNotify, showConfirmDialog, AddressEdit, Area } from 'vant'; import { showSuccessToast, showToast, showNotify, showConfirmDialog, AddressEdit, Area } from 'vant';
import { localStorage } from '@/utils/local-storage' import { localStorage } from '@/utils/local-storage'
import * as badgeApi from '@/api/badge' import * as badgeApi from '@/api/badge'
import { areaList } from '@/utils/area' import { areaList } from '@/utils/area'
import { toValueWithout } from '@/lang/utils' import { toValueWithout } from '@/lang/utils'
import { createTextPosition } from '@/utils/textHelper'
const router = useRouter(); const router = useRouter();
const value = ref(0); const value = ref(0);
const showReload = ref(false) const showReload = ref(false)
@ -209,6 +219,36 @@ const currentIndex = ref(0)
const imageList = ref([]) const imageList = ref([])
const imageWater = ref('') const imageWater = ref('')
const frontText = ref('')
const backText = ref('')
const frontKey = ref(1)
//
const roundTextConfigFront = ref({})
const roundTextConfigBack = ref({})
const cachedImageInfo = ref(null)
const imageInfo = ref(null)
const badgeTypeId = ref(0)
const axisz = ref(1)
// Vue textHelper
const textHelper = createTextPosition({
setData: (data: any) => {
// Vue setData ref
Object.keys(data).forEach(key => {
if (key === 'roundTextConfigFront') {
roundTextConfigFront.value = data[key]
} else if (key === 'roundTextConfigBack') {
roundTextConfigBack.value = data[key]
} else if (key === 'cachedImageInfo') {
cachedImageInfo.value = data[key]
} else if (key === 'imageInfo') {
imageInfo.value = data[key]
}
})
}
})
const code = localStorage.get('code') const code = localStorage.get('code')
function compare() { function compare() {
@ -497,7 +537,10 @@ const confirm = () => {
products: sizeList.value, products: sizeList.value,
prod_id: prodId.value, prod_id: prodId.value,
shape_id: shapeId.value, shape_id: shapeId.value,
custom_text: shapeText.value custom_text: shapeText.value ? shapeText.value : frontText.value,
back_text: backText.value,
shape_ids: shapeIds.value,
type_id: typeId.value,
} }
if (orderStat.value.use_type == 2) { if (orderStat.value.use_type == 2) {
parms.province_id = province_id.value parms.province_id = province_id.value
@ -545,8 +588,11 @@ const getPosition = () => {
badgeApi.composite({ badgeApi.composite({
pid: pid.value, pid: pid.value,
num: imgKey.value, num: imgKey.value,
custom_text: shapeText.value, custom_text: shapeText.value ? shapeText.value : frontSaveText.value,
back_text: backSaveText.value,
shape_id: shapeId.value, shape_id: shapeId.value,
type_id: typeId.value,
shape_ids: shapeIds.value,
}).then((res: any) => { }).then((res: any) => {
console.log('getPosition', res) console.log('getPosition', res)
}).catch((err) => { }).catch((err) => {
@ -697,6 +743,7 @@ const getImageList = () => {
} }
const shapeId = ref(0) const shapeId = ref(0)
const shapeIds = ref([])
const shapeImage = ref('') const shapeImage = ref('')
const shapeList = ref([]) const shapeList = ref([])
@ -714,13 +761,29 @@ const getShapeList = () => {
custom_switch.value = res.list[0]?.custom_switch custom_switch.value = res.list[0]?.custom_switch
limitCount.value = res.list[0]?.text_limit_max limitCount.value = res.list[0]?.text_limit_max
ImageShow(res.list[0]) ImageShow(res.list[0])
if (custom_switch.value == 1) { if (custom_switch.value == 1 && typeId.value == 2) {
textShow(res.list[0]) textShow(res.list[0])
} }
if (custom_switch.value == 1 && typeId.value == 6) {
shapeIds.value = res.list.map((item: any) => item.id)
// id axisz
if (res.list[0].axisz == 1) {
axisz.value = 1
frontKey.value = 1
frontTextShow(res.list[0], true)
} else if (res.list[0].axisz == -1) {
axisz.value = -1
frontKey.value = 2
frontTextShow(res.list[0], false)
} else {
//
axisz.value = 1
frontKey.value = 1
frontTextShow(res.list[0], true)
}
}
}).catch((err) => { }).catch((err) => {
console.log('getShapeList', err) console.log('getShapeList', err)
}).finally((err) => {
}) })
} }
@ -759,6 +822,133 @@ const textShow = (item: any) => {
} }
} }
const frontTextStyle = ref('')
const backTextStyle = ref('')
const frontTextShow = (event: any, isFront: boolean | null = null) => {
// isFront frontKey
if (isFront === null) {
isFront = frontKey.value == 1;
}
// isFront
isFront = Boolean(isFront);
// /
let config: any = {};
if (isFront) {
// 使 event
config = {
x: event.front_text_axisx || 163,
y: event.front_text_axisy || 222,
width: event.front_text_width || 700,
height: event.front_text_height || 700,
radius: event.front_text_radius || 350,
fontSize: event.front_font_size || 72,
maxLength: 18
};
} else {
// 使 event
// 使 back_ 使
config = {
x: event.back_text_axisx !== undefined ? event.back_text_axisx : 238,
y: event.back_text_axisy !== undefined ? event.back_text_axisy : 297,
width: event.back_text_width !== undefined ? event.back_text_width : 550,
height: event.back_text_height !== undefined ? event.back_text_height : 550,
radius: event.back_text_radius !== undefined ? event.back_text_radius : 275,
fontSize: event.back_font_size !== undefined ? event.back_font_size : 60,
maxLength: 56
};
}
const text = isFront ? frontText.value : backText.value;
// roundText ref Vue
// /
const bindKey = isFront ? 'roundTextConfigFront' : 'roundTextConfigBack';
// 使
const shapeImagePath = event.frame_path || shapeImage.value;
const cachedInfo = cachedImageInfo.value;
//
const needFetchImage = !cachedInfo || cachedInfo.src !== shapeImagePath;
// 使
if (!needFetchImage && cachedInfo) {
textHelper.roundText({
shapeImage: shapeImagePath,
x: config.x,
y: config.y,
width: config.width,
height: config.height,
radius: config.radius,
text: text,
isFront: isFront,
style: {
fontSize: config.fontSize,
color: event.font_color || '#000000',
fontWeight: event.font_weight || 'normal',
textAlign: 'center',
},
bindKey: bindKey,
cachedImageInfo: cachedInfo //
});
// 使
nextTick(() => {
const currentConfig = isFront ? roundTextConfigFront.value : roundTextConfigBack.value;
if (frontKey.value == (isFront ? 1 : 2) && currentConfig && currentConfig.charList) {
// Vue setData
}
});
} else {
//
textHelper.roundText({
shapeImage: shapeImagePath,
x: config.x,
y: config.y,
width: config.width,
height: config.height,
radius: config.radius,
text: text,
isFront: isFront,
style: {
fontSize: config.fontSize,
color: event.font_color || '#000000',
fontWeight: event.font_weight || 'normal',
textAlign: 'center',
},
bindKey: bindKey,
onImageInfoCached: (imageInfo: any) => {
// 使
cachedImageInfo.value = imageInfo;
}
});
// frontKey
const checkAndUpdate = (attempts = 0) => {
if (attempts > 10) return; // 10
const currentConfig = isFront ? roundTextConfigFront.value : roundTextConfigBack.value;
// Vue
if (frontKey.value == (isFront ? 1 : 2)) {
if (currentConfig && currentConfig.charList && currentConfig.charList.length > 0) {
// Vue setData
} else if (attempts < 10) {
//
setTimeout(() => {
checkAndUpdate(attempts + 1);
}, 50);
}
}
};
//
setTimeout(() => {
checkAndUpdate(0);
}, 50);
}
}
const shapeText = ref('') const shapeText = ref('')
const changeShapeText = (e: any) => { const changeShapeText = (e: any) => {
console.log('changeShapeText', e.target.value) console.log('changeShapeText', e.target.value)
@ -770,6 +960,40 @@ const changeShapeText = (e: any) => {
handleInput(e.target.value) handleInput(e.target.value)
} }
const frontSaveText = ref('')
const changeFrontText = (e: any) => {
// 使 v-modelfrontText.value
const inputValue = e?.target?.value ?? frontText.value
console.log('changeFrontText', inputValue)
frontText.value = inputValue
frontSaveText.value = inputValue
handleInput(inputValue)
//
if (typeId.value == 6 && shapeList.value.length > 0) {
const currentShape = shapeList.value.find((item: any) => item.id === shapeId.value)
if (currentShape && currentShape.axisz == 1) {
frontTextShow(currentShape, true)
}
}
}
const backSaveText = ref('')
const changeBackText = (e: any) => {
// 使 v-modelbackText.value
const inputValue = e?.target?.value ?? backText.value
console.log('changeBackText', inputValue)
backText.value = inputValue
backSaveText.value = inputValue
handleInput(inputValue)
//
if (typeId.value == 6 && shapeList.value.length > 0) {
const currentShape = shapeList.value.find((item: any) => item.id === shapeId.value)
if (currentShape && currentShape.axisz == -1) {
frontTextShow(currentShape, false)
}
}
}
const validateInput = (input: string) => { const validateInput = (input: string) => {
// //
const regex = /^[a-zA-Z0-9\u4e00-\u9fa5\s]+$/; const regex = /^[a-zA-Z0-9\u4e00-\u9fa5\s]+$/;
@ -798,10 +1022,52 @@ const handleInput = (value: string) => {
break; break;
} }
} }
shapeText.value = validValue; if (typeId.value == 2) {
shapeText.value = validValue;
} else {
if (axisz.value == 1) {
frontText.value = validValue;
frontSaveText.value = validValue;
} else {
backText.value = validValue;
backSaveText.value = validValue;
}
}
//
if (typeId.value == 6 && shapeList.value.length > 0) {
const currentShape = shapeList.value.find((item: any) => item.id === shapeId.value)
if (currentShape) {
if (currentShape.axisz == 1) {
frontTextShow(currentShape, true)
} else if (currentShape.axisz == -1) {
frontTextShow(currentShape, false)
}
}
}
return; return;
} }
shapeText.value = value; if (typeId.value == 2) {
shapeText.value = value;
} else {
if (axisz.value == 1) {
frontText.value = value;
frontSaveText.value = value;
} else {
backText.value = value;
backSaveText.value = value;
}
}
//
if (typeId.value == 6 && shapeList.value.length > 0) {
const currentShape = shapeList.value.find((item: any) => item.id === shapeId.value)
if (currentShape) {
if (currentShape.axisz == 1) {
frontTextShow(currentShape, true)
} else if (currentShape.axisz == -1) {
frontTextShow(currentShape, false)
}
}
}
} }
const calculateByteLength = (str: string) => { const calculateByteLength = (str: string) => {
@ -835,9 +1101,28 @@ const shapeChange = (item: any) => {
imageUrl.value = originUrl.value imageUrl.value = originUrl.value
} }
ImageShow(item) ImageShow(item)
if (custom_switch.value == 1) { if (custom_switch.value == 1 && typeId.value == 2) {
textShow(item) textShow(item)
} }
if (custom_switch.value == 1 && typeId.value == 6) {
if (item.axisz == 1) {
//
axisz.value = 1
frontKey.value = 1
frontText.value = frontSaveText.value ? frontSaveText.value : ''
backText.value = backSaveText.value ? backSaveText.value : ''
//
frontTextShow(item, true)
} else if (item.axisz == -1) {
//
axisz.value = -1
frontKey.value = 2
backText.value = backSaveText.value ? backSaveText.value : ''
frontText.value = frontSaveText.value ? frontSaveText.value : ''
//
frontTextShow(item, false)
}
}
} }
const trialCode = ref(false) const trialCode = ref(false)
@ -857,7 +1142,8 @@ const getOrderStat = () => {
console.log('getOrderStat', res) console.log('getOrderStat', res)
orderStat.value = res orderStat.value = res
typeId.value = res.type_id typeId.value = res.type_id
prodId.value = res.prod_id // prodId.value = res.prod_id
badgeTypeId.value = res.type_id // badgeTypeId
getSizeList() getSizeList()
}) })
} }
@ -1446,6 +1732,14 @@ onUnmounted(() => {
justify-content: center; justify-content: center;
margin-top: 10px; margin-top: 10px;
} }
.shape-box-input-box {
display: flex;
align-items: center;
justify-content: center;
margin-top: 10px;
gap: 10px;
flex-direction: column;
}
.shape-box-input-text { .shape-box-input-text {
width: 100%; width: 100%;
height: 40px; height: 40px;
@ -1461,6 +1755,9 @@ onUnmounted(() => {
text-shadow: 1px 0px 1px #000000a1; text-shadow: 1px 0px 1px #000000a1;
white-space: pre-wrap; white-space: pre-wrap;
} }
.font-chinese {
font-family: chinese;
}
.shape-item-image-round { .shape-item-image-round {
border-radius: 50%; border-radius: 50%;
} }

Loading…
Cancel
Save