目录
- 背景
- 了解工程架构
- 我可开始了啊
- 新建一个页面
- 怎么写?
- 前端代码编写思路
- 感触
背景
方便系统运维、不用每次初始化数据都走数据订正
这是第一次毕业之后,用前端语言新建一个页面,过程自然是极其曲折
。情绪也是跌宕起伏
,从页面显示到数据展渲染展示,每次成功完成一个功能点,内心的喜悦值都上升一个点
。当然脑花拧成团,甚至打结也难以知道怎么开发,代码怎么写。开发页面过程中,多次向前端同学请教,也多次借助GPT,帮助我熟悉React的语法格式。本来大学前端网课就一节没听,全靠特种兵之0基础的勇气 (不是,疫情期间谁在家学网课啊 )。好在结果是好的
,历时四天-前后端都开发完成✅,新技能即将get
(一点点皮毛)~~
了解工程架构
Study
-moke
--index.js
-src
--config
---routes.js
--pages
---Calendar
----index.js
--services
---calendar.js
moke 包用来moke后端接口返回的数据
config包用来写整个工程的页面路由
pages包用来写整个工程的所有页面代码
services包用来写后端接口的请求路径
我可开始了啊
了解一些前端相关知识:
–npm (和后端的maven差不多,管理依赖的一个工具)
–node.js(相当于一个运行环境和后端的javac差不多)
–tsx、jsx为React页面文件类型
(初次了解只知道tsx可以和react很好的扩展语法,更好的实现前端页面。)
GPT官方回答
npm(Node Package Manager)是 Node.js 的包管理器,它允许开发者轻松共享和重复使用代码,以及安装和管理依赖项。npm 也提供了一个终端命令行工具,可以方便地安装、升级、卸载和搜索包。
Node.js 是一个运行 JavaScript 的开源环境,它使用了 Chrome V8 引擎来解析和执行 JavaScript 代码。Node.js 具有事件驱动、非阻塞 I/O 和单线程等特点,使得它能够高效地处理大量并发请求。Node.js 可以用于构建服务器端应用程序、命令行工具和桌面应用程序等。
TSX是TypeScript XML的缩写,它是一种在React应用中使用TypeScript的语法扩展。TSX扩展了JSX语法,使得React组件可以使用TypeScript进行类型检查,提高了代码的可靠性和可维护性。
JSX是一种JavaScript的语法扩展,它被React用于描述UI组件的结构和行为。而TSX通过在JSX中添加类型注解,使得React组件的Props和State等属性可以进行类型检查,从而避免了许多类型错误。
TSX的使用需要先安装TypeScript,并在项目中配置相应的TSX编译器。常见的TSX编译器有babel、ts-loader等。
新建一个页面
在pages下新建一个包 Calendar,新建一个文件index.tsx。
怎么写?
第一步先把页面各部分架子搭起来
const IndexPage = () => {
// 定义列头
// 渲染页面数据
return(
// 前端页面代码
)
};
export default IndexPage;
第二步先把页面渲染出来,后面会分步解释
import * as React from 'react';
import {
ProTable,
useProTable,
PageHeader,
Page,
Card,
CardSection,
Filter,
ProFormItem,
Select,
ProTableRowSelectionInstance,
ProTableColumnProps,
Dialog,
Message,
Input,
ProForm,
} from '@alife/whale-ui';
import request from '@alife/whale-request';
import { useRef, useState } from 'react';
import { getList } from '@/services/calendar';
class Props {
/**
* id
*/
id: bigint;
/**
* 类别编码
*/
categoryCode: String;
/**
* 帐期
*/
accountingPeriod: String;
/**
* 帐期编码
*/
code: String;
/**
* 月结日期
*/
date: String;
/**
* 描述
*/
description: String;
};
const IndexPage = () => {
const rowSelectionRef = useRef<ProTableRowSelectionInstance>();
const [editVisible, setEditVisible] = useState(false);
const [formInfo, setFormInfo] = useState<Props>();
const [isEdit, setIsEdit] = useState(false);
// 定义列头
const columns: ProTableColumnProps[] = React.useMemo(
() => [
{
dataIndex: 'categoryCode',
width: 60,
align: 'left',
title: '类别编码',
},
{
dataIndex: 'code',
width: 80,
align: 'left',
title: '帐期编码 ',
},
{
dataIndex: 'accountingPeriod',
width: 80,
align: 'left',
title: '帐期',
},
{
dataIndex: 'date',
align: 'left',
width: 100,
title: '对应日期',
formatType: 'date',
},
{
dataIndex: 'description',
width: 100,
align: 'left',
title: '描述',
},
],
[],
);
// 渲染页面数据
const { tableProps, filterProps, refresh } = useProTable(
// 请求后端数据
getList(),
{
onParamsChange: () => {
// 当参数改变时清空选中行
rowSelectionRef.current &&
rowSelectionRef.current.selectAllPages(false);
},
},
);
return (
<Page>
<PageHeader
breadcrumbProps={{
dataSource: [
{ children: '月结日历-特殊日期' },
{ children: '月结日历列表' },
],
}}
/>
<Page>
<Dialog cardMode title={isEdit ? '编辑数据' : '新增数据'} visible={editVisible}
onClose={() => {
setEditVisible(false);
setFormInfo(undefined);
}}
onCancel={() => {
setEditVisible(false);
setFormInfo(undefined);
}}
onOk={() => {
request({
url: `/caijing-ops/api/calendar/special/day/createOrUpdate`,
method: 'POST',
data: {
id: formInfo.id,
categoryCode: formInfo.categoryCode,
accountingPeriod: formInfo.accountingPeriod,
code: formInfo.code,
date: formInfo.date,
description: formInfo.description,
},
}).then(() => {
Message.success(isEdit ? '编辑成功' : '新增成功');
setFormInfo(undefined);
});
setEditVisible(false);
}}
>
<Card segmentLine>
<CardSection>
<ProForm isPreview layoutMode='responsive' value={formInfo}>
<ProFormItem isPreview={false} required={true} colSpan={1} label='类别编码'>
<Select name='categoryCode' defaultValue={'MEC'} hasSelectAll showSearch
dataSource={[
{
label: 'MEC',
value: 'MEC',
},
{
label: 'ANT',
value: 'ANT',
},
]} />
</ProFormItem>
<ProFormItem isPreview={false} colSpan={1} label='帐期' explanation={'格式为 年份-月份 eg:2023-01'}>
<Input name={'accountingPeriod'} />
</ProFormItem>
<ProFormItem isPreview={false} colSpan={1} label='帐期编码' explanation={'格式为 类别_D? eg:MEC_D1'}>
<Input name={'code'} />
</ProFormItem>
<ProFormItem isPreview={false} colSpan={1} label='月结日期' explanation={'格式为 年-月-日? eg:2023-03-01'}>
<Input name={'date'} />
</ProFormItem>
<ProFormItem isPreview={false} colSpan={1} label='描述' explanation={'格式为 年-月 月结D? eg:2023-01 月结D1'}>
<Input name={'description'} />
</ProFormItem>
</ProForm>
</CardSection>
</Card>
</Dialog>
</Page>
<Card segmentLine={true}>
<CardSection>
<Filter enableForm enableFilterConfiguration {...filterProps}>
<ProFormItem label='类别'>
<Select name='categoryCode' defaultValue={'MEC'} hasSelectAll showSearch
dataSource={[
{
label: 'MEC',
value: 'MEC',
},
{
label: 'ANT',
value: 'ANT',
},
]}
/>
</ProFormItem>
<ProFormItem label='帐期'>
<Select name='accountingPeriod' showSearch filterLocal={false} requestConfig={{
service: ({ params }) => ({
url: '/caijing-ops/api/calendar/special/day/selectCode',
method: 'GET',
params,
}),
}}
/>
</ProFormItem>
<ProFormItem label='帐期编码'>
<Select name='code' showSearch filterLocal={false} requestConfig={{
service: ({ params }) => ({
url: '/caijing-ops/api/calendar/special/day/selectAccountingPeriod',
method: 'GET',
params,
}),
}}
/>
</ProFormItem>
</Filter>
</CardSection>
<CardSection>
<ProTable
columns={columns}
{...tableProps}
actionBarButtons={{
dataSource: [
{
children: '新增',
type: 'primary',
onClick: (e, payload) => {
setEditVisible(true);
},
},
],
}}
actionColumnButtons={{
dataSource: [
{
children: '编辑',
type: 'primary',
onClick: (e, payload) => {
setEditVisible(true);
setIsEdit(true);
setFormInfo({
id: payload.rowRecord.id,
categoryCode: payload.rowRecord.categoryCode,
accountingPeriod: payload.rowRecord.accountingPeriod,
code: payload.rowRecord.code,
date: payload.rowRecord.date,
description: payload.rowRecord.description,
});
console.log(formInfo);
},
},
{
children: '删除',
onClick: (e, payload) => {
Dialog.confirm({
title: `是否确认删除 "${payload.rowRecord.description}"数据?`,
onOk: () => {
request({
url: `/caijing-ops/api/calendar/special/day/delete?id=${payload.rowRecord.id}`,
method: 'GET',
}).then(() => {
Message.success('删除成功');
refresh(); // 使用 refresh 刷新当前页
});
},
});
},
},
],
}}
/>
</CardSection>
</Card>;
</Page>
)
;
};
export default IndexPage;
routes.js 此处定义的是前端路由
const CalendarSpecialDayList = React.lazy(() => import('@/pages/Calendar/ListPage'));
const routerConfig=[
{
path: '/operation',
title: '运维管理',
component: Layout,
children: [
{
path: '/list',
title: '月结日历运维',
component: CalendarSpecialDayList,
}
],
},
]
export default routerConfig;
calendar.js 此处为后端接口路径
export function getList() {
return async ({ current, pageSize, filterParams }) => {
const res = await request({
url: `/list`,
method: 'POST',
data: {
accountingPeriod: filterParams.accountingPeriod,
code: filterParams.code,
pageNum: current,
pageSize: pageSize,
},
crossOrigin: true,
});
return {
total: res.count,
dataSource: res.data,
};
};
}
前端代码编写思路
1.设置 Dialog弹窗状态,初始化关闭,在点击新增/编辑时更新为true
const [editVisible, setEditVisible] = useState(false);
2.设置 编辑弹窗内的数据值,用于回显数据
3.在点击确定、取消时关闭弹窗(即把 Dialog弹窗状态update即可)
4.在定义回显数据时,先定义一个类
class Props {
/**
* id
*/
id: bigint;
/**
* 类别编码
*/
categoryCode: String;
/**
* 帐期
*/
accountingPeriod: String;
/**
* 帐期编码
*/
code: String;
/**
* 月结日期
*/
date: String;
/**
* 描述
*/
description: String;
};
const [formInfo, setFormInfo] = useState<Props>();
5.Get/Post如何传参
post传参为JSON格式
url: `/list`,
method: 'POST',
data: {
accountingPeriod: filterParams.accountingPeriod,
code: filterParams.code,
pageNum: current,
pageSize: pageSize,
},
GET传参为拼接URL方式
url: `/delete?id=${payload.rowRecord.id}`,
method: 'GET',
感触
前后端交互逻辑独立熟悉编写,感觉react和Java逻辑编写时类似。希望以后能进一步学习,由简到杂,向全栈进军!