hookehuyr

chore: 迁移TypeScript工具函数至JavaScript并更新配置

- 将PosterBuilder组件的工具函数从TypeScript迁移至JavaScript以简化构建
- 修复ESLint配置,添加root标志防止继承外部规则
- 更新package.json添加lint脚本便于代码检查
- 优化API响应处理函数,增强错误处理和类型安全
- 调整环境配置,将生产环境指向开发服务器
// ESLint 检查 .vue 文件需要单独配置编辑器:
// https://eslint.vuejs.org/user-guide/#editor-integrations
{
"root": true,
"extends": ["taro/vue3"],
"parserOptions": {
"requireConfigFile": false
......
......@@ -26,7 +26,8 @@
"dev:rn": "NODE_ENV=development taro build --type rn --watch",
"dev:qq": "NODE_ENV=development taro build --type qq --watch",
"dev:quickapp": "NODE_ENV=development taro build --type quickapp --watch",
"postinstall": "weapp-tw patch"
"postinstall": "weapp-tw patch",
"lint": "eslint --ext .js,.vue src"
},
"browserslist": [
"last 3 versions",
......
/*
* @Date: 2022-05-18 22:56:08
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2026-01-20 11:47:29
* @LastEditTime: 2026-01-24 12:13:14
* @FilePath: /xyxBooking-weapp/src/api/fn.js
* @Description: 文件描述
*/
......@@ -18,24 +18,24 @@ export const fn = (api) => {
return api
.then(res => {
// 适配 H5 逻辑,code === 1 为成功
if (res.data.code == 1) {
return res.data || true;
} else {
// tslint:disable-next-line: no-console
console.warn('API Error:', res);
if (res.data.show === false) return false;
Taro.showToast({
title: res.data.msg || '请求失败',
icon: 'none',
duration: 2000
});
return res.data || false;
const res_data = res && res.data ? res.data : null
if (res_data && String(res_data.code) === '1') {
return res_data
}
// tslint:disable-next-line: no-console
console.warn('API Error:', res)
if (res_data && res_data.show === false) return res_data
Taro.showToast({
title: (res_data && res_data.msg) ? res_data.msg : '请求失败',
icon: 'none',
duration: 2000
})
return res_data || { code: 0, data: null, msg: '请求失败' }
})
.catch(err => {
// tslint:disable-next-line: no-console
console.error(err);
return false;
return { code: 0, data: null, msg: (err && (err.msg || err.message || err.errMsg)) ? (err.msg || err.message || err.errMsg) : '网络异常' }
})
.finally(() => { // 最终执行
})
......
......@@ -10,14 +10,14 @@
<script>
import Taro from "@tarojs/taro"
import { defineComponent, onMounted, ref } from "vue"
import { drawImage, drawText, drawBlock, drawLine } from "./utils/draw"
import { drawImage, drawText, drawBlock, drawLine } from "./utils/draw.js"
import {
toPx,
toRpx,
getRandomId,
getImageInfo,
getLinearColor,
} from "./utils/tools"
} from "./utils/tools.js"
export default defineComponent({
name: "PosterBuilder",
......
export type DrawType = 'text' | 'image' | 'block' | 'line';
export interface Block {
type?: DrawType;
x: number;
y: number;
width?: number;
height: number;
paddingLeft?: number;
paddingRight?: number;
borderWidth?: number;
borderColor?: string;
backgroundColor?: string;
borderRadius?: number;
borderRadiusGroup?: number[];
text?: Text;
opacity?: number;
zIndex?: number;
}
export interface Text {
type?: DrawType;
x?: number;
y?: number;
text: string | Text[];
fontSize?: number;
color?: string;
opacity?: 1 | 0;
lineHeight?: number;
lineNum?: number;
width?: number;
marginTop?: number;
marginLeft?: number;
marginRight?: number;
textDecoration?: 'line-through' | 'none';
baseLine?: 'top' | 'middle' | 'bottom';
textAlign?: 'left' | 'center' | 'right';
fontFamily?: string;
fontWeight?: string;
fontStyle?: string;
zIndex?: number;
}
export interface Image {
type?: DrawType;
x: number;
y: number;
url: string;
width: number;
height: number;
borderRadius?: number;
borderRadiusGroup?: number[];
borderWidth?: number;
borderColor?: string;
zIndex?: number;
}
export interface Line {
type?: DrawType;
startX: number;
startY: number;
endX: number;
endY: number;
width: number;
color?: string;
zIndex?: number;
}
export type DrawConfig = {
width: number;
height: number;
backgroundColor?: string;
debug?: boolean;
blocks?: Block[];
texts?: Text[];
images?: Image[];
lines?: Line[];
};
import { getLinearColor, getTextX, toPx } from './tools'
const drawRadiusRect = ({ x, y, w, h, r }, { ctx }) => {
const minSize = Math.min(w, h)
if (r > minSize / 2) r = minSize / 2
ctx.beginPath()
ctx.moveTo(x + r, y)
ctx.arcTo(x + w, y, x + w, y + h, r)
ctx.arcTo(x + w, y + h, x, y + h, r)
ctx.arcTo(x, y + h, x, y, r)
ctx.arcTo(x, y, x + w, y, r)
ctx.closePath()
}
const drawRadiusGroupRect = ({ x, y, w, h, g }, { ctx }) => {
const [
borderTopLeftRadius,
borderTopRightRadius,
borderBottomRightRadius,
borderBottomLeftRadius
] = g
ctx.beginPath()
ctx.arc(
x + w - borderBottomRightRadius,
y + h - borderBottomRightRadius,
borderBottomRightRadius,
0,
Math.PI * 0.5
)
ctx.lineTo(x + borderBottomLeftRadius, y + h)
ctx.arc(
x + borderBottomLeftRadius,
y + h - borderBottomLeftRadius,
borderBottomLeftRadius,
Math.PI * 0.5,
Math.PI
)
ctx.lineTo(x, y + borderTopLeftRadius)
ctx.arc(
x + borderTopLeftRadius,
y + borderTopLeftRadius,
borderTopLeftRadius,
Math.PI,
Math.PI * 1.5
)
ctx.lineTo(x + w - borderTopRightRadius, y)
ctx.arc(
x + w - borderTopRightRadius,
y + borderTopRightRadius,
borderTopRightRadius,
Math.PI * 1.5,
Math.PI * 2
)
ctx.lineTo(x + w, y + h - borderBottomRightRadius)
ctx.closePath()
}
const getTextWidth = (text, drawOptions) => {
const { ctx } = drawOptions
let texts = []
if (Object.prototype.toString.call(text) === '[object Object]') {
texts.push(text)
} else {
texts = text
}
let width = 0
texts.forEach(
({
fontSize,
text: textStr,
fontStyle = 'normal',
fontWeight = 'normal',
fontFamily = 'sans-serif',
marginLeft = 0,
marginRight = 0
}) => {
ctx.font = `${fontStyle} ${fontWeight} ${fontSize}px ${fontFamily}`
width += ctx.measureText(textStr).width + marginLeft + marginRight
}
)
return width
}
const drawSingleText = (drawData, drawOptions) => {
const {
x = 0,
y = 0,
text,
color,
width,
fontSize = 28,
baseLine = 'top',
textAlign = 'left',
opacity = 1,
textDecoration = 'none',
lineNum = 1,
lineHeight = 0,
fontWeight = 'normal',
fontStyle = 'normal',
fontFamily = 'sans-serif'
} = drawData
const { ctx } = drawOptions
ctx.save()
ctx.beginPath()
ctx.font = `${fontStyle} ${fontWeight} ${fontSize}px ${fontFamily}`
ctx.globalAlpha = opacity
ctx.fillStyle = color
ctx.textBaseline = baseLine
ctx.textAlign = textAlign
let textWidth = ctx.measureText(text).width
const textArr = []
if (textWidth > width) {
let fillText = ''
let line = 1
for (let i = 0; i <= text.length - 1; i++) {
fillText += text[i]
const nextText = i < text.length - 1 ? fillText + text[i + 1] : fillText
const restWidth = width - ctx.measureText(nextText).width
if (restWidth < 0) {
if (line === lineNum) {
if (
restWidth + ctx.measureText(text[i + 1]).width >
ctx.measureText('...').width
) {
fillText = `${fillText}...`
} else {
fillText = `${fillText.substr(0, fillText.length - 1)}...`
}
textArr.push(fillText)
break
} else {
textArr.push(fillText)
line++
fillText = ''
}
} else if (i === text.length - 1) {
textArr.push(fillText)
}
}
textWidth = width
} else {
textArr.push(text)
}
textArr.forEach((item, index) =>
ctx.fillText(
item,
getTextX(textAlign, x, width),
y + (lineHeight || fontSize) * index
)
)
ctx.restore()
if (textDecoration !== 'none') {
let lineY = y
if (textDecoration === 'line-through') {
lineY = y
}
ctx.save()
ctx.moveTo(x, lineY)
ctx.lineTo(x + textWidth, lineY)
ctx.strokeStyle = color
ctx.stroke()
ctx.restore()
}
return textWidth
}
export function drawText(params, drawOptions) {
const { x = 0, y = 0, text, baseLine } = params
if (Object.prototype.toString.call(text) === '[object Array]') {
const preText = { x, y, baseLine }
text.forEach((item) => {
preText.x += item.marginLeft || 0
const textWidth = drawSingleText(
Object.assign(item, { ...preText, y: y + (item.marginTop || 0) }),
drawOptions
)
preText.x += textWidth + (item.marginRight || 0)
})
} else {
drawSingleText(params, drawOptions)
}
}
export function drawLine(drawData, drawOptions) {
const { startX, startY, endX, endY, color, width } = drawData
const { ctx } = drawOptions
if (!width) return
ctx.save()
ctx.beginPath()
ctx.strokeStyle = color
ctx.lineWidth = width
ctx.moveTo(startX, startY)
ctx.lineTo(endX, endY)
ctx.stroke()
ctx.closePath()
ctx.restore()
}
export function drawBlock(data, drawOptions) {
const {
x,
y,
text,
width = 0,
height,
opacity = 1,
paddingLeft = 0,
paddingRight = 0,
borderWidth,
backgroundColor,
borderColor,
borderRadius = 0,
borderRadiusGroup = null
} = data || {}
const { ctx } = drawOptions
ctx.save()
ctx.globalAlpha = opacity
let blockWidth = 0
let textX = 0
let textY = 0
if (text) {
const textWidth = getTextWidth(
typeof text.text === 'string' ? text : text.text,
drawOptions
)
blockWidth = textWidth > width ? textWidth : width
blockWidth += paddingLeft + paddingLeft
const { textAlign = 'left' } = text
textY = y
textX = x + paddingLeft
if (textAlign === 'center') {
textX = blockWidth / 2 + x
} else if (textAlign === 'right') {
textX = x + blockWidth - paddingRight
}
drawText(Object.assign(text, { x: textX, y: textY }), drawOptions)
} else {
blockWidth = width
}
if (backgroundColor) {
const grd = getLinearColor(ctx, backgroundColor, x, y, blockWidth, height)
ctx.fillStyle = grd
if (borderRadius > 0) {
const drawData = {
x,
y,
w: blockWidth,
h: height,
r: borderRadius
}
drawRadiusRect(drawData, drawOptions)
ctx.fill()
} else if (borderRadiusGroup) {
const drawData = {
x,
y,
w: blockWidth,
h: height,
g: borderRadiusGroup
}
drawRadiusGroupRect(drawData, drawOptions)
ctx.fill()
} else {
ctx.fillRect(x, y, blockWidth, height)
}
}
if (borderWidth && borderRadius > 0) {
ctx.strokeStyle = borderColor
ctx.lineWidth = borderWidth
if (borderRadius > 0) {
const drawData = {
x,
y,
w: blockWidth,
h: height,
r: borderRadius
}
drawRadiusRect(drawData, drawOptions)
ctx.stroke()
} else {
ctx.strokeRect(x, y, blockWidth, height)
}
}
ctx.restore()
}
export const drawImage = (data, drawOptions) =>
new Promise((resolve) => {
const { canvas, ctx } = drawOptions
const {
x,
y,
w,
h,
sx,
sy,
sw,
sh,
imgPath,
borderRadius = 0,
borderWidth = 0,
borderColor,
borderRadiusGroup = null
} = data
ctx.save()
if (borderRadius > 0) {
drawRadiusRect(
{
x,
y,
w,
h,
r: borderRadius
},
drawOptions
)
ctx.clip()
ctx.fill()
const img = canvas.createImage()
img.src = imgPath
img.onload = () => {
ctx.drawImage(img, toPx(sx), toPx(sy), toPx(sw), toPx(sh), x, y, w, h)
if (borderWidth > 0) {
ctx.strokeStyle = borderColor
ctx.lineWidth = borderWidth
ctx.stroke()
}
resolve()
ctx.restore()
}
} else if (borderRadiusGroup) {
drawRadiusGroupRect(
{
x,
y,
w,
h,
g: borderRadiusGroup
},
drawOptions
)
ctx.clip()
ctx.fill()
const img = canvas.createImage()
img.src = imgPath
img.onload = () => {
ctx.drawImage(img, toPx(sx), toPx(sy), toPx(sw), toPx(sh), x, y, w, h)
resolve()
ctx.restore()
}
} else {
const img = canvas.createImage()
img.src = imgPath
img.onload = () => {
ctx.drawImage(img, toPx(sx), toPx(sy), toPx(sw), toPx(sh), x, y, w, h)
resolve()
ctx.restore()
}
}
})
This diff is collapsed. Click to expand it.
import Taro from '@tarojs/taro'
export function randomString(length) {
let str = Math.random().toString(36).substr(2)
if (str.length >= length) {
return str.substr(0, length)
}
str += randomString(length - str.length)
return str
}
export function getRandomId(prefix = 'canvas', length = 10) {
return prefix + randomString(length)
}
export function mapHttpToHttps(rawUrl) {
if (rawUrl.indexOf(':') < 0 || rawUrl.startsWith('http://tmp')) {
return rawUrl
}
const urlComponent = rawUrl.split(':')
if (urlComponent.length === 2) {
if (urlComponent[0] === 'http') {
urlComponent[0] = 'https'
return `${urlComponent[0]}:${urlComponent[1]}`
}
}
return rawUrl
}
export const getFactor = () => {
const sysInfo = Taro.getSystemInfoSync()
const { screenWidth } = sysInfo
return screenWidth / 750
}
export const toPx = (rpx, factor = getFactor()) =>
parseInt(String(rpx * factor), 10)
export const toRpx = (px, factor = getFactor()) =>
parseInt(String(px / factor), 10)
export function downImage(url) {
return new Promise((resolve, reject) => {
const wx_user_data_path =
(typeof wx !== 'undefined' && wx && wx.env && wx.env.USER_DATA_PATH)
? wx.env.USER_DATA_PATH
: ''
const is_local_user_path = wx_user_data_path
? new RegExp(wx_user_data_path).test(url)
: false
if (/^http/.test(url) && !is_local_user_path) {
Taro.downloadFile({
url: mapHttpToHttps(url),
success: (res) => {
if (res.statusCode === 200) {
resolve(res.tempFilePath)
} else {
reject(res)
}
},
fail(err) {
reject(err)
}
})
} else {
resolve(url)
}
})
}
export const getImageInfo = (item, index) =>
new Promise((resolve, reject) => {
const { x, y, width, height, url, zIndex } = item
downImage(url).then((imgPath) =>
Taro.getImageInfo({ src: imgPath })
.then((imgInfo) => {
let sx
let sy
const borderRadius = item.borderRadius || 0
const imgWidth = toRpx(imgInfo.width)
const imgHeight = toRpx(imgInfo.height)
if (imgWidth / imgHeight <= width / height) {
sx = 0
sy = (imgHeight - (imgWidth / width) * height) / 2
} else {
sy = 0
sx = (imgWidth - (imgHeight / height) * width) / 2
}
const result = {
type: 'image',
borderRadius,
borderWidth: item.borderWidth,
borderColor: item.borderColor,
borderRadiusGroup: item.borderRadiusGroup,
zIndex: typeof zIndex !== 'undefined' ? zIndex : index,
imgPath: url,
sx,
sy,
sw: imgWidth - sx * 2,
sh: imgHeight - sy * 2,
x,
y,
w: width,
h: height
}
resolve(result)
})
.catch((err) => {
reject(err)
})
)
})
export function getLinearColor(ctx, color, startX, startY, w, h) {
if (
typeof startX !== 'number' ||
typeof startY !== 'number' ||
typeof w !== 'number' ||
typeof h !== 'number'
) {
return color
}
let grd = color
if (color.includes('linear-gradient')) {
const colorList = color.match(/\((\d+)deg,\s(.+)\s\d+%,\s(.+)\s\d+%/)
const radian = colorList[1]
const color1 = colorList[2]
const color2 = colorList[3]
const L = Math.sqrt(w * w + h * h)
const x = Math.ceil(Math.sin(180 - radian) * L)
const y = Math.ceil(Math.cos(180 - radian) * L)
if (Number(radian) === 180 || Number(radian) === 0) {
if (Number(radian) === 180) {
grd = ctx.createLinearGradient(startX, startY, startX, startY + h)
}
if (Number(radian) === 0) {
grd = ctx.createLinearGradient(startX, startY + h, startX, startY)
}
} else if (radian > 0 && radian < 180) {
grd = ctx.createLinearGradient(startX, startY, x + startX, y + startY)
} else {
throw new Error('只支持0 <= 颜色弧度 <= 180')
}
grd.addColorStop(0, color1)
grd.addColorStop(1, color2)
}
return grd
}
export function getTextX(textAlign, x, width) {
let newX = x
if (textAlign === 'center') {
newX = width / 2 + x
} else if (textAlign === 'right') {
newX = width + x
}
return newX
}
/* eslint-disable prefer-destructuring */
import Taro, { CanvasContext, CanvasGradient } from '@tarojs/taro';
declare const wx: any;
/**
* @description 生成随机字符串
* @param { number } length - 字符串长度
* @returns { string }
*/
export function randomString(length) {
let str = Math.random().toString(36).substr(2);
if (str.length >= length) {
return str.substr(0, length);
}
str += randomString(length - str.length);
return str;
}
/**
* 随机创造一个id
* @param { number } length - 字符串长度
* @returns { string }
*/
export function getRandomId(prefix = 'canvas', length = 10) {
return prefix + randomString(length);
}
/**
* @description 获取最大高度
* @param {} config
* @returns { number }
*/
// export function getHeight (config) {
// const getTextHeight = text => {
// const fontHeight = text.lineHeight || text.fontSize
// let height = 0
// if (text.baseLine === 'top') {
// height = fontHeight
// } else if (text.baseLine === 'middle') {
// height = fontHeight / 2
// } else {
// height = 0
// }
// return height
// }
// const heightArr: number[] = [];
// (config.blocks || []).forEach(item => {
// heightArr.push(item.y + item.height)
// });
// (config.texts || []).forEach(item => {
// let height
// if (Object.prototype.toString.call(item.text) === '[object Array]') {
// item.text.forEach(i => {
// height = getTextHeight({ ...i, baseLine: item.baseLine })
// heightArr.push(item.y + height)
// })
// } else {
// height = getTextHeight(item)
// heightArr.push(item.y + height)
// }
// });
// (config.images || []).forEach(item => {
// heightArr.push(item.y + item.height)
// });
// (config.lines || []).forEach(item => {
// heightArr.push(item.startY)
// heightArr.push(item.endY)
// })
// const sortRes = heightArr.sort((a, b) => b - a)
// let canvasHeight = 0
// if (sortRes.length > 0) {
// canvasHeight = sortRes[0]
// }
// if (config.height < canvasHeight || !config.height) {
// return canvasHeight
// }
// return config.height
// }
/**
* 将http转为https
* @param {String}} rawUrl 图片资源url
* @returns { string }
*/
export function mapHttpToHttps(rawUrl) {
if (rawUrl.indexOf(':') < 0 || rawUrl.startsWith('http://tmp')) {
return rawUrl;
}
const urlComponent = rawUrl.split(':');
if (urlComponent.length === 2) {
if (urlComponent[0] === 'http') {
urlComponent[0] = 'https';
return `${urlComponent[0]}:${urlComponent[1]}`;
}
}
return rawUrl;
}
/**
* 获取 rpx => px 的转换系数
* @returns { number } factor 单位转换系数 1rpx = factor * px
*/
export const getFactor = () => {
const sysInfo = Taro.getSystemInfoSync();
const { screenWidth } = sysInfo;
return screenWidth / 750;
};
/**
* rpx => px 单位转换
* @param { number } rpx - 需要转换的数值
* @param { number } factor - 转化因子
* @returns { number }
*/
export const toPx = (rpx, factor = getFactor()) =>
parseInt(String(rpx * factor), 10);
/**
* px => rpx 单位转换
* @param { number } px - 需要转换的数值
* @param { number } factor - 转化因子
* @returns { number }
*/
export const toRpx = (px, factor = getFactor()) =>
parseInt(String(px / factor), 10);
/**
* 下载图片资源
* @param { string } url
* @returns { Promise }
*/
export function downImage(url) {
return new Promise<string>((resolve, reject) => {
// eslint-disable-next-line no-undef
if (/^http/.test(url) && !new RegExp(wx.env.USER_DATA_PATH).test(url)) {
// wx.env.USER_DATA_PATH 文件系统中的用户目录路径
Taro.downloadFile({
url: mapHttpToHttps(url),
success: (res) => {
if (res.statusCode === 200) {
resolve(res.tempFilePath);
} else {
console.log('下载失败', res);
reject(res);
}
},
fail(err) {
console.log('下载失败了', err);
reject(err);
}
});
} else {
resolve(url); // 支持本地地址
}
});
}
/**
* 下载图片并获取图片信息
* @param {} item 图片参数信息
* @param {} index 图片下标
* @returns { Promise } result 整理后的图片信息
*/
export const getImageInfo = (item, index) =>
new Promise((resolve, reject) => {
const { x, y, width, height, url, zIndex } = item;
downImage(url).then((imgPath) =>
Taro.getImageInfo({ src: imgPath })
.then((imgInfo) => {
// 获取图片信息
// 根据画布的宽高计算出图片绘制的大小,这里会保证图片绘制不变形, 即宽高比不变,截取再拉伸
let sx; // 截图的起点 x 坐标
let sy; // 截图的起点 y 坐标
const borderRadius = item.borderRadius || 0;
const imgWidth = toRpx(imgInfo.width); // 图片真实宽度 单位 px
const imgHeight = toRpx(imgInfo.height); // 图片真实高度 单位 px
// 根据宽高比截取图片
if (imgWidth / imgHeight <= width / height) {
sx = 0;
sy = (imgHeight - (imgWidth / width) * height) / 2;
} else {
sy = 0;
sx = (imgWidth - (imgHeight / height) * width) / 2;
}
// 给 canvas 画图准备参数,详见 ./draw.ts-drawImage
const result = {
type: 'image',
borderRadius,
borderWidth: item.borderWidth,
borderColor: item.borderColor,
borderRadiusGroup: item.borderRadiusGroup,
zIndex: typeof zIndex !== 'undefined' ? zIndex : index,
imgPath: url,
sx,
sy,
sw: imgWidth - sx * 2,
sh: imgHeight - sy * 2,
x,
y,
w: width,
h: height
};
resolve(result);
})
.catch((err) => {
console.log('读取图片信息失败', err);
reject(err);
})
);
});
/**
* 获取线性渐变色
* @param {CanvasContext} ctx canvas 实例对象
* @param {String} color 线性渐变色,如 'linear-gradient(180deg, rgba(255, 255, 255, 0) 0%, #fff 100%)'
* @param {Number} startX 起点 x 坐标
* @param {Number} startY 起点 y 坐标
* @param {Number} w 宽度
* @param {Number} h 高度
* @returns {}
*/
// TODO: 待优化, 支持所有角度,多个颜色的线性渐变
export function getLinearColor(
ctx: CanvasContext,
color,
startX,
startY,
w,
h
) {
if (
typeof startX !== 'number' ||
typeof startY !== 'number' ||
typeof w !== 'number' ||
typeof h !== 'number'
) {
console.warn('坐标或者宽高只支持数字');
return color;
}
let grd: CanvasGradient | string = color;
if (color.includes('linear-gradient')) {
// fillStyle 不支持线性渐变色
const colorList = color.match(/\((\d+)deg,\s(.+)\s\d+%,\s(.+)\s\d+%/);
const radian = colorList[1]; // 渐变弧度(角度)
const color1 = colorList[2];
const color2 = colorList[3];
const L = Math.sqrt(w * w + h * h);
const x = Math.ceil(Math.sin(180 - radian) * L);
const y = Math.ceil(Math.cos(180 - radian) * L);
// 根据弧度和宽高确定渐变色的两个点的坐标
if (Number(radian) === 180 || Number(radian) === 0) {
if (Number(radian) === 180) {
grd = ctx.createLinearGradient(startX, startY, startX, startY + h);
}
if (Number(radian) === 0) {
grd = ctx.createLinearGradient(startX, startY + h, startX, startY);
}
} else if (radian > 0 && radian < 180) {
grd = ctx.createLinearGradient(startX, startY, x + startX, y + startY);
} else {
throw new Error('只支持0 <= 颜色弧度 <= 180');
}
(grd as CanvasGradient).addColorStop(0, color1);
(grd as CanvasGradient).addColorStop(1, color2);
}
return grd;
}
/**
* 根据文字对齐方式设置坐标
* @param {*} imgPath
* @param {*} index
* @returns { Promise }
*/
export function getTextX(textAlign, x, width) {
let newX = x;
if (textAlign === 'center') {
newX = width / 2 + x;
} else if (textAlign === 'right') {
newX = width + x;
}
return newX;
}
/*
* @Date: 2022-09-19 14:11:06
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2026-01-16 17:05:21
* @LastEditTime: 2026-01-24 12:28:14
* @FilePath: /xyxBooking-weapp/src/utils/config.js
* @Description: 文件描述
* @Description: 服务器环境配置
*/
// TAG:服务器环境配置
// const isH5Dev = process.env.TARO_ENV === 'h5' && process.env.NODE_ENV === 'development';
const BASE_URL = process.env.NODE_ENV === 'production'
? 'https://oa.onwall.cn'
// ? 'https://oa-dev.onwall.cn'
// ? 'https://oa.onwall.cn'
? 'https://oa-dev.onwall.cn'
// ?'https://oa.jcedu.org'
: 'https://oa-dev.onwall.cn'
// : 'https://oa.jcedu.org'
;
/**
* 接口默认公共参数(避免在多个文件里硬编码)
* - f:业务模块标识
......
This diff is collapsed. Click to expand it.