diff --git a/package.json b/package.json index fde34d1..e1eccd3 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "preview": "vite preview" }, "dependencies": { + "ahooks": "^3.7.8", "antd": "^5.12.8", "mobx": "^6.12.0", "mobx-react": "^9.1.0", diff --git a/src/main.jsx b/src/main.jsx index fc6b817..49bc1b2 100644 --- a/src/main.jsx +++ b/src/main.jsx @@ -59,12 +59,12 @@ const router = createBrowserRouter([ const rootStore = new RootStore(); ReactDOM.createRoot(document.getElementById('root')).render( - + //
Loading...
} />
-
+ //
) diff --git a/src/stores/Auth.js b/src/stores/Auth.js index 14b4ff2..76b02a1 100644 --- a/src/stores/Auth.js +++ b/src/stores/Auth.js @@ -1,7 +1,6 @@ import { makeAutoObservable, runInAction } from 'mobx' const KEY_USER_ID = 'KEY_USER_ID' -const KEY_WEBSITE = 'KEY_WEBSITE' class Auth { @@ -9,22 +8,17 @@ class Auth { makeAutoObservable(this, { rootStore: false }) this.root = root this.userId = root.getSession(KEY_USER_ID) - this.website = root.getSession(KEY_WEBSITE) } - setup(userId, website) { + setup(userId) { runInAction(() => { this.userId = userId - this.website = website - }); + }) this.root.putSession(KEY_USER_ID, userId) - this.root.putSession(KEY_WEBSITE, website) } - // HT 账号 SN + // HT 账号 OP_SN userId = null - // 从哪个网站打开,HTML 代码应用到哪个网站 - website = '' } export default Auth diff --git a/src/stores/Order.js b/src/stores/Order.js index a110dab..fbeb0da 100644 --- a/src/stores/Order.js +++ b/src/stores/Order.js @@ -73,13 +73,6 @@ class Order { }) } - getKeywordHistory() { - const keywordListText = this.root.getLocal('KEYWORD_LIST') - const keywordList = isEmpty(keywordListText) ? [] : JSON.parse(keywordListText) - return keywordList.map(keyword => { - return {value: keyword} - }) - } fetchCityList(countryId) { const fetchCityUrl = @@ -103,238 +96,9 @@ class Order { }) } - fetchCropImageList(userId) { - const formData = new FormData() - formData.append('PII_SN', this.selectedImage.PII_SN) - formData.append('user_id', userId) - const postUrl = 'https://p9axztuwd7x8a7.mycht.cn/service-InfoSysSOA/search_cutimage' - - return postForm(postUrl, formData) - .then(json => { - if (json.errcode == 0) { - runInAction(() => { - this.croppedImageList = json.result - }) - } else { - throw new Error(json.errmsg + ': ' + json.errcode) - } - }) - } - - toggleFavorite(image, userId) { - runInAction(() => { - image.isFavorite = !image.isFavorite - }) - const formData = new FormData() - formData.append('PII_SN', image.PII_SN) - formData.append('user_id', userId) - formData.append('addordelete', image.isFavorite ? 1: 0) - const postUrl = 'https://p9axztuwd7x8a7.mycht.cn/service-InfoSysSOA/favorite_image' - - return postForm(postUrl, formData) - .then(json => { - if (json.errcode == 0) { - console.info(json) - // json.result.PII_SN - } else { - throw new Error(json.errmsg + ': ' + json.errcode) - } - }) - } - - fetchImageList(country, city, keyword, tags, star, type, userId) { - - runInAction(() => { - this.imageSearchList = [] - }) - - if (isNotEmpty(keyword)) { - const keywordListText = this.root.getLocal('KEYWORD_LIST') - const keywordList = isEmpty(keywordListText) ? [] : JSON.parse(keywordListText) - if (keywordList.indexOf(keyword) == -1) { - - keywordList.unshift(keyword) - } - if (keywordList.length > 8) { - keywordList.splice(8, keywordList.length) - } - this.root.putLocal('KEYWORD_LIST', JSON.stringify(keywordList)) - } - - const formData = new FormData() - formData.append('CountrySN', country) - formData.append('citySN', city) - formData.append('keyword', keyword) - formData.append('tags', tags) - formData.append('star', star) - formData.append('searchType', type) - formData.append('user_id', userId) - const postUrl = 'https://p9axztuwd7x8a7.mycht.cn/service-InfoSysSOA/search_image' - - return postForm(postUrl, formData) - .then(json => { - if (json.errcode == 0) { - runInAction(() => { - this.imageSearchList = json.result - }) - } else { - throw new Error(json.errmsg + ': ' + json.errcode) - } - }) - } - - startUpload(userId) { - - for (let index = 0; index < this.imageUploadList.length; index++) { - const element = this.imageUploadList[index]; - this.requiredAlert = - (element.country === null) || - (element.city === null) || - (element.description_zh === '') || - (element.description_en === '') || - (element.photographer === '') || - (element.copyright === -1) || - (element.star === -1) - - if (this.requiredAlert) break - } - - if (this.requiredAlert) return - - let successCount = 0 - this.uploadPercent = 0 - const imageCount = this.imageUploadList.length - const postUrl = 'https://p9axztuwd7x8a7.mycht.cn/service-InfoSysSOA/upload_image' - - this.imageUploadList.forEach((element, index) => { - const formData = new FormData() - formData.append('image_file', element.image_file) - formData.append('image_uid', element.image_uid) - formData.append('country', element.country) - formData.append('city', element.city) - formData.append('description_zh', element.description_zh) - formData.append('description_en', element.description_en) - formData.append('photographer', element.photographer) - formData.append('copyright', element.copyright) - formData.append('labels', element.labelValues.join(',')) - formData.append('user_id', userId) - formData.append('star', element.star) - - return postForm(postUrl, formData) - .then(json => { - successCount++ - runInAction(() => { - this.uploadPercent = parseInt(successCount / imageCount * 100) - }) - if (json.errcode == 0) { - runInAction(() => { - for (var i = this.imageUploadList.length - 1; i >= 0; i--) { - const current = this.imageUploadList[i] - if (current.image_uid === json.result.image_uid) { - current.success = true - current.image_url = 'https://p9axztuwd7x8a7.mycht.cn/service-fileServer' + json.result.image_path - break - } - } - }) - } else { - throw new Error(json.errmsg + ': ' + json.errcode) - } - }) - }) - } - - startCrop(cropData, resizeWidth, userId, website) { - const formData = new FormData() - formData.append('filename', this.selectedImage.PII_Location + this.selectedImage.PII_FileName) - formData.append('x', cropData.x) - formData.append('y', cropData.y) - formData.append('width', Math.trunc(cropData.width)) - formData.append('height', Math.trunc(cropData.height)) - formData.append('resize_width', resizeWidth) - formData.append('user_id', userId) - formData.append('webcode', website) - const postUrl = 'https://p9axztuwd7x8a7.mycht.cn/service-InfoSysSOA/crop_image' - - return postForm(postUrl, formData) - .then(json => { - if (json.errcode == 0) { - this.fetchCropImageList() - const imageHtml = this.generateHtml(json.result, website) - const cropResult = { - imageHtml: imageHtml - } - return cropResult - } else { - throw new Error(json.errmsg + ': ' + json.errcode) - } - }) - } - - getImageHost(website) { - let imageHost = '' - switch (website) { - case 'ch': - imageHost = 'https://images.chinahighlights.com' - break - case 'ah': - imageHost = 'https://images.asiahighlights.com' - break - case 'gh': - imageHost = 'https://images.globalhighlights.com' - break - case 'chinatravel': - imageHost = 'https://images.chinatravel.com' - break - case 'sht': - imageHost = 'https://images.shanghaihighlights.com' - break - case 'ts': - imageHost = 'https://images.trainspread.com' - break - case 'mbj': - imageHost = 'https://images.mybeijingchina.com' - break - default: - imageHost = 'https://images.chinahighlights.com' - break - } - return imageHost - } - - generateHtml(imageObj, website) { - const imageUrl = this.getImageHost(website) + imageObj.PII_Location + imageObj.PII_FileName - let imageHtml = '' - - switch (website) { - case 'ch': - imageHtml = '
' + imageObj.PII2_Intro + '' + imageObj.PII2_Intro + '
' - break - case 'ah': - imageHtml = '
' + imageObj.PII2_Intro + '' + imageObj.PII2_Intro + '
' - break - case 'gh': - imageHtml = '
' + imageObj.PII2_Intro + '' + imageObj.PII2_Intro + '
' - break - case 'chinatravel': - case 'sht': - case 'ts': - case 'mbj': - imageHtml = '
' + imageObj.PII2_Intro + '
' - break - default: - imageHtml = '' + imageObj.PII2_Intro + '' - break - } - - return imageHtml - } - useImage(imageId, userId, website) { const formData = new FormData() formData.append('PII_SN', imageId) - formData.append('user_id', userId) - formData.append('Webcode', website) const postUrl = 'https://p9axztuwd7x8a7.mycht.cn/service-InfoSysSOA/use_image' return postForm(postUrl, formData) @@ -346,86 +110,6 @@ class Order { } }) } - - continueUpload() { - runInAction(() => { - this.imageUploadList = [] - this.uploadPercent = -1 - }) - } - - initImageList(fileList) { - runInAction(() => { - this.imageUploadList = fileList.map(file => { - return { - image_file: file, - image_uid: file.uid, - country: null, - city: null, - description_zh: '', - description_en: '', - photographer: '', - copyright: -1, - labels: '', - labelValues: [], - user_id: -1, - star: -1, - success: false, - image_url: '' - } - }) - }) - } - - removeUploadImage(fileUid) { - runInAction(() => { - this.imageUploadList = this.imageUploadList.filter((image, index) => { - return image.image_uid != fileUid - }) - }) - } - - syncProperties() { - if (this.imageUploadList.length > 1) { - const source = this.imageUploadList[0] - runInAction(() => { - for (let index = 1; index < this.imageUploadList.length; index++) { - const current = this.imageUploadList[index] - current.country = source.country - current.city = source.city - current.description_zh = source.description_zh - current.description_en = source.description_en - current.photographer = source.photographer - current.copyright = source.copyright - current.labelValues = source.labelValues - current.user_id = source.user_id - current.star = source.star - } - }) - } - } - - updateImageProperty(uid, name, value) { - for (var i = this.imageUploadList.length - 1; i >= 0; i--) { - const current = this.imageUploadList[i] - if (current.image_file.uid === uid) { - current[name] = value - break - } - } - } - - selectImage(image) { - this.selectedImage = image - } - - imageUploadList = [] - imageSearchList = [] - uploadPercent = -1 - selectedImage = null - croppedImageList = [] - // 上传时数据验证是否通过 - requiredAlert = false } export default Order diff --git a/src/views/App.jsx b/src/views/App.jsx index a0290cc..edb6a46 100644 --- a/src/views/App.jsx +++ b/src/views/App.jsx @@ -2,6 +2,10 @@ import { Outlet, Link, useHref, NavLink } from 'react-router-dom' import { useRef, useEffect, useState } from 'react' import { Layout, Menu, ConfigProvider, theme, Empty, Row, Col, Dropdown, Space, Typography, Result, App as AntApp } from 'antd' import { DownOutlined } from "@ant-design/icons"; +import zhLocale from 'antd/locale/zh_CN'; +import dayjs from 'dayjs'; +import 'dayjs/locale/zh-cn'; + import '@/assets/App.css' import AppLogo from '@/assets/logo-gh.png' import { useStore } from '@/stores/StoreContext.js' @@ -45,7 +49,7 @@ function App() { function renderLayout() { return ( -
+
@@ -121,6 +125,7 @@ function App() { }, algorithm: theme.defaultAlgorithm, }} + locale={zhLocale} renderEmpty={globalEmpty} > diff --git a/src/views/ChatHistory.jsx b/src/views/ChatHistory.jsx index 6bb498a..c38fff9 100644 --- a/src/views/ChatHistory.jsx +++ b/src/views/ChatHistory.jsx @@ -2,7 +2,7 @@ import { useNavigate } from 'react-router-dom' import { useRef, useEffect, useState } from 'react' import { observer } from 'mobx-react' import { Row, Col, Divider, Table , Card, Button, Input, - Space, Empty, Radio, Select, DatePicker, Spin, List, Avatar + Space, Empty, Radio, AutoComplete, DatePicker, Spin, List, Avatar } from 'antd' import { StarFilled, ZoomInOutlined, StarOutlined, SearchOutlined @@ -39,15 +39,30 @@ function ChatHistory() { + + + { + setKeyword(value) + }} + filterOption={(inputValue, option) => + option.value.toUpperCase().indexOf(inputValue.toUpperCase()) !== -1 + } + /> + + + + + - - {}} - /> + + diff --git a/src/views/DingdingCallbak.jsx b/src/views/DingdingCallbak.jsx index 35b3b41..9a82575 100644 --- a/src/views/DingdingCallbak.jsx +++ b/src/views/DingdingCallbak.jsx @@ -1,6 +1,7 @@ import React, { useEffect } from 'react' import { useParams, useNavigate } from "react-router-dom" -import { Card, Typography, Flex, Button } from 'antd' +import { Card, Typography, Flex, Result, Button } from 'antd' +import { useRequest } from 'ahooks' const { Title } = Typography const { Meta } = Card @@ -13,13 +14,28 @@ function DingdingCallbak() { console.info('code: ' + code) console.info('state: ' + state) + const { data, error, loading } = useRequest(() => { + return new Promise((resolve) => { + setTimeout(() => { + resolve('use Request data...'); + }, 1000); + }); + }); useEffect(() => { }, []) return ( - 钉钉 Callbak +

{error}

+

{loading}

+

{data}

+ 正在获取你的权限,请稍等 +
) } diff --git a/src/views/DingdingQRCode.jsx b/src/views/DingdingQRCode.jsx index c3cebcb..34584e3 100644 --- a/src/views/DingdingQRCode.jsx +++ b/src/views/DingdingQRCode.jsx @@ -1,5 +1,5 @@ +import { Card, Flex, Typography } from 'antd' import React, { useEffect } from 'react' -import { Card, Typography, Flex, Button } from 'antd' const { Title } = Typography const { Meta } = Card @@ -12,7 +12,7 @@ function DingdingQRCode() { import('https://g.alicdn.com/dingding/h5-dingtalk-login/0.21.0/ddlogin.js').then((module) => { window.DTFrameLogin( { - id: 'dingdingContainer', + id: 'qrCodeContainer', width: 300, height: 300, }, @@ -25,26 +25,26 @@ function DingdingQRCode() { prompt: 'consent', }, (loginResult) => { - const { redirectUrl, authCode, state } = loginResult; + const { redirectUrl, authCode, state } = loginResult // 这里可以直接进行重定向 - window.location.href = redirectUrl; + window.location.href = redirectUrl // 也可以在不跳转页面的情况下,使用code进行授权 - console.log(authCode); + console.log(authCode) }, (errorMsg) => { // 这里一般需要展示登录失败的具体原因 - alert(`Login Error: ${errorMsg}`); + alert(`Login Error: ${errorMsg}`) }, ) }) }, []) return ( - + 使用钉钉扫码 -
+
) } -export default DingdingQRCode; \ No newline at end of file +export default DingdingQRCode \ No newline at end of file diff --git a/src/views/ErrorPage.jsx b/src/views/ErrorPage.jsx index a0ffe04..76c9dfb 100644 --- a/src/views/ErrorPage.jsx +++ b/src/views/ErrorPage.jsx @@ -1,16 +1,15 @@ import { useRouteError } from "react-router-dom"; +import { Card, Typography, Flex, Result, Button } from 'antd' export default function ErrorPage() { const errorResponse = useRouteError(); console.error(errorResponse); return ( -
-

Oops!

-

Sorry, an unexpected error has occurred.

-

- {errorResponse.error.message} -

-
+ ); } \ No newline at end of file diff --git a/src/views/OrderFollow.jsx b/src/views/OrderFollow.jsx index 3c61118..b748f79 100644 --- a/src/views/OrderFollow.jsx +++ b/src/views/OrderFollow.jsx @@ -2,10 +2,10 @@ import { useNavigate } from 'react-router-dom' import { useRef, useEffect, useState } from 'react' import { observer } from 'mobx-react' import { Row, Col, Divider, Table , Card, Button, Input, - Space, Empty, Radio, Select, AutoComplete, Spin, Typography, Flex + Space, Segmented, Radio, Select, AutoComplete, Spin, Typography, Flex } from 'antd' import { - StarFilled, ZoomInOutlined, StarOutlined, SearchOutlined + StarFilled, ZoomInOutlined, StarOutlined, BarsOutlined , AppstoreOutlined } from '@ant-design/icons' const dataSource = [ @@ -41,7 +41,7 @@ const dataSource = [ orderNumber: 'LU231218115(3)', fullname: 'Giacomo Guilizzoni(R1)', orderStatus: '新订单', - trip: 'Itinerary2: Tkyoto tour', + trip: 'Itinerary2: Tkyoto tour 超级无敌长的报价标题', lastMessage: '2024-03-25 16:02', comment: '吃素、蜜月', }, @@ -79,6 +79,30 @@ const columns = [ title: '订单号', dataIndex: 'orderNumber', key: 'orderNumber', + width: 300, + render: (text, record, inde) => { + return ( + + {text} + + + ) + } }, { title: '客人姓名', @@ -89,11 +113,49 @@ const columns = [ title: '订单状态', dataIndex: 'orderStatus', key: 'orderStatus', + render: (text, record, inde) => { + return ( +