提交 e40a287e authored 作者: 刘旭's avatar 刘旭

完成广告管理,专题管理50%

上级 d7d941a5
......@@ -4,3 +4,4 @@ VITE_APP_PORT = 3003
# 请求接口
VITE_APP_BASE_URL = "/admin"
VITE_APP_BASE_IMG = "http://192.168.0.23/wx/storage/fetch/"
\ No newline at end of file
......@@ -4,3 +4,4 @@ VITE_APP_PORT = 3002
# 请求接口
VITE_APP_BASE_URL = "/admin"
VITE_APP_BASE_IMG = "http://192.168.0.23/wx/storage/fetch/"
\ No newline at end of file
<template>
<el-dialog v-model="htmlData.htmlVisible" :title="htmlData.title">
<div v-html="htmlData.details" />
</el-dialog>
</template>
<script lang="ts" setup>
let props = defineProps({
htmlData: {
type: Object,
default: {
htmlVisible: {
type: Boolean,
default: false
},
title: {
type: String,
default: ''
},
details: {
type: String,
default: '<p></p>'
}
}
}
})
</script>
\ No newline at end of file
......@@ -46,9 +46,6 @@ let props = defineProps({
}
})
console.log(props);
let emits = defineEmits(['sizeChange', 'currentChange'])
// 新条数
......
import { request } from '../config'
export function listAd(params: any) {
return request({
url: '/ad/list',
method: 'get',
params
})
}
export function createAd(data: any) {
return request({
url: '/ad/create',
method: 'post',
data
})
}
export function readAd(data: any) {
return request({
url: '/ad/read',
method: 'get',
data
})
}
export function updateAd(data: any) {
return request({
url: '/ad/update',
method: 'post',
data
})
}
export function deleteAd(data: any) {
return request({
url: '/ad/delete',
method: 'post',
data
})
}
import { request } from '../config'
export function listTopic(params: any) {
return request({
url: '/topic/list',
method: 'get',
params
})
}
export function createTopic(data: any) {
return request({
url: '/topic/create',
method: 'post',
data
})
}
export function readTopic(params: any) {
return request({
url: '/topic/read',
method: 'get',
params
})
}
export function updateTopic(data: any) {
return request({
url: '/topic/update',
method: 'post',
data
})
}
export function deleteTopic(data: any) {
return request({
url: '/topic/delete',
method: 'post',
data
})
}
export function batchDeleteTopic(data: any) {
return request({
url: '/topic/batch-delete',
method: 'post',
data
})
}
......@@ -68,10 +68,7 @@
<el-table-column align="center" label="详情" prop="detail">
<template #default="scope">
<el-dialog v-model="detailDialogVisible" title="商品详情">
<div class="goods-detail-box" v-html="goodsDetail" />
</el-dialog>
<el-button type="primary" size="small" @click="showDetail(scope.row.detail)">查看</el-button>
<el-button type="primary" link @click="showDetail(scope.row.detail)">查看</el-button>
</template>
</el-table-column>
......@@ -114,16 +111,17 @@
<litemall-page :page-data="listQuery" :total="total" @size-change="sizeChange"
@current-change="currentChange" />
</div>
<shelves ref="shelvesRef" @initShelves="getList"/>
<edit ref="editRef" :editId="editId" @initShelves="getList"/>
<shelves ref="shelvesRef" @initShelves="getList" />
<edit ref="editRef" :editId="editId" @initShelves="getList" />
<!-- 查看详情 -->
<html-details :html-data="htmlData" />
</template>
<script setup lang="ts">
import { ref } from "vue";
import { ElMessageBox, ElNotification } from "element-plus";
import { listGoods, deleteGoods } from "@/services/api/commodityManage/list";
// import { thumbnail, toPreview } from "@/utils/index";
import router from '@/router';
import htmlDetails from '@/components/htmlDetails.vue'
import LitemallPage from "@/components/pagination/litemallPage.vue";
import shelves from './shelves.vue'
import edit from './edit.vue'
......@@ -142,10 +140,12 @@ let listQuery = ref({
sort: "add_time",
order: "desc",
} as any);
let goodsDetail = ref("");
let detailDialogVisible = ref(false);
let downloadLoading = ref(false);
let htmlData = ref({
htmlVisible: false,
title: '商品详情',
details: ''
})
let getList = () => {
listLoading.value = true;
listGoods(listQuery.value)
......@@ -185,8 +185,8 @@ let handleUpdate = (row: any) => {
editRef.value.editDrawer = true
};
let showDetail = (detail: any) => {
goodsDetail = detail;
detailDialogVisible.value = true;
htmlData.value.htmlVisible = true
htmlData.value.details = detail
};
let handleDelete = (row: any) => {
ElMessageBox.confirm("确定删除?", "警告", {
......
......@@ -2,11 +2,12 @@
<div class="app-container">
<!-- 查询和其他操作 -->
<div class="filter-container">
<el-button class="filter-item" type="primary" icon="edit" @click="handleCreate">添加</el-button>
<el-button class="filter-item" type="primary" icon="plus" @click="handleCreate">添加</el-button>
</div>
<!-- 查询结果 -->
<el-table v-loading="listLoading" :data="list" element-loading-text="正在查询中。。。" border fit highlight-current-row>
<el-table v-loading="listLoading" :data="list" element-loading-text="正在查询中。。。" border fit highlight-current-row
row-key="id">
<el-table-column align="center" label="类目ID" prop="id" />
<el-table-column align="center" label="类目名" prop="name" />
......@@ -19,9 +20,8 @@
<el-table-column align="center" property="picUrl" label="类目图片">
<template #default="scope">
<el-image :src="scope.row.picUrl" style="width: 100px; height: 40px"></el-image>
<!-- <el-image :src="thumbnail(scope.row.picUrl)"
:preview-src-list="toPreview(scope.row, scope.row.picUrl)" style="width: 80px; height: 40px" /> -->
<el-image :src="scope.row.picUrl" style="width: 100px; height: 40px" :preview-src-list="srcList"
preview-teleported :initial-index="scope.$index" />
</template>
</el-table-column>
......@@ -80,7 +80,7 @@
<el-form-item label="类目图片" prop="picUrl">
<el-upload :headers="headers" :action="uploadPath" :show-file-list="false"
:on-success="uploadPicUrl" class="avatar-uploader" accept=".jpg,.jpeg,.png,.gif">
<img v-if="dataForm.iconUrl" :src="dataForm.iconUrl" class="avatar" />
<img v-if="dataForm.picUrl" :src="dataForm.picUrl" class="avatar" />
<el-icon v-else class="avatar-uploader-icon">
<Plus />
</el-icon>
......@@ -102,8 +102,8 @@
</template>
<script setup lang="ts">
import { reactive, ref, computed, nextTick } from "vue";
import { ElMessage, ElMessageBox, ElNotification } from 'element-plus';
import { reactive, ref, nextTick } from "vue";
import { ElNotification } from 'element-plus';
import {
listCategory,
listCatL1,
......@@ -113,13 +113,13 @@ import {
} from "@/services/api/market/category";
import { uploadPath } from "@/services/api/storage";
import LitemallPage from "@/components/pagination/litemallPage.vue";
// import { thumbnail, toPreview } from "@/utils/index";
let dataFormRef = ref();
let list = ref([] as any);
let listLoading = ref(true);
let catL1 = ref({} as any);
let dataForm = reactive({
let catL1 = ref([] as any);
let srcList = ref([] as any)
let dataForm = ref({
id: undefined,
name: "",
keywords: "",
......@@ -152,10 +152,12 @@ let getList = () => {
listLoading.value = true;
listCategory(listQuery.value)
.then((res: any) => {
let urls = [] as any
res.data.list.map((item: any) => urls.push(item.picUrl))
srcList.value = urls
urls = []
list.value = res.data.list;
total.value = res.data.total
console.log(res);
listLoading.value = false;
})
.catch(() => {
......@@ -166,7 +168,7 @@ let getList = () => {
getList()
let getCatL1 = () => {
listCatL1().then((res: any) => {
catL1.value = res.data.list;
catL1.value = res.data;
});
};
getCatL1()
......@@ -182,7 +184,7 @@ let currentChange = (val: number) => {
}
let resetForm = () => {
dataForm = {
dataForm.value = {
id: undefined,
name: "",
keywords: "",
......@@ -195,7 +197,7 @@ let resetForm = () => {
};
let onLevelChange = (value: any) => {
if (value === "L1") {
dataForm.pid = 0;
dataForm.value.pid = 0;
}
};
let handleCreate = () => {
......@@ -207,16 +209,17 @@ let handleCreate = () => {
});
};
let uploadIconUrl = (res: any) => {
dataForm.iconUrl = res.data.url;
dataForm.value.iconUrl = import.meta.env.VITE_APP_BASE_IMG + res.data.key;
};
let uploadPicUrl = (res: any) => {
dataForm.picUrl = res.data.url;
dataForm.value.picUrl = import.meta.env.VITE_APP_BASE_IMG + res.data.key;
};
let createData = () => {
dataFormRef.value?.validate((valid: any) => {
if (valid) {
createCategory(dataForm)
createCategory(dataForm.value)
.then((res: any) => {
if (res.code === 200) {
getList();
// 更新L1目录
getCatL1();
......@@ -226,6 +229,7 @@ let createData = () => {
title: "成功",
message: "创建成功",
});
}
})
.catch((res: any) => {
ElNotification({
......@@ -237,7 +241,7 @@ let createData = () => {
});
};
let handleUpdate = (row: any) => {
dataForm = Object.assign({}, row);
dataForm.value = Object.assign({}, row);
dialogStatus.value = "update";
dialogFormVisible.value = true;
nextTick(() => {
......@@ -247,8 +251,9 @@ let handleUpdate = (row: any) => {
let updateData = () => {
dataFormRef.value?.validate((valid: any) => {
if (valid) {
updateCategory(dataForm)
.then(() => {
updateCategory(dataForm.value)
.then((res: any) => {
if (res.code === 200) {
getList();
// 更新L1目录
getCatL1();
......@@ -258,11 +263,12 @@ let updateData = () => {
title: "成功",
message: "更新成功",
});
}
})
.catch((res: any) => {
ElNotification({
title: "失败",
message: res.data.errmsg,
message: res.msg,
});
});
}
......
差异被折叠。
<template>
<div class="app-container">
<!-- 查询和其他操作 -->
<div class="filter-container">
<el-input v-model="listQuery.title" clearable class="filter-item" style="width: 200px;"
placeholder="请输入专题标题" />
<el-input v-model="listQuery.subtitle" clearable class="filter-item" style="width: 200px;"
placeholder="请输入专题子标题" />
<el-select v-model="listQuery.sort" class="filter-item" placeholder="请选择排序字段">
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
<el-button class="filter-item" type="primary" icon="search" @click="handleFilter">查找</el-button>
<el-button :loading="downloadLoading" class="filter-item" type="primary" icon="download"
@click="handleDownload">导出</el-button>
</div>
<div style="margin-bottom: 20px;">
<el-button class="filter-item" type="primary" icon="edit" @click="handleCreate">添加</el-button>
<el-button class="filter-item" type="danger" icon="delete" @click="handleBatchDelete">批量删除
</el-button>
</div>
<!-- 查询结果 -->
<el-table v-loading="listLoading" :data="list" element-loading-text="正在查询中。。。" border fit highlight-current-row
@selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" />
<el-table-column align="center" label="专题标题" prop="title" />
<el-table-column align="center" label="专题子标题" min-width="200" prop="subtitle" />
<el-table-column align="center" property="picUrl" label="图片">
<template #default="scope">
<el-image :src="scope.row.picUrl" :preview-src-list="srcList" style="width: 40px; height: 40px"
preview-teleported :initial-index="scope.$index" />
</template>
</el-table-column>
<el-table-column align="center" label="专题详情" prop="content">
<template #default="scope">
<el-button type="primary" link @click="showContent(scope.row.content)">查看</el-button>
</template>
</el-table-column>
<el-table-column align="center" label="底价" prop="price" />
<el-table-column align="center" label="阅读数量" prop="readCount" />
<el-table-column align="center" label="操作" min-width="100" class-name="small-padding fixed-width">
<template #default="scope">
<el-button type="primary" link @click="handleUpdate(scope.row)">编辑</el-button>
<el-button type="danger" link @click="handleDelete(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<litemall-page :page-data="listQuery" :total="total" @size-change="sizeChange"
@current-change="currentChange" />
<!-- 查看详情 -->
<html-details :html-data="htmlData"/>
<topic-create ref="topicCreateRef" />
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { listTopic, deleteTopic, batchDeleteTopic } from '@/services/api/promotion/topic'
import { ElMessage, ElMessageBox } from 'element-plus';
import _ from 'lodash'
import LitemallPage from "@/components/pagination/litemallPage.vue";
import htmlDetails from '@/components/htmlDetails.vue'
import topicCreate from './topicCreate.vue'
let list = ref([] as any)
let total = ref(0)
let listLoading = ref(true)
let srcList = ref([] as any)
let topicCreateRef = ref()
let listQuery = ref({
page: 1,
limit: 10,
title: undefined,
subtitle: undefined,
sort: 'add_time',
order: 'desc'
})
let htmlData = ref({
htmlVisible: false,
title: '专题详情',
details: ''
})
let options = ref([{
value: 'id',
label: '按序号排序'
}, {
value: 'add_time',
label: '按时间排序'
}, {
value: 'price',
label: '按价格排序'
}])
let multipleSelection = ref([])
let downloadLoading = ref(false)
let getList = () => {
listLoading.value = true
listTopic(listQuery.value)
.then((res: any) => {
let urls = [] as any
res.data.list.map((item: any) => urls.push(item.picUrl))
srcList.value = urls
urls = []
list.value = res.data.list
total.value = res.data.total
listLoading.value = false
})
.catch(() => {
list.value = []
total.value = 0
listLoading.value = false
})
}
getList()
let currentChange = (val: number) => {
listQuery.value.page = val
getList()
}
let sizeChange = (val: number) => {
listQuery.value.limit = val
getList()
}
let handleFilter = () => {
listQuery.value.page = 1
getList()
}
let handleCreate = () => {
topicCreateRef.value.createDrawer = true
// $router.push({ path: '/promotion/topic-create' })
}
let handleUpdate = (row: any) => {
// $router.push({ path: '/promotion/topic-edit', query: { id: row.id } })
}
let handleDelete = (row: any) => {
ElMessageBox.confirm(
'确认删除?', '提示',
{
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning',
}).then(() => {
deleteTopic(row)
.then(res => {
ElMessage({
type: 'success',
message: '删除专题成功'
})
getList()
})
.catch(res => {
ElMessage({
type: 'error',
message: res.data.errmsg
})
})
})
}
let handleSelectionChange = (val: any) => {
multipleSelection.value = val
}
let showContent = (content: any) => {
htmlData.value.htmlVisible = true
htmlData.value.details = content
}
let handleBatchDelete = () => {
if (multipleSelection.value.length === 0) {
ElMessage({
type: 'error',
message: '请选择至少一条记录'
})
return
}
const ids: any = []
_.forEach(multipleSelection.value, function (item: any) {
ids.push(item.id)
})
batchDeleteTopic({ ids: ids })
.then((res: any) => {
ElMessage({
type: 'success',
message: '批量删除专题成功'
})
getList()
})
.catch(res => {
ElMessage({
type: 'error',
message: res.data.errmsg
})
})
}
let handleDownload = () => {
// downloadLoading.value = true
// import('@/vendor/Export2Excel').then(excel => {
// const tHeader = [
// '专题ID',
// '专题标题',
// '专题子标题',
// '专题内容',
// '专题图片',
// '商品低价',
// '阅读量',
// '专题商品'
// ]
// const filterVal = [
// 'id',
// 'title',
// 'subtitle',
// 'content',
// 'picUrl',
// 'price',
// 'readCount',
// 'goods'
// ]
// excel.export_json_to_excel2(tHeader, list, filterVal, '专题信息')
// downloadLoading.value = false
// })
}
</script>
<style>
.el-dialog {
width: 800px;
}
.avatar-uploader .el-upload {
border: 1px dashed #d9d9d9;
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
}
.avatar-uploader .el-upload:hover {
border-color: #20a0ff;
}
.avatar-uploader-icon {
font-size: 28px;
color: #8c939d;
width: 120px;
height: 120px;
line-height: 120px;
text-align: center;
}
.avatar {
width: 145px;
height: 145px;
display: block;
}
</style>
<template>
<el-drawer v-model="createDrawer" title="新增专题" size="50%" @before-close="handleCancel">
<el-form ref="topic" :rules="rules" :model="topic" status-icon label-position="left" label-width="100px"
style="width: 800px; margin-left:50px;">
<el-form-item label="专题标题" prop="title">
<el-input v-model="topic.title" />
</el-form-item>
<el-form-item label="专题子标题" prop="subtitle">
<el-input v-model="topic.subtitle" />
</el-form-item>
<el-form-item label="专题图片" prop="picUrl">
<el-upload :headers="headers" :action="uploadPath" :show-file-list="false" :on-success="uploadPicUrl"
class="avatar-uploader" accept=".jpg,.jpeg,.png,.gif">
<img v-if="topic.picUrl" :src="topic.picUrl" class="avatar">
<el-icon v-else class="avatar-uploader-icon">
<Plus />
</el-icon>
</el-upload>
</el-form-item>
<el-form-item label="专题内容" prop="content">
<!-- <editor :init="editorInit" v-model="topic.content" /> -->
</el-form-item>
<el-form-item label="商品低价" prop="price">
<el-input v-model="topic.price" />
</el-form-item>
<el-form-item label="阅读量" prop="readCount">
<el-input v-model="topic.readCount" />
</el-form-item>
<el-form-item label="专题商品" prop="goods">
<div style="display: flex; justify-content: end; width: 100%;">
<el-button style="margin-bottom: 10px;" size="small" type="primary" @click="handleCreate()">创建商品
</el-button>
</div>
<!-- 查询结果 -->
<el-table :data="goodsList" border fit highlight-current-row>
<el-table-column align="center" label="商品ID" prop="id" />
<el-table-column align="center" property="picUrl" label="图片">
<template #default="scope">
<img :src="scope.row.picUrl" width="60">
</template>
</el-table-column>
<el-table-column align="center" label="商品名称" prop="name" />
<el-table-column align="center" label="商品介绍" prop="brief" />
<el-table-column align="center" label="操作" class-name="small-padding fixed-width">
<template #default="scope">
<el-button type="danger" link @click="handleDelete(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
</el-form-item>
</el-form>
<template #footer class="dialog-footer">
<el-button @click="handleCancel">取消</el-button>
<el-button type="primary" @click="handleConfirm">确定</el-button>
</template>
</el-drawer>
<el-dialog v-model="addVisiable" title="添加商品">
<div class="search">
<div class="filter-container">
<el-input v-model="listQuery.goodsSn" clearable class="filter-item" style="width: 200px;"
placeholder="请输入商品编号" />
<el-input v-model="listQuery.name" clearable class="filter-item" style="width: 200px;"
placeholder="请输入商品名称" />
<el-button class="filter-item" type="primary" icon="search" @click="handleFilter">查找</el-button>
</div>
<el-table v-loading="listLoading" :data="list" element-loading-text="正在查询中。。。" border fit
highlight-current-row @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" />
<el-table-column align="center" label="商品ID" prop="id" />
<el-table-column align="center" property="picUrl" label="图片">
<template #default="scope">
<img :src="scope.row.picUrl" width="40">
</template>
</el-table-column>
<el-table-column align="center" label="商品名称" prop="name" />
</el-table>
<litemall-page :page-data="listQuery" :total="total" @size-change="sizeChange"
@current-change="currentChange" />
</div>
<template #footer class="dialog-footer">
<el-button @click="addVisiable = false">取消</el-button>
<el-button type="primary" @click="confirmAdd">确定</el-button>
</template>
</el-dialog>
</template>
<script setup lang="ts">
import { ref, computed } from 'vue'
import { createTopic } from '@/services/api/promotion/topic'
import { listGoods } from '@/services/api/commodityManage/list'
import { uploadPath } from '@/services/api/storage'
import { ElMessage } from "element-plus";
import LitemallPage from "@/components/pagination/litemallPage.vue";
let topic = ref({
goods: [],
title: '',
subtitle: '',
picUrl: '',
price: '',
readCount: '',
} as any)
let createDrawer = ref(false)
let topicRef = ref()
let goodsList = ref([] as any)
let addVisiable = ref(false)
let list = ref([])
let total = ref(0)
let listLoading = ref(false)
let listQuery = ref({
page: 1,
limit: 10,
id: undefined,
name: undefined,
sort: 'add_time',
order: 'desc',
goodsSn: ''
})
let selectedlist = ref([])
let rules = ref({
title: [
{ required: true, message: '专题标题不能为空', trigger: 'blur' }
],
subtitle: [
{ required: true, message: '专题子标题不能为空', trigger: 'blur' }
],
content: [
{ required: true, message: '专题内容不能为空', trigger: 'blur' }
],
price: [
{ required: true, message: '专题低价不能为空', trigger: 'blur' }
]
})
let headers = computed(() => {
return {
'Authorization': sessionStorage.getItem('token')
}
})
let getList = () => {
listLoading.value = true
listGoods(listQuery.value).then(res => {
list.value = res.data.list
console.log(list.value);
total.value = res.data.total
listLoading.value = false
}).catch(() => {
list.value = []
total.value = 0
listLoading.value = false
})
}
let currentChange = (val: number) => {
listQuery.value.page = val
getList()
}
let sizeChange = (val: number) => {
listQuery.value.limit = val
getList()
}
let handleFilter = () => {
listQuery.value.page = 1
getList()
}
let handleSelectionChange = (val: any) => {
selectedlist.value = val
console.log(selectedlist.value);
}
let uploadPicUrl = (res: any) => {
topic.value.picUrl = res.data.url
}
let handleCreate = () => {
listQuery.value = {
page: 1,
limit: 10,
id: undefined,
name: undefined,
sort: 'add_time',
order: 'desc',
goodsSn: ''
}
list.value = []
total.value = 0
selectedlist.value = []
addVisiable.value = true
}
let confirmAdd = () => {
const newGoodsIds = [] as any
const newGoodsList = [] as any
selectedlist.value.forEach((item: any) => {
const id = item.id
let found = false
console.log(topic.value.goods);
if (topic.value.goods) {
topic.value.goods.forEach((goodsId: any) => {
if (id === goodsId) {
found = true
}
})
}
if (!found) {
newGoodsIds.push(id)
newGoodsList.push(item)
}
})
if (newGoodsIds.length > 0) {
topic.value.goods = topic.value.goods.concat(newGoodsIds)
goodsList.value = goodsList.value.concat(newGoodsList)
}
addVisiable.value = false
}
let handleDelete = (row: any) => {
for (var index = 0; index < topic.value.goods.length; index++) {
if (row.id === topic.value.goods[index]) {
topic.value.goods.splice(index, 1)
}
}
for (var index2 = 0; index2 < goodsList.value.length; index2++) {
if (row.id === goodsList.value[index2].id) {
goodsList.value.splice(index2, 1)
}
}
}
let handleCancel = () => {
// $router.push({ path: '/promotion/topic' })
}
let handleConfirm = () => {
topicRef.value?.validate((valid: any) => {
if (valid) {
createTopic(topic.value).then(res => {
// $router.push({ path: '/promotion/topic' })
})
.catch(res => {
ElMessage({
type: 'error',
message: res.data.errmsg
})
})
}
})
}
defineExpose({
createDrawer
})
</script>
<style>
.el-dialog {
width: 800px;
}
.avatar-uploader .el-upload {
border: 1px dashed #d9d9d9;
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
}
.avatar-uploader .el-upload:hover {
border-color: #20a0ff;
}
.avatar-uploader-icon {
font-size: 28px;
color: #8c939d;
width: 120px;
height: 120px;
line-height: 120px;
text-align: center;
}
.avatar {
width: 145px;
height: 145px;
display: block;
}
</style>
\ No newline at end of file
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论