赞
踩
目录
模板包含三部分:
- <div class="t-upload">
- <ion-grid>
- <!-- {{ fileList }} -->
-
- <!-- 已经上传的图片 -->
- <template v-if="fileList?.length">
- <ion-col v-for="(img, index) in fileList" :key="img?.FILE_ID" size="4">
- <img
- class="file"
- :src="getImgUrl(img)"
- alt=""
- @click="goEnlargeImage(index)"
- />
- <img
- v-if="!readonly"
- class="delete"
- src="@/assets/image/common/upload-delete.png"
- @click.stop="removeFile(img?.FILE_ID)"
- />
- </ion-col>
- </template>
-
- <!-- 添加图片按钮 -->
- <template v-if="!readonly">
- <ion-col v-if="!fileList?.length || fileList?.length < 9" size="4">
- <img
- class="add-file"
- src="@/assets/image/common/upload-add.png"
- @click="addMediaFile()"
- />
- </ion-col>
- </template>
-
- <template v-if="!fileList?.length && readonly">
- <div class="fs-14">暂无附件</div>
- </template>
- </ion-grid>
- </div>
点击添加按钮后,会出现一个弹框,让用户选择图片来源:
这个很简单,使用 ionic 的 actionSheetController 即可实现,根据用户的选择,决定执行的方法
- async addFile(max: number, callback: any) {
- const actionSheet = await actionSheetController.create({
- header: '附件类型选择',
- buttons: [
- {
- text: '拍照',
- handler: () => {
- this.camera({
- quality: 100,
- destinationType: 1,
- sourceType: 1,
- targetWidth: 1080,
- targetHeight: 1920,
- mediaType: 0,
- encodingType: 1,
- })
- .then(async (res) => {
- callback(res, 'photo');
- })
- .catch((err) => {
- publicService.toast('拍照失败,请重试');
- });
- },
- },
- {
- text: '相册',
- handler: () => {
- this.slectImagePicker({
- maximumImagesCount: max,
- quality: 50,
- })
- .then((res) => {
- callback(res, 'img');
- })
- .catch(() => {
- publicService.toast('相册打开失败');
- });
- },
- },
- {
- text: '取消',
- role: 'cancel',
- handler: () => {
- console.error('Cancel clicked');
- },
- },
- ],
- });
- await actionSheet.present();
- }
安装 cordova 插件:
- @awesome-cordova-plugins/camera@6.4.0
- cordova-plugin-camera@7.0.0
容易出现的问题:在真机调试时,点击拍照,提示我传入了非法参数
解决方案:升级 camera 插件版本,原来用的版本是 4.1.4,升级到 7.0.0 后 自动解决问题
此方法最终返回一个图片对象信息
- // 用于拍照或从相册选择照片
- import { Camera, CameraOptions } from '@awesome-cordova-plugins/camera';
-
- /**
- * 拍照
- * @param opts 拍照配置
- * @returns
- */
- camera(opts: CameraOptions): Promise<any> {
- return new Promise((resolve, reject) => {
- Camera.getPicture(opts)
- .then((res: ChooserResult) => {
- resolve(res);
- })
- .then((error) => {
- reject('native camera error');
- });
- });
- }
安装 cordova 插件:
- @awesome-cordova-plugins/image-picker@6.4.0
- cordova-plugin-telerik-imagepicker@2.3.6
容易出现的问题:在相册选择界面中,确认取消按钮是英文
解决方案:在 node_modules 里,找插件源码中的 xml 文件,搜索相关英文单词,改成中文
此方法最终返回一组图片对象信息
- // 用于从相册中选择照片
- import { ImagePicker, ImagePickerOptions } from '@awesome-cordova-plugins/image-picker';
-
- /**
- * 照片选择
- * @param opts
- * @returns
- */
- slectImagePicker(opts: ImagePickerOptions): Promise<any> {
- // console.log('照片选择 ImagePicker ---', ImagePicker);
- return new Promise((resolve, reject) => {
- ImagePicker.getPictures(opts)
- .then((res) => {
- resolve(res);
- })
- .catch(() => {
- reject('slectImagePicker native error');
- });
- });
- }
安装 cordova 插件:
- @awesome-cordova-plugins/file-transfer@6.4.0
- cordova-plugin-file-transfer@1.7.1
容易出现的问题:
解决方案:
- // 文件上传下载
- import {
- FileTransfer,
- FileUploadOptions,
- } from '@awesome-cordova-plugins/file-transfer';
-
- /**
- * 文件上传
- * @param fileUrl 文件路径
- * @param url 服务器地址
- * @param opts 配置项
- * @returns
- */
- fileLoad(
- fileUrl: string,
- url: string,
- opts: FileUploadOptions
- ): Promise<any> {
- return new Promise((resolve, reject) => {
- // 创建文件上传实例
- const file = FileTransfer.create();
- file
- .upload(fileUrl, url, opts, false)
- .then((res) => {
- publicService.closeLoading(this.loading);
- this.loading = null;
- resolve(res);
- })
- .catch((err) => {
- console.log('文件上传错误 native ---', err);
- publicService.closeLoading(this.loading);
- this.loading = null;
- reject('文件上传发生错误');
- });
- });
- }
- /**
- * 文件上传
- * @param fileUrl 附件地址
- * @paramascriptionTypename 附件名称
- */
- function fileUpload(fileUrl: string, name?: string) {
- // 获取文件名称
- const pathArr = state.fileUrl.split('?')[0].split('/') || '';
- // 文件格式后缀
- const suffix = state.fileUrl.substring(
- state.fileUrl.lastIndexOf('.') + 1
- );
- // 文件格式后缀
- const suffixs = ['png', 'jpg', 'jpeg', 'svg'];
-
- // 文件类型验证 通过后再上传文件
- let fileTypeValidate = true;
-
- if (state.fileUrl && !suffix) {
- fileTypeValidate = false;
- toast('不支持的文件类型');
- } else if (!suffixs.includes(suffix)) {
- fileTypeValidate = false;
- toast(`不支持${suffix}文件类型`);
- }
-
- // 若文件格式不合法,则不进行上传
- if (!fileTypeValidate) {
- if (publicService.loading) {
- publicService.closeLoading(publicService.loading);
- publicService.loading = null;
- }
- return;
- }
-
- // 获取文件名称
- const fileName = new Date().getTime() + (name || `${pathArr[pathArr.length - 1]}`);
- nativeService
- .fileLoad(fileUrl, encodeURI(API.uploadFile.serviceApi), {
- fileName, // 将文件保存在服务器上时,要使用的文件名
- fileKey: 'form_file', // 表单元素名称,默认为 file,也可以和后端协商,文件流会存储在这个变量中
- httpMethod: 'POST', // 上传接口请求方式
- params: {
- // 业务数据ID(用于业务关联附件)
- businessKey: props.businessKey,
- // 表单ID(可为空)- 分组
- inputFileId: props.inputFileId,
- // 文件
- form_file: fileUrl,
- // 登录用户
- createUser: userInfos.userId,
- },
- })
- .then((res) => {
- console.log('upload.vue 上传接口响应 ---', res.response);
- const testJX = JSON.parse(res.response);
- console.log('尝试解析 ---', testJX);
-
- if (publicService.loading) {
- publicService.closeLoading(publicService.loading);
- publicService.loading = null;
- }
- // 获取文件列表
- getFiles();
- })
- .catch((err) => {
- console.error(err);
- });
- }
获取图片列表 getFiles 的几个场景:
每次获取了图片列表后,都应该 emit 最新的图片列表信息
上面说过,拍照返回的是一个图片信息,相册选择返回的是一组图片信息
根据返回信息的类型,可以拿到图片在手机本地的路径、名称,并依次调用文件上传
- nativeService.addFile(
- 9 - state.fileList.length,
- (res: any, fileType: string, name?: string) => {
- if (fileType === 'photo') {
- publicService.loading = publicService.sloading('拍照上传中,请稍候...');
- state.fileUrl = res;
- // 文件上传
- fileUpload(res, name || '');
- } else if (Array.isArray(res)) {
- if (res.length) {
- publicService.loading = publicService.sloading('相册选择照片上传中,请稍候...');
- }
- res.forEach(async (item, index1) => {
- state.fileUrl = item;
- state.fileName = name || '';
- // 文件上传
- await fileUpload(item, name || '');
- });
- } else {
- publicService.loading = publicService.sloading('附件上传中,请稍候...');
- state.fileUrl = res;
- state.fileName = name || '';
- // 文件上传
- fileUpload(res, name || '');
- }
- }
- );
使用 ionic modalController 创建一个弹框页面
在方法内部传入 图片放大组件、组件需要的各种参数、默认展示的图片索引 等信息
- /**
- * 打开图片预览界面
- * @param index 当前点击的图片索引
- */
- async function goEnlargeImage(index: number) {
- // console.log('t-upload.vue 点击的图片索引 ---', index);
- const modal = await modalController.create({
- component: EnlargeImage as any,
- componentProps: {
- pictures: state.fileList,
- initialSlide: index,
- time: new Date().getTime() + '',
- },
- cssClass: 'enlarge-image-modal',
- });
- await modal.present();
- }
因为博主使用的是 ionic7,已经不存在 ion-slide 等组件了
通过官网提示 Vue Slides Guide: How to Get Swiper for Vue on Ionic Apps,决定使用 swiper 插件实现需求
组件接受俩参数:
模板如下:
- <ion-page>
- <ion-header>
- <ion-toolbar color="primary">
- <ion-buttons slot="end" @click="closePage()">
- <ion-icon class="close-icon" :icon="close"></ion-icon>
- </ion-buttons>
- </ion-toolbar>
- </ion-header>
-
- <ion-content>
- <swiper :initialSlide="initialSlide" @transitionStart="start($event)">
- <swiper-slide v-for="(item, index) in stateImageList" :key="index">
- <!-- <div class="img-title">
- {{ item.FILE_NAME }}
- </div> -->
- <div class="img-box" :style="{ 'max-height': maxHeight }">
- <img
- v-if="
- !item.FILE_SUFFIX.toLowerCase() ||
- (item.FILE_SUFFIX.toLowerCase() !== 'mp4' &&
- item.FILE_SUFFIX.toLowerCase() !== 'mp3')
- "
- :src="getImgUrl(item)"
- :style="{ 'max-height': maxHeight }"
- />
- </div>
- <!-- {{ getImgUrl(item) }} -->
- </swiper-slide>
- </swiper>
- </ion-content>
- </ion-page>
ionic 官网说的安装 swiper:npm install swiper@latest
执行了这个命令,npm 只会给你装上 swiper/vue,没给你装 swiper/modules,这样问题非常大,因为 Navigation, Pagination 等模块必须安装 swiper/modules,才能进行引入,咱需要手动安装哦
引入 swiper 相关内容:
- // swiper
- import { Swiper, SwiperSlide } from 'swiper/vue';
- import { Navigation, Pagination } from 'swiper/modules';
- import 'swiper/css';
- import 'swiper/css/navigation';
- import 'swiper/css/pagination';
- import '@ionic/vue/css/ionic-swiper.css';
-
- // 响应式变量
- const state = reactive({
- // swiper 扩展模块
- // modules: [Navigation, Pagination],
- // 最大高度
- maxHeight: window.innerHeight - 100,
- });
-
- // 图片列表
- const stateImageList = computed(() => {
- return JSON.parse(JSON.stringify(props.pictures));
- });
-
- function start(ev: any) {
- // console.log('ev ---', ev, stateImageList.value);
- }
-
- /**
- * 关闭当前页面
- */
- function closePage() {
- modalController.dismiss();
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。