增加院士管理
This commit is contained in:
parent
7e7030a13e
commit
9c4c6e6572
|
|
@ -9,3 +9,5 @@ VITE_EDITOR = vscode
|
|||
// VITE_EDITOR = webstorm 如果使用webstorm开发且要使用dom定位到代码行功能 请先自定添加 webstorm到环境变量 再将VITE_EDITOR值修改为webstorm
|
||||
// 如果使用docker-compose开发模式,设置为下面的地址或本机主机IP
|
||||
//VITE_BASE_PATH = http://177.7.0.12
|
||||
|
||||
VITE_WWW_PATH = 'http://w1.zkzk.org.cn'
|
||||
|
|
|
|||
|
|
@ -5,3 +5,5 @@ VITE_BASE_API = /api
|
|||
VITE_FILE_API = /api
|
||||
#下方修改为你的线上ip(如果需要在线使用表单构建工具时使用,其余情况无需使用以下环境变量)
|
||||
VITE_BASE_PATH = ''
|
||||
|
||||
VITE_WWW_PATH = 'http://w1.zkzk.org.cn'
|
||||
|
|
|
|||
|
|
@ -0,0 +1,82 @@
|
|||
import service from '@/utils/request'
|
||||
|
||||
// @Summary 获取列表
|
||||
// @Produce application/json
|
||||
// @Router /cms/academician/getList [post]
|
||||
export const getAcademicianList = (data) => {
|
||||
return service({
|
||||
url: '/cms/academician/getList',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// @Summary 新增
|
||||
// @Produce application/json
|
||||
// @Param Object
|
||||
// @Router /cms/academician/add [post]
|
||||
export const addAcademician = (data) => {
|
||||
return service({
|
||||
url: '/cms/academician/add',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// @Summary 删除
|
||||
// @Produce application/json
|
||||
// @Param ID int
|
||||
// @Router /cms/academician/delete [delete]
|
||||
export const deleteAcademician = (data) => {
|
||||
return service({
|
||||
url: '/cms/academician/delete',
|
||||
method: 'delete',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// @Summary 批量删除
|
||||
// @Param data body request.IdsReq true "批量删除"
|
||||
// @Router /cms/academician/deleteByIds [delete]
|
||||
export const deleteAcademicianByIds = (params) => {
|
||||
return service({
|
||||
url: '/cms/academician/deleteByIds',
|
||||
method: 'delete',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
// @Summary 修改
|
||||
// @Produce application/json
|
||||
// @Param Object
|
||||
// @Router /cms/academician/update [put]
|
||||
export const updateAcademician = (data) => {
|
||||
return service({
|
||||
url: '/cms/academician/update',
|
||||
method: 'put',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// @Summary 根据id获取
|
||||
// @Param data body api.GetById true "根据id获取"
|
||||
// @Router /cms/academician/get [get]
|
||||
export const getAcademicianById = (params) => {
|
||||
return service({
|
||||
url: '/cms/academician/get',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
// @Summary 修改
|
||||
// @Produce application/json
|
||||
// @Param Object
|
||||
// @Router /cms/academician/setRel [put]
|
||||
export const setAcademicianRel = (data) => {
|
||||
return service({
|
||||
url: '/cms/academician/setRel',
|
||||
method: 'put',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
|
@ -699,3 +699,9 @@ li {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 16px;
|
||||
line-height: 1.2;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,3 +59,16 @@ export const ReturnArrImg = (arr) => {
|
|||
export const onDownloadFile = (url) => {
|
||||
window.open(path + url)
|
||||
}
|
||||
|
||||
const wwwPath = import.meta.env.VITE_WWW_PATH
|
||||
export const getArticlePreviewPath = (ID) => {
|
||||
return wwwPath + '/article/' + ID + '.html'
|
||||
}
|
||||
|
||||
export const getAcademicianPreviewPath = (ID) => {
|
||||
return wwwPath + '/academician/' + ID + '.html'
|
||||
}
|
||||
|
||||
export const getEntrepreneurPreviewPath = (ID) => {
|
||||
return wwwPath + '/entrepreneur/' + ID + '.html'
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,20 @@
|
|||
|
||||
export const articleTypeOptions = [
|
||||
{ key: 1, label: '图文' },
|
||||
{ key: 2, label: '视频' },
|
||||
]
|
||||
export const statusOptions = [
|
||||
{ key: 1, label: '草稿' },
|
||||
{ key: 2, label: '待审核' },
|
||||
{ key: 3, label: '待发布' },
|
||||
{ key: 4, label: '已发布' },
|
||||
{ key: 5, label: '已撤销' },
|
||||
]
|
||||
export const formatArticleType = (value) => {
|
||||
const rowLabel = articleTypeOptions.filter(item => item.key === value)
|
||||
return rowLabel && rowLabel[0] && rowLabel[0].label
|
||||
}
|
||||
export const formatStatus = (value) => {
|
||||
const rowLabel = statusOptions.filter(item => item.key === value)
|
||||
return rowLabel && rowLabel[0] && rowLabel[0].label
|
||||
}
|
||||
|
|
@ -94,9 +94,8 @@
|
|||
:title="`文件类型为:${uploadInfo.mediaTypeInfo}, 大小不超过${uploadInfo.fileSizeInfo}, 宽*高: ${uploadInfo.mediaWidth}px*${uploadInfo.mediaHeight}px`" />
|
||||
<div v-if="editForm.adType !== '' && editForm.adPositionId !== ''" class="flex flex-wrap gap-3">
|
||||
<el-upload class="avatar-uploader"
|
||||
:action="`${imgUploadPath}/cms/mediaFile/upload?noSave=0&category=ad_content_imgs`"
|
||||
:show-file-list="false" :on-success="uploadSuccess" :on-error="uploadFailure"
|
||||
:before-upload="beforeUpload">
|
||||
:action="`${imgUploadPath}/cms/mediaFile/upload?category=ad_content_imgs`" :show-file-list="false"
|
||||
:on-success="uploadSuccess" :on-error="uploadFailure" :before-upload="beforeUpload">
|
||||
<el-button type="primary" plain icon="upload">上传</el-button>
|
||||
</el-upload>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -56,9 +56,8 @@
|
|||
<el-input-number v-model="editForm.mediaHeight" autocomplete="off" style="width: 100%" />
|
||||
</el-form-item>
|
||||
<el-form-item label="位置示例图片" prop="imgUrl" style="width: 88%">
|
||||
<el-upload class="avatar-uploader"
|
||||
:action="`${imgUploadPath}/cms/mediaFile/upload?noSave=1&category=ad_pos_exa`" :show-file-list="false"
|
||||
:on-success="uploadSuccess" :on-error="uploadFailure" :before-upload="beforeUpload">
|
||||
<el-upload class="avatar-uploader" :action="`${imgUploadPath}/cms/mediaFile/upload?category=ad_pos_exa`"
|
||||
:show-file-list="false" :on-success="uploadSuccess" :on-error="uploadFailure" :before-upload="beforeUpload">
|
||||
<img v-if="editForm.imgUrl" :src="editForm.imgUrl" class="avatar" style="object-fit: cover;">
|
||||
<el-icon v-else class="avatar-uploader-icon">
|
||||
<Plus />
|
||||
|
|
|
|||
|
|
@ -0,0 +1,246 @@
|
|||
<template>
|
||||
<div>
|
||||
<div class="gva-search-box">
|
||||
<el-form ref="elSearchFormRef" :inline="true" :model="searchInfo" label-width="0" class="demo-form-inline"
|
||||
@keyup.enter="handleSubmitSearch">
|
||||
<el-form-item style="width:300px">
|
||||
<el-tooltip content="从名称中搜索" placement="top-start">
|
||||
<el-input v-model="searchInfo.keyword" class="keyword" placeholder="请输入关键词" clearable style="width:100%" />
|
||||
</el-tooltip>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="search" @click="handleSubmitSearch">查询</el-button>
|
||||
<el-button icon="refresh" @click="handleResetSearch">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<div class="gva-table-box">
|
||||
<div class="gva-btn-list">
|
||||
<el-button type="primary" icon="plus" @click="handleAdd">新增院士</el-button>
|
||||
<el-button icon="delete" style="margin-left: 10px;" :disabled="!multipleSelection.length"
|
||||
@click="handleMultiDelete">删除</el-button>
|
||||
</div>
|
||||
|
||||
<!-- 由于此处菜单跟左侧列表一一对应所以不需要分页 pageSize默认999 -->
|
||||
<el-table ref="multipleTable" :data="tableData" row-key="ID" @selection-change="handleSelectionChange">
|
||||
<el-table-column fixed type="selection" width="40" align="center" />
|
||||
<el-table-column align="left" label="ID" min-width="60" prop="ID" />
|
||||
<el-table-column align="left" label="头像" min-width="120" prop="avatar">
|
||||
<template #default="scope">
|
||||
<el-image v-if="scope.row.avatar" :src="scope.row.avatar" class="file" fit="cover"
|
||||
:preview-src-list="[scope.row.avatar]" preview-teleported hide-on-click-modal close-on-press-escape
|
||||
style="max-width: 70px; max-height: 90px" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="left" label="姓名/职称" min-width="120" prop="name">
|
||||
<template #default="scope">
|
||||
<el-link type="primary" :href="getAcademicianPreviewPath(scope.row.ID)" target="_blank">
|
||||
<el-text size="large" tag="b">{{ scope.row.name }}</el-text>
|
||||
</el-link>
|
||||
<div>{{ scope.row.title }}</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="left" label="简介" min-width="300" prop="brief" class-name="text-truncate">
|
||||
<template #default="scope">
|
||||
<el-text :line-clamp="3">{{ scope.row.brief }}</el-text>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="left" fixed="right" label="操作" width="200">
|
||||
<template #default="scope">
|
||||
<div>
|
||||
<el-button type="primary" link icon="edit" @click="handleRowEdit(scope.row.ID)">编辑</el-button>
|
||||
<el-button type="success" link icon="Guide" @click="handleSelProject(scope.row)">关联项目</el-button>
|
||||
</div>
|
||||
<div>
|
||||
<el-button type="danger" link icon="delete" @click="handleRowDelete(scope.row.ID)">删除</el-button>
|
||||
<el-button type="success" link icon="VideoPlay" @click="handleSelLecture(scope.row)">关联讲座</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="gva-pagination">
|
||||
<el-pagination layout="total, sizes, prev, pager, next, jumper" :current-page="page" :page-size="pageSize"
|
||||
:page-sizes="[10, 30, 50, 100]" :total="total" @current-change="handleCurrentChange"
|
||||
@size-change="handleSizeChange" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<AcademicianEdit ref="elEditRef" :title="editTitle" @on-save="handlerFormSave" />
|
||||
|
||||
<SelectArticle ref="elSelectArticleRef" :title="selectArticleTitle" @on-select="handleSelectArticle" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { getAcademicianPreviewPath } from '@/utils/format'
|
||||
import {
|
||||
getAcademicianList,
|
||||
deleteAcademician,
|
||||
deleteAcademicianByIds,
|
||||
setAcademicianRel,
|
||||
} from '@/api/academician'
|
||||
import AcademicianEdit from '@/view/content/components/academicianEdit.vue'
|
||||
import SelectArticle from '@/view/content/components/selectArticle.vue'
|
||||
|
||||
const page = ref(1)
|
||||
const total = ref(0)
|
||||
const pageSize = ref(10)
|
||||
const searchInfo = ref({})
|
||||
const tableData = ref([])
|
||||
const multipleSelection = ref([])// 多选数据
|
||||
const elSearchFormRef = ref()
|
||||
const elSelectArticleRef = ref()
|
||||
|
||||
const initSearchInfo = () => {
|
||||
searchInfo.value.keyword = ''
|
||||
page.value = 1
|
||||
}
|
||||
initSearchInfo()
|
||||
const getTableData = async valid => {
|
||||
const res = await getAcademicianList({ page: page.value, pageSize: pageSize.value, ...searchInfo.value })
|
||||
if (res.code === 0) {
|
||||
tableData.value = res.data.list
|
||||
total.value = res.data.total
|
||||
}
|
||||
}
|
||||
|
||||
getTableData()
|
||||
|
||||
// 重置
|
||||
const handleResetSearch = () => {
|
||||
initSearchInfo()
|
||||
getTableData()
|
||||
}
|
||||
// 搜索
|
||||
const handleSubmitSearch = () => {
|
||||
elSearchFormRef.value?.validate(async valid => {
|
||||
if (!valid) return
|
||||
getTableData()
|
||||
})
|
||||
}
|
||||
// 分页
|
||||
const handleSizeChange = (val) => {
|
||||
pageSize.value = val
|
||||
getTableData()
|
||||
}
|
||||
// 修改页面容量
|
||||
const handleCurrentChange = (val) => {
|
||||
page.value = val
|
||||
getTableData()
|
||||
}
|
||||
|
||||
// ------ 列表操作相关 -----
|
||||
// 多选
|
||||
const handleSelectionChange = (val) => {
|
||||
multipleSelection.value = val
|
||||
}
|
||||
// 批量删除
|
||||
const handleMultiDelete = () => {
|
||||
ElMessageBox.confirm('确定要删除所选内容吗?', '请确认', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(async valid => {
|
||||
const IDs = []
|
||||
if (multipleSelection.value.length === 0) {
|
||||
ElMessage({
|
||||
type: 'warning',
|
||||
message: '请选择要删除的数据'
|
||||
})
|
||||
return
|
||||
}
|
||||
multipleSelection.value &&
|
||||
multipleSelection.value.map(item => {
|
||||
IDs.push(item.ID)
|
||||
})
|
||||
const res = await deleteAcademicianByIds({ IDs })
|
||||
if (res.code === 0) {
|
||||
ElMessage({
|
||||
type: 'success',
|
||||
message: '删除成功'
|
||||
})
|
||||
if (tableData.value.length === IDs.length && page.value > 1) {
|
||||
page.value--
|
||||
}
|
||||
getTableData()
|
||||
}
|
||||
})
|
||||
}
|
||||
// 删除
|
||||
const handleRowDelete = (ID) => {
|
||||
ElMessageBox.confirm('此操作将删除院士, 是否继续?', '请确认', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(async valid => {
|
||||
const res = await deleteAcademician({ ID })
|
||||
if (res.code === 0) {
|
||||
ElMessage({
|
||||
type: 'success',
|
||||
message: '删除成功!'
|
||||
})
|
||||
if (tableData.value.length === 1 && page.value > 1) {
|
||||
page.value--
|
||||
}
|
||||
getTableData()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const elEditRef = ref(null)
|
||||
const editTitle = ref('')
|
||||
// 添加
|
||||
const handleAdd = () => {
|
||||
editTitle.value = '添加院士'
|
||||
elEditRef.value.openPage({ id: 0 })
|
||||
}
|
||||
// 修改
|
||||
const handleRowEdit = async (ID) => {
|
||||
editTitle.value = '修改院士-' + ID
|
||||
elEditRef.value.openPage({ ID: ID })
|
||||
}
|
||||
// 保存后
|
||||
const handlerFormSave = () => {
|
||||
getTableData()
|
||||
}
|
||||
|
||||
const selectArticleTitle = ref('')
|
||||
const handleSelProject = (row) => {
|
||||
selectArticleTitle.value = '关联院士项目'
|
||||
let articleIds = []
|
||||
if (row.projects != '') {
|
||||
articleIds = JSON.parse(row.projects)
|
||||
}
|
||||
const params = { kind: 'projects', ID: row.ID }
|
||||
elSelectArticleRef.value.openPage(params, articleIds)
|
||||
}
|
||||
const handleSelLecture = (row) => {
|
||||
selectArticleTitle.value = '关联院士讲座'
|
||||
let articleIds = []
|
||||
if (row.lectures != '') {
|
||||
articleIds = JSON.parse(row.lectures)
|
||||
}
|
||||
const params = { kind: 'lectures', ID: row.ID }
|
||||
elSelectArticleRef.value.openPage(params, articleIds)
|
||||
}
|
||||
const handleSelectArticle = async (params, rows) => {
|
||||
// 保存关联项目
|
||||
const articleIds = rows.map(item => item.ID)
|
||||
const res = await setAcademicianRel({ ...params, articleIds: articleIds })
|
||||
if (res && res.code === 0) {
|
||||
ElMessage({
|
||||
type: 'success',
|
||||
message: '更新成功!'
|
||||
})
|
||||
getTableData()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style type="scss">
|
||||
.admin-box .el-table td .cell {
|
||||
line-height: 28px;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -52,7 +52,7 @@
|
|||
<el-table-column align="left" label="标题/副标题" min-width="400" prop="title">
|
||||
<template #default="scope">
|
||||
<div>
|
||||
<el-link type="primary" :href="'http://w1.zkzk.org.cn/article/' + scope.row.ID + '.html'" target="_blank">
|
||||
<el-link type="primary" :href="getArticlePreviewPath(scope.row.ID)" target="_blank">
|
||||
<el-text :line-clamp="2"> {{ scope.row.title }}</el-text>
|
||||
</el-link>
|
||||
</div>
|
||||
|
|
@ -148,7 +148,7 @@
|
|||
<script setup>
|
||||
import { ref, watch, nextTick } from 'vue'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { formatDate } from '@/utils/format'
|
||||
import { formatDate, getArticlePreviewPath } from '@/utils/format'
|
||||
import { getCategoryTree } from '@/api/category'
|
||||
import { getChannelTree } from '@/api/channel'
|
||||
import { formatTimeToStr } from '@/utils/date'
|
||||
|
|
@ -166,6 +166,8 @@ import {
|
|||
} from '@/api/article'
|
||||
import ArticleEdit from '@/view/content/components/articleEdit.vue'
|
||||
import { useBtnAuth } from '@/utils/btnAuth'
|
||||
import { statusOptions, formatArticleType, formatStatus } from '@/utils/options'
|
||||
|
||||
const btnAuth = useBtnAuth()
|
||||
const articleEditTitle = ref('')
|
||||
const articleEditRef = ref(false)
|
||||
|
|
@ -178,27 +180,6 @@ const searchChannelId = ref('')
|
|||
const tableData = ref([])
|
||||
const multipleSelection = ref([])// 多选数据
|
||||
const elSearchFormRef = ref()
|
||||
const articleTypeOptions = ref([
|
||||
{ key: 1, label: '图文' },
|
||||
{ key: 2, label: '视频' },
|
||||
])
|
||||
const statusOptions = ref([
|
||||
{ key: 1, label: '草稿' },
|
||||
{ key: 2, label: '待审核' },
|
||||
{ key: 3, label: '待发布' },
|
||||
{ key: 4, label: '已发布' },
|
||||
{ key: 5, label: '已撤销' },
|
||||
])
|
||||
|
||||
const formatArticleType = (value) => {
|
||||
const rowLabel = articleTypeOptions.value.filter(item => item.key === value)
|
||||
return rowLabel && rowLabel[0] && rowLabel[0].label
|
||||
}
|
||||
|
||||
const formatStatus = (value) => {
|
||||
const rowLabel = statusOptions.value.filter(item => item.key === value)
|
||||
return rowLabel && rowLabel[0] && rowLabel[0].label
|
||||
}
|
||||
|
||||
const formatTags = (tags) => {
|
||||
return tags && tags.split(',')
|
||||
|
|
|
|||
|
|
@ -0,0 +1,350 @@
|
|||
<template>
|
||||
<el-drawer v-model="showDrawer" size="80%" :show-close="false" :close-on-click-modal="false"
|
||||
:close-on-press-escape="false">
|
||||
<template #header>
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="text-lg">{{ !isEdit ? '添加' : '修改' }}院士</span>
|
||||
<div>
|
||||
<el-button type="primary" @click="handleFormSubmit">确 定</el-button>
|
||||
<el-button @click="handleFormClose">取 消</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<div v-loading="fullscreenLoading">
|
||||
<div v-if="showErrMessage != ''">
|
||||
{{ showErrMessage }}
|
||||
</div>
|
||||
<el-form v-else ref="editFormRef" label-position="top" :model="editForm" :rules="rules">
|
||||
<el-row :gutter="0">
|
||||
<el-col :span="16">
|
||||
<el-row :gutter="10">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="姓名" prop="name" style="width: 100%">
|
||||
<el-input v-model="editForm.name" autocomplete="off" style="width: 100%" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="职称" prop="title" style="width: 100%">
|
||||
<el-input v-model="editForm.title" autocomplete="off" style="width: 100%" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-form-item label="简介" prop="brief">
|
||||
<el-input v-model="editForm.brief" type="textarea" rows="5" :show-word-limit="true" style="width: 100%"
|
||||
maxlength="300" autocomplete="off" resize="none" />
|
||||
</el-form-item>
|
||||
<el-form-item label="个人详细介绍" prop="description">
|
||||
<div v-if="showDrawer">
|
||||
<RichEdit v-model="editForm.description" media-category="academician_dsc_imgs" style="height: 30rem;" />
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="专家论文" prop="papers">
|
||||
<div v-if="showDrawer">
|
||||
<RichEdit v-model="editForm.papers" media-category="academician_papers" style="height: 20rem;" />
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="1" align="center">
|
||||
<el-divider direction="vertical" style="height: 100%" />
|
||||
</el-col>
|
||||
<el-col :span="7">
|
||||
<el-form-item label="头像" prop="avatar" style="width: 100%">
|
||||
<el-alert type="info" :closable="false" style="margin-bottom: 10px;"
|
||||
:description="`类型为:${avatarInfo.mediaTypeInfo}, 大小不超过${avatarInfo.fileSizeInfo}, 宽*高: ${avatarInfo.mediaWidth}px*${avatarInfo.mediaHeight}px`" />
|
||||
<el-upload class="avatar-uploader"
|
||||
:action="`${imgUploadPath}/cms/mediaFile/upload?category=academician_avatar`" :show-file-list="false"
|
||||
:on-success="(res) => { uploadSuccess(res, 'avatar') }" :on-error="uploadFailure"
|
||||
:before-upload="(file) => { return beforeUpload(file, avatarInfo) }">
|
||||
<img v-if="editForm.avatar" :src="editForm.avatar" class="avatar" style="object-fit: cover;">
|
||||
<el-icon v-else class="avatar-uploader-icon">
|
||||
<Plus />
|
||||
</el-icon>
|
||||
</el-upload>
|
||||
</el-form-item>
|
||||
<el-form-item label="介绍视频" prop="videoUrl" style="width: 100%">
|
||||
<el-alert type="info" :closable="false" style="margin-bottom: 10px;"
|
||||
:description="`类型为:${videoInfo.mediaTypeInfo}, 大小不超过${videoInfo.fileSizeInfo}, 宽*高: ${videoInfo.mediaWidth}px*${videoInfo.mediaHeight}px`" />
|
||||
<el-upload class="avatar-uploader"
|
||||
:action="`${imgUploadPath}/cms/mediaFile/upload?category=academician_video`" :show-file-list="false"
|
||||
:on-success="(res) => { uploadSuccess(res, 'video') }" :on-error="uploadFailure"
|
||||
:before-upload="(file) => { return beforeUpload(file, videoInfo) }">
|
||||
<el-button type="primary" plain icon="upload">上传</el-button>
|
||||
</el-upload>
|
||||
<video ref="videoRef" controls="controls" :width="300">
|
||||
<source src />
|
||||
</video>
|
||||
</el-form-item>
|
||||
<el-form-item label="企业二维码" prop="qrcodeUrl" style="width: 100%">
|
||||
<el-alert type="info" :closable="false" style="margin-bottom: 10px;"
|
||||
:title="`类型为:${qrcodeInfo.mediaTypeInfo}, 大小不超过${qrcodeInfo.fileSizeInfo}, 宽*高: ${qrcodeInfo.mediaWidth}px*${qrcodeInfo.mediaHeight}px`" />
|
||||
<el-upload class="avatar-uploader" style="width: 100px; height: 100px"
|
||||
:action="`${imgUploadPath}/cms/mediaFile/upload?category=academician_qrcode`" :show-file-list="false"
|
||||
:on-success="(res) => { uploadSuccess(res, 'qrcode') }" :on-error="uploadFailure"
|
||||
:before-upload="(file) => { return beforeUpload(file, qrcodeInfo) }">
|
||||
<img v-if="editForm.qrcodeUrl" :src="editForm.qrcodeUrl" class="avatar" style="object-fit: cover;">
|
||||
<el-icon v-else class="avatar-uploader-icon">
|
||||
<Plus />
|
||||
</el-icon>
|
||||
</el-upload>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
</div>
|
||||
</el-drawer>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import RichEdit from '@/components/richtext/rich-edit.vue'
|
||||
import { isImageMime, isVideoMime, isGifMime, checkImageWHEqual } from '@/utils/image'
|
||||
import {
|
||||
addAcademician,
|
||||
updateAcademician,
|
||||
getAcademicianById,
|
||||
} from '@/api/academician'
|
||||
|
||||
// 组件定义
|
||||
defineOptions({
|
||||
name: 'AcademicianEdit',
|
||||
})
|
||||
const emit = defineEmits(['on-save', 'on-close'])
|
||||
const props = defineProps({
|
||||
title: { type: String, default: '' }
|
||||
})
|
||||
|
||||
const showDrawer = ref(false)
|
||||
const showErrMessage = ref('')
|
||||
const fullscreenLoading = ref(true)
|
||||
|
||||
// ------ 以下为form表单相关 ------
|
||||
const editFormRef = ref(null)
|
||||
const editForm = ref({})
|
||||
const checkFlag = ref(false)
|
||||
const isEdit = ref(false)
|
||||
const rules = reactive({
|
||||
name: [
|
||||
{ required: true, message: '请输入姓名', trigger: 'blur' }
|
||||
],
|
||||
title: [
|
||||
{ required: true, message: '请输入职称', trigger: 'blur' }
|
||||
],
|
||||
brief: [
|
||||
{ required: true, message: '请输入简介', trigger: 'blur' }
|
||||
],
|
||||
avatar: [
|
||||
{ required: true, message: '请选择头像', trigger: 'blur' },
|
||||
],
|
||||
})
|
||||
// 初始化弹窗内表格方法
|
||||
const emptyForm = () => {
|
||||
checkFlag.value = false
|
||||
editForm.value = {
|
||||
ID: 0,
|
||||
name: '',
|
||||
title: '',
|
||||
avatar: '',
|
||||
brief: '',
|
||||
description: '',
|
||||
videoUrl: '',
|
||||
qrcodeUrl: '',
|
||||
papers: '',
|
||||
projects: '',
|
||||
lectures: '',
|
||||
}
|
||||
}
|
||||
// 关闭弹窗
|
||||
const handleFormClose = () => {
|
||||
showDrawer.value = false
|
||||
emit('on-close')
|
||||
}
|
||||
|
||||
// 提交表单
|
||||
const handleFormSubmit = async () => {
|
||||
editFormRef.value.validate(async valid => {
|
||||
if (!valid) {
|
||||
return
|
||||
}
|
||||
let res
|
||||
if (isEdit.value) {
|
||||
res = await updateAcademician(editForm.value)
|
||||
} else {
|
||||
res = await addAcademician(editForm.value)
|
||||
}
|
||||
if (res.code === 0) {
|
||||
ElMessage({
|
||||
type: 'success',
|
||||
message: isEdit.value ? '编辑成功' : '添加成功!'
|
||||
})
|
||||
showDrawer.value = false
|
||||
emit('on-save')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// ----- 以下为图片操作 -----
|
||||
const avatarInfo = {
|
||||
mediaType: 'pic',
|
||||
mediaTypeInfo: 'jpg,png,webp,svg',
|
||||
fileSize: 500,
|
||||
fileSizeInfo: '500K',
|
||||
mediaWidth: 180,
|
||||
mediaHeight: 235,
|
||||
}
|
||||
const videoInfo = {
|
||||
mediaType: 'video',
|
||||
mediaTypeInfo: 'mp4,webm',
|
||||
fileSize: 5000,
|
||||
fileSizeInfo: '5M',
|
||||
mediaWidth: 214,
|
||||
mediaHeight: 380,
|
||||
}
|
||||
const qrcodeInfo = {
|
||||
mediaType: 'pic',
|
||||
mediaTypeInfo: 'jpg,png,webp,svg',
|
||||
fileSize: 500,
|
||||
fileSizeInfo: '500K',
|
||||
mediaWidth: 120,
|
||||
mediaHeight: 120,
|
||||
}
|
||||
const videoRef = ref(null)
|
||||
const imgUploadPath = import.meta.env.VITE_BASE_API
|
||||
const beforeUpload = (file, info) => {
|
||||
const isLtSize = file.size / 1024 < info.fileSize
|
||||
const isVideo = isVideoMime(file.type)
|
||||
const isImage = isImageMime(file.type)
|
||||
const isGif = isGifMime(file.type)
|
||||
if (info.mediaType === 'pic' && !isImage) {
|
||||
ElMessage.error('上传文件只能是 ' + info.mediaTypeInfo + ' 格式')
|
||||
return false
|
||||
}
|
||||
if (info.mediaType === 'video' && !isVideo) {
|
||||
ElMessage.error('上传文件只能是 ' + info.mediaTypeInfo + ' 格式')
|
||||
return false
|
||||
}
|
||||
if (info.mediaType === 'gif' && !isGif) {
|
||||
ElMessage.error('上传文件只能是 ' + info.mediaTypeInfo + ' 格式')
|
||||
return false
|
||||
}
|
||||
if (!isLtSize) {
|
||||
ElMessage.error('上传文件大小不能超过 ' + info.fileSizeInfo)
|
||||
return false
|
||||
}
|
||||
|
||||
if (info.mediaType === 'pic') {
|
||||
const isSize = checkImageWHEqual(
|
||||
file, info.mediaWidth, info.mediaHeight
|
||||
).then(
|
||||
() => {
|
||||
return file
|
||||
},
|
||||
() => {
|
||||
ElMessage.error('上传文件宽*高必须为: ' + info.mediaWidth + 'px*' + info.mediaHeight + 'px')
|
||||
return Promise.reject()
|
||||
})
|
||||
return isSize
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
const uploadSuccess = (res, field) => {
|
||||
const { code, data, msg } = res
|
||||
if (code !== 0) {
|
||||
ElMessage({ type: 'error', message: msg })
|
||||
return
|
||||
}
|
||||
if (!data.mediaFile) {
|
||||
ElMessage({ type: 'error', message: '返回错误,上传失败' })
|
||||
return
|
||||
}
|
||||
if (field === 'avatar') {
|
||||
editForm.value.avatar = data.mediaFile.url
|
||||
} else if (field === 'video') {
|
||||
editForm.value.videUrl = data.mediaFile.url
|
||||
videoRef.value.src = data.mediaFile.url
|
||||
} else if (field === 'qrcode') {
|
||||
editForm.value.qrcodeUrl = data.mediaFile.url
|
||||
}
|
||||
}
|
||||
|
||||
const uploadFailure = () => {
|
||||
ElMessage({
|
||||
type: 'error',
|
||||
message: '上传失败'
|
||||
})
|
||||
}
|
||||
|
||||
// 初始化方法
|
||||
const openPage = async (params) => {
|
||||
fullscreenLoading.value = true
|
||||
showDrawer.value = true
|
||||
isEdit.value = false
|
||||
emptyForm()
|
||||
|
||||
// 建议通过url传参获取目标数据ID 调用 find方法进行查询数据操作 从而决定本页面是create还是update 以下为id作为url参数示例
|
||||
if (params.ID && params.ID > 0) {
|
||||
// 编辑
|
||||
isEdit.value = true
|
||||
initFormById(params.ID)
|
||||
} else {
|
||||
// 新建
|
||||
fullscreenLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const initFormById = async (ID) => {
|
||||
const res = await getAcademicianById({ ID: ID })
|
||||
if (res.code === 0) {
|
||||
// 初始化表单数据
|
||||
editForm.value = res.data.academician
|
||||
fullscreenLoading.value = false
|
||||
} else {
|
||||
ElMessage({
|
||||
type: 'error',
|
||||
message: '获取数据失败'
|
||||
})
|
||||
showErrMessage.value = '获取数据失败'
|
||||
}
|
||||
fullscreenLoading.value = false
|
||||
}
|
||||
|
||||
// 对外暴露方法
|
||||
defineExpose({ openPage })
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.avatar-uploader .avatar {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style>
|
||||
.avatar-uploader .el-upload {
|
||||
border: 1px solid var(--el-border-color);
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
transition: var(--el-transition-duration-fast);
|
||||
}
|
||||
|
||||
.avatar-uploader .el-upload:hover {
|
||||
border-color: var(--el-color-primary);
|
||||
}
|
||||
|
||||
.el-icon.avatar-uploader-icon {
|
||||
font-size: 28px;
|
||||
color: #8c939d;
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.el-form-item__content .el-alert__description {
|
||||
line-height: 22px;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -155,6 +155,7 @@ import {
|
|||
} from '@/api/article'
|
||||
import { importFetcherArticleById } from '@/api/fetcher'
|
||||
import { isUrl } from '@/utils/validator'
|
||||
import { articleTypeOptions } from '@/utils/options'
|
||||
|
||||
// 组件定义
|
||||
defineOptions({
|
||||
|
|
@ -208,10 +209,7 @@ const formRules = reactive({
|
|||
{ validator: isUrl, message: '请输入正确的跳转地址', trigger: 'blur' }
|
||||
]
|
||||
})
|
||||
const articleTypeOptions = ref([
|
||||
{ key: 1, label: '图文' },
|
||||
{ key: 2, label: '视频' },
|
||||
])
|
||||
|
||||
const editForm = ref({
|
||||
ID: 0,
|
||||
articleType: '',
|
||||
|
|
|
|||
|
|
@ -54,9 +54,9 @@
|
|||
<el-alert type="info" :closable="false" style="margin-bottom: 10px;"
|
||||
:description="`类型为:${avatarInfo.mediaTypeInfo}, 大小不超过${avatarInfo.fileSizeInfo}, 宽*高: ${avatarInfo.mediaWidth}px*${avatarInfo.mediaHeight}px`" />
|
||||
<el-upload class="avatar-uploader"
|
||||
:action="`${imgUploadPath}/cms/mediaFile/upload?noSave=1&category=entrepreneur_avatar`"
|
||||
:show-file-list="false" :on-success="(res) => { uploadSuccess(res, 'avatar') }"
|
||||
:on-error="uploadFailure" :before-upload="(file) => { return beforeUpload(file, avatarInfo) }">
|
||||
:action="`${imgUploadPath}/cms/mediaFile/upload?category=entrepreneur_avatar`" :show-file-list="false"
|
||||
:on-success="(res) => { uploadSuccess(res, 'avatar') }" :on-error="uploadFailure"
|
||||
:before-upload="(file) => { return beforeUpload(file, avatarInfo) }">
|
||||
<img v-if="editForm.avatar" :src="editForm.avatar" class="avatar" style="object-fit: cover;">
|
||||
<el-icon v-else class="avatar-uploader-icon">
|
||||
<Plus />
|
||||
|
|
@ -67,8 +67,8 @@
|
|||
<el-alert type="info" :closable="false" style="margin-bottom: 10px;"
|
||||
:description="`类型为:${videoInfo.mediaTypeInfo}, 大小不超过${videoInfo.fileSizeInfo}, 宽*高: ${videoInfo.mediaWidth}px*${videoInfo.mediaHeight}px`" />
|
||||
<el-upload class="avatar-uploader"
|
||||
:action="`${imgUploadPath}/cms/mediaFile/upload?noSave=1&category=entrepreneur_video`"
|
||||
:show-file-list="false" :on-success="(res) => { uploadSuccess(res, 'video') }" :on-error="uploadFailure"
|
||||
:action="`${imgUploadPath}/cms/mediaFile/upload?category=entrepreneur_video`" :show-file-list="false"
|
||||
:on-success="(res) => { uploadSuccess(res, 'video') }" :on-error="uploadFailure"
|
||||
:before-upload="(file) => { return beforeUpload(file, videoInfo) }">
|
||||
<el-button type="primary" plain icon="upload">上传</el-button>
|
||||
</el-upload>
|
||||
|
|
@ -80,9 +80,9 @@
|
|||
<el-alert type="info" :closable="false" style="margin-bottom: 10px;"
|
||||
:title="`类型为:${qrcodeInfo.mediaTypeInfo}, 大小不超过${qrcodeInfo.fileSizeInfo}, 宽*高: ${qrcodeInfo.mediaWidth}px*${qrcodeInfo.mediaHeight}px`" />
|
||||
<el-upload class="avatar-uploader" style="width: 100px; height: 100px"
|
||||
:action="`${imgUploadPath}/cms/mediaFile/upload?noSave=1&category=entrepreneur_avatar`"
|
||||
:show-file-list="false" :on-success="(res) => { uploadSuccess(res, 'qrcode') }"
|
||||
:on-error="uploadFailure" :before-upload="(file) => { return beforeUpload(file, qrcodeInfo) }">
|
||||
:action="`${imgUploadPath}/cms/mediaFile/upload?category=entrepreneur_qrcode`" :show-file-list="false"
|
||||
:on-success="(res) => { uploadSuccess(res, 'qrcode') }" :on-error="uploadFailure"
|
||||
:before-upload="(file) => { return beforeUpload(file, qrcodeInfo) }">
|
||||
<img v-if="editForm.qrcodeUrl" :src="editForm.qrcodeUrl" class="avatar" style="object-fit: cover;">
|
||||
<el-icon v-else class="avatar-uploader-icon">
|
||||
<Plus />
|
||||
|
|
@ -109,7 +109,7 @@ import {
|
|||
|
||||
// 组件定义
|
||||
defineOptions({
|
||||
name: 'ArticleEdit',
|
||||
name: 'EntrepreneurEdit',
|
||||
})
|
||||
const emit = defineEmits(['on-save', 'on-close'])
|
||||
const props = defineProps({
|
||||
|
|
@ -144,12 +144,14 @@ const emptyForm = () => {
|
|||
checkFlag.value = false
|
||||
editForm.value = {
|
||||
ID: 0,
|
||||
adType: '',
|
||||
adPositionId: '',
|
||||
url: '',
|
||||
validStart: '',
|
||||
validEnd: '',
|
||||
mediaUrl: '',
|
||||
name: '',
|
||||
enterprise: '',
|
||||
avatar: '',
|
||||
brief: '',
|
||||
description: '',
|
||||
enterpriseDsc: '',
|
||||
videoUrl: '',
|
||||
qrcodeUrl: '',
|
||||
}
|
||||
}
|
||||
// 关闭弹窗
|
||||
|
|
@ -187,24 +189,24 @@ const avatarInfo = {
|
|||
mediaTypeInfo: 'jpg,png,webp,svg',
|
||||
fileSize: 500,
|
||||
fileSizeInfo: '500K',
|
||||
mediaWidth: 280,
|
||||
mediaHeight: 360,
|
||||
mediaWidth: 180,
|
||||
mediaHeight: 270,
|
||||
}
|
||||
const videoInfo = {
|
||||
mediaType: 'video',
|
||||
mediaTypeInfo: 'mp4,webm',
|
||||
fileSize: 5000,
|
||||
fileSizeInfo: '5M',
|
||||
mediaWidth: 300,
|
||||
mediaHeight: 180,
|
||||
mediaWidth: 214,
|
||||
mediaHeight: 380,
|
||||
}
|
||||
const qrcodeInfo = {
|
||||
mediaType: 'pic',
|
||||
mediaTypeInfo: 'jpg,png,webp,svg',
|
||||
fileSize: 500,
|
||||
fileSizeInfo: '500K',
|
||||
mediaWidth: 300,
|
||||
mediaHeight: 300,
|
||||
mediaWidth: 120,
|
||||
mediaHeight: 120,
|
||||
}
|
||||
const videoRef = ref(null)
|
||||
const imgUploadPath = import.meta.env.VITE_BASE_API
|
||||
|
|
@ -341,4 +343,8 @@ defineExpose({ openPage })
|
|||
height: 150px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.el-form-item__content .el-alert__description {
|
||||
line-height: 22px;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,236 @@
|
|||
<template>
|
||||
<el-drawer v-model="showDrawer" size="1000" :show-close="false" :close-on-click-modal="false"
|
||||
:close-on-press-escape="false" style="background: #f8f8f8">
|
||||
<template #header>
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="text-lg">{{ props.title }}</span>
|
||||
<div>
|
||||
<el-button type="primary" @click="handleSubmitDialog">确 定</el-button>
|
||||
<el-button @click="handleCloseDialog">取 消</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<div v-loading="fullscreenLoading">
|
||||
<div v-if="showErrMessage != ''">
|
||||
{{ showErrMessage }}
|
||||
</div>
|
||||
<div v-else>
|
||||
<div class="gva-search-box">
|
||||
<div class="section-title">已选择的</div>
|
||||
|
||||
<el-table ref="selectedTableRef" :data="selectedData" row-key="ID">
|
||||
<el-table-column align="left" fixed="left" label="ID" min-width="40" prop="ID" />
|
||||
<el-table-column align="left" label="标题/副标题" min-width="360" prop="title">
|
||||
<template #default="scope">
|
||||
<div>
|
||||
<el-link type="primary" :href="getArticlePreviewPath(scope.row.ID)" target="_blank">
|
||||
<el-text :line-clamp="2"> {{ scope.row.title }}</el-text>
|
||||
</el-link>
|
||||
</div>
|
||||
<el-text :line-clamp="2" size="small">{{ scope.row.subtitle }}</el-text>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="left" label="类型" min-width="80" prop="articleType">
|
||||
<template #default="scope">{{ formatArticleType(scope.row.articleType) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="left" label="状态" width="80">
|
||||
<template #default="scope">{{ formatStatus(scope.row.status) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="left" fixed="right" label="操作" width="80">
|
||||
<template #default="scope">
|
||||
<el-button type="danger" link icon="bottom" @click="handleRowRemove(scope.row)">移除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div><br /></div>
|
||||
</div>
|
||||
|
||||
<div class="gva-search-box" style="margin-top: 10px">
|
||||
<div class="section-title">待选择的</div>
|
||||
<el-form ref="elSearchFormRef" :inline="true" :model="searchInfo" label-width="0"
|
||||
@keyup.enter="handleSubmitSearch">
|
||||
<el-form-item prop="createdAt" style="width:260px">
|
||||
<el-tooltip content="搜索范围是创建开始日期(包含)至创建结束日期(包含)" placement="top-start">
|
||||
<el-icon>
|
||||
<QuestionFilled />
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
<el-date-picker v-model="searchInfo.dateRange" type="daterange" value-format="YYYY-MM-DD"
|
||||
:clearable="false" :editable="false" />
|
||||
</el-form-item>
|
||||
<el-form-item style="width:200px">
|
||||
<el-tooltip content="从标题、副标题、摘要中搜索" placement="top-start">
|
||||
<el-input v-model="searchInfo.keyword" class="keyword" placeholder="请输入关键词" clearable
|
||||
style="width:100%" />
|
||||
</el-tooltip>
|
||||
</el-form-item>
|
||||
<el-form-item label="" prop="status" style="width:120px">
|
||||
<el-select v-model="searchInfo.status" placeholder="请选择状态" clearable style="width:300px">
|
||||
<el-option v-for="item in statusOptions" :key="item.key" :label="item.label" :value="item.key" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="search" @click="handleSubmitSearch">查询</el-button>
|
||||
<el-button icon="refresh" @click="handleResetSearch">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<el-table ref="multipleTableRef" :data="tableData" row-key="ID">
|
||||
<el-table-column align="left" label="ID" min-width="60" prop="ID" />
|
||||
<el-table-column align="left" label="标题/副标题" min-width="400" prop="title">
|
||||
<template #default="scope">
|
||||
<div>
|
||||
<el-link type="primary" :href="getArticlePreviewPath(scope.row.ID)" target="_blank">
|
||||
<el-text :line-clamp="2"> {{ scope.row.title }}</el-text>
|
||||
</el-link>
|
||||
</div>
|
||||
<el-text :line-clamp="2" size="small">{{ scope.row.subtitle }}</el-text>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="left" label="类型" min-width="80" prop="articleType">
|
||||
<template #default="scope">{{ formatArticleType(scope.row.articleType) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="left" label="状态" width="80">
|
||||
<template #default="scope">{{ formatStatus(scope.row.status) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="left" fixed="right" label="操作" width="80">
|
||||
<template #default="scope">
|
||||
<el-button type="primary" link icon="top" @click="handleRowSelect(scope.row)">选择</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<div class="gva-pagination">
|
||||
<el-pagination layout="total, sizes, prev, pager, next, jumper" :current-page="page" :page-size="pageSize"
|
||||
:page-sizes="[10, 30, 50, 100]" :total="total" @current-change="handleCurrentChange"
|
||||
@size-change="handleSizeChange" />
|
||||
</div>
|
||||
<div><br /></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-drawer>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { getArticlePreviewPath } from '@/utils/format'
|
||||
import { getArticleList } from '@/api/article'
|
||||
import { statusOptions, formatArticleType, formatStatus } from '@/utils/options'
|
||||
import { getCategoryTree } from '@/api/category'
|
||||
import { getChannelTree } from '@/api/channel'
|
||||
import { formatTimeToStr } from '@/utils/date'
|
||||
|
||||
// 组件定义
|
||||
defineOptions({
|
||||
name: 'SelectArticle',
|
||||
})
|
||||
const emit = defineEmits(['on-select', 'on-close'])
|
||||
const props = defineProps({
|
||||
title: { type: String, default: '选择文章' }
|
||||
})
|
||||
|
||||
const showDrawer = ref(false)
|
||||
const showErrMessage = ref('')
|
||||
const fullscreenLoading = ref(true)
|
||||
|
||||
const page = ref(1)
|
||||
const total = ref(0)
|
||||
const pageSize = ref(10)
|
||||
const searchInfo = ref({})
|
||||
const tableData = ref([])
|
||||
const elSearchFormRef = ref()
|
||||
|
||||
const initSearchInfo = () => {
|
||||
const endDate = new Date()
|
||||
const startDate = new Date(endDate.getTime() - 30 * 24 * 60 * 60 * 1000)
|
||||
|
||||
searchInfo.value.keyword = ''
|
||||
searchInfo.value.dateRange = [
|
||||
formatTimeToStr(startDate, 'yyyy-MM-dd'),
|
||||
formatTimeToStr(endDate, 'yyyy-MM-dd'),
|
||||
]
|
||||
page.value = 1
|
||||
}
|
||||
|
||||
const getTableData = async () => {
|
||||
const excludeIds = selectedData.value.map(item => item.ID)
|
||||
const res = await getArticleList({ page: page.value, pageSize: pageSize.value, excludeIds, ...searchInfo.value })
|
||||
if (res.code === 0) {
|
||||
tableData.value = res.data.list
|
||||
total.value = res.data.total
|
||||
}
|
||||
}
|
||||
|
||||
// 重置
|
||||
const handleResetSearch = () => {
|
||||
initSearchInfo()
|
||||
getTableData()
|
||||
}
|
||||
// 搜索
|
||||
const handleSubmitSearch = () => {
|
||||
elSearchFormRef.value?.validate(async valid => {
|
||||
if (!valid) return
|
||||
getTableData()
|
||||
})
|
||||
}
|
||||
// 分页
|
||||
const handleSizeChange = (val) => {
|
||||
pageSize.value = val
|
||||
getTableData()
|
||||
}
|
||||
// 修改页面容量
|
||||
const handleCurrentChange = (val) => {
|
||||
page.value = val
|
||||
getTableData()
|
||||
}
|
||||
|
||||
// ------ 列表操作相关 -----
|
||||
const handleRowSelect = (row) => {
|
||||
selectedData.value.push(row)
|
||||
getTableData()
|
||||
}
|
||||
|
||||
const handleRowRemove = (row) => {
|
||||
selectedData.value = selectedData.value.filter(item => item.ID != row.ID)
|
||||
getTableData()
|
||||
}
|
||||
|
||||
// 关闭弹窗
|
||||
const handleCloseDialog = () => {
|
||||
showDrawer.value = false
|
||||
emit('on-close')
|
||||
}
|
||||
|
||||
// 提交表单
|
||||
const handleSubmitDialog = async () => {
|
||||
emit('on-select', transParams.value, selectedData.value)
|
||||
showDrawer.value = false
|
||||
}
|
||||
|
||||
// 初始化方法
|
||||
const selectedData = ref([])
|
||||
const transParams = ref(null) // 用于透传给调用方
|
||||
const openPage = async (params, includeIds) => {
|
||||
fullscreenLoading.value = true
|
||||
transParams.value = params
|
||||
selectedData.value = []
|
||||
|
||||
if (includeIds && includeIds.length > 0) {
|
||||
const res = await getArticleList({ includeIds })
|
||||
if (res && res.code === 0) {
|
||||
selectedData.value = res.data.list
|
||||
}
|
||||
console.log(res.data.list)
|
||||
}
|
||||
|
||||
initSearchInfo()
|
||||
getTableData()
|
||||
showDrawer.value = true
|
||||
fullscreenLoading.value = false
|
||||
}
|
||||
|
||||
// 对外暴露方法
|
||||
defineExpose({ openPage })
|
||||
</script>
|
||||
|
|
@ -29,13 +29,12 @@
|
|||
<template #default="scope">
|
||||
<el-image v-if="scope.row.avatar" :src="scope.row.avatar" class="file" fit="cover"
|
||||
:preview-src-list="[scope.row.avatar]" preview-teleported hide-on-click-modal close-on-press-escape
|
||||
style="width: 70px; height: 90px" />
|
||||
style="max-width: 70px; max-height: 90px" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="left" label="姓名/企业" min-width="120" prop="name">
|
||||
<template #default="scope">
|
||||
<el-link type="primary" :href="'http://w1.zkzk.org.cn/entrepreneur/' + scope.row.ID + '.html'"
|
||||
target="_blank">
|
||||
<el-link type="primary" :href="getEntrepreneurPreviewPath(scope.row.ID)" target="_blank">
|
||||
<el-text size="large" tag="b">{{ scope.row.name }}</el-text>
|
||||
</el-link>
|
||||
<div>{{ scope.row.enterprise }}</div>
|
||||
|
|
@ -67,6 +66,7 @@
|
|||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { getEntrepreneurPreviewPath } from '@/utils/format'
|
||||
import {
|
||||
getEntrepreneurList,
|
||||
deleteEntrepreneur,
|
||||
|
|
|
|||
Loading…
Reference in New Issue