✨ api联调
This commit is contained in:
parent
493f15f848
commit
1105a582e4
@ -19,6 +19,7 @@
|
||||
"@emotion/styled": "^11.11.5",
|
||||
"@mui/system": "^5.15.15",
|
||||
"ahooks": "^3.7.11",
|
||||
"axios": "^1.7.2",
|
||||
"clsx": "^2.1.1",
|
||||
"dayjs": "^1.11.11",
|
||||
"file-saver": "^2.0.5",
|
||||
@ -27,6 +28,7 @@
|
||||
"jspdf-autotable": "^3.8.2",
|
||||
"less": "^4.2.0",
|
||||
"qrcode.react": "^3.1.0",
|
||||
"qs": "^6.12.1",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-i18next": "^14.1.1",
|
||||
@ -36,6 +38,7 @@
|
||||
"@types/file-saver": "^2.0.7",
|
||||
"@types/lodash": "^4.17.1",
|
||||
"@types/node": "^20.12.11",
|
||||
"@types/qs": "^6.9.15",
|
||||
"@types/react": "^18.2.66",
|
||||
"@types/react-dom": "^18.2.22",
|
||||
"@typescript-eslint/eslint-plugin": "^7.2.0",
|
||||
|
7
src/components/bill/index.ts
Normal file
7
src/components/bill/index.ts
Normal file
@ -0,0 +1,7 @@
|
||||
import BillDetail from './detail.tsx'
|
||||
import {
|
||||
BillList
|
||||
} from './list.tsx'
|
||||
import useBillQRCode from './qr-code.tsx'
|
||||
|
||||
export {BillDetail, BillList, useBillQRCode}
|
@ -2,16 +2,17 @@ import {Table, Typography} from "@douyinfe/semi-ui";
|
||||
import {ColumnProps} from "@douyinfe/semi-ui/lib/es/table";
|
||||
import React, {useMemo} from "react";
|
||||
import {useTranslation} from "react-i18next";
|
||||
import dayjs from "dayjs";
|
||||
|
||||
import MoneyFormat from "@/components/money-format.tsx";
|
||||
import {Card} from "@/components/card";
|
||||
import './bill.less'
|
||||
import dayjs from "dayjs";
|
||||
|
||||
type BillListProps = {
|
||||
type: 'query' | 'reconciliation';
|
||||
operationRender?: (record: BillModel) => React.ReactNode;
|
||||
onRowSelection?: (selectedRowKeys?: (string | number)[]) => void;
|
||||
source: RecordList<BillModel>;
|
||||
source?: RecordList<BillModel>;
|
||||
onPageChange: () => void;
|
||||
loading?: boolean;
|
||||
}
|
||||
@ -24,38 +25,53 @@ export const BillList: React.FC<BillListProps> = (props) => {
|
||||
{
|
||||
title: '#',
|
||||
dataIndex: 'id',
|
||||
width: 80,
|
||||
width: 120,
|
||||
fixed: true,
|
||||
},
|
||||
{
|
||||
title: t('base.student_number'),
|
||||
dataIndex: 'student_number',
|
||||
width: 150,
|
||||
fixed: true,
|
||||
render: (value) => value ?? 'N/A'
|
||||
},
|
||||
{
|
||||
title: t('base.bill_number'),
|
||||
dataIndex: 'application_number',
|
||||
fixed: true,
|
||||
width: 150,
|
||||
},
|
||||
{
|
||||
title: t('bill.title_paid_at'),
|
||||
dataIndex: 'paid_at',
|
||||
render: (value) => dayjs(value).format('YYYY-MM-DD'),
|
||||
width: 150,
|
||||
render: (value) => value ? dayjs(value).format('YYYY-MM-DD') : 'N/A',
|
||||
},
|
||||
{
|
||||
title: t('bill.title_program_id'),
|
||||
dataIndex: 'program_id',
|
||||
title: t('bill.title_student_name'),
|
||||
dataIndex: 'student_english_name',
|
||||
width: 150,
|
||||
render: (_, record) => (<div>{record.student_english_name}<br/>{record.student_chinese_name}</div>)
|
||||
},
|
||||
{
|
||||
title: t('bill.title_program_name'),
|
||||
width: 250,
|
||||
dataIndex: i18n.language == 'en-US' ? 'programme_english_name' : 'programme_chinese_name',
|
||||
},
|
||||
{
|
||||
title: t('bill.title_department'),
|
||||
dataIndex: 'department',
|
||||
width: 200,
|
||||
dataIndex: i18n.language == 'en-US' ? 'department_english_name' : 'department_chinese_name',
|
||||
},
|
||||
{
|
||||
title: t('bill.title_year'),
|
||||
dataIndex: 'student_year',
|
||||
dataIndex: 'intake_year',
|
||||
width: 120,
|
||||
},
|
||||
{
|
||||
title: t('bill.title_semester'),
|
||||
dataIndex: 'student_semester',
|
||||
},
|
||||
{
|
||||
title: t('bill.title_student_name_en'),
|
||||
dataIndex: 'student_en_name',
|
||||
},
|
||||
{
|
||||
title: t('bill.title_student_name_sc'),
|
||||
dataIndex: 'student_sc_name',
|
||||
render: (_, record) => (`${record.student_tc_name}(${record.student_sc_name})`)
|
||||
dataIndex: 'intake_semester',
|
||||
width: 120,
|
||||
},
|
||||
{
|
||||
title: t('bill.title_bill_detail'),
|
||||
@ -63,21 +79,23 @@ export const BillList: React.FC<BillListProps> = (props) => {
|
||||
ellipsis: {showTitle: true},
|
||||
width: 220,
|
||||
render: (_, record) => (<div style={{fontSize: 13, lineHeight: 1.1}}>
|
||||
{record.detail.map((it,idx) => (<div key={idx}>{it.type}:<MoneyFormat money={it.amount}/></div>))}
|
||||
{record.detail?.map((it, idx) => (<div key={idx}>{it.type}:<MoneyFormat money={it.amount}/></div>))}
|
||||
</div>),
|
||||
},
|
||||
{
|
||||
title: t('bill.title_amount'),
|
||||
dataIndex: 'amount',
|
||||
width: 150,
|
||||
render: (_) => (<MoneyFormat money={_}/>),
|
||||
},
|
||||
{
|
||||
title: t('bill.title_pay_amount'),
|
||||
dataIndex: 'pay_amount',
|
||||
width: 150,
|
||||
render: (_, record) => {
|
||||
if (record.service_charge > 0) {
|
||||
if (record.service_charge && record.service_charge > 0) {
|
||||
return <div>
|
||||
<MoneyFormat money={record.pay_amount}/><br/>
|
||||
<MoneyFormat money={record.payment_amount}/><br/>
|
||||
<Typography.Text type={'quaternary'} size={'small'} style={{position: "absolute"}}>
|
||||
{t('bill.title_service_charge')}: <MoneyFormat money={record.service_charge}/>
|
||||
</Typography.Text>
|
||||
@ -89,21 +107,24 @@ export const BillList: React.FC<BillListProps> = (props) => {
|
||||
{
|
||||
title: t('bill.title_actual_payment_amount'),
|
||||
dataIndex: 'actual_payment_amount',
|
||||
width: 120,
|
||||
render: (_) => (<MoneyFormat money={_}/>),
|
||||
},
|
||||
{
|
||||
title: t('bill.title_pay_method'),
|
||||
dataIndex: 'pay_method',
|
||||
render: (_, {pay_method, payment_channel}) => (<div>
|
||||
width: 120,
|
||||
render: (_, {payment_method, payment_channel}) => (<div>
|
||||
{payment_channel}<br/>
|
||||
<Typography.Text type={'quaternary'} size={'small'} style={{position: "absolute"}}>
|
||||
({pay_method})
|
||||
({payment_method})
|
||||
</Typography.Text>
|
||||
</div>),
|
||||
},
|
||||
{
|
||||
title: t('bill.title_bill_status'),
|
||||
dataIndex: 'bill_status',
|
||||
width: 150,
|
||||
// render: value => dayjs(value).format('YYYY-MM-DD'),
|
||||
},
|
||||
]
|
||||
@ -111,6 +132,7 @@ export const BillList: React.FC<BillListProps> = (props) => {
|
||||
cols.push({
|
||||
title: t('bill.title_reconciliation_status'),
|
||||
dataIndex: 'apply_status',
|
||||
width: 150,
|
||||
// render: value => dayjs(value).format('YYYY-MM-DD'),
|
||||
})
|
||||
}
|
||||
@ -126,36 +148,34 @@ export const BillList: React.FC<BillListProps> = (props) => {
|
||||
return cols;
|
||||
}, [props.operationRender, props.type, i18n.language]);
|
||||
|
||||
const currentTotalAmount = useMemo(()=>{
|
||||
const currentTotalAmount = useMemo(() => {
|
||||
// 计算当前列表总金额
|
||||
return props.source.list.map(s=>s.amount).reduce((s,c)=>(s+c),0)
|
||||
},[props.source])
|
||||
return props.source?.list.map(s => Number(s.amount)).reduce((s, c) => (s + c), 0)
|
||||
}, [props.source])
|
||||
|
||||
return <Card
|
||||
title={t('bill.title_bill_list')}
|
||||
headerRight={<div className="bill-info">
|
||||
<div className="bill-info-item">
|
||||
<span className="bill-info-title">查询总金额: </span>
|
||||
<MoneyFormat money={props.source.pagination.recordTotal || 0}/>
|
||||
<span className="bill-info-title">{t('bill.query_amount_total')} :</span>
|
||||
<MoneyFormat money={props.source?.pagination.recordTotal || 0}/>
|
||||
</div>
|
||||
<div className="bill-info-item">
|
||||
<span className="bill-info-title">当前页总金额: </span>
|
||||
<span className="bill-info-title">{t('bill.query_amount_current_page')} :</span>
|
||||
<MoneyFormat money={currentTotalAmount || 0}/>
|
||||
</div>
|
||||
</div>}
|
||||
>
|
||||
<div className="bill-list-table">
|
||||
<Table<BillModel>
|
||||
sticky={{top: 60}}
|
||||
bordered
|
||||
scroll={{x: 600,y:300,scrollToFirstRowOnChange:true}}
|
||||
columns={columns}
|
||||
dataSource={props.source.list}
|
||||
dataSource={props.source?.list}
|
||||
rowKey={'id'}
|
||||
pagination={{
|
||||
currentPage: props.source.pagination.current,
|
||||
pageSize: props.source.pagination.pageSize,
|
||||
total: props.source.pagination.total,
|
||||
currentPage: props.source?.pagination.current,
|
||||
pageSize: props.source?.pagination.pageSize,
|
||||
total: props.source?.pagination.total,
|
||||
onPageChange: props.onPageChange,
|
||||
}}
|
||||
loading={props.loading}
|
||||
|
28
src/components/bill/qr-code.tsx
Normal file
28
src/components/bill/qr-code.tsx
Normal file
@ -0,0 +1,28 @@
|
||||
import React, {CSSProperties, useRef} from "react";
|
||||
import QRCodeSvg from "qrcode.react";
|
||||
import {saveAs} from "file-saver"
|
||||
|
||||
export type BillQrcodeProps = {
|
||||
size?: number;
|
||||
bill?: BillModel;
|
||||
className?: string;
|
||||
style?: CSSProperties;
|
||||
}
|
||||
const useBillQRCode = () => {
|
||||
const qrCodeRef = useRef<HTMLDivElement>(null)
|
||||
const QRCode: React.FC<BillQrcodeProps> = (props) => (
|
||||
<div style={props.style} className={props.className} ref={qrCodeRef} data-bill-id={props.bill?.id}>
|
||||
<QRCodeSvg size={props.size} value={'http://localhost:5173/pay?bill=123123123&from=qrcode'}/>
|
||||
</div>);
|
||||
const exportQRCode = () => {
|
||||
const canvas = qrCodeRef.current?.querySelector('canvas');
|
||||
if (!canvas) return;
|
||||
const billId = qrCodeRef.current?.getAttribute('data-bill-id') || Date.now().toString();
|
||||
saveAs(canvas.toDataURL(), `qrcode-${billId}.png`)
|
||||
}
|
||||
return {
|
||||
QRCode,
|
||||
exportQRCode
|
||||
}
|
||||
};
|
||||
export default useBillQRCode
|
@ -1,55 +1,108 @@
|
||||
import {Button, Col, Form, Row} from "@douyinfe/semi-ui";
|
||||
import React from "react";
|
||||
import React, {useMemo} from "react";
|
||||
import {Card} from "@/components/card";
|
||||
import {useTranslation} from "react-i18next";
|
||||
import {BillQueryParams} from "@/service/api/bill.ts";
|
||||
import dayjs from "dayjs";
|
||||
|
||||
type SearchFormProps = {
|
||||
onSearch?: () => void;
|
||||
onSearch?: (params: BillQueryParams) => void;
|
||||
showApply?: boolean;
|
||||
loading?: boolean;
|
||||
searchHeader?: React.ReactNode;
|
||||
searchFooter?: React.ReactNode;
|
||||
}
|
||||
|
||||
type SearchFormFields = {
|
||||
dateRange?: Date[];
|
||||
student_number?: string;
|
||||
bill_number?: string;
|
||||
pay_method?: string;
|
||||
bill_status?: string;
|
||||
apply_status?: string;
|
||||
}
|
||||
const SearchForm: React.FC<SearchFormProps> = (props) => {
|
||||
|
||||
const formSubmit = (value: SearchFormFields) => {
|
||||
const params: BillQueryParams = {}
|
||||
if (value.dateRange) {
|
||||
params.start_date = dayjs(value.dateRange[0]).format('YYYY-MM-DD');
|
||||
params.end_date = dayjs(value.dateRange[1]).format('YYYY-MM-DD');
|
||||
}
|
||||
if (value.student_number) {
|
||||
params.student_name = value.student_number;
|
||||
}
|
||||
// 对账状态
|
||||
if (value.apply_status) {
|
||||
params.apply_status = value.apply_status;
|
||||
}
|
||||
// 账单状态
|
||||
if (value.bill_status) {
|
||||
params.status = value.bill_status;
|
||||
}
|
||||
// 支付方式
|
||||
if (value.pay_method) {
|
||||
params.payment_method = value.pay_method;
|
||||
}
|
||||
props.onSearch?.(params);
|
||||
}
|
||||
const {t, i18n} = useTranslation();
|
||||
// 根据语言变化更新订单状态options
|
||||
const billStatusOptions = useMemo(() => {
|
||||
return [
|
||||
{value: `${i18n.language}pending`, label: t('bill.pay_status_pending')},
|
||||
{value: 'paid', label: t('bill.pay_status_paid')},
|
||||
{value: 'canceled', label: t('bill.pay_status_canceled')}
|
||||
]
|
||||
}, [i18n.language])
|
||||
// 根据语言变化更新对账状态options
|
||||
const applyStatusOptions = useMemo(() => {
|
||||
return [
|
||||
{value: 'pending', label: t('bill.reconciliation_status_pending')},
|
||||
{value: 'submitted', label: t('bill.reconciliation_status_submitted')}
|
||||
]
|
||||
}, [i18n.language])
|
||||
return (<Card style={{marginBottom: 20}}>
|
||||
{props.searchHeader}
|
||||
<div className="bill-search-form">
|
||||
<Form>
|
||||
<Form<SearchFormFields> onSubmit={formSubmit}>
|
||||
<Row type={'flex'} gutter={20}>
|
||||
<Col span={4}>
|
||||
<Form.DatePicker type={'dateRange'} field="date" label='Transaction Date'>
|
||||
<Form.DatePicker type={'dateRange'} field="dateRange" label='Transaction Date'
|
||||
style={{width: '100%'}}>
|
||||
</Form.DatePicker>
|
||||
</Col>
|
||||
<Col span={4}>
|
||||
<Form.Input field='student_number' label='Student Number' trigger='blur'
|
||||
placeholder='请输入姓名'/>
|
||||
<Form.Input field='student_number' label={t('base.student_number')} trigger='blur'
|
||||
placeholder={t('base.please_enter')}/>
|
||||
</Col>
|
||||
<Col span={4}>
|
||||
<Form.Input field='bill_number' label='Bill Number' trigger='blur'
|
||||
placeholder='请输入姓名'/>
|
||||
<Form.Input field='bill_number' label={t('base.bill_number')} trigger='blur'
|
||||
placeholder={t('base.please_enter')}/>
|
||||
</Col>
|
||||
<Col span={4}>
|
||||
<Form.Select showClear field="pay_method" label='支付方式' placeholder='请支付方式' style={{width: '100%'}}>
|
||||
<Form.Select showClear field="pay_method" label={t('bill.title_pay_method')}
|
||||
placeholder={t('base.please_select')} style={{width: '100%'}}>
|
||||
<Form.Select.Option value="operate">AsiaPay</Form.Select.Option>
|
||||
<Form.Select.Option value="rd">FlyWire</Form.Select.Option>
|
||||
<Form.Select.Option value="pm">PPS</Form.Select.Option>
|
||||
</Form.Select>
|
||||
</Col>
|
||||
<Col span={4}>
|
||||
<Form.Select showClear field="bill_status" label='账单状态' placeholder='请选择账单状态' style={{width: '100%'}}>
|
||||
<Form.Select.Option value="operate">未支付</Form.Select.Option>
|
||||
<Form.Select.Option value="rd">已支付</Form.Select.Option>
|
||||
<Form.Select.Option value="pm">已作废</Form.Select.Option>
|
||||
<Form.Select showClear field="bill_status" label={t('bill.pay_status')}
|
||||
placeholder={t('base.please_select')} style={{width: '100%'}}>
|
||||
{billStatusOptions.map((item,index) => (
|
||||
<Form.Select.Option key={index} value={item.value}>{item.label}</Form.Select.Option>))}
|
||||
</Form.Select>
|
||||
</Col>
|
||||
{props.showApply && <Col span={4}>
|
||||
<Form.Select showClear field="apply_status" label='对账状态' placeholder='请对账状态' style={{width: '100%'}}>
|
||||
<Form.Select.Option value="operate">未对账</Form.Select.Option>
|
||||
<Form.Select.Option value="rd">已对账</Form.Select.Option>
|
||||
<Form.Select showClear field="apply_status" label={t('bill.title_reconciliation_status')}
|
||||
placeholder={t('base.please_select')} style={{width: '100%'}}>
|
||||
{applyStatusOptions.map((item,index) => (
|
||||
<Form.Select.Option key={index} value={item.value}>{item.label}</Form.Select.Option>))}
|
||||
</Form.Select>
|
||||
</Col>}
|
||||
<Col span={4} style={{ display: 'flex', alignItems: 'flex-end',paddingBottom:12 }}>
|
||||
<Button style={{width: 100}} htmlType={'submit'} theme={'solid'} type={'primary'}>搜索</Button>
|
||||
<Col span={4} style={{display: 'flex', alignItems: 'flex-end', paddingBottom: 12}}>
|
||||
<Button loading={props.loading} style={{width: 100}} htmlType={'submit'} theme={'solid'}
|
||||
type={'primary'}>{t('base.btn_search_submit')}</Button>
|
||||
</Col>
|
||||
</Row>
|
||||
</Form>
|
||||
|
@ -1,8 +1,8 @@
|
||||
import React from "react";
|
||||
|
||||
type MoneyFormatProps = {
|
||||
money: number | string;
|
||||
currency?: 'USD' | 'HKD' | 'RMB';
|
||||
money?: number | string | null;
|
||||
currency?: 'US$' | 'HK$' | 'RMB';
|
||||
}
|
||||
|
||||
function formatCurrency(amount: string | number) {
|
||||
@ -22,8 +22,8 @@ function formatCurrency(amount: string | number) {
|
||||
return (isNegative ? '-' : '') + formattedIntPart + '.' + decimalPart;
|
||||
}
|
||||
|
||||
const MoneyFormat: React.FC<MoneyFormatProps> = ({money, currency = 'HKD'}) => {
|
||||
const MoneyFormat: React.FC<MoneyFormatProps> = ({money, currency = 'HK$'}) => {
|
||||
// 将货币数字转换为千分位格式且带2位小数
|
||||
return <span className={'money-format'}>{currency} {formatCurrency(money)}</span>
|
||||
return money?<span className={'money-format'}>{currency} {formatCurrency(money)}</span>:null
|
||||
}
|
||||
export default MoneyFormat;
|
@ -1,7 +1,23 @@
|
||||
{
|
||||
"base": {
|
||||
"bill_number": "Bill Number",
|
||||
"btn_search_submit": "Search",
|
||||
"please_enter": "Please Enter",
|
||||
"please_select": "Please Select",
|
||||
"student_number": "Student Number"
|
||||
},
|
||||
"bill": {
|
||||
"bill_number": "Bill Number",
|
||||
"download_receipt": "Download receipt",
|
||||
"pay_status": "Bill Status",
|
||||
"pay_status_canceled": "Canceled",
|
||||
"pay_status_paid": "Paid",
|
||||
"pay_status_pending": "Pending",
|
||||
"query_amount_current_page": "The total amount of current page",
|
||||
"query_amount_total": "The total Amount",
|
||||
"reconciliation_status_pending": "Pending",
|
||||
"reconciliation_status_submitted": "Submitted",
|
||||
"require_student_number": "Search Student Number",
|
||||
"title_actual_payment_amount": "Actually Paid",
|
||||
"title_amount": "Amount",
|
||||
"title_bill_detail": "Bill Detail",
|
||||
@ -12,11 +28,12 @@
|
||||
"title_pay_amount": "Pay Amount",
|
||||
"title_pay_method": "Pay Method",
|
||||
"title_program_id": "Program ID",
|
||||
"title_program_name": "Program",
|
||||
"title_reconciliation_status": "Reconciliation",
|
||||
"title_semester": "Semester",
|
||||
"title_service_charge": "Service Charge",
|
||||
"title_student_name": "Student Name",
|
||||
"title_student_name_en": "English Name",
|
||||
"title_student_name_sc": "Chinese Name",
|
||||
"title_year": "Year"
|
||||
},
|
||||
"error": {
|
||||
@ -41,9 +58,10 @@
|
||||
"bill_type": "Bill Type",
|
||||
"bill_type_required": "please select bill type",
|
||||
"btn_generate": "Generate Bill",
|
||||
"exp_time": "bill will expires at",
|
||||
"exp_time": "The bill will expires at",
|
||||
"student_number": "Student Number",
|
||||
"student_number_required": "required student number"
|
||||
"student_number_required": "required student number",
|
||||
"success": "Create bill success"
|
||||
},
|
||||
"pay": {
|
||||
"amount": "Amount",
|
||||
|
@ -1,7 +1,23 @@
|
||||
{
|
||||
"base": {
|
||||
"bill_number": "账单编号",
|
||||
"btn_search_submit": "搜索",
|
||||
"please_enter": "请输入",
|
||||
"please_select": "请选择",
|
||||
"student_number": "学号"
|
||||
},
|
||||
"bill": {
|
||||
"bill_number": "账单编号",
|
||||
"download_receipt": "下载收据",
|
||||
"pay_status": "账单状态",
|
||||
"pay_status_canceled": "已作废",
|
||||
"pay_status_paid": "已支付",
|
||||
"pay_status_pending": "未支付",
|
||||
"query_amount_current_page": "当前页总金额",
|
||||
"query_amount_total": "查询总金额",
|
||||
"reconciliation_status_pending": "未对账",
|
||||
"reconciliation_status_submitted": "已对账",
|
||||
"require_student_number": "请输入查询学号",
|
||||
"title_actual_payment_amount": "实付金额",
|
||||
"title_amount": "账单金额",
|
||||
"title_bill_detail": "账单详情",
|
||||
@ -12,11 +28,12 @@
|
||||
"title_pay_amount": "应付金额",
|
||||
"title_pay_method": "支付方式",
|
||||
"title_program_id": "专业ID",
|
||||
"title_program_name": "就读专业",
|
||||
"title_reconciliation_status": "对账状态",
|
||||
"title_semester": "学期",
|
||||
"title_service_charge": "手续费",
|
||||
"title_student_name": "学生姓名",
|
||||
"title_student_name_en": "英文名称",
|
||||
"title_student_name_sc": "中文名字",
|
||||
"title_year": "学年"
|
||||
},
|
||||
"error": {
|
||||
@ -43,7 +60,8 @@
|
||||
"btn_generate": "生成账单",
|
||||
"exp_time": "账单过期时间",
|
||||
"student_number": "学号",
|
||||
"student_number_required": "请填写学号"
|
||||
"student_number_required": "请填写学号",
|
||||
"success": "创建订单成功"
|
||||
},
|
||||
"pay": {
|
||||
"amount": "应付金额",
|
||||
|
@ -1,7 +1,23 @@
|
||||
{
|
||||
"base": {
|
||||
"bill_number": "账单编号",
|
||||
"btn_search_submit": "搜索",
|
||||
"please_enter": "请输入",
|
||||
"please_select": "请选择",
|
||||
"student_number": "学号"
|
||||
},
|
||||
"bill": {
|
||||
"bill_number": "账单编号",
|
||||
"download_receipt": "下载收据",
|
||||
"pay_status": "账单状态",
|
||||
"pay_status_canceled": "已作废",
|
||||
"pay_status_paid": "已支付",
|
||||
"pay_status_pending": "未支付",
|
||||
"query_amount_current_page": "当前页总金额",
|
||||
"query_amount_total": "查询总金额",
|
||||
"reconciliation_status_pending": "未对账",
|
||||
"reconciliation_status_submitted": "已对账",
|
||||
"require_student_number": "请输入查询学号",
|
||||
"title_actual_payment_amount": "實付金額",
|
||||
"title_amount": "帳單金額",
|
||||
"title_bill_detail": "帳單詳情",
|
||||
@ -12,11 +28,12 @@
|
||||
"title_pay_amount": "應付金額",
|
||||
"title_pay_method": "付款方式",
|
||||
"title_program_id": "專業ID",
|
||||
"title_program_name": "就读专业专业",
|
||||
"title_reconciliation_status": "對帳狀態",
|
||||
"title_semester": "學期",
|
||||
"title_service_charge": "手續費",
|
||||
"title_student_name": "学生姓名",
|
||||
"title_student_name_en": "英文名稱",
|
||||
"title_student_name_sc": "中文名字",
|
||||
"title_year": "學年"
|
||||
},
|
||||
"error": {
|
||||
@ -43,7 +60,8 @@
|
||||
"btn_generate": "產生帳單",
|
||||
"exp_time": "帳單過期時間",
|
||||
"student_number": "學號",
|
||||
"student_number_required": "請填入學號"
|
||||
"student_number_required": "請填入學號",
|
||||
"success": "创建订单成功"
|
||||
},
|
||||
"pay": {
|
||||
"amount": "应付金额",
|
||||
|
@ -2,75 +2,46 @@ import {BillList} from "@/components/bill/list.tsx";
|
||||
import {Button, Modal, Space} from "@douyinfe/semi-ui";
|
||||
import {GeneratePdf} from "@/service/generate-pdf.ts";
|
||||
import {useState} from "react";
|
||||
import {clone} from "lodash";
|
||||
import dayjs from "dayjs";
|
||||
// import dayjs from "dayjs";
|
||||
import SearchForm from "@/components/bill/search-form.tsx";
|
||||
import BillDetail from "@/components/bill/detail.tsx";
|
||||
import {useRequest} from "ahooks";
|
||||
import {billList, BillQueryParams} from "@/service/api/bill.ts";
|
||||
|
||||
|
||||
const mockBill: BillModel = {
|
||||
actual_payment_amount: 110,
|
||||
amount: 110,
|
||||
application_no: "123123",
|
||||
apply_status: "pending",
|
||||
bill_status: "pending",
|
||||
created_at: new Date(),
|
||||
currency: "HKD",
|
||||
department: "经管学院",
|
||||
expiration_time: dayjs().add(30, "minute").toDate(),
|
||||
id: 1123123,
|
||||
paid_area: "HongKong,China",
|
||||
paid_at: new Date(),
|
||||
pay_amount: 110,
|
||||
pay_method: "WechatHk",
|
||||
payment_channel: "AsiaPay",
|
||||
program_id: 123123,
|
||||
service_charge: 0,
|
||||
student_en_name: "SanF Chung",
|
||||
student_no: "123123",
|
||||
student_sc_name: "张三丰",
|
||||
student_semester: "1",
|
||||
student_tc_name: "张三丰",
|
||||
student_year: "2024",
|
||||
updated_at: "",
|
||||
detail: [
|
||||
{amount: 55, bill_id: 1123123, id: 1, type: "APPLICATION FEE"},
|
||||
{amount: 50, bill_id: 1123123, id: 1, type: "TUITION FEE"},
|
||||
{amount: 5, bill_id: 1123123, id: 1, type: "VISA FEE"},
|
||||
]
|
||||
}
|
||||
const BillQuery = () => {
|
||||
const [data, ] = useState<RecordList<BillModel>>({
|
||||
list: Array(10).fill(mockBill).map((it, i) => {
|
||||
const s = clone(it);
|
||||
s.id = i;
|
||||
if (i % 2 == 0) s.service_charge = 10
|
||||
return s;
|
||||
}),
|
||||
pagination: {current: 1, pageSize: 10, total: 250,recordTotal:213123}
|
||||
});
|
||||
const [showBill,setShowBill] = useState<BillModel>()
|
||||
const operation = (_record:BillModel)=>{
|
||||
// const [data, ] = useState<RecordList<BillModel>>();
|
||||
const [showBill, setShowBill] = useState<BillModel>()
|
||||
const [queryParams, setBillQueryParams] = useState<BillQueryParams>({});
|
||||
const {data, loading} = useRequest(() => billList(queryParams), {
|
||||
refreshDeps: [queryParams]
|
||||
})
|
||||
const operation = (_record: BillModel) => {
|
||||
return (<Space>
|
||||
<Button size={'small'} theme={'solid'} type={'primary'}>作废</Button>
|
||||
<Button onClick={()=>setShowBill(_record)} size={'small'} theme={'solid'} type={'primary'}>二维码</Button>
|
||||
<Button onClick={()=>GeneratePdf('111.pdf')} size={'small'} theme={'solid'} type={'primary'}>下载支付收据</Button>
|
||||
<Button onClick={() => setShowBill(_record)} size={'small'} theme={'solid'} type={'primary'}>二维码</Button>
|
||||
<Button onClick={() => GeneratePdf('111.pdf')} size={'small'} theme={'solid'}
|
||||
type={'primary'}>下载支付收据</Button>
|
||||
</Space>)
|
||||
}
|
||||
return (<div>
|
||||
<SearchForm showApply />
|
||||
<BillList type={'query'} operationRender={operation} source={data} onPageChange={function (): void {
|
||||
throw new Error("Function not implemented.");
|
||||
}} />
|
||||
<SearchForm showApply loading={loading} onSearch={setBillQueryParams}/>
|
||||
<BillList
|
||||
type={'query'} loading={loading}
|
||||
operationRender={operation} source={data}
|
||||
onPageChange={function (): void {
|
||||
throw new Error("Function not implemented.");
|
||||
}}
|
||||
/>
|
||||
<Modal
|
||||
title="View QR code"
|
||||
visible={!!showBill}
|
||||
onOk={()=>{}}
|
||||
onCancel={()=>setShowBill(undefined)} //>=1.16.0
|
||||
onOk={() => {
|
||||
}}
|
||||
onCancel={() => setShowBill(undefined)} //>=1.16.0
|
||||
closeOnEsc={true}
|
||||
footerFill={true}
|
||||
>
|
||||
{showBill && <BillDetail bill={showBill} />}
|
||||
{showBill && <BillDetail bill={showBill}/>}
|
||||
</Modal>
|
||||
</div>)
|
||||
}
|
||||
|
@ -1,63 +1,105 @@
|
||||
import {Button, Form, Space} from "@douyinfe/semi-ui";
|
||||
import {Button, Form, Space, Toast} from "@douyinfe/semi-ui";
|
||||
import {useTranslation} from "react-i18next";
|
||||
import {saveAs } from "file-saver"
|
||||
import QRCode from "qrcode.react";
|
||||
import {useRef} from "react";
|
||||
import styles from './manual.module.less'
|
||||
import {Card} from "@/components/card";
|
||||
import {ReactNode, useRef, useState} from "react";
|
||||
|
||||
const BillDetailItem = (item:{title:string;value:string})=>{
|
||||
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 styles from './manual.module.less'
|
||||
import {createManualBill, getBillDetail} from "@/service/api/bill.ts";
|
||||
import {useSetState} from "ahooks";
|
||||
import {BizError} from "@/service/types.ts";
|
||||
import {IconAlertTriangle} from "@douyinfe/semi-icons";
|
||||
|
||||
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() {
|
||||
const {t} = useTranslation()
|
||||
const qrCodeRef = useRef<HTMLDivElement>(null)
|
||||
const downloadQRCode = ()=>{
|
||||
const canvas = qrCodeRef.current?.querySelector('canvas');
|
||||
if(!canvas) return
|
||||
saveAs(canvas.toDataURL(), 'qrcode.png')
|
||||
const frm = useRef<Form<ManualCreateBillParam>>(null)
|
||||
const [billInfo, setBillInfo] = useState<BillModel>()
|
||||
const {exportQRCode, QRCode} = useBillQRCode();
|
||||
const [state, setState] = useSetState({
|
||||
loading: false,
|
||||
errorMessage: ''
|
||||
})
|
||||
|
||||
const handleSubmit = (values: ManualCreateBillParam) => {
|
||||
setState({loading: true})
|
||||
createManualBill(values).then((ret) => {
|
||||
frm.current?.formApi.reset();
|
||||
Toast.info({
|
||||
content: t('manual.success'),
|
||||
})
|
||||
getBillDetail(ret.id).then(setBillInfo);
|
||||
}).catch((e: BizError) => {
|
||||
setState({errorMessage: e.message})
|
||||
}).finally(() => {
|
||||
setState({loading: false})
|
||||
})
|
||||
}
|
||||
|
||||
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}/>}/>
|
||||
<Button onClick={exportQRCode} style={{marginTop: 20}} theme={'solid'} type={'primary'}>Download QR
|
||||
code</Button>
|
||||
</>)
|
||||
}
|
||||
return (<Card>
|
||||
<div className={styles.manualPage}>
|
||||
<div className={styles.generateForm}>
|
||||
<Form layout='horizontal' onValueChange={values => console.log(values)}>
|
||||
<Form<ManualCreateBillParam>
|
||||
layout='horizontal' onValueChange={() => setState({errorMessage: ''})}
|
||||
onSubmit={handleSubmit} ref={frm}>
|
||||
<Form.Select
|
||||
field="bill_type" style={{width: 176}}
|
||||
label={t('manual.bill_type')}
|
||||
placeholder={t('manual.bill_type')}
|
||||
rules={[{required: true, message: t('manual.bill_type_required')}]}
|
||||
>
|
||||
<Form.Select.Option value="admin">TUITION FEE</Form.Select.Option>
|
||||
<Form.Select.Option value="user">CAUTION FEE</Form.Select.Option>
|
||||
<Form.Select.Option value="guest">APPLICATION FEE</Form.Select.Option>
|
||||
{
|
||||
BillTypes.map((it, idx) => (
|
||||
<Form.Select.Option key={idx} value={it.label}>{it.label}</Form.Select.Option>))
|
||||
}
|
||||
</Form.Select>
|
||||
<Form.Input
|
||||
field='amount' label={t('manual.amount')} style={{minWidth: 120}}
|
||||
placeholder={t('manual.amount')}
|
||||
rules={[{required: true, message: t('manual.amount_required')}]}
|
||||
/>
|
||||
<Form.Input
|
||||
field='student_number' label={t('manual.student_number')} style={{minWidth: 150}}
|
||||
placeholder={t('manual.student_number')}
|
||||
rules={[{required: true, message: t('manual.student_number_required')}]}
|
||||
/>
|
||||
<div className={styles.generateButtonContainer}>
|
||||
<Button htmlType="submit">{t('manual.btn_generate')}</Button>
|
||||
<Space>
|
||||
<Button loading={state.loading} htmlType="submit">{t('manual.btn_generate')}</Button>
|
||||
{state.errorMessage && <div className={'semi-form-field-error-message'}>
|
||||
<IconAlertTriangle/>{state.errorMessage}</div>}
|
||||
</Space>
|
||||
</div>
|
||||
</Form>
|
||||
|
||||
</div>
|
||||
<Space className={styles.billDetail} align={'start'}>
|
||||
<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 style={{minWidth: 250}}>
|
||||
<BillInfo bill={billInfo}/>
|
||||
</div>
|
||||
<div className={styles.billQrCode}>
|
||||
<div className={styles.QRCodeContainer}>
|
||||
<div className={styles.qrCode} ref={qrCodeRef}>
|
||||
<QRCode size={250} value={'http://localhost:5173/pay?bill=123123123&from=qrcode'} />
|
||||
</div>
|
||||
<QRCode className={styles.qrCode} bill={billInfo}/>
|
||||
</div>
|
||||
<div className={styles.billExpTime}> {t('manual.exp_time')} {'12:00'} </div>
|
||||
</div>
|
||||
|
@ -40,4 +40,7 @@
|
||||
background-color: #f8f9fa;
|
||||
padding: 25px;
|
||||
border: dashed 1px #ccc;
|
||||
}
|
||||
.formError{
|
||||
|
||||
}
|
37
src/service/api/bill.ts
Normal file
37
src/service/api/bill.ts
Normal file
@ -0,0 +1,37 @@
|
||||
import {get, post} from "@/service/request.ts";
|
||||
|
||||
export type BillQueryResult = {
|
||||
result: BillModel[];
|
||||
total_count: number;
|
||||
query_total_amount: number;
|
||||
}
|
||||
export type BillQueryParams = Partial<BillQueryParam>;
|
||||
const DEFAULT_PAGE_SIZE = 10;
|
||||
|
||||
function formatBillQueryResult(params: BillQueryParams, result: BillQueryResult) {
|
||||
// 将 BillQueryResult 转成成 RecordList
|
||||
const formatData: RecordList<BillModel> = {
|
||||
list: result.result,
|
||||
pagination: {
|
||||
total: result.total_count,
|
||||
pageSize: params.page_size || DEFAULT_PAGE_SIZE,
|
||||
current: params.page_number || 1,
|
||||
recordTotal: Number(result.query_total_amount || 0)
|
||||
}
|
||||
}
|
||||
return formatData
|
||||
}
|
||||
|
||||
export async function billList(params: BillQueryParams) {
|
||||
const result = await get<BillQueryResult>('/bills', {params})
|
||||
return formatBillQueryResult(params, result);
|
||||
}
|
||||
|
||||
//现场支付创建账单接口
|
||||
export function createManualBill(params: ManualCreateBillParam) {
|
||||
return post<{ id: number }>('/manual_payment', params)
|
||||
}
|
||||
|
||||
export function getBillDetail(id: number) {
|
||||
return get<BillModel>('/bills/' + id)
|
||||
}
|
37
src/service/bill-types.ts
Normal file
37
src/service/bill-types.ts
Normal file
@ -0,0 +1,37 @@
|
||||
/**
|
||||
* CF CAUTION FEE
|
||||
* SU STUDENT UNION FEE
|
||||
* TF TUITION FEE
|
||||
* CP CREDIT POINT
|
||||
* CB BALANCE AS AT 30 JUN 2020
|
||||
* PF APPLICATION FEE
|
||||
* OF OTHER FEE
|
||||
* LT LATE PAYMENT OF TUITION FEE
|
||||
* LA LATE APPLICATION FEE
|
||||
* DF DOCUMENT FEE
|
||||
* SC STUDENT CARD
|
||||
* SV STUDENT VISA
|
||||
* SE SUPPLEMENTARY EXAMINATION
|
||||
* SM APPEAL AGAINST ASSESSMENT RESULTS
|
||||
* TN TRANSFER OF CURRICULUM
|
||||
* IN ADMINISTRATIVE FEE
|
||||
*/
|
||||
|
||||
export const BillTypes = [
|
||||
{value:"CF",label:'CAUTION FEE'},
|
||||
{value:"SU",label:'STUDENT UNION FEE'},
|
||||
{value:"TF",label:'TUITION FEE'},
|
||||
{value:"CP",label:'CREDIT POINT'},
|
||||
{value:"CB",label:'BALANCE AS AT 30 JUN 2020'},
|
||||
{value:"PF",label:'APPLICATION FEE'},
|
||||
{value:"OF",label:'OTHER FEE'},
|
||||
{value:"LT",label:'LATE PAYMENT OF TUITION FEE'},
|
||||
{value:"LA",label:'LATE APPLICATION FEE'},
|
||||
{value:"DF",label:'DOCUMENT FEE'},
|
||||
{value:"SC",label:'STUDENT CARD'},
|
||||
{value:"SV",label:'STUDENT VISA'},
|
||||
{value:"SE",label:'SUPPLEMENTARY EXAMINATION'},
|
||||
{value:"SM",label:'APPEAL AGAINST ASSESSMENT RESULTS'},
|
||||
{value:"TN",label:'TRANSFER OF CURRICULUM'},
|
||||
{value:"IN",label:'ADMINISTRATIVE FEE'},
|
||||
]
|
81
src/service/request.ts
Normal file
81
src/service/request.ts
Normal file
@ -0,0 +1,81 @@
|
||||
import axios from 'axios';
|
||||
import {stringify} from 'qs'
|
||||
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,
|
||||
headers: {'Content-Type': JSON_FORMAT}
|
||||
})
|
||||
|
||||
|
||||
// 请求前拦截
|
||||
Axios.interceptors.request.use(config => {
|
||||
const token = localStorage.getItem('payment_front_token');
|
||||
if (token) {
|
||||
config.headers['Authorization'] = `Bearer ${token}`;
|
||||
}
|
||||
if (config.data && config.data instanceof FormData) {
|
||||
config.headers['Content-Type'] = 'multipart/form-data';
|
||||
}
|
||||
return config
|
||||
}, err => {
|
||||
return Promise.reject(err)
|
||||
})
|
||||
|
||||
export function request<T>(url: string, method: RequestMethod, data: AllType = null, getOriginResult = false) {
|
||||
return new Promise<T>((resolve, reject) => {
|
||||
Axios.request<APIResponse<T>>({
|
||||
url,
|
||||
method,
|
||||
data,
|
||||
}).then(res => {
|
||||
if (res.status != 200) {
|
||||
reject(new BizError("Service Internal Exception,Please Try Later!", res.status))
|
||||
return;
|
||||
}
|
||||
// const
|
||||
const {code, message, data} = res.data
|
||||
if (code == 0) {
|
||||
if (getOriginResult) {
|
||||
resolve(res.data as unknown as T)
|
||||
return;
|
||||
}
|
||||
resolve(data as unknown as T)
|
||||
} else {
|
||||
reject(new BizError(message, code, data as unknown as AllType))
|
||||
}
|
||||
}).catch(e => {
|
||||
reject(new BizError(e.message, 500))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
export function post<T>(url: string, data: AllType = {}, returnOrigin = false) {
|
||||
return request<T>(url, 'post', data, returnOrigin)
|
||||
}
|
||||
|
||||
export function get<T>(url: string, data: AllType = null, returnOrigin = false) {
|
||||
if (data) {
|
||||
url += (url.indexOf('?') === -1 ? '?' : '&') + stringify(data)
|
||||
}
|
||||
return request<T>(url, 'get', data, returnOrigin)
|
||||
}
|
||||
|
||||
export function put<T>(url: string, data: AllType = {}) {
|
||||
return request<T>(url, 'put', data)
|
||||
}
|
||||
|
||||
export function getFileBlob(url: string) {
|
||||
return new Promise<Blob>((resolve, reject) => {
|
||||
fetch(url).then(res => res.blob()).then(res => {
|
||||
resolve(res)
|
||||
}).catch(reject);
|
||||
});
|
||||
}
|
13
src/service/types.ts
Normal file
13
src/service/types.ts
Normal file
@ -0,0 +1,13 @@
|
||||
export class BizError extends Error {
|
||||
/**
|
||||
* 错误码
|
||||
*/
|
||||
code = 1;
|
||||
data: string | number | object | undefined | null;
|
||||
|
||||
constructor(message: string, code = 1, data?: AllType) {
|
||||
super(message);
|
||||
this.code = code;
|
||||
this.data = data;
|
||||
}
|
||||
}
|
12
src/types/api.d.ts
vendored
Normal file
12
src/types/api.d.ts
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
|
||||
declare interface APIResponse<T> {
|
||||
/**
|
||||
* 错误码,0:成功,其他失败
|
||||
*/
|
||||
code: number;
|
||||
data?: T;
|
||||
/**
|
||||
* 非0情况下,提示信息
|
||||
*/
|
||||
message: string;
|
||||
}
|
80
src/types/bill.d.ts
vendored
80
src/types/bill.d.ts
vendored
@ -1,34 +1,64 @@
|
||||
|
||||
declare type BaseDate = number | Date | string | null;
|
||||
|
||||
// 现场支付账单数据
|
||||
declare type ManualCreateBillParam = {
|
||||
bill_type:string;
|
||||
amount:decimal;
|
||||
student_number:string;
|
||||
}
|
||||
declare type BillDetail = {
|
||||
id: string | number;
|
||||
bill_id: string | number;
|
||||
type: string;
|
||||
amount: number;
|
||||
amount: decimal;
|
||||
}
|
||||
/**
|
||||
* 账单查询参数
|
||||
*/
|
||||
declare type BillQueryParam = {
|
||||
page_size:int;
|
||||
page_number:int;
|
||||
status:string;
|
||||
apply_status:string;
|
||||
student_name:string;
|
||||
payment_method:string;
|
||||
start_date:string;
|
||||
end_date:string;
|
||||
}
|
||||
/**
|
||||
* 账单模型
|
||||
*/
|
||||
declare type BillModel = {
|
||||
id: string | number;
|
||||
student_no: string;
|
||||
application_no: string;
|
||||
student_sc_name: string;
|
||||
student_tc_name: string;
|
||||
student_en_name: string;
|
||||
program_id: string | number;
|
||||
department: string;
|
||||
student_year: string;
|
||||
student_semester: string;
|
||||
amount: number;
|
||||
service_charge: number;
|
||||
pay_amount: number;
|
||||
actual_payment_amount: number;
|
||||
pay_method: string;
|
||||
currency: string;
|
||||
payment_channel: string;
|
||||
expiration_time: string | Date | number;
|
||||
bill_status: string;
|
||||
id: number;
|
||||
student_number: string;
|
||||
application_number?: null | string | number;
|
||||
student_tc_name?: string;
|
||||
student_sc_name?: string;
|
||||
student_chinese_name: string;
|
||||
student_english_name: string;
|
||||
programme_chinese_name: string;
|
||||
programme_english_name: string;
|
||||
department_chinese_name: string;
|
||||
department_english_name: string;
|
||||
intake_year: string;
|
||||
intake_semester: string;
|
||||
amount: number|string;
|
||||
service_charge?: null | number;
|
||||
payment_amount?: null | number;
|
||||
actual_payment_amount?: null | number;
|
||||
payment_method?: null | string | number;
|
||||
currency?: null | string | number;
|
||||
payment_channel?: null | string | number;
|
||||
expiration_time?: BaseDate;
|
||||
status: string;
|
||||
apply_status: string;
|
||||
paid_area: string;
|
||||
paid_at: string | Date | number;
|
||||
created_at: string | Date | number;
|
||||
updated_at: string | Date | number;
|
||||
paid_area?: null | string | number;
|
||||
paid_at?:BaseDate;
|
||||
merchant_ref?: null | string | number;
|
||||
payment_id?: null | string | number;
|
||||
create_at: BaseDate;
|
||||
update_at: BaseDate;
|
||||
|
||||
detail: BillDetail[]
|
||||
detail?: BillDetail[]
|
||||
}
|
9
src/vite-env.d.ts
vendored
9
src/vite-env.d.ts
vendored
@ -1,7 +1,14 @@
|
||||
/// <reference types="vite/client" />
|
||||
/// <reference types="@types/auth" />
|
||||
|
||||
declare const APP_DEFAULT_PATH:string;
|
||||
declare type decimal = number;
|
||||
declare type int = number;
|
||||
declare type AllType = string | number | object | undefined | null;
|
||||
|
||||
interface ImportMetaEnv {
|
||||
// 系统部署运行地址(主要用于支付二维码生成)
|
||||
readonly VITE_APP_SITE_URL: string
|
||||
}
|
||||
|
||||
declare type BasicComponentProps = {
|
||||
children?: React.ReactNode;
|
||||
|
@ -8,12 +8,22 @@ export default defineConfig(({mode}) => {
|
||||
plugins: [react()],
|
||||
base: mode == 'test' ? './' : '/',
|
||||
define: {
|
||||
APP_DEFAULT_PATH: JSON.stringify('/')
|
||||
APP_DEFAULT_PATH: JSON.stringify('/'),
|
||||
APP_SITE_URL: JSON.stringify(process.env.VITE_APP_SITE_URL)
|
||||
},
|
||||
resolve: {
|
||||
alias: {
|
||||
'@': resolve(__dirname, './src')
|
||||
}
|
||||
},
|
||||
server:{
|
||||
proxy:{
|
||||
'/api': {
|
||||
target: 'http://43.136.175.109:50000',
|
||||
changeOrigin: true,
|
||||
//rewrite: (path) => path.replace(/^\/api/, '')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
163
yarn.lock
163
yarn.lock
@ -853,6 +853,11 @@
|
||||
resolved "https://registry.npmmirror.com/@types/prop-types/-/prop-types-15.7.12.tgz#12bb1e2be27293c1406acb6af1c3f3a1481d98c6"
|
||||
integrity sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==
|
||||
|
||||
"@types/qs@^6.9.15":
|
||||
version "6.9.15"
|
||||
resolved "https://registry.npmmirror.com/@types/qs/-/qs-6.9.15.tgz#adde8a060ec9c305a82de1babc1056e73bd64dce"
|
||||
integrity sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==
|
||||
|
||||
"@types/raf@^3.4.0":
|
||||
version "3.4.3"
|
||||
resolved "https://registry.npmmirror.com/@types/raf/-/raf-3.4.3.tgz#85f1d1d17569b28b8db45e16e996407a56b0ab04"
|
||||
@ -1039,11 +1044,25 @@ async-validator@^3.5.0:
|
||||
resolved "https://registry.npmmirror.com/async-validator/-/async-validator-3.5.2.tgz#68e866a96824e8b2694ff7a831c1a25c44d5e500"
|
||||
integrity sha512-8eLCg00W9pIRZSB781UUX/H6Oskmm8xloZfr09lz5bikRpBVDlJ3hRVuxxP1SxcwsEYfJ4IU8Q19Y8/893r3rQ==
|
||||
|
||||
asynckit@^0.4.0:
|
||||
version "0.4.0"
|
||||
resolved "https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
|
||||
integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==
|
||||
|
||||
atob@^2.1.2:
|
||||
version "2.1.2"
|
||||
resolved "https://registry.npmmirror.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9"
|
||||
integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==
|
||||
|
||||
axios@^1.7.2:
|
||||
version "1.7.2"
|
||||
resolved "https://registry.npmmirror.com/axios/-/axios-1.7.2.tgz#b625db8a7051fbea61c35a3cbb3a1daa7b9c7621"
|
||||
integrity sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw==
|
||||
dependencies:
|
||||
follow-redirects "^1.15.6"
|
||||
form-data "^4.0.0"
|
||||
proxy-from-env "^1.1.0"
|
||||
|
||||
babel-plugin-macros@^3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.npmmirror.com/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz#9ef6dc74deb934b4db344dc973ee851d148c50c1"
|
||||
@ -1105,6 +1124,17 @@ btoa@^1.2.1:
|
||||
resolved "https://registry.npmmirror.com/btoa/-/btoa-1.2.1.tgz#01a9909f8b2c93f6bf680ba26131eb30f7fa3d73"
|
||||
integrity sha512-SB4/MIGlsiVkMcHmT+pSmIPoNDoHg+7cMzmt3Uxt628MTz2487DKSqK/fuhFBrkuqrYv5UCEnACpF4dTFNKc/g==
|
||||
|
||||
call-bind@^1.0.7:
|
||||
version "1.0.7"
|
||||
resolved "https://registry.npmmirror.com/call-bind/-/call-bind-1.0.7.tgz#06016599c40c56498c18769d2730be242b6fa3b9"
|
||||
integrity sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==
|
||||
dependencies:
|
||||
es-define-property "^1.0.0"
|
||||
es-errors "^1.3.0"
|
||||
function-bind "^1.1.2"
|
||||
get-intrinsic "^1.2.4"
|
||||
set-function-length "^1.2.1"
|
||||
|
||||
callsites@^3.0.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.npmmirror.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73"
|
||||
@ -1185,6 +1215,13 @@ color-name@~1.1.4:
|
||||
resolved "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
|
||||
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
|
||||
|
||||
combined-stream@^1.0.8:
|
||||
version "1.0.8"
|
||||
resolved "https://registry.npmmirror.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
|
||||
integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
|
||||
dependencies:
|
||||
delayed-stream "~1.0.0"
|
||||
|
||||
compute-scroll-into-view@^1.0.20:
|
||||
version "1.0.20"
|
||||
resolved "https://registry.npmmirror.com/compute-scroll-into-view/-/compute-scroll-into-view-1.0.20.tgz#1768b5522d1172754f5d0c9b02de3af6be506a43"
|
||||
@ -1283,6 +1320,20 @@ deep-is@^0.1.3:
|
||||
resolved "https://registry.npmmirror.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831"
|
||||
integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==
|
||||
|
||||
define-data-property@^1.1.4:
|
||||
version "1.1.4"
|
||||
resolved "https://registry.npmmirror.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e"
|
||||
integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==
|
||||
dependencies:
|
||||
es-define-property "^1.0.0"
|
||||
es-errors "^1.3.0"
|
||||
gopd "^1.0.1"
|
||||
|
||||
delayed-stream@~1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
|
||||
integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==
|
||||
|
||||
dir-glob@^3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.npmmirror.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f"
|
||||
@ -1321,6 +1372,18 @@ error-ex@^1.3.1:
|
||||
dependencies:
|
||||
is-arrayish "^0.2.1"
|
||||
|
||||
es-define-property@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.npmmirror.com/es-define-property/-/es-define-property-1.0.0.tgz#c7faefbdff8b2696cf5f46921edfb77cc4ba3845"
|
||||
integrity sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==
|
||||
dependencies:
|
||||
get-intrinsic "^1.2.4"
|
||||
|
||||
es-errors@^1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.npmmirror.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f"
|
||||
integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==
|
||||
|
||||
esbuild@^0.20.1:
|
||||
version "0.20.2"
|
||||
resolved "https://registry.npmmirror.com/esbuild/-/esbuild-0.20.2.tgz#9d6b2386561766ee6b5a55196c6d766d28c87ea1"
|
||||
@ -1554,6 +1617,20 @@ flatted@^3.2.9:
|
||||
resolved "https://registry.npmmirror.com/flatted/-/flatted-3.3.1.tgz#21db470729a6734d4997002f439cb308987f567a"
|
||||
integrity sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==
|
||||
|
||||
follow-redirects@^1.15.6:
|
||||
version "1.15.6"
|
||||
resolved "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.15.6.tgz#7f815c0cda4249c74ff09e95ef97c23b5fd0399b"
|
||||
integrity sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==
|
||||
|
||||
form-data@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.npmmirror.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452"
|
||||
integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==
|
||||
dependencies:
|
||||
asynckit "^0.4.0"
|
||||
combined-stream "^1.0.8"
|
||||
mime-types "^2.1.12"
|
||||
|
||||
fs.realpath@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.npmmirror.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
|
||||
@ -1574,6 +1651,17 @@ gensync@^1.0.0-beta.2:
|
||||
resolved "https://registry.npmmirror.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0"
|
||||
integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==
|
||||
|
||||
get-intrinsic@^1.1.3, get-intrinsic@^1.2.4:
|
||||
version "1.2.4"
|
||||
resolved "https://registry.npmmirror.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz#e385f5a4b5227d449c3eabbad05494ef0abbeadd"
|
||||
integrity sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==
|
||||
dependencies:
|
||||
es-errors "^1.3.0"
|
||||
function-bind "^1.1.2"
|
||||
has-proto "^1.0.1"
|
||||
has-symbols "^1.0.3"
|
||||
hasown "^2.0.0"
|
||||
|
||||
glob-parent@^5.1.2:
|
||||
version "5.1.2"
|
||||
resolved "https://registry.npmmirror.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4"
|
||||
@ -1624,6 +1712,13 @@ globby@^11.1.0:
|
||||
merge2 "^1.4.1"
|
||||
slash "^3.0.0"
|
||||
|
||||
gopd@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.npmmirror.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c"
|
||||
integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==
|
||||
dependencies:
|
||||
get-intrinsic "^1.1.3"
|
||||
|
||||
graceful-fs@^4.1.2:
|
||||
version "4.2.11"
|
||||
resolved "https://registry.npmmirror.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3"
|
||||
@ -1644,6 +1739,23 @@ has-flag@^4.0.0:
|
||||
resolved "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b"
|
||||
integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
|
||||
|
||||
has-property-descriptors@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.npmmirror.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854"
|
||||
integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==
|
||||
dependencies:
|
||||
es-define-property "^1.0.0"
|
||||
|
||||
has-proto@^1.0.1:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.npmmirror.com/has-proto/-/has-proto-1.0.3.tgz#b31ddfe9b0e6e9914536a6ab286426d0214f77fd"
|
||||
integrity sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==
|
||||
|
||||
has-symbols@^1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.npmmirror.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8"
|
||||
integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==
|
||||
|
||||
hasown@^2.0.0:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.npmmirror.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003"
|
||||
@ -1933,6 +2045,18 @@ micromatch@^4.0.4:
|
||||
braces "^3.0.2"
|
||||
picomatch "^2.3.1"
|
||||
|
||||
mime-db@1.52.0:
|
||||
version "1.52.0"
|
||||
resolved "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70"
|
||||
integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==
|
||||
|
||||
mime-types@^2.1.12:
|
||||
version "2.1.35"
|
||||
resolved "https://registry.npmmirror.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a"
|
||||
integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==
|
||||
dependencies:
|
||||
mime-db "1.52.0"
|
||||
|
||||
mime@^1.4.1:
|
||||
version "1.6.0"
|
||||
resolved "https://registry.npmmirror.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"
|
||||
@ -1985,6 +2109,11 @@ object-assign@^4.1.1:
|
||||
resolved "https://registry.npmmirror.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
|
||||
integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==
|
||||
|
||||
object-inspect@^1.13.1:
|
||||
version "1.13.1"
|
||||
resolved "https://registry.npmmirror.com/object-inspect/-/object-inspect-1.13.1.tgz#b96c6109324ccfef6b12216a956ca4dc2ff94bc2"
|
||||
integrity sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==
|
||||
|
||||
once@^1.3.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.npmmirror.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
|
||||
@ -2108,6 +2237,11 @@ prop-types@15.x, prop-types@^15.7.2, prop-types@^15.8.1:
|
||||
object-assign "^4.1.1"
|
||||
react-is "^16.13.1"
|
||||
|
||||
proxy-from-env@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.npmmirror.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2"
|
||||
integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==
|
||||
|
||||
prr@~1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.npmmirror.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476"
|
||||
@ -2123,6 +2257,13 @@ qrcode.react@^3.1.0:
|
||||
resolved "https://registry.npmmirror.com/qrcode.react/-/qrcode.react-3.1.0.tgz#5c91ddc0340f768316fbdb8fff2765134c2aecd8"
|
||||
integrity sha512-oyF+Urr3oAMUG/OiOuONL3HXM+53wvuH3mtIWQrYmsXoAq0DkvZp2RYUWFSMFtbdOpuS++9v+WAkzNVkMlNW6Q==
|
||||
|
||||
qs@^6.12.1:
|
||||
version "6.12.1"
|
||||
resolved "https://registry.npmmirror.com/qs/-/qs-6.12.1.tgz#39422111ca7cbdb70425541cba20c7d7b216599a"
|
||||
integrity sha512-zWmv4RSuB9r2mYQw3zxQuHWeU+42aKi1wWig/j4ele4ygELZ7PEO6MM7rim9oAQH2A5MWfsAVf/jPvTPgCbvUQ==
|
||||
dependencies:
|
||||
side-channel "^1.0.6"
|
||||
|
||||
queue-microtask@^1.2.2:
|
||||
version "1.2.3"
|
||||
resolved "https://registry.npmmirror.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243"
|
||||
@ -2339,6 +2480,18 @@ semver@^7.6.0:
|
||||
resolved "https://registry.npmmirror.com/semver/-/semver-7.6.2.tgz#1e3b34759f896e8f14d6134732ce798aeb0c6e13"
|
||||
integrity sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==
|
||||
|
||||
set-function-length@^1.2.1:
|
||||
version "1.2.2"
|
||||
resolved "https://registry.npmmirror.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449"
|
||||
integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==
|
||||
dependencies:
|
||||
define-data-property "^1.1.4"
|
||||
es-errors "^1.3.0"
|
||||
function-bind "^1.1.2"
|
||||
get-intrinsic "^1.2.4"
|
||||
gopd "^1.0.1"
|
||||
has-property-descriptors "^1.0.2"
|
||||
|
||||
shebang-command@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.npmmirror.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea"
|
||||
@ -2351,6 +2504,16 @@ shebang-regex@^3.0.0:
|
||||
resolved "https://registry.npmmirror.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172"
|
||||
integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==
|
||||
|
||||
side-channel@^1.0.6:
|
||||
version "1.0.6"
|
||||
resolved "https://registry.npmmirror.com/side-channel/-/side-channel-1.0.6.tgz#abd25fb7cd24baf45466406b1096b7831c9215f2"
|
||||
integrity sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==
|
||||
dependencies:
|
||||
call-bind "^1.0.7"
|
||||
es-errors "^1.3.0"
|
||||
get-intrinsic "^1.2.4"
|
||||
object-inspect "^1.13.1"
|
||||
|
||||
slash@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.npmmirror.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634"
|
||||
|
Loading…
x
Reference in New Issue
Block a user