foreach、mouse event、<hr>、<a>、date()

php的foreach属性

foreach属性用于遍数组中的每一个元素:以下的代码中array表示数组名,key是foreach属性的一个参数,指向当前键值的变量名,非必须。
    <?php foreach($array as $key=>value)
    ?>

鼠标点击事件

1、功能描述:鼠标移入时,背景色由白色(#FAFAFA)变成灰色(#A4A0A0);字体颜色由灰色(#A4A0A0)变成白色(#FAFAFA)
方法:

    .news-item{background-color:#fafafa} //背景色开始为白色
    .news-item-active{background-color:#A4A0A0//鼠标移入时,定义背景色为灰色
    .news-item-active span,.news-item-active div{color:white !important}//定义div中的所有元素span和div的鼠标移入属性:字体颜色为白色且具有优于其他欲定义的属性(若div中包含某些特殊属性如<a href="#"></a>这种有预定义属性的元素,他们的颜色将会有所冲突,导致定义属性失败)

以上是在.html中的 style标签中定义的css样式,调用时用.js语句如下:

    $('.news-item').mouseover(function(){
    $(this).addClass('news-item-active');//鼠标移入时添加事件
     }).mouseout(function(){
    $(this).removeClass('news-item-active');});//鼠标移出时去除事件

定义直线的样式

<hr>可用于定义直线的样式:为其设置“border:1px ridge;”将直线变成虚线

设置链接样式

鼠标放在链接标签上时,不显示下划线,并修改字体颜色为灰色(#A4A0A0):

    .a:hover{text-decoration:none;color:#A4A0A0}

用php语句获得当前时间

显示当前的时间,格式为:年/月/日

    <?=date('y/m/d')?>
<template> <el-table :data="tableData" style="width: 100%"> <el-table-column type="selection" width="55"/> <el-table-column label="产品名称" width="220"> <template #default="scope"> <div class="product-name-wrapper"> <el-link type="primary" :underline="false" @click="goToProductDetail(scope.row.id)"> <span >{{ scope.row.name }}</span> <span style="color: brown;" >※点击进入详细画面</span> </el-link> </div> </template> </el-table-column> <el-table-column property="date" label="产品分类"width="120"/> <el-table-column property="date" label="产品单价"width="120"/> <el-table-column property="date" label="产品名称"width="120"/> <el-table-column property="date" label="产品分类"width="120"/> <el-table-column property="date" label="产品单价"width="120"/> <el-table-column property="date" label="生产日期"width="120"/> <el-table-column property="date" label="单价"width="120"/> <el-table-column property="date" label="库存"width="120"/> <el-table-column property="date" label="购买数量"width="120"/> <el-table-column property="date" label="合计"width="120"/> <el-table-column label="操作" width="180"> <template #default="scope"> <el-button size="small" @click="handleEdit(scope.$index,scope.row)"> 编辑 </el-button> <el-button size="small" type="danger" @click="handleDelete(scope.$index,scope.row)"> 删除 </el-button> </template> </el-table-column> </el-table> </template> <script setup> const router = useRouter(); const goToProductDetail = (productId) => { router.push(`/home/test${productId}`) } const handleEdit = (index, row) => { console.log(index, row) } const handleDelete = (index, row) => { console.log(index, row) } const tableData = [ { date: '2016-05-04', name: 'Aleyna', address: 'Lohrbergstr. 86c, Süd Lilli, Saarland', }, { date: '2016-05-03', name: 'Helen', address: '760 A Street, South Frankfield, Illinois', }, { date: '2016-05-02', name: 'Brandon', address: 'Arnold-Ohletz-Str. 41a, Alt Malinascheid, Thüringen', }, { date: '2016-05-01', name: 'Margie', address: '23618 Windsor Drive, West Ricardoview, Idaho', } ] </script> <style scoped> .aaa-tag { display: inline-block; background-color: #409eff; color: white; font-size: 12px; padding: 0 4px; border-radius: 3px; margin-right: 5px; } </style>   我想在购买数量中加上数字输入框左边加号右边减号
07-10
<template> <div class="dailyAddBox"> <titlepage v-if="pathStr !== '/'" :title="pathName" :query="query" /> <!-- 统计框 --> <div class="stat-box unchecked-box" :style="{ left: uncheckedBoxPosition.x + 'px', top: uncheckedBoxPosition.y + 'px' }" @mousedown="startDrag($event, 'unchecked')" @touchstart="startDrag($event, 'unchecked')"> <div class="stat-content"> <div class="stat-number">{{ uncheckedCount }}</div> <div class="stat-label">未检查</div> </div> </div> <div class="stat-box problem-box" :style="{ left: problemBoxPosition.x + 'px', top: problemBoxPosition.y + 'px' }" @mousedown="startDrag($event, 'problem')" @touchstart="startDrag($event, 'problem')"> <div class="stat-content"> <div class="stat-number">{{ problemCount }}</div> <div class="stat-label">有问题</div> </div> </div> <div class="contentBox"> <div class="selectBox"> <p class="title">同行检查人</p> <a-select :filter-option="filterOption" @change="pairingCheckNameChange" allowClear placeholder="请选择同行检查人" showSearch style="flex:1" size="small" v-model="pairingCheckNameId" > <a-select-option :disabled="checkPer==item.realname" :key="item.id" v-for="item in userList" :value="item.id"> {{item.realname}} </a-select-option> </a-select> </div> <div class="messageBox"> <p class="titleName">检查时间</p> <p class="titleCon">{{ nowTime }}</p> <p class="titleName">项目名称</p> <p class="titleCon">{{ xmmc ? xmmc : "--" }}</p> <p class="titleName">项目地址</p> <p class="titleCon">{{ xmdz ? xmdz : "--" }}</p> </div> <div class="tableBox"> <a-collapse accordion class="firstCollapse"> <a-collapse-panel v-for="(item, i) in fristdata" :key="i"> <template #header> <van-badge style="display: flex; align-items: center; width: 100%;"> <template #content v-if="item.questionStr"> {{ getBadge(item) }} </template> <div style="width: 25%">一级指标</div> <div style="width: 50%">{{ item.name }}</div> <div class="level1-counts"> <div class="count-item unchecked-count"> 未检({{ getLevel1UncheckedCount(item) }}) </div> <div class="count-item problem-count"> 问题({{ getLevel1ProblemCount(item) }}) </div> </div> </van-badge> </template> <a-collapse accordion class="secondCollapse" v-if="item.children != []"> <a-collapse-panel v-for="(item1, i1) in item.children" :key="i1"> <template #header> <van-badge style="display: flex"> <template #content v-if="item1.questionStr"> {{ getBadge(item1) }} </template> <div style="width: 30%">二级指标</div> <div style="width: 65%">{{ item1.name }}</div> </van-badge> </template> <div class="threeDatas"> <div v-if="item1.children != []" v-for="(item,idx) in item1.children" :key="idx" > <!-- <h4 >{{ item.name }}</h4> --> <div style="display: flex; align-items: center; margin-bottom: 8px;"> <a-checkbox v-model="item.checked" @change="(e) => onCheckboxChange(e, item1.children, idx,item1)" style="margin-right: 8px;"></a-checkbox> <span :class="getIndicatorClass(item)" @click="toggleExpanded(item, item1.children, idx)" style="cursor: pointer; padding: 4px 8px; border-radius: 4px; transition: all 0.2s ease;" @mouseenter="$event.target.style.backgroundColor='rgba(0,0,0,0.05)'" @mouseleave="$event.target.style.backgroundColor=''">{{ item.name }}</span> </div> <!-- 使用手风琴效果,只能同时显示一个三级指标的详细内容 --> <div class="hasProblem" v-if="item.isExpanded"> <p class="title">检查内容</p> <p class="text" style="text-align: justify;">{{ item.inspectionContents ? item.inspectionContents.replaceAll("\n","") : ""}}</p> </div> <div class="radioBox" v-if="item.isExpanded"> <van-radio-group v-model="item.radio" @change="onRadioChange"> <van-radio name="3">无问题</van-radio> <van-radio name="0">有问题</van-radio> </van-radio-group> </div> <div class="hasProblem" v-if="item.isExpanded"> <p class="title">详细描述</p> <p class="text"> <a-input type="textarea" v-model="item['problemDescription']" :maxLength="100" placeholder="请输入问题描述" rows="3" /> </p> <p class="title">问题附件</p> <p class="text"> <a-upload accept=".jpg,.png,.jpeg,.heic,.raw,.heif" :multiple="true" :headers="headers" :action="action" :file-list="item['problemAttachment']" @change="(info) => fileChange(info, item)" :beforeUpload="(fi, fil) => beforeUpload(fi, fil, item)"> <a-button> <a-icon type="upload" /> 上传附件 </a-button> </a-upload> </p> <p class="title">整改期限</p> <p class="text"> <a-date-picker v-model="item['zgqx']" style="width: 100%" @change="dateChange($event, item)" /> </p> </div> </div> </div> </a-collapse-panel> </a-collapse> <a-table v-else :pagination="false" :columns="columns" :data-source="item"> <div slot="action" slot-scope="text, record"> <a-radio-group v-model="record.ruleId"> <a-radio :style="radioStyle" :value="radioItem.id" v-for="(radioItem, ri) in record.ruleList" :key="ri">{{ radioItem.name }} </a-radio> </a-radio-group> </div> </a-table> </a-collapse-panel> </a-collapse> </div> </div> <div class="bottonBox"> <span class="botText">检查人:{{ checkPer }} </span> <van-button size="large" type="info" @click="daliyAddFn">提交2</van-button> </div> </div> </template> <script> import moment from 'moment'; import { daliyAdd, getAllItem, getDailyManageList,pairingChexkUserList } from '@/api/dailyManager'; import { getProject2Metrics, } from "@/api/assessment"; export default { data() { return { xmmc: "", xmdz: "", fristdata: [], pairingCheckNameId:undefined, pairingCheckName:undefined, pairingCheckUsername:undefined, userList:[], checkPer: localStorage.getItem('realname'), getAllItemData: [], headers: { 'X-Access-Token': localStorage.getItem('token') }, action: '/hdygwy/sys/common/upload', pathStr: this.$route.path, pathName: this.$route.meta.title ? this.$route.meta.title : '', query: {}, nowTime: moment(new Date()).format('YYYY年MM月DD日 HH:mm:ss'), // 统计框位置 uncheckedBoxPosition: { x: 0, y: 10 }, problemBoxPosition: { x: 0, y: 10 }, // 统计数据 uncheckedCount: 0, problemCount: 0, // 是否正在拖拽 isDragging: false, // 拖拽开始时的鼠标/触摸位置 startX: 0, startY: 0, // 拖拽元素的当前位置 currentX: 0, currentY: 0, // 拖拽元素的初始位置 initialX: 0, initialY: 0, // 拖拽元素的ID draggedElementId: null, // 拖拽元素的类型 (unchecked 或 problem) draggedElementType: null, }; }, mounted() { this.getAllItemFn(); this.getUserList(); this.initDragEvents(); this.initStatisticsBoxes(); // 监听窗口大小变化,重新调整统计框位置 window.addEventListener('resize', this.initStatisticsBoxes); }, beforeDestroy() { // 清理事件监听器 document.removeEventListener('mousemove', this.onDrag); document.removeEventListener('mouseup', this.onDragEnd); document.removeEventListener('touchmove', this.onDrag); document.removeEventListener('touchend', this.onDragEnd); // 清理窗口大小监听器 window.removeEventListener('resize', this.initStatisticsBoxes); }, methods: { filterOption(input, option) { return ( option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0 ); }, pairingCheckNameChange(id){ let data=this.userList.find(tar=>tar.id==id) this.pairingCheckUsername=data.username this.pairingCheckName=data.realname }, getUserList(){ this.userList = []; pairingChexkUserList().then(res=>{ this.userList=res.result }) }, getAllItemFn() { // this.getAllItemData = []; // getDailyManageList().then((res) => { // if (res.success) { // const { result } = res; // result.forEach((item) => { // console.log(item); // const { wylyfl, childrenList } = item; // childrenList.forEach((child) => { // this.getAllItemData.push({ // ...child, // wylyfl, // checked: false, // radio: '0', // zgqx: child.zgqxDate ?? '', // problemAttachment: [], // problemDescription: '' // }); // }); // }); // } // }); const params = { projectId: this.$route.query.projectId, }; this.fristdata = []; getProject2Metrics(params).then((res) => { if (res.success) { // this.spinning = false; const { // result: { list, projectInfo }, } = res; this.xmmc = projectInfo ? projectInfo.xmmc : "--"; this.xmdz = projectInfo ? projectInfo.xmdz : "--"; // 为每个三级指标添加 isExpanded 属性 list.forEach(level1 => { if (level1.children && level1.children.length > 0) { level1.children.forEach(level2 => { if (level2.children && level2.children.length > 0) { level2.children.forEach(level3 => { // 初始化时设置默认值 if (level3.checked === undefined) { level3.checked = false; } // 不设置默认的单选框状态,让用户自己选择 if (level3.radio === undefined) { level3.radio = ''; } if (level3.problemDescription === undefined) { level3.problemDescription = ''; } if (level3.problemAttachment === undefined) { level3.problemAttachment = []; } if (level3.zgqx === undefined) { level3.zgqx = ''; } // 添加展开状态属性 level3.isExpanded = false; }); } }); } }); this.fristdata = [...list]; this.$nextTick(() => { this.getStatistics(); }); } }); }, // daliyAddFn() { // const params = []; // this.getAllItemData.forEach((item) => { // if (item.checked) { // params.push({ // defaultOption: item.jgsx, // jcnr_xxms: item.xxms, // performanceId: item.id, // problemAttachment: item.problemAttachment.map((i) => i.response.message).join(','), // problemDescription: item.problemDescription, // processState: 0, // projectId: this.$route.query.projectId, // radio: item.radio, // zgqx: item.zgqx, // pairingCheckUsername:this.pairingCheckUsername, // pairingCheckName:this.pairingCheckName // }); // const _performanceId = params.at(-1).performanceId; // params.map(item => item.performanceId = _performanceId); // } // }); // daliyAdd(params).then((res) => { // if (res.success) { // this.$message.success(res.message); // // this.$router.back(); // this.$router.push({ // path: '/dailyManagerCheck', // query: { projectId: this.$route.query.projectId } // }); // } // }); // }, daliyAddFn() { const unchecked = this.uncheckedCount; const problem = this.problemCount; if (unchecked === 0 && problem === 0) { this.handleSubmit(); } else { const messageHTML = ` 未检查指标 <span style="color: red;">${unchecked}</span> 条<br> 有问题指标 <span style="color: red;">${problem}</span> 条<br><br> 注:提交后可在【检查记录】中修改 `; this.$dialog.confirm({ title: '检查未完成', message: messageHTML, messageAlign: 'left', confirmButtonText: '提交', cancelButtonText: '取消', confirmButtonColor: '#1989fa', // 蓝色 cancelButtonColor: '#ccc', // 白色 style: { '--van-dialog-confirm-button-height': '25px', '--van-dialog-cancel-button-height': '25px', '--van-dialog-confirm-button-width': '50px', '--van-dialog-cancel-button-width': '50px', '--van-dialog-padding': '20px', '--van-dialog-font-size': '14px', }, dangerouslyUseHTMLString: true, }).then(() => { this.handleSubmit(); }).catch(() => { console.log('用户取消提交'); }); } }, handleSubmit() { const params = []; this.getAllItemData.forEach((item) => { if (item.checked) { params.push({ defaultOption: item.jgsx, jcnr_xxms: item.xxms, performanceId: item.id, problemAttachment: item.problemAttachment.map((i) => i.response.message).join(','), problemDescription: item.problemDescription, processState: 0, projectId: this.$route.query.projectId, radio: item.radio, zgqx: item.zgqx, pairingCheckUsername: this.pairingCheckUsername, pairingCheckName: this.pairingCheckName }); const _performanceId = params.at(-1).performanceId; params.map(item => item.performanceId = _performanceId); } }); daliyAdd(params).then((res) => { if (res.success) { this.$message.success(res.message); this.$router.push({ path: '/dailyManagerCheck', query: { projectId: this.$route.query.projectId } }); } }); }, fileChange(info, item) { // 直接更新当前指标的文件列表 item.problemAttachment = info.fileList; }, beforeUpload(fi, fil, item) { if (fil.length > 9) { if (fi == fil.at(-1)) { this.$message.warning('最多可上传9个文件'); } return Promise.reject(); } else { if (item.problemAttachment.length + fil.length > 9) { if (fi == fil.at(-1)) { this.$message.warning('最多可上传9个文件'); } return Promise.reject(); } return true; } }, dateChange(e, item) { // 日期变化事件,item 是当前的三级指标对象 // 日期值会自动绑定到 item.zgqx,这里不需要额外处理 }, // 获取统计数据 getStatistics() { this.uncheckedCount = 0; this.problemCount = 0; // 遍历所有三级指标计算统计 this.fristdata.forEach(level1 => { if (level1.children && level1.children.length > 0) { level1.children.forEach(level2 => { if (level2.children && level2.children.length > 0) { level2.children.forEach(level3 => { // 重新定义统计逻辑: // 1. 未处理:checked = false 或者 (checked = true 但 radio 没有值) // 2. 已处理且有问题的:checked = true 且 radio = '0' // 3. 已处理且无问题的:checked = true 且 radio = '3' if (!level3.checked || (level3.checked && (level3.radio === undefined || level3.radio === ''))) { // 未处理的指标(包括未选中和已选中但未选择单选框的) this.uncheckedCount++; } else if (level3.checked && level3.radio === '0') { // 已选中且有问题的指标 this.problemCount++; } // 已选中且无问题的指标不计入任何统计 }); } }); } }); console.log('统计更新:', { uncheckedCount: this.uncheckedCount, problemCount: this.problemCount, totalChecked: this.fristdata.reduce((total, level1) => { if (level1.children && level1.children.length > 0) { return total + level1.children.reduce((level2Total, level2) => { if (level2.children && level2.children.length > 0) { return level2Total + level2.children.filter(level3 => level3.checked).length; } return level2Total; }, 0); } return total; }, 0), totalProcessed: this.fristdata.reduce((total, level1) => { if (level1.children && level1.children.length > 0) { return total + level1.children.reduce((level2Total, level2) => { if (level2.children && level2.children.length > 0) { return level2Total + level2.children.filter(level3 => level3.checked && level3.radio !== undefined && level3.radio !== '' ).length; } return level2Total; }, 0); } return total; }, 0) }); }, // 初始化拖拽事件 initDragEvents() { document.addEventListener('mousemove', this.onDrag); document.addEventListener('mouseup', this.onDragEnd); document.addEventListener('touchmove', this.onDrag, { passive: false }); document.addEventListener('touchend', this.onDragEnd); }, // 拖拽事件处理 onDrag(event) { if (!this.isDragging) return; event.preventDefault(); const clientX = event.clientX || (event.touches && event.touches[0].clientX); const clientY = event.clientY || (event.touches && event.touches[0].clientY); const deltaX = clientX - this.startX; const deltaY = clientY - this.startY; const boxWidth = 60; // 统计框宽度 const boxHeight = 60; // 统计框高度 const margin = 20; // 边距 if (this.draggedElementType === 'unchecked') { const newX = this.uncheckedBoxPosition.x + deltaX; const newY = this.uncheckedBoxPosition.y + deltaY; this.uncheckedBoxPosition.x = Math.max(margin, Math.min(window.innerWidth - boxWidth - margin, newX)); this.uncheckedBoxPosition.y = Math.max(margin, Math.min(window.innerHeight - boxHeight - margin, newY)); } else if (this.draggedElementType === 'problem') { const newX = this.problemBoxPosition.x + deltaX; const newY = this.problemBoxPosition.y + deltaY; this.problemBoxPosition.x = Math.max(margin, Math.min(window.innerWidth - boxWidth - margin, newX)); this.problemBoxPosition.y = Math.max(margin, Math.min(window.innerHeight - boxHeight - margin, newY)); } this.startX = clientX; this.startY = clientY; }, // 拖拽结束事件处理 onDragEnd() { this.isDragging = false; this.draggedElementType = null; }, // 开始拖拽 startDrag(event, type) { this.isDragging = true; this.draggedElementType = type; const clientX = event.clientX || (event.touches && event.touches[0].clientX); const clientY = event.clientY || (event.touches && event.touches[0].clientY); this.startX = clientX; this.startY = clientY; }, // 点击指标名称展开/隐藏详情(智能处理复选框状态) toggleExpanded(item, children, parentIndex) { console.log('点击指标名称:', { name: item.name, currentExpanded: item.isExpanded, currentChecked: item.checked }); if (item.isExpanded) { // 如果当前是展开状态,则隐藏 item.isExpanded = false; console.log('隐藏指标:', item.name); } else { // 如果当前是隐藏状态 if (!item.checked) { // 如果复选框未选中,则同时选中复选框 item.checked = true; console.log('自动选中复选框:', item.name); // 注意:这里不立即更新统计,因为只是选中了复选框,没有做任何实际处理 // 统计会在用户选择单选框或填写详情后更新 } else { console.log('复选框已选中,仅展开:', item.name); } // 展开当前指标(同时隐藏其他指标) children.forEach((level3, index) => { if (index !== parentIndex) { level3.isExpanded = false; } else { level3.isExpanded = true; } }); console.log('展开指标:', item.name); } }, // 复选框变化事件 onCheckboxChange(e, children, parentIndex,item1) { console.log(e.target , ';;;;;;;',item1); if (e.target.checked) { // 选中时,只设置展开状态,不自动设置单选框状态 children.forEach((level3, index) => { if (index !== parentIndex) { level3.isExpanded = false; } else { level3.isExpanded = true; } }); } else { // 取消选中时,清空该指标的所有数据 const currentItem = children[parentIndex]; currentItem.isExpanded = false; // 不清空单选框状态,保持用户之前的选择 currentItem.problemDescription = ''; // 清空问题描述 currentItem.problemAttachment = []; // 清空附件 currentItem.zgqx = ''; // 清空整改期限 currentItem.radio = '' // 取消选中时需要更新统计,因为指标回到了未处理状态 this.$nextTick(() => { this.getStatistics(); }); } // 选中时不立即更新统计,因为还没有做任何实际处理 // 统计会在用户选择单选框或填写详情后更新 }, // 单选框变化事件 onRadioChange(value) { console.log('单选框变化:', value); // 立即更新统计,不需要等待 nextTick this.getStatistics(); }, // 获取指标样式类 getIndicatorClass(item) { if (!item.checked) { return 'indicator-normal'; } else if (item.radio === '3') { return 'indicator-no-problem'; } else if (item.radio === '0') { return 'indicator-has-problem'; } return 'indicator-normal'; }, // 初始化统计框位置 initStatisticsBoxes() { this.$nextTick(() => { // 确保统计框不超出屏幕边界 const boxWidth = 60; // 统计框宽度 const boxHeight = 60; // 统计框高度 const margin = 20; // 增加边距,防止超出屏幕 const spacing = 25; // 两个框之间的间距 // 第一个框放在右上角,确保不超出屏幕 this.uncheckedBoxPosition = { x: Math.max(margin, window.innerWidth - boxWidth - margin), y: margin }; // 第二个框放在第一个框下方,增加间距避免重叠 this.problemBoxPosition = { x: Math.max(margin, window.innerWidth - boxWidth - margin), y: margin + boxHeight + spacing }; }); }, // 获取徽章显示内容 getBadge(item) { if (null == item.questionStr) return; if ( item.questionStr && item.questionStr.split(",").includes("1") && item.questionStr.split(",").includes("2") ) { return "存在扣分和未检查"; } else { if (item.questionStr && item.questionStr.split(",").includes("1")) { return "存在扣分项"; } else { return "存在未检查项"; } } }, // 获取一级指标下未处理的三级指标数量 getLevel1UncheckedCount(level1Item) { let count = 0; if (level1Item.children && level1Item.children.length > 0) { level1Item.children.forEach(level2 => { if (level2.children && level2.children.length > 0) { level2.children.forEach(level3 => { // 与主统计逻辑保持一致: // 未处理:checked = false 或者 (checked = true 但 radio 没有值) if (!level3.checked || (level3.checked && (level3.radio === undefined || level3.radio === ''))) { count++; } }); } }); } return count; }, // 获取一级指标下有问题的三级指标数量 getLevel1ProblemCount(level1Item) { let count = 0; if (level1Item.children && level1Item.children.length > 0) { level1Item.children.forEach(level2 => { if (level2.children && level2.children.length > 0) { level2.children.forEach(level3 => { if (level3.checked && level3.radio === '0') { count++; } }); } }); } return count; }, // 获取当前展开的三级指标的索引 getActiveThirdLevel(children) { for (let i = 0; i < children.length; i++) { if (children[i].isExpanded) { return i; } } return -1; // 如果没有展开的,返回-1 } }, watch: { fristdata: { handler() { this.getStatistics(); }, deep: true } }, computed: { // 计算所有三级指标 allThirdLevelIndicators() { const indicators = []; this.fristdata.forEach(level1 => { if (level1.children && level1.children.length > 0) { level1.children.forEach(level2 => { if (level2.children && level2.children.length > 0) { level2.children.forEach(level3 => { indicators.push(level3); }); } }); } }); return indicators; } } }; </script> <style lang="less" scoped> .dailyAddBox { height: 100%; background: #f1f3f3; width: 100%; position: relative; font-size: 16px; .text { font-size: 14px; color: #999; } p { margin: 0; padding: 0; } /deep/ .bottonBox { height: 12vh; background: #fff; width: 100%; overflow: hidden; text-align: center; position: absolute; box-shadow: 0 -2px 10px #ccc; .botText { font-size: 14px; display: block; margin-top: 5px; } .van-button--large { margin: 0 -10px; border-radius: 10px; width: 87%; font-size: 15px; background: #3b77b3; margin-top: 15px; } } /deep/ .contentBox { margin: 10px; padding: 10px; background: #fff; height: calc(100% - 170px); overflow-y: scroll; .selectBox{ display: flex; align-items: center; margin-top: 18px; margin-bottom: 5px; .title{ margin: 0; margin-right: 10px; } } .radioBox { display: flex; margin-bottom: 20px; margin-top: 20px; padding-left: 0.75rem; font-size: .36rem; .van-radio-group { display: flex; .van-radio { margin-right: 20px; .van-radio__label { color: #666; font-weight: 550; } } } } .hasProblem { padding-left: .75rem !important; } .ant-divider-horizontal { margin: 0; } .title { margin: 0; color: #000; margin-top: 18px; margin-bottom: 5px; } .text { margin-bottom: 5px; } } } .messageBox { margin-bottom: 20px; .titleName { font-weight: 550; margin-top: 18px; margin-bottom: 5px; } .titleCon { color: #999; font-size: 14px; border-bottom: 1px solid #ccc; padding-bottom: 5px; } } /deep/ .firstCollapse>.ant-collapse-item>.ant-collapse-header { color: #fff; background: #3b77b3; .van-badge { display: flex !important; align-items: center !important; width: 100% !important; .van-badge__content { margin-right: 8px; } } } /deep/ .secondCollapse>.ant-collapse-item>.ant-collapse-header { color: #000; background: #eee; } /deep/ .thirdCollapse>.ant-collapse-item>.ant-collapse-header { color: #000; background: #fff; } /deep/ .ant-collapse-content>.ant-collapse-content-box { padding: 0 !important; } /deep/ .ant-table .ant-table-row-indent+.ant-table-row-expand-icon { display: none; } .threeDatas { padding: 10px; padding-left: 15px; } /* 一级指标数量提示样式 */ .level1-counts { display: flex; flex-direction: column; align-items: flex-end; margin-left: auto; font-size: 11px; line-height: 1.1; min-width: 60px; .count-item { padding: 1px 4px; border-radius: 3px; margin: 1px 0; white-space: nowrap; text-align: center; font-weight: 500; } .unchecked-count { color: #fff; background-color: rgba(255, 255, 255, 0.25); border: 1px solid rgba(255, 255, 255, 0.3); } .problem-count { color: #fff; background-color: rgba(255, 255, 0, 0.4); border: 1px solid rgba(255, 255, 0, 0.5); } } /* 统计框样式 */ .stat-box { position: fixed; width: 60px; height: 60px; background-color: rgba(255, 255, 255, 0.7); border-radius: 8px; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15); display: flex; flex-direction: column; align-items: center; justify-content: center; cursor: grab; user-select: none; transition: transform 0.2s ease-in-out; z-index: 1000; &:active { cursor: grabbing; transform: scale(1.05); } .stat-content { text-align: center; } .stat-number { font-size: 18px; font-weight: bold; margin-bottom: 3px; } .stat-label { font-size: 10px; color: #666; } } .unchecked-box { background-color: rgba(249, 249, 249, 0.7); color: #999; &:hover { background-color: rgba(240, 247, 255, 0.85); } .stat-number { color: #999; } } .problem-box { background-color: rgba(255, 240, 240, 0.7); color: #ff6b6b; &:hover { background-color: rgba(255, 251, 230, 0.85); } .stat-number { color: #ff4d4f; } } /* 指标颜色样式 */ .indicator-normal { color: #333; } .indicator-no-problem { color: #52c41a; font-weight: 500; } .indicator-has-problem { color: #ff4d4f; font-weight: 500; } </style>点击提交报错dailyManagerAdd.vue:402 Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'success') at eval (dailyManagerAdd.vue:402:1)
最新发布
08-26
<template> <div> <el-dialog :visible.sync="dialogVisible" width="70%" :show-close="false" :close-on-click-modal="false" append-to-body @open="handleOpen" @close="handleClose" > <template slot="title"> <div style="text-align: center; font-size: 22px;"> {{ title }} </div> </template> <el-form :model="detailForm" label-width="130px" v-loading="loading"> <el-row> <el-col :span="8"> <el-form-item label="日期:"> <el-input readonly v-model="detailForm.recordDate"></el-input> </el-form-item> </el-col> <el-col :span="8"> <el-form-item label="班别:"> <el-input readonly v-model="detailForm.workClass"></el-input> </el-form-item> </el-col> </el-row> <el-form-item label="异常机况:"> <el-table :data="eqpList" style="width: 100%" id="eqpTable"> <el-table-column prop="area" label="Area"></el-table-column> <el-table-column prop="eqpId" label="Eqp Id"></el-table-column> <el-table-column prop="eqpName" label="Eqp Name"></el-table-column> <el-table-column prop="eqpStatus" label="Eqp Status"></el-table-column> <el-table-column prop="eqpHour" label="Hour"></el-table-column> <el-table-column prop="eqpUser" label="User"></el-table-column> <el-table-column prop="comments" label="Comment"></el-table-column> </el-table> <el-input type="textarea" v-model="detailForm.abnormal" :autosize="{ minRows: 2 }" placeholder="请输入异常机况 或 选中粘贴图片" @paste="handlePaste($event, abnormalImageRef)" :readonly="!detailForm.editAuth" ></el-input> <el-upload ref="abnormalImageRef" v-model="detailForm.abnormalImageList" action="#" :http-request="handleHttpUpload" list-type="picture-card" :before-upload="beforeUpload" :on-success="() => uploadSuccess('abnormalImageList')" :on-error="uploadError" :accept="fileType.join(',')" :on-preview="handlePreview" :disabled="!detailForm.editAuth" > <i class="el-icon-plus"></i> </el-upload> </el-form-item> <el-form-item label="产片:"> <el-table :data="lotList" style="width: 100%" id="lotTable"> <el-table-column prop="eqp" label="机台"></el-table-column> <el-table-column prop="priority" label="Priority"></el-table-column> <el-table-column prop="lotId" label="Lot ID"></el-table-column> <el-table-column prop="maskTitle" label="Mask Title"></el-table-column> <el-table-column prop="dueDay" label="Due Day"></el-table-column> </el-table> <el-input type="textarea" v-model="detailForm.product" :autosize="{ minRows: 2 }" placeholder="请输入产片 或 选中粘贴图片" @paste="handlePaste($event, productImageRef)" :readonly="!detailForm.editAuth" ></el-input> <el-upload ref="productImageRef" v-model="detailForm.productImageList" action="#" :http-request="handleHttpUpload" list-type="picture-card" :before-upload="beforeUpload" :on-success="() => uploadSuccess('productImageList')" :on-error="uploadError" :accept="fileType.join(',')" :on-preview="handlePreview" :disabled="!detailForm.editAuth" > <i class="el-icon-plus"></i> </el-upload> </el-form-item> <el-form-item label="工程师交接事项:"> <el-input type="textarea" v-model="detailForm.engHandover" :autosize="{ minRows: 2 }" placeholder="请输入工程师交接事项 或 选中粘贴图片" @paste="handlePaste($event, engHandoverImageRef)" :readonly="!detailForm.editAuth" ></el-input> <el-upload ref="engHandoverImageRef" v-model="detailForm.engHandoverImageList" action="#" :http-request="handleHttpUpload" list-type="picture-card" :before-upload="beforeUpload" :on-success="() => uploadSuccess('engHandoverImageList')" :on-error="uploadError" :accept="fileType.join(',')" :on-preview="handlePreview" :disabled="!detailForm.editAuth" > <i class="el-icon-plus"></i> </el-upload> </el-form-item> <el-form-item label="课长:" v-if="detailForm.managerName !== null"> <el-input v-model="detailForm.managerName" readonly></el-input> </el-form-item> <el-form-item label="接班人:" v-if="detailForm.assigneeName !== null"> <el-input type="textarea" v-model="detailForm.assigneeName" readonly autosize></el-input> </el-form-item> </el-form> <template slot="footer"> <el-button type="primary" @click="save" v-if="detailForm.editAuth">保存</el-button> <el-button @click="closeDialog">取消</el-button> <el-button type="primary" @click="submit" v-if="detailForm.submitAuth">提交</el-button> <el-button type="primary" @click="audit" v-if="detailForm.auditAuth">审核</el-button> <el-button type="primary" @click="assign" v-if="detailForm.assignAuth">签核</el-button> </template> </el-dialog> <el-dialog :visible.sync="previewVisible" :show-close="false"> <img width="100%" :src="previewImageUrl" alt="Preview Image"/> </el-dialog> </div> </template> <script> import { getJournalForEdit, saveJournal, submitJournal, auditJournal, assignJournal, clearEditUser } from '@/api/mfgLog/area'; import request from '@/utils/request'; import {Message, MessageBox } from "element-ui"; import dayjs from 'dayjs'; import { getToken } from '@/utils/auth' export default { data() { return { loading: false, dialogVisible: false, title: '光罩厂制造部站点交接记录簿', fileType: ['image/jpeg', 'image/png', 'image/gif'], abnormalImageRef: null, engHandoverImageRef: null, productImageRef: null, previewVisible: false, previewImageUrl: '', detailForm: { recordDate: '', workClass: '', workArea: '', abnormal: '', lotList: [], eqpList: [], abnormalImage: '', abnormalImageList: [], product: '', productImage: '', productImageList: [], engHandover: '', engHandoverImage: '', engHandoverImageList: [], managerName: '', assigneeName: '', editAuth: false, submitAuth: false, auditAuth: false, assignAuth: false, id: '' }, timer: null }; }, mounted() { // 监听事件以重置计时器 window.addEventListener('keydown', this.resetTimer); window.addEventListener('mousemove', this.resetTimer); window.addEventListener('mouseenter', this.resetTimer); // 浏览器关闭事件 window.addEventListener('beforeunload', (e) => { this.userInactive(); }); }, beforeDestroy() { // 清除事件监听和计时器 window.removeEventListener('keydown', this.resetTimer); window.removeEventListener('mousemove', this.resetTimer); window.removeEventListener('mouseenter', this.resetTimer); clearTimeout(this.timer); }, methods: { handleOpen() { this.resetTimer(); }, handleClose() { clearTimeout(this.timer); }, resetTimer() { // 用户进行了操作,重置计时器 if (this.timer) { clearTimeout(this.timer); } this.startTimer(); }, startTimer() { // 设置5分钟后的无操作处理 this.timer = setTimeout(() => { // 用户5分钟内无操作,执行相关逻辑 if (this.dialogVisible) { this.userInactive(); } }, 5 * 60 * 1000); }, userInactive() { // 用户处于非活跃状态的逻辑处理 if (this.detailForm.editAuth) { this.save(); } this.closeDialog(); }, showDialog(row) { this.loading = true; getJournalForEdit(row).then(res => { Object.assign(this.detailForm, res.data); // 显示提示信息 if (!this.detailForm.editAuth && !this.detailForm.assignAuth && this.detailForm.editUser) { Message.warning({ message: "当前日志正在被 " + this.detailForm.editUserName + " 编辑", position: 'top', // 确保消息显示在页面顶部 duration: 5000 // 消息显示时间为 5 秒 }); return 0; } this.detailForm.abnormalImageList = []; if (this.detailForm.abnormalImage?.length > 0) { let abnormalList = this.detailForm.abnormalImage.split(","); for (let index in abnormalList) { this.detailForm.abnormalImageList.push({ url: abnormalList[index] }); } } this.detailForm.productImageList = []; if (this.detailForm.productImage?.length > 0) { let productList = this.detailForm.productImage.split(","); for (let index in productList) { this.detailForm.productImageList.push({ url: productList[index] }); } } this.detailForm.engHandoverImageList = []; if (this.detailForm.engHandoverImage?.length > 0) { let engHandoverList = this.detailForm.engHandoverImage?.split(","); for (let index in engHandoverList) { this.detailForm.engHandoverImageList.push({ url: engHandoverList[index] }); } } if (this.detailForm.lotList && Array.isArray(this.detailForm.lotList)) { this.lotList = this.detailForm.lotList; } else { this.lotList = []; // 否则初始化为空数组 } if (this.detailForm.eqpList && Array.isArray(this.detailForm.eqpList)) { this.eqpList = this.detailForm.eqpList; } else { this.eqpList = []; // 否则初始化为空数组 } this.title = "光罩厂制造部 " + this.detailForm.workArea + " 站点交接记录簿"; // 判断当前时间是否允许提交/审核日志 if (this.detailForm.submitAuth || this.detailForm.auditAuth) { // 白班18点30分之前不允许提交和审核 let authTime = this.detailForm.recordDate + " 18:30:00"; if ('N' == this.detailForm.workClass.substring(0, 1)) { // 晚班06点30分之前不允许提交和审核 authTime = dayjs(this.detailForm.recordDate).add(1, 'day').format("YYYY-MM-DD") + " 06:30:00"; } if (dayjs().isBefore(dayjs(authTime))) { this.detailForm.submitAuth = false; this.detailForm.auditAuth = false; } } // 父系统页面打开遮罩 window.parent.postMessage("open", '*'); this.dialogVisible = true; // 设置初始计时器 this.loading = false; }).catch(error => { console.log(error); this.loading = false; }); }, closeDialog() { clearEditUser({ id: this.detailForm.id }).catch(error => { Message.error(error.msg ? error.msg : error); }); this.$emit('close'); // 父系统页面关闭遮罩 window.parent.postMessage("close", '*'); this.dialogVisible = false; }, save() { this.detailForm.abnormalImage = this.detailForm.abnormalImageList.map(item => item.url).join(","); this.detailForm.productImage = this.detailForm.productImageList.map(item => item.url).join(","); this.detailForm.engHandoverImage = this.detailForm.engHandoverImageList.map(item => item.url).join(","); this.loading = true; saveJournal(this.detailForm).then(res => { this.loading = false; Message.success("保存成功"); this.closeDialog(); }).catch(error => { this.loading = false; }); }, submit() { MessageBox.confirm("确认要提交吗?", "提示", { confirmButtonText: '确认', cancelButtonText: '取消', type: 'warning', }).then(res => { this.detailForm.abnormalImage = this.detailForm.abnormalImageList.map(item => item.url).join(","); this.detailForm.productImage = this.detailForm.productImageList.map(item => item.url).join(","); this.detailForm.engHandoverImage = this.detailForm.engHandoverImageList.map(item => item.url).join(","); this.loading = true; submitJournal(this.detailForm).then(res => { this.loading = false; Message.success("提交成功"); this.closeDialog(); }).catch(error => { this.loading = false; Message.error(error.msg ? error.msg : error); }); }).catch(error => { console.log(error); }); }, audit() { MessageBox.confirm("确认要提交审核吗?", "提示", { confirmButtonText: '确认', cancelButtonText: '取消', type: 'warning', }).then(res => { this.detailForm.abnormalImage = this.detailForm.abnormalImageList.map(item => item.url).join(","); this.detailForm.productImage = this.detailForm.productImageList.map(item => item.url).join(","); this.detailForm.engHandoverImage = this.detailForm.engHandoverImageList.map(item => item.url).join(","); this.detailForm.lotList = this.detailForm.lotList this.detailForm.eqpList = this.detailForm.eqpList this.loading = true; auditJournal(this.detailForm).then(res => { this.loading = false; Message.success("审核成功"); this.closeDialog(); }).catch(error => { this.loading = false; Message.error(error.msg ? error.msg : error); }); }).catch(error => { console.log(error); }); }, assign() { MessageBox.confirm("确认要签核吗?", "提示", { confirmButtonText: '确认', cancelButtonText: '取消', type: 'warning', }).then(res => { this.loading = true; assignJournal({ id: this.detailForm.id }).then(res => { this.loading = false; Message.success("签核成功"); this.closeDialog(); }).catch(error => { this.loading = false; Message.error(error.msg ? error.msg : error); }); }).catch(error => { console.log(error); }); }, handleHttpUpload(options) { return process.env.VUE_APP_BASE_API + '/viewException/uploadImage' }, headers(){ return { "Authorization": 'Bearer ' + getToken() } }, beforeUpload(rawFile) { const imgType = this.fileType.includes(rawFile.type); if (!imgType) { Message.warning({ title: '温馨提示', message: '上传图片不符合所需的格式!', }); } return imgType; }, uploadSuccess(imageListName) { Message.success({ title: '温馨提示', message: '图片上传成功!', }); this.detailForm[imageListName].forEach(item => { if (item.url.indexOf("/api/") < 0) item.url = item.response.url; }); }, uploadError() { Message.error({ title: '温馨提示', message: '图片上传失败,请您重新上传!', }); }, handlePaste(event, uploadRef) { const items = (event.clipboardData || window.clipboardData).items; let file = null; if (!items || items.length === 0) { Message.error("当前浏览器不支持粘贴板"); return; } // 搜索剪切板items for (let i = 0; i < items.length; i++) { if (items[i].type.indexOf("image") !== -1) { file = items[i].getAsFile(); break; } } if (!file) { return; } uploadRef.handleStart(file); // 将粘贴过来的图片加入预上传队列 uploadRef.submit(); // 提交图片上传队列 }, handlePreview(file) { this.previewImageUrl = file.url; this.previewVisible = true; } } }; </script> <style scoped> .layout-padding-custom { padding: 20px; } .border-vxe-table { margin-top: 20px; } </style> 报错vue.runtime.esm.js:620 [Vue warn]: Error in v-on handler: "TypeError: reqs[uid].abort is not a function" found in ---> <ElUploadList> at packages/upload/src/upload-list.vue <ElUpload> at packages/upload/src/index.vue <ElFormItem> at packages/form/src/form-item.vue <ElForm> at packages/form/src/form.vue <ElDialog> at packages/dialog/src/component.vue <Detail> at src/views/mfgLog/area/detail.vue <Index> at src/views/mfgLog/area/index.vue <AppMain> at src/layout/components/AppMain.vue <Layout> at src/layout/index.vue <App> at src/App.vue <Root> warn @ vue.runtime.esm.js:620 logError @ vue.runtime.esm.js:1892 globalHandleError @ vue.runtime.esm.js:1887 handleError @ vue.runtime.esm.js:1847 invokeWithErrorHandling @ vue.runtime.esm.js:1870 invoker @ vue.runtime.esm.js:2187 invokeWithErrorHandling @ vue.runtime.esm.js:1862 Vue.$emit @ vue.runtime.esm.js:3897 click @ element-ui.common.js:28831 invokeWithErrorHandling @ vue.runtime.esm.js:1862 invoker @ vue.runtime.esm.js:2187 original._wrapper @ vue.runtime.esm.js:6951 vue.runtime.esm.js:1896 TypeError: reqs[uid].abort is not a function at VueComponent.abort (element-ui.common.js:29351:21) at VueComponent.abort (element-ui.common.js:29717:34) at doRemove (element-ui.common.js:29688:16) at VueComponent.handleRemove (element-ui.common.js:29695:9) at invokeWithErrorHandling (vue.runtime.esm.js:1862:26) at Proxy.invoker (vue.runtime.esm.js:2187:14) at invokeWithErrorHandling (vue.runtime.esm.js:1862:26) at Vue.$emit (vue.runtime.esm.js:3897:9) at click (element-ui.common.js:28831:37) at invokeWithErrorHandling (vue.runtime.esm.js:1862:26)
08-08
<script setup lang="ts"> import DrnContextmenu from "@/components/DrnEditorCommon/DrnContextmenu/index.vue"; import DrnContextmenuItem from "@/components/DrnEditorCommon/DrnContextmenuItem/index.vue"; import useStore from "@/store"; import { widgetUtil, stringUtil, jsonUtil } from "doran-web-core"; const { parse } = jsonUtil; import { ref } from "vue"; const { useCopyStore: copyStore } = useStore(); const { renderer } = window.drn; const appStore = parent.appStore; const pageStore = parent.pageStore; const widgetStore = parent.widgetStore; const page = ref(); const contextmenuRef = ref(); const selectWidgetParentRef = ref(); const widgetSource = ref(); const PageComponents = ref(); const widgetType = ref(""); const showEventMenu = ref(false); const widgetParentData: any = ref([]); let currentSelectedWidget: any = ref(); const mountStyle = () => { if (parent?.drn.app.styles?.styleGroup) { window.drn.app.styles.styleGroup = parent.drn.app.styles?.styleGroup; window.drn.app.styles.mountAppStyles(document.head); } if (window.drn.page.styles.styleGroup?.length > 0) { window.drn.page.styles.styleGroup = parent.drn.page.styles?.styleGroup; window.drn.page.styles.mountAppStyles(document.head); } }; const updatePage = () => { // 通过为页面添加和移除class来触发页面重绘 page.value = pageStore.openedPage; if (page.value) { page.value.className = page.value?.className ? page.value?.className : []; page.value.className.push(""); page.value.className.pop(); } mountStyle(); }; page.value = pageStore.openedPage; mountStyle(); appStore.$subscribe(() => { updatePage(); }); pageStore.$subscribe(() => { updatePage(); }); widgetStore.$subscribe(() => { updatePage(); }); const insertWidget = (targetData: any, position: string) => { if (widgetSource.value) { pageStore.openedPage?.moveWidget(widgetSource.value, targetData, position); console.log(widgetSource.value, "111"); widgetStore.selectWidget(widgetSource.value); console.log(widgetStore.selectedWidget, "222"); const prevContainer = document.getElementById(widgetSource.value.id); console.log(widgetSource.value, "+1"); console.log(prevContainer, "+2"); if (prevContainer) { setTimeout(() => { addDropAreaEl(prevContainer); }, 500); } } widgetSource.value = null; }; const drop = (ev: any) => { const realTarget = findTarget(ev.target); const targetId = realTarget?.id; const widget = pageStore.openedPage?.getWidget(targetId); const sourceId = ev.dataTransfer.getData("sourceId"); if (sourceId && sourceId.length > 0) { widgetSource.value = pageStore.openedPage?.getWidget(sourceId); } else { const group = ev.dataTransfer.getData("widget-group"); const type = ev.dataTransfer.getData("widget-type"); if (group && group.length > 0 && type && type.length > 0) { widgetSource.value = widgetUtil.cloneWidgetConfig(type); if (widgetSource.value) { widgetSource.value.id = stringUtil.generateId(); } } } widgetParentData.value = pageStore.openedPage.getParentWidgets( pageStore.openedPage, targetId ); selectWidgetParentRef.value?.show(ev, widget); // const realTarget = findTarget(ev.target); // const targetId = realTarget?.id; // const sourceId = ev.dataTransfer.getData("sourceId"); // let source: any = null; // if (sourceId && sourceId.length > 0) { // source = pageStore.openedPage?.getWidget(sourceId); // } else { // const group = ev.dataTransfer.getData("widget-group"); // const type = ev.dataTransfer.getData("widget-type"); // if (group && group.length > 0 && type && type.length > 0) { // source = widgetUtil.cloneWidgetConfig(type); // if (source) { // source.id = stringUtil.generateId(); // } // } // } // if (source) { // pageStore.openedPage?.moveWidget( // source, // pageStore.openedPage?.getWidget(targetId) // ); // } // ev.target.classList.remove("drn-widget-dragover"); // widgetStore.selectWidget(source); ev.stopPropagation(); }; const dragover = (ev: any) => { ev.preventDefault(); }; const dragstart = (ev: any) => { ev.dataTransfer.setData("sourceId", ev.target.id); ev.dataTransfer.setDragImage(document.createElement("span"), 10, 10); ev.stopPropagation(); }; const dragend = (ev: any) => { const targetId = ev.target.id; const source = pageStore.openedPage?.getWidget(targetId); widgetStore.selectWidget(source); ev.target.classList.remove("drn-widget-dragover"); }; const dragenter = (ev: any) => { ev.target.classList.add("drn-widget-dragover"); }; const dragleave = (ev: any) => { ev.target.classList.remove("drn-widget-dragover"); }; const widgetclick = (ev: any) => { selectedWidget(ev); ev.stopPropagation(); }; // 移除拖拽区域 const removeDropAreaEl = (target: any) => { const dropArea = target.querySelector(".drn-widget-drop-box"); if (dropArea) { target.removeChild(dropArea); } target.classList.remove("selected"); }; // 创建拖拽区域 const addDropAreaEl = (target: any) => { console.log("我走到了+3"); const existingDropArea = target.querySelector(".drn-widget-drop-box"); if (existingDropArea) { console.log("我走到了+4"); return; } console.log("我走到了+5"); const drnDropAreaEl = document.createElement("div"); drnDropAreaEl.className = "drn-widget-drop-box"; drnDropAreaEl.id = "drnDropBox"; const dropImg = new URL("@/assets/img/drop.png", import.meta.url).href; const dropEl = document.createElement("img"); dropEl.id = "drn-widget-dragging_image"; dropEl.className = `drn-widget-drop-img-box`; dropEl.src = dropImg; drnDropAreaEl.appendChild(dropEl); console.log("我走到了+6"); target.appendChild(drnDropAreaEl); console.log("我走到了+7"); console.log(target); }; //处理放置条件,已经添加则返回,没有则添加, const addDropArea = (ev: any) => { console.log("我走到了+1"); const targetWidget = ev.currentTarget; if (currentSelectedWidget.value) { removeDropAreaEl(currentSelectedWidget.value); } console.log("我走到了+2"); currentSelectedWidget.value = targetWidget; addDropAreaEl(targetWidget); console.log("我走到了+n"); }; const widgetmouseove = (ev: any) => { ev.target.classList.add("drn-widget-item-hover"); ev.stopPropagation(); }; const widgetmouseout = (ev: any) => { ev.stopPropagation(); ev.target.classList.remove("drn-widget-item-hover"); }; const selectedWidget = (ev: any) => { const widget = pageStore.openedPage?.getWidget(ev.target.id); if (widget) { widgetStore.selectWidget(widget); } }; const contextmenu = (ev: any) => { ev.stopPropagation(); ev.preventDefault(); selectedWidget(ev); const widget = pageStore.openedPage?.getWidget(ev.target.id); widgetParentData.value = pageStore.openedPage.getParentWidgets( pageStore.openedPage, ev.target.id ); if (widget) { widgetType.value = widget?.type; showEventMenu.value = widget.events?.length > 0 ? true : false; if (widget) { contextmenuRef.value?.show(ev, widget); } } }; const structureBaseProps = (el: any) => { const clazzes = ["drn-widget-item"]; if (el._needMask) { clazzes.push("drn-widget-mask"); } if (el._needWrapper) { clazzes.push("drn-widget-warpper"); } if (widgetStore.selectedWidget && widgetStore.selectedWidget.id === el.id) { clazzes.push("drn-widget-item-selected"); const prevContainer = document.getElementById( widgetStore.selectedWidget.id ); console.log(widgetStore.selectedWidget, "+1"); console.log(prevContainer, "+2"); if (prevContainer) { const mockEvent = { currentTarget: prevContainer, stopPropagation: () => {}, preventDefault: () => {}, }; console.log("我走到了"); // addDropArea(mockEvent); } } if (!widgetStore.selectedWidget) { document .querySelectorAll(".drn-widget-drop-box") .forEach((el) => el.remove()); } return { draggable: true, ondragstart: dragstart, ondragend: dragend, ondragenter: dragenter, ondragleave: dragleave, ondrop: drop, ondragover: dragover, oncontextmenu: contextmenu, onclick: widgetclick, onmouseover: widgetmouseove, onmouseout: widgetmouseout, class: clazzes.join(" "), title: `${el.name} [${el.id}]`, }; }; const findTarget = (el: any) => { let currentEl: any = el; while (currentEl && currentEl.classList) { if ( currentEl.classList.contains("drn-widget-item") || currentEl.classList.contains("drn-page-editor") ) { return currentEl; } currentEl = currentEl.parentNode; } }; const getDragImage = () => { let image: any = document.querySelector("#dragging_image"); const draggingImg = new URL("@/assets/img/dragging.png", import.meta.url) .href; if (!image) { image = document.createElement("img"); image.id = "dragging_image"; image.src = draggingImg; image.style = "position:abslute;right:0;bottom:0;z-index:-1;width:0px;"; document.body.append(image); } return image; }; getDragImage(); PageComponents.value = (props: any) => { const { data } = props; return renderer.render(data, structureBaseProps); }; const copyWidget = (widget: any) => { if (widget) { copyStore.copyWidget(widget); } }; const shearWidget = (widget: any) => { if (widget) { pageStore.openedPage.removeWidget(widget.id); copyStore.shearWidget(widget); } }; const pasteWidget = (widget: any) => { if (copyStore.copiedWidgets) { const newWidget = parse(copyStore.copiedWidgets); if (newWidget) { pageStore.openedPage?.moveWidget( newWidget, pageStore.openedPage?.getWidget(widget.id) ); } widgetStore.selectWidget(newWidget); copyStore.pasteWidget(newWidget); } }; const deleteWidget = (widget: any) => { if (widget) { pageStore.openedPage.removeWidget(widget.id); widgetStore.deselectWidget(); } }; const copyWidgetStyles = (widget: any) => { copyStore.copyWidgetStyles(widget); }; const pasteWidgetStyles = (widget: any) => { if (copyStore.copiedWidgetStyle) { pageStore.openedPage?.modifyWidgetStyle( copyStore.copiedWidgetStyle, pageStore.openedPage?.getWidget(widget.id) ); } }; const copyWidgetEvents = (widget: any) => { copyStore.copyWidgetEvents(widget); }; const pasteWidgetEvent = (widget: any) => { if (copyStore.copiedWidgetEvent) { pageStore.openedPage?.modifyWidgetEvent( copyStore.copiedWidgetEvent, pageStore.openedPage?.getWidget(widget.id) ); } }; const selectWidgetEvent = (item: any) => { widgetStore.selectWidget(item); }; const widgetMouseoveEvent = (item: any) => { const prevContainer = document.getElementById(item.id); if (prevContainer) prevContainer.classList.add("drn-widget-item-hover"); }; const widgetMouseoutEvent = (item: any) => { const prevContainer = document.getElementById(item.id); if (prevContainer) prevContainer.classList.remove("drn-widget-item-hover"); }; document.onkeydown = (ev: KeyboardEvent) => { parent.keyBoardEventHandler(ev, 1); }; </script> <template> <PageComponents :data="page" style="padding: 2px"></PageComponents> <drn-contextmenu ref="contextmenuRef"> <template #default="{ data }"> <div class="drn-contextmenu-item-title"> {{ widgetType !== "DrnPage" ? "组件名称:" : "页面名称:" }}{{ data?.name }} </div> <drn-contextmenu-item separator></drn-contextmenu-item> <drn-contextmenu-item v-if="widgetType !== 'DrnPage'" @click="copyWidget(data)" > <template #icon> <drn-icon icon="copy"></drn-icon> </template> 复制 (Ctrl + C) </drn-contextmenu-item> <drn-contextmenu-item v-if="widgetType !== 'DrnPage'" @click="shearWidget(data)" > <template #icon> <drn-icon icon="shear"></drn-icon> </template> 剪切 (Ctrl + X) </drn-contextmenu-item> <drn-contextmenu-item :isAllow="copyStore.copiedWidgets ? true : false" @click="pasteWidget(data)" > <template #icon> <drn-icon icon="paste"></drn-icon> </template> 粘贴 (Ctrl + V) </drn-contextmenu-item> <drn-contextmenu-item v-if="widgetType !== 'DrnPage'" @click="deleteWidget(data)" > <template #icon> <drn-icon icon="trashCan"></drn-icon> </template> 删除 (Ctrl + D) </drn-contextmenu-item> <drn-contextmenu-item separator></drn-contextmenu-item> <drn-contextmenu-item @click="copyWidgetStyles(data)"> <template #icon> <drn-icon icon="copyStyle"></drn-icon> </template> 复制样式 (Ctrl + Shift + C) </drn-contextmenu-item> <drn-contextmenu-item :isAllow="copyStore.copiedWidgetStyle ? true : false" @click="pasteWidgetStyles(data)" > <template #icon> <drn-icon icon="pasteStyle"></drn-icon> </template> 粘贴样式 (Ctrl + Shift + V) </drn-contextmenu-item> <drn-contextmenu-item v-if="showEventMenu" separator ></drn-contextmenu-item> <drn-contextmenu-item v-if="showEventMenu" @click="copyWidgetEvents(data)" > <template #icon> <drn-icon icon="copyEvent"></drn-icon> </template> 复制事件 (Ctrl + Alt + C) </drn-contextmenu-item> <drn-contextmenu-item :isAllow="copyStore.copiedWidgetEvent ? true : false" v-if="showEventMenu" @click="pasteWidgetEvent(data)" > <template #icon> <drn-icon icon="pasteEvent"></drn-icon> </template> 粘贴事件 (Ctrl + Alt + V) </drn-contextmenu-item> <drn-contextmenu-item separator></drn-contextmenu-item> <div class="drn-contextmenu-item-title">父级组件</div> <drn-contextmenu-item separator></drn-contextmenu-item> <div v-if="widgetParentData?.length > 0"> <drn-contextmenu-item v-for="item in widgetParentData" @click="selectWidgetEvent(item)" @mouseove="widgetMouseoveEvent(item)" @mouseout="widgetMouseoutEvent(item)" > {{ item.name }} <span v-if="item.props.general?.proConfig?.uniqueName?.value" >[{{ item.props.general?.proConfig?.uniqueName?.value }}]</span > </drn-contextmenu-item> </div> <div v-else class="drn-widget-empty-box">暂无父级</div> </template> </drn-contextmenu> <drn-contextmenu ref="selectWidgetParentRef"> <template #default="{ data }"> <div class="drn-contextmenu-item-title"> {{ widgetType !== "DrnPage" ? "组件名称:" : "页面名称:" }}{{ data?.name }} </div> <drn-contextmenu-item separator></drn-contextmenu-item> <div class="drn-contextmenu-item-title">父级组件</div> <drn-contextmenu-item separator></drn-contextmenu-item> <div v-if="widgetParentData?.length > 0"> <div v-for="item in widgetParentData"> <drn-contextmenu-item title="中间" @click="insertWidget(item, 'center')" @mouseove="widgetMouseoveEvent(item)" @mouseout="widgetMouseoutEvent(item)" > <div class="drn-parent-item-widget-box"> <div> {{ item.name }} <span v-if="item.props.general?.proConfig?.uniqueName?.value" >[{{ item.props.general?.proConfig?.uniqueName?.value }}]</span > </div> <div class="drn-widget-drop-area-box" v-if="item.type != 'DrnPage'" > <div class="drn-widget-drop-area"> <drn-icon icon="top" title="顶部" class="drn-icon" @click.stop="insertWidget(item, 'top')" /> </div> <div class="drn-widget-drop-area"> <drn-icon icon="bottom" title="底部" class="drn-icon" @click.stop="insertWidget(item, 'bottom')" /> </div> </div> </div> </drn-contextmenu-item> <drn-contextmenu-item separator></drn-contextmenu-item> </div> </div> <div v-else class="drn-widget-empty-box">暂无父级</div> </template> </drn-contextmenu> </template> <style scoped></style> 上述方法中insertWidget点击完成后创建拖拽小图标,为啥打印出来已经创建上了,但是在页面上没有渲染,上述insertWidget拖拽已有的组件后出现的放置位置的方法,帮我分析原因并给出解决方法
07-05
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值