支持适配uniapp开发(直接workspace嵌入编译模式)

This commit is contained in:
qiuchengw
2025-12-01 18:29:49 +08:00
parent d0c2dc56e4
commit 427a5f816a
+44 -14
View File
@@ -3,6 +3,15 @@ import { ref, watch, nextTick, onMounted, onUnmounted } from 'vue'
import type { Task } from '../models/classes/Task' import type { Task } from '../models/classes/Task'
import { getPredecessorIds } from '../utils/predecessorUtils' import { getPredecessorIds } from '../utils/predecessorUtils'
// uni-app 类型声明
declare global {
interface Window {
uni?: {
createCanvasContext: (canvasId: string) => CanvasRenderingContext2D & { draw?: () => void }
}
}
}
// 定义 TaskBar 位置信息类型 // 定义 TaskBar 位置信息类型
interface TaskBarPosition { interface TaskBarPosition {
left: number left: number
@@ -65,25 +74,39 @@ const drawLinks = () => {
const canvas = canvasRef.value const canvas = canvasRef.value
if (!canvas) return if (!canvas) return
const ctx = canvas.getContext('2d', { alpha: true }) // 判断是否在 uni-app 环境中
const isUniApp = typeof window !== 'undefined' && window.uni
let ctx: (CanvasRenderingContext2D & { draw?: () => void }) | null = null
if (isUniApp && window.uni) {
// uni-app 环境:使用 uni.createCanvasContext
// https://uniapp.dcloud.net.cn/component/canvas.html
// 这儿存在一个问题:如果一个应用多个gantt视图会存在id冲突问题,所以后期可以加上一个配置,外部传入canvas-id
ctx = window.uni.createCanvasContext('gantt-link-canvas')
} else {
// Web 环境:使用标准 Canvas API
ctx = canvas.getContext('2d', { alpha: true })
}
if (!ctx) { if (!ctx) {
// eslint-disable-next-line no-console // eslint-disable-next-line no-console
console.error('❌ Canvas context 获取失败,可能是尺寸超限') console.error('❌ Canvas context 获取失败,可能是尺寸超限')
return return
} }
// 适配高清屏(Retina
const dpr = window.devicePixelRatio || 1
const displayWidth = props.width const displayWidth = props.width
const displayHeight = props.height const displayHeight = props.height
// 只在尺寸变化时更新 canvas 尺寸 // Web 环境才需要手动处理 DPRuni-app 通过 hidpi 属性自动处理)
const pixelWidth = displayWidth * dpr if (!isUniApp) {
const pixelHeight = displayHeight * dpr const dpr = window.devicePixelRatio || 1
if (canvas.width !== pixelWidth || canvas.height !== pixelHeight) { const pixelWidth = displayWidth * dpr
canvas.width = pixelWidth const pixelHeight = displayHeight * dpr
canvas.height = pixelHeight if (canvas.width !== pixelWidth || canvas.height !== pixelHeight) {
ctx.scale(dpr, dpr) canvas.width = pixelWidth
canvas.height = pixelHeight
ctx.scale(dpr, dpr)
}
} }
// 清空画布(透明) // 清空画布(透明)
@@ -311,6 +334,11 @@ const drawLinks = () => {
// 恢复透明度 // 恢复透明度
ctx.globalAlpha = 1 ctx.globalAlpha = 1
} }
// uni-app 环境需要调用 draw() 方法将绘制内容渲染到画布
if (isUniApp && ctx?.draw) {
ctx.draw()
}
} }
/** /**
@@ -390,7 +418,7 @@ watch(
// 组件挂载后初始化绘制 // 组件挂载后初始化绘制
onMounted(() => { onMounted(() => {
// 监听主题变化 // 监听主题变化
themeObserver = new MutationObserver((mutations) => { themeObserver = new MutationObserver(mutations => {
for (const mutation of mutations) { for (const mutation of mutations) {
if (mutation.attributeName === 'data-theme') { if (mutation.attributeName === 'data-theme') {
updateTheme() updateTheme()
@@ -433,14 +461,16 @@ defineExpose({
<template> <template>
<canvas <canvas
ref="canvasRef" ref="canvasRef"
canvas-id="gantt-link-canvas"
class="gantt-links-canvas" class="gantt-links-canvas"
type="2d"
:hidpi="true"
:style="{ :style="{
position: 'absolute', position: 'absolute',
left: 0, left: `${offsetLeft}px`,
top: 0, top: `${offsetTop}px`,
width: `${width}px`, width: `${width}px`,
height: `${height}px`, height: `${height}px`,
transform: `translate(${offsetLeft}px, ${offsetTop}px)`,
zIndex: highlightedTaskId !== null ? 1001 : 25, zIndex: highlightedTaskId !== null ? 1001 : 25,
pointerEvents: 'none', pointerEvents: 'none',
}" }"