支付宝小程序 | 上传图片组件(添加默认样式以及自定义上传样式)

支付宝,程序,上传,图片,组件,添加,默认,样式,以及,自定义 · 浏览次数 : 81

小编点评

```typescript import { useComponents, useMemo } from 'antd'; import { uploadImage } from '/components/upload-image/upload-image'; import './upload-images.less.ts'; // 定义组件 const Tip1 = useMemo(() => 添加图片(非必传), ['tip1']); const Tip2 = useMemo(() => 最多可以添加{{imgCount}}张图片, ['tip2']); // 获取默认标题 const defaultTitle = useMemo(() => '上传图片', ['defaultTitle']); // handleUpload函数 const handleUpload = (file, fileList) => { this.setData({ imgValue: fileList, deleteImage: file }); }; // handleDelete函数 const handleDelete = (file, fileList) => { const arr = [] let { deleteImage } = this.data arr.push(file) const newImage = deleteImage.concat(arr) this.setData({ imgValue: fileList, deleteImage: newImage }); }; // 生成内容时带简单的排版 const content = useMemo(() => { // 定义排版 const tip1 = ; const tip2 = ; // 使用默认标题 const defaultTitle = ; // 生成内容时带排版 return (
{tip1} {tip2}
{/* 加载图标 */}
{defaultTitle}
); }, [defaultTitle]); // 使用memo缓存默认标题 export default content; ```

正文

使用my.uploadFile、 my.chooseImage 的方式实现图片上传

注意: 使用该方式上传文件,后端也需要参照官方文档进行修改

https://opendocs.alipay.com/mini/api/kmq4hc

一、展示效果

默认上传

demo4.gif

自定义上传

demo5.gif

二、上代码

(一)、上传组件

image.png

<view class="custom-upload-container">
  <view a:for="{{imageUrl}}" class="custom-upload images-show">
    <view class="clear" catchTap="handleDelete" data-url="{{item}}">
      <am-icon type="CloseCircleFill" color="#333333" size="x-small" />
    </view>
    <view a:if="{{item.status == 'fail' ? true : false}}" class="loading">
      <loading type="spin" size="small" text="上传中..." loading="{{true}}" />
    </view>
    <image
      mode="aspectFill"
      src={{item}}
      catchTap="hanldeImageLook"
      data-url="{{item}}"
      data-index="{{index}}"
    />
  </view>

  <view
    a:if="{{imageUrl.length < maxCount && imageUrl.length > 0 ? true:false}}"
    class="custom-upload "
  >
    <view class="add" catchTap="handleSelectImage">
      <am-icon type="AddOutline" color="#333333" size="small" />
    </view>
  </view>

  <view catchTap="handleSelectImage" style="width:100%">
    <slot a:if="{{ imageUrl.length == 0 ?true:false }}">
      <view class="default-upload">
        <am-icon type="AddOutline" color="#333333" size="small" />
      </view>
    </slot>
  </view>
</view>

upload-image.ts

Component({
  mixins: [],
  data: {
    imageUrl: [],
    maxCount: 1,
    action: '', //上传的url地址
  },
  props: {
    maxCount: 1,
    onUpload: (image, imageArr) => {},
    onDelete: (image, imageArr) => {},
    value: [],
    action: '',
  },
  didMount() {
    const maxCount = this.props?.maxCount || 1
    const value = this.props?.value || []
    const action =
      this.props?.action ||  'xxxxxxxx'
    this.setData({
      maxCount,
      imageUrl: value,
      action,
    })
  },
  didUpdate() {},
  didUnmount() {},
  methods: {
    handleSelectImage() {
      const { imageUrl, maxCount } = this.data
      if (imageUrl.length == maxCount) {
        my.showToast({
          content: `最多上传${maxCount}张图片`,
        })
        return
      }
      my.chooseImage({
        sourceType: ['camera', 'album'],
        count: 1,
        success: (res) => {
          const path = res.apFilePaths[0]
          const DeviceId = my.getStorageSync({ key: 'DeviceId' }).data
          const ACCESS_TOKEN = my.getStorageSync({ key: '__AT__' }).data
          const { account } = my.getStorageSync({ key: 'userinfo' }).data as any
          const { action } = this.data
          const SYSTEM_ID =
            (my.getStorageSync({ key: 'SyStemId' }).data as string)
          my.uploadFile({
            url: action,
            fileType: 'image',
            fileName: 'file',
            filePath: path,
            name: 'file',
            //请求头信息
            header: {
              DeviceId: DeviceId,
              uname: account,
              System: SYSTEM_ID,
            },
            success: (res) => {
              const value = JSON.parse(res.data)
              if (value?.code == 200) {
                const { imageUrl } = this.data
                const newImageUrl = imageUrl.concat(value?.data)
                this.setData({
                  imageUrl: newImageUrl,
                })
                this.props.onUpload(value?.data, newImageUrl)
              } else {
                my.showToast({
                  content: value?.msg || '上传失败',
                })
              }
            },
            fail: (err) => {
              my.showToast({
                content: '上传失败',
              })
              const { imageUrl } = this.data
              const newImageUrl = imageUrl.concat([])
              this.setData({
                imageUrl: newImageUrl,
                status: 'fail',
              })
            },
          })
        },
      })
    },
    handleDelete(e) {
      const { url } = e.currentTarget.dataset
      const { imageUrl } = this.data
      const newData = imageUrl.filter((i) => i !== url)
      this.setData({
        imageUrl: newData,
      })
      this.props.onDelete(index, newData)
    },
    hanldeImageLook(e) {
      const { imageUrl } = this.data
      const { index } = e.currentTarget.dataset
      my.previewImage({
        current: index, // 当前显示图片
        urls: imageUrl,
        success: (res) => {
          console.log('debug----res', res)
        },
        fail: (error) => {
          console.log('debug----error', error)
        },
      })
    },
  },
})

upload-image.less

.custom-upload-container {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  background: #ffffff;
  padding: 16px;
  border-radius: 8px;
  .custom-upload,
  .images-show {
    width: 80px;
    height: 80px;
    background: #ffffff;
    border: 1px dashed #979797;
    border-radius: 6px;
    display: flex;
    justify-content: center;
    align-items: center;
    position: relative;
    margin-right: 30px;
    .add {
      position: absolute;
      margin: auto;
    }
    .clear {
      position: absolute;
      top: 0;
      right: 0;
      margin-top: -6px;
      margin-right: -6px;
    }
    > image {
      width: 100%;
      height: 100%;
      border-radius: 4px;
      background: #fff;
    }
    .loading {
      position: absolute;
      margin: auto;
      width: 100%;
      height: 100%;
      background-color: rgba(0, 0, 0, 0.5);
      .amd-loading-spin-container {
        width: 100%;
        height: 100%;
      }
      .amd-loading-spin-text {
        color: #ffff;
      }
    }
  }
  .custom-upload:nth-of-type(3n) {
    margin-right: 0px;
  }
  .images-show {
    border: none;
  }

  .default-upload {
    width: 100%;
    height: 80px;
    border-radius: 4px;
    border: 1px dashed #979797;
    display: flex;
    justify-content: center;
    align-items: center;
    background: #ffffff;
  }
}

upload-image.json

    {
      "component": true,
      "usingComponents": {
        "am-icon": "antd-mini/es/Icon/index",
        "loading": "antd-mini/es/Loading/index"
      }
    }

(二)、在页面中引用组件

pageX.axml

//自定义上传样式
<upload-image
  maxCount="{{imgCount}}"
  value="{{imgValue}}"
  onUpload="handleUpload"
  onDelete="handleDelete"
>
  <view class="uplload-images">
    <text class="tip1">添加图片(非必传)</text>
    <text class="tip2">最多可以添加{{imgCount}}张图片</text>
  </view>
</upload-image>

//默认样式
<upload-image
  maxCount="{{imgCount}}"
  value="{{imgValue}}"
  onUpload="handleUpload"
  onDelete="handleDelete"
>
</upload-image>

pageX.less

.uplload-images {
  width: 100%;
  height: 80px;
  background: #ffffff;
  border-radius: 8px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  .tip1 {
    font-size: 14px;
    font-family: PingFangSC-Regular, PingFang SC;
    font-weight: 400;
    color: #333333;
    line-height: 20px;
  }
  .tip2 {
    font-size: 12px;
    font-family: PingFangSC-Regular, PingFang SC;
    font-weight: 400;
    color: #999999;
    line-height: 16px;
    margin-top: 8px;
  }
}

pageX.json

{
  "defaultTitle": "上传图片",
  "usingComponents": {
       "upload-image":"/components/upload-image/upload-image" // 组件的路径
  }
}

pageX.ts

  data:{
    imgValue:[],
    imgCount:3,
   },
   handleUpload(file, fileList) {
      this.setData({
        imgValue: fileList,
      })
   },
    handleDelete(file, fileList) {
    const arr = []
    let { deleteImage } = this.data
    arr.push(file)
    const newImage = deleteImage.concat(arr)
    this.setData({
      imgValue: fileList,
      deleteImage: newImage,
    })
  },

与支付宝小程序 | 上传图片组件(添加默认样式以及自定义上传样式)相似的内容:

支付宝小程序 | 上传图片组件(添加默认样式以及自定义上传样式)

人们害怕他们不理解的东西。 People are afraid of what they don't understand.

支付宝小程序 | 自定义标题导航栏

效果 一 、page.json "transparentTitle": "always" 二、page.axml

支付宝小程序 | 下拉刷新、自动刷新、上拉加载

下拉刷新 (一)onPullDownRefresh方法 模拟器效果展示 实现如下 1、配置下拉选项 demo.json { "pullRefresh": true } 2、定义下拉方法 demo.js onPullDownRefresh() { //做相应的逻辑处理 }, 3、停止下拉 在加载完数据

支付宝小程序 | 获取网络状态

追光者终将光芒万丈

uniapp微信小程序转支付宝小程序踩坑(持续更新)

首先第一个,真有被折磨到! // 微信正常使用,支付宝不行 // 以下两种 微信、支付宝都正常使用

电子钱包小程序:技术与便捷的完美融合

随着移动支付的快速普及,支付宝、微信支付等电子钱包 App 成为了我们日常生活中不可或缺的一部分,手机充值、生活缴费、便利店付款等场景都离开不了。但是也逐步发现,电子钱包 App 们为了提供更加便捷的支付体验和功能,他们有一个共性就是都在往小程序线路发展。

支付宝接入技术

准备工作:去支付宝开放平台准备好以下东西 // 沙箱应用私钥(private key) private String shaxiang_app_private_Key = "MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDX0zMqoLHjndD

HarmonyOS 4.0 实况窗上线!支付宝实现医疗场景智能提醒

本文转载自支付宝体验科技,作者是蚂蚁集团客户端工程师博欢,介绍了支付宝如何基于 HarmonyOS 4.0 实况窗实现医疗场景履约智能提醒。 1.话题背景 8 月 4 日,华为在 HDC(华为 2023 开发者大会)上推出了新版本操作系统HarmonyOS 4.0,主打个性化与多元化的的口号。在功能

面试官随便问几个问题就知道你究竟做没做过微信支付宝支付

我将以面试官的角度来提问一些支付相关的问题,并做出回答,让你对企业中支付的全貌有个大概的认知,这里面有一个问题是我面试别人问过的,xdm看完了可以猜一猜是哪个。

一套基于 .NET Core 开发的支付SDK集 - paylink

前言 在我们的日常工作开发中对接一些第三方支付是比较常见的,如最常见的就是支付宝、微信支付的对接。今天给大家推荐一个基于.NET Core开发的支付SDK集:paylink,它极大简化了API调用及通知的处理流程从而大大提供我们的工作生产效率。 运行环境 .NET Core 3.1、.NET 6.0