当前位置:首页 > 技术文章 > 正文内容

(在线编辑DWG)网页CAD二开实现焊接符号绘制

zonemu5小时前技术文章1

前言

在工程制图和制造领域,焊接符号(Welding Symbols)是用于表示焊缝类型、尺寸、位置以及工艺要求的标准化图形语言。广泛应用于机械设计、钢结构、船舶制造、压力容器等行业中,帮助技术人员理解焊接意图。

本文将介绍焊接符号的基本结构、符号、含义,并根据焊接符号的特性通过网页CAD实现焊接符号类,实现绘制焊接符号的功能。

焊接符号特性分析

一、焊接符号的基本构成

焊接符号由以下几个基本部分组成:

1.参考线:焊接符号的核心部分,通常是一条水平线,所有其他符号都依附于这条线。参考线分为两部分,箭头上面就是上方区域,箭头下面就是下方区域,如下图:

2.箭头:箭头指向要焊接的位置,连接参考线和被焊件的具体部位。

3.基本焊接符号:表示焊缝的类型,如角焊缝、对接焊缝等,绘制在参考线的上方或下方。

4.尾部:可选部分,用于标注焊接方法、工艺编号或其他说明信息(如“GTAW”、“SMAW”等)。

5.补充符号:包括现场焊缝符号、周围焊缝符号、熔透深度符号等。

6. 尺寸标注:表示焊缝的具体尺寸,如焊脚高度、坡口角度、根部间隙等。


二、焊接符号的附加元素

1.现场焊缝符号:一个小旗子标志,表示该焊缝需在现场施工时完成,而非在工厂内完成。

2.周围焊缝符号:一个圆圈,表示焊缝应围绕整个接合处进行。

3.熔透符号:表示焊接过程中需要完全熔透母材。

4.打底焊道符号:表示打底焊或衬垫焊。


三、焊接尺寸标注方法

焊接符号中常常包含尺寸信息,以指导焊工操作。以下是常见尺寸标注方式:

3.1.角焊缝尺寸标注

-焊脚尺寸(Leg Size):用数字标注在焊缝符号左侧。

-长度:标注在符号右侧。

-间距(Pitch):标注在长度之后,斜杠后加数字。例如:6/25 表示每25mm间距有一个6mm的角焊缝。

3.2.对接焊缝尺寸标注

-坡口角度:标注在符号旁边。

-根部间隙:标注在角度下方。

-钝边厚度:标注在角度另一侧


实现 McDbTestWeldingSymbol 焊接符号自定义实体

1. 定义符号相关的枚举或接口

 // 符号位置
   enum symbolPos {
       top = 1,
       down
   }
   // 符号名
   enum symbolName {
       // 带垫板符号
       WithPadSymbol,
       // 周围焊接符
       SurroundingWeldSeamSymbol,
       // 现场符号
       OnSiteSymbol,
       // 三面焊缝符号
       ThreeSidedWeldSeamSymbol,
       // 尾部符号
       TailSymbol,
       // 交错断续焊接符号
       ZSymbol,
       // 卷边焊缝
       RolledEdge,
       // I型焊缝
       IWeldSeam,
       // V型焊缝
       VWeldSeam,
       // 单边V型焊缝
       SingleVWeldSeam,
       // 单边陡侧V型坡口堆焊
       SingleSteepVWeldSeam,
       // 倾斜焊缝
       InclinedWeldSeam,
       // 可移除衬垫
       RemovablePadding1,
       RemovablePadding2,
       // 持久衬垫
       DurableLiner,
       // 带顿边V型焊缝
       VFlangedEdgeSeam,
       // 带顿边U型焊缝
       UFlangedEdgeSeam,
       // 带顿边单边V型焊缝
       SingleVFlangedEdgeSeam,
       // 带顿边单边U型焊缝
       SingleUFlangedEdgeSeam,
       // 端接焊缝
       EndWeldSeam,
       // 堆焊接头
       SurfacingJoint,
       // 封底焊缝
       BottomSeamWeld,
       // 角焊缝
       FilletWeld,
       // 塞焊缝或槽焊缝
       GrooveWeldSeam,
       // 点焊缝
       SpotWeldSeam,
       // 折叠接口
       FoldingInterface,
       // 倾斜接口
       InclinedInterface,
       // 点焊缝(偏移中心)
       SpotWeldSeamOffset,
       // 缝焊缝
       SeamWeld,
       // 缝焊缝(偏离中心)
       SeamWeldOffset,
       // 陡侧V型坡口堆焊
       SteepVWeldSeam,
       // 喇叭形焊缝
       BellShapedWeldSeam,
       // 单边喇叭形焊缝
       SingleBellShapedWeldSeam,
       // 堆焊缝
       HeapWeldSeam,
       // 锁边焊缝
       SeamSeam,
       // 锁边坡口
       LockTheSlopeOpening,
       // 第一种平面符号
       FirstPlaneSymbol,
       // 第二种凹面符号
       SecondConcaveSymbol,
       // 第二种凸面符号
       SecondConvexeSymbol,
       // 第二种平面符号
       SecondPlaneSymbol,
       // 第三种平面符号
       ThirdPlaneSymbol,
       // 第一种凸面符号
       FirstConvexeSymbol,
       // 第一种凹面符号
       FirstConcaveSymbol,
       // 削平焊缝
       FlattenWeldSeam,
       // 趾部平滑过渡
       ToeAareaTranSmoothly,
       // 无
       none,
   }
   // 符号类型设置
   interface symbolType {
       typeName: symbolName,
       position?: symbolPos,
       rotation?: number,
       info?: string
   }
   // 符号标注设置
   interface symbolDim {
       position: symbolPos,
       content: string
   }

2. 基本结构设置

  // 焊接符号自定义实体
   export class McDbTestWeldingSymbol extends McDbCustomEntity {
       // 定义McDbTestWeldingSymbol内部的点对象
       // 标记定位点
       private position: McGePoint3d;
       // 标记转折点
       private turningPt: McGePoint3d;
       // 标记定点
       private fixedPoint: McGePoint3d;
       // 箭头长度
       private size: number = 4;
       // 基本符号
       private baseSymbok: symbolType[] = [];
       // 辅助符号
       private auxiliarySymbol: symbolType[] = [];
       // 特殊符号
       private specialSymbol: symbolType[] = [];
       // 补充符号
       private suppleSymbol: symbolType[] = [];
       // 左尺寸
       private leftDim: symbolDim[] = [];
       // 上尺寸
       private topDim: symbolDim[] = [];
       // 右尺寸
       private rightDim: symbolDim[] = [];
       // 虚线位置:0:无虚线, 1:下虚线,2:上虚线
       private dottedPos: number = 0;
       // 标注内字高
       private height: number = this.size * (7 / 8);
       // 焊接说明
       private weldingInfo: string = '';
       // 交错焊缝
       private interlacedWeldSeam: symbolDim[] = [];
   
       /** 包围盒最大点 包围盒最小点 */
       private minPt: McGePoint3d = new McGePoint3d();
       private maxPt: McGePoint3d = new McGePoint3d();
   }

3. 构造函数和创建方法

       // 构造函数
       constructor(imp?: any) {
           super(imp);
       }
       // 创建函数
       public create(imp: any) {
           return new McDbTestWeldingSymbol(imp)
       }
       // 获取类名
       public getTypeName(): string {
           return "McDbTestWeldingSymbol";
       }

4. 数据持久化

 // 读取自定义实体数据pt1、pt2
       public dwgInFields(filter: IMcDbDwgFiler): boolean {
           this.position = filter.readPoint("position").val;
           this.turningPt = filter.readPoint("turningPt").val;
           this.fixedPoint = filter.readPoint("fixedPoint").val;
           this.size = filter.readDouble("size").val;
           this.dottedPos = filter.readLong("dottedPos").val;
           this.minPt = filter.readPoint("minPt").val;
           this.maxPt = filter.readPoint("maxPt").val;
           const _baseSymbok = filter.readString('baseSymbok').val;
           this.baseSymbok = JSON.parse(_baseSymbok)
           const _AuxiliarySymbol = filter.readString('AuxiliarySymbol').val;
           this.auxiliarySymbol = JSON.parse(_AuxiliarySymbol)
           const _specialSymbol = filter.readString('specialSymbol').val;
           this.specialSymbol = JSON.parse(_specialSymbol)
           const _suppleSymbol = filter.readString('suppleSymbol').val;
           this.suppleSymbol = JSON.parse(_suppleSymbol)
           const _leftDim = filter.readString('leftDim').val;
           this.leftDim = JSON.parse(_leftDim);
           const _topDim = filter.readString('topDim').val;
           this.topDim = JSON.parse(_topDim);
           const _rightDim = filter.readString('rightDim').val;
           this.rightDim = JSON.parse(_rightDim);
           const _interlacedWeldSeam = filter.readString('interlacedWeldSeam').val;
           this.interlacedWeldSeam = JSON.parse(_interlacedWeldSeam);
           this.weldingInfo = filter.readString('weldingInfo').val;
           return true;
       }
       // 写入自定义实体数据pt1、pt2
       public dwgOutFields(filter: IMcDbDwgFiler): boolean {
           filter.writePoint("turningPt", this.turningPt);
           filter.writePoint("position", this.position);
           filter.writePoint("fixedPoint", this.fixedPoint);
           filter.writeDouble("size", this.size);
           filter.writeLong("dottedPos", this.dottedPos);
           filter.writePoint("minPt", this.minPt);
           filter.writePoint("maxPt", this.maxPt);
           filter.writeString('baseSymbok', JSON.stringify(this.baseSymbok));
           filter.writeString('AuxiliarySymbol', JSON.stringify(this.auxiliarySymbol));
           filter.writeString('specialSymbol', JSON.stringify(this.specialSymbol));
           filter.writeString('suppleSymbol', JSON.stringify(this.suppleSymbol));
           filter.writeString('leftDim', JSON.stringify(this.leftDim));
           filter.writeString('topDim', JSON.stringify(this.topDim));
           filter.writeString('rightDim', JSON.stringify(this.rightDim));
           filter.writeString('interlacedWeldSeam', JSON.stringify(this.interlacedWeldSeam));
           filter.writeString('weldingInfo', this.weldingInfo);
           return true;
       }

5. 设置标注夹点及夹点移动规则

  // 移动自定义对象的夹点
       public moveGripPointsAt(iIndex: number, dXOffset: number, dYOffset: number, dZOffset: number) {
           this.assertWrite();
           if (iIndex === 0) {
               this.position.x += dXOffset;
               this.position.y += dYOffset;
               this.position.z += dZOffset;
           } else if (iIndex === 1) {
               this.turningPt.x += dXOffset;
               this.turningPt.y += dYOffset;
               this.turningPt.z += dZOffset;
           } else if (iIndex === 2) {
               this.fixedPoint.x += dXOffset;
               this.fixedPoint.y += dYOffset;
               this.fixedPoint.z += dZOffset;
           }
       };
       // 获取自定义对象的夹点
       public getGripPoints(): McGePoint3dArray {
           let ret = new McGePoint3dArray()
           ret.append(this.position);
           ret.append(this.turningPt);
           ret.append(this.fixedPoint);
           return ret;
       };

6. 绘制标注实体

// 绘制实体
       public worldDraw(draw: MxCADWorldDraw): void {
           const allEntityArr = this.getAllEntity();
           allEntityArr.forEach((ent, index) => {
               if(index === allEntityArr.length-1) draw.setupForEntity(ent);
               draw.drawEntity(ent)
           });
       }
       private getAllEntity(): McDbEntity[] {
           const allEntityArr: McDbEntity[] = [];
           const noChangeEntityArr: McDbEntity[] = [];
           // 是否反向
           let isReverse = this.fixedPoint.x < this.position.x ? true : false;
           // 引线结束点
           let lastPt = this.fixedPoint.clone();
           lastPt.addvec(McGeVector3d.kXAxis.clone().mult(this.size * (1 / 8)));
           // 绘制标注线
           const pl = new McDbPolyline();
           pl.addVertexAt(this.position);
           pl.addVertexAt(this.turningPt);
           pl.addVertexAt(this.fixedPoint);
           noChangeEntityArr.push(pl);
           // 绘制标注箭头
           const v = this.turningPoint.sub(this.position).normalize();
           const midPt = this.position.clone().addvec(v.mult(this.size));
           const _v = v.clone().perpVector().mult(this.size * (1 / 8));
           const pt1 = midPt.clone().addvec(_v);
           const pt2 = midPt.clone().addvec(_v.clone().negate());
           const hatch = new McDbHatch();
           hatch.appendLoop(new McGePoint3dArray([pt1, pt2, this.position]));
           noChangeEntityArr.push(hatch);
           // 绘制补充符号
           if (this.suppleSymbol.length) {
               const { entityArr, noChangeArr, v } = this.drawSuppleSymbol(isReverse);
               lastPt.addvec(v);
               allEntityArr.push(...entityArr);
               noChangeEntityArr.push(...noChangeArr);
           }
           // 绘制左尺寸
           if (this.leftDim.length) {
               const { entityArr, v } = this.drawLeftDim(lastPt);
               lastPt.addvec(v);
               allEntityArr.push(...entityArr)
           }
           // 绘制特殊符号
           if (this.specialSymbol.length) {
               const { entityArr } = this.drawSpecialSymbol(lastPt);
               allEntityArr.push(...entityArr);
                  lastPt.addvec(McGeVector3d.kXAxis.clone().mult(this.size / 2))
           }
           if (this.suppleSymbol.length && this.suppleSymbol.filter(item => item.typeName === symbolName.WithPadSymbol).length) {
               const entityArr = this.drawWidth(lastPt);
               allEntityArr.push(...entityArr);
           }
           // 绘制基本符号
           if (this.baseSymbok.length) {
               const { entityArr } = this.drawBasicSymbol(lastPt);
               allEntityArr.push(...entityArr);
           }
           // 绘制辅助符号
           if (this.auxiliarySymbol.length) {
               const { entityArr } = this.drawAuxiliarySymbol(lastPt);
               allEntityArr.push(...entityArr);
           }
           // 绘制上尺寸
           if (this.topDim.length) {
               const { entityArr } = this.drawTopDim(lastPt);
               allEntityArr.push(...entityArr)
           }
           lastPt.addvec(McGeVector3d.kXAxis.clone().mult(this.size * (7 / 4)));
           // 绘制右尺寸
           if (this.rightDim.length) {
               const { entityArr, v } = this.drawRightDim(lastPt);
               lastPt.addvec(v);
               allEntityArr.push(...entityArr)
           }
           lastPt.addvec(McGeVector3d.kXAxis.clone().mult(this.size * (4 / 8)));
           // 绘制交错断续焊接符号
           if (this.suppleSymbol.length && this.suppleSymbol.filter(item => item.typeName === symbolName.ZSymbol).length) {
               if (this.baseSymbok.length || this.suppleSymbol.filter(item => item.typeName === symbolName.WithPadSymbol)) lastPt.addvec(McGeVector3d.kXAxis.clone().mult(this.size / 2));
               const distanceVec = McGeVector3d.kXAxis.clone().mult(this.size * (1 / 16));
               const v_y = McGeVector3d.kYAxis.clone().mult(this.size * (17 / 16));
               const v_x = McGeVector3d.kXAxis.clone().mult(this.height).negate();
               const pt2 = lastPt.clone().addvec(v_y);
               const pt4 = lastPt.clone().addvec(v_y.clone().negate());
               const pt1 = pt2.clone().addvec(v_x);
               const pt3 = pt4.clone().addvec(v_x);
               const pl = new McDbPolyline();
               pl.addVertexAt(pt1);
               pl.addVertexAt(pt2);
               pl.addVertexAt(pt3);
               pl.addVertexAt(pt4);
               allEntityArr.push(pl);
               if (this.interlacedWeldSeam.length) {
                   let maxPt_x = null;
                   this.interlacedWeldSeam.forEach(item => {
                       const text = new McDbMText();
                       text.contents = item.content;
                       text.textHeight = this.height;
                       text.attachment = McDb.AttachmentPoint.kTopLeft;
                       if (item.position === symbolPos.down) {
                           text.location = lastPt.clone().addvec(distanceVec)
                       } else if (item.position === symbolPos.top) {
                           text.location = lastPt.clone().addvec(McGeVector3d.kYAxis.clone().mult(this.size)).addvec(distanceVec)
                       }
                       // 将ent的文字样式设置为当前文字样式
                       const textStyleId = MxCpp.getCurrentMxCAD().getDatabase().getCurrentlyTextStyleId();
                       text.textStyleId = textStyleId;
                       text.reCompute();
                       const { maxPt } = MxCADUtility.getTextEntityBox(text, false);
                       if (!maxPt_x || maxPt_x < maxPt.x) {
                           maxPt_x = maxPt.x;
                       }
                       allEntityArr.push(text);
                   });
                   lastPt.x = maxPt_x;
               }
           }
           // 绘制尾部符号(焊接说明)
           if (this.suppleSymbol.length && this.suppleSymbol.filter(item => item.typeName === symbolName.TailSymbol).length) {
               const vec = this.fixedPoint.sub(lastPt).mult(2);
               const v_y = McGeVector3d.kYAxis.clone().mult(this.height);
               const v_x = isReverse ? McGeVector3d.kXAxis.clone().negate().mult(this.height) : McGeVector3d.kXAxis.clone().mult(this.height);
               const pt1 = lastPt.clone().addvec(v_y).addvec(v_x);
               const pt2 = lastPt.clone().addvec(v_y.clone().negate()).addvec(v_x);
               const pl = new McDbPolyline();
               pl.addVertexAt(pt1)
               pl.addVertexAt(lastPt);
               pl.addVertexAt(pt2);
               if (isReverse) pl.move(lastPt, lastPt.clone().addvec(vec));
               noChangeEntityArr.push(pl)
   此段代码内容太多,请到官网查看

7. 暴露获取、设置实体内部数据的属性或方法

       //设置或获取标记定位点
       public set weldingPosition(val: McGePoint3d) {
           this.position = this.fixedPoint = this.turningPoint = val.clone();
       }
       public get weldingPosition(): McGePoint3d {
           return this.position;
       }
       //设置或获取标记转折点
       public set turningPoint(val: McGePoint3d) {
           this.turningPt = this.fixedPoint = val.clone();
       }
       public get turningPoint(): McGePoint3d {
           return this.turningPt;
       }
       //设置或获取标记定点
       public set fixedPos(val: McGePoint3d) {
           this.fixedPoint = val.clone();
       }
       public get fixedPos(): McGePoint3d {
           return this.fixedPoint;
       }
       //设置或获取标记箭头尺寸
       public set dimSize(val: number) {
           this.size = val;
           this.height = this.size * (7 / 8)
       }
       public get dimSize(): number {
           return this.size;
       }
       //设置或获取虚线位置
       public set dottedLinePos(val: number) {
           this.dottedPos = val;
       }
       public get dottedLinePos(): number {
           return this.dottedPos;
       }
       //设置或获取焊接说明
       public set weldingSymbolInfo(val: string) {
           this.weldingInfo = val;
       }
       public get weldingSymbolInfo(): string {
           return this.weldingInfo;
       }
       private getBox(entityArr: McDbEntity[]) {
           let _minPt, _maxPt = null;
           entityArr.forEach(entity => {
               if (entity instanceof McDbMText) {
                   const textStyleId = MxCpp.getCurrentMxCAD().getDatabase().getCurrentlyTextStyleId();
                   entity.textStyleId = textStyleId;
                   entity.reCompute();
               }
               const { minPt, maxPt } = entity instanceof McDbMText ? MxCADUtility.getTextEntityBox(entity, false) : entity.getBoundingBox();
               if (!_minPt) _minPt = minPt.clone();
               if (!_maxPt) _maxPt = maxPt.clone();
               if (minPt.x < _minPt.x) _minPt.x = minPt.x;
               if (minPt.y < _minPt.y) _minPt.y = minPt.y;
               if (maxPt.x > _maxPt.x) _maxPt.x = maxPt.x;
               if (maxPt.y > _maxPt.y) _maxPt.y = maxPt.y;
           });
           if (_minPt && _maxPt) {
               this.assertWrite();
               this.maxPt = _maxPt;
               this.minPt = _minPt;
           }
       }
       // 获取包围盒
       public getBoundingBox(): { minPt: McGePoint3d; maxPt: McGePoint3d; ret: boolean; } {
           const allEntityArr = this.getAllEntity();
           this.getBox(allEntityArr);
           return { minPt: this.minPt, maxPt: this.maxPt, ret: true }
       }
       //获取或设置基本符号.
       public getBaseSymbok(): symbolType[] {
           return this.baseSymbok
       }
       public setBaseSymbok(val: symbolType[]) {
           const res = val.filter(item => item.typeName !== symbolName.none);
           this.baseSymbok = res;
       }
       //获取或设置辅助符号
       public getAuxiliarySymbol(): symbolType[] {
           return this.auxiliarySymbol
       }
       public setAuxiliarySymbol(val: symbolType[]) {
           const res = val.filter(item => item.typeName !== symbolName.none);
           this.auxiliarySymbol = res;
       }
       //获取或设置特殊符号
       public getSpecialSymbol(): symbolType[] {
           return this.specialSymbol
       }
       public setSpecialSymbol(val: symbolType[]) {
           const res = val.filter(item => item.typeName !== symbolName.none);
           this.specialSymbol = res;
       }
       //获取或设置补充符号
       public getSuppleSymbol(): symbolType[] {
           return this.suppleSymbol
       }
       public setSuppleSymbol(val: symbolType[]) {
           const res = val.filter(item => item.typeName !== symbolName.none);
           this.suppleSymbol = res;
       }
       //获取或设置左尺寸
       public getLeftDim(): symbolDim[] {
           return this.leftDim;
       }
       public setLeftDim(val: symbolDim[]) {
           const res = val.filter(item => item.content !== '');
           this.leftDim = res;
       }
       //获取或设置上尺寸
       public getTopDim(): symbolDim[] {
           return this.topDim;
       }
       public setTopDim(val: symbolDim[]) {
           const res = val.filter(item => item.content !== '');
           this.topDim = res;
       }
       //获取或设置右尺寸
       public getRightDim(): symbolDim[] {
           return this.rightDim;
       }
       public setRightDim(val: symbolDim[]) {
           const res = val.filter(item => item.content !== '');
           this.rightDim = res;
       }
       //获取或设置交错焊缝
       public getIntWeldSeam(): symbolDim[] {
           return this.interlacedWeldSeam
       }
       public setIntWeldSeam(val: symbolDim[]) {
           const res = val.filter(item => item.content !== '');
           this.interlacedWeldSeam = res;
       }


使用焊接符号标注

根据焊接符号标注于直线、圆弧或圆时标注将垂直于曲线的切线上的位置特点,我们可以通过识别标注点所在的实体类型获取该实体在标注点的切线方向和位置,并以此来确定标注的旋转角度和方向。下面为焊接符号标注的基础的用法,用户可在此基础上为焊接符号设置更多属性值,如补充符号、特殊符号、上下标注等:

let isArc = false;
// 设置标记位置点
const getPos = new MxCADUiPrPoint();
getPos.setMessage('请设置定位点或直线或圆弧');
const pos = await getPos.go();
if (!pos) return;
weldingSymbol.weldingPosition = pos;
// 定义过滤器
const filter = new MxCADResbuf()
// 添加对象类型,选择集只选择文字类型的对象
filter.AddMcDbEntityTypes("ARC,CIRCLE")
let objId = MxCADUtility.findEntAtPoint(pos.x, pos.y,pos.z,-1,filter);
if(objId.isValid()) isArc = true;
// 设置标记转折点
const getTurnPt = new MxCADUiPrPoint();
getTurnPt.setMessage('请设置引线转折点');
getTurnPt.setUserDraw((pt, pw) => {
    if(isArc){
        const arc = objId.getMcDbEntity() as McDbArc;
        const point = arc.getClosestPointTo(pt, true).val;
        weldingSymbol.weldingPosition = point;
    };
    weldingSymbol.turningPoint = pt;
    pw.drawMcDbEntity(weldingSymbol);
});
const turningPt = await getTurnPt.go();
if (!turningPt) return;
weldingSymbol.turningPoint = turningPt;
 
// 设置标记定点
const getFixedPt = new MxCADUiPrPoint();
getFixedPt.setMessage('拖动确定定位点');
getFixedPt.setUserDraw((pt, pw) => {
    const clone = weldingSymbol.clone() as McDbTestWeldingSymbol;
    clone.fixedPos = pt;
    pw.drawMcDbEntity(clone)
});
const fixedPt = await getFixedPt.go();
if (fixedPt) weldingSymbol.fixedPos = fixedPt;
const mxcad = MxCpp.getCurrentMxCAD();
mxcad.drawEntity(weldingSymbol);

效果演示

在上述介绍中,我们已经实现了焊接符号的自定义实体,通过该实体与我们的mxcad项目结合,我们就能够实现更完善的焊接符号标注功能。

基础效果演示:

根据上述内容可做扩展开发,根据焊接符号特性设置对应的弹框,其示例效果如下:

相关文章

财务主管花了一周时间自制费用报销管理系统,是我见过最好用的

公司的费用报销又多又乱,一不小心就出错!头疼,财务主管花了一周时间自制费用报销管理台账,分类统计,重复报销还能自动提醒,真的少了很多麻烦!费用报销是财务日常工作必会面对的,各种票据太多太乱,搞的很烦,...

2024年10 大 Linux 桌面发行版推荐

年已过半,现在是探究 2024 年最流行的 Linux 发行版的最佳时机。Linux 是一个开源操作系统,构建在 Linux 内核上,并集成了 GNU shell 实用程序、桌面环境、应用程序、包管理...

Ubuntu 24.10发行版登场:Linux 6.11内核、GNOME 47桌面环境

IT之家 10 月 11 日消息,Canonical 昨日发布新闻稿,正式推出代号为 Oracular Oriole 的 Ubuntu 24.10 发行版。新版在内核方面升级到最新 6.11 版本,并...

微软的Linux发行版终于加入了对XFS根文件系统的支持

当许多Linux发行版在评估新的根文件系统选项或甚至像OpenZFS这样的特性,微软内部Linux发行版到本月才开始支持XFS作为根文件系统选项。随着这个月对微软内部Linux发行版CBL-Marin...

Linux发行版Nobara更新39版本,号称“专为游戏玩家定制”

IT之家 12 月 27 日消息,Linux 发行版 Nobara 今天推出了 39 版本,主要改进了“Gamescope 合成器”,并更新了 OBS Studio、部分驱动程序及 Nautilus...

Win+Ubuntu缝合怪:第三方开发者推出“Wubuntu”Linux发行版

IT之家 2 月 26 日消息,一位第三方开发者推出了一款名为“Wubuntu”的缝合怪 Linux 发行版,系统本身基于 Ubuntu,但界面为微软 Windows 11 风格,甚至存在微软 Win...