| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767 |
- <template>
- <view class="app-page flex flex-col">
- <!-- 搜索区域 -->
- <view class="filter-wrap bg-white shadow-3">
- <tm-search v-model="queryParams.keyword" :round="24" :shadow="0" color="light-blue" insert-color="light-blue" :clear="true" @confirm="fnOnSearch"></tm-search>
- <tm-dropDownMenu :shadow="0" color="light-blue" @confirm="fnOnConfirm" :list="filterList"></tm-dropDownMenu>
- </view>
- <!-- 占位区域 -->
- <view style="width: 100vw;height: 184rpx;"></view>
- <view v-if="loading != 'success'" class="loading-wrap">
- <tm-skeleton model="listAvatr"></tm-skeleton>
- <tm-skeleton model="listAvatr"></tm-skeleton>
- <tm-skeleton model="listAvatr"></tm-skeleton>
- <tm-skeleton model="listAvatr"></tm-skeleton>
- </view>
- <view class="page-content pa-24 flex flex-col" v-else>
- <view v-if="dataList.length == 0" class="content-empty flex flex-center">
- <!-- 空布局 -->
- <tm-empty icon="icon-shiliangzhinengduixiang-" label="暂无任何附件"></tm-empty>
- </view>
- <block v-else>
- <!-- 内容区域 -->
- <block v-for="(item, index) in dataList" :key="index">
- <tm-translate animation-name="fadeUp" :wait="(index + 1) * 50">
- <view class="attachment-card mb-24 flex bg-white pa-24 round-3" @click="fnShowDetail(item)">
- <view class="cover round-3 flex flex-center" :class="[fnGetIconClass(item.mediaType)]">
- <text class="icon iconfont">{{ item.suffix }}</text>
- </view>
- <!-- 内容区域 -->
- <view class="info pl-36">
- <view class="file-name text-size-m text-weight-b">{{ item.name }}</view>
- <view class="file-media mt-12 text-size-s text-grey-darken-1">附件类型:{{ item.mediaType }}</view>
- <view class="file-media mt-8 text-size-s text-grey-darken-1">附件大小:{{ item.sizeText }}</view>
- <view class="file-path mt-8 text-size-s text-grey-darken-1">上传日期:{{ { d: item.createTime, f: 'yyyy年MM月dd日 星期w' } | formatTime }}</view>
- </view>
- </view>
- </tm-translate>
- </block>
- <tm-flotbutton @click="fnToTopPage" :offset="[16, 80]" color="bg-gradient-light-blue-accent" size="m" icon="icon-angle-up"></tm-flotbutton>
- <view class="load-text ">{{ loadMoreText }}</view>
- </block>
- <!-- 弹窗详情 -->
- <tm-poup v-model="detail.show" position="bottom" height="80vh">
- <view class="poup-content">
- <view class="poup-head text-align-center text-weight-b text-size-g ma-24 ">附件详情</view>
- <scroll-view class="poup-body pa-24 pt-0" :scroll-y="true" @touchmove.stop>
- <view class="preview-file pl-24 pr-24">
- <!-- 图片预览 -->
- <tm-images
- v-if="$utils.fnCheckIsFileType('image', detail.form)"
- :width="700"
- :height="350"
- :round="3"
- :src="$utils.checkThumbnailUrl(detail.form.path)"
- model="aspectFill"
- ></tm-images>
- <!-- 视频 -->
- <video
- v-else-if="$utils.fnCheckIsFileType('video', detail.form)"
- class="round-3"
- style="width: 100%;height: 350rpx;"
- :src="$utils.checkUrl(detail.form.path)"
- controls
- ></video>
- <view v-else class="flex flex-center border-a-1 round-3 text-align-center text-grey-darken-1" style="height: 280rpx;background-color: #f2f2f2;">
- 该文件暂不支持预览
- </view>
- </view>
- <tm-input title="附件名称" v-model="detail.form.name" :clear="true" placeholder="请输入附件名称..."></tm-input>
- <tm-input :disabled="true" color="grey" title="附件类型" v-model="detail.form.mediaType"></tm-input>
- <tm-input :disabled="true" color="grey" title="附件位置" v-model="detail.form.type"></tm-input>
- <tm-input :disabled="true" color="grey" title="附件大小" v-model="detail.form.sizeText"></tm-input>
- <tm-input :disabled="true" color="grey" title="上传日期" v-model="detail.form.createTime"></tm-input>
- <tm-input
- :disabled="true"
- :vertical="true"
- :borderBottom="false"
- input-type="textarea"
- title="文件地址"
- color="grey"
- bg-color="grey-lighten-5"
- :height="120"
- v-model="detail.form.path"
- >
- <template v-slot:default="{ title }">
- {{ title }}
- <tm-button text theme="light-blue" size="xs" @click="$utils.copyText(detail.form.path, '复制成功!')">复制</tm-button>
- </template>
- </tm-input>
- </scroll-view>
- <view class="btn-wrap flex flex-center">
- <tm-button size="m" navtie-type="form" theme="bg-gradient-blue-accent" @click="fnOnUpdate()">保存</tm-button>
- <tm-button size="m" theme="bg-gradient-red-accent" @click="fnOnDelete()">删除</tm-button>
- <tm-button size="m" theme="bg-gradient-blue-grey-accent" @click="detail.show = false">关闭</tm-button>
- </view>
- </view>
- </tm-poup>
- </view>
- <tm-flotbutton :show-text="true" color="bg-gradient-orange-accent" @click="fnOnFlotButton"></tm-flotbutton>
- <tm-actionSheetMenu title="文件上传操作" @change="fnOnFileSelectActionChange" v-model="fileSelectAction.show" :actions="fileSelectAction.list"></tm-actionSheetMenu>
- </view>
- </template>
- <script>
- // #ifdef APP-PLUS
- const AfDocument = uni.requireNativePlugin('Aq-ChooseFile'); // 临时替代
- // #endif
- import { getAdminAccessToken } from '@/utils/auth.js';
- import tmSkeleton from '@/tm-vuetify/components/tm-skeleton/tm-skeleton.vue';
- import tmSearch from '@/tm-vuetify/components/tm-search/tm-search.vue';
- import tmDropDownMenu from '@/tm-vuetify/components/tm-dropDownMenu/tm-dropDownMenu.vue';
- import tmEmpty from '@/tm-vuetify/components/tm-empty/tm-empty.vue';
- import tmButton from '@/tm-vuetify/components/tm-button/tm-button.vue';
- import tmCheckbox from '@/tm-vuetify/components/tm-checkbox/tm-checkbox.vue';
- import tmTranslate from '@/tm-vuetify/components/tm-translate/tm-translate.vue';
- import tmPoup from '@/tm-vuetify/components/tm-poup/tm-poup.vue';
- import tmForm from '@/tm-vuetify/components/tm-form/tm-form.vue';
- import tmUpload from '@/tm-vuetify/components/tm-upload/tm-upload.vue';
- import tmInput from '@/tm-vuetify/components/tm-input/tm-input.vue';
- import tmImages from '@/tm-vuetify/components/tm-images/tm-images.vue';
- import tmFlotbutton from '@/tm-vuetify/components/tm-flotbutton/tm-flotbutton.vue';
- import tmActionSheetMenu from '@/tm-vuetify/components/tm-actionSheetMenu/tm-actionSheetMenu.vue';
- export default {
- components: {
- tmSkeleton,
- tmSearch,
- tmDropDownMenu,
- tmEmpty,
- tmButton,
- tmCheckbox,
- tmPoup,
- tmForm,
- tmUpload,
- tmInput,
- tmImages,
- tmFlotbutton,
- tmTranslate,
- tmActionSheetMenu
- },
- data() {
- return {
- loading: 'loading',
- filterLoading: 'loading',
- btnOption: {
- actions: [
- {
- icon: 'icon-like',
- color: 'bg-gradient-orange-accent'
- },
- {
- icon: 'icon-commentdots-fill',
- color: 'bg-gradient-green-accent'
- },
- {
- icon: 'icon-share1',
- color: 'bg-gradient-blue-accent'
- }
- ]
- },
- filterList: [
- {
- title: '存储位置',
- children: [
- {
- title: '',
- name: 'attachmentType',
- model: 'radio',
- children: []
- }
- ]
- },
- {
- title: '文件类型',
- children: [
- {
- title: '',
- name: 'mediaType',
- model: 'radio',
- children: []
- }
- ]
- }
- ],
- queryParams: {
- size: 8,
- page: 0,
- attachmentType: undefined,
- keyword: undefined,
- mediaType: undefined,
- sort: undefined
- },
- result: {},
- dataList: [],
- total: 0,
- detail: {
- params: {},
- form: {},
- show: false
- },
- isLoadMore: false,
- loadMoreText: '加载中...',
- fileSelectAction: {
- show: false,
- list: []
- }
- };
- },
- onLoad() {
- this.fnSetPageTitle('附件管理');
- },
- created() {
- this.fnGetData();
- this.fnGetFilters();
- },
- onPullDownRefresh() {
- this.queryParams.page = 0;
- this.dataList = [];
- this.fnGetData();
- if (this.filterLoading != 'success') {
- this.fnGetFilters();
- }
- },
- onReachBottom(e) {
- if (this.result.hasNext) {
- this.queryParams.page += 1;
- this.isLoadMore = true;
- this.fnGetData();
- } else {
- uni.showToast({
- icon: 'none',
- title: '没有更多数据了'
- });
- }
- },
- methods: {
- /**
- * 文件大小 字节转换单位
- * @param size
- * @returns {string|*}
- */
- fnTransFileSize(size) {
- if (!size) return '';
- if (size < this.fnPow1024(1)) return size + ' B';
- if (size < this.fnPow1024(2)) return (size / this.fnPow1024(1)).toFixed(2) + ' KB';
- if (size < this.fnPow1024(3)) return (size / this.fnPow1024(2)).toFixed(2) + ' MB';
- if (size < this.fnPow1024(4)) return (size / this.fnPow1024(3)).toFixed(2) + ' GB';
- return (size / this.fnPow1024(4)).toFixed(2) + ' TB';
- },
- // 求次幂
- fnPow1024(num) {
- return Math.pow(1024, num);
- },
- fnGetIconClass(mediaType) {
- let _class = '';
- if (mediaType.indexOf('video/') != -1) {
- _class = 'is-video';
- } else if (mediaType.indexOf('image/') != -1) {
- _class = 'is-image';
- }
- return _class;
- },
- fnCheckIsFileType(type, attachment) {
- if (type == 'video') return attachment.mediaType.indexOf('video/') != -1;
- else if (type == 'image') return attachment.mediaType.indexOf('image/') != -1;
- else return false;
- },
- fnGetFilters() {
- this.filterLoading = 'loading';
- Promise.all([this.$httpApi.admin.getAttachmentsTypes(), this.$httpApi.admin.getAttachmentsMediaTypes()])
- .then(res => {
- const res1 = res[0];
- this.filterList[0].children[0].children = res1.data.map(item => {
- return {
- title: item,
- id: item
- };
- });
- const res2 = res[1];
- this.filterList[1].children[0].children = res2.data.map(item => {
- return {
- title: item,
- id: item
- };
- });
- this.filterLoading = 'success';
- })
- .catch(err => {
- this.filterLoading = 'error';
- uni.$tm.toast('搜索条件数据加载失败!');
- });
- },
- // 搜索区域确定
- fnOnConfirm(e) {
- this.queryParams.attachmentType = e[0].children.map(x => x.id).join('') || undefined;
- this.queryParams.mediaType = e[1].children.map(x => x.id).join('') || undefined;
- this.fnOnSearch();
- },
- fnOnSearch() {
- this.queryParams.page = 0;
- this.dataList = [];
- this.fnGetData();
- },
- fnGetData() {
- uni.showLoading({
- mask: true,
- title: '加载中...'
- });
- // 设置状态为加载中
- if (!this.isLoadMore) {
- this.loading = 'loading';
- }
- this.loadMoreText = '加载中...';
- this.$httpApi.admin
- .getAttachmentsByPage(this.queryParams)
- .then(res => {
- if (res.status == 200) {
- this.loadMoreText = res.data.hasNext ? '上拉加载更多' : '呜呜,没有更多数据啦~';
- this.result = res.data;
- this.total = res.data.total;
- if (this.isLoadMore) {
- let _list = this.dataList.concat(res.data.content);
- this.dataList = _list.map(item => {
- item['sizeText'] = this.fnTransFileSize(item.size);
- return item;
- });
- } else {
- this.dataList = res.data.content.map(item => {
- item['sizeText'] = this.fnTransFileSize(item.size);
- return item;
- });
- }
- this.loading = 'success';
- } else {
- uni.$tm.toast('加载失败,请重试!');
- thi.loading = 'error';
- }
- })
- .catch(err => {
- console.error(err);
- uni.$tm.toast('加载失败,请重试!');
- this.loading = 'error';
- this.loadMoreText = '加载失败,请下拉刷新!';
- })
- .finally(() => {
- setTimeout(() => {
- uni.hideLoading();
- uni.stopPullDownRefresh();
- }, 300);
- });
- },
- // 详情
- fnShowDetail(item) {
- this.detail.params = { ...item };
- this.detail.form = { ...item };
- this.detail.show = true;
- },
- // 删除
- fnOnDelete() {
- uni.$eShowModal({
- title: '提示',
- content: `您确定要删除该附件吗?`,
- showCancel: true,
- cancelText: '否',
- cancelColor: '#999999',
- confirmText: '是',
- confirmColor: '#03a9f4'
- })
- .then(res => {
- uni.showLoading({
- mask: true,
- title: '正在删除...'
- });
- this.$httpApi.admin
- .deleteAttachmentById(this.detail.params.id)
- .then(res => {
- if (res.status == 200) {
- uni.$tm.toast('删除成功!');
- setTimeout(() => {
- this.detail.show = false;
- this.detail.params = {};
- this.detail.form = {};
- this.fnGetData();
- }, 1000);
- } else {
- uni.$tm.toast('删除失败,请重试!');
- }
- })
- .catch(err => {
- console.error(err);
- uni.$tm.toast('删除失败,请重试!');
- });
- })
- .catch(err => {});
- },
- fnOnUpdate() {
- if (this.detail.form.name == '') {
- return uni.$tm.toast('附件名称不能为空!');
- }
- uni.showLoading({
- mask: true,
- title: '正在保存...'
- });
- this.$httpApi.admin
- .updateAttachmentById(this.detail.params.id, this.detail.form.name)
- .then(res => {
- if (res.status == 200) {
- uni.$tm.toast('保存成功!');
- // setTimeout(() => {
- // this.detail.show = false;
- // this.detail.params = {};
- // this.detail.form = {};
- // this.fnGetData();
- // }, 1000);
- } else {
- uni.$tm.toast('保存失败,请重试!');
- }
- })
- .catch(err => {
- uni.$tm.toast('保存失败,请重试!');
- });
- },
- // 浮动按钮点击
- fnOnFlotButton() {
- // 微信小程序:提供从消息列表和媒体选择
- // #ifdef MP-WEIXIN
- this.fileSelectAction.list = ['上传照片', '上传视频', '上传文件'];
- // #endif
- // 安卓app:使用第三方上传
- // #ifdef APP-PLUS
- this.fileSelectAction.list = ['上传照片', '上传视频', '上传文件'];
- // #endif
- // h5
- // #ifdef H5
- this.fileSelectAction.list = ['上传照片', '上传视频', '上传文件'];
- // #endif
- // #ifndef H5||MP-WEIXIN||APP-PLUS
- this.fileSelectAction.list = ['上传照片', '上传视频'];
- // #endif
- this.fileSelectAction.show = true;
- },
- fnOnFileSelectActionChange(e) {
- // 微信小程序:提供从消息列表和媒体选择
- // #ifdef MP-WEIXIN
- switch (e.index) {
- case 0:
- // 上传照片
- uni.chooseImage({
- count: 1,
- success: res => {
- console.log(res);
- this.fnOnUploadFileByPath(res.tempFilePaths[0]);
- }
- });
- break;
- case 1:
- // 上传视频
- uni.chooseVideo({
- count: 1,
- success: res => {
- console.log(res);
- this.fnOnUploadFileByPath(res.tempFilePath);
- }
- });
- break;
- case 2:
- // 会话选择
- uni.chooseMessageFile({
- count: 1,
- success: res => {
- this.fnOnUploadFileByPath(res.tempFiles[0].path);
- }
- });
- break;
- }
- // #endif
- // 安卓app
- // #ifdef APP-PLUS
- switch (e.index) {
- case 0:
- // 上传照片
- uni.chooseImage({
- count: 1,
- success: res => {
- console.log(res);
- this.fnOnUploadFileByPath(res.tempFilePaths[0]);
- }
- });
- break;
- case 1:
- // 上传视频
- uni.chooseVideo({
- count: 1,
- success: res => {
- console.log(res);
- this.fnOnUploadFileByPath(res.tempFilePath);
- }
- });
- break;
- case 2:
- // 上传文件:
- // todo:使用第三方控件
- AfDocument.openMode(
- {
- size: 1,
- isDown: true,
- types: [
- {
- name: '文档',
- value: ['doc', 'wps', 'docx', 'xls', 'xlsx', 'pdf']
- },
- {
- name: '视频',
- value: ['mp4']
- },
- {
- name: '音乐',
- value: ['mp3', 'flac']
- },
- {
- name: '图片',
- value: ['jpg', 'png']
- }
- ]
- },
- res => {
- // this.data = JSON.stringify(res);
- this.fnOnUploadFileByFile(res[0].path);
- }
- );
- break;
- }
- // #endif
- // h5
- // #ifdef H5
- switch (e.index) {
- case 0:
- // 上传照片
- uni.chooseImage({
- count: 1,
- success: res => {
- console.log(res);
- this.fnOnUploadFileByPath(res.tempFilePaths[0]);
- }
- });
- break;
- case 1:
- // 上传视频
- uni.chooseVideo({
- count: 1,
- success: res => {
- console.log(res);
- this.fnOnUploadFileByPath(res.tempFilePath);
- }
- });
- break;
- case 2:
- // 上传文件
- uni.chooseFile({
- count: 1,
- success: res => {
- console.log(res);
- this.fnOnUploadFileByPath(res.tempFilePaths[0]);
- }
- });
- break;
- }
- // #endif
- // #ifndef H5||MP-WEIXIN||APP-PLUS
- switch (e.index) {
- case 0:
- // 上传照片
- uni.chooseImage({
- count: 1,
- success: res => {
- this.fnOnUploadFileByFile(res.tempFiles[0]);
- }
- });
- break;
- case 1:
- // 上传视频
- uni.chooseVideo({
- count: 1,
- success: res => {
- this.fnOnUploadFileByFile(res.tempFile);
- }
- });
- break;
- }
- // #endif
- },
- // 使用文件路径上传文件
- fnOnUploadFileByPath(path) {
- uni.showLoading({
- title: '文件上传中...',
- mask: true
- });
- uni.uploadFile({
- filePath: path,
- header: {
- 'admin-authorization': getAdminAccessToken()
- },
- url: this.$baseApiUrl + '/api/admin/attachments/upload',
- name: 'file',
- success: upladRes => {
- const _uploadRes = JSON.parse(upladRes.data);
- if (_uploadRes.status == 200) {
- uni.$tm.toast('文件上传成功!');
- setTimeout(() => {
- this.fnGetData();
- }, 1000);
- } else {
- uni.$tm.toast(_uploadRes.message);
- }
- },
- fail: err => {
- uni.$tm.toast(err.message);
- }
- });
- },
- // 使用文件对象上传文件
- fnOnUploadFileByFile(file) {
- uni.showLoading({
- title: '文件上传中...',
- mask: true
- });
- uni.uploadFile({
- // #ifdef H5
- file: file,
- // #endif
- // #ifndef H5
- files: [file],
- // #endif
- header: {
- 'admin-authorization': getAdminAccessToken()
- },
- url: this.$baseApiUrl + '/api/admin/attachments/upload',
- name: 'file',
- success: upladRes => {
- const _uploadRes = JSON.parse(upladRes.data);
- if (_uploadRes.status == 200) {
- uni.$tm.toast('文件上传成功!');
- setTimeout(() => {
- this.fnGetData();
- }, 1000);
- } else {
- uni.$tm.toast(_uploadRes.message);
- }
- },
- fail: err => {
- uni.$tm.toast(err.message);
- }
- });
- }
- }
- };
- </script>
- <style lang="scss" scoped>
- .app-page {
- width: 100vw;
- min-height: 100vh;
- }
- .loading-wrap {
- padding: 24rpx;
- }
- .filter-wrap {
- position: fixed;
- left: 0;
- right: 0;
- /* #ifdef H5 */
- top: 88rpx;
- /* #endif */
- /* #ifndef H5 */
- top: 0;
- /* #endif */
- width: 100vw;
- z-index: 6;
- }
- .page-content {
- }
- .content-empty {
- width: 100vw;
- height: 65vh;
- }
- .attachment-card {
- box-shadow: 0rpx 2rpx 24rpx rgba(0, 0, 0, 0.05);
- .cover {
- width: 170rpx;
- height: 160rpx;
- background-color: rgb(104, 136, 151);
- // box-shadow: 0 6rpx 10rpx rgba(51, 154, 204, 0.2);
- &.is-video {
- background-color: rgb(3, 174, 252);
- }
- &.is-image {
- background-color: #1cbcb4;
- }
- .icon {
- font-size: 40rpx;
- color: #fff;
- }
- .thumbnai {
- width: 100%;
- height: 100%;
- box-sizing: border-box;
- box-shadow: 0rpx 4rpx 24rpx rgba(0, 0, 0, 0.03);
- border: 6rpx solid #fff;
- }
- }
- .info {
- width: 0;
- flex-grow: 1;
- .time-icon {
- font-size: 24rpx;
- }
- }
- }
- .poup-body {
- box-sizing: border-box;
- height: 66vh;
- }
- .poup-content {
- width: 100%;
- overflow: hidden;
- }
- .btn-wrap {
- width: 100%;
- }
- .file-name {
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
- word-wrap: break-word;
- word-break: break-all;
- }
- </style>
|