Vue+Element(el-upload+el-form的使用)+springboot

10 篇文章 0 订阅
7 篇文章 0 订阅

目录

1、编写模板

 2、发请求调接口

 3、后端返回数据

1.编写实体类

2.Controller类 

3、interface接口(Service层接口)

 4.Service(接口实现)

5、interface接口(Mapper层接口)

6、xml

7、goods.sql

8、goods_img

4、upload相关参数 


 说明(该案例是一个el-form和el-upload结合的,逻辑是:需要先保存输入框的内容才能上传图片,分别调用了4(查询,删除、插入,上传图片)个接口)

1、编写模板

<template>
  <div class="container">
    <el-card class="box-card">
      <div slot="header" class="clearfix">
        <span>商品详情</span>
      </div>
      <el-form ref="form" label-width="100px">
        <el-form-item label="商品id:">
          <el-input v-model="id" disabled></el-input>
        </el-form-item>
        <el-form-item label="商品名称:">
          <el-input v-model="name" placeholder="请输入内容"></el-input>
        </el-form-item>
        <el-form-item label="商品价格:">
          <el-input-number v-model="price" :step="10" :min="10" :max="100"></el-input-number>
        </el-form-item>
        <el-button size="small" type="success" @click="editGoods">保存</el-button>
      </el-form>

      <el-upload
        ref="upload"
        class="upload-demo"
        action="`${process.env.VUE_APP_API_URL}/upload/uploadImage`"
        multiple
        accept="images/png"
        list-type="picture-card"
        drag
        :limit="10"
        :data="uploadData"
        :before-upload="beforeUpload"
        :on-progress="uploadProgress"
        :on-success="handleSuccess"
        :on-error="uploadError"
        :on-preview="handlePreview"
        :before-remove="beforeRemove"
        :on-remove="handleRemove"
        :on-exceed="handleExceed"
        :file-list="fileList"
      >
        <el-button size="small" type="primary">点击上传</el-button>
      </el-upload>
      <div>
        <el-divider>只能上传jpg/png文件,且不超过2MB</el-divider>
      </div>
      <el-dialog :visible.sync="dialogVisible">
        <img width="100%" :src="dialogImageUrl" alt="">
      </el-dialog>

    </el-card>
  </div>
</template>

 2、发请求调接口

<script>
export default {
  name: "uploadFile",
  data() {
    return {
      name: '',
      price: '',
      id: '',
      uploadData: {
        id: ''
      },
      fileList: [],
      dialogImageUrl: '',
      dialogVisible: false
    };
  },
  mounted() {
    const id = this.$route.params.id;
    this.selectById(id);
    console.log("id:" + id);
    this.uploadData.id = id; //商品id
    this.id = id
  },
  methods: {
    editGoods() {
      if (this.uploadData.id == '' && this.uploadData.id == null) {
        this.$message({
          message: 'id不能为空',
          type: 'error'
        })
        return;
      } else if (this.name == '' && this.name == null) {
        this.$message({
          message: '名称不能为空',
          type: 'error'
        })
        return;
      }
      this.$request.post('upload/editGoods', {
        id: this.id,
        name: this.name,
        price: this.price
      }).then((res) => {
        if (res.code === '200') {
          this.$message({
            message: res.data.message,
            type: 'success'
          })
          this.selectById(this.id)
        }
      })
    },
    selectById(id) {
      this.$request.post('upload/selectGoods', {
        id: id
      }).then((res) => {
        this.id = id;
        this.name = res.data.name
        this.price = res.data.price;

        let imgList = res.data.imgList.list;
        if (imgList.length > 0) {
          this.fileList = imgList[0].imageUrlList.map((item) => {
            return {
              name: item.imageName,
              url: item.imageUrl,
              id: item.imgId //新增
            };
          })
        }
      })
    },
    //图片上传成功之后:将上传图片的数据添加到fileList
    handleSuccess(response, file, fileList) {
      // 根据后端返回的数据修改fileList集合
      console.log("图片上传成功之后response:" + JSON.stringify(response));

      let uploadImg = response.data.map((item) => {
        return {
          name: item.imageName,
          url: item.imageUrl,
          id: item.imgId, //新增
          status: 'finished',
        };
      })
      console.log("###" + JSON.stringify(uploadImg));

      fileList.push(...uploadImg);

      // 更新fileList,触发重新渲染
      this.$forceUpdate();
    },

    //上传失败的逻辑
    uploadError(err, file, fileList) {
      this.$message({
        message: err.message,
        type: "error",
      });
    },
    saveGoods() {
      if (this.name == '') {
        this.$message({
          message: "请输入商品名称",
          type: "error",
        });
        return;
      }
      if (this.price == '') {
        this.$message({
          message: "请输入商品价格",
          type: "error",
        });
        return;
      }
      this.$request.post('upload/saveGoods', {

        name: this.name,
        price: this.price

      }).then((res) => {
        this.$message({
          message: "保存成功",
          type: "success",
        });
        this.uploadData.id = res.data;
      })

    },

    //点击上传成功之后的图片进行预览
    handlePreview(file) {
      this.dialogImageUrl = file.url;
      this.dialogVisible = true;
    },

    //上传之前调用:校验类型、大小
    beforeUpload(file) {
      if (this.uploadData.id == '') {
        this.$message({
          message: "请先保存数据,再上传图片",
          type: "error",
        });
        return false;
      }

      const fileSize = file.size / Math.pow(2, 20);
      if (file.type !== 'image/jpg' && file.type !== 'image/png') {
        this.$message.error('只能上传jpg/png文件')
        return false;
      }

      if (fileSize > 2) {
        this.$message.error("图片不能超过2MB")
        return false;
      }

      return true;
    },

    //删除之前的逻辑
    beforeRemove(file, fileList) {
      return this.$confirm(`确定要删除图片 ${file.name}吗?`);
    },

    //删除的逻辑
    handleRemove(file, fileList) {
      console.log("删除图片的file:" + JSON.stringify(file));
      if (this.id !== '') {
        //发送请求,删除商品的图片
        console.log("删除时的商品id:" + this.id);
        this.$request.post('upload/deleteGoodsImage?imgId=' + file.id, {
          id: this.id,
          imgId: file.id
        }).then((res) => {
          this.$message({
            message: "删除成功",
            type: "success",
          });
          // 根据删除的文件信息修改fileList集合
          const index = fileList.findIndex(item => item.id === file.id);
          if (index !== -1) {
            fileList.splice(index, 1);
          }
          // 返回true允许删除,返回false阻止删除
          return true;
        })
      }
    },

    //文件超出个数限制时的钩子
    handleExceed(files, fileList) {
      this.$message.warning(`当前限制选择 3 个文件,本次选择了 ${files.length} 个文件,共选择了 ${files.length + fileList.length} 个文件`);
    },

    //上传时,执行的逻辑
    uploadProgress(event, file, fileList) {

    }
  },
}
</script>

 3、后端返回数据

1.编写实体类

Goods实体类


public class Goods extends Page {
    private String id;
    private String name;
    private int price;
    private List<GoodsImg> imageUrlList;
    private String status;

    public Goods() {
        super();
    }
    public Goods(int pageNum, int pageSize, String keyWord) {
        super(pageNum, pageSize, keyWord);
    }

    public Goods(int pageNum, int pageSize, String keyWord, String id, String name, int price, List<GoodsImg> imageUrlList, String status) {
        super(pageNum, pageSize, keyWord);
        this.id = id;
        this.name = name;
        this.price = price;
        this.imageUrlList = imageUrlList;
        this.status = status;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getPrice() {
        return price;
    }

    public void setPrice(int price) {
        this.price = price;
    }

    public List<GoodsImg> getImageUrlList() {
        return imageUrlList;
    }

    public void setImageUrlList(List<GoodsImg> imageUrlList) {
        this.imageUrlList = imageUrlList;
    }

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }
}
GoodsImg实体类
package com.example.goods_admin.entity;

public class GoodsImg {

    private String imgId;

    private String goodsId;

    private String imageName;

    private String imageUrl;

    private String status;

    public GoodsImg(String imgId, String goodsId, String imageName, String imageUrl, String status) {
        this.imgId = imgId;
        this.goodsId = goodsId;
        this.imageName = imageName;
        this.imageUrl = imageUrl;
        this.status = status;
    }

    public GoodsImg() {
    }

    public String getImgId() {
        return imgId;
    }

    public void setImgId(String imgId) {
        this.imgId = imgId;
    }

    public String getGoodsId() {
        return goodsId;
    }

    public void setGoodsId(String goodsId) {
        this.goodsId = goodsId;
    }

    public String getImageUrl() {
        return imageUrl;
    }

    public void setImageUrl(String imageUrl) {
        this.imageUrl = imageUrl;
    }

    public String getImageName() {
        return imageName;
    }

    public void setImageName(String imageName) {
        this.imageName = imageName;
    }

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }
}

page实体类

package com.example.goods_admin.entity;

public class Page {
    private int pageNum;

    private int pageSize;

    private String keyWord;

    public Page() {

    }

    public String getKeyWord() {
        return keyWord;
    }

    public void setKeyWord(String keyWord) {
        this.keyWord = keyWord;
    }

    public Page(int pageNum, int pageSize, String keyWord) {
        this.pageNum = pageNum;
        this.pageSize = pageSize;
        this.keyWord = keyWord;
    }

    public int getPageNum() {
        return pageNum;
    }

    public void setPageNum(int pageNum) {
        this.pageNum = pageNum;
    }

    public int getPageSize() {
        return pageSize;
    }

    public void setPageSize(int pageSize) {
        this.pageSize = pageSize;
    }
}

 

2.Controller类 

@RestController
@RequestMapping("/upload")
public class UploadFileController {

    @Autowired
    UploadFileService uploadFileService;

    @PostMapping("/uploadImage")
    public Result uploadImage(@RequestPart MultipartFile[] file,@RequestParam("id") String id) {
        return uploadFileService.uploadImage(file,id);
    }
    @PostMapping("/saveGoods")
    public Result saveGoods(@RequestBody Goods goods) {
        return uploadFileService.saveGoods(goods);
    }

    @PostMapping("/deleteGoodsImage")
    public Result deleteGoodsImage(@RequestBody Goods goods,@RequestParam("imgId") String imgId) {
        return uploadFileService.deleteGoodsImage(goods,imgId);
    }

    @PostMapping("/selectGoods")
    public Result selectGoods(@RequestBody Goods goods) {
        return uploadFileService.selectGoods(goods);
    }
    @PostMapping("/selectGoodsList")
    public Result selectGoodsList(@RequestBody Goods goods) {
        return uploadFileService.selectGoodsList(goods);
    }

    @PostMapping("/deleteGoods")
    public Result deleteGoods(@RequestBody Goods goods) {
        return uploadFileService.deletegoods(goods);
    }

    //json传参
    @PostMapping("/editGoods")
    public Result editGoods(@RequestBody Goods goods) {
        return uploadFileService.editGoods(goods);
    }


   
}
3、interface接口(Service层接口)

public interface UploadFileService {
    Result uploadImage(MultipartFile[] imageFile, String id);

    Result saveGoods(Goods goods);

    Result deleteGoodsImage(Goods goods, String imgId);


    Result selectGoods(Goods goods);

    Result deletegoods(Goods goods);

    Result editGoods(Goods goods);

    Result selectGoodsList(Goods goods);
}
 4.Service(接口实现)


import java.io.IOException;
import java.io.InputStream;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.file.*;
import java.util.*;

@Service
public class UploadFileServiceImpl implements UploadFileService {
    @Autowired
    UploadFileMapper uploadFileMapper;

    @Override
    public Result uploadImage(MultipartFile[] imageFile, String goodsId) {

        // 指定目标文件夹路径 liunx windows
        String folderPath = "/home/files/";

        // 更新商品信息
        Goods goods=new Goods();
        goods.setId(goodsId);

        try {
            List<GoodsImg> goodsImgList = new ArrayList<>();
            // 遍历上传的文件数组
            for (MultipartFile file : imageFile) {
                //图片的全称,test.png
                String originalFilename = file.getOriginalFilename();

                Path path = Paths.get(originalFilename);
                String fileExtension = getFileExtension(path);

                GoodsImg goodsImg = new GoodsImg();
                String imgId = UUID.randomUUID().toString();

                String alisImgName = imgId + "." + fileExtension;

                // 构建目标文件路径
                Path targetPath = Paths.get(folderPath, alisImgName);

                // 将文件保存到目标文件夹(使用输入输出流上传文件到服务器)
                try (InputStream inputStream = file.getInputStream();
                     FileChannel destinationChannel = FileChannel.open(targetPath, StandardOpenOption.CREATE, StandardOpenOption.WRITE)) {
                    destinationChannel.transferFrom(Channels.newChannel(inputStream), 0, Long.MAX_VALUE);
                }

                goodsImg.setImgId(imgId);
                goodsImg.setGoodsId(goodsId);
                goodsImg.setImageName(originalFilename);
                goodsImg.setImageUrl("http://124.220.110.203:8080/api/"+alisImgName);
                goodsImg.setStatus("1");
                goodsImgList.add(goodsImg);
            }


            uploadFileMapper.saveGoodsImg(goodsImgList);

            // 文件保存成功,返回相应信息
            return Result.succeed("文件保存成功!",goodsImgList);
        } catch (IOException e) {
            e.printStackTrace();

            // 文件保存失败,返回错误信息
            return  Result.failed ("文件保存失败!",new HashMap<String,Object>());
        }
    }

    private static String getFileExtension(Path path) {
        String fileName = path.getFileName().toString();
        int lastIndexOfDot = fileName.lastIndexOf(".");
        if (lastIndexOfDot > 0) {
            return fileName.substring(lastIndexOfDot + 1);
        }
        return "";
    }



    @Override
    public Result saveGoods(Goods goods) {
        goods.setStatus("1");
        String id = UUID.randomUUID().toString();
        goods.setId(id);
        int count=uploadFileMapper.saveGoods(goods);
        if (count==1){
            return Result.succeed("保存成功",id);
        }else{
            return Result.failed("保存失败",id);
        }
    }

    @Override
    public Result deleteGoodsImage(Goods goods, String imgId) {

        if (goods.getId()!="" && goods.getId()!=null && imgId!="" && imgId!=null ){
            GoodsImg goodsImg = new GoodsImg();
            goodsImg.setImgId(imgId);
            goodsImg.setGoodsId(goods.getId());
            goodsImg.setStatus("0");
            int count=uploadFileMapper.updateGoodsImg(goodsImg);
            if (count==1){
                return Result.succeed("删除成功");
            }else{
                return Result.failed("删除失败");
            }
        }
        return null;
    }

    @Override
    public Result selectGoods(Goods goods) {


        int pageNum = goods.getPageNum()==0?1:goods.getPageNum();
        int pageSize = goods.getPageSize()==0?10:goods.getPageSize();

        //1、开启分页查询
        PageHelper.startPage(pageNum,pageSize);

        //2、查询结果
        List<Goods> goodsList  = uploadFileMapper.selectGoods(goods);

        //3、封装结果
        PageInfo<Goods> goodsPageInfo = new PageInfo<>(goodsList);

        Goods goodsRes =uploadFileMapper.selectGoodsById(goods.getId());

        HashMap<String, Object> resultMap = new HashMap<>();
        resultMap.put("imgList",goodsPageInfo);
        resultMap.put("name","");
        resultMap.put("price","");
        if (goodsRes!=null){
            resultMap.put("name",goodsRes.getName());
            resultMap.put("price",goodsRes.getPrice());
        }

        //4、返回
        return Result.succeed("查询成功",resultMap);
    }

    @Override
    public Result deletegoods(Goods goods) {

        //删除:物理删除,逻辑删除

        int count=uploadFileMapper.updateGoods(goods);
        if (count==1){
            return Result.succeed("删除成功");
        }else{
            return Result.failed("删除失败");
        }

    }

    @Override
    public Result editGoods(Goods goods) {
        int count=uploadFileMapper.updateGoods(goods);
        if (count==1){
            return Result.succeed("修改成功");
        }else{
            return Result.failed("修改失败");
        }
    }

    @Override
    public Result selectGoodsList(Goods goods) {
        int pageNum = goods.getPageNum()==0?1:goods.getPageNum();
        int pageSize = goods.getPageSize()==0?10:goods.getPageSize();

        //1、开启分页查询
        PageHelper.startPage(pageNum,pageSize);

        //2、查询结果
        List<Goods> goodsList  = uploadFileMapper.selectGoodsList(goods);

        //3、封装结果
        PageInfo<Goods> goodsPageInfo = new PageInfo<>(goodsList);

        //4、返回
        return Result.succeed("查询成功",goodsPageInfo);
    }


}
5、interface接口(Mapper层接口)
public interface UploadFileMapper {

    int saveGoods(Goods goods);
    int updateGoods(Goods goods);

    int deleteGoodsImage(Goods goods);


    List<Goods> selectGoods(Goods goods);

    List<Goods> selectGoodsList(Goods goods);

    int saveGoodsImg(List<GoodsImg> goodsImgList);

    int updateGoodsImg(GoodsImg goodsImg);

    Goods selectGoodsById(String id);
}
6、xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.goods_admin.mapper.UploadFileMapper">

    <resultMap id="BaseResultMap" type="com.example.goods_admin.entity.Goods">
        <id column="id" jdbcType="VARCHAR" property="id" />
        <result column="name" jdbcType="VARCHAR" property="name" />
        <result column="price" jdbcType="INTEGER" property="price" />
        <result column="status" jdbcType="VARCHAR" property="status" />
        <collection property="imageUrlList" ofType="com.example.goods_admin.entity.GoodsImg">
            <result property="imgId" column="imgId"/>
            <result property="goodsId" column="goodsId"/>
            <result property="imageName" column="imageName"/>
            <result property="imageUrl" column="imageUrl"/>
        </collection>
    </resultMap>
    <insert id="saveGoods">
        INSERT INTO goods (
        <if test="id != null and id != ''">
            id
        </if>
        <if test="name != null and name != ''">
            ,name
        </if>
        <if test="price != null and price != ''">
            ,price
        </if>
        <if test="status != null and status != ''">
            ,status
        </if>
        ) VALUES (
        <if test="id != null and id != ''">
            #{id}
        </if>
        <if test="name != null and name != ''">
            ,#{name}
        </if>
        <if test="price != null and price != ''">
            ,#{price}
        </if>
        <if test="status != null and status != ''">
            ,#{status}
        </if>
        )
    </insert>
    <insert id="saveGoodsImg">
        insert into goods_img(
        imgId
            ,goodsId
            ,imageName
            ,imageUrl
            ,status
        )VALUES
        <foreach collection="list" item="item"  separator=",">
           ( #{item.imgId}
            ,#{item.goodsId}
            ,#{item.imageName}
            ,#{item.imageUrl}
            ,#{item.status})
        </foreach>
    </insert>

    <delete id="deleteGoodsImage">
        delete from goods_img where id = #{id}
    </delete>
    <select id="selectGoods" resultMap="BaseResultMap" parameterType="com.example.goods_admin.entity.Goods">
        SELECT
        g.id,g.name,g.price,g.status,gi.goodsId ,gi.imageName,gi.imageUrl,gi.imgId
        FROM
        goods g
        LEFT JOIN goods_img gi ON g.id = gi.goodsId
        <where>
            g.`status`='1'

            <if test="keyWord !=null and keyWord!=''">
                and g.name like concat('%', #{keyWord}, '%')
            </if>
            <if test="id !=null and id!=''">
                and g.id =#{id} and gi.`status`='1'
            </if>
        </where>
    </select>
    <select id="selectGoodsById" resultType="com.example.goods_admin.entity.Goods">
        select * from goods
        where id=#{id} and status='1'
    </select>
    <select id="selectGoodsList" resultType="com.example.goods_admin.entity.Goods">
        select * from goods
        <where>
            `status`='1'
            <if test="keyWord !=null and keyWord!=''">
                and name like concat('%', #{keyWord}, '%')
            </if>
        </where>
    </select>

    <update id="updateGoods">
        update goods
        <set>
            <if test="name!=''and name!=null">name=#{name},</if>
            <if test="price!=''and price!=null">price=#{price},</if>
            <if test="status!=''and status!=null">status=#{status}</if>
        </set>
        where
            id = #{id}
    </update>
    <update id="updateGoodsImg">
        update goods_img
            <set>
                <if test="goodsId!=''and goodsId!=null">goodsId=#{goodsId},</if>
                <if test="imageUrl!=''and imageUrl!=null">imageUrl=#{imageUrl},</if>
                <if test="status!=''and status!=null">status=#{status}</if>
                <if test="imageName!=''and imageName!=null">imageName=#{imageName},</if>
            </set>
            where
                imgId=#{imgId}
    </update>

</mapper>
7、goods.sql

 

/*
 Navicat Premium Data Transfer

 Source Server         : database
 Source Server Type    : MySQL
 Source Server Version : 80029
 Source Host           : localhost:3306
 Source Schema         : goods_admin

 Target Server Type    : MySQL
 Target Server Version : 80029
 File Encoding         : 65001

 Date: 28/01/2024 22:43:08
*/

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for goods
-- ----------------------------
DROP TABLE IF EXISTS `goods`;
CREATE TABLE `goods`  (
  `id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '主键',
  `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '商品名称',
  `price` int NULL DEFAULT NULL COMMENT '商品价格',
  `status` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '状态',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;

SET FOREIGN_KEY_CHECKS = 1;
8、goods_img

 

/*
 Navicat Premium Data Transfer

 Source Server         : database
 Source Server Type    : MySQL
 Source Server Version : 80029
 Source Host           : localhost:3306
 Source Schema         : goods_admin

 Target Server Type    : MySQL
 Target Server Version : 80029
 File Encoding         : 65001

 Date: 28/01/2024 22:43:19
*/

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for goods_img
-- ----------------------------
DROP TABLE IF EXISTS `goods_img`;
CREATE TABLE `goods_img`  (
  `imgId` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
  `goodsId` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
  `imageUrl` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
  `status` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
  `imageName` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
  PRIMARY KEY (`imgId`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;

SET FOREIGN_KEY_CHECKS = 1;

4、upload相关参数 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

娃哈哈哈哈呀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值