Merge branch 'develop' of ssh://code.juyouwu.cn:2222/pay/pay-admin into develop
Some checks failed
Build and Push Docker Image / build (push) Failing after 1m54s

# Conflicts:
#	.umirc.ts
This commit is contained in:
uiuJun 2025-08-27 11:25:56 +08:00
commit 1a1a9be825
12 changed files with 175 additions and 375 deletions

75
.github/workflows/develop.yml vendored Normal file
View File

@ -0,0 +1,75 @@
name: Build and Push Docker Image
on:
push:
branches:
- develop
env:
IMAGE_NAME: ''
REPO_NAME: ''
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Setup Environments
shell: bash
run: |
IFS="/" read -r OWNER REPO <<< "$GITHUB_REPOSITORY"
echo "REPO_NAME=$REPO" >> $GITHUB_ENV
echo "IMAGE_NAME=${{ vars.REGISTRY_URL }}/${{ vars.REGISTRY_NAMESPACE }}/$REPO:$GITHUB_REF_NAME" >> $GITHUB_ENV
- name: Checkout
uses: https://gitee.com/zuowenbo/checkout@v4.2.2
- name: Cache Docker layers
uses: https://gitee.com/zuowenbo/cache@v4.2.1
with:
path: /tmp/.buildx-cache
key: ${{ runner.os }}-buildx-${{ env.REPO_NAME }}-${{ github.sha }}
restore-keys: |
${{ runner.os }}-buildx-${{ env.REPO_NAME }}-
- name: Set up Docker Buildx
uses: https://gitee.com/zuowenbo/setup-buildx-action@v3.9.0
with:
driver-opts: image=registry.cn-shenzhen.aliyuncs.com/zuoge-proxy/buildkit:buildx-stable-1
- name: Login to Docker Hub
uses: https://gitee.com/zuowenbo/login-action@v3.3.0
with:
registry: ${{ vars.REGISTRY_URL }}
username: ${{ vars.REGISTRY_USERNAME }}
password: ${{ secrets.REGISTRY_PASSWORD }}
- name: Build and push final image
uses: https://gitee.com/zuowenbo/build-push-action@v6.14.0
with:
context: .
tags: ${{ env.IMAGE_NAME }}
push: true
platforms: linux/amd64
build-args: BRANCH=${{ env.GITHUB_REF_NAME }}
cache-from: type=local,src=/tmp/.buildx-cache
cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max
- name: Move cache
run: |
rm -rf /tmp/.buildx-cache
mv /tmp/.buildx-cache-new /tmp/.buildx-cache
- name: Deploy to remote
uses: https://gitee.com/zuowenbo/ssh-action@v1.0.3
with:
host: ${{ vars.DEV_HOST_IP }}
port: 22
username: 'root'
password: ${{ secrets.DEV_HOST_PASSWORD }}
script: |
docker login -u ${{ vars.REGISTRY_USERNAME }} -p ${{ secrets.REGISTRY_PASSWORD }} ${{ vars.REGISTRY_URL}}
docker volume create ${{ env.REPO_NAME }} || true
docker pull ${{ env.IMAGE_NAME }}
docker stop ${{ env.REPO_NAME }} || true
docker rm ${{ env.REPO_NAME }} || true
docker run -d --restart always --network my_network --name ${{ env.REPO_NAME }} ${{ env.IMAGE_NAME }}

79
.github/workflows/main.yml vendored Normal file
View File

@ -0,0 +1,79 @@
name: Build and Push Docker Image
on:
push:
branches:
- main
env:
IMAGE_NAME: ''
REPO_NAME: ''
jobs:
build:
runs-on: ubuntu-latest
container:
image: zuogeus/act-ubuntu:node18
options: --add-host nexus.zzwb.cc:192.168.2.7
steps:
- name: Setup Environments
shell: bash
run: |
IFS="/" read -r OWNER REPO <<< "$GITHUB_REPOSITORY"
echo "REPO_NAME=$REPO" >> $GITHUB_ENV
echo "IMAGE_NAME=${{ vars.REGISTRY_URL }}/${{ vars.REGISTRY_NAMESPACE }}/$REPO:$GITHUB_REF_NAME" >> $GITHUB_ENV
- name: Checkout
uses: https://gitee.com/zuowenbo/checkout@v4.1.1
- name: Get npm cache directory
id: npm-cache-dir
shell: bash
run: echo "dir=$(npm config get cache)" >> ${GITHUB_OUTPUT}
- name: Set node_modules cache
uses: https://gitee.com/zuowenbo/cache@v4.0.0
id: npm-cache
with:
path: ${{ steps.npm-cache-dir.outputs.dir }}
key: ${{ runner.os }}-node-umi4-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-umi4-
- run: npm install --registry=https://registry.npmmirror.com
- run: npm run build
- name: Set up Docker Buildx
uses: https://gitee.com/zuowenbo/setup-buildx-action@v3.0.0
with:
driver-opts: network=host
- name: Login to Docker Hub
uses: https://gitee.com/zuowenbo/login-action@v3.0.0
with:
registry: ${{ vars.REGISTRY_URL }}
username: ${{ vars.REGISTRY_USERNAME }}
password: ${{ secrets.REGISTRY_PASSWORD }}
- name: Build and push final image
uses: https://gitee.com/zuowenbo/build-push-action@v5.1.0
with:
context: .
tags: ${{ env.IMAGE_NAME }}
push: true
build-args: BRANCH=${{ env.GITHUB_REF_NAME }}
- name: Deploy to remote
uses: https://gitee.com/zuowenbo/ssh-action@v1.0.3
with:
host: ${{ vars.LOAN_MAIN_HOST_IP_PHP }}
port: 22
username: 'root'
password: ${{ secrets.LOAN_MAIN_HOST_PASSWORD }}
script: |
docker login -u ${{ vars.REGISTRY_USERNAME }} -p ${{ secrets.REGISTRY_PASSWORD }} ${{ vars.REGISTRY_URL}}
docker pull ${{ env.IMAGE_NAME }}
docker stop ${{ env.REPO_NAME }} || true
docker rm ${{ env.REPO_NAME }} || true
docker run -d --restart always --network my_network --name ${{ env.REPO_NAME }} ${{ env.IMAGE_NAME }}

1
.gitignore vendored
View File

@ -11,3 +11,4 @@
/dist /dist
/.mfsu /.mfsu
.swc .swc
/.idea

View File

@ -14,9 +14,14 @@ export default defineConfig({
}, },
proxy: { proxy: {
'/api/': { '/api/': {
<<<<<<< HEAD
// target: 'http://yt:8003', // target: 'http://yt:8003',
target: 'http://10.39.13.80:8001', target: 'http://10.39.13.80:8001',
// target: 'https://weapp-api.linyikj.com.cn/', // target: 'https://weapp-api.linyikj.com.cn/',
=======
target: 'http://yt:8001',
// target: 'http://10.39.13.80:8001',
>>>>>>> 1275c157f58b27d4d2b966e91a73bab4f3360be2
// target: 'http://we6f9c65.natappfree.cc', // target: 'http://we6f9c65.natappfree.cc',
// target: 'https://loanos-test.nchl.net/', // target: 'https://loanos-test.nchl.net/',
changeOrigin: true, changeOrigin: true,

View File

@ -1,3 +1,15 @@
FROM nexus.zzwb.cc:18444/nginx:1.21-alpine # 构建阶段
COPY dist /usr/share/nginx/html FROM registry.cn-shenzhen.aliyuncs.com/zuoge-proxy/node:20-alpine AS build
RUN npm install -g pnpm --registry=https://registry.npmmirror.com
WORKDIR /app
COPY package.json pnpm-lock.yaml* ./
RUN pnpm install --registry=https://registry.npmmirror.com
COPY . .
RUN pnpm build
# 部署阶段
FROM registry.cn-shenzhen.aliyuncs.com/zuoge-proxy/nginx:1.27.3-alpine AS app
COPY --from=build /app/dist /usr/share/nginx/html
COPY docker/nginx.conf /etc/nginx/nginx.conf COPY docker/nginx.conf /etc/nginx/nginx.conf

View File

@ -13,9 +13,6 @@
"dependencies": { "dependencies": {
"@ant-design/icons": "^5.0.1", "@ant-design/icons": "^5.0.1",
"@ant-design/pro-components": "^2.8.10", "@ant-design/pro-components": "^2.8.10",
"@antv/g2": "^5.3.5",
"@antv/s2": "^2.0.0-next.25",
"@antv/s2-react": "^2.0.0-next.24",
"@umijs/max": "^4.3.10", "@umijs/max": "^4.3.10",
"antd": "^5.4.0", "antd": "^5.4.0",
"axios": "^1.7.2", "axios": "^1.7.2",

View File

@ -10,8 +10,8 @@ export * from './components/layout/MyCommonModal';
export * from './components/layout/MyImportModal'; export * from './components/layout/MyImportModal';
export * from './components/layout/MyPageContainer'; export * from './components/layout/MyPageContainer';
export * from './components/layout/MyRootContainer'; export * from './components/layout/MyRootContainer';
export * from './components/layout/usePageTabs';
export * from './components/layout/TabsExample'; export * from './components/layout/TabsExample';
export * from './components/layout/usePageTabs';
export * from './components/props/MyDrawerProps'; export * from './components/props/MyDrawerProps';
export * from './components/props/MyModalFormProps'; export * from './components/props/MyModalFormProps';
@ -33,7 +33,6 @@ export * from './libs/valtio/state';
// pages // pages
export * from './pages/MyLoginPage1'; export * from './pages/MyLoginPage1';
export * from './pages/NewMyS2Table';
// utils // utils
export * from './utils/renderTextHelper'; export * from './utils/renderTextHelper';

View File

@ -1,51 +0,0 @@
import { SheetComponent } from '@antv/s2-react';
import { DataType } from '.';
export function MyS2TableComponent(props: DataType) {
return (
<SheetComponent
sheetType="pivot"
dataCfg={{
fields: props.fields,
data: props.data,
meta: props.meta,
}}
adaptive={true}
options={{
height: 888,
hierarchyType: props.config?.hierarchyType,
// style: {
// layoutWidthType: 'colAdaptive',
// },
totals: {
row: {
showGrandTotals: props.config.rowGrandTotals,
showSubTotals: props.config.rowSubTotals,
reverseGrandTotalsLayout: true,
reverseSubTotalsLayout: true,
calcGrandTotals: {
aggregation: 'SUM',
},
calcSubTotals: {
aggregation: 'SUM',
},
// grandTotalsGroupDimensions: ['day'],
// subTotalsGroupDimensions: ['day'],
},
col: {
showGrandTotals: props.config.colGrandTotals,
showSubTotals: props.config.colSubTotals,
reverseGrandTotalsLayout: true,
reverseSubTotalsLayout: true,
calcGrandTotals: {
aggregation: 'SUM',
},
calcSubTotals: {
aggregation: 'SUM',
},
},
},
}}
/>
);
}

View File

@ -1,106 +0,0 @@
import { Button, Radio, Space, Switch, Typography } from 'antd';
import { DataType } from '.';
function downloadCSV(json: any) {
if (json === undefined) return;
// 提取表头
const headers = Object.keys(json[0]);
// 提取数据行
const rows = json.map((item: any) => Object.values(item));
// 构建CSV内容
let csvContent = '';
// 添加表头
csvContent += headers.join(',') + '\r\n';
// 添加数据行
rows.forEach((row: any) => {
csvContent += row.join(',') + '\r\n';
});
// 创建一个Blob对象使用CSV内容并设置类型为text/csv
const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });
// 创建一个链接元素
const link = document.createElement('a');
// 设置下载的文件名,默认为'download.csv'
if (link.download !== undefined) {
const url = URL.createObjectURL(blob);
link.setAttribute('href', url);
link.setAttribute('download', 'download.csv');
// 触发点击事件以下载文件
document.body.appendChild(link);
link.click();
// 清理DOM
document.body.removeChild(link);
}
}
export function MyS2TableExtra({
config,
data,
setConfig,
}: {
config: DataType['config'];
data: DataType['data'];
setConfig: (config: DataType['config']) => void;
}) {
return (
<Space>
<Typography.Text style={{ marginLeft: 20 }}>:</Typography.Text>
<Switch
value={config?.rowSubTotals || false}
onChange={(e) => {
setConfig({ ...config, rowSubTotals: Boolean(e) });
}}
/>
<Typography.Text style={{ marginLeft: 20 }}>:</Typography.Text>
<Switch
value={config?.rowGrandTotals || false}
onChange={(e) => {
setConfig({ ...config, rowGrandTotals: Boolean(e) });
}}
/>
<Typography.Text style={{ marginLeft: 20 }}>:</Typography.Text>
<Switch
value={config?.colSubTotals || false}
onChange={(e) => {
setConfig({ ...config, colSubTotals: Boolean(e) });
}}
/>
<Typography.Text style={{ marginLeft: 20 }}>:</Typography.Text>
<Switch
value={config?.colGrandTotals || false}
onChange={(e) => {
setConfig({ ...config, colGrandTotals: Boolean(e) });
}}
/>
<Typography.Text style={{ marginLeft: 20 }}>:</Typography.Text>
<Radio.Group
size="small"
options={[
{ label: '树形', value: 'tree' },
{ label: '平铺', value: 'grid' },
]}
value={config?.hierarchyType || 'tree'}
onChange={(e) =>
setConfig({
...config,
hierarchyType: e.target.value,
})
}
optionType="button"
buttonStyle="solid"
style={{ marginRight: 20 }}
/>
<Button
size="small"
onClick={() => {
downloadCSV(data);
}}
>
</Button>
</Space>
);
}

View File

@ -1,73 +0,0 @@
import { Switcher } from '@antv/s2-react';
import { useSetState } from 'react-use';
import { DataType } from '.';
export function MySwitcherFields({
fields,
setFields,
}: {
fields: DataType['fields'];
setFields: (fields: DataType['fields']) => void;
}) {
const [switcherFields, setSwitcherFields] = useSetState(() => {
return {
rows: {
selectable: true,
allowEmpty: false,
items: fields.rows?.map((item) => {
return { id: item };
}),
},
columns: {
selectable: true,
allowEmpty: true,
items: fields.columns?.map((item) => {
return { id: item };
}),
},
values: {
selectable: true,
allowEmpty: false,
items: fields.values?.map((item) => {
return { id: item };
}),
},
};
});
function onSwitcherChange(result: any): void {
const fields = {
rows: result.rows.items
.filter((item: { checked?: boolean }) => item.checked ?? true)
.map((item: { id: string }) => item.id),
columns: result.columns.items
.filter((item: { checked?: boolean }) => item.checked ?? true)
.map((item: { id: string }) => item.id),
values: result.values.items
.filter((item: { checked?: boolean }) => item.checked ?? true)
.map((item: { id: string }) => item.id),
};
setSwitcherFields({
rows: {
selectable: true,
allowEmpty: false,
items: result.rows.items,
},
columns: {
selectable: true,
allowEmpty: true,
items: result.columns.items,
},
values: {
selectable: true,
allowEmpty: false,
items: result.values.items,
},
});
setFields?.(fields);
}
return <Switcher {...switcherFields} onSubmit={onSwitcherChange} />;
}

View File

@ -1,22 +0,0 @@
import { BetaSchemaForm, ProCard } from '@ant-design/pro-components';
import { PropsType } from '.';
export default function Query({
columns,
doRequest,
}: {
columns?: PropsType['columns'];
doRequest: (values: any) => void;
}) {
return (
<ProCard>
<BetaSchemaForm
layoutType="QueryFilter"
onFinish={async (values: Record<string, any>) => {
doRequest(values);
}}
columns={columns as any}
/>
</ProCard>
);
}

View File

@ -1,116 +0,0 @@
import { MyPageContainer } from '@/common';
import { MyResponseType } from '@/common/typings';
import { ProCard, ProFormColumnsType } from '@ant-design/pro-components';
import { Fields, HierarchyType, Meta, RawData } from '@antv/s2';
import { Flex, Space } from 'antd';
import { useEffect } from 'react';
import { useSetState } from 'react-use';
import { MyS2TableComponent } from './MyS2TableComponent';
import { MyS2TableExtra } from './MyS2TableExtra';
import { MySwitcherFields } from './MySwitcherFields';
import Query from './Query';
export type PropsType = {
title: string;
api: (values?: any) => Promise<MyResponseType>;
defaultParams?: Record<string, any>;
columns?: ProFormColumnsType<Record<string, any>, 'text'>[] | undefined;
};
export type DataType = {
config: {
hierarchyType: HierarchyType | undefined;
rowGrandTotals: boolean;
rowSubTotals: boolean;
colGrandTotals: boolean;
colSubTotals: boolean;
};
data: RawData[];
fields: Fields;
meta?: Meta[];
query?: Record<string, any>;
};
export function NewMyS2Table(props: PropsType) {
const [data, setData] = useSetState<DataType>(undefined);
// 请求数据
function doRequest() {
props
.api?.({ ...props.defaultParams, ...data.query, fields: data.fields })
.then((resp) => {
if (!data.config)
setData({
config: resp.data.config,
data: resp.data.data,
fields: resp.data.fields,
meta: resp.data.meta,
});
else setData({ data: resp.data.data });
});
}
// // 如果没有columns直接发起请求
// useEffect(() => {
// if (props.columns === undefined) doRequest({});
// }, []);
useEffect(() => {
console.log('useEffect query', data.query, data.fields);
if (!data.query && !data.fields) {
if (props.columns === undefined) {
doRequest();
}
} else {
doRequest();
}
}, [data.query, data.fields]);
return (
<MyPageContainer title={props.title}>
{props.columns && (
<Query
columns={props.columns}
doRequest={(values) => {
setData({ query: values });
}}
/>
)}
<ProCard>
<Space direction="vertical" style={{ width: '100%' }}>
<Flex
justify="space-between"
style={{ width: '100%', margin: '10px 0' }}
>
{data.fields && (
<MySwitcherFields
fields={data.fields}
setFields={(fields: DataType['fields']) => {
console.log('fields', fields);
setData({ fields });
}}
/>
)}
{data.config && (
<MyS2TableExtra
config={data.config}
setConfig={(config) => {
setData({ config });
}}
data={data.data}
/>
)}
</Flex>
{data.config && (
<MyS2TableComponent
config={data.config}
fields={data.fields}
meta={data.meta}
data={data.data}
/>
)}
</Space>
</ProCard>
</MyPageContainer>
);
}