feat(前端): 统一表单组件样式并添加数据库迁移文档
refactor(前端): 提取表单样式到共享配置文件 docs: 添加数据库迁移说明到README
This commit is contained in:
@@ -16,6 +16,15 @@ import {
|
||||
} from 'antd';
|
||||
import { PlusOutlined, EditOutlined, DeleteOutlined, SearchOutlined } from '@ant-design/icons';
|
||||
import axios from 'axios';
|
||||
import {
|
||||
inputStyles,
|
||||
selectStyles,
|
||||
textAreaStyles,
|
||||
inputNumberStyles,
|
||||
filterInputStyles,
|
||||
inputPlaceholders,
|
||||
inputValidationRules,
|
||||
} from '../styles/deviceManagementStyles';
|
||||
|
||||
const { Option } = Select;
|
||||
|
||||
@@ -183,18 +192,19 @@ function CategoryManagement() {
|
||||
<Card size="small" style={{ marginBottom: 16 }}>
|
||||
<Space>
|
||||
<Input
|
||||
placeholder="搜索分类名称、描述"
|
||||
style={{ width: 300 }}
|
||||
placeholder={inputPlaceholders.searchCategory}
|
||||
style={{ ...inputStyles.search, width: 300 }}
|
||||
value={keyword}
|
||||
onChange={e => setKeyword(e.target.value)}
|
||||
allowClear
|
||||
prefix={<SearchOutlined />}
|
||||
/>
|
||||
<Select value={status} onChange={setStatus} style={{ width: 120 }}>
|
||||
<Select value={status} onChange={setStatus} style={{ ...selectStyles.base, width: 120 }}>
|
||||
<Option value="all">所有状态</Option>
|
||||
<Option value="active">启用</Option>
|
||||
<Option value="inactive">停用</Option>
|
||||
</Select>
|
||||
<Button onClick={() => fetchCategories()}>刷新</Button>
|
||||
<Button onClick={() => fetchCategories()} style={{ height: '40px', borderRadius: '10px' }}>刷新</Button>
|
||||
</Space>
|
||||
</Card>
|
||||
|
||||
@@ -221,30 +231,30 @@ function CategoryManagement() {
|
||||
name="name"
|
||||
label="分类名称"
|
||||
rules={[
|
||||
{ required: true, message: '请输入分类名称' },
|
||||
{ max: 50, message: '分类名称不能超过50个字符' },
|
||||
inputValidationRules.required('请输入分类名称'),
|
||||
inputValidationRules.maxLength(50, '分类名称不能超过50个字符'),
|
||||
]}
|
||||
>
|
||||
<Input placeholder="请输入分类名称" />
|
||||
<Input placeholder="请输入分类名称" style={inputStyles.form} />
|
||||
</Form.Item>
|
||||
<Form.Item name="description" label="描述">
|
||||
<Input.TextArea rows={3} placeholder="请输入分类描述" maxLength={200} showCount />
|
||||
<Input.TextArea rows={3} placeholder={inputPlaceholders.description} maxLength={200} showCount style={textAreaStyles.base} />
|
||||
</Form.Item>
|
||||
<Form.Item name="sortOrder" label="排序">
|
||||
<InputNumber min={0} placeholder="数值越小越靠前" style={{ width: '100%' }} />
|
||||
<InputNumber min={0} placeholder="数值越小越靠前" style={inputNumberStyles.base} />
|
||||
</Form.Item>
|
||||
<Form.Item name="status" label="状态" rules={[{ required: true, message: '请选择状态' }]}>
|
||||
<Select>
|
||||
<Form.Item name="status" label="状态" rules={[inputValidationRules.required('请选择状态')]}>
|
||||
<Select style={selectStyles.base}>
|
||||
<Option value="active">启用</Option>
|
||||
<Option value="inactive">停用</Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
<Form.Item>
|
||||
<Space>
|
||||
<Button type="primary" htmlType="submit">
|
||||
<Button type="primary" htmlType="submit" style={{ height: '40px', borderRadius: '10px' }}>
|
||||
{editingCategory ? '更新' : '创建'}
|
||||
</Button>
|
||||
<Button onClick={handleCancel}>取消</Button>
|
||||
<Button onClick={handleCancel} style={{ height: '40px', borderRadius: '10px' }}>取消</Button>
|
||||
</Space>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
|
||||
@@ -38,6 +38,15 @@ import {
|
||||
import axios from 'axios';
|
||||
import dayjs from 'dayjs';
|
||||
import * as XLSX from 'xlsx';
|
||||
import {
|
||||
inputStyles,
|
||||
selectStyles,
|
||||
textAreaStyles,
|
||||
filterInputStyles,
|
||||
datePickerStyles,
|
||||
inputPlaceholders,
|
||||
inputValidationRules,
|
||||
} from '../styles/deviceManagementStyles';
|
||||
|
||||
const { RangePicker } = DatePicker;
|
||||
const { Option } = Select;
|
||||
@@ -575,8 +584,8 @@ function ConsumableLogs() {
|
||||
<Card size="small" style={{ marginBottom: 16 }}>
|
||||
<Space wrap>
|
||||
<Input
|
||||
placeholder="搜索耗材ID"
|
||||
style={{ width: 200 }}
|
||||
placeholder={inputPlaceholders.consumableId}
|
||||
style={{ ...inputStyles.search, width: 200 }}
|
||||
allowClear
|
||||
value={filters.consumableId}
|
||||
onChange={e => handleFilterChange('consumableId', e.target.value)}
|
||||
@@ -586,7 +595,7 @@ function ConsumableLogs() {
|
||||
mode="multiple"
|
||||
value={filters.operationType}
|
||||
onChange={value => handleFilterChange('operationType', value)}
|
||||
style={{ width: 200 }}
|
||||
style={{ ...selectStyles.base, width: 200 }}
|
||||
placeholder="选择操作类型"
|
||||
allowClear
|
||||
maxTagCount="responsive"
|
||||
@@ -602,7 +611,8 @@ function ConsumableLogs() {
|
||||
<RangePicker
|
||||
value={filters.dateRange}
|
||||
onChange={dates => handleFilterChange('dateRange', dates)}
|
||||
placeholder={['开始日期', '结束日期']}
|
||||
placeholder={inputPlaceholders.dateRange}
|
||||
style={datePickerStyles.range}
|
||||
/>
|
||||
<Button
|
||||
icon={<HistoryOutlined />}
|
||||
@@ -610,6 +620,7 @@ function ConsumableLogs() {
|
||||
setFilters({ operationType: ['in', 'out'], consumableId: '', dateRange: null });
|
||||
fetchLogs(1, pagination.pageSize);
|
||||
}}
|
||||
style={{ height: '40px', borderRadius: '10px' }}
|
||||
>
|
||||
重置筛选
|
||||
</Button>
|
||||
@@ -631,11 +642,11 @@ function ConsumableLogs() {
|
||||
],
|
||||
}}
|
||||
>
|
||||
<Button icon={<DownloadOutlined />}>
|
||||
<Button icon={<DownloadOutlined />} style={{ height: '40px', borderRadius: '10px' }}>
|
||||
导出 <DownOutlined />
|
||||
</Button>
|
||||
</Dropdown>
|
||||
<Button icon={<UploadOutlined />} onClick={() => setImportModalVisible(true)}>
|
||||
<Button icon={<UploadOutlined />} onClick={() => setImportModalVisible(true)} style={{ height: '40px', borderRadius: '10px' }}>
|
||||
导入
|
||||
</Button>
|
||||
</Space>
|
||||
@@ -720,20 +731,20 @@ function ConsumableLogs() {
|
||||
>
|
||||
<Form form={form} layout="vertical" onFinish={handleEditSubmit}>
|
||||
<Form.Item label="操作原因" name="reason">
|
||||
<Input.TextArea rows={2} placeholder="请输入操作原因" />
|
||||
<Input.TextArea rows={2} placeholder={inputPlaceholders.reason} style={textAreaStyles.base} />
|
||||
</Form.Item>
|
||||
<Form.Item label="备注" name="notes">
|
||||
<Input.TextArea rows={3} placeholder="请输入备注信息" />
|
||||
<Input.TextArea rows={3} placeholder={inputPlaceholders.notes} style={textAreaStyles.base} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label="修改原因"
|
||||
name="modificationReason"
|
||||
rules={[{ required: true, message: '请输入修改原因' }]}
|
||||
rules={[inputValidationRules.required('请输入修改原因')]}
|
||||
>
|
||||
<Input.TextArea rows={2} placeholder="请输入修改原因(必填)" />
|
||||
<Input.TextArea rows={2} placeholder="请输入修改原因(必填)" style={textAreaStyles.base} />
|
||||
</Form.Item>
|
||||
<Form.Item label="修改人" name="operator">
|
||||
<Input placeholder="请输入修改人姓名" />
|
||||
<Input placeholder={inputPlaceholders.operator} style={inputStyles.form} />
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Modal>
|
||||
|
||||
@@ -46,6 +46,15 @@ import {
|
||||
} from '@ant-design/icons';
|
||||
import axios from 'axios';
|
||||
import { motion, AnimatePresence } from 'framer-motion';
|
||||
import {
|
||||
inputStyles,
|
||||
selectStyles,
|
||||
inputNumberStyles,
|
||||
textAreaStyles,
|
||||
filterInputStyles,
|
||||
inputPlaceholders,
|
||||
inputValidationRules,
|
||||
} from '../styles/deviceManagementStyles';
|
||||
|
||||
const { Option } = Select;
|
||||
const { Text, Title } = Typography;
|
||||
@@ -871,26 +880,27 @@ function ConsumableManagement() {
|
||||
>
|
||||
<Row gutter={[16, 16]} align="middle">
|
||||
<Col xs={24} sm={12} md={8} lg={8}>
|
||||
<div style={{ marginBottom: '6px', fontSize: '13px', color: designTokens.colors.neutral[600], fontWeight: 500 }}>
|
||||
<div style={filterInputStyles.container}>
|
||||
搜索
|
||||
</div>
|
||||
<Input
|
||||
placeholder="搜索耗材ID、名称、分类、供应商"
|
||||
placeholder={inputPlaceholders.searchConsumable}
|
||||
value={keyword}
|
||||
onChange={e => handleSearch(e.target.value)}
|
||||
onPressEnter={() => fetchConsumables()}
|
||||
prefix={<SearchOutlined style={{ color: designTokens.colors.neutral[400] }} />}
|
||||
allowClear
|
||||
style={filterInputStyles.input}
|
||||
/>
|
||||
</Col>
|
||||
|
||||
<Col xs={24} sm={12} md={6} lg={5}>
|
||||
<div style={{ marginBottom: '6px', fontSize: '13px', color: designTokens.colors.neutral[600], fontWeight: 500 }}>
|
||||
<div style={filterInputStyles.container}>
|
||||
分类
|
||||
</div>
|
||||
<Select
|
||||
placeholder="选择分类"
|
||||
style={{ width: '100%' }}
|
||||
placeholder={inputPlaceholders.category}
|
||||
style={filterInputStyles.select}
|
||||
value={category}
|
||||
onChange={setCategory}
|
||||
allowClear
|
||||
@@ -905,12 +915,12 @@ function ConsumableManagement() {
|
||||
</Col>
|
||||
|
||||
<Col xs={24} sm={12} md={6} lg={5}>
|
||||
<div style={{ marginBottom: '6px', fontSize: '13px', color: designTokens.colors.neutral[600], fontWeight: 500 }}>
|
||||
<div style={filterInputStyles.container}>
|
||||
状态
|
||||
</div>
|
||||
<Select
|
||||
placeholder="选择状态"
|
||||
style={{ width: '100%' }}
|
||||
style={filterInputStyles.select}
|
||||
value={status}
|
||||
onChange={setStatus}
|
||||
>
|
||||
@@ -931,6 +941,7 @@ function ConsumableManagement() {
|
||||
background: designTokens.colors.primary.gradient,
|
||||
border: 'none',
|
||||
borderRadius: designTokens.borderRadius.sm,
|
||||
height: '40px',
|
||||
}}
|
||||
>
|
||||
筛选
|
||||
@@ -939,7 +950,7 @@ function ConsumableManagement() {
|
||||
<Button
|
||||
icon={<ClearOutlined />}
|
||||
onClick={handleReset}
|
||||
style={{ borderRadius: designTokens.borderRadius.sm }}
|
||||
style={{ borderRadius: designTokens.borderRadius.sm, height: '40px' }}
|
||||
/>
|
||||
</Tooltip>
|
||||
</Space>
|
||||
@@ -1092,17 +1103,17 @@ function ConsumableManagement() {
|
||||
<Form form={form} layout="vertical" onFinish={handleSubmit} style={{ marginTop: '16px' }}>
|
||||
<Row gutter={16}>
|
||||
<Col span={12}>
|
||||
<Form.Item name="name" label="名称" rules={[{ required: true, message: '请输入名称' }]}>
|
||||
<Input placeholder="请输入耗材名称" />
|
||||
<Form.Item name="name" label="名称" rules={[inputValidationRules.required('请输入名称')]}>
|
||||
<Input placeholder={inputPlaceholders.consumableName} style={inputStyles.form} />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
name="category"
|
||||
label="分类"
|
||||
rules={[{ required: true, message: '请选择分类' }]}
|
||||
rules={[inputValidationRules.required('请选择分类')]}
|
||||
>
|
||||
<Select placeholder="请选择分类" allowClear>
|
||||
<Select placeholder={inputPlaceholders.category} allowClear style={selectStyles.base}>
|
||||
{categories.map(cat => (
|
||||
<Option key={cat.id} value={cat.name}>
|
||||
{cat.name}
|
||||
@@ -1118,28 +1129,28 @@ function ConsumableManagement() {
|
||||
<Form.Item
|
||||
name="unit"
|
||||
label="单位"
|
||||
rules={[{ required: true, message: '请输入单位' }]}
|
||||
rules={[inputValidationRules.required('请输入单位')]}
|
||||
initialValue="个"
|
||||
>
|
||||
<Input placeholder="如: 个、盒、卷、箱" />
|
||||
<Input placeholder={inputPlaceholders.unit} style={inputStyles.form} />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={8}>
|
||||
<Form.Item
|
||||
name="currentStock"
|
||||
label="当前库存"
|
||||
rules={[{ required: true, message: '请输入当前库存' }]}
|
||||
rules={[inputValidationRules.required('请输入当前库存')]}
|
||||
>
|
||||
<InputNumber min={0} style={{ width: '100%' }} placeholder="请输入当前库存" />
|
||||
<InputNumber min={0} style={inputNumberStyles.base} placeholder={inputPlaceholders.stock} />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={8}>
|
||||
<Form.Item
|
||||
name="minStock"
|
||||
label="最小库存"
|
||||
rules={[{ required: true, message: '请输入最小库存' }]}
|
||||
rules={[inputValidationRules.required('请输入最小库存')]}
|
||||
>
|
||||
<InputNumber min={0} style={{ width: '100%' }} placeholder="请输入最小库存" />
|
||||
<InputNumber min={0} style={inputNumberStyles.base} placeholder={inputPlaceholders.minStock} />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
@@ -1163,9 +1174,9 @@ function ConsumableManagement() {
|
||||
<Form.Item
|
||||
name="maxStock"
|
||||
noStyle
|
||||
rules={[{ required: true, message: '请输入最大库存' }]}
|
||||
rules={[inputValidationRules.required('请输入最大库存')]}
|
||||
>
|
||||
<InputNumber min={0} style={{ width: '100%' }} placeholder="请输入最大库存" />
|
||||
<InputNumber min={0} style={inputNumberStyles.base} placeholder={inputPlaceholders.maxStock} />
|
||||
</Form.Item>
|
||||
)}
|
||||
</Space>
|
||||
@@ -1177,8 +1188,8 @@ function ConsumableManagement() {
|
||||
min={0}
|
||||
step={0.01}
|
||||
precision={2}
|
||||
style={{ width: '100%' }}
|
||||
placeholder="请输入单价"
|
||||
style={inputNumberStyles.base}
|
||||
placeholder={inputPlaceholders.unitPrice}
|
||||
prefix="¥"
|
||||
/>
|
||||
</Form.Item>
|
||||
@@ -1188,18 +1199,18 @@ function ConsumableManagement() {
|
||||
<Row gutter={16}>
|
||||
<Col span={12}>
|
||||
<Form.Item name="supplier" label="供应商">
|
||||
<Input placeholder="请输入供应商" />
|
||||
<Input placeholder={inputPlaceholders.supplier} style={inputStyles.form} />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Form.Item name="location" label="存放位置">
|
||||
<Input placeholder="如: A柜-01层、B区货架3" />
|
||||
<Input placeholder={inputPlaceholders.location} style={inputStyles.form} />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<Form.Item name="description" label="描述">
|
||||
<TextArea rows={3} placeholder="请输入描述信息" />
|
||||
<TextArea rows={3} placeholder={inputPlaceholders.description} style={textAreaStyles.base} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item label={
|
||||
@@ -1289,8 +1300,8 @@ function ConsumableManagement() {
|
||||
)}
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item name="status" label="状态" rules={[{ required: true, message: '请选择状态' }]}>
|
||||
<Select placeholder="请选择状态">
|
||||
<Form.Item name="status" label="状态" rules={[inputValidationRules.required('请选择状态')]}>
|
||||
<Select placeholder="请选择状态" style={selectStyles.base}>
|
||||
<Option value="active">启用</Option>
|
||||
<Option value="inactive">停用</Option>
|
||||
</Select>
|
||||
@@ -1478,10 +1489,10 @@ function ConsumableManagement() {
|
||||
>
|
||||
<Form form={stockForm} layout="vertical" onFinish={handleStockSubmit} style={{ marginTop: '16px' }}>
|
||||
<Form.Item name="consumableId" label="耗材ID">
|
||||
<Input disabled />
|
||||
<Input disabled style={{ ...inputStyles.form, ...inputStyles.disabled }} />
|
||||
</Form.Item>
|
||||
<Form.Item name="consumableName" label="耗材名称">
|
||||
<Input disabled />
|
||||
<Input disabled style={{ ...inputStyles.form, ...inputStyles.disabled }} />
|
||||
</Form.Item>
|
||||
|
||||
{stockType === 'out' && stockRecord?.snList && stockRecord.snList.length > 0 && (
|
||||
@@ -1500,7 +1511,7 @@ function ConsumableManagement() {
|
||||
allowClear
|
||||
value={snSearchKeyword}
|
||||
onChange={e => setSnSearchKeyword(e.target.value)}
|
||||
style={{ marginBottom: '8px' }}
|
||||
style={{ ...inputStyles.search, marginBottom: '8px' }}
|
||||
/>
|
||||
<Space size="small" style={{ marginBottom: '8px' }}>
|
||||
<Button
|
||||
@@ -1576,8 +1587,8 @@ function ConsumableManagement() {
|
||||
<Form.Item name="snList" label="入库SN序列号(可选)">
|
||||
<Select
|
||||
mode="tags"
|
||||
style={{ width: '100%' }}
|
||||
placeholder="输入SN后按回车添加"
|
||||
style={selectStyles.base}
|
||||
placeholder={inputPlaceholders.snList}
|
||||
tokenSeparators={[',', '\n']}
|
||||
/>
|
||||
</Form.Item>
|
||||
@@ -1586,23 +1597,23 @@ function ConsumableManagement() {
|
||||
<Form.Item
|
||||
name="quantity"
|
||||
label="数量"
|
||||
rules={[{ required: true, message: '请输入数量' }]}
|
||||
rules={[inputValidationRules.required('请输入数量')]}
|
||||
>
|
||||
<InputNumber
|
||||
min={1}
|
||||
max={stockType === 'out' && stockRecord?.snList?.length > 0 ? stockRecord.snList.length : undefined}
|
||||
style={{ width: '100%' }}
|
||||
style={inputNumberStyles.base}
|
||||
placeholder="请输入数量"
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item name="operator" label="操作人">
|
||||
<Input placeholder="请输入操作人姓名" />
|
||||
<Input placeholder={inputPlaceholders.operator} style={inputStyles.form} />
|
||||
</Form.Item>
|
||||
<Form.Item name="reason" label={stockType === 'in' ? '入库原因' : '出库原因'}>
|
||||
<Input placeholder={stockType === 'in' ? '如: 采购入库' : '如: 部门领用、报损出库'} />
|
||||
<Input placeholder={stockType === 'in' ? '如: 采购入库' : '如: 部门领用、报损出库'} style={inputStyles.form} />
|
||||
</Form.Item>
|
||||
<Form.Item name="notes" label="备注">
|
||||
<TextArea rows={2} placeholder="请输入备注信息" />
|
||||
<TextArea rows={2} placeholder={inputPlaceholders.notes} style={textAreaStyles.base} />
|
||||
</Form.Item>
|
||||
<Form.Item>
|
||||
<Space>
|
||||
|
||||
@@ -38,6 +38,11 @@ import styled from 'styled-components';
|
||||
import dayjs from 'dayjs';
|
||||
import api from '../api';
|
||||
import { message } from 'antd';
|
||||
import {
|
||||
selectStyles,
|
||||
datePickerStyles,
|
||||
inputPlaceholders,
|
||||
} from '../styles/deviceManagementStyles';
|
||||
|
||||
const { Title, Text } = Typography;
|
||||
const { RangePicker } = DatePicker;
|
||||
@@ -762,8 +767,9 @@ const ConsumableStatistics = () => {
|
||||
<RangePicker
|
||||
value={dateRange}
|
||||
onChange={setDateRange}
|
||||
style={{ width: '100%' }}
|
||||
style={datePickerStyles.range}
|
||||
allowClear={false}
|
||||
placeholder={inputPlaceholders.dateRange}
|
||||
/>
|
||||
</Col>
|
||||
<Col xs={24} sm={12} md={8} lg={6}>
|
||||
@@ -774,7 +780,7 @@ const ConsumableStatistics = () => {
|
||||
<Select
|
||||
value={categoryFilter}
|
||||
onChange={setCategoryFilter}
|
||||
style={{ width: '100%' }}
|
||||
style={selectStyles.base}
|
||||
placeholder="选择类别"
|
||||
>
|
||||
<Option value="all">全部类别</Option>
|
||||
@@ -791,7 +797,7 @@ const ConsumableStatistics = () => {
|
||||
onClick={loadStatistics}
|
||||
loading={loading}
|
||||
style={{
|
||||
height: 40,
|
||||
height: '40px',
|
||||
borderRadius: designTokens.borderRadius.medium,
|
||||
background: designTokens.colors.primary.gradient,
|
||||
border: 'none',
|
||||
|
||||
@@ -450,6 +450,369 @@ export const resizableTitleStyles = {
|
||||
},
|
||||
};
|
||||
|
||||
// ============================================
|
||||
// 输入框统一样式配置
|
||||
// ============================================
|
||||
|
||||
// 输入框基础样式
|
||||
export const inputStyles = {
|
||||
// 基础输入框样式
|
||||
base: {
|
||||
height: '40px',
|
||||
borderRadius: borderRadius.medium,
|
||||
border: `1px solid ${colors.border.light}`,
|
||||
fontSize: '14px',
|
||||
transition: `all ${transitions.fast}`,
|
||||
},
|
||||
|
||||
// 搜索输入框样式
|
||||
search: {
|
||||
height: '40px',
|
||||
borderRadius: borderRadius.medium,
|
||||
border: `1px solid ${colors.border.light}`,
|
||||
fontSize: '14px',
|
||||
transition: `all ${transitions.fast}`,
|
||||
backgroundColor: colors.background.primary,
|
||||
},
|
||||
|
||||
// 表单输入框样式
|
||||
form: {
|
||||
height: '40px',
|
||||
borderRadius: borderRadius.medium,
|
||||
border: `1px solid ${colors.border.light}`,
|
||||
fontSize: '14px',
|
||||
transition: `all ${transitions.fast}`,
|
||||
},
|
||||
|
||||
// 小尺寸输入框
|
||||
small: {
|
||||
height: '32px',
|
||||
borderRadius: borderRadius.small,
|
||||
fontSize: '13px',
|
||||
},
|
||||
|
||||
// 大尺寸输入框
|
||||
large: {
|
||||
height: '48px',
|
||||
borderRadius: borderRadius.medium,
|
||||
fontSize: '16px',
|
||||
},
|
||||
|
||||
// 禁用状态
|
||||
disabled: {
|
||||
backgroundColor: colors.background.tertiary,
|
||||
color: colors.text.tertiary,
|
||||
cursor: 'not-allowed',
|
||||
},
|
||||
|
||||
// 错误状态
|
||||
error: {
|
||||
borderColor: colors.error.main,
|
||||
boxShadow: `0 0 0 2px ${colors.error.main}20`,
|
||||
},
|
||||
|
||||
// 焦点状态
|
||||
focus: {
|
||||
borderColor: colors.primary.main,
|
||||
boxShadow: `0 0 0 3px ${colors.primary.main}15`,
|
||||
},
|
||||
};
|
||||
|
||||
// Select 选择器样式
|
||||
export const selectStyles = {
|
||||
// 基础选择器样式
|
||||
base: {
|
||||
height: '40px',
|
||||
borderRadius: borderRadius.medium,
|
||||
fontSize: '14px',
|
||||
},
|
||||
|
||||
// 小尺寸选择器
|
||||
small: {
|
||||
height: '32px',
|
||||
borderRadius: borderRadius.small,
|
||||
fontSize: '13px',
|
||||
},
|
||||
|
||||
// 大尺寸选择器
|
||||
large: {
|
||||
height: '48px',
|
||||
borderRadius: borderRadius.medium,
|
||||
fontSize: '16px',
|
||||
},
|
||||
|
||||
// 下拉菜单样式
|
||||
dropdown: {
|
||||
borderRadius: borderRadius.medium,
|
||||
boxShadow: shadows.large,
|
||||
border: `1px solid ${colors.border.light}`,
|
||||
},
|
||||
|
||||
// 选项样式
|
||||
option: {
|
||||
padding: '8px 12px',
|
||||
fontSize: '14px',
|
||||
transition: `background-color ${transitions.fast}`,
|
||||
},
|
||||
};
|
||||
|
||||
// InputNumber 数字输入框样式
|
||||
export const inputNumberStyles = {
|
||||
// 基础样式
|
||||
base: {
|
||||
width: '100%',
|
||||
height: '40px',
|
||||
borderRadius: borderRadius.medium,
|
||||
border: `1px solid ${colors.border.light}`,
|
||||
fontSize: '14px',
|
||||
},
|
||||
|
||||
// 小尺寸
|
||||
small: {
|
||||
height: '32px',
|
||||
borderRadius: borderRadius.small,
|
||||
fontSize: '13px',
|
||||
},
|
||||
|
||||
// 大尺寸
|
||||
large: {
|
||||
height: '48px',
|
||||
borderRadius: borderRadius.medium,
|
||||
fontSize: '16px',
|
||||
},
|
||||
};
|
||||
|
||||
// TextArea 文本域样式
|
||||
export const textAreaStyles = {
|
||||
// 基础样式
|
||||
base: {
|
||||
borderRadius: borderRadius.medium,
|
||||
border: `1px solid ${colors.border.light}`,
|
||||
fontSize: '14px',
|
||||
padding: '10px 12px',
|
||||
transition: `all ${transitions.fast}`,
|
||||
resize: 'vertical',
|
||||
minHeight: '80px',
|
||||
},
|
||||
|
||||
// 小尺寸
|
||||
small: {
|
||||
fontSize: '13px',
|
||||
padding: '8px 10px',
|
||||
minHeight: '60px',
|
||||
},
|
||||
|
||||
// 大尺寸
|
||||
large: {
|
||||
fontSize: '16px',
|
||||
padding: '12px 14px',
|
||||
minHeight: '100px',
|
||||
},
|
||||
};
|
||||
|
||||
// DatePicker 日期选择器样式
|
||||
export const datePickerStyles = {
|
||||
// 基础样式
|
||||
base: {
|
||||
height: '40px',
|
||||
borderRadius: borderRadius.medium,
|
||||
border: `1px solid ${colors.border.light}`,
|
||||
fontSize: '14px',
|
||||
width: '100%',
|
||||
},
|
||||
|
||||
// 小尺寸
|
||||
small: {
|
||||
height: '32px',
|
||||
borderRadius: borderRadius.small,
|
||||
fontSize: '13px',
|
||||
},
|
||||
|
||||
// 大尺寸
|
||||
large: {
|
||||
height: '48px',
|
||||
borderRadius: borderRadius.medium,
|
||||
fontSize: '16px',
|
||||
},
|
||||
|
||||
// 范围选择器
|
||||
range: {
|
||||
height: '40px',
|
||||
borderRadius: borderRadius.medium,
|
||||
border: `1px solid ${colors.border.light}`,
|
||||
fontSize: '14px',
|
||||
},
|
||||
};
|
||||
|
||||
// 表单标签样式
|
||||
export const formLabelStyles = {
|
||||
// 基础标签样式
|
||||
base: {
|
||||
fontSize: '14px',
|
||||
fontWeight: '500',
|
||||
color: colors.text.primary,
|
||||
marginBottom: '6px',
|
||||
display: 'block',
|
||||
},
|
||||
|
||||
// 必填标签样式
|
||||
required: {
|
||||
fontSize: '14px',
|
||||
fontWeight: '500',
|
||||
color: colors.text.primary,
|
||||
marginBottom: '6px',
|
||||
},
|
||||
|
||||
// 小标签
|
||||
small: {
|
||||
fontSize: '13px',
|
||||
fontWeight: '500',
|
||||
color: colors.text.secondary,
|
||||
marginBottom: '4px',
|
||||
},
|
||||
};
|
||||
|
||||
// 表单项样式
|
||||
export const formItemStyles = {
|
||||
// 基础表单项
|
||||
base: {
|
||||
marginBottom: '20px',
|
||||
},
|
||||
|
||||
// 紧凑表单项
|
||||
compact: {
|
||||
marginBottom: '12px',
|
||||
},
|
||||
|
||||
// 错误状态
|
||||
error: {
|
||||
marginBottom: '20px',
|
||||
},
|
||||
|
||||
// 错误提示文字
|
||||
errorText: {
|
||||
color: colors.error.main,
|
||||
fontSize: '12px',
|
||||
marginTop: '4px',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: '4px',
|
||||
},
|
||||
};
|
||||
|
||||
// 过滤器区域输入框样式
|
||||
export const filterInputStyles = {
|
||||
// 过滤器输入框容器
|
||||
container: {
|
||||
marginBottom: '6px',
|
||||
fontSize: '13px',
|
||||
color: colors.text.secondary,
|
||||
fontWeight: '500',
|
||||
},
|
||||
|
||||
// 过滤器输入框
|
||||
input: {
|
||||
height: '40px',
|
||||
borderRadius: borderRadius.medium,
|
||||
border: `1px solid ${colors.border.light}`,
|
||||
fontSize: '14px',
|
||||
width: '100%',
|
||||
},
|
||||
|
||||
// 过滤器选择器
|
||||
select: {
|
||||
height: '40px',
|
||||
borderRadius: borderRadius.medium,
|
||||
fontSize: '14px',
|
||||
width: '100%',
|
||||
},
|
||||
};
|
||||
|
||||
// 输入框验证规则配置
|
||||
export const inputValidationRules = {
|
||||
// 必填规则
|
||||
required: (message = '此字段为必填项') => ({
|
||||
required: true,
|
||||
message,
|
||||
}),
|
||||
|
||||
// 最大长度规则
|
||||
maxLength: (max, message) => ({
|
||||
max,
|
||||
message: message || `不能超过${max}个字符`,
|
||||
}),
|
||||
|
||||
// 最小长度规则
|
||||
minLength: (min, message) => ({
|
||||
min,
|
||||
message: message || `不能少于${min}个字符`,
|
||||
}),
|
||||
|
||||
// 数字范围规则
|
||||
numberRange: (min, max, message) => ({
|
||||
type: 'number',
|
||||
min,
|
||||
max,
|
||||
message: message || `数值应在${min}到${max}之间`,
|
||||
}),
|
||||
|
||||
// 正整数规则
|
||||
positiveInteger: () => ({
|
||||
pattern: /^\d+$/,
|
||||
message: '请输入正整数',
|
||||
}),
|
||||
|
||||
// 价格规则(两位小数)
|
||||
price: () => ({
|
||||
pattern: /^\d+(\.\d{1,2})?$/,
|
||||
message: '请输入有效的价格(最多两位小数)',
|
||||
}),
|
||||
|
||||
// 邮箱规则
|
||||
email: () => ({
|
||||
type: 'email',
|
||||
message: '请输入有效的邮箱地址',
|
||||
}),
|
||||
|
||||
// 手机号规则
|
||||
phone: () => ({
|
||||
pattern: /^1[3-9]\d{9}$/,
|
||||
message: '请输入有效的手机号码',
|
||||
}),
|
||||
};
|
||||
|
||||
// 输入框占位符文本配置
|
||||
export const inputPlaceholders = {
|
||||
// 耗材相关
|
||||
consumableName: '请输入耗材名称',
|
||||
consumableId: '请输入耗材ID',
|
||||
category: '请选择分类',
|
||||
unit: '如: 个、盒、卷、箱',
|
||||
stock: '请输入库存数量',
|
||||
minStock: '请输入最小库存',
|
||||
maxStock: '请输入最大库存',
|
||||
unitPrice: '请输入单价',
|
||||
supplier: '请输入供应商名称',
|
||||
location: '如: A柜-01层、B区货架3',
|
||||
description: '请输入描述信息',
|
||||
operator: '请输入操作人姓名',
|
||||
reason: '请输入原因',
|
||||
notes: '请输入备注信息',
|
||||
snList: '输入SN后按回车添加',
|
||||
|
||||
// 搜索相关
|
||||
search: '搜索...',
|
||||
searchConsumable: '搜索耗材ID、名称、分类、供应商',
|
||||
searchCategory: '搜索分类名称、描述',
|
||||
|
||||
// 日期相关
|
||||
dateRange: ['开始日期', '结束日期'],
|
||||
|
||||
// 通用
|
||||
select: '请选择',
|
||||
input: '请输入',
|
||||
};
|
||||
|
||||
// CSS-in-JS 样式字符串生成函数
|
||||
export const generateGlobalStyles = tokens => `
|
||||
.device-modal .ant-modal-close {
|
||||
|
||||
Reference in New Issue
Block a user