Ansible自动化运维
目录
前言
一、概述
常见的开源自动化运维工具比较
二、ansible环境搭建
三、ansible模块
(一)、hostname模块
(二)、file模块
(三)、copy模块
(四)、fetch模块
(五)、user模块
(六)、group模块
(七)、cron模块
(八)、yum_repository模块
(九)、yum模块
(十)、service模块
(十一)、script模块
(十二)、command与shell模块
三、playbook
(一)、YAML格式
(二)、Playbook常见语法
(三)、实例
四、roles介绍
(一)、roles的目录结构
(二)、roles实现lamp
(三)、拓展安装discuz
总结
前言
公司的服务器越来越多, 维护一些简单的事情都会变得很繁琐。用shell脚本来管理少量服务器效率还行, 服务器多了之后, shell脚本无法实现高效率运维。这种情况下,我们需要引入自动化运维工具, 对多台服务器实现高效运维。
一、概述
ansible是一种由Python开发的自动化运维工具,集合了众多运维工具(puppet、cfengine、chef、func、fabric)的优点,实现了批量系统配置、批量程序部署、批量运行命令等功能。
架构图
特点
-
部署简单
-
默认使用ssh进行管理,基于python里的==paramiko==模块开发
-
管理端和被管理端不需要启动服务
-
配置简单,功能强大,扩展性强
-
能过playbook(剧本)进行多个任务的编排
常见的开源自动化运维工具比较
-
puppet(拓展)
基于ruby语言,成熟稳定。适合于大型架构,相对于ansible和saltstack会复杂些。
-
saltstack(拓展)
基于python语言。相对简单,大并发能力比ansible要好, 需要维护被管理端的服务。如果服务断开,连接就会出问题。
-
ansible
基于python语言。简单快捷,被管理端不需要启服务。直接走ssh协议,需要验证所以机器多的话速度会较慢。
二、ansible环境搭建
一台管理
192.168.238.129(hd1)
两台被管理
192.168.238.130(hd2)
192.168.238.131(hd3)
防火墙设置、宽容模式(selinux )、NAT模式
所有主机都要配置主机名和 hosts文件
192.168.238.129
yum install -y epel-release
yum install -y ansible
设置免密登录
若不免密操作,在后面操作agent时都要加-k参数传密码;或者在主机清单里传密码。
ssh-keygen
ssh-copy-id hd2
ssh-copy-id hd3
vim /etc/ansible/hosts
若不进行免密会失败
免密后进行ping通测试(绿色为成功,红色为失败)
主机清单功能
因为未给自己免密所以129会失败
三、ansible模块
ansible是基于模块工作的,本身没有批量部署的能力。真正具有批量部署的是ansible所运行的模块,ansible只是提供一种框架。
ansible支持的模块非常的多,我们并不需要把每个模块都记住,而只需要熟悉一些常见的模块,其它的模块在需要用到时再查询即可。
官网模块文档地址:Ansible Documentation
(一)、hostname模块
hostname模块用于修改主机名(注意: 它不能修改/etc/hosts文件)
基本格式为: ansible 操作的机器名或组名 -m 模块名 -a "参数1=值1 参数2=值2" argment
例:修改hd3的hostname
(二)、file模块
file模块:用于对文件相关的操作(创建, 删除, 软硬链接等)
stat模块:类似linux的stat命令,用于获取文件的状态信息 。(了解)
创建一个目录
ansible my -m file -a 'path=/test state=directory'
创建一个文件
注意:my组的验证文章中多数只截取了一台机器
ansible my -m file -a 'path=/test/1.txt state=touch'
递归修改owner,group,mode
ansible 192.168.238.130 -m file -a 'path=/root/OK recurse=yes owner=bin group=bin mode=1777'
创建文件并指定owner,group,mode等
ansible my -m file -a 'path=/test/1.txt state=file owner=bin group=daemon mode=1777'
也可以指定其中一项进行创建修改
删除文件
删除目录 absent(缺席的) 会连同目录里的所有文件,删除文件值删除对应文件
ansible my -m file -a 'path=/test/1.txt state=absent '
创建软链接文件
ansible my -m file -a 'src=/etc/fstab path=/opt/fstab state=link'
创建硬链接文件
ansible my -m file -a 'src=/etc/fstab path=/opt/fstab2 state=hard'
(三)、copy模块
copy模块用于对文件的远程拷贝操作(如把本地的文件拷贝到远程的机器上)
echo master > OK
ansible my -m copy -a 'src=/root/OK dest=/opt/word'
content参数
使用content参数直接往远程文件里写内容(会覆盖原内容)
注意:ansible中-a后面的参数里也有引号时,记得要单引双引交叉使用,如果都为双引会出现问题。
ansible my -m copy -a 'content="hello\n" dest=/opt/word'
force参数
使用force参数控制是否强制覆盖
如果目标文件已经存在,则不覆盖 ansible my -m copy -a 'src=/root/OK dest=/opt/word force=no'如果目标文件已经存在,则会强制覆盖 ansible my -m copy -a 'src=/root/OK dest=/opt/word force=yes'
backup参数
使用backup参数控制是否备份文件
backup=yes表示如果拷贝的文件内容与原内容不一样,则会备份一份 my的机器上会将/opt/word备份一份(备份文件命名加上时间),再远程拷贝新的文件为/opt/word ansible my -m copy -a 'src=/root/OK dest=/opt/word backup=yes owner=daemon group=daemon mode=1777'
"/"符号
copy模块拷贝时要注意拷贝目录后面是否带"/"符号
/etc/yum.repos.d后面不带/符号,则表示把/etc/yum.repos.d整个目录拷贝到/tmp/目录下 ansible my -m copy -a 'src=/etc/yum.repos.d dest=/mnt/'/etc/yum.repos.d/后面带/符号,则表示把/etc/yum.repos.d/目录里的所有文件拷贝到/tmp/目录下 ansible my -m copy -a 'src=/etc/yum.repos.d/ dest=mnt/'
(四)、fetch模块
fetch模块与copy模块类似,但作用相反。用于把远程机器的文件拷贝到本地。
注意: fetch模块不能从远程拷贝目录到本地
创建同名文件
(五)、user模块
user模块用于管理用户账号和用户属性。
创建aaa用户,默认为普通用户,创建家目录
ansible 192.168.238.130 -m user -a 'name=aaa state=present'
创建bbb系统用户,并且登录shell环境为/sbin/nologin
ansible 192.168.238.130 -m user -a 'name=bbb state=present system=yes shell="/sbin/nologin"'
创建ccc用户, 使用uid参数指定uid, 使用password参数传密码 (密码要用双引号引起来,单引号的话验证时会密码不正确)
echo 123123 | openssl passwd -1 -stdin
ansible 192.168.238.130 -m user -a 'name=ccc uid=2000 state=present password="$1$TyI.ymu/$bDnWZc.re9V/37HAZAgrf0"'
删除aaa用户,但家目录默认没有删除
ansible 192.168.238.130 -m user -a 'name=aaa state=absent'
删除bbb用户,使用remove=yes参数让其删除用户的同时也删除家目录
ansible 192.168.238.130 -m user -a 'name=bbb state=absent remove=yes'
创建一个普通用户叫badboy,并产生空密码 密钥对echo
ansible 192.168.238.130 -m user -a 'name=badboy generate_ssh_key=yes'
产生空密码指的是这个,并非空密码
(六)、group模块
group模块用于管理用户组和用户组属性。
创建组
ansible 192.168.238.130 -m group -a 'name=long gid=3000 state=present'
删除组(如果有用户的gid为此组,则删除不了)
ansible 192.168.238.130 -m group -a 'name=long state=absent'
ansible 192.168.238.130 -m group -a 'name=ss state=absent'
(七)、cron模块
cron模块用于管理周期性时间任务。
创建一个cron任务,不指定user的话,默认就是root。
minute,hour,day,month,week不指定的话,默认都为*
ansible 192.168.238.130 -m cron -a 'name="test cron1" user=root job="touch /mnt/mnt.txt" minute=*/2'
也可以crontab -l查看任务
删除cron任务
ansible 192.168.238.130 -m cron -a 'name="test cron1" state=absent'
(八)、yum_repository模块
yum_repository模块用于配置yum仓库。
注意:此模块只帮助配置yum仓库,但如果仓库里没有软件包,安装一样会失败。所以可以手动去挂载光驱。
增加一个/etc/yum.repos.d/local.repo配置文件 。(输入命令注意-a后引号)
ansible 192.168.238.130 -m yum_repository -a "name=local description=localyum baseurl=file:///mnt/ enabled=yes gpgcheck=no"
删除/etc/yum.repos.d/local.repo配置文件
ansible 192.168.238.130 -m yum_repository -a "name=local state=absent"
(九)、yum模块
yum模块用于使用yum命令来实现软件包的安装与卸载。
使用yum安装一个软件(前提:被安装的机器上yum配置都已经OK)
ansible 192.168.238.130 -m yum -a 'name=dhcp state=present'
使用yum安装l软件,state=latest表示安装最新版本
ansible 192.168.238.130 -m yum -a 'name=dhcp state=latest'
使用yum卸载一个软件
ansible 192.168.238.130 -m yum -a 'name=dhcp state=absent'
(十)、service模块
service模块用于控制服务的启动,关闭,开机自启动等。
启动vsftpd服务,并设为开机自动启动
ansible 192.168.238.130 -m yum -a 'name=vsftpd state=present'
ansible 192.168.238.130 -m service -a 'name=vsftpd state=started enabled=on'
关闭vsftpd服务,并设为开机不自动启动
ansible 192.168.238.130 -m service -a 'name=vsftpd state=stoppd enabled=fales'
(十一)、script模块
script模块用于在远程机器上执行本地脚本。(不用给权限)
vim /root/test.sh
ansible 192.168.238.130 -m script -a '/root/test.sh'
(十二)、command与shell模块
两个模块都是用于执行linux命令的,这对于命令熟悉的工程师来说,用起来非常high。
shell模块与command模块差不多(command模块不能执行一些类似$HOME,>,<,|等符号,但shell可以)
注意: shell模块并不是百分之百任何命令都可以,比如vim或ll别名就不可以。不建议大家去记忆哪些命令不可以,大家只要养成任何在生产环境里的命令都要先在测试环境里测试一下的习惯就好。
查看my组IP
ansible my -m command -a 'ifconfig ens33'
对比于shell
ansible my -m command -a 'ifconfig ens33 |grep netmask'
ansible my -m shell -a 'ifconfig ens33 |grep netmask'
三、playbook
playbook(剧本): 是ansible用于配置,部署,和管理被控节点的剧本。用于ansible操作的编排。
使用的格式为yaml格式。(saltstack,elk,docker,docker-compose,kubernetes等也都会用到yaml格式)
(一)、YAML格式
注意: 写这种文件不要使用tab键,都使用空格。
-
以.yaml或.yml结尾
-
文件的第一行以 "---"开始,表明YMAL文件的开始(可选的)
-
以#号开头为注释
-
列表中的所有成员都开始于相同的缩进级别, 并且使用一个
"- "
作为开头(一个横杠和一个空格) -
一个字典是由一个简单的
键: 值
的形式组成(这个冒号后面必须是一个空格)
(二)、Playbook常见语法
hosts | 用于指定要执行任务的主机,其可以是一个或多个由冒号分隔主机组 | ||
remote_user | 用于指定远程主机上的执行任务的用户 | ||
tasks | 任务列表, 按顺序执行任务 | ||
如果一个host执行task失败, 这个tasks会回滚, 修正playbook 中的错误, 然后重新执行即可 | |||
handlers | 类似task,但需要使用notify通知调用 | ||
不管有多少个通知者进行了notify,等到play中的所有task执行完成之后,handlers也只会被执行一次 | |||
handlers最佳的应用场景是用来重启服务,或者触发系统重启操作.除此以外很少用到了 | |||
variables | 变量 | ||
定义变量可以被多次方便调用 |
(三)、实例
playbook编排my组安装httpd
mkdir /root/palybook
vim /root/palybook/test.yml
可以中文,最好注释以免造成异常(传输的文件要确保主机有不然会失败)
执行写好的palybook :ansible-playbook /root/playbook/test.yml
vim /etc/httpd/conf/httpd.conf
修改配置文件端口为443
再次执行palybook: ansible-playbook /root/playbook/test.yml
playbook编排多个hosts任务
vim /etc/httpd/conf/host.conf
ansible-playbook /root/playbook/host.yml
书写错误
my组用变量
vim /etc/httpd/conf/host.conf
ansible-playbook /root/playbook/host.yml
四、roles介绍
roles(角色): 就是通过分别将variables, tasks及handlers等放置于单独的目录中,并可以便捷地调用它们的一种机制。
假设我们要写一个playbook来安装管理lamp环境,那么这个playbook就会写很长。所以我们希望把这个很大的文件分成多个功能拆分, 分成apache管理,php管理,mysql管理,然后在需要使用的时候直接调用就可以了,以免重复写。就类似编程里的模块化的概念,以达到代码复用的效果。
(一)、roles的目录结构
注意: 在每个角色的目录中分别创建files, tasks,handlers,templates,vars和meta目录,用不到的目录可以创建为空目录.。
files | 用来存放由copy模块或script模块调用的文件 |
tasks | 至少有一个main.yml文件,定义各tasks |
handlers | 有一个main.yml文件,定义各handlers |
templates | 用来存放jinjia2模板 |
vars | 有一个main.yml文件,定义变量 |
meta | 有一个main.yml文件,定义此角色的特殊设定及其依赖关系 |
(二)、roles实现lamp
创建目录及文件,并确认目录结构
mkdir -p {httpd,mysql,php}/{files,tasks,handlers,templates,vars,meta}
touch {httpd,mysql,php}/{tasks,handlers,vars,meta}/main.yml
准备httpd服务器的主页文件,php测试页和配置文件等
echo "hello" > /etc/ansible/roles/httpd/files/index.html
echo -e "<?php\n\tphpinfo();\n?>" > /etc/ansible/roles/httpd/files/test.php
yum install -y httpd
cp /etc/httpd/conf/httpd.conf /etc/ansible/roles/httpd/files/
编写httpd角色的main.yml文件
vim /etc/ansible/roles/httpd/tasks/main.yml
编写httpd角色里的handler
vim /etc/ansible/roles/httpd/handler/main.yml
编写php角色的main.yml文件
vim /etc/ansible/roles/php/tasks/main.yml
编写mysql角色的main.yml文件
vim /etc/ansible/roles/mysql/tasks/main.yml
编写lamp的playbook文件调用前面定义好的三个角色
创建个playbook/lamp.yaml文件,位置随意
vim /root/playbook/lamp.yaml
注意:要与前面创建的名称一样
执行lamp的playbook文件
ansible-playbook /root/playbook/lamp.yml
(三)、拓展安装discuz
在此基础上安装discuz
discuz包放在/roles/httpd/files中
修改httpd角色的main.yml文件进行添加
vim /etc/ansible/roles/httpd/tasks/main.yml
修改mysql角色的main.yml文件
vim /etc/ansible/roles/mysql/tasks/main.yml
编写mysql的建库脚本
vim /etc/ansible/roles/mysql/files/create.sh
执行lamp的playbook文件
后续用mysql创建的授权用户和数据库即可。
总结
今天内容相当于可以舒缓下大脑了,没有zabbix那么繁琐的的流程。与基础命令的使用相似,只是在基础稍微扩展,模版较多熟记常用的就好,要理解含义再操作更有助于背记。playbook为整体,roles为进行分类,显得比较有序,报错可找到对应的地方进行处理。
相关文章:

Ansible自动化运维
目录 前言 一、概述 常见的开源自动化运维工具比较 二、ansible环境搭建 三、ansible模块 (一)、hostname模块 (二)、file模块 (三)、copy模块 (四)、fetch模块 ÿ…...

MSTP + Eth-Trunk配置实验 华为实验手册
1.1 实验介绍 1.1.1 关于本实验 以太网是当今现有局域网LAN(Local Area Network)采用的最通用的通信协议标准,以太网作为一种原理简单、便于实现同时又价格低廉的局域网技术已经成为业界的主流。 本实验主要介绍了LAN网络中的Eth-Trunk技术…...

滚动菜单 flutter
想实现这个功能: 下面的代码可以实现: import package:flutter/material.dart;void main() > runApp(MyApp());class MyApp extends StatelessWidget {static const String _title Flutter Code Sample;overrideWidget build(BuildContext context)…...
javaee springMVC数字类型转换之通过注解的方式
po 在属性上增加注解 NumberFormat(pattern “#,#.#”) package com.test.pojo;import org.springframework.format.annotation.DateTimeFormat; import org.springframework.format.annotation.NumberFormat;import java.util.Date;public class Users {private int uid;pr…...
SQL中CASE的用法
在SQL中,CASE语句是一种条件表达式,用于根据条件执行不同的操作。它有两种形式:简单CASE表达式和搜索CASE表达式。 简单CASE表达式的语法如下: CASE expressionWHEN value1 THEN result1WHEN value2 THEN result2...ELSE result …...

自己的碎碎念集合
自己的碎碎念集合 2023-09-07 c++叠加三目运算符闰年计算法2023-08-13 一个小题目 A+B problem一、问题及解答关碍总结2023-07-26 C的2至36进制转换函数一、itoa()函数的示例代码总结2023-07-19 平面坐标下判断三角形以及输出周长和面积一. 基本知识总结2023-06-25 达芬奇去除白…...
暂定名「码道功成:Coder启示录」
听人劝、吃饱饭,奉劝各位小伙伴,不要订阅该文所属专栏。 作者:不渴望力量的哈士奇(哈哥),十余年工作经验, 跨域学习者,从事过全栈研发、产品经理等工作,现任研发部门 CTO 。荣誉:2022年度博客之星Top4、博客专家认证、全栈领域优质创作者、新星计划导师,“星荐官共赢计…...

Apache HTTPD (CVE-2017-15715)换行解析漏洞复现
Apache HTTPD 换行解析漏洞 CVE-2017-15715漏洞简介 组件版本漏洞名称 Apache HTTPD 换行解析漏洞(CVE-2017-15715) 漏洞描述 Apache HTTPD是一款HTTP服务器,它可以通过mod_php来运行PHP网页。其2.4.0~2.4.29版本中存在一个解析漏洞&…...

Spring Boot集成JasperReport生成文档
由于工作需要,要实现后端根据模板动态填充数据生成PDF文档,通过技术选型,使用Ireport5.6来设计模板,结合JasperReports5.6工具库来调用渲染生成PDF文档。 一、使用Ireport designer 5.6设计模板 ireport的使用由于时间关系不便多…...

02-Tomcat打破双亲委派机制
上一篇:01-从JDK源码级别剖析JVM类加载机制 Tomcat 如果使用默认的双亲委派类加载机制行不行? 我们思考一下:Tomcat是个web容器, 那么它要解决什么问题: 一个web容器可能需要部署两个应用程序,不同的应用…...
怎么理解flink的异步检查点机制
背景 flink的checkpoint监控页面那里有两个指标Sync Duration 和Async Duration,一个是开始进行同步checkpoint所需的时间,一个是异步checkpoint过程所需的时间,你是否也有过疑惑,是否只是同步过程中的时间才会阻塞正常的数据处理…...

SpringMVC <url-pattern/>解读
1. < url-pattern/>的值 (1).使用拓展名的方式,语法*.xxx,xxx是自定义的拓展名,常用的方式*.do,*.action,不能使用*.jsp. (2).使用斜杠 "/"当项目中使用了 / ,他会替代tomcat中的default。导致所有的…...
大学毕业设计的益处:培养实践能力、深入专业领域、展示自信与建立联系
大学生做毕业设计有许多好处,以下是一些主要的原因和好处: 实践应用能力:毕业设计通常需要学生将所学的知识和技能应用到一个具体的项目中,这有助于他们将理论知识转化为实际应用能力。 独立思考和解决问题:毕业设计要…...
ChatGPT:概述Vue.js中data函数初始化和created钩子函数调用的顺序和问题解决方法
ChatGPT:概述Vue.js中data函数初始化和created钩子函数调用的顺序和问题解决方法 我将输入一段Vue代码,请你记住: created() {console.log(this.queryInfo)this.getClueList();},data() {return {allQueryInfo: {str: ,//线索标题查询信息},/…...

SpringBoot【基础篇】
一、快速上手 按照要求,左侧选择web,然后在中间选择Spring Web即可,选完右侧就出现了新的内容项,这就表示勾选成功了 关注:此处选择的SpringBoot的版本使用默认的就可以了,需要说一点,SpringBo…...

Vuex - state 状态(获取和使用共享数据)
文章目录 一、state是什么?二、state状态的作用三、如何使用store数据呢?使用数据的两种方式:1. 通过store 直接访问2. 通过辅助函数访问(简化) 一、state是什么? state是状态(数据) , 类似于v…...

tcp连接+套接字编程
tcp头部 tcp端口号 TCP的连接是需要四个要素确定唯一一个连接:(源IP,源端口号) (目地IP,目的端口号) 所以TCP首部预留了两个16位作为端口号的存储,而IP地址由上一层IP协议负责传递 源…...

OpenCV(三十四):轮廓外接最大、最小矩形和多边形拟合
目录 1.轮廓外接最大矩形boundingRect() 2.轮廓外接最小矩形minAreaRect() 3.轮廓外接多边形approxPolyDP() 1.轮廓外接最大矩形boundingRect() Rect cv::boundingRect ( InputArray array ) array:输入的灰度图像或者2D点集,数据类型为vector<Point>或者M…...

Kafka3.0.0版本——消费者(offset的默认维护位置)
目录 一、offset的默认维护位置1.1、offset的默认维护位置概述1.2、offset的默认维护位置图解 二、消费者offset的案例 一、offset的默认维护位置 1.1、offset的默认维护位置概述 Kafka0.9版本之前,consumer默认将offset保存在Zookeeper中。从Kafka0.9版本开始&am…...

Wireshark技巧[监听串口包]
监听串口包 本文摘录于:https://blog.csdn.net/qq_20405005/article/details/79652927只是做学习备份之用,绝无抄袭之意,有疑惑请联系本人! 这里要保证安装了USBpcap: 打开USBpcap后一半都要输入过滤条件,否则USB太多数据了,比如…...
谷歌浏览器插件
项目中有时候会用到插件 sync-cookie-extension1.0.0:开发环境同步测试 cookie 至 localhost,便于本地请求服务携带 cookie 参考地址:https://juejin.cn/post/7139354571712757767 里面有源码下载下来,加在到扩展即可使用FeHelp…...

DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI
前一阵子在百度 AI 开发者大会上,看到基于小智 AI DIY 玩具的演示,感觉有点意思,想着自己也来试试。 如果只是想烧录现成的固件,乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外,还提供了基于网页版的 ESP LA…...

2025 后端自学UNIAPP【项目实战:旅游项目】6、我的收藏页面
代码框架视图 1、先添加一个获取收藏景点的列表请求 【在文件my_api.js文件中添加】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口(适配服务端返回 Token) export const login async (code, avatar) > {const res await http…...
【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)
升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点,但无自动故障转移能力,Master宕机后需人工切换,期间消息可能无法读取。Slave仅存储数据,无法主动升级为Master响应请求ÿ…...
Unit 1 深度强化学习简介
Deep RL Course ——Unit 1 Introduction 从理论和实践层面深入学习深度强化学习。学会使用知名的深度强化学习库,例如 Stable Baselines3、RL Baselines3 Zoo、Sample Factory 和 CleanRL。在独特的环境中训练智能体,比如 SnowballFight、Huggy the Do…...
06 Deep learning神经网络编程基础 激活函数 --吴恩达
深度学习激活函数详解 一、核心作用 引入非线性:使神经网络可学习复杂模式控制输出范围:如Sigmoid将输出限制在(0,1)梯度传递:影响反向传播的稳定性二、常见类型及数学表达 Sigmoid σ ( x ) = 1 1 +...
浅谈不同二分算法的查找情况
二分算法原理比较简单,但是实际的算法模板却有很多,这一切都源于二分查找问题中的复杂情况和二分算法的边界处理,以下是博主对一些二分算法查找的情况分析。 需要说明的是,以下二分算法都是基于有序序列为升序有序的情况…...
Python ROS2【机器人中间件框架】 简介
销量过万TEEIS德国护膝夏天用薄款 优惠券冠生园 百花蜂蜜428g 挤压瓶纯蜂蜜巨奇严选 鞋子除臭剂360ml 多芬身体磨砂膏280g健70%-75%酒精消毒棉片湿巾1418cm 80片/袋3袋大包清洁食品用消毒 优惠券AIMORNY52朵红玫瑰永生香皂花同城配送非鲜花七夕情人节生日礼物送女友 热卖妙洁棉…...

处理vxe-table 表尾数据是单独一个接口,表格tableData数据更新后,需要点击两下,表尾才是正确的
修改bug思路: 分别把 tabledata 和 表尾相关数据 console.log() 发现 更新数据先后顺序不对 settimeout延迟查询表格接口 ——测试可行 升级↑:async await 等接口返回后再开始下一个接口查询 ________________________________________________________…...
「全栈技术解析」推客小程序系统开发:从架构设计到裂变增长的完整解决方案
在移动互联网营销竞争白热化的当下,推客小程序系统凭借其裂变传播、精准营销等特性,成为企业抢占市场的利器。本文将深度解析推客小程序系统开发的核心技术与实现路径,助力开发者打造具有市场竞争力的营销工具。 一、系统核心功能架构&…...