ZaiZai 2 lat temu
rodzic
commit
5ad1d7dac9
7 zmienionych plików z 446 dodań i 24 usunięć
  1. 42 0
      httpApi/modules/upload.js
  2. 13 0
      pages.json
  3. 248 0
      pages/image/form.vue
  4. 94 1
      pages/image/info.vue
  5. 8 6
      pages/image/view.vue
  6. 24 17
      uno.config.js
  7. 17 0
      utils/utils.js

+ 42 - 0
httpApi/modules/upload.js

@@ -0,0 +1,42 @@
+import baseURL from '@/config/baseURL'
+import {getTokenHeader} from '../request/header'
+import {getObjValue} from "js-fast-way";
+
+export const uploadApi = async (file, form= {}) => {
+    return new Promise((resolve) => {
+        let url = '/api/blade-resource/oss/endpoint/upload-file';
+        //#ifdef APP-PLUS
+        url = baseURL + 'blade-resource/oss/endpoint/upload-file'
+        //#endif
+        uni.uploadFile({
+            url: url,
+            name: 'file',
+            formData: form,
+            header: getTokenHeader(),
+            filePath: file,
+            success:(res) => {
+                const {code, msg, data} = JSON.parse(res?.data)
+                if (code === 200) {
+                    resolve({
+                        error: false,
+                        msg: msg,
+                        data: getObjValue(data)
+                    })
+                } else {
+                    resolve({
+                        error: true,
+                        msg: msg,
+                        data: {}
+                    })
+                }
+            },
+            fail:()=> {
+                resolve({
+                    error: true,
+                    msg: '上传失败',
+                    data: {}
+                })
+            }
+        });
+    })
+}

+ 13 - 0
pages.json

@@ -93,6 +93,19 @@
                 "navigationBarTitleText": "查看声像文件"
             }
         },
+        {
+            "path": "pages/image/info",
+            "style": {
+                "navigationBarTitleText": "声像资料详情"
+            }
+        },
+        {
+            "path": "pages/image/form",
+            "style": {
+                "navigationBarTitleText": "声像资料数据",
+                "navigationStyle": "default"
+            }
+        },
         {"path": "pages/task/index"},
         {
             "path": "pages/task/detail",

+ 248 - 0
pages/image/form.vue

@@ -0,0 +1,248 @@
+<template>
+    <hc-sys :isNavBar="false">
+        <uni-notice-bar text="请上传MP4、MOV格式的视频文件,文件大小不超过500M,只能上传1个视频文件" v-if="formData.type === 1"/>
+        <uni-notice-bar text="请上传JPG、JPEG、PNG格式的图片文件,大小不超过30M,最多10张图片文件" v-if="formData.type === 2"/>
+        <view class="relative bg-white mt-1 hc-p">
+            <!-- 文件上传 -->
+            <view class="hc-flex flex-wrap pb-3 mb-5" un-border-b="1 solid gray-2" v-if="formData.type === 2">
+                <template v-for="(item, index) in fileList" :key="index">
+                    <view class="hc-flex h-120 w-120 b-rounded mr-2 mt-2" @click="previewImg(index)">
+                        <hc-img :src="item" width="60" height="60" class="b-rounded"/>
+                        <view class="hc-tr bg-red-5 text-white text-center w-38 h-38 b-rounded-lb-1 b-rounded-tr-1" @click.stop="delFileClick(index)">
+                            <text class="relative cuIcon-close top--2 text-24"/>
+                        </view>
+                    </view>
+                </template>
+                <template v-if="fileList.length < 10">
+                    <view class="hc-flex-center h-120 w-120 b-rounded mt-2" un-border="2 dashed gray-2" @click="addFileClick">
+                        <text class="i-iconoir-plus text-70 text-gray-4"/>
+                    </view>
+                </template>
+            </view>
+            <!-- 表单 -->
+            <uni-forms ref="formRef" :rules="formRules" :modelValue="formData" :label-width="82">
+                <uni-forms-item label="题名" required name="title">
+                    <uni-easyinput v-model="formData.title" placeholder="请输入题名" />
+                </uni-forms-item>
+                <uni-forms-item label="文字说明" required name="textContent">
+                    <uni-easyinput type="textarea" v-model="formData.textContent" placeholder="请输入文字说明" />
+                </uni-forms-item>
+                <uni-forms-item label="拍摄时间" required name="shootingTimeStr">
+                    <uni-datetime-picker type="date" v-model="formData.shootingTimeStr" :end="dateEnd"/>
+                </uni-forms-item>
+                <uni-forms-item label="上传日期" required name="uploadTime">
+                    <uni-datetime-picker type="date" v-model="formData.uploadTime" :end="dateEnd"/>
+                </uni-forms-item>
+                <uni-forms-item label="拍摄者" required name="shootingUser">
+                    <uni-easyinput v-model="formData.shootingUser" placeholder="请输入拍摄者" />
+                </uni-forms-item>
+                <template v-if="formData.type === 2">
+                    <uni-forms-item label="照片号">
+                        <uni-easyinput v-model="formData.photoCode" placeholder="请输入照片号" />
+                    </uni-forms-item>
+                    <uni-forms-item label="底片号">
+                        <uni-easyinput v-model="formData.filmCode" placeholder="请输入底片号" />
+                    </uni-forms-item>
+                    <uni-forms-item label="参见号">
+                        <uni-easyinput v-model="formData.seeAlsoCode" placeholder="请输入参见号" />
+                    </uni-forms-item>
+                </template>
+            </uni-forms>
+        </view>
+        <!-- 底部操作栏 -->
+        <HcTabbarBlock :height="70"/>
+        <hc-tabbars class="flex items-center">
+            <template v-if="!dataId">
+                <view class="flex-1 mr-2">
+                    <button hover-class="none" class="cu-btn block bg-orange text-white">继续新增</button>
+                </view>
+                <view class="flex-1 ml-2">
+                    <button hover-class="none" class="cu-btn block bg-purple-8 text-white">提交保存</button>
+                </view>
+            </template>
+            <template v-else>
+                <button hover-class="none" class="cu-btn flex-1 bg-purple-8 text-white" @click="saveClick">提交保存</button>
+            </template>
+        </hc-tabbars>
+    </hc-sys>
+</template>
+
+<script setup>
+import {ref} from "vue";
+import mainApi from '~api/image/index';
+import {uploadApi} from '~api/upload';
+import {getObjValue} from "js-fast-way";
+import {errorToast, formValidate, successToast} from "@/utils/tools";
+import {onLoad, onReady} from '@dcloudio/uni-app'
+import {chooseImage} from "@/utils/utils";
+import dayjs from "dayjs";
+
+//初始变量
+const dataId = ref('');
+const fileList = ref([])
+const pdfList = ref([])
+
+const dateEnd = ref(dayjs().format("YYYY-MM-DD"));
+
+//页面启动
+onLoad((options) => {
+    const {id} = getObjValue(options)
+    dataId.value = id ?? '';
+    if (id) {
+        uni.setNavigationBarTitle({title: '编辑声像文件'})
+        getInfoApi()
+    } else {
+        uni.setNavigationBarTitle({title: '新增声像文件'})
+    }
+})
+
+onReady(() => {
+    // 设置自定义表单校验规则,必须在节点渲染完毕后执行
+    formRef.value?.setRules(formRules)
+})
+
+//获取详情
+const getInfoApi = async () => {
+    formData.value = {}
+    if (!dataId.value) {
+        errorToast('参数异常,请退出重试')
+        return false;
+    }
+    uni.showLoading({title: '获取数据中...', mask: true});
+    const { data } = await mainApi.queryById({
+        id: dataId.value
+    })
+    const res = getObjValue(data)
+    formData.value = res
+    console.log(res)
+    const {imageUrl, pdfUrl} = res
+    fileList.value = imageUrl.toString().split(',')
+    pdfList.value = pdfUrl.toString().split(',')
+    uni.hideLoading();
+}
+
+//添加文件
+const addFileClick = async () => {
+    const tempFiles = await chooseImage(10 - fileList.value.length)
+    if (tempFiles.length > 0) {
+        uni.showLoading({title: '上传文件中...', mask: true});
+    }
+    for (let i = 0; i < tempFiles.length; i++) {
+        await uploadFile(tempFiles[i]);
+    }
+    uni.hideLoading();
+}
+
+//上传文件
+const uploadFile = async (item) => {
+    const {error, msg, data} = await uploadApi(item.path || item.tempFilePath)
+    if (!error) {
+        const { link, pdfUrl } = getObjValue(data)
+        fileList.value.push(link)
+        pdfList.value.push(pdfUrl)
+    } else {
+        errorToast(msg)
+    }
+}
+
+//删除文件
+const delFileClick = (index) => {
+    fileList.value.splice(index, 1)
+    pdfList.value.splice(index, 1)
+}
+
+//预览图片
+const previewImg = (index) => {
+    uni.previewImage({
+        current: index,
+        urls: fileList.value,
+    });
+}
+
+//表单验证
+const formRef = ref(null)
+const formData = ref({})
+const formRules = {
+    title: {
+        rules: [{
+            required: true,
+            errorMessage: '请输入题名'
+        }]
+    },
+    textContent: {
+        rules: [{
+            required: true,
+            errorMessage: '请输入文字说明'
+        }]
+    },
+    shootingTimeStr: {
+        rules: [{
+            required: true,
+            errorMessage: '请选择拍摄时间'
+        }]
+    },
+    uploadTime: {
+        rules: [{
+            required: true,
+            errorMessage: '请选择上传日期'
+        }]
+    },
+    shootingUser: {
+        rules: [{
+            required: true,
+            errorMessage: '请输入拍摄者'
+        }]
+    },
+}
+
+//提交保存
+const saveClick = async () => {
+    if (fileList.value.length <= 0) {
+        errorToast('请先上传文件')
+        return false
+    }
+    const isForm = formValidate(formRef.value)
+    if (!isForm) {
+        errorToast('请先完善表单')
+        return false
+    }
+    //更新数据
+    if (dataId.value) {
+        await updateImageData()
+    } else {
+        await addImageData()
+    }
+}
+
+//更新数据
+const updateImageData = async () => {
+    uni.showLoading({title: '保存数据中...', mask: true});
+    const {error, code, msg} = await mainApi.updateImageclassifyFile({
+        ...formData.value,
+        imageUrl: fileList.value.join(','),
+        pdfUrl: pdfList.value.join(','),
+    })
+    uni.hideLoading();
+    if (!error && code === 200) {
+        successToast('保存成功')
+    } else {
+        errorToast('保存失败: ' + msg)
+    }
+}
+
+//新增数据
+const addImageData = async () => {
+    uni.showLoading({title: '新增数据中...', mask: true});
+    const {error, code, msg} = await mainApi.addImageclassifyFile({
+        ...formData.value,
+        imageUrl: fileList.value.join(','),
+        pdfUrl: pdfList.value.join(','),
+    })
+    uni.hideLoading();
+    if (!error && code === 200) {
+        successToast('新增成功')
+    } else {
+        errorToast('新增失败: ' + msg)
+    }
+}
+</script>

+ 94 - 1
pages/image/info.vue

@@ -1,7 +1,100 @@
 <template>
-
+    <hc-sys navBarUi="white">
+        <template #navBar>
+            <hc-nav-back-bar title="声像资料详情">
+                <text class="text-26" @click="editFormClick">编辑</text>
+            </hc-nav-back-bar>
+        </template>
+        <!-- 轮播图 -->
+        <swiper class="screen-swiper square-dot h-8xl" indicator-dots circular autoplay interval="5000" duration="500">
+            <swiper-item v-for="(item,index) in imageList" :key="index">
+                <image :src="item" mode="aspectFill"/>
+            </swiper-item>
+        </swiper>
+        <!-- 详情 -->
+        <view class="relative bg-white">
+            <view class="text-black text-36 hc-p">{{dataInfo.title}}</view>
+            <view class="text-26 hc-p" un-border-t="1 solid gray-1">{{dataInfo.textContent}}</view>
+            <view class="hc-flex hc-p text-26 text-black" un-border-t="1 solid gray-1">
+                <view class="flex-1 hc-flex">
+                    <text class="i-iconoir-user"/>
+                    <text class="ml-0.5">{{ dataInfo.shootingUser }}</text>
+                </view>
+                <view class="flex-1 hc-flex-center">
+                    <text class="i-iconoir-clock"/>
+                    <text class="ml-0.5">{{ dataInfo.shootingTimeStr }}</text>
+                </view>
+                <view class="flex-1 hc-flex-end">
+                    <text class="i-iconoir-page"/>
+                    <text class="ml-0.5">{{ dataInfo.fileSize }}</text>
+                </view>
+            </view>
+        </view>
+        <view class="hc-flex bg-white hc-p mt-2" @click="viewPdfClick" v-if="dataInfo.type === 2">
+            <view class="flex-1 text-26">查看PDF文件</view>
+            <text class="i-iconoir-nav-arrow-right"/>
+        </view>
+    </hc-sys>
 </template>
 
 <script setup>
+import {ref} from "vue";
+import {onLoad} from '@dcloudio/uni-app'
+import mainApi from '~api/image/index';
+import {getObjValue, isString} from "js-fast-way";
+import {errorToast, toPdfPreview} from "@/utils/tools";
+
+const dataId = ref('');
+const dataInfo = ref({})
+const imageList = ref([])
+
+//页面启动
+onLoad(({id}) => {
+    dataId.value = id ?? '';
+    getInfoApi()
+})
+
+//获取详情
+const getInfoApi = async () => {
+    dataInfo.value = {}
+    imageList.value = []
+    if (!dataId.value) {
+        errorToast('参数异常,请退出重试')
+        return false;
+    }
+    uni.showLoading({title: '获取数据中...', mask: true});
+    const { data } = await mainApi.queryById({
+        id: dataId.value
+    })
+    const res = getObjValue(data)
+    console.log(res)
+    dataInfo.value = res
+    imageList.value = res.imageUrl.toString().split(',')
+    uni.hideLoading();
+}
+
+//查看PDF文件
+const viewPdfClick = async () => {
+    const { id, margePdfUrl } = dataInfo.value
+    if (margePdfUrl) {
+        await toPdfPreview(margePdfUrl)
+    } else {
+        const { data } = await mainApi.imageClassificationFile({id})
+        const url = isString(data) ? data : ''
+        if (url) {
+            dataInfo.value.margePdfUrl = url
+            await toPdfPreview(url)
+        } else {
+            errorToast('预览资料文件异常')
+        }
+    }
+}
 
+//编辑资料
+const editFormClick = () => {
+    const { id } = dataInfo.value
+    uni.navigateTo({
+        url: `/pages/image/form?id=${id}`
+    })
+}
 </script>

+ 8 - 6
pages/image/view.vue

@@ -19,12 +19,12 @@
 
         <!-- 树类型的列表 -->
         <template v-for="(item, index) in dataList" :key="index" v-if="pageNode.type === 1">
-            <view class="relative bg-white px-3 py-2 flex items-center" un-border-b="1 solid gray-2" @click="itemClick(item)">
-                <view class="relative flex items-center mr-2" v-if="isDelete" @click.stop="checkClick(item)">
+            <view class="bg-white hc-p hc-flex" un-border-b="1 solid gray-2" @click="itemClick(item)">
+                <view class="hc-flex mr-2" v-if="isDelete" @click.stop="checkClick(item)">
                     <uni-icons type="checkbox-filled" size="26" color="#ee5b20" v-if="item.check"/>
                     <uni-icons type="checkbox" size="26" color="#9a9a9a" v-else/>
                 </view>
-                <view class="relative flex items-center">
+                <view class="hc-flex">
                     <hc-img class="b-rounded" :src="item.imageUrl?.toString()?.split(',')[0]" width="50" height="50"/>
                 </view>
                 <view class="relative flex-1 ml-3">
@@ -36,8 +36,8 @@
 
         <template #bottom>
             <hc-tabbars class="hc-paging-bottom-bar">
-                <view class="relative flex items-center" v-if="isDelete">
-                    <view class="relative flex items-center" @click="allCheckClick">
+                <view class="hc-flex" v-if="isDelete">
+                    <view class="hc-flex" @click="allCheckClick">
                         <uni-icons type="checkbox-filled" size="24" color="#ee5b20" v-if="checkList.length === dataList.length"/>
                         <uni-icons type="checkbox" size="24" color="#9a9a9a" v-else/>
                         <text class="ml-1">全选</text>
@@ -158,7 +158,9 @@ const itemClick = (item) => {
     if(isDelete.value) {
         checkClick(item)
     } else {
-        console.log(item)
+        uni.navigateTo({
+            url: `/pages/image/info?id=${item.id}`
+        })
     }
 }
 

+ 24 - 17
uno.config.js

@@ -4,21 +4,28 @@ import presetWeapp from 'unocss-preset-weapp'
 import {transformerAttributify, transformerClass} from 'unocss-preset-weapp/transformer'
 
 export default defineConfig({
-  presets: [
-    presetUno(),
-    presetWeapp(),
-    presetIcons({
-      //autoInstall: true, //自动安装图标库
-    }),
-    presetAttributify({
-      prefix: 'un-',      //属性冲突的自定义前缀
-      prefixedOnly: true, //强制使用前缀
-    }),
-    //其它扩展,主要用动画,集成了 animate.css
-    presetExtra(),
-  ],
-  transformers: [
-    transformerAttributify(),
-    transformerClass(),
-  ]
+    shortcuts: {
+        'hc-flex': 'relative flex items-center',
+        'hc-flex-center': 'hc-flex justify-center',
+        'hc-flex-end': 'hc-flex justify-end',
+        'hc-p': 'px-3 py-2',
+        'hc-tr': 'absolute top-0 right-0',
+    },
+    presets: [
+        presetUno(),
+        presetWeapp(),
+        presetIcons({
+            //autoInstall: true, //自动安装图标库
+        }),
+        presetAttributify({
+            prefix: 'un-',      //属性冲突的自定义前缀
+            prefixedOnly: true, //强制使用前缀
+        }),
+        //其它扩展,主要用动画,集成了 animate.css
+        presetExtra(),
+    ],
+    transformers: [
+        transformerAttributify(),
+        transformerClass(),
+    ]
 })

+ 17 - 0
utils/utils.js

@@ -8,3 +8,20 @@ export const getUserName = (name) => {
         return name.substr(leng - 2, 2)
     }
 }
+
+//选择文件
+export const chooseImage = (count) => {
+    return new Promise((resolve) => {
+        uni.chooseImage({
+            count: count,
+            sizeType: ['original'],
+            sourceType: ['album', 'camera'],
+            success: ({tempFiles}) => {
+                resolve(tempFiles);
+            },
+            fail: () => {
+                resolve([]);
+            }
+        });
+    })
+}