Commit 0f8401fc031d64c8d383bf6bca29653b9bcda315

Authored by 徐烜
1 parent 6c06084a

电子站牌项目

1、添加resource-gallery通用组件,整合图片和视频的上传选取等功能,定义在core/support下
2、添加自定义插件bsth-slide轮播组件,可以轮播图片和视频,现阶段完成了初步功能和自定义属性编辑器 bsth-slide__editor
front-end/h5/package.json
... ... @@ -42,6 +42,7 @@
42 42 "vue-quill-editor": "^3.0.6",
43 43 "vue-router": "^3.0.3",
44 44 "vuex": "^3.0.1",
  45 + "vue-video-player": "^5.0.2",
45 46 "x-data-spreadsheet": "^1.1.4"
46 47 },
47 48 "devDependencies": {
... ...
front-end/h5/src/components/core/plugins/bsth-slide__editor.js 0 → 100644
  1 +/**
  2 + * 对应bsth-slide组件的属性中设置
  3 + * editor: {
  4 + * custom: true
  5 + * }
  6 + */
  7 +
  8 +import { GalleryValue, GalleryValueType } from 'core/support/resource-gallery/components/galleryValue'
  9 +
  10 +export default {
  11 + props: {
  12 + elementProps: {
  13 + type: Object,
  14 + default: () => ({
  15 + items: [], // 对应bsth-slide组件的items属性
  16 + activeIndex: 0 // 对应bsth-slide组件的activeIndex属性
  17 + })
  18 + }
  19 + },
  20 + computed: {
  21 + innerItems () {
  22 + return this.elementProps.items
  23 + }
  24 + },
  25 + data () {
  26 + return {
  27 + current: 1 // 下标从1开始
  28 + }
  29 + },
  30 + methods: {
  31 + p_change (page) { // 分页条change事件处理器
  32 + this.current = page
  33 + this.elementProps.activeIndex = page - 1
  34 + },
  35 + g_change (item) { // gallery change事件处理器, item 是 GalleryValue 类型
  36 + const currentItem = this.innerItems[this.current - 1]
  37 + let itemObj = item.toObject()
  38 + currentItem.url = itemObj.url
  39 + currentItem.flag = itemObj.flag
  40 + },
  41 + itemRender (current, type, originalElement) {
  42 + if (type === 'prev') { // 上一页
  43 + return <a-button style={{ marginRight: '8px' }} size="small" icon="minus"
  44 + onClick={() => this.minus(current)}
  45 + disabled={this.innerItems.length === 1}></a-button>
  46 + } else if (type === 'next') { // 下一页
  47 + return <a-button style={{ marginLeft: '8px' }} size="small" icon="plus"
  48 + onClick={this.add}></a-button>
  49 + }
  50 + return originalElement
  51 + },
  52 + minus (index) { // index 下标从0开始
  53 + if (this.innerItems.length === 1) { // 只有一个元素,不能再移除
  54 + return
  55 + }
  56 + this.elementProps.items.splice(index, 1)
  57 + this.elementProps.activeIndex = Math.max(index - 1, 0)
  58 + this.current = Math.max(index - 1, 0) + 1
  59 + },
  60 + add () {
  61 + this.elementProps.items.push(new GalleryValue({ url: '', type: GalleryValueType.IMAGE }).toObject())
  62 + this.current = this.elementProps.items.length
  63 + this.elementProps.activeIndex = this.current - 1
  64 + }
  65 + },
  66 + render () {
  67 + const currentItem = GalleryValue.toGalleryValue(this.innerItems[this.current - 1])
  68 + // console.log(currentItem)
  69 + return (
  70 + <div>
  71 + <a-pagination
  72 + current={this.current}
  73 + onChange={this.p_change}
  74 + size="small"
  75 + total={this.innerItems.length}
  76 + defaultPageSize={1}
  77 + itemRender={this.itemRender}
  78 + />
  79 + <bsth-resource-gallery
  80 + style={{ margin: '16px 0' }}
  81 + value={currentItem}
  82 + onChange={this.g_change}
  83 + />
  84 + </div>
  85 + )
  86 + }
  87 +}
... ...
front-end/h5/src/components/core/plugins/bsth/bsth-slide.js 0 → 100644
  1 +/**
  2 + * 自定义轮播组件(可以轮播视频)。
  3 + */
  4 +
  5 +import PropTypes from '@luban-h5/plugin-common-props'
  6 +import { Swipe, SwipeItem } from 'vant'
  7 +import 'vant/lib/swipe/style'
  8 +import 'vant/lib/swipe-item/style'
  9 +import { VideoPlayer } from 'vue-video-player'
  10 +import 'video.js/dist/video-js.css'
  11 +
  12 +import { GalleryValue, GalleryValueType } from 'core/support/resource-gallery/components/galleryValue'
  13 +
  14 +function getDefaultItems () {
  15 + const defaultItems = [ // TODO:目前鲁班的后端渲染引擎处理不了组件属性的自定义类型,所以自定义转换成普通对象
  16 + new GalleryValue({ type: GalleryValueType.IMAGE, url: 'https://img.yzcdn.cn/vant/apple-1.jpg' }).toObject(),
  17 + new GalleryValue({ type: GalleryValueType.IMAGE, url: 'https://img.yzcdn.cn/vant/apple-2.jpg' }).toObject()
  18 + ]
  19 + return defaultItems
  20 +}
  21 +
  22 +export default {
  23 + extra: {
  24 + defaultStyle: { // 默认属性
  25 + top: 0,
  26 + left: 0,
  27 + width: 350,
  28 + height: 300
  29 + }
  30 + },
  31 + name: 'bsth-slide',
  32 + data () {
  33 + return {}
  34 + },
  35 + props: {
  36 + editorMode: PropTypes.string({ // 编辑模式会由编辑器自动注入(值:edit, preview)
  37 + defaultValue: 'preview',
  38 + label: '模式',
  39 + visible: false
  40 + }),
  41 + // -------------- 调用定制editor的属性 -------------//
  42 + items: { // 每个轮播项的内容
  43 + type: Array,
  44 + default: () => getDefaultItems(),
  45 + editor: {
  46 + custom: true
  47 + }
  48 + },
  49 + activeIndex: { // 当前轮播项目的index(对应items数组下标)
  50 + type: Number,
  51 + default: 0,
  52 + editor: {
  53 + custom: true
  54 + }
  55 + },
  56 + // -------------- 数据属性 ------------- //
  57 + interval: PropTypes.number({ label: '间隔时间', defaultValue: 4000 })
  58 + },
  59 + render () {
  60 + const { items, activeIndex } = this
  61 + if (this.editorMode === 'edit') { // 如果是编辑状态显示item中的activeIndex下标项
  62 + if (items.length > 0) {
  63 + return (<div><p>{items[activeIndex].url}</p></div>)
  64 + } else {
  65 + return (<div><p>无轮播项目</p></div>)
  66 + }
  67 + } else {
  68 + return (
  69 + <Swipe autoplay={+this.interval} indicator-color="red">
  70 + {
  71 + items.map(item => (
  72 + <SwipeItem><p>{item.url}</p></SwipeItem>
  73 + ))
  74 + }
  75 + </Swipe>
  76 + )
  77 + }
  78 + },
  79 + mounted () {},
  80 + destroyed () {},
  81 + watch: {},
  82 + methods: {}
  83 +}
... ...
front-end/h5/src/components/core/plugins/index.js
... ... @@ -21,6 +21,7 @@ import LbpNewsList from &#39;core/plugins/lbp-news-list&#39;
21 21  
22 22 import BsthLineChart from 'core/plugins/bsth/bsth-line-chart'
23 23 import BsthLineChartList from 'core/plugins/bsth/bsth-line-chart-list'
  24 +import BsthSlide from 'core/plugins/bsth/bsth-slide'
24 25  
25 26 export const pluginsList = [
26 27 {
... ... @@ -330,6 +331,19 @@ export const pluginsList = [
330 331 component: BsthLineChartList,
331 332 visible: true,
332 333 name: BsthLineChartList.name
  334 + },
  335 +
  336 + {
  337 + i18nTitle: {
  338 + 'en-US': 'Carousel2',
  339 + 'zh-CN': '轮播图2'
  340 + },
  341 + title: '轮播图2',
  342 + icon: 'photo',
  343 + component: BsthSlide,
  344 + visible: true,
  345 + name: BsthSlide.name
  346 + // disabled: true
333 347 }
334 348 ]
335 349  
... ...
front-end/h5/src/components/core/support/index.js
... ... @@ -16,6 +16,7 @@ import Vue from &#39;vue&#39;
16 16 import PropMultiTextItemsEditor from './prop-multi-items-editor/text.js'
17 17 import ImageGallery from './image-gallery/gallery.js'
18 18 import VideoGallery from './video-gallery/gallery.js'
  19 +import ResourceGallery from './resource-gallery/gallery.js'
19 20 import LbsExcelEditor from './excel'
20 21 import ColorsPanel from './colors-panel'
21 22 import LbpTextAlign from '@luban-h5/lbs-text-align'
... ... @@ -31,6 +32,7 @@ Vue.component(ColorPicker.name, ColorPicker)
31 32 Vue.component(PropMultiTextItemsEditor.name, PropMultiTextItemsEditor)
32 33 Vue.component(ImageGallery.name, ImageGallery)
33 34 Vue.component(VideoGallery.name, VideoGallery)
  35 +Vue.component(ResourceGallery.name, ResourceGallery)
34 36 Vue.component(LbpTextAlign.name, LbpTextAlign)
35 37 Vue.component(LbsExcelEditor.name, LbsExcelEditor)
36 38 Vue.component(ColorsPanel.name, ColorsPanel)
... ...
front-end/h5/src/components/core/support/resource-gallery/components/galleryValue.js 0 → 100644
  1 +/**
  2 + * bsth-resource-gallery 的属性value 对应的类型
  3 + */
  4 +
  5 +const IMAGE = 1 // 图片
  6 +const VIDEO = 2 // 视频
  7 +
  8 +const GalleryValueType = Object.freeze({
  9 + IMAGE: Symbol(IMAGE),
  10 + VIDEO: Symbol(VIDEO)
  11 +})
  12 +
  13 +class GalleryValue {
  14 + constructor (value = {}) {
  15 + /** 类型 使用 GalleryValueType */
  16 + this.type = value.type
  17 + /** 资源获取路径 */
  18 + this.url = value.url
  19 +
  20 + // TODO:其他属性再议
  21 + }
  22 +
  23 + toObject () { // 转换成一般对象形式,和静态方法 toGalleryValue 参数对应
  24 + switch (this.type) {
  25 + case GalleryValueType.IMAGE:
  26 + return { url: this.url, flag: IMAGE }
  27 + case GalleryValueType.VIDEO:
  28 + return { url: this.url, flag: VIDEO }
  29 + default:
  30 + throw new Error(`未知的GalleryValue类型:${this.type}`)
  31 + }
  32 + }
  33 +
  34 + /**
  35 + * 转换成GalleryValue对象
  36 + * @param url
  37 + * @param flag
  38 + */
  39 + static toGalleryValue ({ url, flag }) {
  40 + if (GalleryValueType.IMAGE.toString() === 'Symbol(' + flag + ')') {
  41 + return new GalleryValue({ url: url, type: GalleryValueType.IMAGE })
  42 + } else if (GalleryValueType.VIDEO.toString() === 'Symbol(' + flag + ')') {
  43 + return new GalleryValue({ url: url, type: GalleryValueType.VIDEO })
  44 + } else {
  45 + throw new Error(`错误的GalleryValue类型Flag:${flag}`)
  46 + }
  47 + }
  48 +}
  49 +
  50 +export {
  51 + GalleryValueType,
  52 + GalleryValue
  53 +}
... ...
front-end/h5/src/components/core/support/resource-gallery/components/uploader.js 0 → 100644
  1 +/**
  2 + * 上传文件组件。
  3 + */
  4 +export default {
  5 + props: {
  6 + uploadSuccess: {
  7 + type: Function,
  8 + default: () => {}
  9 + },
  10 + beforeUpload: {
  11 + type: Function,
  12 + default: (file) => file
  13 + }
  14 + },
  15 + data () {
  16 + return {
  17 + loading: false
  18 + }
  19 + },
  20 + methods: {
  21 + handleBeforeUpload (file) {
  22 + return this.beforeUpload(file)
  23 + },
  24 + handleChange (info) {
  25 + this.loading = true
  26 + const status = info.file.status
  27 + if (status !== 'uploading') {
  28 + this.loading = true
  29 + const status = info.file.status
  30 + if (status !== 'uploading') {
  31 + console.log(info.file, info.fileList)
  32 + }
  33 + if (status === 'done') {
  34 + this.loading = false
  35 + this.uploadSuccess(info)
  36 + this.$message.success(`${info.file.name} 文件上传成功.`)
  37 + } else if (status === 'error') {
  38 + this.$message.error(`${info.file.name} 文件上传失败.`)
  39 + }
  40 + }
  41 + }
  42 + },
  43 + render (h) {
  44 + return (
  45 + <a-upload
  46 + name="files"
  47 + action="/upload"
  48 + beforeUpload={this.handleBeforeUpload}
  49 + onChange={this.handleChange}>
  50 + <slot>
  51 + <a-button>
  52 + <a-icon type="upload"/>点击上传
  53 + </a-button>
  54 + </slot>
  55 + </a-upload>
  56 + )
  57 + }
  58 +}
... ...
front-end/h5/src/components/core/support/resource-gallery/gallery.js 0 → 100644
  1 +/**
  2 + * 资源库组件(整合图片和视频资源)
  3 + * 整合lbs-image-gallery和lbs-video-gallery
  4 + */
  5 +
  6 +import { GalleryValue, GalleryValueType } from 'core/support/resource-gallery/components/galleryValue'
  7 +import PersonalImage from './tabs/personalImage.js'
  8 +import PersonalVideo from './tabs/personalVideo.js'
  9 +
  10 +export default {
  11 + name: 'bsth-resource-gallery',
  12 + props: {
  13 + visible: { // 是否可见
  14 + type: Boolean,
  15 + default: false
  16 + },
  17 + value: { // 对应的值
  18 + type: GalleryValue
  19 + }
  20 + },
  21 + data () {
  22 + return {
  23 + tabs: [
  24 + {
  25 + value: 'personalImage',
  26 + label: '我的图片库'
  27 + },
  28 + {
  29 + value: 'personalVideo',
  30 + label: '我的视频库'
  31 + }
  32 + ],
  33 + activeTab: 'personalImage',
  34 + innerVisible: false // 对应visible属性
  35 + }
  36 + },
  37 + watch: {
  38 + visible (value) {
  39 + this.innerVisible = value
  40 + }
  41 + },
  42 + methods: {
  43 + showGallery () {
  44 + this.innerVisible = true
  45 + },
  46 + handleClose () {
  47 + this.innerVisible = false
  48 + },
  49 + changeTab ({ key }) {
  50 + this.activeTab = key
  51 + },
  52 + handleSelect (item) { // item是GalleryValue类型
  53 + this.handleClose()
  54 + this.$emit('change', item)
  55 + },
  56 + renderContent () {
  57 + switch (this.activeTab) {
  58 + case 'personalImage' :
  59 + return <PersonalImage onChangeItem={item => {
  60 + this.handleSelect(item)
  61 + }}/>
  62 + case 'personalVideo' :
  63 + return <PersonalVideo onChangeItem={item => {
  64 + this.handleSelect(item)
  65 + }}/>
  66 + }
  67 + },
  68 + renderDefaultActivator () {
  69 + const activatorWithout = (
  70 + <div
  71 + class="default-activator cursor-pointer empty-bg-activator"
  72 + onClick={this.showGallery}
  73 + >
  74 + <a-icon type="plus" />
  75 + </div>
  76 + )
  77 +
  78 + const activatorWithImg = (
  79 + <div onClick={this.showGallery}>
  80 + <div class="default-activator cursor-pointer "><img src={this.value.url} width="50%" style={{ margin: 'auto' }} /></div>
  81 + <div class="flex-space-between" style="margin-top: 8px;">
  82 + <a-button size="small">更换</a-button>
  83 + {/* <a-button size="small" onClick={e => {
  84 + e.stopPropagation()
  85 + }}>裁剪</a-button> */}
  86 + <a-button size="small" onClick={(e) => {
  87 + e.stopPropagation()
  88 + this.handleSelect(new GalleryValue({ type: GalleryValueType.IMAGE, url: '' }))
  89 + }}>移除</a-button>
  90 + </div>
  91 + </div>
  92 + )
  93 +
  94 + const activatorWithVideo = (
  95 + <div onClick={this.showGallery}>
  96 + <div class="default-activator cursor-pointer "><video src={this.value.url} width="50%" style={{ margin: 'auto' }} /></div>
  97 + <div class="flex-space-between" style="margin-top: 8px;">
  98 + <a-button size="small">更换</a-button>
  99 + <a-button size="small" onClick={(e) => {
  100 + e.stopPropagation()
  101 + this.handleSelect(new GalleryValue({ type: GalleryValueType.VIDEO, url: '' }))
  102 + }}>移除</a-button>
  103 + </div>
  104 + </div>
  105 + )
  106 + if (this.value && this.value.url && this.value.type === GalleryValueType.IMAGE) {
  107 + return (activatorWithImg)
  108 + } else if (this.value && this.value.url && this.value.type === GalleryValueType.VIDEO) {
  109 + return (activatorWithVideo)
  110 + } else {
  111 + return (activatorWithout)
  112 + }
  113 + }
  114 + },
  115 + render (h) {
  116 + return (
  117 + <div>
  118 + <slot>{this.renderDefaultActivator()}</slot>
  119 + <a-modal
  120 + closable
  121 + title="资源库"
  122 + width="65%"
  123 + visible={this.innerVisible}
  124 + onOk={this.handleClose}
  125 + onCancel={this.handleClose}
  126 + bodyStyle={{ margin: 0, padding: 0 }}
  127 + >
  128 + <div slot='okText'>确认</div>
  129 + <div slot='cancelText'>取消</div>
  130 + <a-layout style="height: 500px; position: relative;">
  131 + <a-layout-sider width="200px" style="background-color: white;">
  132 + <a-menu mode="inline"
  133 + defaultSelectedKeys={['personalImage']}
  134 + onClick={this.changeTab}>
  135 + {
  136 + this.tabs.map((tab, index) => (
  137 + <a-menu-item key={tab.value} >
  138 + <a-icon type="user" />
  139 + <span>{tab.label}</span>
  140 + </a-menu-item>
  141 + ))
  142 + }
  143 + </a-menu>
  144 + </a-layout-sider>
  145 + <a-layout-content>
  146 + {this.renderContent()}
  147 + </a-layout-content>
  148 + </a-layout>
  149 + </a-modal>
  150 + </div>
  151 + )
  152 + }
  153 +}
... ...
front-end/h5/src/components/core/support/resource-gallery/gallery.scss 0 → 100644
  1 +.default-activator {
  2 + border: 1px dashed #eee;
  3 + text-align: center;
  4 +
  5 + img {
  6 + width: 50%;
  7 + border: 1px dashed #ccc;
  8 + }
  9 +}
  10 +
  11 +.empty-bg-activator {
  12 + height: 178px;
  13 + line-height: 178px;
  14 +}
0 15 \ No newline at end of file
... ...
front-end/h5/src/components/core/support/resource-gallery/tabs/personalImage.js 0 → 100644
  1 +/**
  2 + * 我的图片库组件。
  3 + */
  4 +
  5 +import axios from 'axios'
  6 +import Uploader from 'core/support/resource-gallery/components/uploader.js'
  7 +import { GalleryValue, GalleryValueType } from 'core/support/resource-gallery/components/galleryValue'
  8 +
  9 +export default {
  10 + data () {
  11 + return {
  12 + items: [], // 数据列表(GalleryValue类型)
  13 + loading: false, // 是否载入中
  14 + total: 30, // 总记录数
  15 + page: 1, // 第几页(从1开始)
  16 + pageSize: 30 // 每页大小
  17 + }
  18 + },
  19 + methods: {
  20 + uploadSuccess ({ file }) {
  21 + this.searchFiles()
  22 + },
  23 + beforeUpload (file) {
  24 + this.loading = true
  25 + },
  26 + searchFiles () {
  27 + this.loading = true
  28 + axios.get('/upload/getFiles', {
  29 + params: {
  30 + '_limit': this.pageSize,
  31 + '_start': (this.page - 1) * this.pageSize, // 后台页码从0开始
  32 + 'mime': 'image'
  33 + // TODO:后面再加其他参数
  34 + }
  35 + })
  36 + .then(res => {
  37 + this.items = []
  38 + if (res.data && res.data.dataList && res.data.dataList.length > 0) {
  39 + for (let uploadFileDto of res.data.dataList) {
  40 + this.items.push(new GalleryValue({
  41 + url: uploadFileDto.url, // 获取路径
  42 + type: GalleryValueType.IMAGE // 图片类型
  43 + }))
  44 + }
  45 + this.total = res.data.totalDataCount
  46 + this.page = res.data.page
  47 + this.pageSize = res.data.size
  48 + }
  49 + })
  50 + .catch(err => {
  51 + this.$message.error('资源库数据查询失败')
  52 + })
  53 + .finally(() => {
  54 + this.loading = false
  55 + })
  56 + }
  57 + },
  58 + render (h) {
  59 + return (
  60 + <div>
  61 + <a-spin tip="载入中..." spinning={this.loading}>
  62 + <a-card>
  63 + <Uploader
  64 + slot="extra"
  65 + beforeUpload={file => this.beforeUpload(file)}
  66 + uploadSuccess={info => this.uploadSuccess(info)}
  67 + />
  68 + <a-list
  69 + pagination={{
  70 + showSizeChanger: true,
  71 + total: this.total,
  72 + pageSize: this.pageSize,
  73 + onChange: (page, pageSize) => {
  74 + this.page = page
  75 + this.searchFiles()
  76 + console.log(page)
  77 + },
  78 + onShowSizeChange: (currentPage, pageSize) => {
  79 + this.pageSize = pageSize
  80 + this.searchFiles()
  81 + }
  82 + }}
  83 + style="height: 400px; overflow: auto;"
  84 + grid={{ gutter: 12, column: 3 }}
  85 + dataSource={this.items}
  86 + renderItem={(item, index) => (
  87 + <a-list-item onClick={() => {
  88 + this.$emit('changeItem', item)
  89 + }}>
  90 + <a-card hoverable>
  91 + <div
  92 + slot="cover"
  93 + style={{
  94 + backgroundImage: `url(${item.url})`,
  95 + backgroundSize: 'cover',
  96 + height: '142px'
  97 + }}>
  98 + </div>
  99 + </a-card>
  100 + </a-list-item>
  101 + )}
  102 + >
  103 + </a-list>
  104 + </a-card>
  105 + </a-spin>
  106 + </div>
  107 + )
  108 + },
  109 + mounted () {
  110 + // 请求数据
  111 + this.searchFiles()
  112 + }
  113 +}
... ...
front-end/h5/src/components/core/support/resource-gallery/tabs/personalVideo.js 0 → 100644
  1 +/**
  2 + * 我的视频库组件。
  3 + */
  4 +
  5 +import axios from 'axios'
  6 +import Uploader from 'core/support/resource-gallery/components/uploader.js'
  7 +import { GalleryValue, GalleryValueType } from 'core/support/resource-gallery/components/galleryValue'
  8 +
  9 +export default {
  10 + data () {
  11 + return {
  12 + items: [], // 数据列表(GalleryValue类型)
  13 + loading: false, // 是否载入中
  14 + total: 30, // 总记录数
  15 + page: 1, // 第几页(从1开始)
  16 + pageSize: 30 // 每页大小
  17 + }
  18 + },
  19 + methods: {
  20 + uploadSuccess ({ file }) {
  21 + this.searchFiles()
  22 + },
  23 + beforeUpload (file) {
  24 + this.loading = true
  25 + },
  26 + searchFiles () {
  27 + this.loading = true
  28 + axios.get('/upload/getFiles', {
  29 + params: {
  30 + '_limit': this.pageSize,
  31 + '_start': (this.page - 1) * this.pageSize, // 后台页码从0开始
  32 + 'mime': 'video'
  33 + // TODO:后面再加其他参数
  34 + }
  35 + })
  36 + .then(res => {
  37 + this.items = []
  38 + if (res.data && res.data.dataList && res.data.dataList.length > 0) {
  39 + for (let uploadFileDto of res.data.dataList) {
  40 + this.items.push(new GalleryValue({
  41 + url: uploadFileDto.url, // 获取路径
  42 + type: GalleryValueType.VIDEO // 图片类型
  43 + }))
  44 + }
  45 + this.total = res.data.totalDataCount
  46 + this.page = res.data.page
  47 + this.pageSize = res.data.size
  48 + }
  49 + })
  50 + .catch(err => {
  51 + this.$message.error('资源库数据查询失败')
  52 + })
  53 + .finally(() => {
  54 + this.loading = false
  55 + })
  56 + }
  57 + },
  58 + render (h) {
  59 + return (
  60 + <div>
  61 + <a-spin tip="载入中..." spinning={this.loading}>
  62 + <a-card>
  63 + <Uploader
  64 + slot="extra"
  65 + beforeUpload={file => this.beforeUpload(file)}
  66 + uploadSuccess={info => this.uploadSuccess(info)}
  67 + />
  68 + <a-list
  69 + pagination={{
  70 + showSizeChanger: true,
  71 + total: this.total,
  72 + pageSize: this.pageSize,
  73 + onChange: (page, pageSize) => {
  74 + this.page = page
  75 + this.searchFiles()
  76 + console.log(page)
  77 + },
  78 + onShowSizeChange: (currentPage, pageSize) => {
  79 + this.pageSize = pageSize
  80 + this.searchFiles()
  81 + }
  82 + }}
  83 + style="height: 400px; overflow: auto;"
  84 + grid={{ gutter: 12, column: 3 }}
  85 + dataSource={this.items}
  86 + renderItem={(item, index) => (
  87 + <a-list-item onClick={() => {
  88 + this.$emit('changeItem', item)
  89 + }}>
  90 + <a-card hoverable>
  91 + <video
  92 + onClick={function (e) {
  93 + e.preventDefault() /* 阻止默认点击video标签的默认行为(播放行为) */
  94 + }}
  95 + controls
  96 + slot="cover"
  97 + src={item.url}
  98 + style={{
  99 + height: '240px'
  100 + }}>
  101 + </video>
  102 + </a-card>
  103 + </a-list-item>
  104 + )}
  105 + >
  106 + </a-list>
  107 + </a-card>
  108 + </a-spin>
  109 + </div>
  110 + )
  111 + },
  112 + mounted () {
  113 + // 请求数据
  114 + this.searchFiles()
  115 + }
  116 +}
... ...