当前位置:   article > 正文

flutter、微信小程序uni-app、web(avue)上传图片资源到oss_avue oss

avue oss

一、微信小程序上传图片资源到oss

微信小程序直传实践
使用的是uview的u-upload组件
1、表单页面
a、页面

	<u-upload :fileList="fileList" name="1" multiple :maxCount="3" @delete="deleteFun" @afterRead="afterRead"
					:previewFullImage="true"></u-upload>
  • 1
  • 2

b、主要js

async afterRead(event) {
				let fileArr = event.file;
				let fileList = this.fileList.concat(event.file);
				this.fileList = fileList; //显示在页面上的图片列表
				for (let i = 0; i < fileArr.length; i++) {
					let data = await initClient(); //获取需要的上传的参数,文件在后面
					const host = 'http://阿里后台配置的桶名.oss-cn-shenzhen.aliyuncs.com';
					const signature = data.signature;
					const ossAccessKeyId = data.OSSAccessKeyId;
					const policy = data.policy;
					const securityToken = data.securityToken;

					let tempFile = fileArr[i];
					let filePath =tempFile.url;
					
					let date = new Date();
					let year = date.getFullYear();
					let month = date.getMonth() + 1;
					let month2 = month < 10 ? "0" + month : month;
					let date2 = date.getDate() < 10 ? "0" + date.getDate() : date.getDate();
					let name = "";
					if (!tempFile.name) {
						let path = tempFile.url;
						let indexOf = path.lastIndexOf("/");
						name = path.substring(indexOf + 1);
					} else {
						name = tempFile.name;
					}
					let indexOf = name.lastIndexOf(".");
					let extension = name.substring(indexOf + 1);

					const key =
						`public/car/${tenantId}/${year}/${month2}/${date2}/${uuidv4()}.${extension}`;
					//const key = '/public/car/000000/2023/01/12/'+res.tempFiles[0].name;  //多了一根斜杠报错:InvalidObjectName
					uni.uploadFile({
						url: host, // 开发者服务器的URL。
						filePath: filePath, // 待上传文件的文件路径。
						name: 'file', // 必须填file。
						formData: {
							key,//传到服务器的地址,切记千万不要有斜杠
							policy,
							'success_action_status': '200', //让服务端返回200,不然,默认会返回204
							OSSAccessKeyId: ossAccessKeyId,
							signature,
							'x-oss-security-token': securityToken // 使用STS签名时必传。
						},
						success: (res2) => {
							if (res2.statusCode === 200) {
								let link = host + "/" + key;
								//调取后台接口
								saveAttachAPI({
									link: link,
									domainUrl: host,
									name: key,
									originalName: name,
									extension: extension,
									attachSize: tempFile.size
								}).then(([err, attach_data]) => {
									if (err) return;
									let params = {
										attachId: attach_data,
										link: link,
										originalName:name,
										attachCategory:1,
										businessType:1
									};
									this.requestFileList.push(params);//保存需要保存到后台的是数据
								})
							}
						},
						fail: err => {
							console.log(err);
						}
					});
				}
			}

		}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78

ossClient.js

const MpUploadOssHelper = require("./uploadOssHelper.js");

import {
	getStsAPI
} from "@/api/api/my.js"
import {
	getNowTime
} from "@/utils/utils.js"
export const initClient = async () => {
	let value = uni.getStorageSync('ossConfig'); //获取缓存里面储存的oss配置数据
	//对比时间和缓存里面是否有值,如果过期,需要重新获取sts参数
	if (value && value.expiration > getNowTime()) {
		return value;
	} else {
		let [err, data] = await getStsAPI();
		const mpHelper = new MpUploadOssHelper({
			// 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户并授权。
			accessKeyId: data.accessKeyId,
			accessKeySecret: data.accessKeySecret,
		});
		// 生成参数。
		const params = mpHelper.createUploadParams();
		params.securityToken = data.securityToken;
		params.expiration = data.expiration;
		//保存oss配置参数
		uni.setStorage({
			key: 'ossConfig',
			data: params,
		});
		return params;
	}

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

uploadOssHelper.js(这个是从oss文档里面copy出来的)

const crypto = require("crypto-js");

class MpUploadOssHelper {
  constructor(options) {
    this.accessKeyId = options.accessKeyId;
    this.accessKeySecret = options.accessKeySecret;
    // 限制参数的生效时间,单位为小时,默认值为1。
    this.timeout = options.timeout || 1; 
    // 限制上传文件的大小,单位为MB,默认值为10。
    this.maxSize = options.maxSize || 10;
  }

  createUploadParams() {
    const policy = this.getPolicyBase64();
    const signature = this.signature(policy);
    return {
      OSSAccessKeyId: this.accessKeyId,
      policy: policy,
      signature: signature,
    };
  }

  getPolicyBase64() {
    let date = new Date();
    // 设置policy过期时间。
    date.setHours(date.getHours() + this.timeout);
    let srcT = date.toISOString();
    const policyText = {
      expiration: srcT,
      conditions: [
        // 限制上传文件大小。
        ["content-length-range", 0, this.maxSize * 1024 * 1024],
      ],
    };
    const buffer = Buffer.from(JSON.stringify(policyText));
    return buffer.toString("base64");
  }

  signature(policy) {
    return crypto.enc.Base64.stringify(
      crypto.HmacSHA1(policy, this.accessKeySecret)
    );
  }
}

module.exports = MpUploadOssHelper;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46

二、flutter上传图片资源到OSS

利用组件: flutter_oss_aliyun
flutter_oss_aliyun
页面初始化的时候,调用此方法

  static initOss() async {
    String authorization =
        "${ProjectConfig.clientId}:${ProjectConfig.clientSecret}";
    String base64Authorization = base64Encode(utf8.encode(authorization));
    var prefs = await SharedPreferences.getInstance();
    Client2.init(
        stsUrl:
            '${ProjectConfig.baseUrl}/blade-resource/oss/endpoint/get-acs-param-ali',
        stsHeader: {
          'Authorization': 'Basic ${base64Authorization}',
          'Blade-Auth': 'bearer ${prefs.getString("accessToken")}',
          'Content-Type': 'application/json'
        },
        ossEndpoint: 'oss-cn-shenzhen.aliyuncs.com',
        bucketName: 'bucketName');
  }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

上传文件调用此方法:

  XFile? image = await _picker.pickImage(source: ImageSource.gallery,imageQuality: 40);
  //获取文件
   var file = await image?.readAsBytes();      
   //获取文件大小                                                
  int? size =
       file?.lengthInBytes;
   String uploadPath='upload/${ProjectConfig.tenantId}/${FunUtils.getNowDate()}/${uuid.v1()}.$extension';
                                                         
await Client2()
        .putObject(
  file!,//字节文件
  uploadPath,//上传到服务器上的地址
);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

三、web(avue)上传图片资源到OSS

main.js

//oss配置
Vue.prototype.aliConfig = {
  stsUrl:'/api/blade-resource/oss/endpoint/get-acs-param-ali', // 获取sts服务
  region:'oss-cn-shenzhen',
  bucket:'bucketName',
  tenantId:"000000",//租户id
  system:"car",//系统类型
  rsUrl:"/api/blade-resource/attach/save" //保存到后台的地址
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

修改avue上传模块源码
avue/packages/element-ui/upload/index.vue
修改源码对比
在这里插入图片描述

<template>
  <div :class="b()"
       v-loading.lock="loading">
    <el-upload :class="b({'list':listType=='picture-img','upload':disabled})"
               @click.native="handleClick"
               :action="action"
               :on-remove="handleRemove"
               :accept="acceptList"
               :before-remove="beforeRemove"
               :multiple="multiple"
               :on-preview="handlePreview"
               :limit="limit"
               :http-request="httpRequest"
               :drag="drag"
               :readonly="readonly"
               :show-file-list="isPictureImg?false:showFileList"
               :list-type="listType"
               :on-change="handleFileChange"
               :on-exceed="handleExceed"
               :disabled="disabled"
               :file-list="fileList">
      <template v-if="listType=='picture-card'">
        <i class="el-icon-plus"></i>
      </template>
      <template v-else-if="listType=='picture-img'">
        <el-image v-if="imgUrl"
                  :src="imgUrl"
                  :preview-src-list="[imgUrl]"
                  v-bind="allParams"
                  @mouseover="menu=true"
                  :class="b('avatar')"></el-image>
        <i v-else
           class="el-icon-plus"
           :class="b('icon')"></i>
        <div class="el-upload-list__item-actions"
             :class="b('menu')"
             v-if="menu"
             @mouseover="menu=true"
             @mouseout="menu=false"
             @click.stop="()=>{return false}">
          <i class="el-icon-zoom-in"
             @click.stop="handlePreview({url:imgUrl})"></i>
          <i class="el-icon-delete"
             v-if="!disabled"
             @click.stop="handleDelete(imgUrl)"></i>
        </div>
      </template>
      <template v-else-if="drag">
        <i class="el-icon-upload"></i>
        <div class="el-upload__text">
          将文件拖到此处,或
          <em>点击上传</em>
        </div>
      </template>
      <template v-else>
        <el-button size="small"
                   type="primary">点击上传</el-button>
      </template>
      <div slot="tip"
           class="el-upload__tip">{{tip}}</div>
    </el-upload>
    <el-dialog append-to-body
               :class="b('dialog')"
               top="0"
               :modal-append-to-body="true"
               :visible.sync="dialogVisible">
      <img v-if="typeList.img.test(dialogUrl)"
           :src="dialogUrl"
           style="max-width:100%"
           alt>
      <video v-else-if="typeList.video.test(dialogUrl)"
             controls="controls"
             style="max-width:100%"
             :src="dialogUrl"></video>
    </el-dialog>
  </div>
</template>

<script>
import create from "core/create";
import props from "../../core/common/props.js";
import event from "../../core/common/event.js";
import { getObjValue } from "utils/util";
import { detailImg } from "plugin/canvas/";
import { getToken } from "plugin/qiniu/";
import { getClient } from "plugin/ali/";
import packages from "core/packages";
export default create({
  name: "upload",
  mixins: [props(), event()],
  data () {
    return {
      menu: false,
      loading: false,
      typeList: {
        img: /(\.(gif|jpg|jpeg|png|GIF|JPG|PNG))|(data:image)/,
        video: /\.(swf|avi|flv|mpg|rm|mov|wav|asf|3gp|mkv|rmvb|ogg|mp4)/
      },
      dialogUrl: "",
      dialogType: true,
      dialogVisible: false,
      text: [],
      file: {}
    };
  },
  props: {
    data: {
      type: Object,
      default: () => {
        return {}
      }
    },
    preview: {
      type: Object,
      default: () => { }
    },
    value: {},
    onRemove: Function,
    showFileList: {
      type: Boolean,
      default: true
    },
    oss: {
      type: String
    },
    limit: {
      type: Number,
      default: 10
    },
    headers: {
      type: Object,
      default: () => {
        return {}
      }
    },
    accept: {
      type: [String, Array],
      default: ""
    },
    canvasOption: {
      type: Object,
      default: () => {
        return {};
      }
    },
    fileSize: {
      type: Number
    },
    drag: {
      type: Boolean,
      default: false
    },
    loadText: {
      type: String,
      default: "文件上传中,请稍等"
    },
    action: {
      type: String,
      default: ""
    },
    uploadBefore: Function,
    uploadAfter: Function,
    uploadDelete: Function,
    uploadPreview: Function,
    uploadError: Function
  },
  computed: {
    acceptList () {
      if (Array.isArray(this.accept)) {
        return this.accept.join(',')
      }
      return this.accept
    },
    homeUrl () {
      return this.propsHttp.home || ''
    },
    allParams () {
      if (this.typeList.video.test(this.imgUrl)) {
        return Object.assign({
          is: 'video'
        }, this.params)
      }
      return this.params
    },
    fileName () {
      return this.propsHttp.fileName || 'file'
    },
    isAliOss () {
      return this.oss === "ali";
    },
    isQiniuOss () {
      return this.oss === "qiniu";
    },
    isPictureImg () {
      return this.listType === "picture-img";
    },
    //单个头像图片
    imgUrl () {
      if (!this.validatenull(this.text)) {
        return this.homeUrl + this.text[0];
      }
    },
    fileList () {
      let list = [];
      const flag = this.isArray || this.isString;
      (this.text || []).forEach((ele, index) => {
        if (ele) {
          let name;
          //处理单个url链接取最后为label
          if (flag) {
            let i = ele.lastIndexOf('/');
            name = ele.substring(i + 1);
          }
          list.push({
            uid: index + '',
            status: 'done',
            name: flag ? name : ele[this.labelKey],
            url: this.homeUrl + (flag ? ele : ele[this.valueKey])
          });
        }
      });
      return list;
    }
  },
  created () { },
  watch: {},
  mounted () { },
  methods: {
    handleClick () {
      if (typeof this.click === "function")
        this.click({ value: this.text, column: this.column });
    },
    handleFileChange (file, fileList) {
      fileList.splice(fileList.length - 1, 1);
      if (typeof this.change === "function")
        this.change({ value: this.text, column: this.column });
    },
    handleSuccess (file) {
      if (this.isArray || this.isString) {
        this.text.push(file[this.urlKey]);
      } else if (this.isPictureImg) {
        this.text.splice(0, 1, file[this.urlKey])
      } else {
        let obj = {};
        obj[this.labelKey] = file[this.nameKey];
        obj[this.valueKey] = file[this.urlKey];
        this.text.push(obj);
      }
      this.$message.success("上传成功");
    },
    handleRemove (file, fileList) {
      this.onRemove && this.onRemove(file, fileList);
      this.delete(file);
      this.$message.success("删除成功");
    },
    handleError (error) {
      if (typeof this.uploadError === "function") {
        this.uploadError(error, this.column)
      }
    },
    delete (file) {
      if (this.isArray || this.isString) {
        (this.text || []).forEach((ele, index) => {
          if (ele === file.url) this.text.splice(index, 1);
        });
      } else {
        (this.text || []).forEach((ele, index) => {
          if (ele[this.valueKey] === file.url) this.text.splice(index, 1);
        });
      }
    },
    show (data) {
      this.loading = false;
      this.handleSuccess(data);
    },
    hide (msg) {
      this.loading = false;
      this.handleError(msg);
    },
    httpRequest (config) {
      this.loading = true;
      let file = config.file;
      const accept = file.type;
      const fileSize = file.size;
      this.file = config.file;
      let acceptList = this.acceptList;
      if (!Array.isArray(acceptList) && !this.validatenull(acceptList)) {
        acceptList = acceptList.split(',')
      }
      if (!this.validatenull(acceptList) && !acceptList.includes(accept)) {
        this.hide("文件类型不符合");
        return;
      }
      if (!this.validatenull(fileSize) && fileSize > this.fileSize) {
        this.hide("文件太大不符合");
        return;
      }
      const headers = Object.assign(this.headers, { "Content-Type": "multipart/form-data" });
      //oss配置属性
      let oss_config = {};
      let client = {};
      let param = new FormData();
      //附加属性
      for (let o in this.data) {
        param.append(o, this.data[o]);
      }
      const done = () => {
        let url = this.action;
        const callack = async (newFile) => {
          const uploadfile = newFile || file;
          param.append(this.fileName, uploadfile);
          //七牛云oss存储
          if (this.isQiniuOss) {
            if (!window.CryptoJS) {
              packages.logs("CryptoJS");
              this.hide();
              return;
            }
            oss_config = this.$AVUE.qiniu;
            const token = getToken(oss_config.AK, oss_config.SK, {
              scope: oss_config.scope,
              deadline: new Date().getTime() + oss_config.deadline * 3600
            });
            param.append("token", token);
            url = oss_config.bucket
          } else if (this.isAliOss) {
            if (!window.OSS) {
              packages.logs("AliOSS");
              this.hide();
              return;
            }
            // oss_config = this.$AVUE.ali;
            // "获取当前时间2023-01-12 20:36:55与this.$AVUE.aliExpiration比较"
             if( this.$AVUE.ali.accessKeyId == "" || (this.$AVUE.aliExpiration&&new Date()>new Date(this.$AVUE.aliExpiration.replace(/\-/g, "/")))){
              // let res = this.$axios.get(this.aliConfig.stsUrl);
              // console.log('res: ', res);
              await this.$axios.get(this.aliConfig.stsUrl).then(res=>{
                let data = res.data.data;
                let  ali =  {
                  // yourRegion填写Bucket所在地域。以华东1(杭州)为例,yourRegion填写为oss-cn-hangzhou。
                  region: this.aliConfig.region,
                  // 从STS服务获取的临时访问密钥(AccessKey ID和AccessKey Secret)。
                  accessKeyId: data.accessKeyId,
                  accessKeySecret: data.accessKeySecret,
                  // 从STS服务获取的安全令牌(SecurityToken)。
                  stsToken: data.securityToken,
                  // 填写Bucket名称。
                  bucket: this.aliConfig.bucket
                }
                this.$AVUE.ali = ali;
                this.$AVUE.aliExpiration = data.expiration;
              })
            }
            oss_config = this.$AVUE.ali;
            console.log('oss_config: ', oss_config);
            client = getClient(oss_config);
          }
          (() => {
            if (this.isAliOss) {
              let date = new Date();
              return client.put("/public/"+this.aliConfig.system+"/"+this.aliConfig.tenantId+"/"+date.getFullYear()+"/"+date.getMonth()+"/"+date.getDate()+"/"+uploadfile.name, uploadfile);
              // return client.put(uploadfile.name, uploadfile);
            } else {
              if (!window.axios) {
                packages.logs('axios');
                return Promise.reject()
              }
              return this.$axios.post(url, param, { headers });
            }
          })()
            .then(async res => {
              let list = {};
              if (this.isQiniuOss) {
                res.data.key = oss_config.url + res.data.key;
              }

              if (this.isAliOss) {
                let reg2 = new RegExp("/"+res.name);
                let domainUrl = res.url.replace(reg2,"");
                let params={
                  link:res.url,
                  domainUrl:domainUrl,
                  name:res.name,
                  originalName:uploadfile.name,
                  extension:(res.name).split(".")[1],
                  attachSize:uploadfile.size
                };
                await this.$axios.post(this.aliConfig.rsUrl,params).then(res1=>{
                  list = getObjValue(Object.assign({},res,{attachId:res1.data.data}), this.resKey, "object");
                });
              } else {
                list = getObjValue(res.data, this.resKey, "object");
              }

              if (typeof this.uploadAfter === "function")
                this.uploadAfter(
                  list,
                  () => {
                    this.show(list);
                  },
                  () => {
                    this.loading = false;
                  },
                  this.column
                );
              else this.show(list);
            })
            .catch(error => {
              if (typeof this.uploadAfter === "function")
                this.uploadAfter(error, this.hide, () => {
                  this.loading = false;
                }, this.column);
              else this.hide(error);
            });
        };
        if (typeof this.uploadBefore === "function")
          this.uploadBefore(this.file, callack, () => {
            this.loading = false;
          }, this.column);
        else callack();
      };
      //是否开启水印
      if (!this.validatenull(this.canvasOption)) {
        detailImg(file, this.canvasOption).then(res => {
          file = res;
          done();
        });
      } else {
        done();
      }
    },
    handleExceed (files, fileList) {
      this.$message.warning(
        `当前限制选择 ${this.limit} 个文件,本次选择了 ${
        files.length
        } 个文件,共上传了 ${files.length + fileList.length} 个文件`
      );
    },
    handlePreview (file) {
      const callback = () => {
        //判断是否为图片
        this.dialogUrl = file.url;
        if (this.typeList.img.test(file.url)) {
          this.dialogVisible = true;
          return;
        } else if (this.typeList.video.test(file.url)) {
          this.dialogVisible = true;
        }
      }
      if (typeof this.uploadPreview === "function") {
        this.uploadPreview(file, this.column, callback);
      } else {
        callback();
      }
    },
    handleDelete (file) {
      this.beforeRemove(file).then(() => {
        this.text = [];
      }).catch(() => {
      });
    },
    beforeRemove (file) {
      if (typeof this.uploadDelete === "function") {
        return this.uploadDelete(this.column, file);
      } else {
        return this.$confirm(`是否确定移除该选项?`);
      }
    }
  }
});
</script>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 294
  • 295
  • 296
  • 297
  • 298
  • 299
  • 300
  • 301
  • 302
  • 303
  • 304
  • 305
  • 306
  • 307
  • 308
  • 309
  • 310
  • 311
  • 312
  • 313
  • 314
  • 315
  • 316
  • 317
  • 318
  • 319
  • 320
  • 321
  • 322
  • 323
  • 324
  • 325
  • 326
  • 327
  • 328
  • 329
  • 330
  • 331
  • 332
  • 333
  • 334
  • 335
  • 336
  • 337
  • 338
  • 339
  • 340
  • 341
  • 342
  • 343
  • 344
  • 345
  • 346
  • 347
  • 348
  • 349
  • 350
  • 351
  • 352
  • 353
  • 354
  • 355
  • 356
  • 357
  • 358
  • 359
  • 360
  • 361
  • 362
  • 363
  • 364
  • 365
  • 366
  • 367
  • 368
  • 369
  • 370
  • 371
  • 372
  • 373
  • 374
  • 375
  • 376
  • 377
  • 378
  • 379
  • 380
  • 381
  • 382
  • 383
  • 384
  • 385
  • 386
  • 387
  • 388
  • 389
  • 390
  • 391
  • 392
  • 393
  • 394
  • 395
  • 396
  • 397
  • 398
  • 399
  • 400
  • 401
  • 402
  • 403
  • 404
  • 405
  • 406
  • 407
  • 408
  • 409
  • 410
  • 411
  • 412
  • 413
  • 414
  • 415
  • 416
  • 417
  • 418
  • 419
  • 420
  • 421
  • 422
  • 423
  • 424
  • 425
  • 426
  • 427
  • 428
  • 429
  • 430
  • 431
  • 432
  • 433
  • 434
  • 435
  • 436
  • 437
  • 438
  • 439
  • 440
  • 441
  • 442
  • 443
  • 444
  • 445
  • 446
  • 447
  • 448
  • 449
  • 450
  • 451
  • 452
  • 453
  • 454
  • 455
  • 456
  • 457
  • 458
  • 459
  • 460
  • 461
  • 462
  • 463
  • 464
  • 465
  • 466
  • 467
  • 468
  • 469
  • 470
  • 471
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小惠珠哦/article/detail/742021
推荐阅读
相关标签
  

闽ICP备14008679号