活动介绍

java报错the field Circle.radius is not visible

时间: 2025-08-28 10:21:36 浏览: 4
<think>好的,我现在需要解决用户在Java中遇到的Circle类的radius字段不可见的错误。首先,用户提到访问radius字段时出现可见性问题,这通常是因为字段被声明为private,而用户试图从其他类直接访问它。Java的封装性原则规定,私有字段只能在其所属的类内部访问,外部类需要通过公共的getter和setter方法来访问或修改这些字段。 首先,我应该确认用户是否确实将radius声明为private。如果是的话,直接访问会导致编译错误。解决方法是提供公共的访问方法,比如getRadius()和setRadius()方法。同时,用户可能没有正确生成这些方法,或者在使用时没有调用方法而是直接引用了字段。 另一个可能的情况是,用户可能将radius声明为包级私有(即没有访问修饰符),但在不同包中访问时也会出现问题。这时候需要检查类的包结构和访问修饰符。 此外,用户可能误用了继承,比如子类试图访问父类的私有字段,这也是不允许的。这种情况下,应该使用protected修饰符或者提供公共方法。 最后,如果用户确实需要直接访问字段,可以将radius的访问修饰符改为public,但这违反了封装性原则,不推荐这样做。更好的做法是保持字段私有并通过方法访问。 总结下来,解决方案包括检查字段的访问修饰符,添加getter和setter方法,确保正确调用这些方法,或者调整访问修饰符。同时,需要提醒用户遵循封装性原则,以保持良好的面向对象设计。</think>### Java中Circle类radius字段可见性错误解决方案 当出现"field not visible"错误时,通常是由于访问权限控制导致的。以下是分步解决方案: 1. **检查字段修饰符** ```java public class Circle { private double radius; // 私有字段无法被外部类直接访问 } ``` 此时直接通过`circle.radius`访问会报错,因为private字段只能在类内部访问[^1] 2. **推荐解决方案:添加访问方法** ```java public class Circle { private double radius; // Getter方法 public double getRadius() { return this.radius; } // Setter方法 public void setRadius(double radius) { if(radius > 0) { // 可添加验证逻辑 this.radius = radius; } } } ``` 3. **正确访问方式** ```java Circle myCircle = new Circle(); myCircle.setRadius(5.0); // 通过setter设置值 System.out.println(myCircle.getRadius()); // 通过getter获取值 ``` 4. **其他访问权限说明** - 包级访问(无修饰符):同一包内可见 - protected:子类和同包可见 - public:全局可见(但建议优先使用方法访问) **最佳实践建议**: - 始终遵循封装原则,保持字段私有化 - 通过方法访问字段可实现数据验证和业务逻辑控制 - 使用IDE自动生成getter/setter(Eclipse/IntelliJ都支持Alt+Insert快捷生成)
阅读全文

相关推荐

<template> <el-form ref="baseForm" :model="baseFormCurr" :rules="rules" label-width="105px"> <el-row :gutter="10"> <el-col :lg="8" :md="12" :sm="24" :xl="8" :xs="24"> <el-form-item label="表名称" prop="tableName"> <el-input v-model="baseFormCurr.tableName" autocomplete="off"></el-input> </el-form-item> </el-col> <el-col :lg="8" :md="12" :sm="24" :xl="8" :xs="24"> <el-form-item label="表类型" prop="tableType"> <el-select v-model="baseFormCurr.tableType" :disabled="formState.tableType" placeholder="请选择" style="width: 100%" @change="tableTypeChange"> <el-option v-for="item in dictCurr.table_type" :key="item.dictValue" :label="item.dictName" :value="item.dictValue" ></el-option> </el-select> </el-form-item> </el-col> <el-col :lg="8" :md="12" :sm="24" :xl="8" :xs="24"> <el-form-item label="描述" prop="comments"> <el-input v-model="baseFormCurr.comments" autocomplete="off" maxlength="100" show-word-limit ></el-input> </el-form-item> </el-col> <el-col :lg="8" :md="12" :sm="24" :xl="8" :xs="24"> <el-form-item label="数据库类型" prop="jdbcType"> <el-select ref="jdbcType" v-model="baseFormCurr.jdbcType" :disabled="formState.jdbcType" placeholder="请选择" style="width: 100%" @change="jdbcTypeChange"> <el-option v-for="item in dictCurr.jdbc_type" :key="item.dictValue" :label="item.dictName" :value="item.dictValue" ></el-option> </el-select> </el-form-item> </el-col> <el-col :lg="8" :md="12" :sm="24" :xl="8" :xs="24"> <el-form-item label="备注" prop="remark"> <el-input v-model="baseFormCurr.remark" autocomplete="off" maxlength="120" show-word-limit ></el-input> </el-form-item> </el-col> </el-row> </el-form> <vab-query-form> <vab-query-form-left-panel> <el-button :disabled="!baseFormCurr.jdbcType" icon="el-icon-plus" type="primary" @click="columnHandleAdd"> 添加 </el-button> <el-button icon="el-icon-plus" type="primary" @click="dialogVisible = true"> 常用字段 </el-button> <el-button :disabled="!selectRows.length > 0" icon="el-icon-delete" type="danger" @click="columnHandleDelete" > 删除 </el-button> </vab-query-form-left-panel> </vab-query-form> <el-form ref="tableForm" :model="{'tableForm': tableFormCurr}"> <el-table :data="tableFormCurr" :element-loading-text="elementLoadingText" border @selection-change="setSelectRows" > <el-table-column show-overflow-tooltip type="selection"></el-table-column> <el-table-column align="center" label="拖动" show-overflow-tooltip width="60" > <template v-slot="scope"> <el-button circle class="move-btn" icon="el-icon-d-caret" ></el-button> </template> </el-table-column> <el-table-column label="字段名称" min-width="200" prop="fieldName" show-overflow-tooltip > <template v-slot="scope"> <el-form-item :prop="'tableForm.'+scope.$index+'.fieldName'" :rules="columnRules.fieldName" class="el-form-item-table" > <el-input v-model="scope.row.fieldName" :disabled="scope.row.disabled" style="width: 100%"/> </el-form-item> </template> </el-table-column> <el-table-column label="字段类型" min-width="180" prop="fieldType" show-overflow-tooltip > <template v-slot="scope"> <el-form-item :prop="'tableForm.'+scope.$index+'.fieldType'" :rules="columnRules.fieldType" class="el-form-item-table" > <el-select v-model="scope.row.fieldType" :disabled="scope.row.disabled" default-first-option="" filterable placeholder="请选择" style="width: 100%"> <el-option v-for="item in baseDictData.fieldList" :key="item" :label="item" :value="item" ></el-option> </el-select> </el-form-item> </template> </el-table-column> <el-table-column label="字段长度" min-width="140" prop="fieldLength" show-overflow-tooltip > <template v-slot="scope"> <el-form-item :prop="'tableForm.'+scope.$index+'.fieldLength'" class="el-form-item-table" > <el-input-number v-model="scope.row.fieldLength" :disabled="scope.row.disabled" :max="20000" :min="0" controls-position="right" style="width: 100%" ></el-input-number> </el-form-item> </template> </el-table-column> <el-table-column label="字段精度" min-width="140" prop="fieldPrecision" show-overflow-tooltip > <template v-slot="scope"> <el-form-item :prop="'tableForm.'+scope.$index+'.fieldComments'" class="el-form-item-table" > <el-input-number v-model="scope.row.fieldPrecision" :disabled="scope.row.disabled" :max="100" :min="0" controls-position="right" style="width: 100%" ></el-input-number> </el-form-item> </template> </el-table-column> <el-table-column label="字段描述" min-width="240" prop="fieldComments" show-overflow-tooltip > <template v-slot="scope"> <el-form-item :prop="'tableForm.'+scope.$index+'.fieldComments'" :rules="columnRules.fieldComments" class="el-form-item-table" > <el-input v-model="scope.row.fieldComments" :disabled="scope.row.disabled" maxlength="100" show-word-limit style="width: 100%"/> </el-form-item> </template> </el-table-column> <el-table-column label="主键" min-width="80" prop="izPk" show-overflow-tooltip > <template v-slot="scope"> <el-form-item :prop="'tableForm.'+scope.$index+'.izPk'" class="el-form-item-table" > <el-switch v-model="scope.row.izPk" :active-value="1" :disabled="scope.row.disabled" :inactive-value="0" @change="pKChange(scope.row)" > </el-switch> </el-form-item> </template> </el-table-column> <el-table-column label="非空" min-width="80" prop="izNotNull" show-overflow-tooltip > <template v-slot="scope"> <el-form-item :prop="'tableForm.'+scope.$index+'.izNotNull'" class="el-form-item-table" > <el-switch v-model="scope.row.izNotNull" :active-value="1" :disabled="scope.row.disabled || scope.row.izPk === 1" :inactive-value="0" > </el-switch> </el-form-item> </template> </el-table-column> </el-table> </el-form> <step-footer ref="step-footer" :flag="flag" :info-data="{ obj: this, baseForm: baseFormCurr, tableForm: tableFormCurr }" :max-flag="maxFlag" :min-flag="minFlag" ></step-footer> <el-dialog :before-close="handleClose" :visible.sync="dialogVisible" append-to-body title="选择常见字段" width="30%"> <template v-for="item in BuiltInFields"> <el-checkbox v-model="BuiltInFieldsSelect" :label="item.fieldName" border style="margin: 5px" @change="changeBuiltInFieldsSelect"></el-checkbox> </template> <el-button @click="dialogVisible = false">取 消</el-button> <el-button type="primary" @click="AddDefaultFields">确 定</el-button> </el-dialog> </template> <script> import {isCode, isNull} from "@/utils/validate"; import StepFooter from "./footer/StepFooter.vue" import {deepClone} from "@/utils/clone"; import Sortable from "sortablejs"; import {uuid} from "@/utils"; import {getFieldTypes, getJavaFieldTypesBySafety} from "@/api/generator/tableManagement"; import {isNotNull} from "@/utils/valiargs"; import { useGlobalStore } from '@/pinia/global'; let state = useGlobalStore(); export default { name: "TableDataStep", components: {Sortable, StepFooter}, props: { active: { type: Number, default: () => { return 1; }, }, minFlag: { type: Number, default: () => { return 1; }, }, maxFlag: { type: Number, default: () => { return 1; }, }, baseForm: { type: Object, default: () => { return {}; }, }, tableForm: { type: Array, default: () => { return []; }, }, dict: { type: Object, default: () => { return {}; }, }, baseDictData: { type: Object, default: () => { return { fieldList: [], JavaFieldMap: {}, }; }, } }, data() { const validateTableName = (rule, value, callback) => { if (isNull(value)) { callback(new Error("请输入表名")); } if (!isCode(value)) { callback(new Error("表名只能为字母、数字或下划线")); } else { callback(); } }; const validateName = (rule, value, callback) => { if (!isCode(value)) { callback(new Error("只能为字母、数字或下划线")); } else { callback(); } }; return { BuiltInFieldsSelect: [],//已选中的字段 BuiltInFields: [ { "encryptData": null, "fieldName": "id", "fieldType": "bigint", "fieldLength": 19, "fieldPrecision": 0, "fieldComments": "唯一主键", "izPk": 1, "izNotNull": 1, "izShowList": null, "izShowForm": null, "javaType": "String", "showType": null, "dictTypeCode": null, "sort": 0, "validateType": null, "queryType": null, "disabled": false }, { "encryptData": null, "fieldName": "org_ids", "fieldType": "varchar", "fieldLength": 500, "fieldPrecision": 0, "fieldComments": "父级主键集合", "izPk": 0, "izNotNull": 0, "izShowList": null, "izShowForm": null, "javaType": "String", "showType": null, "dictTypeCode": null, "sort": 1, "validateType": null, "queryType": null, "disabled": false }, { "encryptData": null, "fieldName": "tenant_id", "fieldType": "bigint", "fieldLength": 19, "fieldPrecision": 0, "fieldComments": "多租户ID", "izPk": 0, "izNotNull": 0, "izShowList": null, "izShowForm": null, "javaType": "String", "showType": null, "dictTypeCode": null, "sort": 8, "validateType": null, "queryType": null, "disabled": false }, { "encryptData": null, "fieldName": "create_by", "fieldType": "bigint", "fieldLength": 19, "fieldPrecision": 0, "fieldComments": "创建者", "izPk": 0, "izNotNull": 1, "izShowList": null, "izShowForm": null, "javaType": "String", "showType": null, "dictTypeCode": null, "sort": 10, "validateType": null, "queryType": null, "disabled": false }, { "encryptData": null, "fieldName": "create_time", "fieldType": "datetime", "fieldLength": 0, "fieldPrecision": 0, "fieldComments": "创建时间", "izPk": 0, "izNotNull": 1, "izShowList": null, "izShowForm": null, "javaType": "String", "showType": null, "dictTypeCode": null, "sort": 11, "validateType": null, "queryType": null, "disabled": false }, { "encryptData": null, "fieldName": "update_by", "fieldType": "bigint", "fieldLength": 19, "fieldPrecision": 0, "fieldComments": "修改人", "izPk": 0, "izNotNull": 1, "izShowList": null, "izShowForm": null, "javaType": "String", "showType": null, "dictTypeCode": null, "sort": 12, "validateType": null, "queryType": null, "disabled": false }, { "encryptData": null, "fieldName": "update_time", "fieldType": "datetime", "fieldLength": 0, "fieldPrecision": 0, "fieldComments": "修改时间", "izPk": 0, "izNotNull": 1, "izShowList": null, "izShowForm": null, "javaType": "String", "showType": null, "dictTypeCode": null, "sort": 13, "validateType": null, "queryType": null, "disabled": false }, { "fieldName": "delected", "sort": 8, "izPk": 0, "izNotNull": 1, "izShowList": 0, "izShowForm": 0, "queryType": "", "fieldType": "int", "fieldLength": 1, "fieldPrecision": 0, "fieldComments": "删除", "javaType": "", "validateType": "", "showType": "", "dictTypeCode": "", "disabled": false }, { "fieldName": "version", "sort": 8, "izPk": 0, "izNotNull": 1, "izShowList": 0, "izShowForm": 0, "queryType": "", "fieldType": "int", "fieldLength": 1, "fieldPrecision": 0, "fieldComments": "乐观锁", "javaType": "", "validateType": "", "showType": "", "dictTypeCode": "", "disabled": false } ], dialogVisible: false,//选址内置字段 // 标示 flag: 1, title: "数据库表设置", dictCurr: [], baseFormCurr: {}, tableFormCurr: [], formState: { jdbcType: false, tableType: false, }, rules: { tableName: [ {required: true, trigger: "blur", validator: validateTableName}, ], tableType: [ {required: true, trigger: "change", message: "请选择表类型"}, ], jdbcType: [ {required: true, trigger: "change", message: "请选择数据库类型"}, ], comments: [ {required: true, trigger: "blur", message: "请输入描述"}, ], }, treeName: "parent_id", // 新增字段模版 columnFormTemp: { id: "", sort: 0, izPk: 0, izNotNull: 0, izShowList: 0, izShowForm: 0, queryType: "", fieldName: "", fieldType: "", fieldLength: 0, fieldPrecision: 0, fieldComments: "", javaType: "", validateType: "", showType: "", dictTypeCode: "", disabled: false, }, columnRules: { fieldName: [ {required: true, message: "请选择字段名称", trigger: "blur"}, {required: true, trigger: "blur", validator: validateName}, ], fieldType: [ {required: true, message: "请选择字段类型", trigger: "change"}, ], fieldComments: [ {required: true, message: "请输入字段描述", trigger: "blur"}, ] }, layout: "total, sizes, prev, pager, next, jumper", selectRows: "", elementLoadingText: "正在加载...", }; }, created() { // 告诉父节点 自己的 flag 编号 this.$emit("inform-flag", this.flag, this.title); }, mounted() { // 拷贝 props this.baseFormCurr = deepClone(this.baseForm); this.tableFormCurr = deepClone(this.tableForm); this.dictCurr = deepClone(this.dict); // 数据库字段类型 // this.dictCurr.field_type = this.$getDictList(this.baseFormCurr.jdbcType + "_data_type"); // 改成自己项目的字典项获取方式 // this.dict = state.sysDict; // this.dictCurr.field_type = state.sysDict.table_type; let dataType = this.baseFormCurr.jdbcType + "_data_type"; // JavaScript 对象支持两种属性访问方式:1点符号:object.propertyName ,适用于静态属性名。 2方括号符号:object[propertyName] ,适用于动态属性名,propertyName 可以是一个变量或表达式。 this.dictCurr.field_type = state.sysDict[dataType]; // 表拖动 this.rowDrop(); // 初始化数据 this.doGetFieldData(); }, watch: { baseForm(newV, oldV) { this.baseFormCurr = deepClone(newV); }, tableForm(newV, oldV) { this.tableFormCurr = deepClone(newV); }, dict(newV, oldV) { this.dictCurr = deepClone(newV); // 数据库字段类型 // this.dictCurr.field_type = this.$getDictList(this.baseFormCurr.jdbcType + "_data_type"); // 改成自己项目的字典项获取方式 // this.dict = state.sysDict; // this.dictCurr.field_type = state.sysDict.table_type; let dataType = this.baseFormCurr.jdbcType + "_data_type"; // JavaScript 对象支持两种属性访问方式:1点符号:object.propertyName ,适用于静态属性名。 2方括号符号:object[propertyName] ,适用于动态属性名,propertyName 可以是一个变量或表达式。 this.dictCurr.field_type = state.sysDict[dataType]; }, }, methods: { handleClose() { this.dialogVisible = false }, changeBuiltInFieldsSelect(e) { this.BuiltInFieldsSelect = this.removeElementsFromArray(this.BuiltInFieldsSelect, this.tableFormCurr) }, removeElementsFromArray(A, B) { A = A.filter(a => { let isEqual = B.some(b => b.fieldName === a); if (isEqual) { this.$message.error(已存在字段:${a}) } return !isEqual; }); return A; }, //添加默认字段 AddDefaultFields(params) { console.log(this.BuiltInFieldsSelect) for (const param of this.BuiltInFieldsSelect) { this.AddDefaultFields2(param) } this.dialogVisible = false }, //方法2 AddDefaultFields2(title) { let temp = null for (const tempElement of this.BuiltInFields) { if (tempElement.fieldName == title) { temp = tempElement } } this.tableFormCurr.push(temp); }, // 数据库类型发生改动 jdbcTypeChange(newValue) { const _this = this; this.tableFormCurr.jdbcType = this.$refs.jdbcType.value; this.$baseConfirm("更换数据库类型将会清空当前已设字段,你确定要更换吗", null, () => { // 改为新值 _this.tableFormCurr.jdbcType = newValue; // 加载字典 // _this.dictCurr.field_type = _this.$getDictList(_this.baseFormCurr.jdbcType + "_data_type"); // 改成自己项目的字典项获取方式 // this.dict = state.sysDict; // this.dictCurr.field_type = state.sysDict.table_type; let dataType = this.baseFormCurr.jdbcType + "_data_type"; // JavaScript 对象支持两种属性访问方式:1点符号:object.propertyName ,适用于静态属性名。 2方括号符号:object[propertyName] ,适用于动态属性名,propertyName 可以是一个变量或表达式。 this.dictCurr.field_type = state.sysDict[dataType]; // 清空已有字段数据 _this.tableFormCurr = []; // 初始化数据 this.doGetFieldData(); }); }, // 表类型发生改动 tableTypeChange(newValue) { if (newValue === '0') { // 删除 parent_id 字段 for (let i = this.tableFormCurr.length - 1; i >= 0; i--) { let item = this.tableFormCurr[i]; if (item.fieldName === this.treeName) { this.tableFormCurr.splice(i, 1); break; } } } else if (newValue === '1') { // 删除 parent_id 字段 for (let i = this.tableFormCurr.length - 1; i >= 0; i--) { let item = this.tableFormCurr[i]; if (item.fieldName === this.treeName) { this.tableFormCurr.splice(i, 1); break; } } // 增加 parent_id 字段 let tmp = deepClone(this.columnFormTemp); tmp.disabled = true; tmp.fieldName = this.treeName; tmp.fieldType = "bigint"; tmp.fieldLength = 20; tmp.fieldComments = "上级ID"; tmp.javaType = "Integer"; tmp.izNotNull = 1; this.columnHandleAdd(tmp); } }, // 主键改动 pKChange(el) { if (!isNull(el)) { // 如果主键选中 则默认选中不可为空 if (el.izPk === 1) { el.izNotNull = 1; } else { el.izNotNull = 0; } } }, // ============================== async doGetFieldData() { this.$emit("loading"); // 通知父级 锁定当前表 this.$emit("inform-data", { fieldList: await this.doGetFieldTypes(), JavaFieldMap: await this.doGetJavaFieldTypesBySafety(), }); this.$emit("unLoading"); }, // 获得 数据类型 async doGetFieldTypes() { // const { data } = await getFieldTypes(); // 改成自己项目的数据返回格式 const res = await getFieldTypes(); const data = res.result.opsliData.data; if (isNotNull(data)) { return data; } return null; }, // 获得 Java 类型 (安全兜底模式) async doGetJavaFieldTypesBySafety() { // const { data } = await getJavaFieldTypesBySafety(); // 改成自己项目的数据返回格式 const res = await getJavaFieldTypesBySafety(); const data = res.result.opsliData.data; if (isNotNull(data)) { return data; } return null; }, // 行添加 columnHandleAdd(params) { let temp; if (!isNull(params) && !(params instanceof MouseEvent)) { temp = params; } else { temp = deepClone(this.columnFormTemp); } temp.id = "temp_" + uuid() if (this.tableFormCurr == null || this.tableFormCurr.length === 0) { temp.sort = 0; } else { temp.sort = this.tableFormCurr.length; } this.tableFormCurr.push(temp); }, // 行删除 columnHandleDelete(row) { if (row.id) { this.$baseConfirm("你确定要删除当前字段吗", null, () => { for (let i = this.tableFormCurr.length - 1; i >= 0; i--) { let item = this.tableFormCurr[i]; if (item.id === row.id) { // 树装接口 不允许删除 parent_id 字段 if (this.tableFormCurr.tableType === '1') { if (item.fieldName !== this.treeName) { this.tableFormCurr.splice(i, 1); } } else { this.tableFormCurr.splice(i, 1); } break; } } }); } else if (this.selectRows.length > 0) { const ids = this.selectRows.map((item) => item.id); this.$baseConfirm("你确定要删除当前字段吗", null, () => { for (let i = this.tableFormCurr.length - 1; i >= 0; i--) { let item = this.tableFormCurr[i]; if (ids.indexOf(item.id) !== -1) { // 树装接口 不允许删除 parent_id 字段 if (this.tableFormCurr.tableType === '1') { if (item.fieldName !== this.treeName) { this.tableFormCurr.splice(i, 1); } } else { this.tableFormCurr.splice(i, 1); } } } }); } else { this.$baseMessage("未选中任何行", "error"); return false; } }, // 行选中 setSelectRows(val) { this.selectRows = val; }, //行拖拽 rowDrop() { const tbody = this.$refs["tableForm"].$el .querySelector(".el-table__body-wrapper tbody"); const _this = this Sortable.create(tbody, { // 只能纵向拖动 axis: "y", // 限制触发事件只能某个元素可以触发 handle: ".move-btn", // 如果设置成true,则被拖拽的元素在返回新位置时,会有一个动画效果。 revert: true, // 如果设置成true,则元素被拖动到页面边缘时,会自动滚动。 scroll: true, onEnd({oldIndex, newIndex}) { _this.tableFormCurr[oldIndex].sort = newIndex; // 如果是 从后往前 移动 则 当前项改为newIndex 而 原newIndex 往后的所有内容全部向后顺产移动 if (oldIndex > newIndex) { for (let i = oldIndex; i > newIndex; i--) { _this.tableFormCurr[i - 1].sort = i; } } // 如果是 从前往后 移动 则 当前项改为newIndex 而 原newIndex 往后的所有内容全部向前顺产移动 else { for (let i = oldIndex; i < newIndex; i++) { _this.tableFormCurr[i + 1].sort = i; } } } }) }, }, }; </script> 这段代码是一个vue文件, 代码语法的框架是element-ui, 版本是2.15.13。我的前端项目vue版本是3.4.21, 框架ant-design-vue版本是4.2.1。现在的问题是文件内容和项目框架语法不一样, 请帮我把整个文件的代码内容修改成适配我项目框架的语法(注意:我的前端项目vue版本是3.4.21, 框架ant-design-vue版本是4.2.1,必须生成对应版本的语法)。 不要删除里边已经注释的代码, 即使有相同的代码, 你也不要省略代码, 把所有内容全部输出来, 需要保持原有的布局样式而调整转换代码。如果这个文件引入的别的文件, 不用你关心别的文件, 你不要给我生成别的文件内容, 最后生成一个vue文件给我, 如果输出内容过长而被终止截断了,请接着输出剩余的部分。转换后要求代码不报错, 按钮方法和底部方法名称要对应起来, 转换过程中不要遗漏代码, 注意:如果之前代码有$baseConfirm, 给我替换成Modal.confirm , 并且引入import { message, Modal } from “ant-design-vue”; 如果之前代码有$baseMessage, 给我替换成message.success或message.warning或message.error。 你好好思考分析下我的需求,不是将把Element UI组件替换为Ant Design Vue组件,你考虑转换后的版本了吗,不同版本语法api不一样,否则转换后的代码根本不能用。不要给我进行简化处理,方法内容不要给我留空,不要等着我补充,你都给我转换处理好。

showDevicesOnMap(devices) { // 存储当前设备列表,用于后续更新状态 this.currentDevices = devices; // 清除旧图层和事件监听 this.removeExistingLayers(); // 创建GeoJSON数据源(确保每个特征有唯一ID) const geojson = { type: "FeatureCollection", features: devices.map((device, index) => ({ type: "Feature", id: device.channelId, // 确保id唯一 geometry: { type: "Point", coordinates: [device.longitude, device.latitude], }, properties: { ...device, index: index + 1, // isSelected: this.selectedDeviceIds.has(device.channelId), }, })), }; // 添加数据源 this.mapObj.addSource("devices-source", { type: "geojson", data: geojson, generateId: true, // 如果特征本身没有id,则生成一个 }); // 预加载图标 const loadPromises = [ this.loadImageSafe("jk_online", "/images/jk_online.png"), this.loadImageSafe("jk_unline", "/images/jk_unline.png"), ]; // 加载图标并添加图层 Promise.all(loadPromises) .then(() => { // // 添加设备图标层 this.mapObj.addLayer({ id: "devices-layer", type: "symbol", source: "devices-source", interactive: true, // 显式启用交互 layout: { "icon-image": [ "case", ["==", ["get", "online"], true], "jk_online", "jk_unline", ], "icon-size": [ "interpolate", ["linear"], ["zoom"], 10, 0.5, // 当缩放级别为10时,大小为0.5 22, 1.0, // 当缩放级别为22时,大小为1.0 ], "icon-anchor": "bottom", "icon-allow-overlap": true, // 防止图标被隐藏 }, }); // 添加序号背景层(圆形) this.mapObj.addLayer({ id: "label-backgrounds", type: "circle", source: "devices-source", paint: { "circle-radius": 10, "circle-color": [ "case", ["==", ["feature-state", "isSelected"], true], "#FF6666", "#45CCDA", ], "circle-stroke-color": "#fff", "circle-translate": [0, -28], // 向上平移,与图标位置配合 }, }); // 添加序号文本层 this.mapObj.addLayer({ id: "device-labels", type: "symbol", source: "devices-source", layout: { "text-field": ["get", "index"], "text-size": 12, "text-offset": [0, -2.4], // 调整位置到背景圆中心 "text-anchor": "center", "text-allow-overlap": true, }, paint: { "text-color": "#FFFFFF", "text-halo-color": "rgba(0, 0, 0, 0.5)", "text-halo-width": 1, }, }); // 设置初始特征状态 devices.forEach((device) => { this.mapObj.setFeatureState( { source: "devices-source", id: device.channelId }, { isSelected: this.selectedDeviceIds.has(device.channelId) } ); }); // 设置初始特征状态 this.updateFeatureStates(); // 点击事件处理 this.mapObj.off("click"); // 移除旧的监听器,避免重复绑定 this.mapObj.on("click", (e) => { const features = this.mapObj.queryRenderedFeatures(e.point, { layers: ["devices-layer"] }); if (features.length > 0) { console.log(features, '0000000000'); this.toggleDeviceSelection(features[0].properties.channelId); } }); }) .catch((error) => { console.error("图层添加失败:", error); }); }, // 选中 toggleDeviceSelection(deviceId) { console.log(deviceId, '11111111111'); // 更新选中状态 const newSelectedId = this.selectedDeviceId === deviceId ? null : deviceId; this.selectedDeviceId = newSelectedId; console.log(newSelectedId, '2222222'); // 更新所有特征的状态 // 使用Set实现多选切换 const newSelectedIds = new Set(this.selectedDeviceIds); if (newSelectedIds.has(deviceId)) { newSelectedIds.delete(deviceId); // 如果已选中,则取消 } else { newSelectedIds.add(deviceId); // 否则选中 } this.selectedDeviceIds = newSelectedIds; // 更新地图上所有特征的状态 this.updateFeatureStates(); // 立即更新特征状态 this.mapObj.setFeatureState( { source: 'devices-source', id: deviceId }, { isSelected: this.selectedDeviceIds.has(deviceId) } ); // 通知父组件 this.$emit("device-selected", newSelectedId, deviceId); }, // 更新所有特征状态 updateFeatureStates() { console.log('5555555555'); const source = this.mapObj.getSource("devices-source"); if (!source) return; // 使用设备列表而非遍历特征 this.currentDevices.forEach(device => { const isSelected = this.selectedDeviceIds.has(device.channelId); this.mapObj.setFeatureState( { source: "devices-source", id: device.channelId }, { isSelected } ); }); },选中更新的时候,有isSelected数据为true,页面不更新背景色

Loading image: jk_online from /images/jk_online.png index.vue?./node_modules/babel-loader/lib/index.js!./node_modules/vue-loader/lib/index.js??vue-loader-options:657 Image jk_online already exists. index.vue?./node_modules/babel-loader/lib/index.js!./node_modules/vue-loader/lib/index.js??vue-loader-options:654 Loading image: jk_unline from /images/jk_unline.png index.vue?./node_modules/babel-loader/lib/index.js!./node_modules/vue-loader/lib/index.js??vue-loader-options:657 Image jk_unline already exists. index.vue?./node_modules/babel-loader/lib/index.js!./node_modules/vue-loader/lib/index.js??vue-loader-options:648 当前地图样式中的图片: undefined index.vue?./node_modules/babel-loader/lib/index.js!./node_modules/vue-loader/lib/index.js??vue-loader-options:649 设备源是否存在: i {id: 'devices-source', _isLatLon: true, type: 'geojson', minzoom: 0, maxzoom: 18, …}actor: ec {…}id: "devices-source"isTileClipped: trueload: ƒ ()map: n {…}maxzoom: 18minzoom: 0promoteId: undefinedreparseOverscaled: trueserialize: ƒ ()tileSize: 512type: "geojson"workerOptions: {source: 'devices-source', cluster: false, geojsonVtOptions: {…}, superclusterOptions: {…}, clusterProperties: undefined}_collectResourceTiming: undefined_data: {type: 'FeatureCollection', features: Array(2)}_eventedParent: i {id: 'devices-source', dispatcher: e, _isLatLon: true, _listeners: {…}, _source: i, …}_eventedParentData: undefined_iconMap: []_isLatLon: true_loaded: true_options: {type: 'geojson', data: {…}, generateId: true}_removed: false_resourceTiming: [][[Prototype]]: ct index.vue?./node_modules/babel-loader/lib/index.js!./node_modules/vue-loader/lib/index.js??vue-loader-options:662 查询到的周边设备: (2) [{…}, {…}] index.vue?./node_modules/babel-loader/lib/index.js!./node_modules/vue-loader/lib/index.js??vue-loader-options:557 图标访问路径: http://localhost:8080/images/jk_online.png index.vue?./node_modules/babel-loader/lib/index.js!./node_modules/vue-loader/lib/index.js??vue-loader-options:570 调试层已添加 showDevicesOnMap(devices) { // 清除旧图层(确保移除所有相关图层) const layersToRemove = [ "devices-layer", "device-labels", "label-backgrounds", "selection-layer", ]; layersToRemove.forEach((layerId) => { if (this.mapObj.getLayer(layerId)) this.mapObj.removeLayer(layerId); }); if (this.mapObj.getSource("devices-source")) { this.mapObj.removeSource("devices-source"); } // 创建GeoJSON数据源(确保每个特征有唯一ID) const geojson = { type: "FeatureCollection", features: devices.map((device, index) => ({ type: "Feature", id: device.id, // 确保id唯一 geometry: { type: "Point", coordinates: [device.longitude, device.latitude], }, properties: { ...device, index: index + 1, isSelected: this.selectedDeviceId === device.id, }, })), }; // 添加数据源 this.mapObj.addSource("devices-source", { type: "geojson", data: geojson, generateId: true, // 如果特征本身没有id,则生成一个 }); // 预加载图标 const loadPromises = [ this.loadImageSafe("jk_online", "/images/jk_online.png"), this.loadImageSafe("jk_unline", "/images/jk_unline.png"), ]; // 加载图标并添加图层 Promise.all(loadPromises) .then(() => { // 检查图标路径是否正确(使用绝对路径) const iconBaseUrl = window.location.origin + "/images/"; console.log("图标访问路径:", iconBaseUrl + "jk_online.png"); // 在设备图层前添加调试层 if (!this.mapObj.getLayer("debug-layer")) { this.mapObj.addLayer({ id: "debug-layer", type: "circle", source: "devices-source", paint: { "circle-radius": 5, "circle-color": "#FF0000", "circle-opacity": 0.8 } }); console.log("调试层已添加"); } // 添加设备图标层 if (!this.mapObj.getLayer("devices-layer")) { this.mapObj.addLayer({ id: "devices-layer", type: "symbol", source: "devices-source", layout: { "icon-image": [ "case", ["==", ["get", "online"], true], "jk_online", "jk_unline", ], "icon-size": 0.8, "icon-anchor": "bottom", "icon-allow-overlap": true, // 防止图标被隐藏 }, }); } // 添加序号背景层(圆形) if (!this.mapObj.getLayer("label-backgrounds")) { this.mapObj.addLayer({ id: "label-backgrounds", type: "circle", source: "devices-source", paint: { "circle-radius": 10, "circle-color": [ "case", ["==", ["feature-state", "isSelected"], true], "#FF6666", "#45CCDA", ], "circle-stroke-width": 1, "circle-stroke-color": "#fff", "circle-translate": [0, -22], // 向上平移,与图标位置配合 }, }); } // 添加序号文本层 if (!this.mapObj.getLayer("device-labels")) { this.mapObj.addLayer({ id: "device-labels", type: "symbol", source: "devices-source", layout: { "text-field": ["get", "index"], "text-font": ["Noto Sans Bold"], "text-size": 12, "text-offset": [0, -1.8], // 调整位置到背景圆中心 "text-anchor": "top", "text-allow-overlap": true, }, paint: { "text-color": "#FFFFFF", "text-halo-color": "rgba(0, 0, 0, 0.5)", "text-halo-width": 1, }, }); } // 设置初始特征状态 devices.forEach((device) => { this.mapObj.setFeatureState( { source: "devices-source", id: device.id }, { isSelected: device.id === this.selectedDeviceId } ); }); }) .catch((error) => { console.error("图层添加失败:", error); }); // 点击事件处理 this.mapObj.off("click"); // 移除旧的监听器,避免重复绑定 this.mapObj.on( "click", ["devices-layer", "device-labels", "label-backgrounds"], (e) => { if (e.features && e.features.length > 0) { const deviceId = e.features[0].properties.id; this.toggleDeviceSelection(deviceId); } } ); console.log('当前地图样式中的图片:', this.mapObj.getStyle().images); console.log('设备源是否存在:', this.mapObj.getSource('devices-source')); }, loadImageSafe(name, url) { console.log(Loading image: ${name} from ${url}); return new Promise((resolve) => { if (this.mapObj.hasImage(name)) { console.log(Image ${name} already exists.); resolve(); } else { this.mapObj.loadImage(url, (error, image) => { if (error) { console.error(图片加载失败: ${url}, error); resolve(); // 即使失败也继续执行 } else { this.mapObj.addImage(name, image); resolve(); } }); } }); },地图上还是没有任何显示,打印有图片信息可以在浏览器打开图片

<template> <el-form class="search-from" :inline="true" label-width="70px" @submit.prevent="initGantt"> <el-form-item label="名称"> <el-input v-model="queryParams.name" placeholder="请输入名称" clearable/> </el-form-item> <el-form-item label="责任人"> <el-input v-model="queryParams.respPerson" placeholder="请输入责任人" clearable/> </el-form-item> <el-form-item> <el-button type="primary" @click="initGantt"> 搜索 </el-button> <el-button @click="resetQuery"> 重置 </el-button> <el-button type="primary" style="margin-left: 10px;" @click="retractGantt" > {{ '收起甘特图' }} </el-button> </el-form-item> </el-form> <Dialog title="查看治理计划" :visible.sync="open" width="850px" height="600px" append-to-body> <el-form ref="form" :model="form" label-width="100px" disabled> <el-row> <el-col :span="12"> <el-form-item label="编号" prop="code"> <el-input v-model="form.code" placeholder="请输入编号"/> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="名称" prop="text"> <el-input v-model="form.text" placeholder="请输入名称"/> </el-form-item> </el-col> </el-row> <el-row> <el-col :span="12"> <el-form-item label="上级计划" prop="parent"> <treeselect v-model="form.parent" :options="planOptions" :normalizer="normalizer" placeholder="选择上级计划" disabled /> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="完成度(%)" prop="progress"> <el-input-number v-model="form.progress" placeholder="请输入完成百分比"/> </el-form-item> </el-col> </el-row> <el-row> <el-col :span="12"> <el-form-item label="责任人" prop="respPerson"> 责任人 {{ form.respPerson }} <el-button size="mini" type="primary" icon="el-icon-user" class="btn-wizard-trigger" style="margin-left: 10px" >选择用户 </el-button> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="责任部门" prop="respDept"> <el-input v-model="form.respDept" placeholder="请输入责任部门"/> </el-form-item> </el-col> </el-row> <el-row> <el-col :span="12"> <el-form-item label="计划开始日期" prop="planStartDate"> <el-date-picker clearable v-model="form.planStartDate" type="date" value-format="yyyy-MM-dd" placeholder="请选择计划开始日期"> </el-date-picker> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="实际开始日期" prop="realStartDate"> <el-date-picker clearable v-model="form.realStartDate" type="date" value-format="yyyy-MM-dd" placeholder="请选择实际开始日期"> </el-date-picker> </el-form-item> </el-col> </el-row> <el-row> <el-col :span="12"> <el-form-item label="计划结束时间" prop="planEndDate"> <el-date-picker clearable v-model="form.planEndDate" type="date" value-format="yyyy-MM-dd" placeholder="请选择计划结束时间"> </el-date-picker> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="实际结束日期" prop="realEndDate"> <el-date-picker clearable v-model="form.realEndDate" type="date" value-format="yyyy-MM-dd" placeholder="请选择实际结束日期"> </el-date-picker> </el-form-item> </el-col> </el-row> <el-row> <el-col :span="12"> <el-form-item label="计划工期(天)" prop="planDuration"> <el-input v-model="form.planDuration" placeholder="请选择计划日期"/> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="实际工期(天)" prop="realDuration"> <el-input v-model="form.realDuration" placeholder="请选择实际日期"/> </el-form-item> </el-col> </el-row> <el-row> <el-col :span="24"> <el-form-item label="备注" prop="remarks"> <el-input v-model="form.remarks" type="textarea" placeholder="请输入备注"/> </el-form-item> </el-col> </el-row> <el-row> <el-col :span="24"> <el-form-item label="反馈内容" prop="feedback"> <el-input v-model="form.feedback" type="textarea" placeholder="请输入内容"/> </el-form-item> </el-col> </el-row> </el-form> <el-button @click="open = false">关 闭</el-button> </Dialog> </template> <script> import TablePane from '@/components/TablePane' import Dialog from '@/components/Dialog' import Treeselect from '@riophae/vue-treeselect' import '@riophae/vue-treeselect/dist/vue-treeselect.css' import {gantt} from "dhtmlx-gantt"; import "dhtmlx-gantt/codebase/dhtmlxgantt.css"; import {listPlan} from "@/api/dw/plan/planview"; export default { components: {TablePane, Dialog, Treeselect}, name: "gantt", data() { return { getListFun: listPlan, searchFields: [ {'field': 'name', 'label': '名称', 'type': 'input'}, {'field': 'respPerson', 'label': '责任人', 'type': 'input'}, ], operations: [ { 'label': '展开甘特图', 'click': this.expandGantt, 'hasPermi': ['dw:planview:list'] }], tableData: { 'idField': 'uid', //加载数据后进行转换用于特殊处理 'loadDataHook': this.loadDataHook, 'attrs': { 'row-key': 'uid', '@row-click': this.rowClick, 'tree-props': { children: 'children', hasChildren: 'hasChildren' }, 'default-expand-all': true }, 'column': [ {'label': '编号', 'prop': 'code', 'attrs': { 'sortable': false,'align': 'left' } }, {'label': '状态', 'prop': 'status1', 'attrs': { 'sortable': false } ,'width': 80,'columnHook': this.light}, {'label': '名称', 'prop': 'name', 'attrs': { 'sortable': false } }, {'label': '完成百分比', 'prop': 'schedule', 'attrs': { 'sortable': false } }, {'label': '责任人', 'prop': 'respPerson', 'attrs': { 'sortable': false } }, {'label': '责任部门', 'prop': 'respDept' , 'attrs': { 'sortable': false }}, {'label': '计划开始日期', 'prop': 'planStartDate' ,'type':"dateTime" , 'format': (date) => { return this.parseTime(date, '{y}-{m}-{d}')}}, {'label': '计划结束时间', 'prop': 'planEndDate' ,'type':"dateTime" , 'format': (date) => { return this.parseTime(date, '{y}-{m}-{d}')}}, {'label': '实际开始日期', 'prop': 'realStartDate' ,'type':"dateTime" , 'format': (date) => { return this.parseTime(date, '{y}-{m}-{d}')}}, {'label': '实际结束日期', 'prop': 'realEndDate' ,'type':"dateTime" , 'format': (date) => { return this.parseTime(date, '{y}-{m}-{d}')}}, {'label': '计划工期', 'prop': 'planDuration' }, {'label': '实际工期', 'prop': 'realDuration' }, {'label': '备注', 'prop': 'remarks' }, { 'width': 100, 'label': '操作', 'type': 'button', 'attrs': { 'sortable': false, 'fixed': 'right' }, 'buttons': [ { 'icon': 'el-icon-view', 'label': '查看', 'hasPermi': ['dw:planview:query'], 'click': this.handleView }, ] } ] }, /***************************************************甘特图 start****************************************************************/ tasks: { data: [], }, queryParams: { name: null, respPerson: null }, showGantt: true, // 状态控制甘特图显示 planOptions: [], open: false, // 控制详情弹窗显示 form: {} // 当前查看的任务 /***************************************************甘特图 end****************************************************************/ }; }, // 把携带的参数放到queryParams查询参数里 created() { // console.log(this.$route.params.id); }, methods: { /** 查询治理计划列表 */ getList() { this.$refs.tablePane.loadData() }, loadDataHook(response) { response.data = this.handleTree(response.data, 'uid','parentUid') return response }, light(column, row){ const currentDate = this.getCurrentDate(); if( row.realStartDate != null){//有实际开始时间 // 状态灯:绿色:已完成; // 红色:计划开始时间小于当前日期并且没有实际开始日期; // 黄色:有实际开始日期,但是没有实际结束日期,并且计划结束日期小宇当前日期。 // 其他状态都没有颜色(数据体系里面的计划状态灯昨天没写,也按这个规则) var res = this.compareDate(new Date(row.planEndDate),new Date(currentDate)) if( row.realEndDate == null){ if(res== -1){ column.class='circle-light-yellow' } }else{ column.class='circle-light-green' } }else{//没用实际开始时间 红色:没有实际开始,但是当前日期大于计划开始日期; if(row.planStartDate != null){//有计划开始时间 var res = this.compareDate(new Date(row.planStartDate),new Date(currentDate)) if(res == -1){ column.class='circle-light-red' } } } }, getCurrentDate(){ const dateObj = new Date(); const year = dateObj.getFullYear(); // 获取当前年份 const month = ("0" + (dateObj.getMonth() + 1)).slice(-2); // 获取当前月份,其中需要将月份加1,因为月份是从0开始计数的 const day = ("0" + dateObj.getDate()).slice(-2); // 获取当前日期 const formattedDate = ${year}-${month}-${day}; // 格式化日期 return formattedDate; // 输出当前时间的年月日 }, compareDate(date1,date2){//date1 > date2 返回1;date1 < date2 返回-1 相等返回0 if (date1.getTime() > date2.getTime()) { return 1; } else if (date1.getTime() < date2.getTime()) { return -1; } else { return 0; } }, // 上级节点 getTreeselect() { listPlan().then(response => { const data = {uid: 0, name: '顶级节点', children: []}; data.children = this.handleTree(response.data, 'uid', 'parentUid') this.planOptions.push(data) }) }, normalizer(node) { if (node.children && !node.children.length) { delete node.children } return { id: node.uid, label: node.name, children: node.children } }, rowClick(row, column, event) { // 行点击事件 }, /***************************************************甘特图 start****************************************************************/ // 查看任务详情 handleView(taskId) { // 根据任务ID查找任务详情 const task = this.tasks.data.find(item => item.id == taskId); if (task) { this.getTreeselect(); this.form = task; this.open = true; } }, expandGantt() { this.showGantt = false this.$nextTick(() => { this.initGantt(); // 确保DOM更新后再初始化甘特图 }); }, retractGantt() { this.showGantt = true; this.destroyGantt(); // 添加销毁甘特图方法 }, //开始时间-结束时间参数 DateDifference: function (strDateStart, strDateEnd) { var begintime_ms = Date.parse(new Date(strDateStart.replace(/-/g, "/"))); //begintime 为开始时间 var endtime_ms = Date.parse(new Date(strDateEnd.replace(/-/g, "/"))); // endtime 为结束时间 var date3 = endtime_ms - begintime_ms; //时间差的毫秒数 var days = Math.floor(date3 / (24 * 3600 * 1000)); return days; }, // 重置查询 resetQuery() { this.queryParams = { name: null, respPerson: null }; this.initGantt(); }, initGantt: function () { // 确保容器存在 if (!this.$refs.gantt) return; // 先销毁旧实例 this.destroyGantt(); // 清空容器 this.$refs.gantt.innerHTML = ""; // 设置容器尺寸 this.$refs.gantt.style.height = ${window.innerHeight - 150}px; // 在初始化前配置所有设置 //自适应甘特图的尺寸大小, 使得在不出现滚动条的情况下, 显示全部任务 gantt.config.autosize = true; //只读模式 gantt.config.readonly = true; //是否显示左侧树表格 gantt.config.show_grid = true; //时间轴配置 gantt.config.show_task_cells = true; //当task的长度改变时,自动调整图表坐标轴区间用于适配task的长度 gantt.config.fit_tasks = true; gantt.config.min_column_width = 50; gantt.config.auto_types = true; gantt.config.xml_date = "%Y-%m-%d"; gantt.config.scale_unit = "month"; gantt.config.step = 1; gantt.config.date_scale = "%Y年%M"; gantt.config.start_on_monday = true; gantt.config.scale_height = 160; gantt.config.autoscroll = true; gantt.config.calendar_property = "start_date"; gantt.config.calendar_property = "end_date"; gantt.config.readonly = true; //时间刻度配置 var weekScaleTemplate = function (date) { var dateToStr = gantt.date.date_to_str("%m %d"); var endDate = gantt.date.add( gantt.date.add(date, 1, "week"), -1, "day" ); var weekNum = gantt.date.date_to_str("第 %W 周"); return weekNum(date); }; gantt.config.subscales = [ { unit: "week", step: 1, template: weekScaleTemplate, }, { unit: "day", step: 1, format: "%d", }, ]; //表格列设置 gantt.config.columns = [ { name: "code", label: "编号", tree: true, width: "160", onrender: function (task, node) { node.setAttribute( "class", "gantt_cell gantt_last_cell gantt_cell_tree " + task.status ); }, }, { name: "status", label: "状态", align: "center", width: "80", template: function (task) { // 自定义状态列显示为状态灯 return ; } }, {name: "text", label: "名称", align: "center", width: "180", hide: true}, {name: "progress", label: "完成度(%)", align: "center", width: "90", hide: true}, {name: "respPerson", label: "责任人", align: "center", width: "120", hide: true}, {name: "respDept", label: "责任部门", align: "center", width: "140", hide: true}, {name: "planStartDate", label: "计划开始日期", align: "center", width: "130", hide: true}, {name: "planEndDate", label: "计划结束时间", align: "center", width: "130", hide: true}, {name: "realStartDate", label: "实际开始日期", align: "center", width: "130", hide: true}, {name: "realEndDate", label: "实际结束日期", align: "center", width: "130", hide: true}, {name: "planDuration", label: "计划工期", align: "center", width: "90", hide: true}, {name: "realDuration", label: "实际工期", align: "center", width: "90", hide: true}, {name: "remarks", label: "备注", align: "center", width: "220", hide: true}, ]; // 设置布局 - 修复表格铺满问题 gantt.config.layout = { css: "gantt_container", cols: [ { width: 400, // 固定左侧表格宽度 min_width: 300, rows: [ { view: "grid", scrollX: "gridScroll", scrollable: true, scrollY: "scrollVer", }, { view: "scrollbar", id: "gridScroll", group: "horizontal", }, ], }, { resizer: true, width: 1, }, { rows: [ { view: "timeline", scrollX: "scrollHor", scrollY: "scrollVer", }, { view: "scrollbar", id: "scrollHor", group: "horizontal", }, ] } ], }; // 初始化 gantt.init(this.$refs.gantt); gantt.plugins({ tooltip: true, }); //设置鼠标放置显示事件 gantt.attachEvent("onGanttReady", function() { var tooltips = gantt.ext.tooltips; gantt.templates.tooltip_text = function(start, end, task) { return "编号:" + task.code + "
" + "名称:" + task.text + "
" + "计划开始:" + gantt.templates.tooltip_date_format(start) + "
" + "工期:" + task.duration }; }); //设置任务条进度内容 gantt.templates.progress_text = function (start, end, task) { return ( "" + task.progress + "% " ); }; //任务条显示内容 gantt.templates.task_text = function (start, end, task) { return ( "" + task.text + "(" + task.duration + "天)" + "" ); }; //任务条上的文字大小 以及取消border自带样式 gantt.templates.task_class = function (start, end, item) { return item.$level == 0 ? "firstLevelTask" : "secondLevelTask"; }; gantt.i18n.setLocale("cn"); listPlan(this.queryParams).then((res) => { // 检查响应数据有效性 if (!res || !res.data) return; this.tasks.data = res.data.map((item) => { let statusColor; //存在status字段 说明非一级菜单,判断阶段的具体类型 设置不同颜色 if (item.status == '1') { //冒烟 statusColor = "#84bd54" } else if (item.status == '2') { //单元 statusColor = "#fcca02" } else if (item.status == '3') { //回归 statusColor = "#dc1626" } else { statusColor = "#999999" } return { id: item.uid, parent: item.parent, text: item.name, start_date: item.planStartDate, duration: item.planDuration, open: true, //默认打开, toolTipsTxt: item.name, progress: item.schedule, status: item.status, code: item.code, respPerson: item.respPerson, respDept: item.respDept, planStartDate: item.planStartDate, planEndDate: item.planEndDate, realStartDate: item.realStartDate, realEndDate: item.realEndDate, planDuration: item.planDuration, realDuration: item.realDuration, remarks: item.remarks, feedback: item.feedback, color: statusColor, } }); // 数据解析前检查甘特图是否仍然有效 if (gantt.$root) { // 数据解析 gantt.parse(this.tasks); } }); // 添加双击行事件监听器 gantt.attachEvent("onTaskDblClick", function(id, e) { // 调用查看详情方法 window.vueInstance.handleView(id); return true; }); }, destroyGantt() { try { // 更彻底地清理甘特图实例 if (gantt) { // 移除所有事件监听器 if (typeof gantt.detachAllEvents === 'function') { gantt.detachAllEvents(); } // 清空所有数据 if (typeof gantt.clearAll === 'function') { gantt.clearAll(); } // 使用正确的销毁方法 if (typeof gantt.destructor === 'function') { gantt.destructor(); } } } catch (e) { console.warn('Error destroying gantt chart:', e); } finally { // 确保容器被清空 if (this.$refs.gantt) { this.$refs.gantt.innerHTML = ""; } } }, }, mounted() { window.vueInstance = this; if (!this.showGantt) { this.$nextTick(this.initGantt); } else { this.getList(); } }, }; </script> <style lang="scss" scoped> .firstLevelTask { border: none; .gantt_task_content { font-size: 13px; } } .secondLevelTask { border: none; } .thirdLevelTask { border: 2px solid #da645d; color: #da645d; background: #da645d; } .milestone-default { border: none; background: rgba(0, 0, 0, 0.45); } .milestone-unfinished { border: none; background: #5692f0; } .milestone-finished { border: none; background: #84bd54; } .milestone-canceled { border: none; background: #da645d; } html, body { margin: 0; padding: 0; height: 100%; overflow: hidden; } .container { height: 100%; width: 100%; position: relative; padding: 10px; .gantt_grid_head_cell { padding-left: 20px; text-align: left !important; font-size: 14px; color: #333; } .left-container { height: 100%; } .green, .yellow, .pink, .popular { .gantt_tree_icon.gantt_file { background: none; position: relative; &::before { content: ""; width: 10px; height: 10px; border-radius: 50%; position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); } } } .green { .gantt_tree_icon.gantt_file { &::before { background: #84bd54; } } } .yellow { .gantt_tree_icon.gantt_file { &::before { background: #fcca02; } } } .pink { .gantt_tree_icon.gantt_file { &::before { background: #da645d; } } } .popular { .gantt_tree_icon.gantt_file { &::before { background: #d1a6ff; } } } } .left-container { height: 100%; } .gantt_task_content { text-align: left; padding-left: 10px; } .gantt-container { height: calc(100vh - 150px) !important; width: 100%; } // 状态灯样式 ::v-deep .gantt_grid_data .gantt_cell div.status-light { width: 12px; height: 12px; border-radius: 50%; display: inline-block; margin: 0 auto; } // 表格表头居中样式 ::v-deep .gantt_grid_head_cell { text-align: center !important; } .search-wrapper { text-align: left; padding: 10px 0; } .search-from { .el-form-item--mini.el-form-item, .el-form-item--small.el-form-item { margin-bottom: 3px; } } </style> <style lang="less"> .circle-light-yellow > span::before { content: ''; display: inline-block; width: 16px; height: 16px; background-color: #e6a23c; border-radius: 50%; margin-right: 10px; } .circle-light-green > span::before { content: ""; display: inline-block; width: 16px; height: 16px; background-color: #67c23a; border-radius: 50%; margin-right: 10px; } .circle-light-red > span::before { content: ""; display: inline-block; width: 16px; height: 16px; background-color: #f56c6c; border-radius: 50%; margin-right: 10px; } </style> 展开甘特图报错Cannot read properties of undefined (reading 'tasksStore')

<template> <el-table-column v-if="col.show && col.type != 'selection' && col.type != 'radio'" v-bind="col" :align="'center'" showOverflowTooltip > <template #header> {{ col.label }} <template v-if="col.templet !== 'tool' && col.filter && col.prop"> <el-popover :visible="visible && col.prop === showKey" :virtual-ref="refName" placement="bottom" :width="'fit-content'" ref="popoverRef" > <template #reference> <el-icon @click.stop="toggleNameFilter(col.prop, col)" size="17.4" :class="{ 'filter-active': searchData[col.prop] }" > <Filter /> </el-icon> </template> <el-input v-if="col.filter.filterFormType === 'input'" v-model="searchData[col.prop]" :autofocus="true" placeholder="请输入" v-bind="col.attrs" @input="applyNameFilter" clearable style="margin-top: 10px; width: 150px" /> <template v-if="!col.filter.needGetList"> <el-select v-if="col.filter.filterFormType === 'select'" filterable :reserve-keyword="false" v-model="searchData[col.prop]" v-bind="col.attrs" @change="applyTagFilter" clearable style="margin-top: 10px; width: 150px" > <el-option v-for="item in col.filter.selectList" :key="item" :value="item.value" :label="item.name" /> </el-select> <FkSelectTree v-if="col.filter.filterFormType === 'select-tree'" v-model="searchData[col.prop]" v-bind="col.attrs" /> </template> <template v-if="col.filter.needGetList"> <FkSelect v-if="col.filter.filterFormType === 'select'" v-bind="col.attrs" v-model="searchData[col.prop]" :sourceData="javaList" ></FkSelect> <FkSelectTree v-if="col.filter.filterFormType === 'select-tree'" v-model="searchData[col.prop]" v-bind="col.attrs" :data="javaList" :sourceData="javaList" ></FkSelectTree> </template> <el-date-picker v-if=" col.filter.filterFormType === 'daterange' || col.filter.filterFormType === 'datetimerange' " style="width: 360px" v-model="searchData[col.prop]" :type="col.filter.filterFormType" range-separator="~" start-placeholder="开始时间" end-placeholder="结束时间" :format="col.dateType" @change="changeData($event, col.field, col.dateType)" /> <el-button type="info" link @click="cancelFilter(col.prop)">重置</el-button> <el-button type="primary" link @click="searchFilter">筛选</el-button> </el-popover> </template> </template> <template #default="scope"> <template v-if="col.templet === 'image'"> <template v-if="col.prop"> <template v-if="Array.isArray(scope.row[col.prop])"> <template v-for="(item, index) in scope.row[col.prop]" :key="item"> <el-image :src="item" :preview-src-list="scope.row[col.prop]" :initial-index="index" :preview-teleported="true" :style="width: ${col.imageWidth ?? 40}px; height: ${col.imageHeight ?? 40}px" /> </template> </template> <template v-else> <el-image :src="scope.row[col.prop]" :preview-src-list="[scope.row[col.prop]]" :preview-teleported="true" :style="width: ${col.imageWidth ?? 40}px; height: ${col.imageHeight ?? 40}px" /> </template> </template> </template> <template v-else-if="col.templet === 'list'"> <template v-if="col.prop"> {{ (col.selectList ?? {})[scope.row[col.prop]] }} </template> </template> <template v-else-if="col.templet === 'url'"> <template v-if="col.prop"> <el-link type="primary" :href="scope.row[col.prop]" target="_blank"> {{ scope.row[col.prop] }} </el-link> </template> </template> <template v-else-if="col.templet === 'price'"> <template v-if="col.prop"> {{ ${col.priceFormat ?? "¥"}${scope.row[col.prop]} }} </template> </template> <template v-else-if="col.templet === 'percent'"> <template v-if="col.prop">{{ scope.row[col.prop] }}%</template> </template> <template v-else-if="col.templet === 'icon'"> <template v-if="col.prop"> <template v-if="scope.row[col.prop].startsWith('el-icon-')"> <el-icon> <component :is="scope.row[col.prop].replace('el-icon-', '')" /> </el-icon> </template> <template v-else> </template> </template> </template> <template v-else-if="col.templet === 'date'"> <template v-if="col.prop"> {{ scope.row[col.prop] ? useDateFormat(scope.row[col.prop], col.dateFormat ?? "YYYY-MM-DD HH:mm:ss").value : "" }} </template> </template> <template v-else-if="col.templet === 'sys-code'"> <FkSysCodeLable v-if="col.prop" v-model="scope.row[col.prop]" :code="col.sysCodeSetCode" /> </template> <template v-else-if="col.templet === 'copy'"> <el-text>{{ scope.row[col.prop] }}</el-text> <copy-button v-if="scope.row[col.prop]" :text="scope.row[col.prop]" style="margin-left: 2px" /> </template> <template v-else-if="col.templet === 'yes-no'"> <el-tag :type="scope.row[col.prop] == '1' ? 'success' : 'info'"> {{ scope.row[col.prop] == "1" ? "启用" : "禁用" }} </el-tag> </template> <template v-else-if="col.templet === 'translate'"> {{ scope.row[col.prop + "Name"] }} </template> </template> </el-table-column> </template>优化,点击非弹出部分,自定关闭弹窗

<template> <a-form :form="form" layout="inline" class="top-filter" hideRequiredMark v-show="showToolbox"> <a-form-item v-for="item in searchItems" :key="item.id" :label="item.label"> <a-input v-if="item.type == 'text'" v-decorator="[item.id, { rules: item.rules, initialValue: item.value }]" :placeholder="item.placeholder" :allowClear="item.allowClear" :model="parameter[item.id]" :style="item.style" /> <a-input v-if="item.type == 'hidetext'" v-decorator="[item.id, { rules: item.rules, initialValue: item.value }]" :model="parameter[item.id]" v-show="false" /> <a-select :style="item.width ? width:${item.width}px : item.mode === 'multiple' ? 'width:300px' : 'width:144px'" v-if="item.type == 'select'" :mode="item.mode || 'default'" :model="parameter[item.id]" v-decorator="[item.id, { rules: item.rules, initialValue: item.value }]" :select="item.onSelected" @change="item.onChange" :allowClear="item.allowClear" :maxTagCount="item.maxTagCount ? item.maxTagCount : 2" :showArrow="true" > <a-select-option v-for="opt in item.data" :key="opt.label" :value="opt.value">{{ opt.label }}</a-select-option> </a-select> <district-calc-type-select v-if="item.type == 'districtcalctypeselect'" v-decorator="[item.id, { rules: item.rules, initialValue: item.value }]" @onIsEmpty="hideFormItem(item.id)" ></district-calc-type-select> <a-date-picker v-if="item.type == 'yeardatepicker'" v-decorator="[item.id, { rules: item.rules, initialValue: item.value }]" mode="year" :format="item.format" :style="item.style" :open="dateOpen" @openChange="openChange" @panelChange="(value) => yearChange(value, item)" > <a-icon type="calendar" slot="suffixIcon" style="color: rgba(0, 0, 0, 0.65)" /> <a-button size="small" type="primary" @click="dateOpen = false">确定</a-button> </a-date-picker> <a-date-picker v-if="item.type == 'datepicker'" v-decorator="[item.id, { rules: item.rules, initialValue: item.value }]" :format="item.format" :show-time="item.showTime" :style="item.style" > <a-icon v-if="item.showTime" type="clock-circle" slot="suffixIcon" style="color: rgba(0, 0, 0, 0.65)" /> </a-date-picker> <a-month-picker dropdownClassName="quarter-selecter" v-if="item.type == 'quarterselecter'" v-decorator="[item.id, { rules: item.rules, initialValue: item.value }]" :format="'YYYY年第Q季度'" :style="item.style" placeholder="请选择季度" @change="(value) => singleQuarter(value, item)" > </a-month-picker> <a-range-picker dropdownClassName="quarter-selecter" v-if="item.type == 'quarterrangeselecter'" v-decorator="[item.id, { rules: item.rules, initialValue: item.value }]" :format="'YYYY年第Q季度'" :style="item.style" :mode="['month', 'month']" :placeholder="['请选择季度', '请选择季度']" @panelChange="(value) => quarterChange(value, item)" ></a-range-picker> <a-month-picker v-if="item.type == 'monthdatepicker'" v-decorator="[item.id, { rules: item.rules, initialValue: item.value }]" :format="item.format" :style="item.style" /> <a-week-picker v-if="item.type == 'weekdatepicker'" v-decorator="[item.id, { rules: item.rules, initialValue: item.value }]" :format="item.format" :style="item.style" /> <a-radio-group v-if="item.type == 'radiobutton'" v-decorator="[item.id, { rules: item.rules, initialValue: item.value }]" :mode="parameter[item.id]" buttonStyle="solid" :name="item.id" @change="item.change" > <a-radio-button v-for="opt in item.data" :key="opt.label" :value="opt.value"> {{ opt.label.replace(')', ')').replace('(', '(') }} </a-radio-button> </a-radio-group> <a-range-picker v-if="item.type === 'rangepicker' && item.format === 'YYYY-MM-DD'" v-decorator="[item.id, { rules: item.rules, initialValue: item.value }]" :format="item.format" :ranges="dayRange" :disabled-date="disabledDate" style="width: 200px" > <a-icon type="calendar" slot="suffixIcon" style="color: rgba(0, 0, 0, 0.65)" /> </a-range-picker> <a-range-picker v-else-if="item.type === 'rangepicker' && item.format.indexOf('YYYY-MM-DD H') !== -1" v-decorator="[item.id, { rules: item.rules, initialValue: item.value }]" :format="item.format" :ranges="hourRange" :showTime="item.showTime" :disabled-date="disabledDate" :inputReadOnly="true" style="width: 270px; min-width: auto" > <a-icon type="clock-circle" slot="suffixIcon" style="color: rgba(0, 0, 0, 0.65)" /> </a-range-picker> <a-range-picker v-if="item.type === 'monthrangepicker'" v-decorator="[item.id, { rules: item.rules, initialValue: item.value }]" :format="item.format" style="width: 200px" :mode="['month', 'month']" @panelChange="(value) => monthChange(value, item)" > <a-icon type="clock-circle" slot="suffixIcon" style="color: rgba(0, 0, 0, 0.65)" /> </a-range-picker> <a-range-picker v-if="item.type === 'yearrangepicker'" v-decorator="[item.id, { rules: item.rules, initialValue: item.value }]" style="width: 170px" :format="item.format" :mode="['year', 'year']" dropdownClassName="notimebtn" showTime @panelChange="(value) => yearChange(value, item)" > <a-icon type="clock-circle" slot="suffixIcon" style="color: rgba(0, 0, 0, 0.65)" /> </a-range-picker> <district-station-select v-if="item.type === 'districtstationselect'" v-decorator="[item.id, { rules: item.rules }]" :defaultValue="item.value" @onLoad="query" ></district-station-select> <station-select v-if="item.type === 'stationselect'" v-decorator="[item.id, { rules: item.rules }]" :defaultValue="item.value" @onLoad="query" ></station-select> <district-select v-if="item.type === 'districtselect'" v-decorator="[item.id, { rules: item.rules }]" :listSize="{ width: 600, height: 400 }" :initialValue="item.value" :syncId="item.syncId" :useDefaultValue="item.useDefaultValue" @onLoad="query" ></district-select> <city-station-select v-if="item.type === 'citystationselect'" v-decorator="[item.id, { rules: item.rules }]" :listSize="{ width: 600, height: 400 }" :styles="width: 200px;" :syncId="item.syncId" :initialValue="item.value" :defaultAll="item.defaultAll" :stationTypeSelectTab="item.stationTypeSelectTab" :hideOthersStationTypeTab="item.hideOthersStationTypeTab" :useDefaultStationType="item.useDefaultStationType" @onLoad="query" ></city-station-select> <opa-city-station-select v-if="item.type === 'opacitystationselect'" v-decorator="[item.id, { rules: item.rules }]" :listSize="{ width: 600, height: 400 }" :styles="width: 200px;" :syncId="item.syncId" :initialValue="item.value" :defaultAll="item.defaultAll" :stationTypeSelectTab="item.stationTypeSelectTab" :hideOthersStationTypeTab="item.hideOthersStationTypeTab" :useDefaultStationType="item.useDefaultStationType" @onLoad="query" ></opa-city-station-select> <department-select v-if="item.type === 'departmentselect'" v-decorator="[item.id, { rules: item.rules, initialValue: item.value }]" ></department-select> <a-select v-if="item.type == 'searchSelect'" show-search :allowClear="true" option-filter-prop="children" v-decorator="[item.id, { rules: item.rules, initialValue: item.value }]" :filter-option="item.filterOption ? item.filterOption : filterOption" style="width: 250px" :disabled="item.disabled || false" @focus="item.focus" @blur="item.blur" @change="item.change" > <a-select-option v-for="opt in item.data" :key="opt.label" :value="opt.value">{{ opt.label }}</a-select-option> </a-select> <city-select v-if="item.type === 'cityselect'" v-decorator="[item.id, { rules: item.rules }]" :listSize="{ width: 600, height: 400 }" :styles="width: 200px;" :initialValue="item.value" @onLoad="query" ></city-select> <drop-select v-if="item.type === 'dropdownselect'" v-decorator="[item.id, { rules: item.rules }]" :defaultValue="item.value" :level="item.level" :multiple="item.multiple" ></drop-select> </a-form-item> <a-form-item> <a-popconfirm v-if="loading" title="正在查询中,是否重新查询" ok-text="是" cancel-text="否" @confirm="confirm" @cancel="cancel" > <a-button type="primary" style="margin-right: 5px"> 查询 <a-icon type="search" /> </a-button> </a-popconfirm> <a-button v-else type="primary" style="margin-right: 5px" @click="search"> 查询 <a-icon type="search" /> </a-button> <a-button v-if="showExport" @click="exportExcel" :disabled="loading"> 导出Excel <a-icon type="file-excel" /> </a-button> </a-form-item> <slot name="button"></slot> <a-form-item> <my-timer class="refreshTimer" v-if="showTimer" :refreshSecond="refreshSecond" :query="query"></my-timer> </a-form-item> </a-form> <slot name="tip"></slot> <full-table @resize="tableSize"> <template v-slot:table> <a-table v-if="showTable" :rowKey="rowKey" bordered :columns="widthFullColumns" :dataSource="loadData" :pagination=" isMemoryPaging ? { class: 'ant-table-pagination', pageSizeOptions: pageSizeOptions, pageSize: pageSize, showTotal: showTotal, showSizeChanger: true } : false " :loading="loading" :scroll="{ x: 500, y: loadData.length > 0 ? tableHeight : false }" @change="onTableChange" > {{ index + 1 }} </a-table> </template> <template v-slot:page> <a-pagination v-if="showTable && !isMemoryPaging" class="ant-table-pagination" showSizeChanger :total="total" :pageSize="pageSize" :pageSizeOptions="pageSizeOptions" :showTotal="showTotal" :current="currentPage" :disabled="loading" @change="pageChanged" @showSizeChange="showSizeChange" ></a-pagination> </template> </full-table> </template> <script> import { axios } from '../../utils/request' import { exportExcel } from '@/components/ExcelExport' import StationSelect from '@/components/StationSelect/StationSelect' import DistrictSelect from '@/components/Selector/DistrictSelect' import CitySelect from '@/components/Selector/CitySelect' import DropSelect from '@/components/StationSelect/DropDownSelect' import DistrictStationSelect from '@/components/StationSelect/DistrictStationSelect' import CityStationSelect from '@/components/Selector/CityStationSelect' import PollutantSelect from '@/components/Selector/PollutantSelect' import FullTable from '@/components/Networking/FullTable' import { formtTableColums } from '@/utils/formatTabelColums' import DistrictCalcTypeSelect from '@/components/Selector/DistrictCalcTypeSelect' import MyTimer from '@/components/tools/Timer' import DepartmentSelect from '@/components/OperationBasic/DepartmentSelect' import OpaCityStationSelect from '@/components/Selector/OpaCityStationSelect' // import store from '@suncereltd/suncere-sys/src/store' import moment from 'moment' export default { name: 'DataQuery', components: { StationSelect, DistrictSelect, CitySelect, DistrictStationSelect, CityStationSelect, DropSelect, FullTable, PollutantSelect, DistrictCalcTypeSelect, MyTimer, DepartmentSelect, OpaCityStationSelect }, props: { // 是否内存分页 isMemoryPaging: { type: Boolean, default() { return false } }, // 显示序号 showSerial: { type: Boolean, default() { return false } }, // 列头 columns: { type: Array, default() { return [{ title: 'ID', dataIndex: 'id', key: 'id', sorter: true }] } }, // 查询条件 searchItems: { type: Array, default() { return [] } }, // 主键名 rowKey: { type: String, default() { return 'id' } }, // 查询URL searchUrl: { type: String, default: '' }, // 导出 report: { type: Object, default: null }, pageSizeOptions: { type: Array, default() { return ['20', '30', '40', '50'] } }, pageSize: { type: Number, default: 20 }, parameter: { type: Object, default: () => { return { skipCount: 0, maxResultCount: 20 } } }, showTable: { type: Boolean, default: () => { return true } }, showExport: { type: Boolean, default: () => { return true } }, showTimer: { type: Boolean, default: () => { return false } }, refreshSecond: { type: Number, default: 300 }, createOrUpdate: { type: Boolean, default() { return true } }, validateFieldsSuccess: { type: Function, default: null }, // 查询前特殊处理 // eslint-disable-next-line vue/require-default-prop beforeQuery: { type: Function }, // 查询后特殊处理 // eslint-disable-next-line vue/require-default-prop afterQuery: { type: Function }, usePostQuery: { // 使用post查询,针对请求url过长情况 type: Boolean }, showToolbox: { type: Boolean, default() { return true } } }, data() { const hDate = moment(moment().format('YYYY-MM-DD HH:00:00')) const dDate = moment(moment().format('YYYY-MM-DD')) return { dateOpen: false, hourRange: { 最近一周: [hDate.clone().subtract('week', 1), hDate], 最近一个月: [hDate.clone().subtract('month', 1), hDate], 最近三个月: [hDate.clone().subtract('month', 3), hDate] }, dayRange: { 最近一周: [dDate.clone().subtract('week', 1), dDate], 最近一个月: [dDate.clone().subtract('month', 1), dDate], 最近三个月: [dDate.clone().subtract('month', 3), dDate] }, tableHeight: 200, total: 0, loadData: [], pageIndex: 0, skipCount: 0, currentPage: 0, // pageSize: 20, // pageSizeOptions: ['20', '30', '40', '50'], loading: false, form: this.$form.createForm(this, { name: 'search' }), widthFullColumns: [{ title: 'ID', dataIndex: 'id', key: 'id', sorter: true }], requestCancel: null, currentDataSource: [] } }, computed: { showTotal: () => { return (total) => 总共 ${total} 条 }, // currentPage: function() { // return this.skipCount + 1 // }, oprationColumns: function () { let optColumn = [] if (this.showSerial) { optColumn.push({ title: '序号', scopedSlots: { customRender: 'serial' } }) optColumn = optColumn.concat(this.columns) } else { optColumn = this.columns } return optColumn } }, mounted() { this.setDefaultValue() this.loading = false // 如果配置站点、区县、城市选择器,并且赋予初始值,则页面加载完成即执行查询 const selectors = ['cityselect', 'opacitystationselect', 'citystationselect', 'districtselect'] const selectoritem = this.searchItems.filter((d) => selectors.indexOf(d.type) > -1) if (!(selectoritem.length > 0 && !selectoritem[0].value)) { this.searchUrl && this.search() } this.setMinTable() // 页面加载时重新分配表格宽度 this.$nextTick(() => { const fixeds = this.oprationColumns.filter((d) => d.fixed && (d.fixed === 'left' || d.fixed === 'right')) if (fixeds.length > 0) { this.widthFullColumns = formtTableColums(this.oprationColumns) } else { this.widthFullColumns = this.oprationColumns } }) const self = this window.addEventListener('resize', function () { const fixeds = self.oprationColumns.filter((d) => d.fixed && (d.fixed === 'left' || d.fixed === 'right')) if (fixeds.length > 0) { self.widthFullColumns = formtTableColums(self.oprationColumns) } else { self.widthFullColumns = self.oprationColumns } }) }, methods: { openChange(data) { this.dateOpen = data }, // 季度格式化 formatQuarter(d, type) { // const num = ['一', '二', '三', '四'] const year = d.year() const quarter = d.quarter() const text = type === 1 ? ${year}年第${quarter}季度 : 第${quarter}季度 return text }, changeValue(value, item) { this.form.setFieldsValue({ [item.id]: value }) }, // 获取表头有多少层 getHeightCount() { let count = 0 const columns = this.widthFullColumns let children = [] let temp = [] do { if (count === 0) { temp = columns } else { temp = children } children = [] temp.forEach((e) => { if (e.children && e.children.length > 0) { children = children.concat(e.children) } }) count++ } while (children.length > 0) return count }, tableSize(size) { this.$nextTick(() => { console.log('表头有多少层', this.getHeightCount()) const headHeight = 40 * this.getHeightCount() let tableHeight = size - headHeight - 5 if (this.isMemoryPaging) { tableHeight = tableHeight - 65 } this.tableHeight = tableHeight this.setMinTable() }) }, onTimeTypeChange(e) { this.$emit('onTimeTypeChange', e, this.form) }, // select默认值 setDefaultValue() { if (this.searchItems && this.searchItems.length > 0) { this.searchItems.forEach((item, i) => { if ( (item.type === 'select' || item.type === 'cityselect' || item.type === 'citystationselect' || item.type === 'opacitystationselect' || item.type === 'pollutantselect') && item.value ) { this.form.setFieldsValue({ [item.id]: item.value }) } }) } }, // moment值转换 convertMomentType(values, searchItems) { const defaultFormatStr = 'YYYY-MM-DD HH:mm:ss' const data = {} for (const k in values) { let v = values[k] if (v !== undefined && v !== null) { if (Array.isArray(v)) { data[k] = [...v] v = v.map((m, i) => { if (m instanceof moment) { data[k][i] = m.format(defaultFormatStr) } }) } else { if (v instanceof moment) { // 针对时间点选择器,先根据格式化字段生成后面为0的moment const _item = searchItems.find((x) => x.id === k) if (_item) { const _formatStr = _item.format if (_formatStr) { const newMoment = moment(v.format(_formatStr), _formatStr) data[k] = newMoment.format(defaultFormatStr) } else { data[k] = v.format(defaultFormatStr) } } else { data[k] = v.format(defaultFormatStr) } } else { data[k] = v } } } } return data }, init() { this.total = 0 this.loadData = [] this.skipCount = 0 this.currentPage = 1 this.parameter.skipCount = 0 }, search() { this.init() this.query() }, // 表格查找修改下标 formatTableData(data) { return data.map((item) => { const res = {} for (const key in item) { if (typeof item[key] == 'string') { res[key] = this.formatPollutantSub(item[key]) } else { res[key] = item[key] } } return res }) }, formatPollutantSub(str) { return str .replace(/PM2_5/gi, 'PM₂.₅') .replace(/PM2.5/gi, 'PM₂.₅') .replace(/PM10/gi, 'PM₁₀') .replace(/O3/gi, 'O₃') .replace(/SO2/gi, 'SO₂') .replace(/NO2/gi, 'NO₂') }, filterOption(input, option) { return option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0 }, query() { const self = this self.form.validateFields((err, values) => { if (err) { return } if (this.beforeQuery) { values = this.beforeQuery(values) if(values === 'ywfalse'){ this.$message.error('选择时间不能超过3个月!') return } } $('.ant-table-body').scrollLeft(0) self.loading = true if (self.validateFieldsSuccess && typeof self.validateFieldsSuccess === 'function') { self.validateFieldsSuccess(values) } const formData = self.convertMomentType(values, self.searchItems) self.params = { ...self.parameter, ...formData } if (self.requestCancel && typeof self.requestCancel === 'function') { self.requestCancel('取消上一次清求') } if (self.usePostQuery) { axios .postData(self.searchUrl, self.params) .then((res) => { self.loading = false if (this.afterQuery) { res = this.afterQuery(res) } self.total = res.result.totalCount self.loadData = self.formatTableData(res.result.items) self.currentDataSource = self.loadData self.$emit('search', res.result.items) }) .catch((err) => { self.loading = false self.total = 0 self.loadData = [] self.currentDataSource = self.loadData this.parameter.skipCount = 0 }) } else { axios .getData(self.searchUrl, self.params) .then((res) => { if (this.afterQuery) { res = this.afterQuery(res) } self.total = res.result.totalCount self.loadData = self.formatTableData(res.result.items) self.currentDataSource = self.loadData self.loading = false self.$emit('search', res.result.items) }) .catch((err) => { if (self.$axios.isCancel(err)) { console.log('Request canceled', err.message) } else { // 处理错误 console.log(err) self.total = 0 self.loadData = [] self.currentDataSource = self.loadData this.parameter.skipCount = 0 self.loading = false } }) } }) }, // 点击分页 pageChanged(page, pageSize) { this.currentPage = page this.skipCount = (page - 1) * pageSize this.parameter.skipCount = this.skipCount this.query() }, // 单页大小改变 showSizeChange(current, pageSize) { this.pageSize = pageSize this.currentPage = 1 this.skipCount = 0 this.parameter.skipCount = 0 this.parameter.maxResultCount = this.pageSize this.query() }, // 按列排序 onTableChange(pagination, filters, sorter, obj) { // 后台第一次加载需要排序 this.parameter.columnKey = sorter.columnKey this.parameter.order = sorter.order if (this.isMemoryPaging) { const { currentDataSource } = obj this.currentDataSource = currentDataSource return } this.parameter.sorting = sorter.field this.parameter.ascending = sorter.order === 'ascend' this.query() }, exportExcel() { if (this.total === 0) { this.$message.info('无数据可导出') return } const header = this.columns.map((column) => { if (column.children) { column.children.forEach((c) => { c.render = c.exportRender ? c.exportRender : c.customRender }) } return { k: column.key || column.dataIndex, v: column.reportTitle || column.title, render: column.exportRender ? column.exportRender : column.customRender, children: column.children } }) //正常导出不应该使用分页接口,历史遗留问题 const params = { ...this.params, skipCount: 0, maxResultCount: this.total > 1000 ? 1000 : this.total } // 默认导出文件名称 let reportName = ${this.$route.meta.title}.xlsx if (this.report) { if (this.report.name) { if (typeof this.report.name === 'function') { reportName = this.report.name(params) } else { reportName = this.report.name } } if (this.report.url) { this.loading = true if (this.usePostQuery) { axios .postData(this.report.url, params) .then((res) => { if (res.result.items) { // 调用了分页接口 exportExcel(header, res.result.items, reportName) } else { exportExcel(header, res.result, reportName) } this.loading = false }) .catch(() => { this.loading = false }) } else { axios .getData(this.report.url, params) .then((res) => { if (res.result.items) { // 调用了分页接口 exportExcel(header, res.result.items, reportName) } else { exportExcel(header, res.result, reportName) } this.loading = false }) .catch(() => { this.loading = false }) } } else { exportExcel(header, this.currentDataSource, reportName) } } }, setMinTable() { const MIN_ITEM = 10 // 监听表格数据,表格数据少于MIN_ITEM时撑高表格 if (this.loadData.length < MIN_ITEM && this.loadData.length > 0) { this.$nextTick(() => { this.$refs.table.getElementsByClassName('ant-table-body')[0].style.minHeight = this.tableHeight + 'px' }) } else { this.$refs.table.getElementsByClassName('ant-table-body')[0].style.minHeight = 'none' } }, singleQuarter(value, item) { this.form.setFieldsValue({ [item.id]: value.startOf('quarter') }) }, quarterChange(value, item) { this.form.setFieldsValue({ [item.id]: [value[0].startOf('quarter'), value[1].startOf('quarter')] }) }, monthChange(value, item) { this.form.setFieldsValue({ [item.id]: value }) }, yearChange(value, item) { this.form.setFieldsValue({ [item.id]: value }) }, disabledDate(current) { // 相关链接:https://3x.ant.design/docs/react/faq-cn#%E5%BD%93%E6%88%91%E6%8C%87%E5%AE%9A%E4%BA%86-DatePicker/RangePicker-%E7%9A%84-mode-%E5%B1%9E%E6%80%A7%E5%90%8E%EF%BC%8C%E7%82%B9%E5%87%BB%E5%90%8E%E6%97%A0%E6%B3%95%E9%80%89%E6%8B%A9%E5%B9%B4%E4%BB%BD/%E6%9C%88%E4%BB%BD%EF%BC%9F // 这是因为 <DatePicker mode="year" /> 不等于 YearPicker,<RangePicker mode="month" /> 不等于 MonthRangePicker。 mode 属性是在 antd 3.0 时,为了控制面板展现状态而添加的属性,以支持展示时间面板等需求而添加的。mode 只会简单的改变当前显示的面板,不会修改默认的交互行为(比如 DatePicker 依然是点击日才会完成选择并关闭面板)。 return current && current > moment().endOf('day') }, confirm() { this.search() }, cancel() {}, hideFormItem(id) { this.searchItems = this.searchItems.filter((key) => key.id !== id) }, pickerConfirm(data) { console.log(data) } }, watch: { tableHeight(data) { this.setMinTable() }, total() { this.currentPage = 1 this.skipCount = 0 }, loadData() { this.setMinTable() }, oprationColumns(columns) { this.$nextTick(() => { const fixeds = columns.filter((d) => d.fixed && (d.fixed === 'left' || d.fixed === 'right')) if (fixeds.length > 0) { this.widthFullColumns = formtTableColums(columns) } else { this.widthFullColumns = columns } }) } } } </script> <style lang="less"> .query-page .ant-select-selection--multiple .ant-select-selection__choice__content { max-width: 50px; width: 50px; } .query-page .ant-table-thead > tr > th { padding: 8px 8px; font-weight: bold; text-align: center; background: #deefff; } .query-page .ant-table-tbody > tr > td { padding: 8px 8px; text-align: center; } .refreshTimer { line-height: 30px; font-weight: bold; } </style> <style lang="less"> .quarter-selecter { .ant-calendar-month-panel-cell:nth-child(n + 2) { display: none !important; } .ant-calendar-month-panel-month { font-size: 0; &::after { display: inline-block; font-size: 14px; } } tr:nth-child(1) .ant-calendar-month-panel-month::after { content: '第1季度'; } tr:nth-child(2) .ant-calendar-month-panel-month::after { content: '第2季度'; } tr:nth-child(3) .ant-calendar-month-panel-month::after { content: '第3季度'; } tr:nth-child(4) .ant-calendar-month-panel-month::after { content: '第4季度'; } } ._full-table { padding: 0 12px; } /************ 时间选择器提示信息下面显示 Begin */ .top-filter .has-error .ant-form-explain { margin-top: -4px; padding-left: 0px; } /************ 时间选择器提示信息下面显示 End */ </style> <template> <query ref="query" :showSerial="false" :columns="columns" :searchUrl="searchUrl" :report="report" :searchItems="searchItems" :validateFieldsSuccess="beforeQuery" ></query> </template> <script> // 基本布局 import BaseLayout from '@/components/Networking/BaseLayout' // 表格布局 import Query from '@/components/Page/QueryPage' // 时间格式 import moment from 'moment' export default { name: 'AuditRecords', components: { Query, BaseLayout }, data() { return { columns: [ { title: '城市', dataIndex: 'cityName' }, { title: '区县', dataIndex: 'districtName' }, { title: '站点', dataIndex: 'positionName' }, { title: '唯一编码', dataIndex: 'uniqueCode' }, { title: '监测时间', dataIndex: 'timePoint', customRender: (v) => moment(v).format(this.$datefmt.hour) }, { title: '监测物', dataIndex: 'pollutantName' }, { title: '审核类型', dataIndex: 'auditType' }, { title: '操作人', dataIndex: 'operator' }, { title: '审核操作', dataIndex: 'operateDesc' }, { title: '审核时间', width: 200, dataIndex: 'operateTime', customRender: (v) => moment(v).format(this.$datefmt.second) }, { title: '审核前', dataIndex: 'beforeValue', customRender: (v, row) => (row.beforeMark === '' ? v : v + (${row.beforeMark})) }, { title: '审核后', dataIndex: 'afterValue', customRender: (v, row) => (row.afterMark === '' ? v : v + (${row.afterMark})) }, { title: '审核描述', dataIndex: 'auditDesc' } // , // { // title: '备注', // dataIndex: 'remarks' // } ], searchItems: [ { label: '站点', id: 'StationCode', type: 'citystationselect', rules: [{ required: true, message: '请选择站点!' }], stationTypeSelectTab: ['2','3','4','5','6','7','8'], hideOthersStationTypeTab: true }, { id: 'TimePoint', type: 'rangepicker', label: '时间', format: 'YYYY-MM-DD', rules: [{ required: true, message: '时间不能为空!' }], value: [moment(moment().add(-1, 'days').format('YYYY-MM-DD')), moment(moment().format('YYYY-MM-DD'))] } // , // { // id: 'StateCode', // type: 'select', // label: '审核状态', // value: '', // data: [ // { label: '全部', value: '' }, // { label: '待审核', value: 'WaitAudit' }, // { label: '待上报', value: 'WaitUpload' }, // { label: '待复核', value: 'WaitReview' }, // { label: '已复核', value: 'Reviewed' }, // { label: '已直审', value: 'DirectAudit' } // ] // } ], searchUrl: 'airprovinceproduct/audit/AirCityDataAudit/GetAuditDatasLogsAsync', report: { url: 'airprovinceproduct/audit/AirCityDataAudit/GetAuditDatasLogsListAsync', name: (v) => { return this.exportName(v) } } } }, methods: { moment, beforeQuery(values) { values.StartTime = moment(values.TimePoint[0]).format('YYYY-MM-DD') values.EndTime = moment(values.TimePoint[1]).format('YYYY-MM-DD 23:59:59') return values }, exportName(values) { return 审核记录[${values.StartTime}至${values.EndTime}].xlsx } } } </script> 前端框架 VUE + suncere-ui ( Vue.js 2.6.14 的前端 UI 组件库,在 ant-vue-design 1.7.8 UI框架基础上 进行二次开发) 请根据给出的前端页面写出 乡镇站审核记录 页面, 页面内容 查询条件: 站点选择器,日期选择, 地方审核状态(全部、待审核、已审核) 选择 监测项 (默认为 空,SO₂、 NO₂、CO、O₃、PM₂.₅、PM₁₀、NO、NOx)选择 按钮:查询 前一天 后一天 点击前一天日期选择前一天 立刻查询 点击后一天日期选择前一天 立刻查询 table表格 字段如下: 地方审核状态 、站点名称、时间点(格式:8月15日)、监测项、原始值、审核值、操作、地方审核人员、地方审核意见、省站审核人员、省站审核意见

大家在看

recommend-type

react-map-gl-typescript:react-map-gl + create-react-app +打字稿

:bomb: react-map-gl + create-react-app +打字稿 此存储库呈现全屏Mapbox地图,由Typescript create-react-app -无需弹出! 克隆存储库 $ git clone [email protected]:zackhsi/react-map-gl-typescript.git 使用Mapbox令牌创建环境变量文件 首先,请确保您有一个。 在“ 页面上,创建访问令牌并进行复制。 然后,在存储库的根目录下创建一个.env.development.local文件。 create-react-app会将其加载到process.env ,如此。 $ cat &lt; .env.development.local REACT_APP_MAPBOX_TOKEN=your_mapbox_token EOF 安装节点模块 $ npm i 启动应用 $ n
recommend-type

opentelnet

Opentelnet.exe的用法: OpenTelnet.exe \\server (注:如果administrator用户的密码为空的话,则格式为:opentelnet.exe \\ip administrator "" ) 。
recommend-type

cloudwatch-logback-appender:将签发日志条目发布到AWS CloudWatch的Appender

适用于AWS CloudWatch的Logback日志附加程序 背景 该程序包提供了一个将其日志事件写入Cloudwatch的logback附加程序。 在您说出它之前,似乎有很多这样的项目,但是我发现没有一个项目是独立的并且已经发布到中央Maven存储库中。 可以从获取代码。 Maven软件包通过发布 享受,格雷·沃森 Maven配置 com.j256.cloudwatchlogbackappender cloudwatchlogbackappender &lt;!-- NOTE: change the version to the most recent release version from the re
recommend-type

泛微e8后台维护手册

泛微e8后台维护手册,要学习泛微OA的朋友很值得下载,欢迎广大朋友下载
recommend-type

物理引擎Havok教程

Havok引擎,全称为Havok游戏动力开发工具包(Havok Game Dynamics SDK),一般称为Havok,是一个用于物理系统方面的游戏引擎,为电子游戏所设计,注重在游戏中对于真实世界的模拟。使用碰撞功能的Havok引擎可以让更多真实世界的情况以最大的拟真度反映在游戏中。

最新推荐

recommend-type

发动机飞轮壳前端面钻模夹具设计方案acn.doc

发动机飞轮壳前端面钻模夹具设计方案acn.doc
recommend-type

煤炭协会网络课程《误差理论测量平差》作业题.doc

煤炭协会网络课程《误差理论测量平差》作业题.doc
recommend-type

《软件工程》作业及详细答案.doc

《软件工程》作业及详细答案.doc
recommend-type

PHPlibraryforprintingtoESC-POS-compatiblethermalandimpactprinters.zip

PHPlibraryforprintingtoESC-POS-compatiblethermalandimpactprinters.zip
recommend-type

PLC在自动消防灭火系统中的应用完整版.doc

PLC在自动消防灭火系统中的应用完整版.doc
recommend-type

NY5306-2005标准下的无公害食用植物油指南

标题中提到的“NY5306-2005 无公害食品 食用植物油”指的是中国农业行业标准,其中NY代表“农业”,数字5306为标准编号,2005则是该标准发布的时间。这一标准针对的是无公害食用植物油的生产、加工、检验和销售等环节,旨在规范无公害食用植物油的质量,确保消费者能购买到安全、健康的食品。 从描述中可以了解到,这份文档作为参考资料具有一定的专业性,它能够帮助相关从业人员或研究者深入了解无公害食用植物油的生产与质量控制要求。这类标准文件通常包含无公害食用植物油的定义、分类、技术要求、检验规则、标识、包装、运输、贮存等内容。 虽然没有具体的标签信息提供,但我们可以根据标题和描述推断出文档内容可能涉及以下几个方面: 1. 无公害食品的定义:无公害食品是指在生产、加工过程中不使用国家禁止的高毒高残留农药、兽药、渔药、生长调节剂、添加剂,不使用放射性物质、重金属元素、激素等有害物质,达到安全质量要求的食品。 2. 食用植物油的种类:食用植物油通常包括但不限于大豆油、菜籽油、花生油、玉米油、橄榄油、葵花籽油等多种植物油。 3. 无公害食用植物油的技术要求:这部分内容会详细规定无公害食用植物油的理化指标、卫生指标等,如酸价、过氧化值、色泽、透明度、水分及挥发物含量、杂质等,以及重金属和有机污染物(如黄曲霉毒素、农药残留等)的限量要求。 4. 生产与加工过程的控制:为了确保食用植物油达到无公害标准,文档会描述生产过程中的关键技术点和控制措施,例如原料的来源与质量控制、生产过程中的清洁卫生要求、加工设备与操作人员的卫生要求等。 5. 检验规则:包括产品出厂前必须进行的质量检验项目和方法,以及检验规则和标准,确保产品符合无公害食品的标准。 6. 标识、包装、运输和贮存:标准会规定无公害食用植物油的标签信息,如产地、生产日期、保质期、净含量、生产批号等;包装材料应符合食品安全要求,防止油品在运输和贮存过程中受到污染或变质。 7. 监督管理:文档可能会提及无公害食用植物油产品的监督管理机制,包括监督管理部门、检查制度以及违规后的处罚措施,以确保标准的执行力度。 由于文件是PDF格式,意味着它很可能是可打印的正式文档,适合存档备查,且通常会在文字中包含大量的表格、图表和专业术语,方便读者理解和参照执行。 鉴于以上分析,对于感兴趣的读者来说,这份文档能够作为学习和工作中的重要参考资料,帮助掌握无公害食用植物油的生产和质量控制要求,确保相关产品的安全和卫生。由于文档下载自“www.glzy8.com管理资源吧”,读者需要注意检查该网站的合法性和文档的最新版本,以确保获取的信息是准确和可靠的。
recommend-type

机器学习模型训练与高效预测API构建

### 机器学习模型训练与高效预测 API 构建 #### 1. 支持向量机(SVM)基础 在简单的分类问题中,我们希望将样本分为两个类别。直观上,对于一些随机生成的数据,找到一条直线来清晰地分隔这两个类别似乎很简单,但实际上有很多不同的解决方案。 SVM 的做法是在每个可能的分类器周围绘制一个边界,直到最近的点。最大化这个边界的分类器将被选作我们的模型。与边界接触的两个样本就是支持向量。 在现实世界中,数据往往不是线性可分的。为了解决这个问题,SVM 通过对数据应用核函数将数据集投影到更高的维度。核函数可以计算每对点之间的相似度,在新的维度中,相似的点靠近,不相似的点远离。例如,径向基
recommend-type

层流预混火焰形状计算

<think>嗯,我现在需要了解层流预混火焰形状的计算方法。首先,我应该回忆一下层流预混火焰的基本概念。层流预混火焰是指燃料和氧化剂在燃烧前已经均匀混合,并且流动状态为层流的火焰。这种火焰通常呈现锥形,比如本生灯火焰。那火焰形状的计算可能涉及到哪些因素呢? 首先想到的是火焰传播速度,也就是层流燃烧速度,这可能是一个关键参数。火焰的形状应该与燃烧速度和气流速度之间的平衡有关。如果气流速度在某个位置等于燃烧速度,火焰可能会稳定在那里。这可能涉及到质量守恒或者动量守恒的方程? 然后,可能需要考虑火焰面的几何形状。比如,本生灯的火焰是锥形的,锥顶的高度可能与气流速度和燃烧速度有关。锥形的表面积可能
recommend-type

小墨机器人HDT-Robot-003获取Root权限的完整教程

标题所提到的"小墨机器人HDT-Robot-003-Root.rar"暗示了一项与小墨机器人HDT-Robot-003型号相关的Root操作包。Root通常指的是获取设备的最高权限,即超级用户权限,这通常用于Android设备。在这个过程中,用户通常能够对设备进行更深层次的自定义和优化。这个压缩包可能包含了进行Root操作所需的各种工具、驱动程序以及烧写工具。 描述中的"小墨机器人HDT-Robot-003的Root教程"则说明了这个压缩包内含有具体的教程指导文件,用于指导用户如何对小墨机器人HDT-Robot-003型号的设备进行Root操作。教程内容可能包括步骤说明、注意事项以及可能出现的问题解决方法等。 【标签】中提到了"Root"、"小墨机器人"、"RK3128"以及"安卓5.1.1"。标签"Root"已经解释过,是获取设备最高权限的行为。"小墨机器人"则是一个特定品牌的机器人产品,该产品采用的处理器是"RK3128",这是一款四核处理器,被广泛应用于入门级的智能设备中。"安卓5.1.1"表明小墨机器人HDT-Robot-003运行的是Android系统的一个特定版本,这个版本的系统较为稳定,也是众多设备常用的系统版本。 【压缩包子文件的文件名称列表】中列出了"Root方法"、"驱动"以及"镜像烧写工具"。这些文件名揭示了Root包中所包含的内容: - "Root方法"可能是一个文本文件、PDF文档或是一个网页链接,里面详细介绍了获取Root权限的步骤、方法和相关原理。 - "驱动"指的可能是设备的USB驱动程序,因为进行Root操作需要电脑与设备通过USB连接,而这通常需要正确的驱动支持。这些驱动程序文件允许电脑识别连接的机器人设备,以便进行后续操作。 - "镜像烧写工具"指的是用于将新的系统镜像文件写入设备存储的工具,这通常在Root过程中需要,因为替换系统文件或刷入自定义ROM需要先烧写系统镜像。 为了完成Root操作,用户通常需要按照以下步骤进行: 1. 开启设备的开发者选项,并启用USB调试。这一步骤允许设备在连接电脑时允许从电脑上运行的程序对其系统文件进行操作。 2. 下载并安装适当的USB驱动程序。这个驱动能够保证设备能够被电脑正确识别,从而进行后续的操作。 3. 获取并安装烧写工具。这个工具通常是用来将更新的系统镜像文件写入到设备存储中的。 4. 下载_root方法_,并仔细阅读其中提供的指南。这一步骤非常重要,因为用户需要了解每一步操作的原因和后果,以及每一步的具体操作方法。 5. 根据教程的指导进行Root操作。这个过程可能涉及到连接设备到电脑、使用命令行窗口、通过ADB(Android Debug Bridge)工具发送指令以及执行某些系统更新。 需要注意的是,Root操作有可能使设备失去保修,或者由于操作不当导致设备损坏。因此,进行Root操作前,用户应该充分了解其风险并严格按照教程指导进行。此外,用户在Root之前应确保数据备份,以防不测。 此外,"小墨机器人HDT-Robot-003"这一型号,虽然在标签中提到,但是由于市场或搜索信息的局限性,可能并没过多公开信息,因此在进行Root操作之前,了解该型号的特定信息和特点也是十分重要的,它有助于评估该设备是否适合进行Root操作,并有助于在操作过程中更准确地进行问题判断和解决。
recommend-type

基于WebSocket和FastAPI实现实时人脸检测系统

# 基于 WebSocket 和 FastAPI 实现实时人脸检测系统 ## 1. WebSocket 实现与图像流发送 ### 1.1 WebSocket 实现特点 WebSocket 的实现与之前有所不同,这里不希望两个任务并发执行,而是希望接收新图像并在图像传入时持续进行检测。`detect` 函数有自己的无限循环,通过 `create_task` 将其安排在事件循环中,使其开始处理队列中的图像。同时有常规的 WebSocket 循环调用 `receive` 函数,`detect` 可看作在“后台”运行,并且确保在 WebSocket 关闭时取消该任务,以正确停止无限循环。 ###