提交 43a00b0e authored 作者: 龙菲's avatar 龙菲

布展管理新增、编辑功能;字典逻辑修改

上级 c8431db1
import request from '@/utils/request'
export function getDeptDetailById(id) {
return request({
url: '/sys/dept/'+id,
method: 'get',
})
}
export function getDepList() {
return request({
url: '/sys/depts',
method: 'get',
})
}
\ No newline at end of file
import request from '@/utils/request'
// 获取列表
export function getList(data) {
return request({
url: '/bizExhibition/listByPage',
......@@ -7,3 +8,18 @@ export function getList(data) {
data
})
}
// 新增
export function addDisplay(data) {
return request({
url: '/bizExhibition/add',
method: 'post',
data
})
}
export function editDisplay(data) {
return request({
url: '/bizExhibition/update',
method: 'put',
data
})
}
\ No newline at end of file
......@@ -28,6 +28,6 @@ export function getInfo(token) {
export function logout() {
return request({
url: '/sys/user/logout',
method: 'post'
method: 'get'
})
}
import {
getDictCode
} from "@/api/dict";
import {
getLiteratureList
} from '@/api/literature'
import store from "@/store";
import Vue from "vue";
class Dict {
......@@ -9,36 +12,75 @@ class Dict {
}
async init(names) {
// console.log('names', names);
// const ps = [];
await getDictCode(names).then((data) => {
// 先判断list中的name是否存在,如果不存在,把不存在的放置在一个list中,再对list进行获取
var nonExistentNames = []
// debugger
names.forEach(name => {
// 如果vuex中已经存在当前字典名,则不进行设置
if (store.getters.dicts[name]) {
Vue.set(this.dict, name, store.getters.dicts[name]);
} else {
Vue.set(this.dict, name, []);
// this.dict[name] = Object.freeze(data);
// 把dictType都为name的全部传入this.dict[name]中
nonExistentNames.push(name) //存入list中,单独进行处理调用
}
});
// console.log('nonExistentNames', nonExistentNames);
// 拿所有不存在的name去获取字典
// 对所有不存在的name进行遍历,如果里面有literature,则删除该数组中的literature
var index = nonExistentNames.indexOf('literature')
// console.log('index');
if (index != -1) {
// debugger
Vue.set(this.dict, 'literature', []);
nonExistentNames.splice(index, 1)
var params = {
limit: 100,
page: 1
}
var res = await getLiteratureList(params)
if (res.code == 0) {
var literatureList = res.data.records
Vue.set(this.dict, 'literature', literatureList);
this.dict['literature'] = Object.freeze(literatureList)
store.commit("dict/SET_DICTS", {
label: 'literature',
value: Object.freeze(literatureList),
});
}
}
if (nonExistentNames.length > 0) {
var res = await getDictCode(nonExistentNames)
nonExistentNames.forEach(n => {
Vue.set(this.dict, n, []);
var arr = []
data.data.map(item => {
if (item.dictType === name) {
if (res.code == 0) {
res.data.map(item => {
if (item.dictType === n) {
arr.push(item)
}
})
this.dict[name] = Object.freeze(arr)
this.dict[n] = Object.freeze(arr)
store.commit("dict/SET_DICTS", {
label: name,
label: n,
value: Object.freeze(arr),
});
}
});
})
}
}
loadDictCode() {
}
}
const install = function (Vue) {
Vue.mixin({
data() {
// 如果在调用组件处data中有定义dicts,再进行初始化dict
if (
this.$options.dicts instanceof Array &&
this.$options.dicts.length > 0
......@@ -51,6 +93,7 @@ const install = function (Vue) {
}
},
created() {
// 如果在调用组件处data中有定义dicts,再进行获取dicts中定义的字典
if (
this.$options.dicts instanceof Array &&
this.$options.dicts.length > 0
......
<template>
<el-form :inline="true" :model="form">
<el-form :inline="true">
<el-form-item
item.label="展览名称"
:label="item.label"
v-for="(item, index) in config"
:key="index"
>
<el-input
v-if="item.type == 'input'"
v-model="form[item.prop]"
v-model="searchData[item.prop]"
:placeholder="item.placeholder || item.label"
></el-input>
<el-select
v-if="item.type == 'select'"
v-model="searchData[item.prop]"
:placeholder="item.placeholder || item.label"
>
<el-option
:label="option.label"
:value="option.value"
v-for="option in item.selectOptions"
:key="option.value"
></el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="search" icon="el-icon-search">
<el-button
type="primary"
icon="el-icon-search"
@click.native="handleSearch"
>
查询</el-button
>
<el-button type="primary" @click="reset" icon="el-icon-refresh">
<el-button
type="primary"
icon="el-icon-refresh"
@click.native="handleReset"
>
重置</el-button
>
</el-form-item>
......@@ -26,10 +46,6 @@
export default {
name: "SearchBar",
props: {
form: {
type: Object,
default: () => ({}),
},
config: {
type: Array,
default: () => [{}],
......@@ -68,14 +84,32 @@ export default {
*
*/
},
watch: {
config: {
handler: function (value) {
if (value) {
var obj = {};
this.config.map((item) => {
obj[item.prop] = "";
});
this.searchData = JSON.parse(JSON.stringify(obj));
}
},
immediate: true,
deep: true,
},
},
data() {
return {};
return {
searchData: {},
};
},
methods: {
search() {
this.$emit("search");
handleSearch() {
this.$emit("search", this.searchData);
},
reset() {
handleReset() {
this.searchData = {};
this.$emit("reset");
},
},
......
......@@ -23,11 +23,23 @@
:header-align="item.titleAlign"
>
<template slot-scope="scope">
<template v-if="item.tag">
<slot name="tags" :scope="scope.row"></slot>
<template v-if="item.prop=='faceImage'">
<slot name="faceImage" :scope="scope.row"></slot>
</template>
<template v-if="item.isStatus">
<template v-else-if="item.prop=='images'">
<slot name="images" :scope="scope.row"></slot>
</template>
<template v-else-if="item.prop=='audios'">
<slot name="audios" :scope="scope.row"></slot>
</template>
<template v-else-if="item.prop=='videos'">
<slot name="videos" :scope="scope.row"></slot>
</template>
<template v-else-if="item.isStatus">
<slot name="status" :scope="scope.row"></slot>
</template>
<template v-else-if="item.prop=='type'">
<slot name="type" :scope="scope.row"></slot>
</template>
<span v-else>{{ scope.row[item.prop] }}</span>
</template>
......@@ -39,6 +51,7 @@
:width="operates.width"
:align="operates.columnAlign"
:header-align="operates.titleAlign"
fixed="right"
>
<template slot-scope="scope">
<slot name="operates" :scope="scope"></slot>
......
<template>
<el-upload
:action="uploadUrl"
:before-upload="handleBeforeUpload"
:on-success="handleSuccess"
:on-error="handleUploadError"
:on-remove="handleRemove"
:on-exceed="handleExceed"
:on-change="handleChange"
:file-list="fileList"
:multiple="fileLimit > 1"
:headers="headers"
:limit="fileLimit"
:list-type="listType"
name="files"
:class="{ disabled: uploadDisabled }"
:accept="fileAccept"
>
<el-button slot="trigger" size="small" type="primary">选取文件</el-button>
<div slot="tip" class="el-upload__tip" style="margin-bottom: 10px">
只能上传mp3文件,且不超过2M,播放长度不超过60s
</div>
</el-upload>
</template>
<script>
export default {
beforeAvatarUpload(file) {
// 文件类型进行判断
const isAudio = file.type === "audio/mp3" || file.type === "audio/mpeg";
// 限制上传文件大小 2M
const isLt2M = file.size / 1024 / 1024 < 2;
const isTime60S = this.audioDuration >= 60 ? true : "";
// 获取时长
this.getTimes(file);
if (!isAudio) {
this.$message.error("上传文件只能是Mp3格式!");
this.fileList = [];
} else {
if (!isLt2M) {
this.$message.error("上传文件大小不能超过 2MB!");
this.fileList = [];
} else {
if (!isTime60S) {
this.$message.error("上传文件时长不能超过60秒!");
this.fileList = [];
}
}
}
return isAudio && isLt2M && isTime60S;
},
getTimes(file) {
var content = file;
//获取录音时长
var url = URL.createObjectURL(content);
//经测试,发现audio也可获取视频的时长
var audioElement = new Audio(url);
audioElement.addEventListener("loadedmetadata", (_event) => {
this.audioDuration = parseInt(audioElement.duration);
// console.log(this.audioDuration);
});
},
};
</script>
<style>
</style>
\ No newline at end of file
<!-- -->
<template>
<el-upload
class="avatar-uploader"
:action="uploadUrl"
v-bind:on-progress="uploadVideoProcess"
v-bind:on-success="handleVideoSuccess"
v-bind:before-upload="beforeUploadVideo"
v-bind:show-file-list="false"
:headers="headers"
>
<video
v-if="videoForm.showVideoPath != '' && !videoFlag"
v-bind:src="videoForm.showVideoPath"
class="avatar video-avatar"
controls="controls"
>
您的浏览器不支持视频播放
</video>
<i
v-else-if="videoForm.showVideoPath == '' && !videoFlag"
class="el-icon-plus avatar-uploader-icon"
></i>
<el-progress
v-if="videoFlag == true"
type="circle"
v-bind:percentage="videoUploadPercent"
style="margin-top: 7px"
></el-progress>
</el-upload>
</template>
<script>
export default {
data() {
return {
uploadUrl:
process.env.NODE_ENV === "test" ||
process.env.NODE_ENV === "development"
? "/api/sysFiles/upload"
: process.env.NODE_ENV + "/sysFiles/upload", // 上传的图片服务器地址
headers: {
authorization: getToken(),
},
videoFlag: false,
//是否显示进度条
videoUploadPercent: "",
//进度条的进度,
isShowUploadVideo: false,
//显示上传按钮
videoForm: {
showVideoPath: "", //回显的变量
},
};
},
mounted() {},
methods: {
//上传前回调
beforeUploadVideo(file) {
var fileSize = file.size / 1024 / 1024 < 50; //控制大小 修改50的值即可
if (
[
"video/mp4",
"video/ogg",
"video/flv",
"video/avi",
"video/wmv",
"video/rmvb",
"video/mov",
].indexOf(file.type) == -1 //控制格式
) {
layer.msg("请上传正确的视频格式");
return false;
}
if (!fileSize) {
layer.msg("视频大小不能超过50MB");
return false;
}
this.isShowUploadVideo = false;
},
//进度条
uploadVideoProcess(event, file, fileList) {
//注意在data中添加对应的变量名
this.videoFlag = true;
this.videoUploadPercent = file.percentage.toFixed(0) * 1;
},
//上传成功回调
handleVideoSuccess(res, file) {
this.isShowUploadVideo = true;
this.videoFlag = false;
this.videoUploadPercent = 0;
console.log(res);
//后台上传数据
if (res.success == true) {
this.videoForm.showVideoPath = res.data.url; //上传成功后端返回视频地址 回显
} else {
this.$message.error("上传失败!");
}
},
},
};
</script>
<style lang="scss" scoped>
</style>
......@@ -14,12 +14,14 @@
:limit="fileLimit"
:list-type="listType"
name="files"
:class="{ disabled: uploadDisabled }"
:accept="fileAccept"
>
<i v-if="listType === 'picture-card'" class="el-icon-plus"></i>
<el-button v-else size="small" type="primary">点击上传</el-button>
<div v-if="showTip" slot="tip" class="el-upload__tip">
只能上传{{ fileTypeName || "jpg/png" }}文件,且不超过 {{ fileSize }}MB
只能上传{{ fileTypeName || "jpg/png" }}文件,且不超过
{{ fileSize }}MB,最多上传{{ fileLimit }}个文件
</div>
</el-upload>
</div>
......@@ -30,7 +32,11 @@ export default {
name: "Uploader",
props: {
// 值
value: [String, Object, Array],
// value: [String, Object, Array],
files: {
type: Array,
default: () => [],
},
// 大小限制(MB)
fileSize: {
type: Number,
......@@ -68,14 +74,20 @@ export default {
authorization: getToken(),
},
fileList: [],
tempFileList: [],
// tempFileList: [],
uploadDisabled: false,
};
},
watch: {
value: {
handler: function (newVal, oldVa) {
this.tempFileList = newVal;
files: {
handler: function (newVal, oldVal) {
console.log("newVal", newVal);
this.fileList = newVal;
// if (this.fileList.length >= this.fileLimit) {
// this.uploadDisabled = true;
// }else{
// this.uploadDisabled = false;
// }
},
immediate: true,
deep: true,
......@@ -102,12 +114,58 @@ export default {
},
},
created() {
this.fileList = JSON.parse(JSON.stringify(this.value));
this.fileList = JSON.parse(JSON.stringify(this.files));
},
methods: {
// 自定义上传实现,用于修改上传后的封面
uploadmany(file) {
var formData = new FormData(); //这是由于接口数据类型规定,可以根据自己所需进行更改
formData.append("files", file.file);
upload(formData).then((res) => {
if (res.code == 0) {
console.log(res);
var last = res.data.substring(res.data.lastIndexOf(".")); //将接口中返回的各文件链接进行截取,来判断属于什么格式文件
if (last == ".pdf") {
this.fileList.push({
url: "https://img0.baidu.com/it/u=3644622474,3688361323&fm=26&fmt=auto&gp=0.jpg", //pdf封面图片
realUrl: res.data.result, //接口返回的pdf文件链接
});
} else if (
last == ".png" ||
last == ".jpg" ||
last == ".jpeg" ||
last == ".jfif"
) {
this.fileList.push({
url: res.data.result,
realurl: res.data.result,
});
} else if (last == ".doc" || last == ".docx") {
this.fileList.push({
url: "https://img1.baidu.com/it/u=1714136260,3766911961&fm=26&fmt=auto&gp=0.jpg",
realurl: res.data.result,
});
} else if (last == ".xls" || last == ".xlsx") {
this.fileList.push({
url: "https://img1.baidu.com/it/u=1123362811,2189997153&fm=26&fmt=auto&gp=0.jpg",
realurl: res.data.result,
});
}
} else {
this.$message({
message: res.data.message,
type: "error",
offset: 70,
});
}
});
},
// 上传前校检格式和大小
handleBeforeUpload(file) {
// 校检文件类型
this.$emit("endLoading");
this.$emit("startLoading");
if (this.fileType && file) {
let fileExtension = "";
if (file.name.lastIndexOf(".") > -1) {
......@@ -122,6 +180,7 @@ export default {
this.$message.error(
`文件格式不正确, 请上传${this.fileType.join("/")}格式文件!`
);
this.$emit("endLoading");
return false;
}
}
......@@ -146,6 +205,7 @@ export default {
handleSuccess(res, file, fileList) {
console.log("res", res);
this.$message.success("上传成功");
this.$emit("endLoading");
this.changeFileList(fileList);
},
// 文件列表移除文件时的钩子
......@@ -154,9 +214,9 @@ export default {
},
handleChange(file, fileList) {
if (fileList.length == this.fileLimit) {
this.uploadDisabled = true;
}
// if (fileList.length == this.fileLimit) {
// this.uploadDisabled = true;
// }
},
// 文件列表改变的时候,更新组件的v-model的文的数据
......@@ -169,7 +229,8 @@ export default {
};
return tempItem;
});
// this.$emit("handleFileReady", tempFileList);
this.$emit("endLoading");
this.$emit("handleFileReady", tempFileList);
},
},
};
......
......@@ -46,7 +46,7 @@ export default {
this.$store.dispatch("app/toggleSideBar");
},
async logout() {
await this.$store.dispatch("user/logout");
let res = await this.$store.dispatch("user/logout");
this.$router.push(`/login?redirect=${this.$route.fullPath}`);
},
},
......
......@@ -2,6 +2,7 @@ const getters = {
sidebar: state => state.app.sidebar,
device: state => state.app.device,
token: state => state.user.token,
userInfo: state => state.user.userInfo,
avatar: state => state.user.avatar,
name: state => state.user.name,
dicts: state => state.dict.dicts
......
......@@ -3,10 +3,16 @@ import {
logout,
getInfo
} from '@/api/user'
import{
getDepList
} from '@/api/dept'
import {
getToken,
setToken,
removeToken
removeToken,
getUserInfo,
setUserInfo,
removeUserInfo
} from '@/utils/auth'
import {
resetRouter
......@@ -15,8 +21,10 @@ import {
const getDefaultState = () => {
return {
token: getToken(),
userInfo:getUserInfo(),
name: '',
avatar: ''
avatar: '',
// deptList:{}
}
}
......@@ -34,7 +42,13 @@ const mutations = {
},
SET_AVATAR: (state, avatar) => {
state.avatar = avatar
}
},
SET_USERINFO: (state, userInfo) => {
state.userInfo = userInfo
},
// SET_DEPTLIST:(state,deptList)=>{
// state.deptList = deptList
// }
}
const actions = {
......@@ -58,7 +72,9 @@ const actions = {
} = response
commit('SET_TOKEN', data.accessToken)
commit('SET_NAME', data.username)
commit('SET_USERINFO', data)
setToken(data.accessToken)
setUserInfo(data)
resolve()
}).catch(error => {
reject(error)
......@@ -67,33 +83,33 @@ const actions = {
},
// get user info
getInfo({
commit,
state
}) {
return new Promise((resolve, reject) => {
getInfo(state.token).then(response => {
const {
data
} = response
// getInfo({
// commit,
// state
// }) {
// return new Promise((resolve, reject) => {
// getInfo(state.token).then(response => {
// const {
// data
// } = response
if (!data) {
return reject('Verification failed, please Login again.')
}
// if (!data) {
// return reject('Verification failed, please Login again.')
// }
const {
name,
avatar
} = data
// const {
// name,
// avatar
// } = data
commit('SET_NAME', name)
commit('SET_AVATAR', avatar)
resolve(data)
}).catch(error => {
reject(error)
})
})
},
// commit('SET_NAME', name)
// commit('SET_AVATAR', avatar)
// resolve(data)
// }).catch(error => {
// reject(error)
// })
// })
// },
// user logout
logout({
......@@ -103,11 +119,13 @@ const actions = {
return new Promise((resolve, reject) => {
logout(state.token).then(() => {
removeToken() // must remove token first
removeUserInfo()
resetRouter()
commit('RESET_STATE')
resolve()
}).catch(error => {
reject(error)
console.log('err',error);
// reject(error)
})
})
},
......@@ -121,7 +139,25 @@ const actions = {
commit('RESET_STATE')
resolve()
})
}
},
// getDeptList({
// commit,
// state
// }) {
// return new Promise((resolve, reject) => {
// let deptRes = await getDepList();
// let deptList = {};
// deptRes.data.map((dept) => {
// deptList[dept[id]] = {
// name: dept.name,
// regionCode: dept.regionCode,
// };
// });
// this.$store.commit('SET_DEPTLIST',deptList)
// })
// },
}
export default {
......
import Cookies from 'js-cookie'
const TokenKey = 'exhibition_token'
const UserInfoKey = 'exhibition_userInfo'
export function getToken() {
// return Cookies.get(TokenKey)
......@@ -16,3 +17,17 @@ export function removeToken() {
// return Cookies.remove(TokenKey)
localStorage.removeItem(TokenKey)
}
export function setUserInfo(userInfo){
return localStorage.setItem(UserInfoKey,JSON.stringify(userInfo))
}
export function getUserInfo() {
// return Cookies.get(TokenKey)
return JSON.parse(localStorage.getItem(UserInfoKey))
}
export function removeUserInfo() {
// return Cookies.remove(TokenKey)
localStorage.removeItem(UserInfoKey)
}
......@@ -54,8 +54,6 @@ service.interceptors.response.use(
*/
response => {
const res = response.data
// debugger
console.log(res.code);
// console.log('响应拦截res--------',response);
if (response.config.url === '/api/sys/getVerify') {
// debugger
......@@ -69,8 +67,8 @@ service.interceptors.response.use(
type: 'error',
duration: 5 * 1000
})
// 401001l令牌过期;500001
if (res.code === 401001 || res.code === 500001) {
// 401001l令牌过期;
if (res.code === 401001) {
MessageBox.confirm('登录令牌已过期,请重新登录', '确认退出', {
confirmButtonText: '重新登录',
cancelButtonText: '取消',
......
......@@ -12,7 +12,6 @@ export function upload(url, data) {
return new Promise((resolve, reject) => {
axios.post(url, data, {
headers: {
'Content-Type': 'multipart/form-data',
'authorization': getToken(),
}
}).then(response => {
......
// // {
// "audios": "",//音频
// // "crId": "",//主键
// // "deptId": "",//收藏馆id!
// // "detailSize": "",//具体尺寸!
// "directory": "",//文件夹(字母或者数字命名)
// "flag3d": "",//是否有3D图片(字典值:1-有;0-无)
// "images": "",//图片文件(文件id,多个以逗号隔开)
// // "intro": "",//馆藏介绍!
// // "level": "",//文物级别(字典值)!
// "literature": "",//关联文献。id1,id2,id3
// // "name": "",//名称!
// // "num": 0,// 数量!
// // "regionCode": "",// 所属地(分号分隔的编号)!
// "remark": "",//备注
// "sayExplain": "",//讲解词文件。文件id
// "sourceWay": "",//来源方式
// "status": "",//上下架状态(0-下架,1-上架)
// // "textureType": "",//质地类别(字典值)!
// "themeWord": "",//主题词
// // "type": "",//类别(字典值)!
// "url3d": "",// 3durl链接
// "videos": "",//视频文件(文件id)
// // "years": ""//年代!
// // }
export const title = [{
prop: "name",
label: "名称",
columnAlign: 'center',
},
{
prop: "num",
label: "数量",
columnAlign: 'center',
},
{
prop: "years",
label: "年代",
columnAlign: 'center',
},
{
prop: "type",
label: "类别",
columnAlign: 'center',
},
{
prop: "level",
label: "级别",
columnAlign: 'center',
},
{
prop: "textureType",
label: "质地",
columnAlign: 'center',
},
{
prop: "detailSize",
label: "尺寸",
columnAlign: 'center',
},
{
prop: "deptId",
label: "馆藏单位",
columnAlign: 'center',
},
{
prop: "regionCode",
label: "所属地",
columnAlign: 'center',
},
{
prop: "intro",
label: "馆藏介绍",
columnAlign: 'center',
},
{
prop: "literature",
label: "关联文献",
columnAlign: 'center',
},
{
prop: "collectCount",
label: "收藏量",
columnAlign: 'center',
},
{
prop: "loveCount",
label: "点赞量",
width: 100,
columnAlign: 'center',
},
{
prop: "region",
label: "所在地区",
width: 100,
columnAlign: 'center',
},
{
prop: "remark",
label: "备注",
width: 100,
columnAlign: 'center',
},
{
prop: "status",
label: "状态",
width: 100,
columnAlign: 'center',
isStatus: true
},
{
prop: "themeType",
label: "模板主题",
width: 100,
columnAlign: 'center',
isStatus: true
},
{
prop: "videos",
label: "展览视频",
width: 100,
columnAlign: 'center',
},
]
export const operates = {
operate: true,
label: "操作",
width: "300px",
minwidth: "220px",
titleAlign: "center",
columnAlign: "center",
}
export const operations = [{
type: 'view',
title: '预览'
},
{
type: 'edit',
title: '编辑'
},
{
type: 'delete',
title: '删除'
},
]
export const literatureTableTitle=[
{
prop: "name",
label: "文献名称",
columnAlign: 'center',
},
{
prop: "authors",
label: "作者",
columnAlign: 'center',
},
{
prop: "remark",
label: "备注",
columnAlign: 'center',
},
]
\ No newline at end of file
<template>
<el-dialog
:visible.sync="dialogVisible"
width="50%"
style="height: 98%"
:before-close="handleClose"
top="5vh"
lock-scroll
>
<div class="title" slot="title">
<div class="divider"></div>
<div class="label">{{ title }}</div>
</div>
<div class="dialog-content">
<el-main style="height: 100%">
<el-row v-if="videos.length == 1" style="height: 100%">
<el-col :span="24" style="height: 100%" class="video-container">
<video
:src="videos[0]"
style="height: auto; width: 100%"
controls
muted
loop
></video>
</el-col>
</el-row>
<el-row v-if="videos.length > 1" style="height: 100%" :gutter="16">
<template v-for="(item, index) in videos">
<el-col
:span="16"
:key="item"
v-if="index == 0"
style="height: 100%"
class="video-container"
>
<video
:src="videos[0]"
style="height: auto; width: 100%"
controls
loop
></video>
</el-col>
<el-col :span="8" :key="item" v-else>
<video
:src="videos[index]"
style="height: auto; width: 100%"
class="video-container"
controls
loop
></video>
</el-col>
</template>
</el-row>
</el-main>
<div class="dialog-footer">
<el-button type="primary" @click="handleClose">关闭</el-button>
</div>
</div>
</el-dialog>
</template>
<script>
export default {
name: "PreviewDialog",
components: {},
props: {
visible: {
type: Boolean,
default: false,
},
videos: {
type: Array,
default: () => [],
},
},
computed: {
dialogVisible: {
get: function () {
return this.visible;
},
set: function () {},
},
title() {
return "查看视频";
},
},
dicts: [],
data() {
return {};
},
async created() {
// console.log(this.videos);
},
methods: {
// 取消编辑
cancelForm() {
this.$emit("handleClose");
},
handleClose(done) {
this.$emit("handleClose");
},
},
};
</script>
<style lang='scss' scoped>
.title {
display: flex;
margin-bottom: 16px;
.divider {
width: 8px;
border-left: 4px solid #409eff;
margin-right: 8px;
}
.label {
font-weight: bold;
}
}
.dialog-content {
padding: 0 32px;
display: flex;
flex-direction: column;
.relate {
flex: 1;
}
.dialog-footer {
display: flex;
justify-content: flex-end;
}
}
.video-container {
background-color: #000;
display: flex;
justify-content: center;
}
.el-dialog__body {
padding: 0 20px 30px 20px;
}
</style>
\ No newline at end of file
......@@ -2,6 +2,7 @@ export const title = [{
prop: "title",
label: "标题",
columnAlign: 'center',
width:120
},
{
prop: "keyword",
......@@ -15,31 +16,31 @@ export const title = [{
},
{
prop: "dep_id",
label: "展览单位id",
prop: "depName",
label: "展览单位",
columnAlign: 'center',
isDept: true
},
{
prop: "faceImage",
label: "封面",
columnAlign: 'center',
isFaceImage: true,
width:130
},
{
prop: "images",
label: "展览图片",
columnAlign: 'center',
},
{
prop: "intro",
label: "展览介绍",
columnAlign: 'center',
},
{
prop: "literature",
label: "关联文献",
columnAlign: 'center',
},
// {
// prop: "literature",
// label: "关联文献",
// columnAlign: 'center',
// width:100
// },
{
prop: "collectCount",
label: "收藏量",
......@@ -48,48 +49,59 @@ export const title = [{
{
prop: "loveCount",
label: "点赞量",
width: 100,
columnAlign: 'center',
},
{
prop: "region",
prop: "browseCount",
label: "浏览量",
columnAlign: 'center',
},
{
prop: "regionCode",
label: "所在地区",
width: 100,
columnAlign: 'center',
},
{
prop: "remark",
label: "备注",
width: 100,
columnAlign: 'center',
},
{
prop: "status",
label: "状态",
width: 100,
columnAlign: 'center',
isStatus: true
},
{
prop: "themeType",
label: "模板主题",
width: 100,
columnAlign: 'center',
isStatus: true
},
{
prop: "videos",
label: "展览视频",
width: 100,
prop: "images",
label: "展览图片",
columnAlign: 'center',
},
isImages: true
},
// {
// prop: "audios",
// label: "展览音频",
// columnAlign: 'center',
// isAudios: true
// },
// {
// prop: "videos",
// label: "展览视频",
// columnAlign: 'center',
// isVideos: true
// },
]
export const operates = {
operate: true,
label: "操作",
width: "300px",
width: "260px",
minwidth: "220px",
titleAlign: "center",
columnAlign: "center",
......@@ -110,8 +122,7 @@ export const operations = [{
]
export const literatureTableTitle=[
{
export const literatureTableTitle = [{
prop: "name",
label: "文献名称",
columnAlign: 'center',
......
<!-- -->
<template>
<div class="display app-container">
<div class="top-bar">
<el-form :inline="true" :model="search" class="demo-form-inline">
<el-form-item label="展览名称">
<el-input v-model="search.name" placeholder="展览名称"></el-input>
</el-form-item>
<el-form-item label="状态">
<el-select v-model="search.status" placeholder="状态">
<el-option label="已上线" :value="1"></el-option>
<el-option label="已下线" :value="0"></el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSubmitSearch">
<i class="el-icon-search"></i>
查询</el-button
>
</el-form-item>
</el-form>
<el-button type="primary" @click.native="handleOpenDialog('add')">
<i class="el-icon-s-promotion"></i>
发布</el-button
>
</div>
<template>
<el-table
ref="multipleTable"
:data="list.record"
tooltip-effect="dark"
style="width: 100%"
border
@selection-change="handleSelectionChange"
>
<el-table-column type="selection" width="55"> </el-table-column>
<el-table-column
prop="theme_type"
label="展览主题"
show-overflow-tooltip
>
</el-table-column>
<el-table-column prop="title" label="展览标题" width="120">
</el-table-column>
<el-table-column prop="type" label="展览类型" show-overflow-tooltip>
</el-table-column>
<el-table-column
prop="character"
label="展览性质"
show-overflow-tooltip
>
</el-table-column>
<el-table-column prop="ragion" label="所在地域" show-overflow-tooltip>
</el-table-column>
<el-table-column prop="dep_id" label="展览单位" show-overflow-tooltip>
</el-table-column>
<el-table-column prop="intro" label="展览介绍" show-overflow-tooltip>
</el-table-column>
<el-table-column prop="status" label="状态" show-overflow-tooltip>
<template slot-scope="scope">
<el-popconfirm
:title="'是否确定' + getStatusLabel(scope.row.status)"
>
<el-switch
v-model="scope.row.status"
@change="handleChangeStatus(scope.row)"
slot="reference"
>
</el-switch>
</el-popconfirm>
</template>
</el-table-column>
<el-table-column label="操作" width="300" fixed="right">
<template slot-scope="scope">
<!-- <el-button
size="mini"
@click="handleEdit(scope.$index, scope.row)"
type="primary"
><i class="el-icon-upload" style="margin-right: 4px"></i
></el-button
> -->
<!-- <el-button
size="mini"
@click="handleEdit(scope.row)"
type="primary"
>
<i class="el-icon-open" style="margin-right: 4px"></i
>上下架</el-button
> -->
<el-button
size="mini"
@click="handlePreview(scope.row)"
type="primary"
><i class="el-icon-edit" style="margin-right: 4px"></i
>预览</el-button
>
<el-button
size="mini"
@click="handleOpenDialog('edit', scope.row)"
type="primary"
><i class="el-icon-edit" style="margin-right: 4px"></i
>编辑</el-button
>
<el-button
size="mini"
type="danger"
@click="handleDelete(scope.$index, scope.row)"
>
<i class="el-icon-delete" style="margin-right: 4px"></i>
删除</el-button
>
</template>
</el-table-column>
</el-table>
</template>
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="list.current"
:page-sizes="[100, 200, 300, 400]"
:page-size="list.size"
layout="total, sizes, prev, pager, next, jumper"
:total="list.total"
class="pagination"
>
</el-pagination>
<InfoEditDialog
:visible="drawerVisible"
:form="form"
:cascaderOptions="cascaderOptions"
@handleClose="handleClose"
/>
</div>
</template>
<script>
import { getList } from "@/api/display";
import InfoEditDialog from "./components/InfoEditDialog";
export default {
components: {
InfoEditDialog,
},
data() {
return {
multipleSelection: [],
pickerOptions: {
shortcuts: [
{
text: "最近一周",
onClick(picker) {
const end = new Date();
const start = new Date();
start.setTime(start.getTime() - 3600 * 1000 * 24 * 7);
picker.$emit("pick", [start, end]);
},
},
{
text: "最近一个月",
onClick(picker) {
const end = new Date();
const start = new Date();
start.setTime(start.getTime() - 3600 * 1000 * 24 * 30);
picker.$emit("pick", [start, end]);
},
},
{
text: "最近三个月",
onClick(picker) {
const end = new Date();
const start = new Date();
start.setTime(start.getTime() - 3600 * 1000 * 24 * 90);
picker.$emit("pick", [start, end]);
},
},
],
},
list: {
record: [],
size: 10,
current: 1,
total: 0,
},
search: {
searchTime: [new Date(), new Date()],
name: "",
status: "",
},
drawerVisible: false,
isAdd: true,
form: {
name: "",
startTime: "",
endTime: "",
imgs: [],
audios: [],
videos: [],
},
loading: false,
cascaderOptions: [
{
value: "zhinan",
label: "指南",
children: [
{
value: "shejiyuanze",
label: "设计原则",
children: [
{
value: "yizhi",
label: "一致",
},
{
value: "fankui",
label: "反馈",
},
{
value: "xiaolv",
label: "效率",
},
{
value: "kekong",
label: "可控",
},
],
},
{
value: "daohang",
label: "导航",
children: [
{
value: "cexiangdaohang",
label: "侧向导航",
},
{
value: "dingbudaohang",
label: "顶部导航",
},
],
},
],
},
],
};
},
computed: {
getStatusLabel(status) {
return (status) => {
return status ? "上线" : "下线";
};
},
},
mounted() {
this.loadData();
},
methods: {
// 加载表格数据
async loadData() {
var params = {
current: this.list.current,
size: this.list.size,
};
let res = await getList(params);
this.list = res.data;
},
// 选中、反选
toggleSelection(rows) {
if (rows) {
rows.forEach((row) => {
this.$refs.multipleTable.toggleRowSelection(row);
});
} else {
this.$refs.multipleTable.clearSelection();
}
},
// 多选
handleSelectionChange(val) {
this.multipleSelection = val;
},
// 改变页容量
handleSizeChange() {},
// 改变当前显示页
handleCurrentChange() {},
// 搜索
onSubmitSearch() {
console.log("submit!");
},
// 点击状态
handleChangeStatus(status) {
console.log("handleChangeStatus", status);
},
// 打开drawer
handleOpenDialog(type, value) {
this.drawerVisible = true;
switch (type) {
case "add":
console.log("新增");
break;
case "edit":
console.log("编辑", value);
break;
}
},
// 关闭Dialog
handleClose() {
this.drawerVisible = false;
},
// 预览展览
handlePreview(data) {},
},
};
</script>
<style lang="scss" scoped>
.display {
.top-bar {
display: flex;
justify-content: space-between;
align-items: flex-start;
}
.pagination {
margin-top: 10px;
}
}
</style>
<template>
<div class="app-container">
<div class="top-bar">
<!-- <SearchBar :form="searchForm" :config="searchConfig" /> -->
<el-button type="primary" @click.native="handleOpenDialog('add')">
<SearchBar :config="searchConfig" @search="search" @reset="reset" />
<el-button type="primary" @click.native="handleOperation({type:'add'})">
<i class="el-icon-s-promotion"></i>
发布</el-button
>
</div>
<TablePage
:data="list.record"
:data="list.records"
:tableTitle="tableTitle"
:operates="tableOperates"
>
......@@ -20,6 +20,40 @@
<el-switch slot="reference" :value="data.scope.status"></el-switch>
</el-popconfirm>
</template>
<template v-slot:type="data">
{{ displayTypes[data.scope.type] }}
</template>
<template v-slot:faceImage="data">
<img
:src="data.scope.faceImage"
alt="查看大图"
v-if="data.scope.faceImage"
style="cursor: pointer"
width="100px"
@click="handelPreviewImages(data.scope.faceImage)"
/>
</template>
<template v-slot:images="data">
<span
v-if="data.scope.images"
style="color: #409eff; cursor: pointer"
@click="handelPreviewImages(data.scope.images)"
>查看大图</span
>
</template>
<template v-slot:videos="data">
<span
v-if="data.scope.videos"
style="color: #409eff; cursor: pointer"
@click="handelPreviewVideos(data.scope.videos)"
>查看视频</span
>
</template>
<template v-slot:audios="data">
<span v-if="data.scope.videos" style="color: #409eff; cursor: pointer"
>查看音频</span
>
</template>
<template v-slot:operates="scope">
<TableOperation
:operations="tableOperations"
......@@ -29,10 +63,11 @@
</template>
</TablePage>
<el-pagination
style="margin: 16px 0"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="Number(list.current)"
:page-sizes="[100, 200, 300, 400]"
:page-sizes="[10, 20, 50, 100]"
:page-size="Number(list.size)"
layout="total, sizes, prev, pager, next, jumper"
:total="Number(list.total)"
......@@ -40,9 +75,20 @@
>
</el-pagination>
<InfoEditDialog
:visible="drawerVisible"
:visible="editDialogVisible"
:form="form"
@handleClose="handleClose"
@refresh="loadData"
/>
<PreviewDialog
:visible="previewDialogVisible"
@handleClose="handleClosePreviewDialog"
:videos="previewVideos"
/>
<el-image-viewer
v-if="imgViewerVisible"
:on-close="closeImgViewer"
:url-list="imgList"
/>
</div>
</template>
......@@ -53,14 +99,17 @@ import TableOperation from "@/components/Table/TableOperation.vue";
import { title, operates, operations } from "./config";
import { getList } from "@/api/display";
import InfoEditDialog from "./components/InfoEditDialog";
import PreviewDialog from "./components/PreviewDialog";
import SearchBar from "@/components/SearchBar";
export default {
components: {
TablePage,
TableOperation,
InfoEditDialog,
PreviewDialog,
SearchBar,
"el-image-viewer": () =>
import("element-ui/packages/image/src/image-viewer"),
},
data() {
return {
......@@ -96,28 +145,42 @@ export default {
],
},
],
drawerVisible: false,
editDialogVisible: false,
isAdd: true,
form: {
title: "", //标题
type: "", // 类别(待定)--枚举值(社会、生活等)
character: "", //展览性质(精品展、布展、文物展)--此处填写布展类别
displayCharacter: 1, //展览性质(精品展2、布展1、文物展3)--此处填写布展类别
keyword: "", // 关键词
deptId: "", //展览单位id--暂填入用户自己的单位
region: "", // 所在地域--暂填入用户自己的地区
regionCode: "", // 所在地域--暂填入用户自己的地区
intro: "", //展览介绍,
themeType: "", //模板主题--前端枚举
literature: "", //关联文献。id1,id2,id3--接口查询
remark: "", //备注
status: "", //上下架状态(0-下架,1-上架)
status: false, //上下架状态(0-下架,1-上架)
faceImage: "", // 封面(图片1张)
images: "", //展览图片
videos: "", //展览视频
audios: "", //展览音频
},
loading: false,
imgViewerVisible: false,
previewDialogVisible: false,
previewVideos: [],
displayTypes: {},
};
},
watch: {
dict(value) {
if (value) {
console.log("value.display_type", value.display_type);
value.display_type.map((item) => {
this.displayTypes[item.value] = item.label;
});
}
},
},
computed: {
tableTitle() {
return title;
......@@ -138,10 +201,32 @@ export default {
};
},
},
dicts: ["display_type"],
async created() {
// console.log("this.dict", this.dict);
// this.processDic();
},
mounted() {
this.loadData();
},
methods: {
async search(form) {
var params = {
page: this.list.current,
limit: this.list.size,
...form,
};
let res = await getList(params);
if (res.code == 0) {
this.list = res.data;
}
},
reset() {
this.loadData();
console.log("reset");
},
// 加载表格数据
async loadData() {
var params = {
......@@ -149,15 +234,22 @@ export default {
limit: this.list.size,
};
let res = await getList(params);
if (res.code == 0) {
console.log(res.data);
this.list = res.data;
}
},
handleOperation(value, row) {
console.log("handleOperation", value, row);
switch (value.type) {
case "add":
this.editDialogVisible = true;
this.form = {};
case "view":
break;
case "edit":
this.drawerVisible = true;
this.form = JSON.parse(JSON.stringify(row));
this.editDialogVisible = true;
break;
// case "delete":
// break;
......@@ -181,22 +273,36 @@ export default {
onSubmitSearch() {
console.log("submit!");
},
// 打开drawer
handleOpenDialog(type, value) {
this.drawerVisible = true;
switch (type) {
case "add":
console.log("新增");
break;
case "edit":
console.log("编辑", value);
break;
}
},
// 关闭Dialog
handleClose() {
this.drawerVisible = false;
this.editDialogVisible = false;
this.form={}
},
// 关闭预览图片
closeImgViewer() {
this.imgViewerVisible = false;
},
// 预览图片
handelPreviewImages(images) {
this.imgViewerVisible = true;
if (images.length > 1) {
this.imgList = images.split(",");
} else {
this.imgList = [images];
}
},
// 预览视频和音频
handelPreviewVideos(videos) {
this.previewDialogVisible = true;
if (videos.indexOf(",") != -1) {
this.previewVideos = videos.split(",");
} else {
this.previewVideos = [videos];
}
},
handleClosePreviewDialog() {
this.previewDialogVisible = false;
},
},
};
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论