`

java web 二维码生成 工具类 内嵌图片 背景图片 彩色二维码

阅读更多
基于 google zxing

1.添加Maven依赖:

<dependency>
			<groupId>net.glxn.qrgen</groupId>
			<artifactId>javase</artifactId>
			<version>2.0</version>
		</dependency>


2.封装二维码对象

import java.io.InputStream;
import java.io.Serializable;

/**
 * Created by Gjh on 2016/5/18.
 * 封装生成二维码数据传输对象
 */
public class QrCodeDTO implements Serializable {

    /**
     * 背景图流
     */
    private InputStream backImageStream;
    /**
     * 内嵌图流
     */
    private InputStream innerImageStream;
    /**
     * 二维码内容
     */
    private String content;
    /**
     * 生成二维码宽度
     */
    private int imageWidth = 300;
    /**
     * 生成二维码高度
     */
    private int imageHeight = 300;
    /**
     * 生成图片宽度
     */
    private int outerImageWidth;
    /**
     * 生成图片高度
     */
    private int outerImageHeight;
    /**
     * 生成二维码边框宽度(默认边框:2)
     */
    private int frameWidth = 2;
    /**
     * 内嵌图片宽度
     */
    private int innerImageWidth;
    /**
     * 内嵌图片高度
     */
    private int innerImageHeight;
    /**
     * 二维码颜色(ARGB)(默认值:0xff000000)
     */
    private int argb = 0xff000000;

    public QrCodeDTO() {
    }

    /**
     * 构建二维码数据传输对象
     * @param content
     *          内容
     * @param imageWidth
     *          生成宽度
     * @param imageHeight
     *          生成高度
     */
    public QrCodeDTO(String content, int imageWidth, int imageHeight) {
        this.content = content;
        this.imageWidth = imageWidth;
        this.imageHeight = imageHeight;
    }

    /**
     * 构建带有内嵌图片的二维码数据传输对象
     * @param innerImageStream
     *          内嵌图片流
     * @param content
     *          二维码内容
     * @param imageWidth
     *          生成图片宽度
     * @param imageHeight
     *          生成图片高度
     * @param innerImageWidth
     *          内嵌图片的宽度
     * @param innerImageHeight
     *          内嵌图片的高度
     */
    public QrCodeDTO(InputStream innerImageStream, String content, int imageWidth, int imageHeight, int innerImageWidth, int innerImageHeight) {
        this.innerImageStream = innerImageStream;
        this.content = content;
        this.imageWidth = imageWidth;
        this.imageHeight = imageHeight;
        this.innerImageWidth = innerImageWidth;
        this.innerImageHeight = innerImageHeight;
    }

    /**
     * 构建带有背景图 内嵌图的 二维码数据传输对象
     * @param backImageStream
     * @param innerImageStream
     * @param content
     * @param imageWidth
     * @param imageHeight
     * @param outterImageWidth
     * @param outterImageHeight
     * @param frameWidth
     * @param innerImageWidth
     * @param innerImageHeight
     * @param argb
     */
    public QrCodeDTO(InputStream backImageStream, InputStream innerImageStream, String content, int imageWidth, int imageHeight, int outterImageWidth, int outterImageHeight, int frameWidth, int innerImageWidth, int innerImageHeight, int argb) {
        this.backImageStream = backImageStream;
        this.innerImageStream = innerImageStream;
        this.content = content;
        this.imageWidth = imageWidth;
        this.imageHeight = imageHeight;
        this.outerImageWidth = outterImageWidth;
        this.outerImageHeight = outterImageHeight;
        this.frameWidth = frameWidth;
        this.innerImageWidth = innerImageWidth;
        this.innerImageHeight = innerImageHeight;
        this.argb = argb;
    }

    public InputStream getBackImageStream() {
        return backImageStream;
    }

    public void setBackImageStream(InputStream backImageStream) {
        this.backImageStream = backImageStream;
    }

    public InputStream getInnerImageStream() {
        return innerImageStream;
    }

    public void setInnerImageStream(InputStream innerImageStream) {
        this.innerImageStream = innerImageStream;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public int getImageWidth() {
        return imageWidth;
    }

    public void setImageWidth(int imageWidth) {
        this.imageWidth = imageWidth;
    }

    public int getImageHeight() {
        return imageHeight;
    }

    public void setImageHeight(int imageHeight) {
        this.imageHeight = imageHeight;
    }

    public int getOuterImageWidth() {
        return outerImageWidth;
    }

    public void setOuterImageWidth(int outerImageWidth) {
        this.outerImageWidth = outerImageWidth;
    }

    public int getOuterImageHeight() {
        return outerImageHeight;
    }

    public void setOuterImageHeight(int outerImageHeight) {
        this.outerImageHeight = outerImageHeight;
    }

    public int getFrameWidth() {
        return frameWidth;
    }

    public void setFrameWidth(int frameWidth) {
        this.frameWidth = frameWidth;
    }

    public int getInnerImageWidth() {
        return innerImageWidth;
    }

    public void setInnerImageWidth(int innerImageWidth) {
        this.innerImageWidth = innerImageWidth;
    }

    public int getInnerImageHeight() {
        return innerImageHeight;
    }

    public void setInnerImageHeight(int innerImageHeight) {
        this.innerImageHeight = innerImageHeight;
    }

    public int getArgb() {
        return argb;
    }

    public void setArgb(int argb) {
        this.argb = argb;
    }
}


3.工具类
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import org.apache.commons.lang3.StringUtils;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by Gjh on 2016/5/18.
 * 二维码生成工具
 */
public class QrGenUtils {

    // 二维码写码器
    private static MultiFormatWriter mutiWriter = new MultiFormatWriter();

    //Test
    public static void main(String[] args) {
        try {
            //新建二维码数据传输对象(内容,二维码 宽度 高度)
            QrCodeDTO code = new QrCodeDTO("http://www.baidu.com", 270, 270);
            code.setArgb(0xffaaee44);       //设置二维码颜色(可选)
            code.setFrameWidth(10);         //设置二维码边框宽度(可选)

            //添加背景(可选)
            code.setBackImageStream(new FileInputStream(new File("D:\\back.png")));
            code.setOuterImageWidth(300);
            code.setOuterImageHeight(300);

            //添加内嵌图片(可选)
            code.setInnerImageStream(new FileInputStream(new File("D:\\logo.png")));
            code.setInnerImageHeight(80);
            code.setInnerImageWidth(80);

            //生成二维码,并写入指定文件
            encode(code, "D:\\qrcode.jpg");

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 生成二维码 并存盘到指定文件
     * @param code
     *          封装二维码信息 QrCode
     * @param targetFile
     *          生成二维码文件(文件格式 jpg)
     */
    public static void encode(QrCodeDTO code, String targetFile) {
        try {
            ImageIO.write(genBarcode(code), "jpg", new File(targetFile));
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 生成二维码 返回内存流
     * @param code
     *          封装QrCode对象
     * @return
     *          返回图片流
     */
    public static OutputStream encode(QrCodeDTO code) {
        try {
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            ImageIO.write(genBarcode(code), "jpg", os);
            InputStream is = new ByteArrayInputStream(os.toByteArray());
            return  os;
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 根据QrCode 生成二维码图片
     * @param code
     * @return
     */
    private static BufferedImage genBarcode(QrCodeDTO code) {
        try {
            //二维码内容是必须的
            if(StringUtils.isBlank( code.getContent())){
                throw new Exception("二维码内容不能为空!");
            }

            if(code.getInnerImageStream() != null && (code.getInnerImageHeight() > code.getImageHeight()
                    || code.getInnerImageWidth() > code.getImageWidth() || code.getInnerImageWidth() == 0 || code.getInnerImageHeight() == 0)){
                throw new Exception("内嵌图片长宽(必须设置)不能大于二维码图片长宽");
            }

            if(code.getBackImageStream() != null && (code.getOuterImageHeight() < code.getImageHeight()
                    || code.getOuterImageWidth() < code.getImageWidth() || code.getOuterImageHeight() == 0 || code.getOuterImageWidth() == 0)){
                throw new Exception("背景图长宽(必须设置)不能小于二维码图片长宽");
            }

            if((float)code.getInnerImageWidth() / code.getImageWidth() > 0.3 || (float)code.getInnerImageHeight() / code.getImageHeight() > 0.3){
                throw new Exception("内嵌图大小不能超过二维码图片的30%,否则生成的二维码不容易识别");
            }

            //声明二维码内容编码及错误修正级别
            Map<EncodeHintType, Object> hint = new HashMap<EncodeHintType, Object>();
            hint.put(EncodeHintType.CHARACTER_SET, "utf-8");
            hint.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
            hint.put(EncodeHintType.MARGIN, 1);

            //获取缩放后 背景图的像素点集合
            int[][] outerPixels = null;
            if(code.getBackImageStream() != null){
                //定比例缩放或放大背景图
                BufferedImage outerImage = scale(code.getBackImageStream(), code.getOuterImageHeight(), code.getOuterImageWidth(), true);
                outerPixels = new int[code.getOuterImageWidth()][code.getOuterImageHeight()];
                for (int i = 0; i < outerImage.getWidth(); i++) {
                    for (int j = 0; j < outerImage.getHeight(); j++) {
                        outerPixels[i][j] = outerImage.getRGB(i, j);
                    }
                }
            }

            //获取缩放后 内嵌图的像素点集合
            int[][] innerPixels = null;
            if(code.getInnerImageStream() != null){
                //定比例缩放或放大背景图
                BufferedImage innerImage = scale(code.getInnerImageStream(), code.getInnerImageHeight(), code.getInnerImageWidth(), true);
                innerPixels = new int[code.getInnerImageWidth()][code.getInnerImageHeight()];
                for (int i = 0; i < innerImage.getWidth(); i++) {
                    for (int j = 0; j < innerImage.getHeight(); j++) {
                        innerPixels[i][j] = innerImage.getRGB(i, j);
                    }
                }
            }

            // 生成二维码
            BitMatrix matrix = mutiWriter.encode(code.getContent(), BarcodeFormat.QR_CODE, code.getImageWidth(), code.getImageHeight(), hint);

            if(innerPixels != null || outerPixels != null) {
                if(innerPixels != null && outerPixels == null){
                    // 二维矩阵转为一维像素数组
                    int halfW = matrix.getWidth() / 2;
                    int halfH = matrix.getHeight() / 2;
                    int[] pixels = new int[code.getImageWidth() * code.getImageHeight()];
                    int frameWidth = code.getFrameWidth();
                    int innerHalfW = code.getInnerImageWidth() / 2;

                    for (int y = 0; y < matrix.getHeight(); y++) {
                        for (int x = 0; x < matrix.getWidth(); x++) {
                            // 读取图片
                            if (x > halfW - innerHalfW && x < halfW + innerHalfW && y > halfH - innerHalfW
                                    && y < halfH + innerHalfW) {
                                pixels[y * code.getImageWidth() + x] = innerPixels[x - halfW + innerHalfW][y - halfH + innerHalfW];
                            }

                            // 在图片四周形成边框
                            else if ((x > halfW - innerHalfW - frameWidth && x < halfW - innerHalfW + frameWidth
                                    && y > halfH - innerHalfW - frameWidth && y < halfH + innerHalfW + frameWidth)
                                    || (x > halfW + innerHalfW - frameWidth && x < halfW + innerHalfW + frameWidth
                                    && y > halfH - innerHalfW - frameWidth
                                    && y < halfH + innerHalfW + frameWidth)
                                    || (x > halfW - innerHalfW - frameWidth && x < halfW + innerHalfW + frameWidth
                                    && y > halfH - innerHalfW - frameWidth
                                    && y < halfH - innerHalfW + frameWidth)
                                    || (x > halfW - innerHalfW - frameWidth && x < halfW + innerHalfW + frameWidth
                                    && y > halfH + innerHalfW - frameWidth
                                    && y < halfH + innerHalfW + frameWidth)) {
                                pixels[y * code.getImageWidth() + x] = 0xfffffff;
                            } else {
                                // 此处可以修改二维码的颜色,可以分别制定二维码和背景的颜色;
                                pixels[y * code.getImageWidth() + x] = matrix.get(x, y) ? code.getArgb() : 0xfffffff;
                            }
                        }
                    }
                    BufferedImage image = new BufferedImage(code.getImageWidth(), code.getImageHeight(), BufferedImage.TYPE_INT_RGB);
                    image.getRaster().setDataElements(0, 0, code.getImageWidth(), code.getImageHeight(), pixels);
                    return image;
                } else if(outerPixels != null){
                    // 二维矩阵转为一维像素数组
                    int halfW = code.getOuterImageWidth() / 2;
                    int halfH = code.getOuterImageHeight() / 2;
                    int[] pixels = new int[code.getOuterImageWidth() * code.getOuterImageHeight()];
                    int frameWidth = code.getFrameWidth();
                    int innerHalfW = matrix.getWidth() / 2;
                    int iconHalfW = code.getInnerImageWidth() / 2;

                    for (int y = 0; y < code.getOuterImageHeight(); y++) {
                        for (int x = 0; x < code.getOuterImageWidth(); x++) {
                            // 绘制二维码
                            if (x > halfW - innerHalfW && x < halfW + innerHalfW && y > halfH - innerHalfW && y < halfH + innerHalfW) {
                                pixels[y * code.getOuterImageWidth() + x] = matrix.get((x - halfW + innerHalfW), (y - halfH + innerHalfW))? (outerPixels[x][y]) : 0xfffffff;
                                if(innerPixels != null) {
                                    if(x > halfW - iconHalfW && x < halfW + iconHalfW && y > halfH - iconHalfW && y < halfH + iconHalfW) {
                                        pixels[y * code.getOuterImageWidth() + x] = innerPixels[x - halfW +iconHalfW][y - halfH +iconHalfW];
                                    }
                                }
                            }
                            // 在图片四周形成边框
                            else if ((x > halfW - innerHalfW - frameWidth && x < halfW - innerHalfW + frameWidth
                                    && y > halfH - innerHalfW - frameWidth && y < halfH + innerHalfW + frameWidth)
                                    || (x > halfW + innerHalfW - frameWidth && x < halfW + innerHalfW + frameWidth
                                    && y > halfH - innerHalfW - frameWidth
                                    && y < halfH + innerHalfW + frameWidth)
                                    || (x > halfW - innerHalfW - frameWidth && x < halfW + innerHalfW + frameWidth
                                    && y > halfH - innerHalfW - frameWidth
                                    && y < halfH - innerHalfW + frameWidth)
                                    || (x > halfW - innerHalfW - frameWidth && x < halfW + innerHalfW + frameWidth
                                    && y > halfH + innerHalfW - frameWidth
                                    && y < halfH + innerHalfW + frameWidth)) {
                                pixels[y * code.getOuterImageWidth() + x] = outerPixels[x][y];//0xfffffff;
                            } else {
                                //背景图绘制
                                pixels[y * code.getOuterImageWidth() + x] = outerPixels[x][y];
                            }
                        }
                    }
                    BufferedImage image = new BufferedImage(code.getOuterImageWidth(), code.getOuterImageHeight(), BufferedImage.TYPE_INT_RGB);
                    image.getRaster().setDataElements(0, 0, code.getOuterImageWidth(), code.getOuterImageHeight(), pixels);
                    return image;
                }
            } else {
                int[] pixels = new int[code.getImageWidth() * code.getImageHeight()];
                for (int y = 0; y < matrix.getHeight(); y++) {
                    for (int x = 0; x < matrix.getWidth(); x++) {
                        pixels[y * code.getImageWidth() + x] = matrix.get(x, y) ? code.getArgb() : 0xfffffff;
                    }
                }
                BufferedImage image = new BufferedImage(code.getImageWidth(), code.getImageHeight(), BufferedImage.TYPE_INT_RGB);
                image.getRaster().setDataElements(0, 0, code.getImageWidth(), code.getImageHeight(), pixels);
                return image;
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 把传入的原始图像按高度和宽度进行缩放,生成符合要求的图标
     *
     * @param inputStream
     *            图片流
     * @param height
     *            目标高度
     * @param width
     *            目标宽度
     * @param hasFiller
     *            比例不对时是否需要补白:true为补白; false为不补白;
     * @throws IOException
     */
    private static BufferedImage scale(InputStream inputStream, int height, int width, boolean hasFiller)
            throws IOException {
        double ratio = 0.0; // 缩放比例
        BufferedImage srcImage = ImageIO.read(inputStream);
        if(srcImage.getWidth() != width || srcImage.getHeight() != height) {
            if(width == 0 ) width = srcImage.getWidth();
            if(height == 0) height = srcImage.getHeight();
            Image destImage = srcImage.getScaledInstance(width, height, BufferedImage.SCALE_SMOOTH);
            // 计算比例
            if ((srcImage.getHeight() > height) || (srcImage.getWidth() > width)) {
                if (srcImage.getHeight() > srcImage.getWidth()) {
                    ratio = (new Integer(height)).doubleValue() / srcImage.getHeight();
                } else {
                    ratio = (new Integer(width)).doubleValue() / srcImage.getWidth();
                }
                AffineTransformOp op = new AffineTransformOp(AffineTransform.getScaleInstance(ratio, ratio), null);
                destImage = op.filter(srcImage, null);
            }
            if (hasFiller) {// 补白
                BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
                Graphics2D graphic = image.createGraphics();
                graphic.setColor(Color.white);
                graphic.fillRect(0, 0, width, height);
                if (width == destImage.getWidth(null))
                    graphic.drawImage(destImage, 0, (height - destImage.getHeight(null)) / 2, destImage.getWidth(null),
                            destImage.getHeight(null), Color.white, null);
                else
                    graphic.drawImage(destImage, (width - destImage.getWidth(null)) / 2, 0, destImage.getWidth(null),
                            destImage.getHeight(null), Color.white, null);
                graphic.dispose();
                destImage = image;
            }
            return (BufferedImage) destImage;
        } else {
            return srcImage;
        }
    }
}

4.效果图


  • 大小: 20.2 KB
分享到:
评论

相关推荐

    使用Zxing实现二维码生成器内嵌图片

    综上所述,这篇文章主要讲解了如何使用ZXing库在Java中生成内嵌有图片的二维码,涉及到了条码编码、图形处理和文件操作等多个技术点。这个功能在产品推广、营销活动以及个性化服务等领域有广泛应用。

    Java 生成二维码 依赖包

    接下来,"Qrcode_swetake.j"这个文件可能是一个专用于生成二维码的Java类或者组件,由Swetake或者其他开发者编写。Swetake是一个早期的二维码生成库,可能提供了自定义样式和图形化选项,使得生成的二维码更具个性化...

    java生成二维码(基于springboot)部署tomcat

    在本文中,我们将深入探讨如何使用Java和Spring Boot框架生成二维码并将其部署到Tomcat服务器。这个项目展示了Spring Boot的强大之处,它简化了Java应用程序的开发,并提供了与各种服务集成的能力,包括创建二维码。...

    谷歌Zxing:快捷生成二维码、扫码、支持扫描本地相册中的二维码。

    这个库提供了一整套工具,使得开发者能够方便地在应用程序中集成二维码和条形码的生成与扫描功能。ZXing,这个名字来源于交通斑马线,象征着在数据流中引导和交叉的信息,其主要目标是简化二维码和条形码的处理流程...

    QrCode_java.zip

    【QrCode_java.zip】是一个基于Java开发的二维码生成工具,专为生成带有参数和内嵌自定义图片的二维码而设计。这个工具包名为QRCodeUtil,提供了完整的功能,允许开发者轻松地在Java环境中创建个性化的二维码。下面...

    安卓Android源码——zxing 生成二维码名片.rar

    在安卓开发中,生成和解析二维码是一项常见的功能,ZXing(Zebra Crossing)是一个开源项目,提供了多种二维码和条形码处理工具。在这个项目中,我们将关注如何使用ZXing库在Android应用中生成二维码名片。首先,...

    java源码 钉钉扫码登陆 示例源码 2018127

    - `QrCodeGenerator.java`: 可能用于生成二维码的工具类,通常会使用第三方库如ZXing或Google的Charts API。 - `Utils.java`: 通用工具类,可能包含签名、加密、解密等方法,这些都是与钉钉API交互时必不可少的。 ...

    zxing二维码扫描功能

    这个组件允许你在自己的应用中内嵌二维码扫描界面,而无需跳转到其他应用。以下是集成步骤: 1. 添加依赖:在项目的build.gradle文件中,添加ZXing的依赖库。 ``` dependencies { implementation '...

    仿嘻嘻哈哈右下角固定的二维码代码,无JS,纯CSS代码,兼容主流浏览器.rar

    此外,为了在没有JavaScript的情况下显示二维码,可能使用了CSS伪元素或者内嵌的背景图像。例如,可以创建一个包含二维码数据的div,并通过背景图像来展示: ```css .qrcode { width: 200px; /* 设置二维码的宽度 ...

    CSS3右侧悬浮二维码返回顶部特效代码

    - 生成二维码通常需要借助第三方库或在线工具,将其转换为图片(如PNG或SVG),然后在HTML中作为背景图片或者内嵌图像插入。 8. **事件监听**: - JavaScript可以用来监听用户的滚动事件,当页面滚动到底部时,...

    NET条形码操作类

    .NET条形码操作类是C#编程环境下用于生成和显示条形码的一种工具,它能够帮助开发者在Asp.Net页面上便捷地展示条形码图片。条形码是一种广泛应用于商品标识、物流管理、图书管理等领域的一维码或二维码表示方式,...

    Zxing Jar包 使用例子

    当开发者选择使用Zxing的Jar包时,意味着他们想要将解码功能内嵌到Java项目中,而无需直接依赖Zxing源代码。以下是一个简单的步骤,展示如何使用Zxing Jar包: 1. **获取Zxing Jar**:首先,你需要从Zxing的官方...

    基于ssm+vue本科生导师指导平台.zip

    - `src/main/java`:存放所有Java源代码,包括SpringBoot的启动类、Controller、Service、DAO层以及实体类(Entity)。 - `pom.xml`:Maven或Gradle的项目配置文件,管理项目的依赖库。 2. **前端代码**: - `...

    基于微信小程序的校园兼职系统.zip

    - SpringBoot的起步依赖、自动配置、内嵌式Web服务器的使用。 - SpringMVC的控制器、模型、视图和处理器适配器的配置与使用。 - MyBatis的XML映射文件和动态SQL,以及与数据库的交互。 - 数据库设计,如MySQL,包括...

    工程硕士学位论文 基于Android+HTML5的移动Web项目高效开发探究

    GCF 谷歌内嵌浏览器框架, 使用此插件,用户可以通过Internet Explorer的用户界面,以Chrome内核的渲染方式浏览网页。Chrome Frame 会把最新版的Chrome Webkit 内核和JavaScript 引擎注入到IE中, IE浏览器将获得...

    基于springboot+vue的物资仓储物流管理系统源码数据库.zip

    SpringBoot的核心特性包括自动配置、内嵌式Web服务器(如Tomcat)、健康检查和Actuator监控工具等。在这个系统中,SpringBoot作为后端框架,提供了快速构建RESTful API的能力,支持数据访问、安全控制、错误处理等...

    支付宝手机网页支付MP4视频

    4. **调用支付接口**:通过SDK,开发者可以调用支付宝提供的接口,如"alipay.trade.page.pay"接口,生成支付二维码或者跳转至支付宝支付页面。在请求中,需要包含订单信息(如商品标题、价格、交易号等)。 5. **...

    行业文档-设计装置-利用食品饮料瓶作为信息传播媒体的方法.zip

    通过在瓶身上印刷二维码、AR增强现实标识或内嵌智能芯片,食品饮料瓶可以承载丰富的信息,如品牌故事、产品成分、健康提示,甚至互动游戏和优惠券,这大大提升了消费者的参与度和品牌粘性。 在实施这种传播方法时,...

    微信小程序项目插件集合WX-Plug-In-master.zip

    9. **工具类插件**:如二维码扫描、图片压缩、文件操作等实用工具,提高开发效率。 10. **分析统计**:提供用户行为分析和数据统计功能,帮助开发者了解用户使用习惯,优化产品。 在使用这些插件时,开发者需要...

    企业图书管理系统

    企业图书管理系统是一款专为企业设计的综合管理工具,旨在优化图书和杂志的采购、分类、借阅及归还流程,同时兼顾企业内部部门管理和员工(读者)管理,以及规范企业规章制度。下面将详细介绍这个系统的关键功能和...

Global site tag (gtag.js) - Google Analytics