ezuikit-js官网使用示例

ezuikit-js 的api https://open.ys7.com/help/4275

获取url的接口 https://open.ezviz.com/help/1414

获取accessToken的接口 https://open.ezviz.com/help/81

官网给的常见问题及解决 https://open.ys7.com/help/4292

github地址 https://github.com/Ezviz-OpenBiz/EZUIKit-JavaScript-npm


版本8.2.0这么引入启动项目编译不会报错 import { EZUIKitPlayer } from 'ezuikit-js/ezuikit.js'

不这么引入的话 需要修改vue.config.js,加入代码

javascript 复制代码
transpileDependencies: ['ezuikit'], // 强制转译 ESM 模块

chainWebpack: config => {
	config.module
		.rule('mjs')
		.test(/\.mjs$/)
		.include.add(/node_modules/)
		.end()
		.type('javascript/auto') // 强制解析为 JavaScript
		.use('babel-loader')
		.loader('babel-loader')
		.options({
			presets: ['@babel/preset-env'] // 转译 ESM 为 CommonJS
		})
	}

提取代码

https://github.com/Ezviz-OpenBiz/EZUIKit-JavaScript-npm/blob/master/demos/vue-demo/src/components/Player.vue

官网的代码示例vue2版

https://github.com/Ezviz-OpenBiz/EZUIKit-JavaScript-npm

html 复制代码
<template>
  <div class="player-box">
    <div>
      <div id="video-container" style="height: 400px"></div>
      <div style="display: flex; justify-content: center;">
        <div style="width: 500px; display: flex; flex-direction: column;">
          <div style="display: flex;">url: <input placeholder="url" :value="url" style="width: 450px;" @input="event => url = event.target.value"/></div>
          <div style="display: flex;">accessToken: <input placeholder="accessToken" :value="accessToken" style="width: 450px;" @input="event => accessToken = event.target.value"/></div>
          <div style="display: flex;">template: <input placeholder="template" :value="template" style="width: 450px;" @input="event => template = event.target.value"/></div>
          <div style="display: flex;">width: <input placeholder="width" :value="width" style="width: 450px;" @input="event => width = event.target.value"/></div>
          <div style="display: flex;">height: <input placeholder="height" :value="height" style="width: 450px;" @input="event => height = event.target.value"/></div>
          <div style="display: flex;">staticPath: <input placeholder="staticPath" :value="staticPath" style="width: 450px;" @input="event => staticPath = event.target.value"/></div>
        </div>
      </div>
    </div>
    <div>
      <button v-on:click="init">init</button>
      <button v-on:click="stop">stop</button>
      <button v-on:click="play">play</button>
      <button v-on:click="openSound">openSound</button>
      <button v-on:click="closeSound">closeSound</button>
      <button v-on:click="startSave">startSave</button>
      <button v-on:click="stopSave">stopSave</button>
      <button v-on:click="capturePicture">capturePicture</button>
      <button v-on:click="fullscreen">fullscreen</button>
      <button v-on:click="getOSDTime">getOSDTime</button>
      <button v-on:click="startTalk">startTalk</button>
      <button v-on:click="stopTalk">stopTalk</button>
      <button v-on:click="destroy">destroy</button>
    </div>
  </div>
</template>

<script>
import { EZUIKitPlayer } from "ezuikit-js";
var player = null;

export default {
  name: "Player",
  props: {
    msg: String,
  },
  data() {
    return {
      url: "ezopen://open.ys7.com/BC7799091/1.live",
      accessToken: "at.9uoaxo0k3e5dinq8bretm18e5l37k1l6-26lx1qcvcc-1neesaz-kh9hqvqc3",
      template: "pcLive",
      width: "100%",
      height: 400,
      staticPath: "",
    };
  },
  mounted: () => {
    console.group("mounted 组件挂载完毕状态===============》");
  },
  methods: {
    init() {
      if (player) {
        this.destroy();
      }

      // fetch("https://open.ys7.com/jssdk/ezopen/demo/token")
      //   .then((response) => response.json())
      //   .then((res) => {
      //     var accessToken = res.data.accessToken;
      //   });
      player = new EZUIKitPlayer({
        id: "video-container", // 视频容器ID
        accessToken: this.accessToken,
        url: this.url,
        // simple: 极简版; pcLive: pc直播; pcRec: pc回放; mobileLive: 移动端直播; mobileRec: 移动端回放; security: 安防版; voice: 语音版;
        template: this.template, // 视频模板
        width: this.width,
        height: this.height,
        handleError: (error) => {
          console.error("handleError", error);
        },
        // quality: 1, // 
        // language: "en", // zh | en
        staticPath: this.staticPath, // 如果想使用本地静态资源,请复制根目录下ezuikit_static 到当前目录下, 然后设置该值
        scaleMode: 1, // 默认 0 完全填充窗口,会有拉伸 1: 等比适配 2: 等比完全填充窗口, 超出隐藏 @sine 8.2.0
        env: {
          // https://open.ys7.com/help/1772?h=domain
          // domain默认是 https://open.ys7.com, 如果是私有化部署或海外的环境,请配置对应的domain
          // The default domain is https://open.ys7.com If it is a private deployment or overseas (outside of China) environment, please configure the corresponding domain
          domain: "https://open.ys7.com",
        },
        // staticPath:"https://openstatic.ys7.com/ezuikit_js/v8.1.9/ezuikit_static",
        // 日志打印设置
        loggerOptions: {
          // player.setLoggerOptions(options)
          level: "INFO", // INFO LOG  WARN  ERROR
          name: "ezuikit",
          showTime: true,
        },
        // 视频流的信息回调类型
        /**
         * 打开流信息回调,监听 streamInfoCB 事件
         * 0 : 每次都回调
         * 1 : 只回调一次
         * 注意:会影响性能
         * 默认值 1
         */
        streamInfoCBType: 1,
        // v8.1.10
        // 自定义清晰度 默认 null, 如果有值 sdk 内部不在进行获取, null 默认使用接口获取的清晰度列表, videoLevelList.length === 0 不展示清晰度控件 sdk 内部不在进行获取, videoLevelList.length > 0 展示控件 sdk 内部不在进行获取
        // videoLevelList: [
        //   { level: 1, name: "标清", streamTypeIn: 2 }, // 需要保证支持子码流 (streamTypeIn=2)
        //   { level: 2, name: "高清", streamTypeIn: 1 },
        // ],
        // videoLevelList: [
        //   { level: -1, name: "标清", streamTypeIn: 2 }, // 8.1.17 开始 当 level 的值小于 0时, 不在向设备发送指令,仅根据 streamTypeIn 切换码流 (请保证 streamTypeIn 对应的码流存在)
        //   { level: -2, name: "高清", streamTypeIn: 1 }, // 8.1.17 开始 当 level 的值小于 0时, 不在向设备发送指令,仅根据 streamTypeIn 切换码流 (请保证 streamTypeIn 对应的码流存在)
        // ]
      });

      // 8.1.x 事件监听
      // player.eventEmitter.on(EZUIKitPlayer.EVENTS.videoInfo, (info) => {
      //   console.warn("eventEmitter videoInfo", info);
      // });
      // 8.2.x 事件监听
      player.on(EZUIKitPlayer.EVENTS.videoInfo, (info) => {
        console.warn("videoInfo", info);
      });

      // 8.1.x 事件监听
      // player.eventEmitter.on(EZUIKitPlayer.EVENTS.audioInfo, (info) => {
      //   console.warn("eventEmitter audioInfo", info);
      // });
      // 8.2.x 事件监听
      player.on(EZUIKitPlayer.EVENTS.audioInfo, (info) => {
        console.warn("audioInfo", info);
      });

      // 首帧渲染成功
      // first frame display
      // 8.1.x 事件监听
      // player.eventEmitter.on(EZUIKitPlayer.EVENTS.firstFrameDisplay, () => {
      //     console.warn("eventEmitter firstFrameDisplay ");
      // });
      // 8.2.x 事件监听
      player.on(EZUIKitPlayer.EVENTS.firstFrameDisplay, () => {
        console.warn("firstFrameDisplay ");
      });

      // 8.1.x 事件监听
      // player.eventEmitter.on(EZUIKitPlayer.EVENTS.streamInfoCB, (info) => {
      //   console.warn("eventEmitter streamInfoCB ", info);
      // });
      // 8.2.x 事件监听
      player.on(EZUIKitPlayer.EVENTS.streamInfoCB, (info) => {
        console.warn("streamInfoCB ", info);
      });

      window.player = player;
    },
    play() {
      if (player) {
        player.play().then((data) => {
          console.log("play 获取 数据", data);
        });
      }
    },
    stop() {
      if (player) {
        player.stop().then((data) => {
          console.log("stop 获取 数据", data);
        });
      }
    },
    getOSDTime() {
      if (player) 
       player.getOSDTime().then((data) => {
        console.log("getOSDTime 获取 数据", data);
      });
    },
    capturePicture() {
      if (player) {
        player.capturePicture(`${new Date().getTime()}`).then((data) => {
          console.log("capturePicture 获取 数据", data);
        });
      }
    },
    openSound() {
      if (player) {
        player.openSound().then((data) => {
          console.log("openSound 获取 数据", data);
        });
      }
    },
    closeSound() {
      if (player) {
        player.closeSound().then((data) => {
          console.log("closeSound 获取 数据", data);
        });
      }
    },
    startSave() {
      if (player) {
        player.startSave(`${new Date().getTime()}`).then((data) => {
          console.log("startSave 获取 数据", data);
        });
      }
    },
    stopSave() {
      if (player) {
        player.stopSave().then((data) => {
          console.log("promise 获取 数据", data);
        });
      }
    },
    startTalk() {
      // 一个页面中只可以有一个对讲
      if (player) {
        player.startTalk();
      }
    },
    stopTalk() {
      if (player) {
        player.stopTalk();
      }
    },
    fullscreen() {
      if (player) player.fullscreen();
    },
    destroy() {
      if (player)  {
        player.destroy().then((data) => {
          console.log("promise 获取 数据", data);
        });
        player = null;
      }
    },
  },
};
</script>

vue3版示例

html 复制代码
<script lang="ts" setup>
import { EZUIKitPlayer } from "ezuikit-js";
import { onMounted } from "vue";

interface IPlayer {
  play: Function;
  stop: Function;
  getOSDTime: Function;
  capturePicture: Function;
  openSound: Function;
  closeSound: Function;
  startSave: Function;
  stopSave: Function;
  startTalk: Function;
  stopTalk: Function;
  fullscreen: Function;
  destroy: Function;
  eventEmitter: any;
  on: any // eventEmitter
}

let player: IPlayer;

const play = () => {
  if (player) player.play()
};

const stop = () => {
  if (player) player.stop();
};

const getOSDTime = () => {
  if (player)
  player.getOSDTime().then((data: any) => {
    console.log("getOSDTime 获取 数据", data);
  });
};

const capturePicture = () => {
  if (player)
    player.capturePicture(
      `${new Date().getTime()}`
    ).then((data: any) => {
      console.log("capturePicture 获取 数据", data);
    });
};

const openSound = () => {
    if (player) player.openSound();
};

const closeSound = () => {
    if (player) player.closeSound();
};

const startSave = () => {
  if (player)
    player.startSave(`${new Date().getTime()}`).then((data: any) => {
      console.log("startSave 获取 数据", data);
    });
};

const stopSave = () => {
  if (player)
    player.stopSave().then((data: any) => {
      console.log("stopSave 获取 数据", data);
    });
};

const startTalk = () => {
  if (player) player.startTalk();
};

const stopTalk = () => {
  if (player) player.stopTalk();
};

const fullscreen = () => {
  if (player) player.fullscreen();
};

const destroy = () => {
  if (player) {
    player.destroy().then((data: any) => {
      console.log("promise 获取 数据", data);
    });
    player = null!;
  }
};

const init = () => {
  if (player) {
    destroy();
  }
  console.group("mounted 组件挂载完毕状态===============》");
  // fetch("https://open.ys7.com/jssdk/ezopen/demo/token")
  //   .then((response) => response.json())
  //   .then((res) => {
  //     var accessToken = res.data.accessToken;
  player = new EZUIKitPlayer({
    id: "video-container", // 视频容器ID
    accessToken:
      "at.9uoaxo0k3e5dinq8bretm18e5l37k1l6-26lx1qcvcc-1neesaz-kh9hqvqc3",
    url: "ezopen://open.ys7.com/BC7799091/1.hd.live",
    // simple: 极简版; pcLive: pc直播; pcRec: pc回放; mobileLive: 移动端直播; mobileRec: 移动端回放;security: 安防版; voice: 语音版;
    template: "pcLive",
    // width: 600,
    height: 400,
    // quality: 1, // 
    // language: "en", // zh | en
    handleError: (err: any) => {
      console.error("handleError", err);
    },
    // 自定义清晰度 默认 null, 如果有值 sdk 内部不在进行获取, null 默认使用接口获取的清晰度列表, videoLevelList.length === 0 不展示清晰度控件 sdk 内部不在进行获取, videoLevelList.length > 0 展示控件 sdk 内部不在进行获取
    // videoLevelList: [
    //   { level: 0, name: "流畅", streamTypeIn: 1 },
    //   { level: 1, name: "标清", streamTypeIn: 1 },
    // ],
    // staticPath: "./ezuikit_static", // 如果想使用本地静态资源,请复制根目录下ezuikit_static 到当前目录下, 然后设置该值
    scaleMode: 1, // 默认 0 完全填充窗口,会有拉伸 1: 等比适配 2: 等比完全填充窗口, 超出隐藏 @sine 8.2.0
    env: {
      // https://open.ys7.com/help/1772?h=domain
      // domain默认是 https://open.ys7.com, 如果是私有化部署或海外的环境,请配置对应的domain
      // The default domain is https://open.ys7.com If it is a private deployment or overseas (outside of China) environment, please configure the corresponding domain
      domain: "https://open.ys7.com",
    },
    // staticPath: "https://openstatic.ys7.com/ezuikit_js/v8.1.9/ezuikit_static",
    // 日志打印设置
    loggerOptions: {
      // player.setLoggerOptions(options)
      level: "INFO", // INFO LOG  WARN  ERROR
      name: "ezuikit",
      showTime: true,
    },
    // 视频流的信息回调类型
    /**
     * 打开流信息回调,监听 streamInfoCB 事件
     * 0 : 每次都回调
     * 1 : 只回调一次
     * 注意:会影响性能
     * 默认值 1
     */
    streamInfoCBType: 1,
    // v8.1.10
    // 自定义清晰度 默认 null, 如果有值 sdk 内部不在进行获取, null 默认使用接口获取的清晰度列表, videoLevelList.length === 0 不展示清晰度控件 sdk 内部不在进行获取, videoLevelList.length > 0 展示控件 sdk 内部不在进行获取
    // videoLevelList: [
    //   { level: 1, name: "标清", streamTypeIn: 2 }, // 需要保证支持子码流 (streamTypeIn=2)
    //   { level: 2, name: "高清", streamTypeIn: 1 },
    // ],
    // videoLevelList: [
    //   { level: -1, name: "标清", streamTypeIn: 2 }, // 8.1.17 开始 当 level 的值小于 0时, 不在向设备发送指令,仅根据 streamTypeIn 切换码流 (请保证 streamTypeIn 对应的码流存在)
    //   { level: -2, name: "高清", streamTypeIn: 1 }, // 8.1.17 开始 当 level 的值小于 0时, 不在向设备发送指令,仅根据 streamTypeIn 切换码流 (请保证 streamTypeIn 对应的码流存在)
    // ]
  });

      // 8.1.x 事件监听
      // player.eventEmitter.on(EZUIKitPlayer.EVENTS.videoInfo, (info) => {
      //   console.warn("eventEmitter videoInfo", info);
      // });
      // 8.2.x 事件监听
      player.on(EZUIKitPlayer.EVENTS.videoInfo, (info: any) => {
        console.warn("videoInfo", info);
      });

      // 8.1.x 事件监听
      // player.eventEmitter.on(EZUIKitPlayer.EVENTS.audioInfo, (info) => {
      //   console.warn("eventEmitter audioInfo", info);
      // });
      // 8.2.x 事件监听
      player.on(EZUIKitPlayer.EVENTS.audioInfo, (info: any) => {
        console.warn("audioInfo", info);
      });

      // 首帧渲染成功
      // first frame display
      // 8.1.x 事件监听
      // player.eventEmitter.on(EZUIKitPlayer.EVENTS.firstFrameDisplay, () => {
      //     console.warn("eventEmitter firstFrameDisplay ");
      // });
      // 8.2.x 事件监听
      player.on(EZUIKitPlayer.EVENTS.firstFrameDisplay, () => {
        console.warn("firstFrameDisplay ");
      });

      // 8.1.x 事件监听
      // player.eventEmitter.on(EZUIKitPlayer.EVENTS.streamInfoCB, (info) => {
      //   console.warn("eventEmitter streamInfoCB ", info);
      // });
      // 8.2.x 事件监听
      player.on(EZUIKitPlayer.EVENTS.streamInfoCB, (info: any) => {
        console.warn("streamInfoCB ", info);
      });

      window.player = player;
  // });
};

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

<template>
  <div class="hello-ezuikit-js">
    <div>
      <div id="video-container" style="height: 400px"></div>
    </div>
    <div>
      <button @click="init">init</button>
      <button @click="stop">stop</button>
      <button @click="play">play</button>
      <button @click="openSound">openSound</button>
      <button @click="closeSound">closeSound</button>
      <button @click="startSave">startSave</button>
      <button @click="stopSave">stopSave</button>
      <button @click="capturePicture">capturePicture</button>
      <button @click="fullscreen">fullscreen</button>
      <button @click="getOSDTime">getOSDTime</button>
      <button @click="startTalk">startTalk</button>
      <button @click="stopTalk">stopTalk</button>
      <button @click="destroy">destroy</button>
    </div>
  </div>
</template>

uniapp vue2版

html 复制代码
<template>
  <div class="ezuikit-js">
    <div>
      <div id="video-container" style="width: 100%;height: 300px"></div>
    </div>
    <div>
      <button v-on:click="init">init</button>
      <button v-on:click="stop">stop</button>
      <button v-on:click="play">play</button>
      <button v-on:click="openSound">openSound</button>
      <button v-on:click="closeSound">closeSound</button>
      <button v-on:click="startSave">startSave</button>
      <button v-on:click="stopSave">stopSave</button>
      <button v-on:click="capturePicture">capturePicture</button>
      <button v-on:click="fullscreen">fullscreen</button>
      <button v-on:click="getOSDTime">getOSDTime</button>
      <button v-on:click="startTalk">startTalk</button>
      <button v-on:click="stopTalk">stopTalk</button>
      <button v-on:click="destroy">destroy</button>
    </div>
  </div>
</template>

<script>
import { EZUIKitPlayer } from "ezuikit-js";
var player = null;

export default {
  name: "Player",
  props: {
    msg: String,
  },
  mounted: () => {
    console.group("mounted 组件挂载完毕状态===============》");
  },
  methods: {
    init() {
      if (player) {
        this.destroy();
      }

      const systemInfo = uni.getSystemInfoSync();
      const windowWidth = systemInfo.windowWidth;

      player = new EZUIKitPlayer({
        id: "video-container", // 视频容器ID
        accessToken:
          "at.9uoaxo0k3e5dinq8bretm18e5l37k1l6-26lx1qcvcc-1neesaz-kh9hqvqc3",
        url: "ezopen://open.ys7.com/BC7799091/1.hd.live",
        // simple: 极简版; pcLive: pc直播; pcRec: pc回放; mobileLive: 移动端直播; mobileRec: 移动端回放;security: 安防版; voice: 语音版;
        template: "mobileLive",
        plugin: ["talk"], // 加载插件,talk-对讲
        width: windowWidth || 375,
        height: 300,
        audio: false,
        enableSharedArrayBufferGuide: false,
        talkChannelNo: 0,
        useHardDev: true,
        handleError: (error) => {
          console.error("handleError", error);
        },
        // quality: 1, // 
        // language: "en", // zh | en
        // staticPath: "/ezuikit_static", // 如果想使用本地静态资源,请复制根目录下ezuikit_static 到当前目录下, 然后设置该值
        // isCloudRecord: true, // 如果是云录制的播放 需要这个值,是必须的, 8.2.0 开始 默认支持
        scaleMode: 1, // 默认 0 完全填充窗口,会有拉伸 1: 等比适配 2: 等比完全填充窗口, 超出隐藏 @sine 8.2.0
        env: {
          // https://open.ys7.com/help/1772?h=domain
          // domain默认是 https://open.ys7.com, 如果是私有化部署或海外的环境,请配置对应的domain
          // The default domain is https://open.ys7.com If it is a private deployment or overseas (outside of China) environment, please configure the corresponding domain
          domain: "https://open.ys7.com",
        },
        // staticPath:"https://openstatic.ys7.com/ezuikit_js/v8.1.9/ezuikit_static",
        // 日志打印设置
        loggerOptions: {
          // player.setLoggerOptions(options)
          level: "INFO", // INFO LOG  WARN  ERROR
          name: "ezuikit",
          showTime: true,
        },
        showStreamInfo: false,
        // 视频流的信息回调类型
        /**
         * 打开流信息回调,监听 streamInfoCB 事件
         * 0 : 每次都回调
         * 1 : 只回调一次
         * 注意:会影响性能
         * 默认值 1
         */
        streamInfoCBType: 1,
        // v8.1.10
        // 自定义清晰度 默认 null, 如果有值 sdk 内部不在进行获取, null 默认使用接口获取的清晰度列表, videoLevelList.length === 0 不展示清晰度控件 sdk 内部不在进行获取, videoLevelList.length > 0 展示控件 sdk 内部不在进行获取
        // videoLevelList: [
        //   { level: 1, name: "标清", streamTypeIn: 2 }, // 需要保证支持子码流 (streamTypeIn=2)
        //   { level: 2, name: "高清", streamTypeIn: 1 },
        // ],
        // videoLevelList: [
        //   { level: -1, name: "标清", streamTypeIn: 2 }, // 8.1.17 开始 当 level 的值小于 0时, 不在向设备发送指令,仅根据 streamTypeIn 切换码流 (请保证 streamTypeIn 对应的码流存在)
        //   { level: -2, name: "高清", streamTypeIn: 1 }, // 8.1.17 开始 当 level 的值小于 0时, 不在向设备发送指令,仅根据 streamTypeIn 切换码流 (请保证 streamTypeIn 对应的码流存在)
        // ]
      });

      player.eventEmitter.on(EZUIKitPlayer.EVENTS.videoInfo, (info) => {
        console.log("videoinfo", info);
      });

      player.eventEmitter.on(EZUIKitPlayer.EVENTS.audioInfo, (info) => {
        console.log("audioInfo", info);
      });

      // 首帧渲染成功
      // first frame display
      player.eventEmitter.on(
        EZUIKitPlayer.EVENTS.firstFrameDisplay,
        () => {
          console.log("firstFrameDisplay ");
        }
      );
      player.eventEmitter.on(
        EZUIKitPlayer.EVENTS.streamInfoCB,
        (info) => {
          console.log("streamInfoCB ", info);
        }
      );

      window.player = player;
    },
    play() {
      var playPromise = player.play();
      playPromise.then((data) => {
        console.log("promise 获取 数据", data);
      });
    },
    stop() {
      var stopPromise = player.stop();
      stopPromise.then((data) => {
        console.log("promise 获取 数据", data);
      });
    },
    getOSDTime() {
      var getOSDTimePromise = player.getOSDTime();
      getOSDTimePromise.then((data) => {
        console.log("promise 获取 数据", data);
      });
    },
    capturePicture() {
      var capturePicturePromise = player.capturePicture(
        `${new Date().getTime()}`
      );
      capturePicturePromise.then((data) => {
        console.log("promise 获取 数据", data);
      });
    },
    openSound() {
      var openSoundPromise = player.openSound();
      openSoundPromise.then((data) => {
        console.log("promise 获取 数据", data);
      });
    },
    closeSound() {
      var openSoundPromise = player.closeSound();
      openSoundPromise.then((data) => {
        console.log("promise 获取 数据", data);
      });
    },
    startSave() {
      var startSavePromise = player.startSave(`${new Date().getTime()}`);
      startSavePromise.then((data) => {
        console.log("promise 获取 数据", data);
      });
    },
    stopSave() {
      var stopSavePromise = player.stopSave();
      stopSavePromise.then((data) => {
        console.log("promise 获取 数据", data);
      });
    },
    startTalk() {
      player.startTalk();
    },
    stopTalk() {
      player.stopTalk();
    },
    fullscreen() {
      player.fullscreen();
    },
    destroy() {
      var destroyPromise = player.destroy();
      destroyPromise.then((data) => {
        console.log("promise 获取 数据", data);
      });
      player = null;
    },
  },
};
</script>

配置themeData 添加链接描述

相关推荐
梓仁沐白2 小时前
CSAPP-Attacklab
前端
郑州光合科技余经理2 小时前
海外国际版同城服务系统开发:PHP技术栈
java·大数据·开发语言·前端·人工智能·架构·php
zhz52142 小时前
代码之恋(第十五篇:分布式心跳与网络延迟)
网络·分布式·ai·重构·vue·结对编程
一行注释2 小时前
前端数据加密:保护用户数据的第一道防线
前端
running up2 小时前
Java集合框架之ArrayList与LinkedList详解
javascript·ubuntu·typescript
纪伊路上盛名在2 小时前
记1次BioPython Entrez模块Elink的debug
前端·数据库·python·debug·工具开发
xiaoxue..2 小时前
React 之 Hooks
前端·javascript·react.js·面试·前端框架
Alair‎3 小时前
300TypeScript基础知识
javascript
旧梦吟3 小时前
脚本网页 三人四字棋
前端·数据库·算法·css3·html5