Merge branch 'main' of github.com:hainatravel/GHHub

release
赵鹏 2 years ago
commit 26e172a78c

@ -23,6 +23,7 @@ import AccountProfile from "@/views/account/Profile";
import FeedbackIndex from "@/views/feedback/Index";
import FeedbackDetail from "@/views/feedback/Detail";
import NoticeIndex from "@/views/notice/Index";
import NoticeDetail from "@/views/notice/Detail";
import InvoiceIndex from "@/views/invoice/Index";
import InvoiceDetail from "@/views/invoice/Detail";
@ -52,6 +53,7 @@ const router = createBrowserRouter([
{ path: "feedback", element: <FeedbackIndex />},
{ path: "feedback/:GRI_SN", element: <FeedbackDetail />},
{ path: "notice", element: <NoticeIndex />},
{ path: "notice/:CCP_BLID", element: <NoticeDetail />},
{ path: "invoice",element:<InvoiceIndex />},
{ path: "invoice/detail/:GMDSN/:GSN",element:<InvoiceDetail />},
]

@ -128,7 +128,7 @@ class Feedback {
//提交供应商反馈信息
postFeedbackInfo(VEI_SN, GRI_SN, EOI_SN, info_content) {
let url = `/service-fileServer/FeedbackInfo`;
let url = `/service-CooperateSOA/FeedbackInfo`;
let formData = new FormData();
formData.append("VEI_SN", VEI_SN);
formData.append("GRI_SN", GRI_SN);

@ -0,0 +1,71 @@
import { makeAutoObservable, runInAction } from "mobx";
import * as config from "@/config";
class Notice {
constructor(root) {
makeAutoObservable(this, { rootStore: false });
this.root = root;
}
noticeList = []; //公告列表
noticeUnRead = 0; //未读公告数量
noticeInfo = { CCP_BLID: 0, CCP_BLTitle: "", CCP_BLContent: "", CCP_LastEditTime: "" }; //公告详情
/*
LMI_SN 登录用户SN用户sn用来判断是否已读公告
*/
getBulletinList(LMI_SN) {
let url = `/service-Cooperate/Cooperate/GetBulletinList`;
url += `?LMI_SN=${LMI_SN}`;
fetch(config.HT_HOST + url)
.then(response => response.json())
.then(json => {
console.log(json);
runInAction(() => {
this.noticeList = json.Result;
});
})
.catch(error => {
console.log("fetch data failed", error);
});
}
/*
LMI_SN 登录用户sn 用户sn用来设置已读公告请求过一次详情页表示已读
CCP_BLID 公告sn
*/
getNoticeDetail(LMI_SN, CCP_BLID) {
let url = `/service-Cooperate/Cooperate/GetBulletinDetail`;
url += `?LMI_SN=${LMI_SN}&CCP_BLID=${CCP_BLID}`;
fetch(config.HT_HOST + url)
.then(response => response.json())
.then(json => {
console.log(json);
runInAction(() => {
this.noticeInfo = json.Result;
});
})
.catch(error => {
console.log("fetch data failed", error);
});
}
//检查是否有未读公告
getBulletinUnReadCount(LMI_SN) {
let url = `/service-Cooperate/Cooperate/GetBulletinUnReadCount`;
url += `?LMI_SN=${LMI_SN}`;
fetch(config.HT_HOST + url)
.then(response => response.json())
.then(json => {
console.log(json);
runInAction(() => {
this.noticeUnRead = json.Result.CCP_BulletinCount;
});
})
.catch(error => {
console.log("fetch data failed", error);
});
}
}
export default Notice;

@ -10,13 +10,15 @@ class Reservation {
this.root = root;
}
fetchReservationList(current, referenceNo, fromDate, thruDate) {
fetchReservationList(current) {
const fromDate = this.arrivalDateRange.length == 0 ? null : this.arrivalDateRange[0].format('YYYY-MM-DD');
const thruDate = this.arrivalDateRange.length == 0 ? null : this.arrivalDateRange[1].format('YYYY-MM-DD');
this.reservationPage.current = current;
// 设置为 0后端会重新计算总数当跳转第 X 页时可用原来的总数。
const totalNum = current == 1 ? 0 : this.reservationPage.total;
const fetchUrl = prepareUrl(HT_HOST + '/service-cusservice/GetPlanSearchList')
.append('VEI_SN', this.root.authStore.login.travelAgencyId)
.append('GroupNo', referenceNo)
.append('GroupNo', this.referenceNo)
.append('DateStart', fromDate)
.append('DateEnd', thruDate)
.append('TotalNum', totalNum)
@ -186,11 +188,19 @@ class Reservation {
this.selectedConfirmation = confirmation;
}
updatePropertyValue(name, value) {
runInAction(() => {
this[name] = value;
});
}
guideList = [];
cityList = [];
selectedReservation = null;
selectedConfirmation = null;
arrivalDateRange = [];
referenceNo = '';
reservationList = [];

@ -1,6 +1,7 @@
import { makeAutoObservable } from "mobx";
import Reservation from "./Reservation";
import Feedback from "./Feedback";
import Notice from "./Notice";
import Auth from "./Auth";
import Invoice from "./Invoice";
@ -8,6 +9,7 @@ class Root {
constructor() {
this.reservationStore = new Reservation(this);
this.feedbackStore = new Feedback(this);
this.noticeStore = new Notice(this);
this.authStore = new Auth(this);
this.invoiceStore = new Invoice(this);
makeAutoObservable(this);

@ -1,7 +1,7 @@
import { Outlet, Link, useHref, useLocation, NavLink } from "react-router-dom";
import { useEffect } from "react";
import { observer } from "mobx-react";
import { Layout, Menu, ConfigProvider, theme, Dropdown, Space, Row, Col, Alert, Typography, Divider, App as AntApp } from "antd";
import { Layout, Menu, ConfigProvider, theme, Dropdown, Space, Row, Col, Badge, Typography, Divider, App as AntApp } from "antd";
import { DownOutlined } from "@ant-design/icons";
import "antd/dist/reset.css";
import AppLogo from "@/assets/logo-gh.png";
@ -28,8 +28,8 @@ const items = [
},
];
function App() {
const { authStore } = useStore();
const { authStore, noticeStore } = useStore();
const { noticeUnRead } = noticeStore;
const href = useHref();
useEffect(() => {
// Check location
@ -61,7 +61,7 @@ function App() {
minHeight: "100vh",
}}>
<Header className="header" style={{ position: "sticky", top: 0, zIndex: 1, width: "100%" }}>
<Row gutter={{ md: 24 }} justify="end" align="middle">
<Row gutter={{ md: 24 }} justify="end" align="middle">
<Col span={16}>
<NavLink to="/">
<img src={AppLogo} className="logo" alt="App logo" />
@ -74,12 +74,22 @@ function App() {
{ key: "reservation", label: <Link to="/reservation/newest">Reservation</Link> },
{ key: "invoice", label: <Link to="/invoice">Invoice</Link> },
{ key: "feedback", label: <Link to="/feedback">Feedback</Link> },
{ key: "notice", label: <Link to="/notice">Notice</Link> },
{
key: "notice",
label: (
<Link to="/notice">
Notice
{noticeUnRead ? <Badge dot /> : ""}
</Link>
),
},
]}
/>
</Col>
<Col span={4}>
<Title level={3} style={{color: 'white', marginBottom: '0', display: 'flex', justifyContent: 'end'}}>{authStore.login.travelAgencyName}</Title>
<Title level={3} style={{ color: "white", marginBottom: "0", display: "flex", justifyContent: "end" }}>
{authStore.login.travelAgencyName}
</Title>
</Col>
<Col span={4}>
<Dropdown
@ -97,8 +107,6 @@ function App() {
</Row>
</Header>
<Alert message={<NavLink to="/notice">公告 查看后不再显示或者一直显示或者放到页面底部</NavLink>} description="" type="info" banner closable />
<Content
style={{
padding: 24,

@ -5,7 +5,7 @@ import { useStore } from '@/stores/StoreContext.js';
function Login() {
const { authStore } = useStore();
const { authStore,noticeStore } = useStore();
const { notification } = App.useApp();
const navigate = useNavigate();
const [form] = Form.useForm();
@ -13,6 +13,7 @@ function Login() {
const onFinish = (values) => {
authStore.valdateUserPassword(values.username, values.password)
.then((userId) => {
noticeStore.getBulletinUnReadCount(userId);
authStore.fetchUserDetail(userId)
.then((user) => {
// navigate(-1) is equivalent to hitting the back button.

@ -5,8 +5,6 @@ import { toJS } from "mobx";
import { Row, Col, Space, Button, Table, Input, Typography, DatePicker, Radio } from "antd";
import { useStore } from "@/stores/StoreContext.js";
import * as config from "@/config";
import * as comm from "@/utils/commons";
import dayjs from "dayjs";
const { Title } = Typography;
const feedbackListColumns = [
@ -51,10 +49,10 @@ function Index() {
const { feedbackStore, authStore } = useStore();
const { feedbackList, search_date_start, search_date_end } = feedbackStore;
const [referenceNo, onNumberChange] = useState("");
const showTotal = (total) => `Total ${feedbackList.length} items`;
const showTotal = total => `Total ${feedbackList.length} items`;
useEffect(() => {
console.info("feedback.useEffect");
feedbackStore.searchFeedbackList(authStore.login.travelAgencyId, referenceNo, search_date_start.format(config.DATE_FORMAT), search_date_end.format(config.DATE_FORMAT) + " 23:59");
}, []);
return (

@ -0,0 +1,40 @@
import { NavLink, useParams } from "react-router-dom";
import { useEffect, useState } from "react";
import { observer } from "mobx-react";
import { toJS } from "mobx";
import { Row, Col, Space, Button, Table, Input, Typography, Badge, Divider } from "antd";
import { useStore } from "@/stores/StoreContext.js";
import * as config from "@/config";
import * as comm from "@/utils/commons";
import dayjs from "dayjs";
const { Title, Paragraph, Text } = Typography;
function Detail() {
const { noticeStore, authStore } = useStore();
const { noticeInfo } = noticeStore;
const { CCP_BLID } = useParams();
useEffect(() => {
console.info("notice detail .useEffect " + CCP_BLID);
noticeStore.getNoticeDetail(authStore.login.userId, CCP_BLID);
}, []);
return (
<Space direction="vertical" style={{ width: "100%" }}>
<Row gutter={16}>
<Col span={4}></Col>
<Col span={16}>
<Title level={1}>{noticeInfo.CCP_BLTitle}</Title>
<Divider orientation="right">{noticeInfo.CCP_LastEditTime}</Divider>
<Paragraph>{noticeInfo.CCP_BLContent}</Paragraph>
</Col>
<Col span={4}>
<NavLink to="/notice">Back</NavLink>
</Col>
</Row>
</Space>
);
}
export default observer(Detail);

@ -2,7 +2,7 @@ import { NavLink } from "react-router-dom";
import { useEffect, useState } from "react";
import { observer } from "mobx-react";
import { toJS } from "mobx";
import { Row, Col, Space, Button, Table, Input, Typography, DatePicker, Radio } from "antd";
import { Row, Col, Space, Button, Table, Input, Typography, Badge, List } from "antd";
import { useStore } from "@/stores/StoreContext.js";
import * as config from "@/config";
import * as comm from "@/utils/commons";
@ -11,44 +11,28 @@ import dayjs from "dayjs";
const { Title, Paragraph, Text } = Typography;
function Index() {
const { feedbackStore } = useStore();
const { noticeStore, authStore } = useStore();
const { noticeList } = noticeStore;
useEffect(() => {
console.info("feedback.useEffect");
console.info("notice.useEffect");
noticeStore.getBulletinList(authStore.login.userId);
noticeStore.getBulletinUnReadCount(authStore.login.userId); //
}, []);
const [ellipsis, setEllipsis] = useState(true);
return (
<Space direction="vertical" style={{ width: "100%" }}>
<Row gutter={16}>
<Col span={4}></Col>
<Col span={18}>
<Title level={2}>Guidelines and Resources</Title>
<Paragraph ellipsis={{ expandable: true, rows: 5 }}>
We supply a series of design principles, practical patterns and high quality design resources (<Text code>Sketch</Text> and <Text code>Axure</Text>), to help people create their product prototypes beautifully and We
supply a series of design principles, practical patterns and high quality design resources (<Text code>Sketch</Text> and <Text code>Axure</Text>), to help people create their product prototypes beautifully and We
supply a series of design principles, practical patterns and high quality design resources (<Text code>Sketch</Text> and <Text code>Axure</Text>), to help people create their product prototypes beautifully and We
supply a series of design principles, practical patterns and high quality design resources (<Text code>Sketch</Text> and <Text code>Axure</Text>), to help people create their product prototypes beautifully and
efficiently. efficiently. We supply a series of design principles, practical patterns and high quality design resources (<Text code>Sketch</Text> and <Text code>Axure</Text>), to help people create their product
prototypes beautifully and We supply a series of design principles, practical patterns and high quality design resources (<Text code>Sketch</Text> and <Text code>Axure</Text>), to help people create their product
prototypes beautifully and efficiently. efficiently. We supply a series of design principles, practical patterns and high quality design resources (<Text code>Sketch</Text> and <Text code>Axure</Text>), to help
people create their product prototypes beautifully and We supply a series of design principles, practical patterns and high quality design resources (<Text code>Sketch</Text> and <Text code>Axure</Text>), to help
people create their product prototypes beautifully and efficiently. efficiently. efficiently. efficiently.
</Paragraph>
<Title level={2}>第二个公告</Title>
<Paragraph ellipsis={{ expandable: true, rows: 5 }}>
We supply a series of design principles, practical patterns and high quality design resources (<Text code>Sketch</Text> and <Text code>Axure</Text>), to help people create their product prototypes beautifully and We
supply a series of design principles, practical patterns and high quality design resources (<Text code>Sketch</Text> and <Text code>Axure</Text>), to help people create their product prototypes beautifully and We
supply a series of design principles, practical patterns and high quality design resources (<Text code>Sketch</Text> and <Text code>Axure</Text>), to help people create their product prototypes beautifully and We
supply a series of design principles, practical patterns and high quality design resources (<Text code>Sketch</Text> and <Text code>Axure</Text>), to help people create their product prototypes beautifully and
efficiently. efficiently. We supply a series of design principles, practical patterns and high quality design resources (<Text code>Sketch</Text> and <Text code>Axure</Text>), to help people create their product
prototypes beautifully and We supply a series of design principles, practical patterns and high quality design resources (<Text code>Sketch</Text> and <Text code>Axure</Text>), to help people create their product
prototypes beautifully and efficiently. efficiently. We supply a series of design principles, practical patterns and high quality design resources (<Text code>Sketch</Text> and <Text code>Axure</Text>), to help
people create their product prototypes beautifully and We supply a series of design principles, practical patterns and high quality design resources (<Text code>Sketch</Text> and <Text code>Axure</Text>), to help
people create their product prototypes beautifully and efficiently. efficiently. efficiently. efficiently.
</Paragraph>
<Col span={16}>
<List
dataSource={toJS(noticeList)}
renderItem={item => (
<List.Item>
<Typography.Text>[{item.CCP_LastEditTime}]</Typography.Text>
<NavLink to={`/notice/${item.CCP_BLID}`}> {item.CCP_BLTitle}</NavLink> {item.IsRead ? "" : <Badge dot />}
</List.Item>
)}></List>
</Col>
<Col span={4}></Col>
</Row>

@ -1,5 +1,5 @@
import { NavLink } from "react-router-dom";
import { useState, useEffect } from 'react';
import { useState, useRef, useEffect } from 'react';
import { observer } from "mobx-react";
import { toJS } from "mobx";
import { Row, Col, Space, Button, Table, Input, Typography, DatePicker, Radio, Modal, App, Select } from 'antd';
@ -87,18 +87,18 @@ function Newest() {
/>
);
}
// const href = useHref();
// const isMountedRef = useRef(false);
const { reservationStore } = useStore();
const { reservationList, reservationPage, cityList, guideList } = reservationStore;
const { reservationList, reservationPage, referenceNo, arrivalDateRange, cityList, guideList } = reservationStore;
const [isModalOpen, setIsModalOpen] = useState(false);
const arrivalDateFrom = dayjs().startOf("M");
const arrivalDateThru = dayjs().endOf("M");
const [arrivalDateRange, onDateRangeChange] =
useState([arrivalDateFrom.format('YYYY-MM-DD'), arrivalDateThru.format('YYYY-MM-DD')]);
const [referenceNo, onNumberChange] = useState('');
const [dataLoading, setDataLoading] = useState(false);
const { notification } = App.useApp();
const arrivalDateFrom = arrivalDateRange.length == 0 ? null : arrivalDateRange[0];
const arrivalDateThru = arrivalDateRange.length == 0 ? null : arrivalDateRange[1];
const guideSelectOptions = guideList.map((data, index) => {
return {
value: data.guideId,
@ -108,7 +108,8 @@ function Newest() {
useEffect(() => {
onSearchClick();
}, []);
console.info('Newest...');
}, [123]);
const showCityGuideModal = (reservation) => {
setDataLoading(true);
@ -139,7 +140,7 @@ function Newest() {
const onSearchClick = (current=1) => {
setDataLoading(true);
reservationStore.fetchReservationList(current, referenceNo, arrivalDateRange[0], arrivalDateRange[1])
reservationStore.fetchReservationList(current)
.catch(ex => {
notification.error({
message: `Notification`,
@ -188,25 +189,23 @@ function Newest() {
<Space direction="vertical" style={{ width: '100%' }}>
<Title level={3}>Newest Reservations</Title>
<Row gutter={{ md: 24 }}>
<Col span={4}>
<Input placeholder="Reference number" onChange={(e) => {onNumberChange(e.target.value)}} />
</Col>
<Col span={6}>
<Input placeholder="Reference number" value={referenceNo} onChange={(e) => { reservationStore.updatePropertyValue('referenceNo', e.target.value)} } />
</Col>
<Col span={18}>
<Space direction="horizontal">
Arrival Date
<DatePicker.RangePicker
allowClear={true}
inputReadOnly={true}
presets={DATE_PRESETS}
defaultValue={[arrivalDateFrom, arrivalDateThru]}
value={[arrivalDateFrom, arrivalDateThru]}
placeholder={['From', 'Thru']}
onChange={(date, dateRange) => { onDateRangeChange(dateRange)}}
onChange={(dateRange) => { reservationStore.updatePropertyValue('arrivalDateRange', dateRange)}}
/>
<Button type='primary' onClick={() => onSearchClick()} loading={dataLoading}>Search</Button>
</Space>
</Col>
<Col span={14}>
<Button type='primary' onClick={() => onSearchClick()} loading={dataLoading}>Search</Button>
</Col>
</Row>
<Row>
<Col span={24}>

Loading…
Cancel
Save