From 4cc526979b4417eb336ad090812cbc3666821245 Mon Sep 17 00:00:00 2001 From: gaoluyang <2820782392@qq.com> Date: 星期三, 30 七月 2025 13:52:16 +0800 Subject: [PATCH] 1.反馈登记-开发联调 --- src/views/customerService/feedbackRegistration/components/formDia.vue | 166 ++++++++++++ src/views/customerService/afterSalesHandling/components/formDia.vue | 166 ++++++++++++ src/views/customerService/feedbackRegistration/index.vue | 201 +++++++++++++++ src/api/customerService/index.js | 35 ++ src/views/customerService/afterSalesHandling/index.vue | 200 +++++++++++++++ 5 files changed, 768 insertions(+), 0 deletions(-) diff --git a/src/api/customerService/index.js b/src/api/customerService/index.js new file mode 100644 index 0000000..1f9a69d --- /dev/null +++ b/src/api/customerService/index.js @@ -0,0 +1,35 @@ +// 鍞悗鏈嶅姟 +import request from "@/utils/request"; + +// 鍙嶉鐧昏-鍒嗛〉鏌ヨ +export function afterSalesServiceListPage(query) { + return request({ + url: '/afterSalesService/listPage', + method: 'get', + params: query, + }) +} +// 鍙嶉鐧昏-鍒犻櫎 +export function afterSalesServiceDelete(query) { + return request({ + url: '/afterSalesService/delete', + method: 'delete', + data: query, + }) +} +// 鍙嶉鐧昏-鍒犻櫎 +export function afterSalesServiceAdd(query) { + return request({ + url: '/afterSalesService/add', + method: 'post', + data: query, + }) +} +// 鍙嶉鐧昏-鍒犻櫎 +export function afterSalesServiceUpdate(query) { + return request({ + url: '/afterSalesService/update', + method: 'post', + data: query, + }) +} \ No newline at end of file diff --git a/src/views/customerService/afterSalesHandling/components/formDia.vue b/src/views/customerService/afterSalesHandling/components/formDia.vue new file mode 100644 index 0000000..08eacfa --- /dev/null +++ b/src/views/customerService/afterSalesHandling/components/formDia.vue @@ -0,0 +1,166 @@ +<template> + <div> + <el-dialog + v-model="dialogFormVisible" + title="璁惧鑳借��" + width="70%" + @close="closeDia" + > + <el-form + :model="form" + label-width="140px" + label-position="top" + :rules="rules" + ref="formRef" + > + <el-row :gutter="30"> + <el-col :span="12"> + <el-form-item label="鍙嶉鏃堕棿锛�" prop="feedbackDate"> + <el-date-picker + style="width: 100%" + v-model="form.feedbackDate" + value-format="YYYY-MM-DD" + format="YYYY-MM-DD" + type="date" + placeholder="璇烽�夋嫨" + clearable + /> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="鐧昏浜猴細" prop="checkUserId"> + <el-select + v-model="form.checkUserId" + placeholder="璇烽�夋嫨" + clearable + > + <el-option + v-for="item in userList" + :key="item.userId" + :label="item.nickName" + :value="item.userId" + ></el-option> + </el-select> + </el-form-item> + </el-col> + </el-row> + <el-row :gutter="30"> + <el-col :span="12"> + <el-form-item label="瀹㈡埛鍚嶇О锛�" prop="customerName"> + <el-input + v-model="form.customerName" + placeholder="璇疯緭鍏�" + clearable + /> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="闂鎻忚堪锛�" prop="proDesc"> + <el-input + v-model="form.proDesc" + placeholder="璇疯緭鍏�" + clearable + /> + </el-form-item> + </el-col> + </el-row> + </el-form> + <template #footer> + <div class="dialog-footer"> + <el-button type="primary" @click="submitForm">纭</el-button> + <el-button @click="closeDia">鍙栨秷</el-button> + </div> + </template> + </el-dialog> + </div> +</template> + +<script setup> +import {ref} from "vue"; +import useUserStore from "@/store/modules/user.js"; +import {userListNoPageByTenantId} from "@/api/system/user.js"; +import {afterSalesServiceAdd, afterSalesServiceUpdate} from "@/api/customerService/index.js"; +const { proxy } = getCurrentInstance() +const emit = defineEmits(['close']) +const dialogFormVisible = ref(false); +const operationType = ref('') +const userStore = useUserStore(); + +const data = reactive({ + form: { + feedbackDate: "", + checkUserId: "", + customerName: "", + proDesc: "", + }, + rules: { + feedbackDate: [{required: true, message: "璇烽�夋嫨", trigger: "change"}], + checkUserId: [{required: true, message: "璇烽�夋嫨", trigger: "change"}], + customerName: [{required: true, message: "璇疯緭鍏�", trigger: "blur"}], + proDesc: [{required: true, message: "璇疯緭鍏�", trigger: "blur"}], + } +}) +const { form, rules } = toRefs(data); +const userList = ref([]) + +// 鎵撳紑寮规 +const openDialog = (type, row) => { + operationType.value = type; + dialogFormVisible.value = true; + form.value = {} + proxy.resetForm("formRef"); + form.value.checkUserId = userStore.id; + form.value.feedbackDate = getCurrentDate(); + userListNoPageByTenantId().then((res) => { + userList.value = res.data; + }); + if (type === "edit") { + form.value = {...row} + } +} +// const setName = (code) => { +// const index = userList.value.findIndex(item => item.deviceModel === code); +// if (index > -1) { +// console.log(userList) +// form.value.name = userList.value[index].deviceName; +// } +// } +const submitForm = () => { + proxy.$refs["formRef"].validate(valid => { + if (valid) { + if (operationType.value === "add") { + afterSalesServiceAdd(form.value).then(response => { + proxy.$modal.msgSuccess("鏂板鎴愬姛") + closeDia() + }) + } else { + afterSalesServiceUpdate(form.value).then(response => { + proxy.$modal.msgSuccess("淇敼鎴愬姛") + closeDia() + }) + } + } + }) +} +// 鍏抽棴寮规 +const closeDia = () => { + proxy.resetForm("formRef"); + dialogFormVisible.value = false; + emit('close') +}; +// 鑾峰彇褰撳墠鏃ユ湡骞舵牸寮忓寲涓� YYYY-MM-DD +function getCurrentDate() { + const today = new Date(); + const year = today.getFullYear(); + const month = String(today.getMonth() + 1).padStart(2, "0"); // 鏈堜唤浠�0寮�濮� + const day = String(today.getDate()).padStart(2, "0"); + return `${year}-${month}-${day}`; +} +defineExpose({ + openDialog, +}); +</script> + +<style scoped> + +</style> \ No newline at end of file diff --git a/src/views/customerService/afterSalesHandling/index.vue b/src/views/customerService/afterSalesHandling/index.vue new file mode 100644 index 0000000..50f250e --- /dev/null +++ b/src/views/customerService/afterSalesHandling/index.vue @@ -0,0 +1,200 @@ +<template> + <div class="app-container"> + <div class="search_form"> + <div> + <span class="search_title">璁惧鍚嶇О锛�</span> + <el-input + v-model="searchForm.name" + style="width: 240px" + placeholder="璇疯緭鍏�" + @change="handleQuery" + clearable + :prefix-icon="Search" + /> + <el-button type="primary" @click="handleQuery" style="margin-left: 10px" + >鎼滅储</el-button + > + </div> + <div> + <el-button type="primary" @click="openForm('add')">鏂板</el-button> + <el-button type="danger" plain @click="handleDelete">鍒犻櫎</el-button> + </div> + </div> + <div class="table_list"> + <PIMTable + rowKey="id" + :column="tableColumn" + :tableData="tableData" + :page="page" + :isSelection="true" + @selection-change="handleSelectionChange" + :tableLoading="tableLoading" + @pagination="pagination" + ></PIMTable> + </div> + <form-dia ref="formDia" @close="handleQuery"></form-dia> + </div> +</template> + +<script setup> +import {Search} from "@element-plus/icons-vue"; +import {onMounted, ref} from "vue"; +import FormDia from "@/views/customerService/feedbackRegistration/components/formDia.vue"; +import {ElMessageBox} from "element-plus"; +import {afterSalesServiceDelete, afterSalesServiceListPage} from "@/api/customerService/index.js"; +import useUserStore from "@/store/modules/user.js"; +const { proxy } = getCurrentInstance(); +const userStore = useUserStore() + +const data = reactive({ + searchForm: { + name: "", + }, +}); +const { searchForm } = toRefs(data); + +const tableColumn = ref([ + { + label: "澶勭悊鐘舵��", + prop: "status", + dataType: "tag", + formatData: (params) => { + if (params == 1) { + return "寰呭鐞�"; + } else if (params == 2) { + return "宸插鐞�"; + } else { + return null; + } + }, + formatType: (params) => { + if (params == 1) { + return "danger"; + } else if (params == 2) { + return "success"; + } else { + return null; + } + }, + }, + { + label: "鍙嶉鏃ユ湡", + prop: "feedbackDate", + width: 150, + }, + { + label: "鐧昏浜�", + prop: "checkNickName", + }, + { + label: "瀹㈡埛鍚嶇О", + prop: "customerName", + width: 200, + }, + { + label: "闂鎻忚堪", + prop: "proDesc", + width:300 + }, + { + label: "鍏宠仈閮ㄩ棬", + prop: "deptName", + width: 200, + }, + { + dataType: "action", + label: "鎿嶄綔", + align: "center", + fixed: 'right', + operation: [ + { + name: "缂栬緫", + type: "text", + clickFun: (row) => { + openForm("edit", row); + }, + disabled: (row) => { + return row.checkUserId !== userStore.id || row.status !== 1 + } + }, + ], + }, +]); +const tableData = ref([]); +const tableLoading = ref(false); +const page = reactive({ + current: 1, + size: 100, + total: 0, +}); +const selectedRows = ref([]); + +// 琛ㄦ牸閫夋嫨鏁版嵁 +const handleSelectionChange = (selection) => { + selectedRows.value = selection; +}; +const formDia = ref() + +// 鏌ヨ鍒楄〃 +/** 鎼滅储鎸夐挳鎿嶄綔 */ +const handleQuery = () => { + page.current = 1; + getList(); +}; +const pagination = (obj) => { + page.current = obj.page; + page.size = obj.limit; + getList(); +}; +const getList = () => { + tableLoading.value = true; + afterSalesServiceListPage({ ...searchForm.value, ...page }).then((res) => { + tableLoading.value = false; + tableData.value = res.data.records; + page.total = res.data.total; + }); +}; + +// 鎵撳紑寮规 +const openForm = (type, row) => { + nextTick(() => { + formDia.value?.openDialog(type, row) + }) +}; + +const handleDelete = () => { + let ids = []; + if (selectedRows.value.length > 0) { + ids = selectedRows.value.map((item) => item.id); + } else { + proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁"); + return; + } + ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "鍒犻櫎鎻愮ず", { + confirmButtonText: "纭", + cancelButtonText: "鍙栨秷", + type: "warning", + }) + .then(() => { + tableLoading.value = true; + afterSalesServiceDelete(ids) + .then((res) => { + proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛"); + getList(); + }) + .finally(() => { + tableLoading.value = false; + }); + }) + .catch(() => { + proxy.$modal.msg("宸插彇娑�"); + }); +}; +onMounted(() => { + getList(); +}); +</script> + +<style scoped> + +</style> \ No newline at end of file diff --git a/src/views/customerService/feedbackRegistration/components/formDia.vue b/src/views/customerService/feedbackRegistration/components/formDia.vue new file mode 100644 index 0000000..08eacfa --- /dev/null +++ b/src/views/customerService/feedbackRegistration/components/formDia.vue @@ -0,0 +1,166 @@ +<template> + <div> + <el-dialog + v-model="dialogFormVisible" + title="璁惧鑳借��" + width="70%" + @close="closeDia" + > + <el-form + :model="form" + label-width="140px" + label-position="top" + :rules="rules" + ref="formRef" + > + <el-row :gutter="30"> + <el-col :span="12"> + <el-form-item label="鍙嶉鏃堕棿锛�" prop="feedbackDate"> + <el-date-picker + style="width: 100%" + v-model="form.feedbackDate" + value-format="YYYY-MM-DD" + format="YYYY-MM-DD" + type="date" + placeholder="璇烽�夋嫨" + clearable + /> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="鐧昏浜猴細" prop="checkUserId"> + <el-select + v-model="form.checkUserId" + placeholder="璇烽�夋嫨" + clearable + > + <el-option + v-for="item in userList" + :key="item.userId" + :label="item.nickName" + :value="item.userId" + ></el-option> + </el-select> + </el-form-item> + </el-col> + </el-row> + <el-row :gutter="30"> + <el-col :span="12"> + <el-form-item label="瀹㈡埛鍚嶇О锛�" prop="customerName"> + <el-input + v-model="form.customerName" + placeholder="璇疯緭鍏�" + clearable + /> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="闂鎻忚堪锛�" prop="proDesc"> + <el-input + v-model="form.proDesc" + placeholder="璇疯緭鍏�" + clearable + /> + </el-form-item> + </el-col> + </el-row> + </el-form> + <template #footer> + <div class="dialog-footer"> + <el-button type="primary" @click="submitForm">纭</el-button> + <el-button @click="closeDia">鍙栨秷</el-button> + </div> + </template> + </el-dialog> + </div> +</template> + +<script setup> +import {ref} from "vue"; +import useUserStore from "@/store/modules/user.js"; +import {userListNoPageByTenantId} from "@/api/system/user.js"; +import {afterSalesServiceAdd, afterSalesServiceUpdate} from "@/api/customerService/index.js"; +const { proxy } = getCurrentInstance() +const emit = defineEmits(['close']) +const dialogFormVisible = ref(false); +const operationType = ref('') +const userStore = useUserStore(); + +const data = reactive({ + form: { + feedbackDate: "", + checkUserId: "", + customerName: "", + proDesc: "", + }, + rules: { + feedbackDate: [{required: true, message: "璇烽�夋嫨", trigger: "change"}], + checkUserId: [{required: true, message: "璇烽�夋嫨", trigger: "change"}], + customerName: [{required: true, message: "璇疯緭鍏�", trigger: "blur"}], + proDesc: [{required: true, message: "璇疯緭鍏�", trigger: "blur"}], + } +}) +const { form, rules } = toRefs(data); +const userList = ref([]) + +// 鎵撳紑寮规 +const openDialog = (type, row) => { + operationType.value = type; + dialogFormVisible.value = true; + form.value = {} + proxy.resetForm("formRef"); + form.value.checkUserId = userStore.id; + form.value.feedbackDate = getCurrentDate(); + userListNoPageByTenantId().then((res) => { + userList.value = res.data; + }); + if (type === "edit") { + form.value = {...row} + } +} +// const setName = (code) => { +// const index = userList.value.findIndex(item => item.deviceModel === code); +// if (index > -1) { +// console.log(userList) +// form.value.name = userList.value[index].deviceName; +// } +// } +const submitForm = () => { + proxy.$refs["formRef"].validate(valid => { + if (valid) { + if (operationType.value === "add") { + afterSalesServiceAdd(form.value).then(response => { + proxy.$modal.msgSuccess("鏂板鎴愬姛") + closeDia() + }) + } else { + afterSalesServiceUpdate(form.value).then(response => { + proxy.$modal.msgSuccess("淇敼鎴愬姛") + closeDia() + }) + } + } + }) +} +// 鍏抽棴寮规 +const closeDia = () => { + proxy.resetForm("formRef"); + dialogFormVisible.value = false; + emit('close') +}; +// 鑾峰彇褰撳墠鏃ユ湡骞舵牸寮忓寲涓� YYYY-MM-DD +function getCurrentDate() { + const today = new Date(); + const year = today.getFullYear(); + const month = String(today.getMonth() + 1).padStart(2, "0"); // 鏈堜唤浠�0寮�濮� + const day = String(today.getDate()).padStart(2, "0"); + return `${year}-${month}-${day}`; +} +defineExpose({ + openDialog, +}); +</script> + +<style scoped> + +</style> \ No newline at end of file diff --git a/src/views/customerService/feedbackRegistration/index.vue b/src/views/customerService/feedbackRegistration/index.vue new file mode 100644 index 0000000..95e064e --- /dev/null +++ b/src/views/customerService/feedbackRegistration/index.vue @@ -0,0 +1,201 @@ +<template> + <div class="app-container"> + <div class="search_form"> + <div> + <span class="search_title">鍙嶉鏃ユ湡锛�</span> + <el-date-picker + style="width: 100%" + v-model="searchForm.feedbackDate" + value-format="YYYY-MM-DD" + format="YYYY-MM-DD" + type="date" + placeholder="璇烽�夋嫨" + clearable + /> + <el-button type="primary" @click="handleQuery" style="margin-left: 10px" + >鎼滅储</el-button + > + </div> + <div> + <el-button type="primary" @click="openForm('add')">鏂板</el-button> + <el-button type="danger" plain @click="handleDelete">鍒犻櫎</el-button> + </div> + </div> + <div class="table_list"> + <PIMTable + rowKey="id" + :column="tableColumn" + :tableData="tableData" + :page="page" + :isSelection="true" + @selection-change="handleSelectionChange" + :tableLoading="tableLoading" + @pagination="pagination" + ></PIMTable> + </div> + <form-dia ref="formDia" @close="handleQuery"></form-dia> + </div> +</template> + +<script setup> +import {Search} from "@element-plus/icons-vue"; +import {onMounted, ref} from "vue"; +import FormDia from "@/views/customerService/feedbackRegistration/components/formDia.vue"; +import {ElMessageBox} from "element-plus"; +import {afterSalesServiceDelete, afterSalesServiceListPage} from "@/api/customerService/index.js"; +import useUserStore from "@/store/modules/user.js"; +const { proxy } = getCurrentInstance(); +const userStore = useUserStore() + +const data = reactive({ + searchForm: { + feedbackDate: "", + }, +}); +const { searchForm } = toRefs(data); + +const tableColumn = ref([ + { + label: "澶勭悊鐘舵��", + prop: "status", + dataType: "tag", + formatData: (params) => { + if (params == 1) { + return "寰呭鐞�"; + } else if (params == 2) { + return "宸插鐞�"; + } else { + return null; + } + }, + formatType: (params) => { + if (params == 1) { + return "danger"; + } else if (params == 2) { + return "success"; + } else { + return null; + } + }, + }, + { + label: "鍙嶉鏃ユ湡", + prop: "feedbackDate", + width: 150, + }, + { + label: "鐧昏浜�", + prop: "checkNickName", + }, + { + label: "瀹㈡埛鍚嶇О", + prop: "customerName", + width: 200, + }, + { + label: "闂鎻忚堪", + prop: "proDesc", + width:300 + }, + { + label: "鍏宠仈閮ㄩ棬", + prop: "deptName", + width: 200, + }, + { + dataType: "action", + label: "鎿嶄綔", + align: "center", + fixed: 'right', + operation: [ + { + name: "缂栬緫", + type: "text", + clickFun: (row) => { + openForm("edit", row); + }, + disabled: (row) => { + return row.checkUserId !== userStore.id || row.status !== 1 + } + }, + ], + }, +]); +const tableData = ref([]); +const tableLoading = ref(false); +const page = reactive({ + current: 1, + size: 100, + total: 0, +}); +const selectedRows = ref([]); + +// 琛ㄦ牸閫夋嫨鏁版嵁 +const handleSelectionChange = (selection) => { + selectedRows.value = selection; +}; +const formDia = ref() + +// 鏌ヨ鍒楄〃 +/** 鎼滅储鎸夐挳鎿嶄綔 */ +const handleQuery = () => { + page.current = 1; + getList(); +}; +const pagination = (obj) => { + page.current = obj.page; + page.size = obj.limit; + getList(); +}; +const getList = () => { + tableLoading.value = true; + afterSalesServiceListPage({ ...searchForm.value, ...page }).then((res) => { + tableLoading.value = false; + tableData.value = res.data.records; + page.total = res.data.total; + }); +}; + +// 鎵撳紑寮规 +const openForm = (type, row) => { + nextTick(() => { + formDia.value?.openDialog(type, row) + }) +}; + +const handleDelete = () => { + let ids = []; + if (selectedRows.value.length > 0) { + ids = selectedRows.value.map((item) => item.id); + } else { + proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁"); + return; + } + ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "鍒犻櫎鎻愮ず", { + confirmButtonText: "纭", + cancelButtonText: "鍙栨秷", + type: "warning", + }) + .then(() => { + tableLoading.value = true; + afterSalesServiceDelete(ids) + .then((res) => { + proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛"); + getList(); + }) + .finally(() => { + tableLoading.value = false; + }); + }) + .catch(() => { + proxy.$modal.msg("宸插彇娑�"); + }); +}; +onMounted(() => { + getList(); +}); +</script> + +<style scoped> + +</style> \ No newline at end of file -- Gitblit v1.9.3