feat(auth): 冷启动登录态校验 + 设备/房间列表样式打磨
- 新增 getLoginInfo(/v0/app/users/getLoginInfo)冷启动校验 token 有效性, http 层将 /v0/ 前缀路由到 user 服务;登录页 useDidShow 恢复 userInfo 后落地,restoring 态防并发登录 - 详情页指标卡配色从数值移到标签(对齐 web 端 MetricCard), 心率图标加底、设备信息卡补"设备信息"标题 - 设备列表新增"我的设备 N"分区标题,功能入口图标加圆底 - 房间列表改整卡圆角+行内分隔,删除按钮改浅红胶囊 - global.d.ts 补 png/jpg 模块声明
This commit is contained in:
parent
9f3ea3d82b
commit
40783ccabe
|
|
@ -48,3 +48,9 @@ export function wxMiniappLogin(params: WxMiniappLoginParams): Promise<WxMiniappL
|
|||
{ needAuth: false }
|
||||
)
|
||||
}
|
||||
|
||||
// 冷启动登录态校验:token 有效返回登录信息,过期返回 202 由 http 层统一踢登录页。
|
||||
// 响应 Content 结构(ResponseData<UserInfo>)联调实测后修正字段
|
||||
export function getLoginInfo(): Promise<WxUserInfo> {
|
||||
return request.get('/v0/app/users/getLoginInfo')
|
||||
}
|
||||
|
|
|
|||
|
|
@ -72,8 +72,8 @@ export async function request<T>(
|
|||
if (tokenAtStart) headers.token = tokenAtStart
|
||||
}
|
||||
|
||||
// 登录接口走 user 服务前缀,其余业务接口走 biz 前缀
|
||||
const base = url.startsWith('/thirdPlatform/') ? USER_BASE : BIZ_BASE
|
||||
// 登录接口与 users 系列冷启动校验接口走 user 服务前缀,其余业务接口走 biz 前缀
|
||||
const base = url.startsWith('/thirdPlatform/') || url.startsWith('/v0/') ? USER_BASE : BIZ_BASE
|
||||
|
||||
let res: Taro.request.SuccessCallbackResult<ApiEnvelope<T>>
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -8,7 +8,8 @@
|
|||
margin: 24px;
|
||||
padding: 40px 32px;
|
||||
background: $color-bg-white;
|
||||
border-radius: $radius-md;
|
||||
border-radius: $radius-lg;
|
||||
box-shadow: $shadow-card;
|
||||
}
|
||||
|
||||
.sectionTitle {
|
||||
|
|
@ -32,11 +33,17 @@
|
|||
height: 96px;
|
||||
padding: 0 32px;
|
||||
background: $color-bg-gray;
|
||||
border: 1px solid transparent;
|
||||
border-radius: $radius-md;
|
||||
font-size: 28px;
|
||||
color: $color-text;
|
||||
box-sizing: border-box;
|
||||
margin-bottom: 32px;
|
||||
|
||||
&:focus {
|
||||
border-color: $color-primary;
|
||||
background: $color-bg-white;
|
||||
}
|
||||
}
|
||||
|
||||
// 安装房间选择:label + 横向 chip 组
|
||||
|
|
|
|||
|
|
@ -13,11 +13,12 @@
|
|||
.heartCard {
|
||||
margin: 24px;
|
||||
padding: 32px;
|
||||
background: $color-bg-white;
|
||||
background: linear-gradient(135deg, #fff 0%, #fdf7f6 100%);
|
||||
border-radius: $radius-lg;
|
||||
box-shadow: $shadow-card;
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
border: 1px solid rgba(245, 34, 45, 0.06);
|
||||
}
|
||||
|
||||
.heartLeft {
|
||||
|
|
@ -27,7 +28,22 @@
|
|||
min-width: 200px;
|
||||
}
|
||||
|
||||
.heartIcon { font-size: 72px; color: $color-danger; line-height: 1; }
|
||||
// 心形图标:浅红圆底衬托,弱化大面积实色
|
||||
.heartIconWrap {
|
||||
width: 88px;
|
||||
height: 88px;
|
||||
border-radius: $radius-circle;
|
||||
background: $color-danger-light-bg;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.heartIcon {
|
||||
font-size: 48px;
|
||||
color: $color-danger;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.heartValue {
|
||||
margin-top: 16px;
|
||||
|
|
@ -87,21 +103,45 @@
|
|||
width: 48.5%;
|
||||
box-sizing: border-box;
|
||||
margin-bottom: 20px;
|
||||
padding: 24px;
|
||||
padding: 28px 24px;
|
||||
background: $color-bg-white;
|
||||
border-radius: $radius-md;
|
||||
box-shadow: $shadow-card;
|
||||
}
|
||||
|
||||
.metricLabel { font-size: 26px; color: $color-text-secondary; }
|
||||
// 指标名左侧小色条:六卡各自的语义色,替代大数字整体染色
|
||||
.metricLabel {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 26px;
|
||||
color: $color-text-secondary;
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
width: 8px;
|
||||
height: 24px;
|
||||
border-radius: $radius-pill;
|
||||
margin-right: 12px;
|
||||
background: $color-text-placeholder;
|
||||
}
|
||||
}
|
||||
|
||||
.metricLabelBlue::before { background: $color-info; }
|
||||
.metricLabelOrange::before { background: $color-warning; }
|
||||
.metricLabelGreen::before { background: $color-success; }
|
||||
.metricLabelRed::before { background: $color-danger; }
|
||||
|
||||
.metricRow {
|
||||
margin-top: 12px;
|
||||
margin-top: 14px;
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
}
|
||||
|
||||
.metricValue { font-size: 44px; font-weight: 700; }
|
||||
.metricValue {
|
||||
font-size: 44px;
|
||||
font-weight: 700;
|
||||
color: $color-text;
|
||||
}
|
||||
|
||||
.metricBlue { color: $color-primary-deep; }
|
||||
.metricOrange { color: #fa8c16; }
|
||||
|
|
@ -114,6 +154,15 @@
|
|||
color: $color-text-tertiary;
|
||||
}
|
||||
|
||||
// 设备信息卡分区标题
|
||||
.infoTitle {
|
||||
display: block;
|
||||
margin: 24px 24px 16px;
|
||||
font-size: 30px;
|
||||
font-weight: 600;
|
||||
color: $color-text;
|
||||
}
|
||||
|
||||
.infoCard {
|
||||
margin: 4px 24px 24px;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -127,7 +127,9 @@ export default function Detail() {
|
|||
|
||||
<View className={styles.heartCard}>
|
||||
<View className={styles.heartLeft}>
|
||||
<View className={styles.heartIconWrap}>
|
||||
<Text className={styles.heartIcon}>❤</Text>
|
||||
</View>
|
||||
<Text className={styles.heartValue}>{fmt(signs?.heartRate)}</Text>
|
||||
<Text className={styles.heartUnit}>BPM</Text>
|
||||
<View className={`${styles.badge} ${online ? styles.badgeOn : styles.badgeOff}`}>
|
||||
|
|
@ -146,45 +148,46 @@ export default function Detail() {
|
|||
|
||||
<View className={styles.metricGrid}>
|
||||
<View className={styles.metricCard}>
|
||||
<Text className={styles.metricLabel}>呼吸率</Text>
|
||||
<Text className={`${styles.metricLabel} ${styles.metricLabelBlue}`}>呼吸率</Text>
|
||||
<View className={styles.metricRow}>
|
||||
<Text className={`${styles.metricValue} ${styles.metricBlue}`}>{fmt(signs?.respiratoryRate)}</Text>
|
||||
<Text className={styles.metricValue}>{fmt(signs?.respiratoryRate)}</Text>
|
||||
<Text className={styles.metricUnit}>/min</Text>
|
||||
</View>
|
||||
</View>
|
||||
<View className={styles.metricCard}>
|
||||
<Text className={styles.metricLabel}>体动</Text>
|
||||
<Text className={`${styles.metricLabel} ${styles.metricLabelOrange}`}>体动</Text>
|
||||
<View className={styles.metricRow}>
|
||||
<Text className={`${styles.metricValue} ${styles.metricOrange}`}>{fmt(signs?.bodyMovement)}</Text>
|
||||
<Text className={styles.metricValue}>{fmt(signs?.bodyMovement)}</Text>
|
||||
</View>
|
||||
</View>
|
||||
<View className={styles.metricCard}>
|
||||
<Text className={styles.metricLabel}>运动状态</Text>
|
||||
<Text className={`${styles.metricLabel} ${styles.metricLabelGreen}`}>运动状态</Text>
|
||||
<View className={styles.metricRow}>
|
||||
<Text className={`${styles.metricValue} ${styles.metricGreen}`}>{MOVE_STATE_MAP[signs?.moveState ?? -1] ?? '--'}</Text>
|
||||
<Text className={styles.metricValue}>{MOVE_STATE_MAP[signs?.moveState ?? -1] ?? '--'}</Text>
|
||||
</View>
|
||||
</View>
|
||||
<View className={styles.metricCard}>
|
||||
<Text className={styles.metricLabel}>在床状态</Text>
|
||||
<Text className={`${styles.metricLabel} ${styles.metricLabelRed}`}>在床状态</Text>
|
||||
<View className={styles.metricRow}>
|
||||
<Text className={`${styles.metricValue} ${styles.metricRed}`}>{ONBED_STATUS_MAP[signs?.onbedStatus ?? -1] ?? '--'}</Text>
|
||||
<Text className={styles.metricValue}>{ONBED_STATUS_MAP[signs?.onbedStatus ?? -1] ?? '--'}</Text>
|
||||
</View>
|
||||
</View>
|
||||
<View className={styles.metricCard}>
|
||||
<Text className={styles.metricLabel}>人体状态</Text>
|
||||
<Text className={`${styles.metricLabel} ${styles.metricLabelBlue}`}>人体状态</Text>
|
||||
<View className={styles.metricRow}>
|
||||
<Text className={`${styles.metricValue} ${styles.metricBlue}`}>{BODY_STATUS_MAP[signs?.bodyStatus ?? -1] ?? '--'}</Text>
|
||||
<Text className={styles.metricValue}>{BODY_STATUS_MAP[signs?.bodyStatus ?? -1] ?? '--'}</Text>
|
||||
</View>
|
||||
</View>
|
||||
<View className={styles.metricCard}>
|
||||
<Text className={styles.metricLabel}>人体位置</Text>
|
||||
<Text className={`${styles.metricLabel} ${styles.metricLabelGreen}`}>人体位置</Text>
|
||||
<View className={styles.metricRow}>
|
||||
<Text className={`${styles.metricValue} ${styles.metricGreen}`}>{fmt(signs?.bodyPosition)}</Text>
|
||||
<Text className={styles.metricValue}>{fmt(signs?.bodyPosition)}</Text>
|
||||
<Text className={styles.metricUnit}>分米</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<Text className={styles.infoTitle}>设备信息</Text>
|
||||
<View className={styles.infoCard}>
|
||||
<ListRowGroup>
|
||||
<ListRow label="设备型号" value={deviceModel || '-'} />
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
// 绿色衬底:占位高度与浮卡上浮量(-40px)匹配,卡片叠在它上面而不是压进导航栏
|
||||
.heroSpace {
|
||||
height: 64px;
|
||||
background: #2ccb98;
|
||||
background: linear-gradient(180deg, #2ccb98 0%, #35d6a5 100%);
|
||||
margin-bottom: -40px;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
|
|
@ -27,7 +27,7 @@
|
|||
padding: 8px 32px 32px;
|
||||
background: $color-bg-white;
|
||||
border-radius: $radius-lg;
|
||||
box-shadow: $shadow-card;
|
||||
box-shadow: 0 8px 24px rgba(44, 203, 152, 0.12);
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
}
|
||||
|
|
@ -38,6 +38,10 @@
|
|||
align-items: center;
|
||||
justify-content: space-between;
|
||||
border-bottom: 1px solid $color-border;
|
||||
|
||||
&:last-of-type {
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
|
||||
.familyLabel {
|
||||
|
|
@ -75,7 +79,7 @@
|
|||
// 房间管理 / 添加设备 两张并排功能卡
|
||||
.funcRow {
|
||||
display: flex;
|
||||
padding: 24px;
|
||||
padding: 24px 24px 0;
|
||||
gap: 24px;
|
||||
}
|
||||
|
||||
|
|
@ -86,20 +90,30 @@
|
|||
border-radius: $radius-md;
|
||||
box-shadow: $shadow-card;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.funcCardPressed {
|
||||
background: $color-bg-press;
|
||||
}
|
||||
|
||||
// 左侧圆角浅绿图标底:延续「左图标色块」卡片语言
|
||||
.funcIconWrap {
|
||||
width: 88px;
|
||||
height: 88px;
|
||||
border-radius: $radius-md;
|
||||
background: $color-primary-light-bg;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.funcIcon {
|
||||
font-size: 56px;
|
||||
font-size: 48px;
|
||||
color: $color-primary;
|
||||
line-height: 1;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.funcText {
|
||||
|
|
@ -113,7 +127,7 @@
|
|||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
overflow-x: auto;
|
||||
padding: 0 24px 24px;
|
||||
padding: 24px 24px 8px;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
|
|
@ -121,16 +135,40 @@
|
|||
flex-shrink: 0;
|
||||
padding: 12px 32px;
|
||||
background: $color-bg-white;
|
||||
border: 1px solid $color-border;
|
||||
border-radius: $radius-pill;
|
||||
box-shadow: $shadow-card;
|
||||
font-size: 26px;
|
||||
color: $color-text-secondary;
|
||||
}
|
||||
|
||||
.roomChipActive {
|
||||
background: $color-primary-grad;
|
||||
border-color: transparent;
|
||||
}
|
||||
|
||||
.roomChipTextActive {
|
||||
color: #ffffff;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
// 「我的设备」分区标题:筛选条与网格之间的视觉锚点
|
||||
.sectionTitle {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 24px 24px 16px;
|
||||
font-size: 30px;
|
||||
font-weight: 600;
|
||||
color: $color-text;
|
||||
|
||||
.sectionCount {
|
||||
margin-left: 12px;
|
||||
padding: 2px 16px;
|
||||
background: $color-primary-light-bg;
|
||||
border-radius: $radius-pill;
|
||||
font-size: 22px;
|
||||
font-weight: 500;
|
||||
color: $color-primary-deep;
|
||||
}
|
||||
}
|
||||
|
||||
// 设备网格
|
||||
|
|
@ -144,7 +182,7 @@
|
|||
.card {
|
||||
width: 48.5%;
|
||||
margin-bottom: 24px;
|
||||
padding: 36px 20px 24px;
|
||||
padding: 36px 20px 28px;
|
||||
box-sizing: border-box;
|
||||
background: $color-bg-white;
|
||||
border-radius: $radius-lg;
|
||||
|
|
@ -152,6 +190,11 @@
|
|||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
border: 1px solid transparent;
|
||||
|
||||
&:active {
|
||||
border-color: $color-primary-light-border;
|
||||
}
|
||||
}
|
||||
|
||||
// 上半区(图标/名称/状态)点击进详情,下方解绑按钮独立命中
|
||||
|
|
@ -166,13 +209,14 @@
|
|||
width: 108px;
|
||||
height: 108px;
|
||||
padding: 14px;
|
||||
border-radius: $radius-circle;
|
||||
border-radius: 32px;
|
||||
background: $color-primary-grad;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-bottom: 20px;
|
||||
box-sizing: border-box;
|
||||
box-shadow: 0 6px 16px rgba(44, 203, 152, 0.25);
|
||||
}
|
||||
|
||||
.iconOffline { background: $color-bg-disabled; }
|
||||
|
|
@ -228,13 +272,14 @@
|
|||
.sheetItem {
|
||||
padding: 24px 32px;
|
||||
background: $color-bg-gray;
|
||||
border: 2px solid transparent;
|
||||
border-radius: $radius-md;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.sheetItemActive {
|
||||
background: $color-primary-light-bg;
|
||||
border: 2px solid $color-primary;
|
||||
border-color: $color-primary;
|
||||
}
|
||||
|
||||
.sheetHead {
|
||||
|
|
|
|||
|
|
@ -182,11 +182,15 @@ export default function DeviceList() {
|
|||
{/* 房间管理 + 添加设备 两张并排 */}
|
||||
<View className={styles.funcRow}>
|
||||
<View className={styles.funcCard} hoverClass={styles.funcCardPressed} onClick={goRoom}>
|
||||
<View className={styles.funcIconWrap}>
|
||||
<Text className={styles.funcIcon}>⌂</Text>
|
||||
</View>
|
||||
<Text className={styles.funcText}>房间管理</Text>
|
||||
</View>
|
||||
<View className={styles.funcCard} hoverClass={styles.funcCardPressed} onClick={goAdd}>
|
||||
<View className={styles.funcIconWrap}>
|
||||
<Text className={styles.funcIcon}>+</Text>
|
||||
</View>
|
||||
<Text className={styles.funcText}>添加设备</Text>
|
||||
</View>
|
||||
</View>
|
||||
|
|
@ -215,6 +219,14 @@ export default function DeviceList() {
|
|||
</View>
|
||||
)}
|
||||
|
||||
{/* 「我的设备」分区标题:数量随筛选联动 */}
|
||||
{!loading && !loadError && (
|
||||
<View className={styles.sectionTitle}>
|
||||
<Text>我的设备</Text>
|
||||
<Text className={styles.sectionCount}>{deviceList.length}</Text>
|
||||
</View>
|
||||
)}
|
||||
|
||||
{/* 设备网格 */}
|
||||
{loading ? (
|
||||
<View className={styles.stateWrap}><Loading /></View>
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import { useRouter, useDidShow } from '@tarojs/taro'
|
|||
import { useAppDispatch, useAppSelector } from '@/store/hooks'
|
||||
import { setAuth } from '@/store/authSlice'
|
||||
import { performWxLogin, completeUserInfoLogin, getLoginSubState } from './wxLoginFlow'
|
||||
import { getLoginInfo } from '@/api/auth'
|
||||
import { useToast } from '@/hooks/useToast'
|
||||
import { ROUTES } from '@/constants/routes'
|
||||
import { reLaunch } from '@/utils/navigation'
|
||||
|
|
@ -20,6 +21,8 @@ export default function Login() {
|
|||
// 注册中间态:needUserInfo(待用户资料授权)→ null(初始/完成)
|
||||
const [needAuth, setNeedAuth] = useState(false)
|
||||
const [openId, setOpenId] = useState('')
|
||||
// 冷启动校验进行中:阻止 useDidShow 与按钮登录并发
|
||||
const [restoring, setRestoring] = useState(false)
|
||||
|
||||
// 登录后落地页:携带 redirect 参数时优先回跳(守卫踢登录/分享卡直达场景),否则进首页
|
||||
const afterLoginUrl = () => {
|
||||
|
|
@ -28,9 +31,20 @@ export default function Login() {
|
|||
return target || ROUTES.HOME
|
||||
}
|
||||
|
||||
// 已有 token 直接进首页(本期不做 checkLogin 校验,spec D5)
|
||||
// 冷启动 token 有效性校验:有效则恢复 userInfo(内存态,重启即失)后进首页;
|
||||
// 无效 getLoginInfo 返回 202,http 层统一 clearAuth + 踢回本页,此处无需分支
|
||||
useDidShow(() => {
|
||||
if (token && !loading) reLaunch(afterLoginUrl())
|
||||
if (!token || loading || restoring) return
|
||||
setRestoring(true)
|
||||
getLoginInfo()
|
||||
.then((userInfo) => {
|
||||
dispatch(setAuth({ token, userInfo }))
|
||||
return reLaunch(afterLoginUrl())
|
||||
})
|
||||
.catch(() => {
|
||||
// 202 分支 http 层已踢回本页(reLaunch 目标即本页,幂等);其余异常保持登录页可手动登录
|
||||
})
|
||||
.finally(() => setRestoring(false))
|
||||
})
|
||||
|
||||
// 完整登录态校验与落地;未完成时推进授权态
|
||||
|
|
@ -61,7 +75,7 @@ export default function Login() {
|
|||
}
|
||||
|
||||
const handleWxLogin = async () => {
|
||||
if (loading) return
|
||||
if (loading || restoring) return
|
||||
setLoading(true)
|
||||
try {
|
||||
applyResult(await performWxLogin())
|
||||
|
|
@ -102,7 +116,7 @@ export default function Login() {
|
|||
onClick={needAuth ? handleAuthUserInfo : handleWxLogin}
|
||||
>
|
||||
<Text className={styles.submitText}>
|
||||
{loading ? '登录中...' : needAuth ? '授权用户信息,继续' : '微信一键登录'}
|
||||
{loading ? '登录中...' : restoring ? '恢复登录...' : needAuth ? '授权用户信息,继续' : '微信一键登录'}
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
|
|
|
|||
|
|
@ -11,16 +11,26 @@
|
|||
align-items: center;
|
||||
}
|
||||
|
||||
.list { margin-top: 20px; }
|
||||
// 房间列表:整体一张圆角卡,行内分隔
|
||||
.list {
|
||||
margin: 24px;
|
||||
background: $color-bg-white;
|
||||
border-radius: $radius-lg;
|
||||
box-shadow: $shadow-card;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.item {
|
||||
min-height: 104px;
|
||||
min-height: 112px;
|
||||
padding: 16px 32px;
|
||||
margin-bottom: 2px;
|
||||
background: $color-bg-white;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
border-bottom: 1px solid $color-border;
|
||||
|
||||
&:last-of-type {
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
|
||||
// 名称 + 场景标签组:点击进编辑
|
||||
|
|
@ -50,20 +60,24 @@
|
|||
color: $color-primary-deep;
|
||||
}
|
||||
|
||||
// 删除操作:胶囊浅红底,弱化破坏性但保持可识别
|
||||
.del {
|
||||
flex-shrink: 0;
|
||||
margin-left: 24px;
|
||||
font-size: 26px;
|
||||
padding: 8px 24px;
|
||||
background: $color-danger-light-bg;
|
||||
border-radius: $radius-pill;
|
||||
font-size: 24px;
|
||||
color: $color-danger;
|
||||
}
|
||||
|
||||
// 添加房间:虚线边框卡,与家庭圈添加卡风格一致
|
||||
.addBtn {
|
||||
margin: 24px 24px 0;
|
||||
margin: 24px;
|
||||
height: 104px;
|
||||
border: 1px dashed $color-primary-light-border;
|
||||
border: 2px dashed $color-primary-light-border;
|
||||
border-radius: $radius-md;
|
||||
background: $color-bg-white;
|
||||
background: $color-primary-light-bg;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
|
@ -104,10 +118,16 @@
|
|||
height: 88px;
|
||||
padding: 0 32px;
|
||||
background: $color-bg-gray;
|
||||
border: 1px solid transparent;
|
||||
border-radius: $radius-md;
|
||||
font-size: 28px;
|
||||
color: $color-text;
|
||||
box-sizing: border-box;
|
||||
|
||||
&:focus {
|
||||
border-color: $color-primary;
|
||||
background: $color-bg-white;
|
||||
}
|
||||
}
|
||||
|
||||
.senceGrid {
|
||||
|
|
|
|||
|
|
@ -2,3 +2,13 @@ declare module '*.module.scss' {
|
|||
const classes: { readonly [key: string]: string }
|
||||
export default classes
|
||||
}
|
||||
|
||||
declare module '*.png' {
|
||||
const src: string
|
||||
export default src
|
||||
}
|
||||
|
||||
declare module '*.jpg' {
|
||||
const src: string
|
||||
export default src
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue