Java二次开发海康SDK-对接门禁机

news2025/7/10 14:43:23

写在最前

SDK版本:CH-HCNetSDKV6.1.6.45_build20210302_win64

参考文档:海康SDK使用手册_V6.1

对接测试设备型号:DS-K1T671M

设备序列号:E50247795

业务目标

使用门禁设备实现对人脸的抓拍,将抓拍的人脸与其对应的数据进行上传。

业务流程图:

业务流程节点解释:

1.初始化SDK(NET_DVR_Init):进行海康提供开发库的载入,使用海康官方提供的文件库,进入之后,修改载入路径就可以了。

2.设置报警回调函数(NET_DVR_SetDVRMessageCallBack_V31):初始完SDK之后,进行报警回调函数的设置,当设备进行人脸抓拍之后,上传报警信息到SDK,触发回调函数进行内部业务逻辑处理。对于(门禁设备)人脸侦测,回调函数中的报警类型(lCommand)为COMM_ALARM_ACS,,报警信息(pAlarmInfo)对应结构体:NET_DVR_ACS_ALARM_INFO。

3.用户注册(NET_DVR_Login_V40):填写设备对应的设备参数,进行设备的注册,注册成功会返回一个lUserID,使用这个lUserID进行下面一系列的操作。

4.获取设备能力集(NET_DVR_GetDeviceAbility):能力集类型DEVICE_ABILITY_INFO,获取智能通道分析能力集可以判断设备是否支持相关功能。(可选功能)

5.设置人脸抓拍参数(NET_DVR_SetDVRConfig) (可选功能)

6.获取人脸抓拍参数(NET_DVR_GetDVRConfig) (可选功能)

7.报警布防(NET_DVR_SetupAlarmChan_v41):布防即建立设备跟客户端之间报警上传的连接通道,这样设备发生报警之后通过该连接上传报警信息,SDK在报警回调函数中接收和处理报警信息数据即可。如果设备同时支持人脸侦测和人脸抓拍方式,调用该接口时,NET_DVR_SETUPALARM_PARAM布防参数中byFaceAlarmDetection赋值为0即选择设备上传的报警信息类型为人脸抓拍类型。

注意:在报警布防中需要设置连接的参数,设置不对或没有设置会提示连接设备失败。

8.报警回调函数里面接收和处理数据:报警类型:COMM_ALARM_ACS,报警信息结构体:NET_DVR_ACS_ALARM_INFO。对设备上传来的数据信息进行接收

9.报警撤防(NET_DVR_CloseAlarmChan_v30)

10.注销用户(NET_DVR_logout)

11.释放SDK资源(NET_DVR_Cleanup):关闭连接通道,释放资源。

代码示例

1.首先根据你需要开发的系统去海康官网下载对应的程序包。

比如我的win64

2. 创建好springboot项目,将这个程序包里面的库文件引进去。

3. 将程序包里面它提供的 HCNetSDK.java 复制到你的项目里面,并修改你刚才放的库文件路径,注意以.dll结尾

4. 接下来就是写 demo 测试连接

package com.example.testsdk;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;

/**
 * @author LH
 * @date 2021/11/29 10:37
 */
public class startHCNetAlarm {

    private static final Logger LOGGER = LoggerFactory.getLogger(startHCNetAlarm.class);
    // 载入sdk库文件
    static HCNetSDK hCNetSDK = HCNetSDK.INSTANCE;

    public static void main(String[] args) throws IOException {

        HCNetAlarm hcNetAlarm = new HCNetAlarm();
        // 资源初始化
        int row = hcNetAlarm.initDevice();
        if (row == 1) {
            LOGGER.info("初始化失败");
        }
        
        // 设置连接超时时间与重连功能
        hCNetSDK.NET_DVR_SetConnectTime(2000, 1);
        hCNetSDK.NET_DVR_SetReconnect(10000, true);
        // 设备注册,注册成功返回一个唯一标识符 lUserID,根据这个进行设备的其它操作
        int luserID = hcNetAlarm.deviceRegister(-1, "填你设备的ip地址", "设备用户名", "设备密码", "设备端口,一般默认8000");
        System.out.println(luserID);
        // 设置报警回调函数,建立报警上传通道(启用布防)
        int lAlarmHandle = hcNetAlarm.setupAlarmChan(luserID, -1);
        // 检查设备状态(是否在线),打印设备信息
        hcNetAlarm.onlineState(luserID);
        // 设备抓拍功能,
//      hcNetAlarm.getDVRPic(luserID);
        try {
            // 等待设备上传报警信息
            LOGGER.info("等待设备上传报警信息====================");
            Thread.sleep(100 * 60 * 60);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        
        // 撤销布防上传通道
        hcNetAlarm.closeAlarmChan(lAlarmHandle);
        // 注销 释放sdk资源
        hcNetAlarm.logout(luserID);
        System.out.println("====== 设备注销 ======");
    }
}
package com.example.testsdk;

import com.sun.jna.NativeLong;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.IntByReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;

/**
 * @author LH
 * @date 2021/11/29 9:06
 */
public class HCNetAlarm {

    private static final Logger LOGGER = LoggerFactory.getLogger(HCNetAlarm.class);

    // 载入sdk库文件
    static HCNetSDK hCNetSDK = HCNetSDK.INSTANCE;

    // 设备登录信息
    HCNetSDK.NET_DVR_USER_LOGIN_INFO m_strLoginInfo = new HCNetSDK.NET_DVR_USER_LOGIN_INFO();
    // 设备信息
    HCNetSDK.NET_DVR_DEVICEINFO_V40 m_strDeviceInfo = new HCNetSDK.NET_DVR_DEVICEINFO_V40();
    // 已登录设备的IP
    String m_sDeviceIP;
    // 设备用户名
    String m_sUsername;
    // 设备密码
    String m_sPassword;
    // 报警回调函数实现
    public static HCNetSDK.FMSGCallBack_V31 fMSFCallBack_V31;

    /**
     * sdk初始化
     *
     * @return
     */
    public int initDevice() {
        if (!hCNetSDK.NET_DVR_Init()) {
            // sdk初始化失败
            return 1;
        }
        return 0;
    }

    /**
     * 注销
     *
     * @param lUserID 设备注册成功唯一标识符
     */
    public void logout(int lUserID) {
        // 注销
        hCNetSDK.NET_DVR_Logout(lUserID);
        // 释放sdk资源
        hCNetSDK.NET_DVR_Cleanup();
    }


    /**
     * 设备注册
     *
     * @param ip       设备ip
     * @param name     设备名
     * @param password 设备密码
     */
    public int deviceRegister(int lUserID, String ip, String name, String password, String port) {
        // 设备注册之前先进行判断,注销已注册的设备
        if (lUserID > -1) {
            // 先注销
            hCNetSDK.NET_DVR_Logout(lUserID);
            lUserID = -1;
        }
        // ip地址
        m_sDeviceIP = ip;
        m_strLoginInfo.sDeviceAddress = new byte[HCNetSDK.NET_DVR_DEV_ADDRESS_MAX_LEN];
        System.arraycopy(m_sDeviceIP.getBytes(), 0, m_strLoginInfo.sDeviceAddress, 0, m_sDeviceIP.length());
        // 设备用户名
        m_sUsername = name;
        m_strLoginInfo.sUserName = new byte[HCNetSDK.NET_DVR_LOGIN_USERNAME_MAX_LEN];
        System.arraycopy(m_sUsername.getBytes(), 0, m_strLoginInfo.sUserName, 0, m_sUsername.length());
        // 设备密码
        m_sPassword = password;
        m_strLoginInfo.sPassword = new byte[HCNetSDK.NET_DVR_LOGIN_PASSWD_MAX_LEN];
        System.arraycopy(m_sPassword.getBytes(), 0, m_strLoginInfo.sPassword, 0, m_sPassword.length());
        m_strLoginInfo.wPort = (short) Integer.parseInt(port);
        // 是否异步登录:0 - 否,1 - 是
        m_strLoginInfo.bUseAsynLogin = false;
        m_strLoginInfo.write();
        // 设备注册调用 NET_DVR_Login_V40,注册成功得到唯一标识符 lUserID
        // 设备注册失败,调用 NET_DVR_GetLastError,根据错误号判断错误类型
        lUserID = hCNetSDK.NET_DVR_Login_V40(m_strLoginInfo, m_strDeviceInfo);
        if (lUserID == -1) {
            LOGGER.info("设备注册失败,错误号:", hCNetSDK.NET_DVR_GetLastError());
            return -1;
        } else {
            LOGGER.info("设备注册成功");
            return lUserID;
        }
    }

    /**
     * 设置报警信息回调函数,根据上传的数据进行回调触发
     */
    public class FMSGCallBack_V31 implements HCNetSDK.FMSGCallBack_V31 {
        // lCommand 上传消息类型,这个是设备上传的数据类型,比如现在测试的门禁设备,回传回来的是 COMM_ALARM_ACS = 0x5002; 门禁主机报警信息
        // pAlarmer 报警设备信息
        // pAlarmInfo  报警信息 根据 lCommand 来选择接收的报警信息数据结构
        // dwBufLen 报警信息缓存大小
        // pUser  用户数据
        @Override
        public boolean invoke(int lCommand, HCNetSDK.NET_DVR_ALARMER pAlarmer, Pointer pAlarmInfo, int dwBufLen, Pointer pUser) {
            alarmDataHandle(lCommand, pAlarmer, pAlarmInfo, dwBufLen, pUser);
            return true;
        }
    }


    /**
     * 建立布防上传通道,用于传输数据
     *
     * @param lUserID      唯一标识符
     * @param lAlarmHandle 报警处理器
     */
    public int setupAlarmChan(int lUserID, int lAlarmHandle) {
        // 根据设备注册生成的lUserID建立布防的上传通道,即数据的上传通道
        if (lUserID == -1) {
            LOGGER.info("请先注册");
            return lUserID;
        }
        if (lAlarmHandle < 0) {
            // 设备尚未布防,需要先进行布防
            if (fMSFCallBack_V31 == null) {
                fMSFCallBack_V31 = new FMSGCallBack_V31();
                Pointer pUser = null;
                if (!hCNetSDK.NET_DVR_SetDVRMessageCallBack_V31(fMSFCallBack_V31, pUser)) {
                    LOGGER.info("设置回调函数失败!", hCNetSDK.NET_DVR_GetLastError());
                }
            }
            // 这里需要对设备进行相应的参数设置,不设置或设置错误都会导致设备注册失败
            HCNetSDK.NET_DVR_SETUPALARM_PARAM m_strAlarmInfo = new HCNetSDK.NET_DVR_SETUPALARM_PARAM();
            m_strAlarmInfo.dwSize = m_strAlarmInfo.size();
            // 智能交通布防优先级:0 - 一等级(高),1 - 二等级(中),2 - 三等级(低)
            m_strAlarmInfo.byLevel = 1;
            // 智能交通报警信息上传类型:0 - 老报警信息(NET_DVR_PLATE_RESULT), 1 - 新报警信息(NET_ITS_PLATE_RESULT)
            m_strAlarmInfo.byAlarmInfoType = 1;
            // 布防类型(仅针对门禁主机、人证设备):0 - 客户端布防(会断网续传),1 - 实时布防(只上传实时数据)
            m_strAlarmInfo.byDeployType = 1;
            // 抓拍,这个类型要设置为 0 ,最重要的一点设置
            m_strAlarmInfo.byFaceAlarmDetection = 0;
            m_strAlarmInfo.write();
            // 布防成功,返回布防成功的数据传输通道号
            lAlarmHandle = hCNetSDK.NET_DVR_SetupAlarmChan_V41(lUserID, m_strAlarmInfo);
            if (lAlarmHandle == -1) {
                LOGGER.info("设备布防失败,错误码=========={}", hCNetSDK.NET_DVR_GetLastError());
                // 注销 释放sdk资源
                logout(lUserID);
                return lAlarmHandle;
            } else {
                LOGGER.info("设备布防成功");
                return lAlarmHandle;
            }
        }
        return lAlarmHandle;
    }

    /**
     * 报警撤防
     *
     * @param lAlarmHandle 报警处理器
     */
    public int closeAlarmChan(int lAlarmHandle) {
        if (lAlarmHandle > -1) {
            if (hCNetSDK.NET_DVR_CloseAlarmChan_V30(lAlarmHandle)) {
                LOGGER.info("撤防成功");
                lAlarmHandle = -1;
                return lAlarmHandle;
            }
            return lAlarmHandle;
        }
        return lAlarmHandle;
    }

    /**
     * 接收设备上传的报警信息,进行上传数据的业务逻辑处理
     *
     * @param lCommand   上传消息类型
     * @param pAlarmer   报警设备信息
     * @param pAlarmInfo 报警信息
     * @param dwBufLen   报警信息缓存大小
     * @param pUser      用户数据
     */
    public void alarmDataHandle(int lCommand, HCNetSDK.NET_DVR_ALARMER pAlarmer, Pointer pAlarmInfo, int dwBufLen, Pointer pUser) {
        System.out.println("报警监听中================================");
        System.out.println(pAlarmInfo);

        String sAlarmType = new String();
        String[] newRow = new String[3];
        //报警时间
        Date today = new Date();
        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        String[] sIP = new String[2];

        sAlarmType = new String("lCommand=0x") + Integer.toHexString(lCommand);
        // lCommand是传的报警类型
        switch (lCommand) {
            // 摄像头实时人脸抓拍上传
            case HCNetSDK.COMM_UPLOAD_FACESNAP_RESULT:
                // 分配存储空间
                HCNetSDK.NET_VCA_FACESNAP_RESULT strFaceSnapInfo = new HCNetSDK.NET_VCA_FACESNAP_RESULT();
                strFaceSnapInfo.write();
                Pointer pFaceSnapInfo = strFaceSnapInfo.getPointer();

                // 写入传入数据
                pFaceSnapInfo.write(0, pAlarmInfo.getByteArray(0, strFaceSnapInfo.size()), 0, strFaceSnapInfo.size());
                strFaceSnapInfo.read();
                sAlarmType = sAlarmType + ":人脸抓拍上传[人脸评分:" + strFaceSnapInfo.dwFaceScore + ",年龄:" + strFaceSnapInfo.struFeature.byAge + ",性别:" + strFaceSnapInfo.struFeature.bySex + "]";
                newRow[0] = dateFormat.format(today);
                // 报警类型
                newRow[1] = sAlarmType;
                // 报警设备IP地址
                sIP = new String(strFaceSnapInfo.struDevInfo.struDevIP.sIpV4).split("\0", 2);
                newRow[2] = sIP[0];
                LOGGER.info("人脸抓拍========{}", Arrays.toString(newRow));
                // 设置日期格式
                SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");
                // new Date()为获取当前系统时间
                String time = df.format(new Date());

                // 人脸图片写文件
                File file = new File(System.getProperty("user.dir") + "\\pic1\\");
                if (!file.exists()) {
                    file.mkdir();
                }
                try {
                    FileOutputStream big = new FileOutputStream(System.getProperty("user.dir") + "\\pic1\\" + time + "background.jpg");
                    if (strFaceSnapInfo.dwFacePicLen > 0) {
                        if (strFaceSnapInfo.dwFacePicLen > 0) {
                            try {
                                big.write(strFaceSnapInfo.pBuffer2.getByteArray(0, strFaceSnapInfo.dwBackgroundPicLen), 0, strFaceSnapInfo.dwBackgroundPicLen);
                                big.close();
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                }
                break;
            // 门禁主机类型实时人脸抓拍上传,走这里
            case HCNetSDK.COMM_ALARM_ACS:
                // 分配存储空间
                System.out.println("============ 这是门禁主机的报警信息 ============");
                HCNetSDK.NET_DVR_ACS_ALARM_INFO strFaceSnapInfo1 = new HCNetSDK.NET_DVR_ACS_ALARM_INFO();
                strFaceSnapInfo1.write();
                Pointer pFaceSnapInfo1 = strFaceSnapInfo1.getPointer();

                // 写入传入数据
                pFaceSnapInfo1.write(0, pAlarmInfo.getByteArray(0, strFaceSnapInfo1.size()), 0, strFaceSnapInfo1.size());
                strFaceSnapInfo1.read();
                // 设置日期格式
                SimpleDateFormat df1 = new SimpleDateFormat("yyyyMMddHHmmss");
                // new Date()为获取当前系统时间
                String time1 = df1.format(new Date());

                // 人脸图片写文件
                File file1 = new File(System.getProperty("user.dir") + "\\pic3\\");
                if (!file1.exists()) {
                    file1.mkdir();
                }
                try {
                    FileOutputStream big = new FileOutputStream(System.getProperty("user.dir") + "\\pic3\\" + time1 + ".jpg");
                    if (strFaceSnapInfo1.dwPicDataLen > 0) {
                        System.out.println("========== 图片有数据  ========");
                        if (strFaceSnapInfo1.dwPicDataLen > 0) {
                            try {
                                System.out.println("============ 图片上传成功 =============");
                                big.write(strFaceSnapInfo1.pPicData.getByteArray(0, strFaceSnapInfo1.dwPicDataLen), 0, strFaceSnapInfo1.dwPicDataLen);
                                big.close();
                                System.out.println("设备唯一编码=================" + strFaceSnapInfo1.struAcsEventInfo.byDeviceNo);
                                System.out.println("数据采集时间=================" + strFaceSnapInfo1.struTime.dwYear + strFaceSnapInfo1.struTime.dwMonth + strFaceSnapInfo1.struTime.dwDay + strFaceSnapInfo1.struTime.dwHour + strFaceSnapInfo1.struTime.dwMinute + strFaceSnapInfo1.struTime.dwSecond);
                                System.out.println("人员工号=================" + strFaceSnapInfo1.struAcsEventInfo.dwEmployeeNo);
                                System.out.println("人员姓名=================" + strFaceSnapInfo1.sNetUser);
                                System.out.println("通进类型(0:入场,1:离场)=================" + strFaceSnapInfo1.struAcsEventInfo.dwDoorNo);
                                System.out.println("图片唯一标识(工号加时间)=================" + strFaceSnapInfo1.struAcsEventInfo.dwEmployeeNo + time1 + ".jpg");
                                System.out.println("人员类型(0:白名单,1:访客,2:黑名单)=================" + strFaceSnapInfo1.struAcsEventInfo.byCardType);
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                }
                break;
            default:
                newRow[0] = dateFormat.format(today);
                // 报警类型
                newRow[1] = sAlarmType;
                // 报警设备IP地址
                sIP = new String(pAlarmer.sDeviceIP).split("\0", 2);
                newRow[2] = sIP[0];
                LOGGER.info("其他报警信息=========={}", Arrays.toString(newRow));
                break;
        }
    }

    // 抓拍图片
    public static void getDVRPic(int userId) throws IOException {
        // 设置通道号,其中 1 正常,-1不正常
        NativeLong chanLong = new NativeLong(1);
        // 返回Boolean值,判断是否获取设备能力
        HCNetSDK.NET_DVR_WORKSTATE_V30 devwork = new HCNetSDK.NET_DVR_WORKSTATE_V30();
        if (!hCNetSDK.NET_DVR_GetDVRWorkState_V30(userId, devwork)) {
            System.out.println("返回设备状态失败");
        }
        // JPEG图像信息结构体
        HCNetSDK.NET_DVR_JPEGPARA jpeg = new HCNetSDK.NET_DVR_JPEGPARA();
        jpeg.wPicSize = 2; // 设置图片的分辨率
        jpeg.wPicQuality = 2; // 设置图片质量
        IntByReference a = new IntByReference();
        SimpleDateFormat sdf = new SimpleDateFormat("yyMMddHHmmss");
        Date date = new Date();
        int random = (int) (Math.random() * 1000);
        String fileNameString = sdf.format(date) + random + ".jpg";
        // 设置字节缓存
        ByteBuffer jpegBuffer = ByteBuffer.allocate(1024 * 1024);
        // 抓图到文件
        boolean is = hCNetSDK.NET_DVR_CaptureJPEGPicture(userId, chanLong.intValue(), jpeg, fileNameString);
        if (is) {
            System.out.println("图片抓取成功,返回长度:" + a.getValue());
        } else {
            System.out.println("图片抓取失败:" + hCNetSDK.NET_DVR_GetLastError());

        }
    }

    /**
     * 设备状态,是否在线,打印设备信息
     */
    public Boolean onlineState(int lUserID) {
        HCNetAlarm hcNetAlarm = new HCNetAlarm();
        int row = hcNetAlarm.initDevice();
        if (row == 1) {
            LOGGER.info("初始化失败");
        }
        // 检查设备在线状态
        LOGGER.info("设备信息========={}", hcNetAlarm.m_strDeviceInfo.struDeviceV30);
        boolean isOnLine = hCNetSDK.NET_DVR_RemoteControl(lUserID, 20005, null, 0);
        LOGGER.info("checkDeviceOnLine---isOnLine============{}", isOnLine);
        return isOnLine;
    }
}

写在结尾

遇到的问题:无法上传图片。(官方文档有点坑)

可能原因:刚开始以为是设备不支持抓拍功能。

解决方式:一遍一遍地阅读官方文档,换了一个又一个接口,最后发现,官方文档上提示的抓拍功能流程图是基于海康摄像头的,但是我使用的设备是海康的门禁设备,两者虽然大体相似,但是还是有不同之处,对于不同的设备需要进行不同的判断。

如这次使用的设备是门禁设备,首先根据触发回调返回的lCommand 进行设备区分,本次测试返回的 lCommand = 0x5002, 即门禁主机报警信息,然后去官方文档上查看对应的sdk接收信息体,为NET_DVR_ACS_ALARM_INFO。这样才能正确接收设备传过来的数据,也能得到上传的图片及其对应的人员信息。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/407225.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

用Pytorch构建一个喵咪识别模型

本文参加新星计划人工智能(Pytorch)赛道&#xff1a;https://bbs.csdn.net/topics/613989052 目录 一、前言 二、问题阐述及理论流程 2.1问题阐述 2.2猫咪图片识别原理 三、用PyTorch 实现 3.1PyTorch介绍 3.2PyTorch 构建模型的五要素 3.3PyTorch 实现的步骤 3.3.…

重新学习Vue,了解一下Vue的故事和核心特点

vueVue的由来Vue是什么1.响应的数据绑定2.可组合视图组件3.虚拟DOM4.MVVM模式5.声明式渲染总结Vue的由来 大家应该都知道VUE是尤大大尤雨溪开发出来的&#xff0c;尤大大专业不是计算机&#xff0c;而是室内艺术专业。后来尤大大到帕森斯设计学院进修艺术研究硕士学位&#xf…

猿创征文|【HTML】标签学习之路

&#x1f496;目录 一、HTML语法规范 1.基本语法概述 2.标签关系 二、HTML基本结构标签 1.第一个HTML页面 2.HTML基本结构标签总结 一、HTML语法规范 1.基本语法概述 html是由尖括号包围的关键词&#xff0c;列如&#xff1a;<html>。html标签通常是成对出现的&a…

前端微信小程序开发基础

文章参考&#xff08;黑马小程序教学视频&#xff09;仅供参考与学习 简介 小程序和普通页面开发的区别 运行环境不同 网页运行在浏览器中&#xff0c;小程序运行在微信环境中 API不同 由于运行环境不同&#xff0c;所以小程序中&#xff0c;无法调用DOM和BOM的API. 但是…

如何使用 CSS 使表格居中(快速指南)

在网页设计中使用表格有一段有趣的历史。在采用 CSS 之前&#xff0c;表格不仅仅用于以传统方式显示表格数据练习列表&#xff0c;而是更常用于控制完整的页面布局。 那时&#xff0c;HTML 表格用于定义网页的结构和视觉外观&#xff0c;其中表格的位置可以直接在 HTML 中指定…

input详解之文件上传

input 全部类型 常用的并且能为大多数浏览器所识别的类型大概有&#xff1a;text、password、number、button、reset、submit、hidden、radio、checkbox、file、image、color、range、date、month、week、time、datetime-local。 1、一般类型 <!-- text类型 文本框 默认…

Vue2 Element DatePicker组件设置默认日期、控制日期范围

文章目录前言一、设置默认日期1.不要用placeholder2.设置动态的默认日期二、限制日期选取1.方案2.举例总结前言 以前都是做练习, 上周拿到这个任务直接被卡住… 一、设置默认日期 1.不要用placeholder 依然不使用placeholder属性, 在v-model初始就绑定了时间的情况下, 组件可…

vue导入处理Excel表格详解

目录1. 前言2.vue导入Excel表格2.1 使用ElementUI中的upload组件2.2 使用input文件上传3. 总体代码与效果4. 总结1. 前言 最近遇到前端导入并处理excel表格的情况&#xff0c;趁此机会刚好研究一下vue导入并处理excel数据&#xff1b;当然自己手撸一个工具没有那么多时间&#…

vue3 使用tinymce编辑器实现单/多图片上传,附件上传,视频上传

安装: 我用的是tinymce最新版本v6 npm install tinymce -S npm install tinymce/tinymce-vue -S 2.安装语言包:Language Packages | Trusted Rich Text Editor | TinyMCE 3.在项目public文件夹下--新建tinymce文件夹,安装包解压在该文件夹下 封装组件TEditor.vue <templa…

微信小程序实现上拉加载下拉刷新(即粘即用)

前言 去年有出过一篇关于 vue 实现上拉加载下拉刷新的功能&#xff0c;最近微信小程序中也用到了这个功能&#xff0c;下面一起来看看微信小程序中是怎么实现这个小功能的吧。 实现效果如下&#xff1a; 实现思路&#xff1a; 1. 首先需要在使用到的 json 文件下配置 "ena…

vue项目遇见事件冒泡如何处理

开发环境 Win 10 element-ui "2.8.2" Vue 2.9.6 事件冒泡简介 如下图&#xff0c;当我们点击页面某个元素时&#xff0c;会产生点击事件&#xff0c;事件由外到内&#xff0c;逐层递进&#xff08;事件捕获阶段&#xff0c;途中的1->2->3->4&#xff09…

DVWA靶场搭建

1.靶场是什么&#xff0c;靶场的搭建 在学习web安全的过程中&#xff0c;靶场是必不可少的&#xff0c;毕竟在计算机界&#xff0c;任何理论知识都不如实操 靶场就是人为提供的带有安全漏洞的服务&#xff0c;每一个学习者都可以在本地快速搭建来实操&#xff0c;回溯漏洞的发…

超好玩的js页面效果---实现数值的动态变化

✅ 作者简介&#xff1a;一名普通本科大三的学生&#xff0c;致力于提高前端开发能力 ✨ 个人主页&#xff1a;前端小白在前进的主页 &#x1f525; 系列专栏 &#xff1a; node.js学习专栏 ⭐️ 个人社区 : 个人交流社区 &#x1f340; 学习格言: ☀️ 打不倒你的会使你更强&a…

JS实战——轮播图

目录 一、轮播图介绍 二、原理 三、轮播图基本htm布局 四、轮播图CSS布局 五、轮播图JS布局 六、轮播图效果 一、轮播图介绍 现在我们在很多网站上都能看到轮播图&#xff0c;像某东、某宝、某猫等等大小型网站上都有应用。下面就是某宝上的轮播图样式。 二、原理 将一些图…

【chatgpt谈前端三大主流框架】React、Vue和Angular的优缺点及如何选择

文章目录React优点缺点Vue优点缺点Angular优点缺点总结chatgpt号称无所不能&#xff0c;今天我们就来考考他&#xff0c;让他来对比下React、Vue和Angular。下面是chatgpt全部回答&#xff0c;大家觉得他分析得对吗&#xff1f;React、Vue和Angular都是目前最流行的前端框架&am…

【vue2】使用elementUI进行表单验证实操(附源码)

&#x1f973;博 主&#xff1a;初映CY的前说(前端领域) &#x1f31e;个人信条&#xff1a;想要变成得到&#xff0c;中间还有做到&#xff01; &#x1f918;本文核心&#xff1a;vue使用elementUI进行表单验证实操&#xff08;附源码&#xff09; 【前言】我们在构建一…

VUE 使用 vue create 命令 创建 vue2.0 项目

为了保证创建过程中避免出现因权限不足的原因 从而 导致创建失败的问题&#xff0c;我们使用 管理员身份 打开命令行 第一步&#xff0c;打开命令行后&#xff0c;首先进入我们想要创建项目的目录下 g: 表示切换进入G盘 cd git 表示打开 当前盘下的 git 文件夹 大家可以根据以上…

如何解决 npm 安装依赖报错 ERESOLVE unable to resolve dependency tree

现代前端项目开发中依赖管理已经是不可或缺的一环&#xff0c;然后由于各种问题&#xff0c;如历史原因、项目缺少维护等&#xff0c;前端项目在依赖管理中会遇到非常多的问题。本篇文章讨论其中一种&#xff0c;当 npm install 时遇到报错 ERESOLVE unable to resolve depende…

百度文心一言对标 ChatGPT,你怎么看?

文心一言 VS ChatGPT接受不完美 期待进步里程碑意义文心一言初体验✔ 文学创作✔ 商业文案创作✔ 数理逻辑推算✔ 中文理解✔ 多模态生成写在最后何为文心&#xff1f;“文”就是我们中华语言文字中的文&#xff0c;“心”是希望该语言模型可以用心的去理解语言&#xff0c;用心…

手把手教你基于HTML、CSS搭建我的相册(上)

The sand accumulates to form a pagoda写在前面HTML是什么&#xff1f;CSS是什么&#xff1f;demo搭建写在最后写在前面 其实有过一些粉丝咨询前端该从什么开始学&#xff0c;那当然是我们的前端基础三件套开始学起&#xff0c;HTML、CSS、javaScript&#xff0c;前端的大部分…