From 6ad342cb2e1ede2d36794aef47d4c0f377a9a567 Mon Sep 17 00:00:00 2001 From: Lei OT Date: Tue, 4 Jun 2024 16:59:20 +0800 Subject: [PATCH] refactor: Feedback CustomerDetail --- src/main.jsx | 2 +- src/stores/Feedback.js | 57 ++++ src/utils/request.js | 10 +- src/views/feedback/CustomerDetail.jsx | 395 +++++++++++++------------- src/views/feedback/Index.jsx | 10 +- 5 files changed, 273 insertions(+), 201 deletions(-) diff --git a/src/main.jsx b/src/main.jsx index 1e4e687..c29c9b4 100644 --- a/src/main.jsx +++ b/src/main.jsx @@ -51,8 +51,8 @@ const router = createBrowserRouter([ { path: "account/change-password", element: }, { path: "account/profile", element: }, { path: "feedback", element: }, - { path: "feedback/:GRI_SN/:RefNo", element: }, { path: "feedback/:GRI_SN/:CII_SN/:RefNo", element: }, + { path: "feedback/:GRI_SN/:RefNo", element: }, { path: "report", element: }, { path: "notice", element: }, { path: "notice/:CCP_BLID", element: }, diff --git a/src/stores/Feedback.js b/src/stores/Feedback.js index 9b4ac1c..17f5313 100644 --- a/src/stores/Feedback.js +++ b/src/stores/Feedback.js @@ -9,6 +9,62 @@ import { devtools } from 'zustand/middleware'; const { HT_HOST } = config; +export const getFeedbackDetail = async (VEI_SN, GRI_SN) => { + const { errcode, Result, Result1 } = await fetchJSON(`${HT_HOST}/service-Cooperate/Cooperate/getFeedbackDetail`, { VEI_SN, GRI_SN }); + return errcode !== 0 ? {} : { feedbackRate: Result, feedbackReview: Result1 }; +}; +export const getCustomerFeedbackDetail = async (VEI_SN, GRI_SN, CII_SN) => { + const json = await fetchJSON(`${HT_HOST}/service-CooperateSOA/get_feedback_service_item`, { VEI_SN, GRI_SN, city_sn: CII_SN, lgc: 1 }); + const _feedbackItemList = json.feedbackItemList; + const itemGroup = groupBy(json.feedbackItemList, 'type'); + const serviceItem = { + HWO_Guide: itemGroup?.W || [], + HWO_Driver: itemGroup?.Y || [], + HWO_Activity: [ + ...(itemGroup['7'] || []), + ...(itemGroup.G || []), + ...(itemGroup.C || []), + ...(itemGroup.A || []).map((ele) => ({ ...ele, Describe: ele.name })), + ], + }; + const OtherThoughts = json.feedbackEvaluation[0]?.otherComments || ''; + const PhotoPermission = json.feedbackEvaluation[0]?.usePhotos || ''; + const signatureData = json.feedbackEvaluation[0]?.signatureDataUrl || ''; + const cityName = json.group[0]?.cityName || ''; + + return { ...serviceItem, OtherThoughts, PhotoPermission, signatureData, cityName }; // feedbackServiceRate +}; +export const getFeedbackImages = async (VEI_SN, GRI_SN) => { + const { errcode, result } = await fetchJSON(`${HT_HOST}/service-fileServer/ListFile`, { VEI_SN, GRI_SN }); + return errcode !== 0 ? {} : result.map((data, index) => { + return { + uid: -index, //用负数,防止添加删除的时候错误 + name: data.file_name, + status: "done", + url: data.file_url, + }; + }); +}; + +export const removeFeedbackImages = async (fileurl) => { + const { errcode, Result } = await fetchJSON(`${HT_HOST}/service-fileServer/FileDelete`, { fileurl }); + return errcode !== 0 ? {} : Result; +}; +export const getFeedbackInfo = async (VEI_SN, GRI_SN) => { + const { errcode, Result } = await fetchJSON(`${HT_HOST}/service-Cooperate/Cooperate/getVEIFeedbackInfo`, { VEI_SN, GRI_SN }); + return errcode !== 0 ? {} : Result; +}; + +export const postFeedbackInfo = async (VEI_SN, GRI_SN, EOI_SN, info_content) => { + const postbody = { VEI_SN, GRI_SN, EOI_SN, FeedbackInfo: info_content }; + const formData = new FormData(); + Object.keys(postbody).forEach(key => { + formData.append(key, postbody[key]); + }); + const { errcode, Result } = await postForm(`${HT_HOST}/service-CooperateSOA/FeedbackInfo`, formData); + return errcode !== 0 ? {} : Result; +}; + const initialState = { loading: false, search_date_start: dayjs().subtract(2, 'M').startOf('M'), @@ -37,6 +93,7 @@ const useFeedbackStore = create( async fetchFeedbackList(veisn, EOI_Group_Name, TimeStart, TimeEnd) { const { setLoading, setFeedbackList } = get(); + setLoading(true); const searchParams = { PageSize: 2000, PageIndex: 1, diff --git a/src/utils/request.js b/src/utils/request.js index de0eafa..c83a272 100644 --- a/src/utils/request.js +++ b/src/utils/request.js @@ -70,8 +70,8 @@ export function fetchText(url) { export function fetchJSON(url, data = {}) { const initParams = getRequestInitParams(); - Object.assign(data, initParams); - const params = data ? new URLSearchParams(data).toString() : ''; + const params4get = Object.assign({}, initParams, data); + const params = params4get ? new URLSearchParams(params4get).toString() : ''; const ifp = url.includes('?') ? '&' : '?'; const headerObj = getRequestHeader(); const fUrl = params !== '' ? `${url}${ifp}${params}` : url; @@ -90,6 +90,12 @@ export function fetchJSON(url, data = {}) { } export function postForm(url, data) { + const initParams = getRequestInitParams(); + Object.keys(initParams).forEach(key => { + if (! data.has(key)) { + data.append(key, initParams[key]); + } + }); const headerObj = getRequestHeader() return fetch(url, { method: 'POST', diff --git a/src/views/feedback/CustomerDetail.jsx b/src/views/feedback/CustomerDetail.jsx index 235141c..1a61dcd 100644 --- a/src/views/feedback/CustomerDetail.jsx +++ b/src/views/feedback/CustomerDetail.jsx @@ -1,198 +1,207 @@ -import { useParams, useNavigate } from "react-router-dom"; -import { useEffect } from "react"; -import { observer } from "mobx-react"; -import { toJS, runInAction } from "mobx"; -import { Row, Col, Space, Button, Divider, Form, Typography, Rate, Radio, Upload, Input, App, Card } from "antd"; -import { useStore } from "../../stores/StoreContext.js"; -import { PlusOutlined } from "@ant-design/icons"; +import { useParams, useNavigate } from 'react-router-dom'; +import { useEffect, useState } from 'react'; +import { Row, Col, Space, Button, Divider, Form, Typography, Rate, Radio, Upload, Input, App, Card } from 'antd'; +import { PlusOutlined } from '@ant-design/icons'; +import * as config from '@/config'; +import useAuthStore from '@/stores/Auth'; +import { getFeedbackDetail, getCustomerFeedbackDetail, getFeedbackImages, getFeedbackInfo, removeFeedbackImages, postFeedbackInfo } from '@/stores/Feedback'; + const { Title, Text, Paragraph } = Typography; -import * as config from "@/config"; function Detail() { - const navigate = useNavigate(); - const { GRI_SN, RefNo, CII_SN } = useParams(); - const { feedbackStore, authStore } = useStore(); - const { feedbackReview, feedbackImages, feedbackInfo, feedbackServiceRate: feedbackRate } = feedbackStore; - const desc = ["none", "Unacceptable", "Poor", "Fair", "Very Good", "Excellent"]; - const { notification } = App.useApp(); - const [form] = Form.useForm(); - - useEffect(() => { - console.info("Detail.useEffect: " + GRI_SN); - feedbackStore.getFeedbackDetail(authStore.login.travelAgencyId, GRI_SN); - feedbackStore.getCustomerFeedbackDetail(authStore.login.travelAgencyId, GRI_SN, CII_SN); - feedbackStore.getFeedbackImages(authStore.login.travelAgencyId, GRI_SN); - feedbackStore.getFeedbackInfo(authStore.login.travelAgencyId, GRI_SN).then(v => { - form.setFieldsValue({ info_content: v.EEF_Content }); - }); - }, [GRI_SN]); - - const HWO_Guide = feedbackRate && feedbackRate.HWO_Guide ? feedbackRate.HWO_Guide : []; - const HWO_Driver = feedbackRate && feedbackRate.HWO_Driver ? feedbackRate.HWO_Driver : []; - const HWO_Activity = feedbackRate && feedbackRate.HWO_Activity ? feedbackRate.HWO_Activity : []; - const OtherThoughts = feedbackRate && feedbackRate.OtherThoughts ? feedbackRate.OtherThoughts : ""; - const signatureData = feedbackRate && feedbackRate.signatureData ? feedbackRate.signatureData : ""; - const PhotoPermission = feedbackRate?.PhotoPermission === 1; - const cityName = feedbackRate.cityName; - const ECI_Content = feedbackReview && feedbackReview.ECI_Content ? feedbackReview.ECI_Content : "None"; - const fileList = toJS(feedbackImages); - - const handleChange = info => { - let newFileList = [...info.fileList]; - newFileList = newFileList.map(file => { - if (file.response && file.response.result) { - file.url = file.response.result.file_url; - } - return file; - }); - runInAction(() => { - feedbackStore.feedbackImages = newFileList; - }); - }; - - const handRemove = info => { - return feedbackStore.removeFeedbackImages(info.url); - }; - - const onFinish = values => { - console.log("Success:", values); - if (values) { - feedbackStore.postFeedbackInfo(feedbackInfo.EEF_VEI_SN, feedbackInfo.EEF_GRI_SN, feedbackInfo.EEF_EOI_SN, values.info_content).then(() => { - notification.success({ - message: `Notification`, - description: "Submit Successful", - placement: "top", - duration: 4, - }); - }); - } - }; - - return ( - - - - - - - - - - - - - Post Survey {RefNo} in {cityName}}> -
- How satisfied were you with your tour guide? - {HWO_Guide.map(ele => ( - - - - {desc[ele.rate]} - - - ))} - - How about the Driver and Car/Van? - {HWO_Driver.map(ele => ( - - - - {desc[ele.rate]} - - - ))} - - General Experience with: - {HWO_Activity.map(ele => ( - - - - {desc[ele.rate]} - - - ))} - - Would you like to give us permission to use the photos taken by the tour guide(s) during your trip which contain your portrait? - - {PhotoPermission ? ( - <> - Yes - No - - ) : ( - <> - Yes - No - - )} - - Other thoughts you want to share with us: - {OtherThoughts} - Signature: - {signatureData ? customer signature : null} - -
- - -
- - - - - - External Reviews}> - {ECI_Content} - - - - - - - - - Feedback from local agent}> -
- - -
- -
Upload photos
-
-
-
- - - - - - -
-
- - -
-
- ); + const navigate = useNavigate(); + const { GRI_SN, RefNo, CII_SN } = useParams(); + const [travelAgencyId, token] = useAuthStore((state) => [state.loginUser.travelAgencyId, state.loginUser.token]); + const desc = ['none', 'Unacceptable', 'Poor', 'Fair', 'Very Good', 'Excellent']; + const { notification } = App.useApp(); + const [form] = Form.useForm(); + + const [feedbackRate, setFeedbackRate] = useState({}); + const [feedbackReview, setFeedbackReview] = useState({}); + const [feedbackImages, setFeedbackImages] = useState([]); + const [feedbackInfo, setFeedbackInfo] = useState({}); + + useEffect(() => { + console.info('Detail.useEffect: ' + GRI_SN); + getFeedbackDetail(travelAgencyId, GRI_SN).then((res) => { + setFeedbackRate(res.feedbackRate); + setFeedbackReview(res.feedbackReview); + }); + getCustomerFeedbackDetail(travelAgencyId, GRI_SN, CII_SN).then((res) => setFeedbackRate(res)); + getFeedbackImages(travelAgencyId, GRI_SN).then((res) => setFeedbackImages(res)); + getFeedbackInfo(travelAgencyId, GRI_SN).then((v) => { + form.setFieldsValue({ info_content: v.EEF_Content }); + setFeedbackInfo(v); + }); + }, [GRI_SN]); + + const HWO_Guide = feedbackRate && feedbackRate.HWO_Guide ? feedbackRate.HWO_Guide : []; + const HWO_Driver = feedbackRate && feedbackRate.HWO_Driver ? feedbackRate.HWO_Driver : []; + const HWO_Activity = feedbackRate && feedbackRate.HWO_Activity ? feedbackRate.HWO_Activity : []; + const OtherThoughts = feedbackRate && feedbackRate.OtherThoughts ? feedbackRate.OtherThoughts : ''; + const signatureData = feedbackRate && feedbackRate.signatureData ? feedbackRate.signatureData : ''; + const PhotoPermission = feedbackRate?.PhotoPermission === 1; + const cityName = feedbackRate?.cityName || ''; + const ECI_Content = feedbackReview && feedbackReview.ECI_Content ? feedbackReview.ECI_Content : 'None'; + const fileList = feedbackImages; + + const handleChange = (info) => { + let newFileList = [...info.fileList]; + newFileList = newFileList.map((file) => { + if (file.response && file.response.result) { + file.url = file.response.result.file_url; + } + return file; + }); + setFeedbackImages(newFileList); + }; + + const handRemove = (info) => { + return removeFeedbackImages(info.url); + }; + + const onFinish = (values) => { + // console.log("Success:", values); + if (values) { + postFeedbackInfo(feedbackInfo.EEF_VEI_SN, feedbackInfo.EEF_GRI_SN, feedbackInfo.EEF_EOI_SN, values.info_content).then(() => { + notification.success({ + message: `Notification`, + description: 'Submit Successful', + placement: 'top', + duration: 4, + }); + }); + } + }; + + return ( + + + + + + + + + + + + Post Survey {RefNo} in {cityName} + + }> +
+ How satisfied were you with your tour guide? + {HWO_Guide.map((ele) => ( + + + + {desc[ele.rate]} + + + ))} + + How about the Driver and Car/Van? + {HWO_Driver.map((ele) => ( + + + + {desc[ele.rate]} + + + ))} + + General Experience with: + {HWO_Activity.map((ele) => ( + + + + {desc[ele.rate]} + + + ))} + + Would you like to give us permission to use the photos taken by the tour guide(s) during your trip which contain your portrait? + + {PhotoPermission ? ( + <> + Yes + No + + ) : ( + <> + Yes + No + + )} + + Other thoughts you want to share with us: + {OtherThoughts} + Signature: + {signatureData ? customer signature : null} +
+
+ + +
+ + + + + External Reviews}> + {ECI_Content} + + + + + + + + + Feedback from local agent}> +
+ + +
+ +
Upload photos
+
+
+
+ + + + + + +
+
+ + +
+
+ ); } -export default observer(Detail); +export default Detail; diff --git a/src/views/feedback/Index.jsx b/src/views/feedback/Index.jsx index 54f49d5..3e8a5f0 100644 --- a/src/views/feedback/Index.jsx +++ b/src/views/feedback/Index.jsx @@ -1,9 +1,9 @@ import { NavLink } from 'react-router-dom'; import { useEffect } from 'react'; import { Row, Col, Space, Table, App } from 'antd'; -import { useStore } from '@/stores/StoreContext.js'; import { useTranslation } from 'react-i18next'; import SearchForm from '@/components/SearchForm'; +import useAuthStore from '@/stores/Auth'; import useFeedbackStore from '@/stores/Feedback'; import dayjs from 'dayjs'; @@ -47,9 +47,9 @@ const feedbackListColumns = [ function Index() { const { t } = useTranslation(); const { notification } = App.useApp(); - const { feedbackStore, authStore } = useStore(); - const [feedbackList, fetchFeedbackList] = useFeedbackStore((state) => [state.feedbackList, state.fetchFeedbackList]); + const travelAgencyId = useAuthStore((state) => state.loginUser.travelAgencyId) + const [loading, feedbackList, fetchFeedbackList] = useFeedbackStore((state) => [state.loading, state.feedbackList, state.fetchFeedbackList]); const showTotal = (total) => `Total ${total} items`; @@ -78,12 +78,12 @@ function Index() { }, }} onSubmit={(err, formVal, filedsVal) => { - fetchFeedbackList(authStore.login.travelAgencyId, formVal.referenceNo, formVal.startdate, formVal.endtime); + fetchFeedbackList(travelAgencyId, formVal.referenceNo, formVal.startdate, formVal.endtime); }} /> - +