✨ update qr-code style
This commit is contained in:
parent
f9761015c3
commit
d98bddc54f
@ -4,6 +4,12 @@ FROM node:18.19.1-alpine AS builder
|
||||
MAINTAINER yaclty2@gmail.com
|
||||
WORKDIR /app
|
||||
|
||||
# envs 配置
|
||||
# 应用部署后的URL
|
||||
ENV APP_SITE_URL ""
|
||||
# 应用接口前缀
|
||||
ENV APP_API_URL ""
|
||||
|
||||
# Copy source code to the builder
|
||||
COPY package.json yarn.lock* ./
|
||||
COPY public ./public
|
||||
@ -24,8 +30,7 @@ FROM nginx:1.26-alpine3.19 AS runner
|
||||
WORKDIR /app
|
||||
|
||||
# envs 配置
|
||||
ENV APP_API_URL https://baidu.com
|
||||
ENV APP_SITE_URL https://pay.wm-app.xyz
|
||||
ENV APP_API_URL http://43.136.175.109:50000
|
||||
|
||||
# nginx配置文件
|
||||
COPY nginx.conf /etc/nginx/conf.d/default.conf.template
|
||||
|
25
src/components/bill/bill-detail-items.tsx
Normal file
25
src/components/bill/bill-detail-items.tsx
Normal file
@ -0,0 +1,25 @@
|
||||
import React from "react";
|
||||
import {useTranslation} from "react-i18next";
|
||||
|
||||
import {IconBillType, IconMoney, IconStudentId} from "@/components/icons";
|
||||
import MoneyFormat from "@/components/money-format.tsx";
|
||||
import './bill.less'
|
||||
|
||||
const BillDetailItem = (item: { title: React.ReactNode; value: React.ReactNode, icon?: React.ReactNode }) => {
|
||||
return <div className={'bill-detail-item'}>
|
||||
<div className={'detail-item-title'}>{item.icon} <span className={'item-title'}>{item.title}</span> :</div>
|
||||
<div className={'detail-item-value'}>{item.value}</div>
|
||||
</div>
|
||||
}
|
||||
const BillDetailItems = ({bill}: { bill: BillModel }) => {
|
||||
const {t} = useTranslation();
|
||||
return (<>
|
||||
<BillDetailItem icon={<IconBillType/>} title={t('manual.bill_type')} value={'TUITION FEE'}/>
|
||||
<BillDetailItem icon={<IconStudentId/>} title={t('manual.student_number')} value={bill.student_number}/>
|
||||
<BillDetailItem icon={<IconStudentId/>} title={t('bill.title_student_name')}
|
||||
value={`${bill.student_english_name}/${bill.student_chinese_name}`}/>
|
||||
<BillDetailItem icon={<IconMoney/>} title={t('manual.amount')} value={<MoneyFormat money={bill.amount}/>}/>
|
||||
</>)
|
||||
}
|
||||
|
||||
export default BillDetailItems;
|
@ -1,4 +1,4 @@
|
||||
.bill-search-form{
|
||||
.bill-search-form {
|
||||
|
||||
}
|
||||
|
||||
@ -15,6 +15,7 @@
|
||||
.bill-info-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-right: 5px;
|
||||
|
||||
&:before {
|
||||
content: ' ';
|
||||
@ -27,4 +28,49 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.modal-bill-detail{
|
||||
.modal-bill-info{
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
.bill-info-detail{
|
||||
margin-left: 30px;
|
||||
width: 340px;
|
||||
}
|
||||
.bill-exp-time{
|
||||
font-size: 18px;
|
||||
margin-bottom: 20px;
|
||||
border-bottom: dashed 2px #eeeeee;
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.bill-detail-item {
|
||||
display: flex;
|
||||
margin-bottom: 10px;
|
||||
align-items: center;
|
||||
|
||||
.detail-item-title {
|
||||
font-weight: bold;
|
||||
width: 120px;
|
||||
white-space: nowrap;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.item-title{
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.detail-item-value {
|
||||
color: #999999;
|
||||
}
|
||||
}
|
||||
body[data-lang=en-US]{
|
||||
.bill-detail-item {
|
||||
.detail-item-title{
|
||||
width: 170px;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,43 +1,37 @@
|
||||
import styles from "@/pages/manual/manual.module.less";
|
||||
import {Button, Space} from "@douyinfe/semi-ui";
|
||||
import QRCode from "qrcode.react";
|
||||
import {useTranslation} from "react-i18next";
|
||||
import {useRef} from "react";
|
||||
import {saveAs} from "file-saver";
|
||||
|
||||
import {BillDetailItems, useBillQRCode} from "@/components/bill/index.ts";
|
||||
|
||||
import './bill.less'
|
||||
|
||||
|
||||
const BillDetailItem = (item:{title:string;value:string})=>{
|
||||
return <div className={styles.billDetailItem}>
|
||||
<div className={styles.billDetailItemTitle}>{item.title} :</div>
|
||||
<div className={styles.billDetailItemValue}>{item.value}</div>
|
||||
</div>
|
||||
type BillDetailProps = {
|
||||
onCancel: ()=>void;
|
||||
bill:BillModel;
|
||||
}
|
||||
|
||||
const BillDetail:BasicComponent<{bill:BillModel}> = ()=>{
|
||||
const BillDetail:BasicComponent<BillDetailProps> = ({bill,onCancel})=>{
|
||||
const {t} = useTranslation();
|
||||
const qrCodeRef = useRef<HTMLDivElement>(null)
|
||||
const downloadQRCode = ()=>{
|
||||
const canvas = qrCodeRef.current?.querySelector('canvas');
|
||||
if(!canvas) return
|
||||
saveAs(canvas.toDataURL(), 'qrcode.png')
|
||||
}
|
||||
return <div>
|
||||
<Space className={styles.billDetail} align={'start'}>
|
||||
<div className={styles.billQrCode}>
|
||||
const { exportQRCode,QRCode } = useBillQRCode()
|
||||
return <div className={'modal-bill-detail'}>
|
||||
<div className={'modal-bill-info'}>
|
||||
<div className={'bill-qr-code'}>
|
||||
<div className={styles.QRCodeContainer}>
|
||||
<div className={styles.qrCode} ref={qrCodeRef}>
|
||||
<QRCode size={250} value={'http://localhost:5173/pay?bill=123123123&from=qrcode'} />
|
||||
</div>
|
||||
<QRCode size={160} className={styles.qrCode} bill={bill} />
|
||||
</div>
|
||||
<div className={styles.billExpTime}> {t('manual.exp_time')} {'12:00'} </div>
|
||||
</div>
|
||||
<div >
|
||||
<BillDetailItem title={t('manual.bill_type')} value={'TUITION FEE'} />
|
||||
<BillDetailItem title={t('manual.student_number')} value={'12345612'} />
|
||||
<BillDetailItem title={t('manual.amount')} value={'HK$ 13600.00'} />
|
||||
<Button onClick={downloadQRCode} style={{marginTop:20}} theme={'solid'} type={'primary'}>Download QR code</Button>
|
||||
<div className={'bill-info-detail'}>
|
||||
<div className={'bill-exp-time text-center'}> {t('manual.exp_time')} {'12:00'} </div>
|
||||
<BillDetailItems bill={bill} />
|
||||
</div>
|
||||
</Space>
|
||||
</div>
|
||||
<div className="text-center semi-modal-footer">
|
||||
<Space spacing={1}>
|
||||
<Button type="primary" onClick={onCancel}>{t('base.close')}</Button>
|
||||
<Button theme={'solid'} type="primary" onClick={exportQRCode}>{t('bill.download-qr-code')}</Button>
|
||||
</Space>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
export default BillDetail
|
@ -3,5 +3,6 @@ import {
|
||||
BillList
|
||||
} from './list.tsx'
|
||||
import useBillQRCode from './qr-code.tsx'
|
||||
import BillDetailItems from './bill-detail-items.tsx'
|
||||
|
||||
export {BillDetail, BillList, useBillQRCode}
|
||||
export {BillDetail, BillList, useBillQRCode,BillDetailItems}
|
@ -15,7 +15,7 @@ export type BillQrcodeProps = {
|
||||
function getPayUrl(billId?: string | number) {
|
||||
const {host, protocol} = location //AppConfig.SITE_URL
|
||||
|
||||
const rootUrl = (typeof (APP_SITE_URL) == "string" ? APP_SITE_URL : undefined) || `${protocol}//${host}`
|
||||
const rootUrl = (typeof (APP_SITE_URL) == "string" ? APP_SITE_URL : undefined) || AppConfig.SITE_URL || `${protocol}//${host}`
|
||||
return `${rootUrl}/pay?bill=${billId || 0}&from=qrcode`
|
||||
}
|
||||
|
||||
|
@ -23,7 +23,7 @@ type SearchFormFields = {
|
||||
const SearchForm: React.FC<SearchFormProps> = (props) => {
|
||||
const formSubmit = (value: SearchFormFields) => {
|
||||
const params: BillQueryParams = {}
|
||||
if (value.dateRange) {
|
||||
if (value.dateRange && value.dateRange.length == 2) {
|
||||
params.start_date = dayjs(value.dateRange[0]).format('YYYY-MM-DD');
|
||||
params.end_date = dayjs(value.dateRange[1]).format('YYYY-MM-DD');
|
||||
}
|
||||
|
@ -32,4 +32,93 @@ export const IconChecked = ({style}: IconProps) => {
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
export const IconMoney = ({style}: IconProps) => {
|
||||
return (
|
||||
<svg className="icon" viewBox="0 0 20 20" version="1.1" xmlns="http://www.w3.org/2000/svg"
|
||||
width="1em" height="1em" style={style}>
|
||||
<defs>
|
||||
<clipPath id="master_svg0_1_579925">
|
||||
<rect x="0" y="0" width="20" height="20" rx="0"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
<g clip-path="url(#master_svg0_1_579925)">
|
||||
<g>
|
||||
<path
|
||||
d="M8.247756875,7.59451C8.575876875,7.38402,9.096836875000001,7.2191399999999994,9.767556875,7.1875L10.239506875,7.1875C10.910256875,7.2191399999999994,11.431196875000001,7.38402,11.759336874999999,7.59451C12.088336875,7.8055699999999995,12.191036875,8.02607,12.191036875,8.27881C12.191036875,8.31139,12.189336875,8.343440000000001,12.185666874999999,8.375L13.438906875,8.375C13.440336875,8.34324,13.441036875,8.31119,13.441036875,8.27881C13.441036875,6.946149999999999,12.228616875,6.13037,10.628536875,5.9637899999999995L10.628536875,4.375L9.378536875,4.375L9.378536875,5.9637899999999995C7.778456875,6.13037,6.566035275,6.946149999999999,6.566035275,8.27881C6.566035275,9.78029,8.105056875,10.625630000000001,10.003536875,10.625630000000001C10.785876875,10.62645,11.389026874999999,10.80287,11.753826875,11.03688C12.082856875000001,11.24793,12.185546875,11.468440000000001,12.185546875,11.72119C12.185546875,11.97393,12.082856875000001,12.19445,11.753826875,12.40549C11.425706875,12.61598,10.904746875,12.78086,10.234026875,12.8125L9.762066875,12.8125C9.091346875,12.78086,8.570386875,12.61598,8.242266875,12.40549C7.9132468750000005,12.19445,7.810546875,11.97393,7.810546875,11.72119C7.810546875,11.68861,7.812246875,11.656559999999999,7.815936875,11.625L6.562675955,11.625C6.561269283,11.65676,6.560546875,11.68883,6.560546875,11.72119C6.560546875,13.05385,7.772966875,13.86963,9.373046875,14.03621L9.373046875,15.625L10.623046875,15.625L10.623046875,14.03621C12.223126875,13.86963,13.435546875,13.05385,13.435546875,11.72119C13.435546875,10.21971,11.896526875,9.374369999999999,9.998046875,9.374369999999999C9.215706875,9.37355,8.612556875,9.19713,8.247756875,8.96313C7.918726875,8.75207,7.816036875,8.531559999999999,7.816036875,8.27881C7.816036875,8.02607,7.918726875,7.8055699999999995,8.247756875,7.59451Z"
|
||||
fill="#FF8432" fill-opacity="1"/>
|
||||
</g>
|
||||
<g>
|
||||
<path
|
||||
d="M18.75,10C18.75,14.8325,14.8325,18.75,10,18.75C5.1675,18.75,1.25,14.8325,1.25,10C1.25,5.1675,5.1675,1.25,10,1.25C14.8325,1.25,18.75,5.1675,18.75,10ZM17.5,10C17.5,5.85787,14.1421,2.5,10,2.5C5.85787,2.5,2.5,5.85787,2.5,10C2.5,14.1421,5.85787,17.5,10,17.5C14.1421,17.5,17.5,14.1421,17.5,10Z"
|
||||
fill="#FF8432" fill-opacity="1"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
export const IconStudentId = ({style}: IconProps) => {
|
||||
return (
|
||||
<svg className="icon" viewBox="0 0 20 20" version="1.1" xmlns="http://www.w3.org/2000/svg"
|
||||
width="1em" height="1em" style={style}>
|
||||
<defs>
|
||||
<clipPath id="master_svg0_1_310440">
|
||||
<rect x="0" y="0" width="20" height="20" rx="0"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
<g clip-path="url(#master_svg0_1_310440)">
|
||||
<g>
|
||||
<path
|
||||
d="M14.6875,5.9375C14.6875,3.34867,12.5888,1.25,10,1.25C7.41117,1.25,5.3125,3.34867,5.3125,5.9375C5.3125,7.47584,6.05354,8.84111,7.19812,9.6958C4.1175999999999995,10.62863,1.875,13.4899,1.875,16.875L1.875,18.125C1.875,18.4702,2.154824,18.75,2.5,18.75L11.25,18.75L11.25,17.5L3.125,17.5L3.125,16.875C3.125,13.4232,5.92322,10.625,9.375,10.625L10.625,10.625C11.60687,10.625,12.5359,10.85141,13.3626,11.2549L15.5914,11.2549C14.7944,10.55002,13.8463,10.01207,12.8019,9.6958C13.9465,8.84111,14.6875,7.47584,14.6875,5.9375ZM10,9.375C8.10152,9.375,6.5625,7.83598,6.5625,5.9375C6.5625,4.03902,8.10152,2.5,10,2.5C11.8985,2.5,13.4375,4.03902,13.4375,5.9375C13.4375,7.83598,11.8985,9.375,10,9.375Z"
|
||||
fill="#00C479" fill-opacity="1"/>
|
||||
</g>
|
||||
<g>
|
||||
<path d="M12.5,13.75L18.125,13.75L18.125,12.5L12.5,12.5L12.5,13.75Z" fill="#00C479"
|
||||
fill-opacity="1"/>
|
||||
</g>
|
||||
<g>
|
||||
<path d="M18.125,16.25L12.5,16.25L12.5,15L18.125,15L18.125,16.25Z" fill="#00C479" fill-opacity="1"/>
|
||||
</g>
|
||||
<g>
|
||||
<path d="M12.5,18.75L18.125,18.75L18.125,17.5L12.5,17.5L12.5,18.75Z" fill="#00C479"
|
||||
fill-opacity="1"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>)
|
||||
}
|
||||
|
||||
export const IconBillType = ({style}: IconProps) => {
|
||||
return (
|
||||
<svg className="icon" viewBox="0 0 20 20" version="1.1" xmlns="http://www.w3.org/2000/svg"
|
||||
width="1em" height="1em" style={style}>
|
||||
<defs>
|
||||
<clipPath id="master_svg0_1_310428">
|
||||
<rect x="0" y="0" width="20" height="20" rx="0"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
<g clip-path="url(#master_svg0_1_310428)">
|
||||
<g>
|
||||
<path
|
||||
d="M11.875,7.499664306640625L5,7.499664306640625L5,6.249664306640625L11.875,6.249664306640625L11.875,7.499664306640625Z"
|
||||
fill="#FFC65F" fill-opacity="1"/>
|
||||
</g>
|
||||
<g>
|
||||
<path
|
||||
d="M5,13.749969482421875L10,13.749969482421875L10,12.499969482421875L5,12.499969482421875L5,13.749969482421875Z"
|
||||
fill="#FFC65F" fill-opacity="1"/>
|
||||
</g>
|
||||
<g>
|
||||
<path d="M11.875,10.625L5,10.625L5,9.375L11.875,9.375L11.875,10.625Z" fill="#FFC65F"
|
||||
fill-opacity="1"/>
|
||||
</g>
|
||||
<g>
|
||||
<path
|
||||
d="M15,16.875C15,17.5654,14.4404,18.125,13.75,18.125L3.125,18.125C2.434649,18.125,1.875,17.5654,1.875,16.875L1.875,3.125C1.875,2.434649,2.434649,1.875,3.125,1.875L13.75,1.875C14.4404,1.875,15,2.434649,15,3.125L16.875,3.125C17.5654,3.125,18.125,3.68465,18.125,4.375L18.125,15.625C18.125,16.3154,17.5654,16.875,16.875,16.875L15,16.875ZM13.75,3.125L3.125,3.125L3.125,16.875L13.75,16.875L13.75,3.125ZM15,4.375L15,15.625L16.875,15.625L16.875,4.375L15,4.375Z"
|
||||
fill="#FFC65F" fill-opacity="1"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
)
|
||||
}
|
@ -6,6 +6,9 @@ type MoneyFormatProps = {
|
||||
}
|
||||
|
||||
function formatCurrency(amount: string | number) {
|
||||
if(amount === '0' || amount === '0.00') {
|
||||
return '0.00';
|
||||
}
|
||||
// 将金额转换为字符串,并限制小数点后两位
|
||||
let amountStr = Number(amount).toFixed(2);
|
||||
|
||||
@ -24,6 +27,6 @@ function formatCurrency(amount: string | number) {
|
||||
|
||||
const MoneyFormat: React.FC<MoneyFormatProps> = ({money, currency = 'HK$'}) => {
|
||||
// 将货币数字转换为千分位格式且带2位小数
|
||||
return money?<span className={'money-format'}>{currency} {formatCurrency(money)}</span>:null
|
||||
return (money||money==0||money=='0') ?<span className={'money-format'}>{currency} {formatCurrency(money)}</span>:null;
|
||||
}
|
||||
export default MoneyFormat;
|
@ -2,6 +2,7 @@
|
||||
"base": {
|
||||
"bill_number": "Bill Number",
|
||||
"btn_search_submit": "Search",
|
||||
"close": "Close",
|
||||
"please_enter": "Please Enter",
|
||||
"please_select": "Please Select",
|
||||
"student_number": "Student Number"
|
||||
@ -13,6 +14,7 @@
|
||||
"confirm_batch": "Batch Confirm",
|
||||
"confirm_select_empty": "Require confirm bill data",
|
||||
"confirmed": "Confirmed",
|
||||
"download-qr-code": "Download QR Code",
|
||||
"download_receipt": "Download receipt",
|
||||
"pay_status": "Bill Status",
|
||||
"pay_status_canceled": "Canceled",
|
||||
|
@ -2,6 +2,7 @@
|
||||
"base": {
|
||||
"bill_number": "账单编号",
|
||||
"btn_search_submit": "搜索",
|
||||
"close": "关闭",
|
||||
"please_enter": "请输入",
|
||||
"please_select": "请选择",
|
||||
"student_number": "学号"
|
||||
@ -13,6 +14,7 @@
|
||||
"confirm_batch": "批量对账",
|
||||
"confirm_select_empty": "对账账单为空",
|
||||
"confirmed": "已对账",
|
||||
"download-qr-code": "下载二维码",
|
||||
"download_receipt": "下载收据",
|
||||
"pay_status": "账单状态",
|
||||
"pay_status_canceled": "已作废",
|
||||
|
@ -2,6 +2,7 @@
|
||||
"base": {
|
||||
"bill_number": "账单编号",
|
||||
"btn_search_submit": "搜索",
|
||||
"close": "关闭",
|
||||
"please_enter": "请输入",
|
||||
"please_select": "请选择",
|
||||
"student_number": "学号"
|
||||
@ -13,6 +14,7 @@
|
||||
"confirm_batch": "批量对账",
|
||||
"confirm_select_empty": "对账账单为空",
|
||||
"confirmed": "已对账",
|
||||
"download-qr-code": "下载二维码",
|
||||
"download_receipt": "下载收据",
|
||||
"pay_status": "账单状态",
|
||||
"pay_status_canceled": "已作废",
|
||||
|
@ -32,15 +32,15 @@ const BillQuery = () => {
|
||||
}}
|
||||
/>
|
||||
<Modal
|
||||
title="View QR code"
|
||||
title="Bill Detail"
|
||||
visible={!!showBill}
|
||||
onOk={() => {
|
||||
}}
|
||||
width={620}
|
||||
onCancel={() => setShowBill(undefined)} //>=1.16.0
|
||||
closeOnEsc={true}
|
||||
footerFill={true}
|
||||
footer={null}
|
||||
closeIcon={<span></span>}
|
||||
>
|
||||
{showBill && <BillDetail bill={showBill}/>}
|
||||
{showBill && <BillDetail bill={showBill} onCancel={() => setShowBill(undefined)}/>}
|
||||
</Modal>
|
||||
</div>)
|
||||
}
|
||||
|
@ -1,11 +1,10 @@
|
||||
import {Button, Form, Space, Toast} from "@douyinfe/semi-ui";
|
||||
import {useTranslation} from "react-i18next";
|
||||
import {ReactNode, useRef, useState} from "react";
|
||||
import { useRef, useState} from "react";
|
||||
|
||||
import {Card} from "@/components/card";
|
||||
import MoneyFormat from "@/components/money-format.tsx";
|
||||
import {BillTypes} from "@/service/bill-types.ts";
|
||||
import {useBillQRCode} from "@/components/bill";
|
||||
import {BillDetailItems, useBillQRCode} from "@/components/bill";
|
||||
|
||||
import styles from './manual.module.less'
|
||||
import {createManualBill, getBillDetail} from "@/service/api/bill.ts";
|
||||
@ -14,12 +13,6 @@ import {BizError} from "@/service/types.ts";
|
||||
import {IconAlertTriangle} from "@douyinfe/semi-icons";
|
||||
import dayjs from "dayjs";
|
||||
|
||||
const BillDetailItem = (item: { title: string; value: ReactNode }) => {
|
||||
return <div className={styles.billDetailItem}>
|
||||
<div className={styles.billDetailItemTitle}>{item.title} :</div>
|
||||
<div className={styles.billDetailItemValue}>{item.value}</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
|
||||
export default function Index() {
|
||||
@ -50,9 +43,7 @@ export default function Index() {
|
||||
const BillInfo = ({bill}: { bill?: BillModel }) => {
|
||||
if (!bill) return null;
|
||||
return (<>
|
||||
<BillDetailItem title={t('manual.bill_type')} value={'TUITION FEE'}/>
|
||||
<BillDetailItem title={t('manual.student_number')} value={bill.student_number}/>
|
||||
<BillDetailItem title={t('manual.amount')} value={<MoneyFormat money={bill.amount}/>}/>
|
||||
<BillDetailItems bill={bill} />
|
||||
<Button onClick={exportQRCode} style={{marginTop: 20}} theme={'solid'} type={'primary'}>Download QR
|
||||
code</Button>
|
||||
</>)
|
||||
@ -100,7 +91,7 @@ export default function Index() {
|
||||
</div>
|
||||
<div className={styles.billQrCode}>
|
||||
<div className={styles.QRCodeContainer}>
|
||||
<QRCode className={styles.qrCode} bill={billInfo}/>
|
||||
<QRCode size={250} className={styles.qrCode} bill={billInfo}/>
|
||||
</div>
|
||||
{billInfo && <div
|
||||
className={styles.billExpTime}> {t('manual.exp_time')} {dayjs(billInfo.expiration_time).format('HH:mm')} </div>}
|
||||
|
@ -11,23 +11,9 @@
|
||||
}
|
||||
|
||||
.billDetail {
|
||||
|
||||
padding: 30px 0 50px;
|
||||
}
|
||||
|
||||
.billDetailItem {
|
||||
display: flex;
|
||||
margin-bottom: 10px;
|
||||
align-items: center;
|
||||
}
|
||||
.billDetailItemTitle {
|
||||
font-weight: bold;
|
||||
width: 150px;
|
||||
}
|
||||
|
||||
.billDetailItemValue {
|
||||
color: #999999;
|
||||
}
|
||||
.billQrCode{
|
||||
text-align: center;
|
||||
margin-left: 150px;
|
||||
|
@ -80,6 +80,7 @@ const AppRouter = () => {
|
||||
// change ui locale
|
||||
const {i18n} = useTranslation()
|
||||
const locale = useMemo(()=>{
|
||||
document.body.setAttribute('data-lang', i18n.language)
|
||||
if(i18n.language === 'zh-CN') return zh_CN;
|
||||
else if(i18n.language === 'zh-TW') return zh_TW;
|
||||
return en_US;
|
||||
|
@ -1,4 +1,4 @@
|
||||
import {get, post} from "@/service/request.ts";
|
||||
import {get, post, put} from "@/service/request.ts";
|
||||
|
||||
export type BillQueryResult = {
|
||||
result: BillModel[];
|
||||
@ -23,7 +23,7 @@ function formatBillQueryResult(params: BillQueryParams, result: BillQueryResult)
|
||||
}
|
||||
|
||||
export async function billList(params: BillQueryParams) {
|
||||
const result = await get<BillQueryResult>('/bills', {params})
|
||||
const result = await get<BillQueryResult>('/bills', params)
|
||||
return formatBillQueryResult(params, result);
|
||||
}
|
||||
|
||||
@ -32,6 +32,12 @@ export function createManualBill(params: ManualCreateBillParam) {
|
||||
return post<{ id: number }>('/manual_payment', params)
|
||||
}
|
||||
|
||||
// 获取账单详情
|
||||
export function getBillDetail(id: number) {
|
||||
return get<BillModel>('/bills/' + id)
|
||||
}
|
||||
|
||||
// 作废订单
|
||||
export function cancelBill(id: number){
|
||||
return put('/bills/' + id)
|
||||
}
|
@ -1,15 +1,13 @@
|
||||
import axios from 'axios';
|
||||
import {stringify} from 'qs'
|
||||
import { BizError } from './types';
|
||||
|
||||
import {BizError} from './types';
|
||||
|
||||
const JSON_FORMAT: string = 'application/json';
|
||||
export type RequestMethod = 'get' | 'post' | 'put' | 'delete'
|
||||
const REQUEST_TIMEOUT = 300000; // 超时时长5min
|
||||
|
||||
const Axios = axios.create({
|
||||
baseURL: "/api",
|
||||
timeout:REQUEST_TIMEOUT,
|
||||
baseURL: AppConfig.API_PREFIX || '/api',
|
||||
timeout: REQUEST_TIMEOUT,
|
||||
headers: {'Content-Type': JSON_FORMAT}
|
||||
})
|
||||
|
||||
|
4
src/types/api.d.ts
vendored
4
src/types/api.d.ts
vendored
@ -1,4 +1,7 @@
|
||||
// 请求方式
|
||||
declare type RequestMethod = 'get' | 'post' | 'put' | 'delete'
|
||||
|
||||
// 接口返回数据类型
|
||||
declare interface APIResponse<T> {
|
||||
/**
|
||||
* 错误码,0:成功,其他失败
|
||||
@ -9,4 +12,5 @@ declare interface APIResponse<T> {
|
||||
* 非0情况下,提示信息
|
||||
*/
|
||||
message: string;
|
||||
request_id: string;
|
||||
}
|
3
src/vite-env.d.ts
vendored
3
src/vite-env.d.ts
vendored
@ -7,7 +7,8 @@ declare type AllType = string | number | object | undefined | null;
|
||||
declare const APP_SITE_URL:string;
|
||||
declare const AppConfig:{
|
||||
// 系统部署运行地址(主要用于支付二维码生成)
|
||||
SITE_URL:string
|
||||
SITE_URL:string;
|
||||
API_PREFIX: string;
|
||||
};
|
||||
|
||||
declare type BasicComponentProps = {
|
||||
|
@ -11,6 +11,7 @@ export default defineConfig(({mode}) => {
|
||||
define: {
|
||||
AppConfig: JSON.stringify({
|
||||
SITE_URL: process.env.APP_SITE_URL || null,
|
||||
API_PREFIX: process.env.APP_API_PREFIX || '/api',
|
||||
}),
|
||||
},
|
||||
resolve: {
|
||||
|
Loading…
x
Reference in New Issue
Block a user