工作中遇到的问题记录

el-upload limit=1时 无法上传多次

        <el-upload :limit="1" :action="importUrl" :before-upload="beforeUpload" :on-success="handleSuccess" :on-error="handleError" :show-file-list="false" accept=".xlsx" ref="uploadRef">
          <el-button type="primary" icon="Upload" style="margin-left: 10px" :loading="uploadLoading">导入算法</el-button>
        </el-upload>

在成功的钩子函数中使用clearFiles(),清空已上传文件

    handleSuccess(response) {
     if (response.code === 0) {
       ElMessage.success("导入成功");
       this.$refs.uploadRef.clearFiles();
       this.getDataList();
     } else {
       this.handleError(response);
     }
     this.uploadLoading = false;
   },

nginx部署时,有两个前端时的打包配置

非主前端的项目,打包需要加上nginx的路径,例如/point
vite.config.js

export default defineConfig({
  base: "/point",
  build: {
    outDir: 'point'  //输出目录
  },
  plugins: [
    vue(),
    // commonjs()
  ],
  resolve: {
    alias: {
      '@': fileURLToPath(new URL('./src', import.meta.url))
    }
  }
})

打包后的静态文件
在这里插入图片描述
方案二:在nginx配置文件中配置两个server

server {
    listen 8080;  # 第一个端口
    server_name localhost;
    
    location / {
        root html/dist;
        try_files $uri $uri/ /index.html;
    }
}

server {
    listen 8081;  # 第二个端口
    server_name localhost;
    
    location / {
        root html/3dview;
        try_files $uri $uri/ /index.html;
    }
}

打开弹窗组件的处理思路 拒绝用emit

弹窗组件init方法:
先调用表单的resetFields方法(去除校验,恢复默认值)
再清空dataForm
如果是编辑再给dataForm赋值
弹窗常用属性:close-on-click-modal=“false” 禁止点击空白关闭

const init = (row: IObject) => {
  visible.value = true;

  // 重置表单数据
  if (dataFormRef.value) {
    dataFormRef.value.resetFields();
  }
  for (const key in dataForm) {
    dataForm[key] = "";
  }

  if (row) {
    Object.assign(dataForm, row);
  }
};

根据坐标点,转换为图像

<!--
  CAD解析结果预览图片
* @Description
* @ReservedFields
-->
<template>
	<el-dialog :title="title" v-model="open" width="40%" append-to-body @close="clearSvg">
		<div class="svgContainer">
			<svg id="mySvg"></svg>
		</div>
	</el-dialog>
</template>

<script setup>
import * as d3 from 'd3'
import { onMounted, ref, getCurrentInstance } from 'vue'
const { proxy } = getCurrentInstance()
const data = ref([])
const open = ref(false)
const title = ref('')
const width = 480
const offset = 10 // 画布的偏移量

const init = () => {
	open.value = true
	proxy.$nextTick(() => {
		drawSvg()
	})
}
const drawSvg = () => {
	// 找到x坐标的最小值和最大值
	const xMin = d3.min(data.value, (d) => d.x)
	const xMax = d3.max(data.value, (d) => d.x)
	// 找到y坐标的最小值和最大值
	const yMin = d3.min(data.value, (d) => d.y)
	const yMax = d3.max(data.value, (d) => d.y)

	// 计算x和y方向的缩放比例
	const xScale = width / (xMax - xMin)
	const yScale = width / (yMax - yMin)

	// 对坐标点进行缩放和偏移适配到合适范围内
	const scaledData = data.value.map((d) => {
		return {
			x: (d.x - xMin) * xScale + offset,
			y: width - (d.y - yMin) * yScale + offset
		}
	})

	const svg = d3.select('#mySvg')
	const polygon = svg
		.append('polygon')
		.attr('points', function () {
			return scaledData.map((d) => `${d.x},${d.y}`).join(' ')
		})
		.attr('fill', 'none')
		.attr('stroke', 'red')
		.attr('stroke-width', 3)
}

const clearSvg = () => {
	const svg = d3.select('#mySvg')
	svg.selectAll('*').remove()
}

defineExpose({
	init,
	data,
	title
})

onMounted(() => {})
</script>

<style lang="scss" scoped>
.svgContainer {
	width: 100%;
	height: 100%;
	text-align: center;
	svg {
		width: 500px;
		height: 500px;
	}
}
</style>

沿svg轨迹运动

使用animateMotion定义沿路径的动画

  <animateMotion dur="30" repeatCount="1" href="#plane" rotate="auto">
    <mpath xlink:href="#myPath" />
  </animateMotion>

让物体中心在轨迹上

<g transform=“translate(-长的一半,-宽的一半)”> 物体的path</g>

使用gsap动画库

<script setup>
import { onMounted, ref } from 'vue'
import { defineComponent, reactive, toRefs } from 'vue'
import { useRoute } from 'vue-router'
const route = useRoute()
let tl = gsap.timeline({ paused: true })
const pathLength = ref(143.16) // 轨迹实际总长为143km
const speed = ref(0) // 每秒传入的速度(km/s)
const currentMileage = ref(0) // 当前小车的里程(km)

const fnArrayString = route.query.fns
const fns = fnArrayString?.split(',')
route.query.length && (pathLength.value = route.query.length)
function toggleAnimation() {
  if (tl.paused()) {
    tl.play()
  } else {
    tl.pause()
  }
}
function updateProgress() {
  if (speed.value === 0) {
    tl.paused()
    console.log('小车停止')
    return
  }
  // 结束动画
  if (currentMileage.value > pathLength.value) {
    currentMileage.value = pathLength.value
    tl.paused()
  }
  const progress = currentMileage.value / pathLength.value
  tl.progress(progress) //更新进度
}
onMounted(() => {
  const path = document.getElementById('myPath')
  const car = document.getElementById('plane')
  const length = path.getTotalLength()
  tl.add('start')
  tl.to('#plane', {
    motionPath: {
      path: '#myPath', //
      align: '#myPath', // 对齐的参照物
      autoRotate: true, //自动旋转角度
      alignOrigin: [0.5, 0.5] // 水平和垂直方向都位于元素的中心
    },
    yoyo: false
  })
  // 初始进度
  tl.progress(0.00001)
  window.ue = {
    ...window.ue,
    interface: {
      ...window.ue.interface
    }
  }
  // 更新速度
  window.ue.interface[fns[0]] = (speed) => {
    speed.value = speed
  }
  //更新里程
  window.ue.interface[fns[1]] = (mileage) => {
    currentMileage.value = mileage
    updateProgress()
  }
})
</script>

el-input 内容换行

boundData.map((item) => `x:${item.x}, y:${item.y}`).join('\n') // 分隔符用\n

批量处理表单

比如要在表格的每一行对表单进行校验

							<el-form
								:model="row"
								label-width="90px"
								label-position="left"
								:rules="rules"
								:ref="
									(el) => {
										formRefs[row.id] = el
									}
								"
							>
							// js
							const formRefs = reactive({})
							const formRef = formRefs[row.id]
							// 分别对每个表单进行表单校验...

iframe通信总结

		<iframe :src="src" frameborder="0" width="100%" height="100%" ref="iframeRef" @load="iframeLoad" @error="handleIframeError"></iframe>

父窗口向嵌入发送信息时,务必等待iframe加载完毕

父传子窗口:dom.contentWindow.postMessage()

let loadFinish = false
const loading = ref(true)
const iframeLoad = () => {
	loadFinish = true
	const iframe = iframeRef.value
	if (iframe && loadFinish) {
		const dataToSend = {
			id: props.task.id,
			trainType: props.task.trainType,
			train: props.task.train,
			url: props.url
		}
		// 此处延迟发送,经测试立马发送子窗口可能收不到
		setTimeout(() => {
			iframe.contentWindow.postMessage(dataToSend, '*')
			loading.value = false
		}, 500)
	}
}

子窗口:window.addEventListener(‘message’,function(e){})

onMounted(() => {
  // 挂载后初始化视图
  initViewer()
  window.addEventListener('message', function (event) {
    const receivedData = event.data
    if (receivedData.id) {
      id.value = receivedData.id
      trainType.value = receivedData.trainType
      train.value = receivedData.train
      url.value = receivedData.url
      queryAutoConvert()
    }
  })
})

相邻兄弟选择器(+)的使用场景

例如 一个列表,除最后一个元素以外,每个元素距离底部20px 作用的是后面一个child

.child + .child {
margin-top:20px;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值