feat(goods): 新增文章编辑功能并优化列表页面
- 新增文章编辑页面,支持添加和编辑文章 - 优化文章列表页面,增加详情对话框和删除功能 - 更新相关 API 接口,支持文章添加和编辑- 调整用户列表页面布局 - 移除底部边框样式
This commit is contained in:
parent
480f1e02ed
commit
e6ceacfae1
@ -15,21 +15,21 @@ export const list = (params) => {
|
|||||||
|
|
||||||
export const add = (data) => {
|
export const add = (data) => {
|
||||||
return service({
|
return service({
|
||||||
url: '/article/list',
|
url: '/article',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data
|
data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
export const edit = (data) => {
|
export const edit = (data) => {
|
||||||
return service({
|
return service({
|
||||||
url: '/article/list',
|
url: '/article',
|
||||||
method: 'put',
|
method: 'put',
|
||||||
data
|
data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
export const del = (data) => {
|
export const del = (data) => {
|
||||||
return service({
|
return service({
|
||||||
url: '/article/list',
|
url: '/article',
|
||||||
method: 'delete',
|
method: 'delete',
|
||||||
data
|
data
|
||||||
})
|
})
|
||||||
|
@ -64,5 +64,5 @@
|
|||||||
padding: 1rem 0;
|
padding: 1rem 0;
|
||||||
position: sticky;
|
position: sticky;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
border-top: 1px solid #ededed;
|
//border-top: 1px solid #ededed;
|
||||||
}
|
}
|
||||||
|
@ -24,16 +24,7 @@
|
|||||||
<el-row :gutter="20">
|
<el-row :gutter="20">
|
||||||
<el-col :span="8">
|
<el-col :span="8">
|
||||||
<el-form-item label="图片" prop="coverImg">
|
<el-form-item label="图片" prop="coverImg">
|
||||||
<el-upload
|
<SelectImage v-model="formData.coverImg" />
|
||||||
class="avatar-uploader"
|
|
||||||
action="https://run.mocky.io/v3/9d059bf9-4660-45f2-925d-ce80ad6c4d15"
|
|
||||||
:show-file-list="false"
|
|
||||||
:on-success="handleAvatarSuccess"
|
|
||||||
:before-upload="beforeAvatarUpload"
|
|
||||||
>
|
|
||||||
<img v-if="formData.coverImg" :src="formData.coverImg" class="avatar" alt=""/>
|
|
||||||
<el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>
|
|
||||||
</el-upload>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="8">
|
<el-col :span="8">
|
||||||
@ -46,7 +37,7 @@
|
|||||||
<el-row :gutter="20">
|
<el-row :gutter="20">
|
||||||
<el-col :span="20">
|
<el-col :span="20">
|
||||||
<el-form-item label="详情" prop="content">
|
<el-form-item label="详情" prop="content">
|
||||||
<RichEdit v-model="formData.content"/>
|
<RichEdit style="width: 100%" v-model="formData.content"/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
@ -63,7 +54,7 @@
|
|||||||
</el-form>
|
</el-form>
|
||||||
<div class="gva-table-box footer-box">
|
<div class="gva-table-box footer-box">
|
||||||
<el-button @click="$router.back()">返回</el-button>
|
<el-button @click="$router.back()">返回</el-button>
|
||||||
<el-button type="primary" @click="submit">提交</el-button>
|
<el-button type="primary" @click="submit(ruleFormRef)">提交</el-button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
@ -76,28 +67,42 @@
|
|||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<script setup>
|
<script setup>
|
||||||
|
import SelectImage from '@/components/selectImage/selectImage.vue'
|
||||||
import {onMounted, ref } from 'vue'
|
import {onMounted, ref } from 'vue'
|
||||||
import userChoose from '@/components/userChoose/index.vue'
|
import userChoose from '@/components/userChoose/index.vue'
|
||||||
import { useRouter, useRoute} from 'vue-router'
|
import { useRouter, useRoute} from 'vue-router'
|
||||||
import {detail} from '@/api/goods/index.js'
|
import { add, detail, edit } from '@/api/goods/index.js'
|
||||||
import ColumnItem from '@/components/columnItem/ColumnItem.vue'
|
import ColumnItem from '@/components/columnItem/ColumnItem.vue'
|
||||||
import { ElMessage } from 'element-plus'
|
import { ElMessage } from 'element-plus'
|
||||||
import { Plus } from '@element-plus/icons-vue'
|
|
||||||
import RichEdit from '@/components/richtext/rich-edit.vue'
|
import RichEdit from '@/components/richtext/rich-edit.vue'
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const userDialogRef = ref()
|
const userDialogRef = ref()
|
||||||
|
const isEdit = ref(false)
|
||||||
|
|
||||||
const ruleFormRef = ref(null), formData = ref({}), rules = ref({
|
const ruleFormRef = ref(null), formData = ref({}), rules = ref({
|
||||||
title: [
|
title: [
|
||||||
{ required: true, message: '请输入文章标题', trigger: 'blur' }
|
{ required: true, message: '请输入文章标题', trigger: 'blur' }
|
||||||
],
|
],
|
||||||
|
price: [
|
||||||
|
{ required: true, message: '请输入价格', trigger: 'blur' }
|
||||||
|
],
|
||||||
|
coverImg: [
|
||||||
|
{ required: true, message: '请上传封面', trigger: 'blur' }
|
||||||
|
],
|
||||||
|
teacher: [
|
||||||
|
{ required: true, message: '请选择讲师', trigger: 'blur' }
|
||||||
|
],
|
||||||
|
content: [
|
||||||
|
{ required: true, message: '请输入文章内容', trigger: 'blur' }
|
||||||
|
]
|
||||||
})
|
})
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
console.log(route.query.id)
|
console.log(route.query.id)
|
||||||
if(route.query.id) {
|
if(route.query.id) {
|
||||||
getDetail()
|
isEdit.value = true
|
||||||
|
getDetail()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
const handleAvatarSuccess = ( response, uploadFile ) => {
|
const handleAvatarSuccess = ( response, uploadFile ) => {
|
||||||
@ -120,13 +125,32 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
function getStaffInfo(data) {
|
function getStaffInfo(data) {
|
||||||
console.log(data)
|
|
||||||
formData.value.teacherId = data.ID
|
formData.value.teacherId = data.ID
|
||||||
formData.value.teacher = data.nickName
|
formData.value.teacher = data.nickName
|
||||||
}
|
}
|
||||||
function submit() {
|
function submit(formRef) {
|
||||||
console.log('提交')
|
if(!formRef) return
|
||||||
|
// 校验
|
||||||
|
formRef.validate(async (valid) => {
|
||||||
|
if(!valid) return
|
||||||
|
let fn = isEdit.value ? edit : add
|
||||||
|
// price字段转为数字
|
||||||
|
formData.value.price = Number(formData.value.price)
|
||||||
|
const res = await fn(formData.value)
|
||||||
|
console.log(res)
|
||||||
|
if(res.code === 0) {
|
||||||
|
ElMessage({
|
||||||
|
type: 'success',
|
||||||
|
message: isEdit.value ? '编辑成功' : '添加成功!'
|
||||||
|
})
|
||||||
|
router.back()
|
||||||
|
} else {
|
||||||
|
ElMessage({
|
||||||
|
type: 'error',
|
||||||
|
message: res.msg
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="gva-table-box">
|
<div class="gva-table-box">
|
||||||
<div class="gva-btn-list">
|
<div class="gva-btn-list">
|
||||||
<el-button type="primary" icon="plus" @click="openDialog()">新增</el-button>
|
<el-button type="primary" icon="plus" @click="handleEdit()">新增</el-button>
|
||||||
</div>
|
</div>
|
||||||
<Content
|
<Content
|
||||||
@changePage="changePage"
|
@changePage="changePage"
|
||||||
@ -53,12 +53,38 @@
|
|||||||
</template>
|
</template>
|
||||||
</Content>
|
</Content>
|
||||||
</div>
|
</div>
|
||||||
|
<!-- 在 template 的 Content 组件后添加 Dialog -->
|
||||||
|
<el-dialog
|
||||||
|
v-model="detailVisible"
|
||||||
|
title="文章详情"
|
||||||
|
width="60%"
|
||||||
|
destroy-on-close
|
||||||
|
>
|
||||||
|
<el-descriptions :column="2" border>
|
||||||
|
<el-descriptions-item label="封面图">
|
||||||
|
<el-image
|
||||||
|
style="width: 100px; height: 100px"
|
||||||
|
:src="detailData.coverImg"
|
||||||
|
:preview-src-list="[detailData.coverImg]"
|
||||||
|
fit="cover"
|
||||||
|
/>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="商品名称">{{ detailData.title || EMPTY_STR }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="创建时间">{{ formatDate(detailData.CreatedAt) }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="更新时间">{{ formatDate(detailData.UpdatedAt) }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="商品描述" :span="2">
|
||||||
|
<div v-html="detailData.content"></div>
|
||||||
|
</el-descriptions-item>
|
||||||
|
</el-descriptions>
|
||||||
|
</el-dialog>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup>
|
<script setup>
|
||||||
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||||
import searchForm from '@/components/searchForm/index.vue'
|
import searchForm from '@/components/searchForm/index.vue'
|
||||||
import Content from '@/components/content/index.vue'
|
import Content from '@/components/content/index.vue'
|
||||||
import {list} from '@/api/goods/index.js'
|
import { del, list } from '@/api/goods/index.js'
|
||||||
import { ref, onMounted } from 'vue'
|
import { ref, onMounted } from 'vue'
|
||||||
import {formatDate} from '@/utils/format'
|
import {formatDate} from '@/utils/format'
|
||||||
import { ARTICLE_SEARCH_CONFIG, ARTICLE_TABLE_CONFIG } from '@/config'
|
import { ARTICLE_SEARCH_CONFIG, ARTICLE_TABLE_CONFIG } from '@/config'
|
||||||
@ -66,9 +92,12 @@
|
|||||||
import { useRouter, useRoute} from 'vue-router'
|
import { useRouter, useRoute} from 'vue-router'
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
|
const EMPTY_STR = '- -'
|
||||||
|
// 在 script setup 中添加响应式数据
|
||||||
|
const detailVisible = ref(false)
|
||||||
|
const detailData = ref({})
|
||||||
|
|
||||||
|
const tableLoading = ref(true), tableData = ref([])
|
||||||
const tableLoading = ref(true), tableData = ref([{status:1}])
|
|
||||||
const queryParams = ref({
|
const queryParams = ref({
|
||||||
page: 1,
|
page: 1,
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
@ -76,10 +105,6 @@
|
|||||||
startTime: '',
|
startTime: '',
|
||||||
endTime: ''
|
endTime: ''
|
||||||
}), total = ref(0)
|
}), total = ref(0)
|
||||||
// const EMPTY_STR = '- -'
|
|
||||||
const tag = (status) => {
|
|
||||||
return userStatus.find((item) => item.value === status+'') || { type: '', label: EMPTY_STR }
|
|
||||||
}
|
|
||||||
const searchData = (data) => {
|
const searchData = (data) => {
|
||||||
if (data.times) {
|
if (data.times) {
|
||||||
data.startTime = data.times[0]
|
data.startTime = data.times[0]
|
||||||
@ -100,6 +125,11 @@
|
|||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
getList()
|
getList()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
function handleDetail(row) {
|
||||||
|
detailData.value = { ...row }
|
||||||
|
detailVisible.value = true
|
||||||
|
}
|
||||||
async function getList() {
|
async function getList() {
|
||||||
const res = await list(queryParams.value)
|
const res = await list(queryParams.value)
|
||||||
if(res.code === 0) {
|
if(res.code === 0) {
|
||||||
@ -107,21 +137,49 @@
|
|||||||
total.value = res.data.total
|
total.value = res.data.total
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleDetail(row) {
|
|
||||||
|
|
||||||
}
|
|
||||||
function handleEdit(row) {
|
function handleEdit(row) {
|
||||||
console.log(row)
|
|
||||||
router.push({
|
router.push({
|
||||||
name: 'edit',
|
name: 'edit',
|
||||||
query: {
|
query: {
|
||||||
id: row.ID
|
id: row?row.ID:''
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
function handleDelete(row) {
|
async function handleDelete(row) {
|
||||||
|
// 提醒
|
||||||
|
// this.$confirm('此操作将永久删除该文件, 是否继续?', '提示', {
|
||||||
|
// confirmButtonText: '确定',
|
||||||
|
// cancelButtonText: '取消',
|
||||||
|
// type: 'warning'
|
||||||
|
// }).then(() => {
|
||||||
|
// // 删除
|
||||||
|
// del(row.ID)
|
||||||
|
// }).catch(() => {
|
||||||
|
// this.$message({
|
||||||
|
// type: 'info',
|
||||||
|
// message: '已取消删除'
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
try {
|
||||||
|
await ElMessageBox.confirm('此操作将永久删除该商品,是否继续?', '警告', {
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
type: 'warning',
|
||||||
|
})
|
||||||
|
|
||||||
|
const res = await del({
|
||||||
|
ids: [row.ID]
|
||||||
|
})
|
||||||
|
if (res.code === 0) {
|
||||||
|
ElMessage.success('删除成功')
|
||||||
|
getList() // 刷新列表
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
// 取消删除时不需要提示
|
||||||
|
if (error !== 'cancel') {
|
||||||
|
ElMessage.error(error.message || '删除失败')
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
function changePage(data) {
|
function changePage(data) {
|
||||||
queryParams.value.pageNum = data
|
queryParams.value.pageNum = data
|
||||||
|
@ -7,9 +7,11 @@
|
|||||||
@resetData="resetData"
|
@resetData="resetData"
|
||||||
class="search-box searchForm"
|
class="search-box searchForm"
|
||||||
/>
|
/>
|
||||||
<el-button type="primary" @click="handleAdd">新增用户</el-button>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="gva-table-box">
|
<div class="gva-table-box">
|
||||||
|
<div class="gva-btn-list">
|
||||||
|
<el-button type="primary" @click="handleAdd">新增用户</el-button>
|
||||||
|
</div>
|
||||||
<Content
|
<Content
|
||||||
@changePage="changePage"
|
@changePage="changePage"
|
||||||
:total="total"
|
:total="total"
|
||||||
@ -359,13 +361,4 @@
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.searchForm {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
.el-descriptions {
|
|
||||||
margin: 20px 0;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
Loading…
Reference in New Issue
Block a user