Merge remote-tracking branch 'origin/gyj'

# Conflicts:
#	src/views/goods/index.vue
#	src/views/users/reconnaissance.vue
This commit is contained in:
2024-10-14 19:24:12 +08:00
8 changed files with 383 additions and 244 deletions
+11
View File
@@ -0,0 +1,11 @@
import service from "../request.js";
const API_BASE_URL = '/file';
// 上传文件
export function addFile(formData) {
return service({
method: "post",
url: `${API_BASE_URL}`,
data: formData
});
}
+4
View File
@@ -30,6 +30,10 @@ service.interceptors.request.use(
config.headers["Content-Type"] = "application/json";
}
if (config.url === "/file") {
config.headers["Content-Type"] = "multipart/form-data";
}
let params = config.params;
let newData = {};
for (let key in params) {
+332 -221
View File
@@ -1,296 +1,407 @@
<template>
<el-card shadow="never" class="henader-card">
<div class="flx-row">
<el-button type="success" @click="dialogVisibleShow">
<el-card shadow="never" class="header-card">
<el-col :span="4">
<el-button type="success" @click="drawer = true;drawerEdit = false">
<el-icon style="margin-right: 10px;"><CirclePlus /></el-icon>
添加
添加
</el-button>
<el-form :inline="true" :model="queryData" style="flex: 1">
<!-- <el-input placeholder="请输入搜索内容" v-model="queryData.keyWord">-->
<!-- </el-input>-->
</el-form>
<div class="flex-right">
<!-- <el-button type="primary" :icon="Search" @click="initData" class="ml20"-->
<!-- >搜索</el-button-->
<!-- >-->
</div>
</div>
</el-col>
<el-drawer v-model="drawer" :direction="direction">
<template v-if="!drawerEdit" #header>
<h4>创建服务</h4>
</template>
<template v-else #header>
<h4>编辑服务</h4>
</template>
<template #default>
<el-form
:model="formData"
label-width="auto" style="max-width: 600px">
<el-form-item label="服务名称" prop="formData.goodsName">
<el-input
v-model="formData.goodsName"
placeholder="请输入服务名称"
></el-input>
</el-form-item>
<el-form-item label="服务价格" prop="price">
<el-input type="number" v-model="formData.price" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="轮播图">
<el-upload
v-model:file-list="fileBannerList"
multiple
list-type="picture-card"
:before-upload="beforeUpload"
:http-request="addUploadCarouselImageFile"
:limit="5"
:on-exceed="handleBannerExceed"
:on-remove="handleBannerRemove"
>
<el-icon><Plus /></el-icon>
</el-upload>
</el-form-item>
<el-form-item label="详情图">
<el-upload
v-model:file-list="fileDetail"
list-type="picture-card"
:before-upload="beforeUpload"
:http-request="addUploadDetailFile"
:limit="1"
:on-exceed="handleDetailExceed"
:on-remove="handleDetailRemove"
>
<el-icon><Plus /></el-icon>
</el-upload>
</el-form-item>
<div style="display: flex; justify-content: flex-end; margin-top: 50px">
<el-button @click="drawer = false;drawerEdit = false;">取消</el-button>
<el-button type="primary" @click="onSubmit">确认</el-button>
</div>
</el-form>
</template>
</el-drawer>
</el-card>
<el-card shadow="never">
<el-table
:data="tableData"
:header-cell-style="{ backgroundColor: '#ecf5ff' }"
border
stripe
style="width: 100%"
:data="tableData"
:header-cell-style="{ backgroundColor: '#ecf5ff' }"
border
stripe
style="width: 100%"
>
<el-table-column
v-for="item in options"
:key="item.type"
:prop="item.props"
:label="item.label"
:width="item.width"
:align="item.align"
show-overflow-tooltip
:fixed="item.fixed"
v-for="item in options"
:key="item.type"
:prop="item.props"
:label="item.label"
:width="item.width"
:align="item.align"
show-overflow-tooltip
:fixed="item.fixed"
>
<template v-slot:default="scope" v-if="item.props === 'price'">
{{ formatPrice(scope.row.price) }}
</template>
<template v-slot:default="scope" v-if="item.props === 'carouselImage'">
<el-image
style="width: 600px; height: 50px"
:src="scope.row.carouselImage"
:preview-src-list="[scope.row.carouselImage]"
/>
</template>
<template v-slot:default="scope" v-if="item.props === 'details'">
<el-image
style="width: 600px; height: 50px"
:src="scope.row.details"
:preview-src-list="[scope.row.details]"
/>
</template>
<template v-slot:default="scope" v-if="item.props === 'actions'">
<el-icon class="icon-view" @click="ItemView(scope.row)"
><View
/></el-icon>
<el-icon class="icon-edit" @click="editorClick(scope.row)"
><Edit
/></el-icon>
<el-button
type="info"
size="small"
@click="viewItem(scope.row)"
>查看</el-button>
<el-button
type="info"
size="small"
@click="editItem(scope.row)"
>编辑</el-button>
<el-popconfirm
confirm-button-text="确认"
cancel-button-text="取消"
:icon="InfoFilled"
icon-color="#626AEF"
title="确定要除该服务项目?"
@confirm="DeleteItem(index)"
confirm-button-text="确认"
cancel-button-text="取消"
:icon="InfoFilled"
icon-color="#626AEF"
title="确定要除该服务项目?"
@confirm="deleteItem(scope.$index)"
>
<template #reference>
<el-icon class="icon-dele"><Delete /></el-icon>
<el-button type="danger" size="small">删除</el-button>
</template>
</el-popconfirm>
</template>
</el-table-column>
</el-table>
<el-pagination
small
background
:page-size="queryData.size"
layout="prev, pager, next"
:total="total"
class="mt-4"
@current-change="handleCurrentChange"
small
background
:page-size="queryData.size"
layout="prev, pager, next"
:total="total"
class="mt-4"
@current-change="handleCurrentChange"
/>
</el-card>
<el-dialog
v-model="dialogVisible"
:title="`${dialogData.title}服务项目`"
:width="dialogWidth"
:hide-required-asterisk="dialogData.isView"
draggable
>
<el-form
:model="dialogData.FormData"
:rules="rules"
ref="FormRef"
class="demo-ruleForm"
>
<el-form-item
label="服务名称"
:label-width="formLabelWidth"
prop="goodsName"
>
<el-input v-model="dialogData.FormData.goodsName" autocomplete="off" />
</el-form-item>
<el-form-item label="服务价格" :label-width="formLabelWidth" prop="price">
<el-input v-model="dialogData.FormData.price" autocomplete="off" />
</el-form-item>
<el-form-item label="标题图片" :label-width="formLabelWidth" prop="carouselImage">
<el-input v-model="dialogData.FormData.carouselImage" type="textarea" />
</el-form-item>
<el-form-item label="服务说明" :label-width="formLabelWidth" prop="details">
<el-input v-model="dialogData.FormData.details" type="textarea" />
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="onSubmit()">确认</el-button>
</span>
</template>
</el-dialog>
</template>
<script setup>
import {
Search,
Edit,
Delete,
UserFilled,
CirclePlus,
Plus,
InfoFilled,
View,
Edit,
Delete,
} from '@element-plus/icons-vue'
import { getGoodsList, addGoods, updateGoods, delGoods} from '../../api/modules/goods.js'
import { getGoodsList, addGoods, updateGoods } from '../../api/modules/goods.js'
import { addFile } from '../../api/modules/upload'
import { options } from './options.js'
import { onMounted, reactive, ref } from 'vue'
import { ElMessage } from 'element-plus'
import { getDateTime } from '../../utils'
const queryData = ref({
keyWord: '',
page: 1,
size: 10,
})
const FormRef = ref()
const formLabelWidth = '140px'
const dialogData = reactive({
isView: true,
title: '添加',
FormData: {
id: 1,
goodsName: '',
price: '',
carouselImage: '',
details: '',
},
})
const dialogWidth = ref('0')
const rules = reactive({
goodsName: [{ required: true, message: '请填写服务项目姓名', trigger: 'change' }],
price: [{ required: true, message: '请填写价格', trigger: 'change' }],
carouselImage: [{ required: true, message: '请填写服务说明', trigger: 'change' }],
details: [{ required: true, message: '请填写说明信息', trigger: 'change' }],
})
const oldTableData = ref([])
const dialogVisible = ref(false)
const tableData = ref([])
const total = ref(0)
const drawer = ref(false)
const drawerEdit = ref(false)
const direction = ref('rtl')
const formData = ref({
goodsName: '',
price: '',
carouselImage: [],
details: '',
})
const fileBannerList = ref([]); // 轮播图
const fileDetail = ref(); // 详情图
// 页面初始化
const initData = () => {
getGoodsList(queryData.value).then((res) => {
total.value = res.total
tableData.value = res.data
total.value = res.total
})
}
const dialogVisibleShow = () => {
dialogData.FormData = {
goodsName: '',
price: '',
carouselImage: '',
details: '',
// 上传前的钩子
const beforeUpload = (file) => {
const maxSize = 10 * 1024 * 1024; // 最大 2MB
if (file.size > maxSize) {
alert('文件大小不能超过 10MB');
return false;
}
dialogVisible.value = true
const allowedTypes = ['image/jpeg', 'image/png'];
if (!allowedTypes.includes(file.type)) {
alert('只允许上传 JPEG 或 PNG 图片');
return false;
}
console.log('文件准备上传:', file);
return true;
}
const onSubmit = () => {
FormRef.value.validate(async (valid) => {
if (!valid) return
try {
if (dialogData.FormData.id) {
updateGoods(dialogData.FormData).then((res) => {
console.log('编辑数据成功')
console.log(ElMessage)
ElMessage({
message: '编辑服务项目成功',
type: 'success',
})
// tableData.value = res.data
})
} else {
dialogData.FormData.date = getDateTime('')
addGoods(dialogData.FormData)
.then((res) => {
ElMessage({
message: '添加服务项目成功',
type: 'success',
})
dialogData.FormData.id = res.data.data.id
tableData.value.unshift(dialogData.FormData)
})
.catch((err) => {})
// 轮播图片上传限制
const handleBannerExceed= (files, uploadFiles) => {
ElMessage.warning(
`轮播图最多可上传5张`
)
}
// 详情图片上传限制
const handleDetailExceed= (files, uploadFiles) => {
ElMessage.warning(
`详情图最多可上传1张`
)
}
// 轮播图移除
const handleBannerRemove = (file) => {
let fileName = file.name; // 移除的文件名
// 更新 formData 中的 details
formData.value.carouselImage = formData.value.carouselImage.filter(item => item.name !== file.name);
}
// 详情图移除
const handleDetailRemove = (file, fileList) => {
formData.value.details = '';
}
// 轮播上传请求
const addUploadCarouselImageFile = (params) => {
const formData = new FormData();
formData.append('files', params.file);
addFile(formData)
.then((response) => {
handleCarouselImageSuccess(response, params.file, params.fileList);
})
.catch((error) => {
if(!error)
{
handleError(error, params.file, params.fileList);
}
dialogVisible.value = false
} catch (error) {
console.log(error)
}
})
});
}
// 详情上传
const addUploadDetailFile = (params) => {
const formData = new FormData();
formData.append('files', params.file);
addFile(formData)
.then((response) => {
handleDetailSuccess(response, params.file, params.fileList);
})
.catch((error) => {
if(!error)
{
handleError(error, params.file, params.fileList);
}
});
}
// 处理轮播上传成功的回调
const handleCarouselImageSuccess = (response, file) => {
let fileObj = {
'name': file.name,
'url': response.data[0]
};
formData.value.carouselImage.push(fileObj);
}
// 处理详情上传成功的回调
const handleDetailSuccess = (response) => {
formData.value.details = response.data[0];
}
// 处理上传失败的回调
const handleError = (error, file, fileList) => {
console.error('上传失败:', error, file, fileList);
}
// 格式化价格
const formatPrice = (price) => {
return parseFloat(price).toFixed(2);
}
// 提交表单
const onSubmit = () => {
if (!formData.value.goodsName || !formData.value.price || !formData.value.details || formData.value.carouselImage.length < 1 ) {
ElMessage.error('请填写完整信息');
return;
}
formData.value.carouselImage = JSON.stringify(formData.value.carouselImage); // 转为字符串
addGoods(formData.value)
.then((res) => {
ElMessage({
message: '添加成功',
type: 'success',
})
drawer.value = false;
initData();
})
.catch((err) => {
console.error('添加失败:', err);
})
// if (drawer.value) {
//
// } else {
// updateGoods(formData.value)
// .then((res) => {
// ElMessage({
// message: '编辑服务项目成功',
// type: 'success',
// })
// tableData.value = tableData.value.map(item => item.id === formData.value.id ? formData.value : item)
// drawer.value = false
// })
// .catch((err) => {
// console.error('更新失败:', err);
// })
// }
}
// 分页切换
const handleCurrentChange = (val) => {
queryData.value.page = val
initData(queryData.value)
}
const editorClick = (item) => {
dialogVisible.value = true
dialogData.FormData = item
console.log(dialogData.FormData)
dialogData.isView = false
dialogData.title = '编辑'
initData()
}
const ItemView = (item) => {
dialogVisible.value = true
dialogData.FormData = item
dialogData.isView = false
dialogData.title = ''
// 编辑项
const editItem = (item) => {
formData.value = { ...item }
console.log('aaa', formData.value.carouselImage);
console.log('bbb', formData.value.details);
// fileBannerList.value.push(formData.value.carouselImage);
// fileDetail.value.push(formData.value.details);
drawer.value = true;
drawerEdit.value = true;
}
const DeleteItem = async (index) => {
const row = tableData.value[index]; // 获取要删除的行
console.log("调试:row=",row)
const id = row.id; // 假设行数据中有一个名为 `id` 的属性
// 调用 delRecord 函数并等待其完成
await delGoods(id).then((res) => {
// 如果 delRecord 成功,则从 tableData 中移除该行
tableData.value.splice(index, 1);
});
};
const cancelEvent = () => {
console.log('cancel!')
// 查看项
const viewItem = (item) => {
console.log('查看项:', item)
}
const setDialogWidth = () => {
console.log(document.body.clientWidth)
var val = document.body.clientWidth
const def = 800 // 默认宽度
if (val < def) {
dialogWidth.value = '100%'
} else {
dialogWidth.value = def + 'px'
}
// 删除项
const deleteItem = (index) => {
tableData.value.splice(index, 1)
ElMessage({
message: '删除成功',
type: 'success',
})
}
// 进入页面加载
onMounted(() => {
setDialogWidth()
window.onresize = () => {
return (() => {
setDialogWidth()
})()
}
initData()
})
</script>
<style lang="scss" scoped>
.henader-card {
.header-card {
margin-bottom: 20px;
}
.icon-view {
font-size: 20px;
color: #673ab7;
margin: 0 10px;
.el-button--text {
margin-right: 15px;
}
.icon-edit {
font-size: 20px;
color: #2f60c2;
margin: 0 10px;
.el-select {
width: 300px;
}
.icon-dele {
font-size: 20px;
color: #ff5722;
.el-input {
width: 300px;
}
.dialog-footer button:first-child {
margin-right: 10px;
}
.mt-4 {
float: right;
text-align: right;
margin-top: 20px;
margin-bottom: 20px;
}
.el-button--text {
margin-right: 15px;
}
.el-select {
width: 300px;
}
.el-input {
width: 300px;
}
.dialog-footer button:first-child {
margin-right: 10px;
}
</style>
+9 -8
View File
@@ -1,10 +1,5 @@
export const options = [
{
label: '标题图片',
props: 'carouselImage',
width: '200',
align: 'left'
},
{
label: '服务名称',
props: 'goodsName',
@@ -16,9 +11,15 @@ export const options = [
props: 'price',
width: '150',
align: 'left'
},
{
label: '标题图片',
props: 'carouselImage',
width: '200',
align: 'left'
},
{
label: '服务说明',
label: '服务详情',
props: 'details',
width: 'auto',
align: 'left',
@@ -27,7 +28,7 @@ export const options = [
{
label: '操作',
props: 'actions',
width: '150',
width: '300',
align: 'center',
fixed: 'right',
}
+1 -1
View File
@@ -123,7 +123,7 @@
<el-card class="mt10">
<el-table
ref="table"
ref="table"
:data="tableData"
:default-sort="{ prop: 'date', order: 'descending' }"
:header-cell-style="{ backgroundColor: '#ecf5ff' }"
+5
View File
@@ -122,6 +122,11 @@ const initData = () => {
tableData.value = columnData.value;
// 获取用户列表
getUserList(queryData.value).then((res) => {
console.log('用户', res.data);
});
// orderLists(queryData.value).then((res) => {
// console.log(res.data.data)
// // total.value = res.data.data.total
+6
View File
@@ -166,6 +166,12 @@ const initData = () => {
tableData.value = columnData.value;
// 获取维修工程师列表
getUserList(queryData.value).then((res) => {
console.log('用户', res.data);
});
// orderLists(queryData.value).then((res) => {
// console.log(res.data.data)
// // total.value = res.data.data.total
+15 -14
View File
@@ -141,19 +141,15 @@ import {
} from '@element-plus/icons-vue'
import {nextTick, onMounted, reactive, ref} from 'vue'
// 示例数据
// import {options} from './options.js'
import {getApplyList, reject, approve} from "../../api/modules/postApply";
import {options} from './options.js'
import {getUserList} from "../../api/modules/user";
const tableData = ref([])
const dataList = ref([])
const table = ref()
const tabclickIndex = ref()
const isExpand = ref(false)
// 示例数据
// const exampleData = ref(JSON.parse(JSON.stringify(options)))
const columnData = ref(JSON.parse(JSON.stringify(options)))
const disabled = ref(false)
const dialogVisible = ref(false)
const total = ref(0)
@@ -168,14 +164,19 @@ const queryData = ref({
const initData = () => {
// 加载示例数据
// tableData.value = exampleData.value;
tableData.value = columnData.value;
getApplyList(queryData.value).then((res) => {
console.log(res.data.data)
total.value = res.data.total
tableData.value = res.data
})
// 获取勘察工程师列表
getUserList(queryData.value).then((res) => {
console.log('用户', res.data);
});
// orderLists(queryData.value).then((res) => {
// console.log(res.data.data)
// // total.value = res.data.data.total
// tableData.value = res.data.data
// })
}
const itemEditHanld = (item) => {
item.itemEdit = !item.itemEdit