Vue3对话框(Dialog)
Vue2对话框(Dialog)
可自定义设置以下属性:
-
标题(title),类型:string | slot,默认 '提示'
-
内容(content),类型:string | slot,默认 ''
-
宽度(width),类型:number,默认 640px
-
高度(height),类型:number,默认 480px
-
是否允许切换全屏,允许后右上角会出现一个按钮(switchFullscreen),类型:boolean,默认 false
-
取消按钮文字(cancelText),类型:string,默认 '取消'
-
确认按钮文字(okText),类型:string,默认 '确认'
-
是否显示底部按钮(footer),类型:boolean,默认 false
-
是否水平垂直居中(center),类型:boolean,默认 true,(false时是固定高度水平居中)
-
固定高度水平居中时,距顶部高度(top),类型:number,默认 100px
-
加载中(loading),类型:boolean,默认 false
-
对话框是否可见(visible),类型:boolean,默认 false
效果如下图:(整体样式模仿ant-design-vue Modal,同时阴影覆盖浏览器窗口)

①创建对话框组件Dialog.vue:
<script setup lang="ts">
import { ref, computed, watch } from 'vue'
const props = defineProps({title: { // 标题 string | slottype: String,default: '提示'},content: { // 内容 string | slottype: String,default: ''},width: { // 宽度,默认640type: Number,default: 640},height: { // 高度,默认480type: Number,default: 480},switchFullscreen: { // 是否允许切换全屏,允许后右上角会出现一个按钮type: Boolean,default: false},cancelText: { // 取消按钮文字type: String,default: '取消'},okText: { // 确认按钮文字type: String,default: '确定'},footer: { // 是否显示底部按钮,默认不显示type: Boolean,default: false},center: { // 水平垂直居中:true 固定高度水平居中:falsetype: Boolean,default: true},top: { // 固定高度水平居中时,距顶部高度type: Number,default: 100},loading: { // 加载中type: Boolean,default: false},visible: { // 对话框是否可见type: Boolean,default: false}})const fullScreen = ref(false)
const dialogWidth = computed(() => {if (fullScreen.value) {return '100%'} else {return props.width + 'px'}})
const dialogHeight = computed(() => {if (fullScreen.value) {return '100vh'} else {return props.height + 'px'}})
watch(() => props.visible, (to) => {if (!to) { // 重置全屏显示fullScreen.value = false}
})
const emits = defineEmits(['close', 'cancel', 'ok'])
function onBlur () {if (!props.loading) {emits('close')}
}
function onFullScreen () {fullScreen.value = !fullScreen.value
}
function onClose () {emits('close')
}
function onCancel () {emits('cancel')
}
function onConfirm () {emits('ok')
}
</script>
<template><Transition><div class="m-dialog-mask" v-show="visible" @click.self="onBlur"><div :class="['m-dialog', center ? 'relative-hv-center' : 'top-center']" :style="`width: ${dialogWidth}; height: ${dialogHeight}; top: ${!center ? top + 'px':'50%'}`"><div class="m-dialog-content" :class="{loading: loading}"><div class="m-spin-dot" v-show="loading"><span class="u-dot-item"></span><span class="u-dot-item"></span><span class="u-dot-item"></span><span class="u-dot-item"></span></div><svg @click="onFullScreen" v-show="!fullScreen&&switchFullscreen" class="u-screen" viewBox="64 64 896 896" data-icon="fullscreen" aria-hidden="true" focusable="false"><path d="M290 236.4l43.9-43.9a8.01 8.01 0 0 0-4.7-13.6L169 160c-5.1-.6-9.5 3.7-8.9 8.9L179 329.1c.8 6.6 8.9 9.4 13.6 4.7l43.7-43.7L370 423.7c3.1 3.1 8.2 3.1 11.3 0l42.4-42.3c3.1-3.1 3.1-8.2 0-11.3L290 236.4zm352.7 187.3c3.1 3.1 8.2 3.1 11.3 0l133.7-133.6 43.7 43.7a8.01 8.01 0 0 0 13.6-4.7L863.9 169c.6-5.1-3.7-9.5-8.9-8.9L694.8 179c-6.6.8-9.4 8.9-4.7 13.6l43.9 43.9L600.3 370a8.03 8.03 0 0 0 0 11.3l42.4 42.4zM845 694.9c-.8-6.6-8.9-9.4-13.6-4.7l-43.7 43.7L654 600.3a8.03 8.03 0 0 0-11.3 0l-42.4 42.3a8.03 8.03 0 0 0 0 11.3L734 787.6l-43.9 43.9a8.01 8.01 0 0 0 4.7 13.6L855 864c5.1.6 9.5-3.7 8.9-8.9L845 694.9zm-463.7-94.6a8.03 8.03 0 0 0-11.3 0L236.3 733.9l-43.7-43.7a8.01 8.01 0 0 0-13.6 4.7L160.1 855c-.6 5.1 3.7 9.5 8.9 8.9L329.2 845c6.6-.8 9.4-8.9 4.7-13.6L290 787.6 423.7 654c3.1-3.1 3.1-8.2 0-11.3l-42.4-42.4z"></path></svg><svg @click="onFullScreen" v-show="fullScreen&&switchFullscreen" class="u-screen" viewBox="64 64 896 896" data-icon="fullscreen-exit" aria-hidden="true" focusable="false"><path d="M391 240.9c-.8-6.6-8.9-9.4-13.6-4.7l-43.7 43.7L200 146.3a8.03 8.03 0 0 0-11.3 0l-42.4 42.3a8.03 8.03 0 0 0 0 11.3L280 333.6l-43.9 43.9a8.01 8.01 0 0 0 4.7 13.6L401 410c5.1.6 9.5-3.7 8.9-8.9L391 240.9zm10.1 373.2L240.8 633c-6.6.8-9.4 8.9-4.7 13.6l43.9 43.9L146.3 824a8.03 8.03 0 0 0 0 11.3l42.4 42.3c3.1 3.1 8.2 3.1 11.3 0L333.7 744l43.7 43.7A8.01 8.01 0 0 0 391 783l18.9-160.1c.6-5.1-3.7-9.4-8.8-8.8zm221.8-204.2L783.2 391c6.6-.8 9.4-8.9 4.7-13.6L744 333.6 877.7 200c3.1-3.1 3.1-8.2 0-11.3l-42.4-42.3a8.03 8.03 0 0 0-11.3 0L690.3 279.9l-43.7-43.7a8.01 8.01 0 0 0-13.6 4.7L614.1 401c-.6 5.2 3.7 9.5 8.8 8.9zM744 690.4l43.9-43.9a8.01 8.01 0 0 0-4.7-13.6L623 614c-5.1-.6-9.5 3.7-8.9 8.9L633 783.1c.8 6.6 8.9 9.4 13.6 4.7l43.7-43.7L824 877.7c3.1 3.1 8.2 3.1 11.3 0l42.4-42.3c3.1-3.1 3.1-8.2 0-11.3L744 690.4z"></path></svg><svg @click="onClose" class="u-close" viewBox="64 64 896 896" data-icon="close" aria-hidden="true" focusable="false"><path d="M563.8 512l262.5-312.9c4.4-5.2.7-13.1-6.1-13.1h-79.8c-4.7 0-9.2 2.1-12.3 5.7L511.6 449.8 295.1 191.7c-3-3.6-7.5-5.7-12.3-5.7H203c-6.8 0-10.5 7.9-6.1 13.1L459.4 512 196.9 824.9A7.95 7.95 0 0 0 203 838h79.8c4.7 0 9.2-2.1 12.3-5.7l216.5-258.1 216.5 258.1c3 3.6 7.5 5.7 12.3 5.7h79.8c6.8 0 10.5-7.9 6.1-13.1L563.8 512z"></path></svg><div class="m-dialog-header"><slot name="title"><div class="u-head">{{ title }}</div></slot></div><div class="m-dialog-body" :style="`height: calc(${dialogHeight} - ${footer ? '158px':'103px'});`"><slot>{{ content }}</slot></div><div class="m-dialog-footer" v-show="footer"><button class="u-cancel" @click="onCancel">{{ cancelText }}</button><button class="u-confirm" @click="onConfirm">{{ okText }}</button></div></div></div></div></Transition>
</template>
<style lang="less" scoped>
.v-enter-active, .v-leave-active {transition: opacity 0.3s ease;
}
.v-enter-from, .v-leave-to {opacity: 0;
}
.flex-hv-center { // 水平垂直居中方法①:弹性布局,随内容增大高度,并自适应水平垂直居中display: flex;justify-content: center;align-items: center;
}
.relative-hv-center { // 水平垂直居中方法②:相对定位,随内容增大高度,并自适应水平垂直居中position: relative;top: 50%;transform: translateY(-50%);-ms-transform: translateY(-50%);; /* IE 9 */-webkit-transform: translateY(-50%); /* Safari and Chrome */
}
.top-center { // 相对定位,固定高度,始终距离视图顶端100pxposition: relative;// top: 100px;
}
.m-dialog-mask {position: fixed;top: 0;right: 0;bottom: 0;left: 0;width: 100%;height: 100%;z-index: 10000;background: rgba(0,0,0,0.45);.m-dialog {margin: 0 auto;transition: all .3s ease;.m-spin-dot { // 绝对定位,并设置水平垂直居中position: absolute;display: inline-block;right: 0;left: 0;top: 0;bottom: 0;margin: auto;width: 24px;height: 24px;transform: rotate(45deg);-ms-transform: rotate(45deg); /* Internet Explorer */-moz-transform: rotate(45deg); /* Firefox */-webkit-transform: rotate(45deg); /* Safari 和 Chrome */-o-transform: rotate(45deg); /* Opera */animation: rotate 1.2s linear infinite;-webkit-animation: rotate 1.2s linear infinite;@keyframes rotate {100% {transform: rotate(405deg);}}.u-dot-item { // 单个圆点样式position: absolute;width: 8px;height: 8px;background: @themeColor;border-radius: 50%;opacity: .3;animation: spinMove 1s linear infinite alternate;-webkit-animation: spinMove 1s linear infinite alternate;@keyframes spinMove {100% {opacity: 1;}}}.u-dot-item:first-child {top: 0;left: 0;}.u-dot-item:nth-child(2) {top: 0;right: 0;animation-delay: .4s;-webkit-animation-delay: .4s;}.u-dot-item:nth-child(3) {bottom: 0;right: 0;animation-delay: .8s;-webkit-animation-delay: .8s;}.u-dot-item:last-child {bottom: 0;left: 0;animation-delay: 1.2s;-webkit-animation-delay: 1.2s;}}.loading { // 加载过程背景虚化background: rgb(248, 248, 248) !important;pointer-events: none; // 屏蔽鼠标事件}.m-dialog-content {position: relative;background: #fff;border-radius: 4px;box-shadow: 0 4px 12px rgba(0,0,0,.1);.u-screen {.u-close();right: 64px;}.u-close {width: 16px;height: 16px;position: absolute;top: 19px;right: 24px;fill: rgba(0,0,0,.45);cursor: pointer;transition: fill .3s;&:hover {fill: rgba(0,0,0,.75);}}.m-dialog-header {height: 22px;padding: 16px 24px;color: rgba(0,0,0,.65);border-radius: 4px 4px 0 0;border-bottom: 1px solid #e8e8e8;.u-head {margin: 0;color: rgba(0,0,0,.85);font-weight: 500;font-size: 16px;line-height: 22px;word-wrap: break-word;}}.m-dialog-body {padding: 24px;font-size: 16px;line-height: 1.5;word-wrap: break-word;overflow: auto;transition: all .3s;}.m-dialog-footer {padding: 10px 16px;text-align: right;border-top: 1px solid #e8e8e8;.u-cancel {height: 32px;line-height: 32px;padding: 0 15px;font-size: 16px;border-radius: 4px;color: rgba(0,0,0,.65);background: #fff;border: 1px solid #d9d9d9;cursor: pointer;transition: all .3s cubic-bezier(.645,.045,.355,1);&:hover {color: fade(@themeColor, 80%);border-color: fade(@themeColor, 80%);}&:focus {color: shade(@themeColor, 12%);border-color: shade(@themeColor, 12%);}}.u-confirm {margin-left: 8px;height: 32px;line-height: 32px;padding: 0 15px;font-size: 16px;border-radius: 4px;background: @themeColor;border: 1px solid @themeColor;color: #fff;transition: all .3s cubic-bezier(.645,.045,.355,1);cursor: pointer;&:hover {background: fade(@themeColor, 80%);border-color: fade(@themeColor, 80%);}&:focus {background: shade(@themeColor, 12%);border-color: shade(@themeColor, 12%);}}}}}
}
</style>
②在要使用的页面引入:
<script setup lang="ts">
import { Dialog } from './Dialog.vue'
import { ref } from 'vue'
import { rafTimeout } from '../../packages'const center = ref(true)
const footer = ref(false)
const loading = ref(false)
const visible = ref(false)
const title = ref('Dialog Title')
const content = ref('Content of the modal ...')
function showDialog (info: string) {footer.value = falsecenter.value = truecontent.value = infovisible.value = true
}
function showFooterDialog (info: string) {footer.value = truecenter.value = truecontent.value = infovisible.value = true
}
function showCenterDialog (info: string) {center.value = truecontent.value = infovisible.value = true
}
function showFixDialog (info: string) {center.value = falsecontent.value = infovisible.value = true
}
function onClose () { // 关闭回调visible.value = false
}
function onCancel () { // “取消”按钮回调visible.value = false
}
function onConfirm () { // “确定”,“知道了”按钮回调loading.value = true // 开启加载状态rafTimeout(() => {visible.value = falseloading.value = false}, 500)
}
</script>
<template><div><h2 class="mb10">Dialog 对话框基本使用</h2><Button class="mr30" @click="showDialog('Some descriptions ...')">默认对话框</Button><Button class="mr30" @click="showFooterDialog('Some descriptions ...')">有底部按钮的对话框</Button><Button class="mr30" @click="showCenterDialog('Some descriptions ...')">水平垂直居中对话框</Button><Button class="mr30" @click="showFixDialog('Some descriptions ...')">高度固定对话框</Button><Dialog:title="title":width="720":height="480":content="content":footer="footer"cancelText="取消"okText="确认"switchFullscreen@close="onClose"@cancel="onCancel"@ok="onConfirm":center="center":top="100":loading="loading":visible="visible"><template #title><p class="u-title">Title</p></template><p>Bla bla ...</p><p>Bla bla ...</p><p>Bla bla ...</p></Dialog></div>
</template>
<style lang="less" scoped>
.u-title {font-size: 16px;
}
</style>
相关文章:
Vue3对话框(Dialog)
Vue2对话框(Dialog) 可自定义设置以下属性: 标题(title),类型:string | slot,默认 提示 内容(content),类型:string | slot…...
【深度强化学习】(5) DDPG 模型解析,附Pytorch完整代码
大家好,今天和各位分享一下深度确定性策略梯度算法 (Deterministic Policy Gradient,DDPG)。并基于 OpenAI 的 gym 环境完成一个小游戏。完整代码在我的 GitHub 中获得: https://github.com/LiSir-HIT/Reinforcement-Learning/tree/main/Mod…...
unity,Color.Lerp函数
介绍 Color.Lerp函数是Unity引擎中的一个静态函数,用于在两个颜色值之间进行线性插值,从而实现颜色渐变效果 方法 Color.Lerp函数是Unity引擎中的一个静态函数,用于在两个颜色值之间进行线性插值,从而实现颜色渐变效果。该函数的…...
洛谷P8799 [蓝桥杯 2022 国 B] 齿轮 C语言/C++
[蓝桥杯 2022 国 B] 齿轮 题目描述 这天,小明在组装齿轮。 他一共有 nnn 个齿轮,第 iii 个齿轮的半径为 rir_{i}ri, 他需要把这 nnn 个齿轮按一定顺序从左到右组装起来,这样最左边的齿轮转起来之后,可以传递到最右边的齿轮&a…...
景区在线售票系统功能开发介绍
目前游客线上订票已经普及,景区开通线上购票渠道,方便游客购票,对于还没有开通线上购票的景区来说,需要提前了解一下景区线上售票系统的一些功能,下面给大家详细介绍一下景区在线售票需要哪些功能。 1、在线售票 包含门…...
webService的底层调用方式
webservice中采用协议Http,是指什么意思 WebService使用的是 SOAP (Simple Object Access Protocol)协议 Soap协议只是用来封装消息用的。封装后的消息你可以通过各种已有的协议来传输,比如http,tcp/ip,smtp,等等,你甚至还一次用自定义的协议…...
关于文件的一些小知识下
🍍个人主页🍍:🔜勇敢的小牛儿🚩 🔱推荐专栏🔱:C语言知识点 ⚠️座右铭⚠️:敢于尝试才有机会 🐒今日鸡汤🐒: 你受的苦 吃的亏 担的责 扛的罪 忍的…...
使用Cheat Engine与DnSpy破解Unity游戏
题目连接: https://play.picoctf.org/practice/challenge/361?originalEvent72&page3我们是windows系统,所以点击windows game下载游戏 双击运行pico.exe 屏幕上方的一串英文是叫我们找flag,我在这个小地图里走来走去也没flagÿ…...
溯源取证-内存取证基础篇
使用工具: volatility_2.6_lin64_standalone 镜像文件: CYBERDEF-567078-20230213-171333.raw 使用环境: kali linux 2022.02 我们只有一个RAW映像文件,如何从该映像文件中提取出我们想要的东西呢? 1.Which volatili…...
Leetcode.100 相同的树
题目链接 Leetcode.100 相同的树 easy 题目描述 给你两棵二叉树的根节点 p和 q,编写一个函数来检验这两棵树是否相同。 如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。 示例 1: 输入:p [1,2,3…...
每个程序员都应该知道的8大算法
在编程开发中,算法是用于解决特定问题或完成特定任务的一组指令或过程。算法可以用任何编程语言表示,可以像一系列基本操作一样简单,也可以像涉及不同数据结构和逻辑的多步骤过程一样复杂。 算法的主要目标是接收输入、处理它并提供预期的输…...
Nestjs实战超干货-概况-模块-Modules
模块 模块就是一个声明了装饰器Module()的类。装饰器Module()提供了元数据,以便让Nest组织应用程序结构。 每个应用程序至少有一个模块,即根模块。根模块是 Nest 用来构建应用程序图的起点,应用程序图是 Nest 用来解析模块和提供者关系和依赖…...
template
模板 模板注意事项 模板的函数体和声明一定要在一起,即放在同一个.h文件中,而不能将其分开到cpp和h文件中模板的编译技巧就是尽量多编译,模板很难查找错误模板的报错一般只有第一行有作用模板指定类型从左到右依次指定 模板推导 #pragma #…...
innovus中时序路径debug及命令使用详解?
写在前面:发现place结果所有与outport相关的timing check都找不到? 刚开始怀疑是sdc约束问题,check了input sdc文件及enc.dat/mmmc/mode/func.sdc 看一下是否设置了set_false_path.当然也可以用命令报出来: report_timing -unconstrained …...
C语言爱心代码大全集—会Ctrl+C就可以表白了
一、C语言爱心代码大全,会CtrlC就可以表白了! 博主整理了一个C语言爱心代码大全,里面有C语言爱心代码会动的动态效果和C语言爱心代码大全静态效果,只需复制粘贴就可以用啦! 1、动态C语言爱心代码效果图如下ÿ…...
python+vue+django耕地信息管理系统的设计与实现
基普通用户模块含有个人中心、耕地信息管理、转让许可申请管理、租赁许可申请管理等功能;普通管理员模块含有个人中心、用户管理、公示公告管理、耕地信息管理、耕地信息统计、转让许可申请管理、租赁许可申请管理、转让协议管理、租赁协议管理等功能;管…...
【云原生】Dockerfile制作WordPress镜像,实现compose编排部署
文章目录👹 关于作者前言环境准备目录结构dockerfile制作镜像yum 脚本Dockerfile-mariadb 镜像Dockerfile-service 镜像docker compose 编排提升✊ 最后👹 关于作者 大家好,我是秋意临。 😈 CSDN作者主页 😎 博客主页…...
五款好用又有趣的WIN10软件推荐
如果你想让你的电脑使用更方便、更有趣、更专业,那么你一定要看看这篇文章,因为我要给你推荐五款好用又有趣的WIN10软件 1.全局搜索——火柴 火柴是一款全局搜索软件,可以让你快速找到你想要的文件、程序、网页等,只需按下AltSp…...
朴素贝叶斯算法
# -*-coding:utf-8-*- """ Author: sunchang Desc: 代码4-7 朴素贝叶斯实现对异常账户检测 """ import numpy as np class NaiveBayesian: def __init__(self, alpha): self.classP dict() self.classP_f…...
【常见CSS扫盲雪碧图】从源码细看CSS雪碧图原理及实现,千字详解【附源码demo下载】
【写在前面】其实估计很多人都听过雪碧图,或者是CSS-Sprite,在很多门户网站就会经常有用到的,之所有引出雪碧图这个概念还得从前端加载多个图片时候页面闪了一下说起,这样给人的视觉效果体验很差,也就借此机会和大家说…...
ABAP开发避坑指南:绕过SAP GUI安全弹窗的5种编程方案实测
ABAP开发实战:5种绕过SAP GUI安全弹窗的编程方案深度解析 引言:SAP GUI安全机制的困境与突破 在SAP系统的日常开发与运维中,频繁出现的"系统试图创建文件"安全弹窗堪称ABAP开发者的噩梦。这种设计初衷为保护本地文件安全的机制&…...
高频电路设计必看:5分钟搞懂PCB阻抗匹配的3个关键参数(附SI9000计算技巧)
高频PCB设计实战:从阻抗理论到SI9000精准计算的完整指南 引言:为什么你的高速信号总是不稳定? 上周和一位资深硬件工程师聊天,他提到自己设计的千兆以太网板卡在测试时总是出现信号抖动问题,反复调整了三四版Layout依然…...
dygraphs核心架构解析:理解Canvas渲染机制与高性能图表实现
dygraphs核心架构解析:理解Canvas渲染机制与高性能图表实现 【免费下载链接】dygraphs Interactive visualizations of time series using JavaScript and the HTML canvas tag 项目地址: https://gitcode.com/gh_mirrors/dy/dygraphs dygraphs是一个基于HTM…...
数字化、智能化、移动化,人力资源系统革新的三大法宝!
人力资源系统革新,打造企业人才发展新引擎在当今竞争激烈的商业环境中,企业的人才发展成为了决定其成败的关键因素之一。然而,传统的人力资源管理系统往往存在着诸多问题,如流程繁琐、数据不精准、缺乏智能化等,这些问…...
从随机采样到精准决策:蒙特卡罗方法在复杂系统建模中的实践
1. 蒙特卡罗方法:用随机性破解复杂世界的密码 想象你是一位古代数学家,手里只有一把沙子和一块画着方格的石板。现在要计算一个不规则形状的湖泊面积,你会怎么做?最原始的方法可能是把沙子均匀撒在石板上,然后数出落在…...
保姆级教程:手把手教你安装并激活DevExpress 20.1.3(附资源与注册机使用避坑指南)
深度指南:DevExpress 20.1.3开发环境高效配置与资源管理 在.NET生态系统中,DevExpress始终以其强大的控件库和高效的开发工具占据重要地位。对于刚接触这个工具集的开发者来说,如何快速搭建一个稳定的开发环境往往成为项目启动的第一道门槛。…...
M5Stack U126 RTC驱动库:PCF8563T嵌入式实时时钟深度解析
1. 项目概述M5Unit-RTC 是专为 M5Stack 生态中 Unit 系列模块设计的轻量级实时时钟(RTC)驱动库,对应硬件型号为U126—— 一款基于Ricoh RP5C01A 兼容架构、实际采用 NXP PCF8563T 实时时钟芯片的 IC 接口 RTC 模块。该模块集成高精度温度补偿…...
2026 工程指南:为什么 AWS Bedrock + Claude 4.6 正在成为多 Agent 协作的底层首选?
进入 2026 年第一季度,大模型领域的竞争已经从“单纯的参数规模”转向了“端到端的工程效率”。随着 GPT-5.4 陷入推理成本高企的泥潭,Anthropic 联手亚马逊发布的 Claude 4.6 托管方案,正在通过 Amazon Bedrock 平台迅速收割企业级市场。作为…...
深入解析NAND Flash基础操作与系统集成——从阵列结构到多Die协同
1. NAND Flash基础结构与工作原理 NAND Flash存储器是现代存储系统的核心组件,从U盘到企业级SSD都依赖这项技术。要理解它的强大之处,得先从它的物理结构说起——想象一个巨大的立体停车场,每个停车位就是一个存储单元,而控制电路…...
LFM2.5-1.2B-Thinking-GGUF应用场景:智能硬件说明书问答机器人落地实践
LFM2.5-1.2B-Thinking-GGUF应用场景:智能硬件说明书问答机器人落地实践 1. 项目背景与需求 在智能硬件领域,产品说明书往往存在以下痛点: 内容专业术语多,普通用户难以理解纸质说明书查找信息效率低不同型号产品差异导致用户混…...
