提交 6e6de54a authored 作者: 王鹏飞's avatar 王鹏飞

feat: 新增知识日历

上级 53f9703c
...@@ -15,31 +15,31 @@ ...@@ -15,31 +15,31 @@
"dependencies": { "dependencies": {
"@element-plus/icons-vue": "^1.1.4", "@element-plus/icons-vue": "^1.1.4",
"@tinymce/tinymce-vue": "^5.0.0", "@tinymce/tinymce-vue": "^5.0.0",
"axios": "^0.27.1", "axios": "^0.27.2",
"blueimp-md5": "^2.19.0", "blueimp-md5": "^2.19.0",
"element-plus": "^2.1.11", "element-plus": "^2.2.0",
"pinia": "^2.0.13", "pinia": "^2.0.14",
"qs": "^6.10.3", "qs": "^6.10.3",
"sass": "^1.51.0", "sass": "^1.51.0",
"vue": "^3.2.33", "vue": "^3.2.33",
"vue-router": "^4.0.14" "vue-router": "^4.0.15"
}, },
"devDependencies": { "devDependencies": {
"@rushstack/eslint-patch": "^1.1.3", "@rushstack/eslint-patch": "^1.1.3",
"@types/blueimp-md5": "^2.18.0", "@types/blueimp-md5": "^2.18.0",
"@types/node": "^17.0.29", "@types/node": "^17.0.33",
"@types/qs": "^6.9.7", "@types/qs": "^6.9.7",
"@vitejs/plugin-vue": "^2.3.1", "@vitejs/plugin-vue": "^2.3.3",
"@vue/eslint-config-typescript": "^10.0.0", "@vue/eslint-config-typescript": "^10.0.0",
"@vue/tsconfig": "^0.1.3", "@vue/tsconfig": "^0.1.3",
"ali-oss": "^6.17.1", "ali-oss": "^6.17.1",
"chalk": "^5.0.1", "chalk": "^5.0.1",
"eslint": "^8.14.0", "eslint": "^8.14.0",
"eslint-plugin-vue": "^8.7.1", "eslint-plugin-vue": "^8.7.1",
"typescript": "~4.6.3", "typescript": "~4.6.4",
"unplugin-auto-import": "^0.7.1", "unplugin-auto-import": "^0.7.1",
"vite": "^2.9.6", "vite": "^2.9.9",
"vite-plugin-checker": "^0.4.6", "vite-plugin-checker": "^0.4.6",
"vue-tsc": "^0.34.10" "vue-tsc": "^0.34.13"
} }
} }
差异被折叠。
...@@ -6,7 +6,17 @@ export default { ...@@ -6,7 +6,17 @@ export default {
<script setup lang="ts"> <script setup lang="ts">
import type { Component } from 'vue' import type { Component } from 'vue'
import { User, Picture, Files, VideoCamera, Notebook, DishDot, QuestionFilled, Stamp } from '@element-plus/icons-vue' import {
User,
Picture,
Files,
VideoCamera,
Notebook,
DishDot,
QuestionFilled,
Stamp,
Calendar
} from '@element-plus/icons-vue'
const route = useRoute() const route = useRoute()
interface IMenuItem { interface IMenuItem {
name: string name: string
...@@ -23,7 +33,8 @@ const menuList: IMenuItem[] = [ ...@@ -23,7 +33,8 @@ const menuList: IMenuItem[] = [
{ name: '课程管理', path: '/course', icon: Notebook }, { name: '课程管理', path: '/course', icon: Notebook },
{ name: '团队管理', path: '/team', icon: DishDot }, { name: '团队管理', path: '/team', icon: DishDot },
{ name: '问答管理', path: '/qa', icon: QuestionFilled }, { name: '问答管理', path: '/qa', icon: QuestionFilled },
{ name: '审核管理', path: '/audit', icon: Stamp } { name: '审核管理', path: '/audit', icon: Stamp },
{ name: '知识日历', path: '/share', icon: Calendar }
] ]
const defaultActive = computed(() => { const defaultActive = computed(() => {
// 扁平菜单 // 扁平菜单
......
...@@ -50,7 +50,7 @@ function update() { ...@@ -50,7 +50,7 @@ function update() {
</el-form-item> </el-form-item>
</el-form> </el-form>
<template #footer> <template #footer>
<el-button type="text" @click="$emit('update:modelValue', false)">取消</el-button>&nbsp;&nbsp; <el-button text @click="$emit('update:modelValue', false)">取消</el-button>
<el-button type="primary" @click="onSubmit">保存</el-button> <el-button type="primary" @click="onSubmit">保存</el-button>
</template> </template>
</el-dialog> </el-dialog>
......
import httpRequest from '@/utils/axios'
// 获取资料消息列表
// 类型(1:入学指南,2:学习地图,3:考试攻略,4:消息)
export function getShareList(params?: { title?: string; page?: number; page_size?: number }) {
return httpRequest.get('/api/psp/backend/share/index', { params })
}
// 创建资料
export function createShare(data: { title: string; content: string[]; weight?: string }) {
return httpRequest.post('/api/psp/backend/share/create', data)
}
// 更新资料
export function updateShare(data: { id: string; title: string; content: string[]; weight?: string }) {
return httpRequest.post('/api/psp/backend/share/update', data)
}
// 获取资料详情
export function getShare(params: { id: string }) {
return httpRequest.get('/api/psp/backend/share/view', { params })
}
// 删除资料
export function deleteShare(data: { id: string }) {
return httpRequest.post('/api/psp/backend/share/delete', data)
}
import type { RouteRecordRaw } from 'vue-router'
import AppLayout from '@/components/layout/Index.vue'
export const routes: Array<RouteRecordRaw> = [
{
path: '/share',
component: AppLayout,
children: [
{ path: '', component: () => import('./views/List.vue') },
{ path: 'create', component: () => import('./views/Update.vue') },
{ path: 'update/:id', component: () => import('./views/Update.vue'), props: true }
]
}
]
<script setup lang="ts">
import { ElMessage, ElMessageBox } from 'element-plus'
import { getShareList, deleteShare } from '../api'
const appList = ref()
const listOptions = {
remote: {
httpRequest: getShareList,
params: { title: '' }
},
filters: [{ type: 'input', prop: 'title', placeholder: '标题' }],
columns: [
{ label: '标题', prop: 'title' },
{ label: '权重', prop: 'weight' },
{ label: '创建时间', prop: 'created_time' },
{ label: '操作', slots: 'table-operate', width: 160, align: 'right' }
]
}
const onRemove = (row: any) => {
ElMessageBox.confirm('确定要删除吗?', '提示').then(() => {
deleteShare({ id: row.id }).then(() => {
ElMessage({ type: 'success', message: '删除成功' })
appList.value?.refetch()
})
})
}
</script>
<template>
<AppCard>
<AppList v-bind="listOptions" ref="appList">
<template #header-aside>
<router-link to="/share/create">
<el-button type="primary">创建</el-button>
</router-link>
</template>
<template #table-cover="{ row }">
<el-image
:src="row.cover_page + '?x-oss-process=image/resize,m_fill,h_100,w_200'"
:preview-src-list="[row.cover_page]"
preview-teleported
lazy
fit="cover"
style="width: 200px; height: 100px"
/>
</template>
<template #table-operate="{ row }">
<el-space>
<router-link :to="`/share/update/${row.id}`">
<el-button plain>编辑</el-button>
</router-link>
<el-button type="danger" plain @click="onRemove(row)">删除</el-button>
</el-space>
</template>
</AppList>
</AppCard>
</template>
<script setup lang="ts">
import { ElMessage } from 'element-plus'
import type { FormInstance } from 'element-plus'
import { CirclePlus, Delete } from '@element-plus/icons-vue'
import { createShare, updateShare, getShare } from '../api'
const props = defineProps<{ id?: string }>()
const router = useRouter()
const formRef = ref<FormInstance>()
const form = reactive<{ title: string; content: string[]; weight: string }>({ title: '', content: [], weight: '0' })
const rules = {
title: [{ required: true, message: '请输入标题', trigger: 'blur' }]
}
// 提交
const onSubmit = () => {
if (!formRef.value) return
formRef.value.validate().then(() => {
props.id ? update() : create()
})
}
// 取消
const onCancel = () => {
router.replace('/share')
}
// 创建
const create = () => {
createShare(form).then(() => {
ElMessage({ message: '创建成功', type: 'success' })
router.push('/share')
})
}
// 修改
const update = () => {
const params = { ...form, id: props.id as string }
updateShare(params).then(() => {
ElMessage({ message: '修改成功', type: 'success' })
router.push('/share')
})
}
// 添加金句
const onAddText = () => {
form.content = [...form.content, '']
}
// 删除金句
const onRemoveText = (index: number) => {
form.content.splice(index, 1)
}
onMounted(() => {
props.id &&
getShare({ id: props.id }).then(res => {
Object.assign(form, res.data)
})
})
</script>
<template>
<AppCard>
<el-form ref="formRef" :model="form" :rules="rules" label-width="120px">
<el-form-item label="标题" prop="title">
<el-input v-model="form.title" />
</el-form-item>
<el-form-item label="权重" prop="weight">
<el-input type="number" v-model="form.weight" />
</el-form-item>
<el-form-item label="金句" prop="content">
<div class="text-wrapper">
<div class="text-item" v-for="(item, index) in form.content" :key="index">
<el-input type="textarea" v-model="form.content[index]" />
<el-button :icon="Delete" @click="onRemoveText(index)"></el-button>
</div>
<el-button :icon="CirclePlus" @click="onAddText">添加金句</el-button>
</div>
</el-form-item>
<el-form-item>
<el-button type="primary" auto-insert-space @click="onSubmit">保存</el-button>
<el-button auto-insert-space @click="onCancel">取消</el-button>
</el-form-item>
</el-form>
</AppCard>
</template>
<style lang="scss" scoped>
.text-wrapper {
width: 100%;
background-color: #f9f9f9;
padding: 10px;
border-radius: 8px;
}
.text-item {
display: flex;
align-items: center;
margin-bottom: 20px;
.el-button {
margin-left: 20px;
}
}
</style>
...@@ -15,7 +15,7 @@ const httpRequest = axios.create({ ...@@ -15,7 +15,7 @@ const httpRequest = axios.create({
httpRequest.interceptors.request.use( httpRequest.interceptors.request.use(
function (config) { function (config) {
if (config.headers?.['Content-Type'] === 'application/x-www-form-urlencoded') { if (config.headers?.['Content-Type'] === 'application/x-www-form-urlencoded') {
config.data = qs.stringify(config.data) config.data = qs.stringify(config.data, { skipNulls: true })
} }
if (config.headers?.['Content-Type'] === 'multipart/form-data') { if (config.headers?.['Content-Type'] === 'multipart/form-data') {
const formData = new window.FormData() const formData = new window.FormData()
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论