优化backend产品和解决方案

This commit is contained in:
2026-08-20 17:47:47 +08:00
parent 735534c6e6
commit a4f7a97763
14 changed files with 201 additions and 67 deletions
@@ -98,6 +98,20 @@ const getCategoryName = (cate) => {
return category?.name || "无分类";
};
// 格式化日期
const formatDate = (date: string | number | Date) => {
if (!date) return "-";
const d = new Date(date);
if (isNaN(d.getTime())) return String(date);
const year = d.getFullYear();
const month = String(d.getMonth() + 1).padStart(2, "0");
const day = String(d.getDate()).padStart(2, "0");
const hours = String(d.getHours()).padStart(2, "0");
const minutes = String(d.getMinutes()).padStart(2, "0");
const seconds = String(d.getSeconds()).padStart(2, "0");
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
};
const emit = defineEmits(["update:modelValue"]);
const visible = ref(false);
@@ -213,8 +213,8 @@
import { ref, onMounted } from "vue";
import { ElMessage, ElMessageBox } from "element-plus";
import { Search } from "@element-plus/icons-vue";
import Edit from "./index/components/edit.vue";
import Preview from "./index/components/preview.vue";
import Edit from "./components/edit.vue";
import Preview from "./components/preview.vue";
import { useAuthStore } from "@/stores/auth";
import {
listArticles,
@@ -1,8 +1,9 @@
<template>
<el-dialog
<el-drawer
v-model="visible"
:title="title"
width="600px"
size="65%"
class="cms-product-drawer"
destroy-on-close
@close="handleClose"
>
@@ -11,6 +12,7 @@
:model="formData"
:rules="formRules"
label-width="100px"
class="product-form"
>
<el-form-item label="产品名称" prop="title">
<el-input v-model="formData.title" placeholder="请输入产品名称" />
@@ -19,11 +21,11 @@
<el-input
v-model="formData.desc"
type="textarea"
:rows="5"
:rows="4"
placeholder="请输入产品描述"
/>
</el-form-item>
<el-form-item label="产品内容" prop="content">
<el-form-item label="产品内容" prop="content" class="content-form-item">
<div class="editor-container">
<UmoEditor v-model="formData.content" style="height: 450px;" />
</div>
@@ -87,7 +89,7 @@
</el-button>
</span>
</template>
</el-dialog>
</el-drawer>
</template>
<script setup>
@@ -265,6 +267,30 @@ const handleSubmit = async () => {
</script>
<style scoped>
:deep(.el-drawer__body) {
overflow-x: hidden;
padding: 20px;
}
.product-form {
width: 100%;
}
:deep(.el-form-item__content) {
min-width: 0;
max-width: 100%;
}
.editor-container {
width: 100%;
min-width: 0;
max-width: 100%;
border: 1px solid var(--el-border-color, #dcdfe6);
border-radius: 4px;
overflow: hidden;
box-sizing: border-box;
}
.dialog-footer {
display: flex;
justify-content: flex-end;
@@ -1,8 +1,9 @@
<template>
<el-dialog
<el-drawer
v-model="visible"
:title="title"
width="600px"
size="65%"
class="cms-solution-drawer"
destroy-on-close
@close="handleClose"
>
@@ -11,19 +12,25 @@
:model="formData"
:rules="formRules"
label-width="100px"
class="solution-form"
>
<el-form-item label="服务名称" prop="title">
<el-input v-model="formData.title" placeholder="请输入服务名称" />
<el-form-item label="方案名称" prop="title">
<el-input v-model="formData.title" placeholder="请输入解决方案名称" />
</el-form-item>
<el-form-item label="服务描述" prop="desc">
<el-form-item label="方案描述" prop="desc">
<el-input
v-model="formData.desc"
type="textarea"
:rows="5"
placeholder="请输入服务描述"
:rows="4"
placeholder="请输入解决方案描述"
/>
</el-form-item>
<el-form-item label="Logo" prop="thumb">
<el-form-item label="方案内容" prop="content" class="content-form-item">
<div class="editor-container">
<UmoEditor v-model="formData.content" style="height: 450px;" />
</div>
</el-form-item>
<el-form-item label="方案图片" prop="thumb">
<div class="flex-direction">
<el-upload
class="image-uploader"
@@ -42,7 +49,7 @@
/>
<div v-else class="upload-placeholder">
<el-icon class="image-uploader-icon"><Plus /></el-icon>
<div class="el-upload__text">点击上传服务图标</div>
<div class="el-upload__text">点击上传方案图片</div>
</div>
</el-upload>
<div
@@ -63,7 +70,7 @@
@click="handleRemoveImage"
style="margin-top: 8px"
>
删除图标
删除图片
</el-button>
</el-form-item>
<el-form-item label="排序" prop="sort">
@@ -82,7 +89,7 @@
</el-button>
</span>
</template>
</el-dialog>
</el-drawer>
</template>
<script setup>
@@ -101,7 +108,7 @@ const props = defineProps({
},
title: {
type: String,
default: "添加服务",
default: "添加解决方案",
},
isEdit: {
type: Boolean,
@@ -144,7 +151,7 @@ const beforeImageUpload = (file) => {
// 图片上传成功
const handleImageSuccess = (response) => {
if (response.code === 200 || response.code === 201) {
formData.link_logo = response.data.url || response.data.path;
formData.thumb = response.data.url || response.data.path;
ElMessage.success(
response.code === 201 ? "文件已存在,直接使用" : "图片上传成功",
);
@@ -160,7 +167,7 @@ const handleImageError = () => {
// 删除图片
const handleRemoveImage = () => {
formData.link_logo = "";
formData.thumb = "";
ElMessage.success("图片已删除");
};
@@ -174,6 +181,7 @@ const getImageUrl = (imagePath) => {
const formData = reactive({
title: "",
desc: "",
content: "",
thumb: "",
url: "",
sort: 0,
@@ -182,11 +190,11 @@ const formData = reactive({
const formRules = {
title: [
{ required: true, message: "请输入服务名称", trigger: "blur" },
{ required: true, message: "请输入解决方案名称", trigger: "blur" },
{ max: 100, message: "长度不超过100个字符", trigger: "blur" },
],
desc: [
{ required: true, message: "请输入服务描述", trigger: "blur" },
{ required: true, message: "请输入解决方案描述", trigger: "blur" },
{ max: 200, message: "描述长度不超过200个字符", trigger: "blur" },
],
};
@@ -214,6 +222,7 @@ watch(visible, (val) => {
const resetForm = () => {
formData.title = "";
formData.desc = "";
formData.content = "";
formData.thumb = "";
formData.url = "";
formData.sort = 0;
@@ -259,6 +268,30 @@ const handleSubmit = async () => {
</script>
<style scoped>
:deep(.el-drawer__body) {
overflow-x: hidden;
padding: 20px;
}
.solution-form {
width: 100%;
}
:deep(.el-form-item__content) {
min-width: 0;
max-width: 100%;
}
.editor-container {
width: 100%;
min-width: 0;
max-width: 100%;
border: 1px solid var(--el-border-color, #dcdfe6);
border-radius: 4px;
overflow: hidden;
box-sizing: border-box;
}
.dialog-footer {
display: flex;
justify-content: flex-end;
@@ -1,7 +1,7 @@
<template>
<div class="container-box">
<div class="header-bar">
<h2>特色服务管理</h2>
<h2>解决方案管理</h2>
<div class="header-actions">
<el-button type="primary" @click="handleTypes">
<el-icon>
@@ -13,7 +13,7 @@
<el-icon>
<Plus />
</el-icon>
添加内容
添加解决方案
</el-button>
<el-button @click="refresh" :loading="loading">
<el-icon>
@@ -28,7 +28,7 @@
<!-- 搜索栏 -->
<div class="search-bar">
<el-input v-model="searchForm.keyword" placeholder="请输入内容搜索" clearable style="width: 200px; margin-right: 10px"
<el-input v-model="searchForm.keyword" placeholder="请输入解决方案名称搜索" clearable style="width: 200px; margin-right: 10px"
@keyup.enter="handleSearch" />
<el-select v-model="searchForm.status" placeholder="状态筛选" clearable style="width: 120px; margin-right: 10px">
<el-option label="启用" :value="1" />
@@ -46,9 +46,23 @@
<!-- 数据表格 -->
<el-table :data="servicesList" style="width: 100%" v-loading="loading" @selection-change="handleSelectionChange">
<el-table-column prop="id" label="ID" width="80" align="center" />
<el-table-column prop="thumb" label="服务图片" min-width="150" align="center" />
<el-table-column prop="title" label="服务名称" min-width="150" align="center" />
<el-table-column prop="desc" label="服务描述" min-width="150" align="center" />
<el-table-column prop="thumb" label="方案图片" min-width="150" align="center">
<template #default="{ row }">
<el-image v-if="row.thumb" :src="getImageUrl(row.thumb)" :preview-src-list="[getImageUrl(row.thumb)]"
fit="cover" class="solution-thumb" :preview-teleported="true" lazy>
<template #error>
<div class="image-slot">
<el-icon>
<Picture />
</el-icon>
</div>
</template>
</el-image>
<span v-else class="text-gray">暂无图片</span>
</template>
</el-table-column>
<el-table-column prop="title" label="方案名称" min-width="150" align="center" />
<el-table-column prop="desc" label="方案描述" min-width="150" align="center" />
<el-table-column prop="url" label="跳转地址" min-width="150" align="center" />
<el-table-column prop="sort" label="排序" width="80" align="center" />
<el-table-column prop="create_time" label="创建时间" width="180" align="center" />
@@ -148,8 +162,8 @@ const fetchList = async () => {
pagination.total = res.data.total
}
} catch (error) {
console.error('获取特色服务列表失败:', error)
ElMessage.error('获取特色服务列表失败')
console.error('获取解决方案列表失败:', error)
ElMessage.error('获取解决方案列表失败')
} finally {
loading.value = false
}
@@ -193,7 +207,7 @@ const handleSelectionChange = (selection) => {
// 添加
const handleAdd = () => {
isEdit.value = false
dialogTitle.value = '添加特色服务'
dialogTitle.value = '添加解决方案'
currentRow.value = {}
dialogVisible.value = true
}
@@ -201,7 +215,7 @@ const handleAdd = () => {
// 编辑
const handleEdit = (row) => {
isEdit.value = true
dialogTitle.value = '编辑特色服务'
dialogTitle.value = '编辑解决方案'
currentRow.value = row
dialogVisible.value = true
}
@@ -209,7 +223,7 @@ const handleEdit = (row) => {
// 删除
const handleDelete = async (row) => {
try {
await ElMessageBox.confirm('确定要删除该特色服务吗?', '提示', {
await ElMessageBox.confirm('确定要删除该解决方案吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
@@ -224,8 +238,8 @@ const handleDelete = async (row) => {
}
} catch (error) {
if (error !== 'cancel') {
console.error('删除特色服务失败:', error)
ElMessage.error('删除特色服务失败')
console.error('删除解决方案失败:', error)
ElMessage.error('删除解决方案失败')
}
}
}
@@ -241,8 +255,8 @@ const handleStatusChange = async (row, val) => {
row.status = val === 1 ? 0 : 1
}
} catch (error) {
console.error('更新特色服务状态失败:', error)
ElMessage.error('更新特色服务状态失败')
console.error('更新解决方案状态失败:', error)
ElMessage.error('更新解决方案状态失败')
row.status = val === 1 ? 0 : 1
}
}