text-align:justify兼容写法

本文探讨了CSS中text-align属性的使用技巧,特别是在实现文本两端对齐时遇到的问题及解决方案。通过实例说明如何利用内联块状元素使单行文本也能达到两端对齐的效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

兼容测试referrer:

http://caniuse.com/#search=text-align-last

 

为什么单独设置text-align:justify;不起作用,非要在后面加一个内联块状元素宽度为100%的才可以?

<class="center">我是两端对齐文字端对齐文字<span></span></p>
 
.center{
  text-align:justify;
}

span{
  display:inline-block;
  width:100%;
}

这个是因为text-align不会处理被打断的行和最后一行。因为你这里的文字只占了一行,所以也是最后一行了,所以text-align设置为justify不会产生任何效果。
解决方法是使用text-align-last,并将其设置为justify。
不过不幸的是,text-align-last不是所有浏览器支持。

所以对于不支持text-align-last的,可以在最后一行人工生成两行文本,然后把第二行隐藏了,那么我们要现实的第一行自然就可以实现两端对齐了。

而你的span是inline-block,也可以设置宽度(100%),那么这个时候内联匿名盒的宽度超过行盒,浏览器会将其拆成两行,自然第一行文本的text-align效果就生效了。你的实现刚刚好是上面的第二个实现方法。

 

转载于:https://www.cnblogs.com/tangchangcai/p/7774056.html

<template> <view class="wapper"> <!-- <view class="bg-image"></view> --> <image class="bg-image" src="/static/home/bus/bg-image.png" mode="widthFix" style="width: 100%;" /> <!-- 自定义导航栏 --> <view class="custom-navbar" :style="{ paddingTop: statusBarHeight + 'px' }"> <view class="navbar-content"> <!-- 左侧返回按钮 --> <view class="back-btn" @click="handleBack"> <image src="/static/home/bus/back-icon.png" mode="aspectFit" style="width: 48rpx;height: 48rpx;" /> </view> <!-- 中间标题 --> <text class="title">{{busLineBase.name}}</text> </view> </view> <view class="wapper-content" :style="{ paddingTop: statusBarHeight +50 + 'px' }"> <view class="line_info"> <view class="site"> <text class="from">{{busLineBase.startSn}}</text> <view class="arrow"> <text class="to">{{busLineBase.endSn}}</text> </view> </view> <view class="tit"> <view class="time_s"> <text class="time-text">{{busLineBase.firstTime}}</text> </view> <view class="time_e"> <text class="time-text">{{busLineBase.lastTime}}</text> </view> <text class="price">票价: {{busLineBase.price}}</text> </view> </view> <view class="distance-class"> <view class="station"> <view class="station-title"> <view class="station-name">候车站</view> <view class="station-content"> <view class="active">{{stationName}}</view> <view class="underline"></view> </view> </view> </view> <view class="distance" v-if="state==0 && travelOrder!=0"> <view class="time"> <text class="time_title">{{Math.ceil(travelTime/60)}}分钟</text> </view> <text class="arr">{{travelOrder}}站/ <text v-if="travelDistance<1000">{{numFilter(travelDistance)}}m</text> <text v-else>{{numFilter(travelDistance/1000)}}km</text> </text> </view> <view class="distance" v-else-if="state==0 && travelOrder==0 && isArrive==1"> <view class="time"> <view class="bus-arr">已到站</view> </view> </view> <view class="distance" v-else-if="state==0 &&isArrive==0"> <view class="time"> <view class="bus-coming">即将到站 {{travelDistance}}m</view> </view> </view> <view class="distance" v-else-if="state==-1"> <view class="time"> <view class="none">等待发车</view> </view> </view> <view class="distance" v-else> <view class="time"> <view class="none">暂无车辆信息</view> </view> </view> <!-- <view>已到站</view> --> </view> </view> <view class="site_list"> <scroll-view class="wapper_sitelist" scroll-x="true" scroll-with-animation :scroll-into-view="targetId"> <view class="road"> <view class='part' v-for="(item, index) in siteList" @click="showActive(index, item.sn)"> <view :id="'id'+item.sid" class='name'> <view> <view class="dot_p" :class="{'dot_p_show': ind === index}"></view> <view class='dot_r' v-if="index!=siteList.length-1"></view> </view> <div :class="item.state==1?'road-bus':'road-bus-coming'" v-if="item.isHaveBus==0"></div> <view class='dot_d' :class="{'dot_d_show': ind === index}"></view> <view class='text' :class="{'text_show': ind === index}"> <view>{{index +1}}</view> <view class="text-dir"> {{item.sn}} </view> </view> </view> </view> </view> </scroll-view> <!-- <view class="my-map"></view> --> </view> <view class="my-map"> 223123 <web-view ref="webview" :webview-styles="webviewStyles" :src="src" @onPostMessage="getMessage"></web-view> </view> </view> </template> <script> import { getRealTimeBusLine, getRealTimeBusLineStation } from '@/request/bus.js' export default { data() { return { src: '', timer: null, isArrive: 0, targetId: '', state: 0, stationName: '', travelDistance: 0, travelTime: 0, travelOrder: 0, ratio: '', ind: '', siteId: "", lineName: "二号线", siteName: "动漫园站", siteList: [], busLineBase: [], stateBus: [], time_s: '', time_e: '', from: '', busPosition: [0, 5, 11], to: '', isActive: false, lineId: '', siteNum: '0', haveBus: true, webviewStyles: { position: 'absolute', top: '850px', bottom: '30px', // zIndex: '999', marginTop: '850px', marginLeft: '20px', marginRight: '20px', marginBottom: '10px', height: '500px' } // 保留原有数据项... } }, onLoad(options) { // 获取路由参数 const { statusBarHeight } = uni.getSystemInfoSync() // const systemInfo = uni.getSystemInfoSync(); // this.ratio = (systemInfo.windowWidth / 750) / 0.5 console.log("options", options) this.statusBarHeight = statusBarHeight this.lineId = options.lineId this.lat = options.lat this.lng = options.lng this.lineName = options.lineName this.getLineDetail() if (this.timer) { clearInterval(this.timer); this.timer = null; } // this.timer = setInterval(() => { // console.log("30") // this.refresh() // }, 1000 * 30); this.init() }, methods: { init() { setTimeout(() => { this.src = '../../../../hybrid/html/map.html' }, 1000); }, handlePostMessage(res) { this.$refs.webview.evalJs(`handleMessage()`); }, getMessage(e) { uni.showModal({ content: "111", showCancel: false }) }, numFilter(value) { if (value != 0) { // 将数值转换为浮点数,并保留两位小数 let realVal = parseFloat(value).toFixed(2); return realVal; } }, async getLineDetail() { var res = await getRealTimeBusLine({ lineId: this.lineId, lat: this.lat, lng: this.lng }) if (res.code == 0) { console.log("1", res) this.siteList = res.data.busInfStop var ind = res.data.targetOrder this.ind = res.data.targetOrder - 1 this.stationName = this.siteList[ind - 1].sn this.state = res.data.state this.busLineBase = res.data.busLineBase this.targetOrder = res.data.targetOrder this.$nextTick(function() { this.targetId = 'id' + this.siteList[ind - 4].sid }); if (this.state == 0) { this.stateBus = res.data.stateBus var travelsList = this.stateBus.travels this.distance = this.findAllClosest(this.stateBus, this.targetOrder) if (this.distance.length != 0) { var travels = this.distance[0].travels this.travelDistance = travels[0].travelDistance this.travelOrder = travels[0].travelOrder this.travelTime = travels[0].travelTime this.siteList = this.processArrays(this.siteList, this.stateBus, 'order', 'state'); } } } }, async showActive(index, siteName) { this.ind = index this.stationName = siteName var res = await getRealTimeBusLineStation({ lineId: this.lineId, stationName: this.stationName }) if (res.code == 0) { this.siteList = res.data.busInfStop var ind = res.data.targetOrder this.stationName = this.siteList[ind - 1].sn this.state = res.data.state this.busLineBase = res.data.busLineBase this.ind = res.data.targetOrder - 1 this.targetOrder = res.data.targetOrder this.$nextTick(function() { this.targetId = 'id' + this.siteList[ind - 4].sid }); if (this.state == 0) { this.stateBus = res.data.stateBus var travelsList = this.stateBus.travels this.distance = this.findAllClosest(this.stateBus, this.targetOrder) if (this.distance.length != 0) { var travels = this.distance[0].travels this.travelDistance = travels[0].travelDistance this.travelOrder = travels[0].travelOrder this.travelTime = travels[0].travelTime this.isArrive = this.distance[0].state this.siteList = this.processArrays(this.siteList, this.stateBus, 'order', 'state'); } } } }, handleBack() { uni.navigateBack() }, async refresh() { console.log("刷新") var res = await getRealTimeBusLineStation({ lineId: this.lineId, stationName: this.stationName }) if (res.code == 0) { this.siteList = res.data.busInfStop var ind = res.data.targetOrder this.stationName = this.siteList[ind - 1].sn this.state = res.data.state this.busLineBase = res.data.busLineBase this.ind = res.data.targetOrder - 1 this.targetOrder = res.data.targetOrder this.$nextTick(function() { this.targetId = 'id' + this.siteList[ind - 4].sid }); if (this.state == 0) { this.stateBus = res.data.stateBus var travelsList = this.stateBus.travels this.distance = this.findAllClosest(this.stateBus, this .targetOrder) if (this.distance.length != 0) { var travels = this.distance[0].travels this.travelDistance = travels[0].travelDistance this.travelOrder = travels[0].travelOrder this.travelTime = travels[0].travelTime this.isArrive = this.distance[0].state this.siteList = this.processArrays(this.siteList, this .stateBus, 'order', 'state'); } } } }, // 找到距离最近车站的小车 findAllClosest(arr, target) { const validItems = arr.filter(item => item.order < target + 1); if (validItems.length === 0) return []; const distances = validItems.map(item => ({ item, distance: Math.abs(item.order - target) })); if (distances.length != 0) { const minDist = Math.min(...distances.map(d => d.distance)); return distances.filter(d => d.distance === minDist).map(d => d.item); } }, processArrays(arrayA, arrayB, key, valueKey) { // 创建arrayB的快速查找映射(基于指定键) const bMap = new Map(); arrayB.forEach(item => { if (item[key] !== undefined) { bMap.set(item[key], item); } }); // 遍历arrayA并添加属性 return arrayA.map(itemA => { // 浅拷贝避免修改原对象 const newItem = { ...itemA }; // 检查是否存在匹配元素 if (bMap.has(newItem[key])) { const matchedB = bMap.get(newItem[key]); // newItem.state = 0; newItem.isHaveBus = 0; // 添加arrayB中的属性值(如果存在) if (matchedB[valueKey] !== undefined) { newItem[valueKey] = matchedB[valueKey]; } } return newItem; }); } }, onPullDownRefresh() { console.log("下拉") this.refresh() setTimeout(() => { //结束下拉刷新 uni.stopPullDownRefresh(); }, 1000); }, onUnload() { console.log('页面即将卸载'); if (this.timer) { clearInterval(this.timer); this.timer = null; } } } </script> <style> page { background-color: #f5f5f5; } </style> <style scoped> .bg-image { position: absolute; } .custom-navbar { position: absolute; top: 0; left: 0; width: 100%; z-index: 1000; /* 自定义背景色 */ /* 自定义阴影 */ } .navbar-content { height: 44px; /* 标准导航栏高度 */ display: flex; align-items: center; padding: 0 15px; } .title { flex: 1; text-align: center; font-size: 17px; font-weight: bold; color: #333; /* 标题颜色 */ } .back-btn { width: 48rpx; height: 48rpx; } .right-area { width: 40px; text-align: right; } .info_wapper { height: 156px; /* background: #36A3F9; */ /* background: url(@/static/home/bus/detail-bg.png) left no-repeat; */ padding: 15px; color: black; position: absolute; z-index: 9; width: 100%; } .line_info { position: relative; /* display: flex; */ } .site { font-size: 32rpx; color: black; margin-bottom: 10px; text-align: left; display: flex; margin-left: 30px; } .from { /* padding-left: 52rpx; */ color: black; } .arrow { background: url(@/static/home/bus/single.png) left no-repeat; background-size: 14px 5px; margin-left: 10px; color: black; } .to { padding-left: 26px; color: black; } .time_s { background: url(@/static/home/bus/start.png) left no-repeat; background-size: 18px 18px; justify-self: baseline; } .time_e { background: url(@/static/home/bus/end.png) left no-repeat; background-size: 18px 18px; margin-left: 15px; } .price { margin-left: 15px; } .tit { color: #fff; font-size: 26rpx; /* padding-left: 52rpx; */ margin-bottom: 10px; height: 21px; color: #333; display: flex; align-items: baseline; margin-left: 30px; } .distance-class { border-radius: 15px; /* box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1); */ background: url(@/static/home/bus/distance-bg.png) center no-repeat; background-size: cover; height: 160px; position: absolute; z-index: 99; left: 20px; right: 20px; } .distance { color: #B7BABB; line-height: 20px; text-align: center; display: flex; flex-direction: column; align-items: center; position: relative; z-index: 99; /* align-items: baseline; */ } .time { color: aquamarine; } .bus-arr { color: rgb(255, 164, 17); font-weight: bold; margin-top: 10px; } .bus-coming { color: rgb(55, 170, 126); font-weight: bold; margin-top: 10px; } .station { margin-left: 20px; color: #353738; padding: 10px; } .station-title { display: flex; align-items: baseline; } .station-name { margin-right: 15px; } .station-content { padding-top: 10px; /* padding-left: 20rpx; */ position: relative; /* padding-right: 50rpx; */ /* 确保文字在下划线上方 */ z-index: 2; justify-content: center; display: flex; align-items: center; /* 文字在上层 */ } .underline { position: absolute; bottom: 2px; height: 3px; background: linear-gradient(to right, rgb(110, 207, 169), rgb(110, 224, 176)); /* 下划线颜色 */ border-radius: 3px; z-index: -1; width: 80%; align-items: center; justify-content: center; display: flex; /* margin-left: 30rpx; */ /* width: 60rpx; */ /* 下划线在文字下方 */ } .active { color: black; /* 激活状态文字颜色 */ font-weight: bold; /* font-size: 36rpx; */ } .time { float: left; width: 40%; font-size: 26rpx; /* height: 130rpx; */ line-height: 40px; } .time { font-size: 36rpx; color: #353738; } .time-text { margin-left: 25px; } .time_title { color: rgb(14, 170, 112); font-weight: bold; } .arr { float: left; /* width: 20%; */ font-size: 30rpx; color: rgb(14, 170, 112); } .site_list { /* margin: 15px; */ /* box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1); */ background-color: white; border-radius: 15px; margin-top: 150px; padding-left: 15px; padding-right: 15px; padding-top: 15px; padding-bottom: 10px; background: url(@/static/home/bus/site-bg.png) center no-repeat; position: absolute; z-index: 99; left: 20px; right: 20px; background-size: cover; /* 让背景图片覆盖整个视口 */ } .site_list .wapper_sitelist { width: 100%; overflow-x: scroll; position: relative; -webkit-overflow-scrolling: touch; display: flex; } .bus_road { background: url(@/static/home/bus/bus.png) no-repeat center; background-size: cover; width: 28px; height: 14px; position: absolute; z-index: 1; margin-top: 4px; left: 14px; /* margin-top: -40px; */ } .road-bus { background: url(@/static/home/bus/bus.png) no-repeat center; background-size: cover; width: 28px; height: 14px; position: absolute; z-index: 1; margin-top: -35px; margin-left: 10px; /* left: 14px; */ /* margin-top: -40px; */ } .road-bus-coming { background: url(@/static/home/bus/bus.png) no-repeat center; background-size: cover; width: 28px; height: 14px; position: absolute; z-index: 1; margin-top: -35px; margin-left: -40px; } .road { display: flex; } .wapper_sitelist::-webkit-scrollbar { display: none; } /deep/::-webkit-scrollbar { display: none; width: 0; height: 0; } .part { padding: 10px; display: flex; flex-direction: row; text-align: center; justify-content: center; padding-top: 30px; } .site_list .dot_r { margin-top: 25px; position: absolute; top: 23px; height: 3px; background: linear-gradient(to right, rgb(110, 207, 169), rgb(110, 224, 176)); /* 下划线颜色 */ width: 46px; border-radius: 3rpx; z-index: 1; margin-left: 4px; align-items: center; justify-content: center; display: flex; } .site_list .name { margin-top: 28px; display: flex; flex-direction: column; align-items: center; } .site_list .text { display: flex; text-align: center; margin-left: 5px; flex-direction: column; } .site_list .text_show { display: flex; text-align: center; margin-left: 5px; color: rgb(14, 170, 112); font-weight: bold; } .site_list .dot_show { background: url(@/static/home/bus/position_red.png) no-repeat center; background-size: 14px 18px; } .site_list .dot_d_show { border-radius: 50%; width: 16px; height: 16px; background-color: rgba(110, 207, 169, 0.5); position: absolute; z-index: 999; top: 41px; margin-left: 8px; display: flex; align-items: center; justify-content: center; } .road-class { display: flex; } .dot_p { border-radius: 50%; width: 8px; height: 8px; background-color: rgb(110, 207, 169); position: absolute; z-index: 999; top: 45px; display: flex; align-items: center; justify-content: center; /* margin-right: 2px; */ /* margin-left: 10rpx; */ } .dot_p_show { border-radius: 50%; width: 8px; height: 8px; background-color: rgb(14, 170, 112); position: absolute; z-index: 999; top: 45px; display: flex; align-items: center; justify-content: center; } .text-dir { margin-top: 5px; writing-mode: vertical-rl; letter-spacing: 3px; } .none { color: #848484; font-size: 16px; margin-top: 15px; } .my-map { /* width: 100%; */ position: absolute; z-index: 999; /* bottom: 20px; */ /* background-color: white; */ /* margin-bottom: 50px; */ left: 0; right: 0; top: 650px; margin: 20px; height: 370px; } .map { margin-top: 500px; margin-left: 20px; margin-right: 20px; margin-bottom: 10px; /* z-index: 9999; */ } </style> 将uniapp写法转化为h5
07-04
✓ 客服系统登录 请使用您的账号登录系统 ✓ 登录成功!正在跳转到控制面板... 用户名 admin 密码 •••••• 登录 快速链接 帮助中心 找回密码 用户注册 联系我们 客服系统 v2.5.1 © 2023 [root@yfw ~]# cd /www/wwwroot/szrengjing.com/kefu [root@yfw kefu]# ll total 80 drwxr-xr-x 2 www www 4096 Aug 6 20:14 cache -rwxr-xr-x 1 www www 5060 Aug 6 19:41 config.php drwxr-xr-x 4 root root 4096 Aug 6 14:46 includes -rwxr-xr-x 1 www www 48150 Aug 6 20:11 index.php drwxr-xr-x 3 root root 4096 Aug 6 14:24 js drwxr-xr-x 2 www www 4096 Aug 6 20:15 logs drwxr-xr-x 2 root root 4096 Aug 6 20:16 templates drwxr-xr-x 2 www www 4096 Aug 6 21:04 templates_c [root@yfw kefu]# <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>客服系统 - 登录页面</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; } body { background: linear-gradient(135deg, #1a2a6c, #b21f1f, #fdbb2d); min-height: 100vh; display: flex; justify-content: center; align-items: center; padding: 20px; } .container { width: 100%; max-width: 500px; background: rgba(255, 255, 255, 0.95); border-radius: 15px; box-shadow: 0 15px 30px rgba(0, 0, 0, 0.3); overflow: hidden; } .header { background: #2c3e50; color: white; padding: 25px 30px; text-align: center; position: relative; } .header h1 { font-size: 24px; margin-bottom: 10px; display: flex; align-items: center; justify-content: center; gap: 10px; } .header h1 i { font-size: 28px; } .content { padding: 30px; } .message-container { margin-bottom: 25px; padding: 15px; border-radius: 8px; display: flex; align-items: center; gap: 12px; font-size: 16px; } .info { background-color: #e3f2fd; color: #0d47a1; border-left: 4px solid #2196f3; } .success { background-color: #e8f5e9; color: #2e7d32; border-left: 4px solid #4caf50; } .error { background-color: #ffebee; color: #c62828; border-left: 4px solid #f44336; } .error-details { margin-top: 10px; padding: 10px; background: #fff; border-radius: 5px; border: 1px solid #ffcdd2; font-size: 14px; } .form-group { margin-bottom: 20px; } .form-group label { display: block; margin-bottom: 8px; font-weight: 500; color: #333; } .form-control { width: 100%; padding: 14px; border: 1px solid #ddd; border-radius: 8px; font-size: 16px; transition: border-color 0.3s; } .form-control:focus { outline: none; border-color: #3498db; box-shadow: 0 0 0 3px rgba(52, 152, 219, 0.2); } .btn { display: block; width: 100%; padding: 14px; background: linear-gradient(to right, #3498db, #2980b9); color: white; border: none; border-radius: 8px; font-size: 18px; font-weight: 600; cursor: pointer; transition: all 0.3s; } .btn:hover { background: linear-gradient(to right, #2980b9, #2573a7); transform: translateY(-2px); box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1); } .links-container { margin-top: 25px; padding-top: 20px; border-top: 1px solid #eee; } .links-container h3 { margin-bottom: 15px; color: #2c3e50; text-align: center; } .link-list { display: flex; flex-wrap: wrap; gap: 15px; justify-content: center; } .link-item { display: inline-block; padding: 10px 20px; background: #f8f9fa; border-radius: 30px; color: #3498db; text-decoration: none; font-weight: 500; transition: all 0.3s; border: 1px solid #e9ecef; } .link-item:hover { background: #3498db; color: white; transform: translateY(-3px); box-shadow: 0 5px 15px rgba(52, 152, 219, 0.3); } .footer { text-align: center; padding: 20px; background: #f8f9fa; color: #6c757d; font-size: 14px; border-top: 1px solid #e9ecef; } @media (max-width: 576px) { .content { padding: 20px 15px; } .header { padding: 20px; } .link-list { flex-direction: column; align-items: center; } } </style> </head> <body> <div class="container"> <div class="header"> <h1><i class="icon">✓</i> 客服系统登录</h1> <p>请使用您的账号登录系统</p> </div> <div class="content"> <!-- 消息提示区域 - 修复了Smarty语法错误 --> <div class="message-container success"> <span class="icon">✓</span> <div class="message"> 登录成功!正在跳转到控制面板... </div> </div> <!-- 登录表单区域 - 修复了Smarty语法错误 --> <form id="loginForm"> <div class="form-group"> <label for="username">用户名</label> <input type="text" id="username" class="form-control" placeholder="请输入用户名" value="admin"> </div> <div class="form-group"> <label for="password">密码</label> <input type="password" id="password" class="form-control" placeholder="请输入密码" value="••••••"> </div> <button type="submit" class="btn">登录</button> </form> <!-- 链接区域 - 修复了Smarty语法错误 --> <div class="links-container"> <h3>快速链接</h3> <div class="link-list"> <a href="#" class="link-item">帮助中心</a> <a href="#" class="link-item">找回密码</a> <a href="#" class="link-item">用户注册</a> <a href="#" class="link-item">联系我们</a> </div> </div> </div> <div class="footer"> 客服系统 v2.5.1 © 2023 </div> </div> <script> // 模拟Smarty模板功能 document.getElementById('loginForm').addEventListener('submit', function(e) { e.preventDefault(); const username = document.getElementById('username').value; const password = document.getElementById('password').value; // 模拟不同消息类型 const messageContainer = document.querySelector('.message-container'); const messageIcon = messageContainer.querySelector('.icon'); const messageText = messageContainer.querySelector('.message'); if(username === 'admin' && password === 'password123') { messageContainer.className = 'message-container success'; messageIcon.textContent = '✓'; messageText.textContent = '登录成功!正在跳转到控制面板...'; } else { messageContainer.className = 'message-container error'; messageIcon.textContent = '✗'; messageText.innerHTML = '登录失败!用户名或密码错误<br><div class="error-details">错误详情:用户不存在或密码不匹配</div>'; } }); </script> </body> </html> 根据信息 请生成对应源文件完整版 全面兼容PHP5.3.29
最新发布
08-07
<template> <div class="login-container"> <div class="login-form"> <h2>用户登录</h2> <input v-model="username" placeholder="用户名"> <input v-model="password" type="password" placeholder="密码"> <button @click="handleLogin">登录</button> <!-- <router-link to="/register">注册账号</router-link> --> </div> </div> </template> <script setup> import { ref } from 'vue' import { useRouter } from 'vue-router' import axios from 'axios' import { ElMessage } from 'element-plus' const router = useRouter() const username = ref('') const password = ref('') const handleLogin = async () => { try { // 发送POST请求到登录接口 const response = await axios.post('http://172.26.26.43/dev-api/login', { username: username.value, password: password.value }) const { code, message, token } = response.data // 根据状态码判断登录是否成功 if (code === 200) { // 存储token到localStorage localStorage.setItem('token', token) ElMessage.success({ message:'登录成功!', customClass:'mobile-message', duration: 1000 }) setTimeout(() => { // 登录成功后跳转到详情页 router.push({ name: 'Detail' , params: { id: 123 } }) }, 1000) } else { alert(`登录失败: ${message}`) } } catch (error) { // 处理请求错误 console.error('登录请求出错:', error) alert('登录请求失败,请检查网络或联系管理员') } } </script> <style scoped> /* 添加移动端适配的样式 */ .login-container { display: flex; justify-content: center; align-items: center; min-height: 100vh; /* 使容器至少和视口一样高 */ background-color: #f5f5f5; /* 背景色 */ padding: 16px; /* 内边距 */ } .login-form { width: 100%; max-width: 400px; /* 最大宽度,避免在大屏幕上过宽 */ padding: 20px; background: #fff; border-radius: 8px; box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); } .login-form h2 { text-align: center; margin-bottom: 20px; color: #333; } .login-form input { width: 100%; padding: 12px; margin-bottom: 12px; border: 1px solid #ddd; border-radius: 4px; font-size: 16px; box-sizing: border-box; /* 确保宽度包含内边距和边框 */ } .login-form button { width: 100%; padding: 12px; background-color: #007bff; color: white; border: none; border-radius: 4px; font-size: 16px; cursor: pointer; } /* 按钮的点击区域已经足够大(高度44px左右) */ .login-form button:active { background-color: #0056b3; } .login-form a { display: block; text-align: center; margin-top: 12px; color: #007bff; text-decoration: none; } </style> 我什么我这个项目的登录界面可以正常登录,但是修改后:<template> <view class="login-container"> <view class="login-form"> <text class="login-title">用户登录</text> <input v-model="username" placeholder="用户名" class="login-input" placeholder-class="input-placeholder" /> <input v-model="password" type="password" placeholder="密码" class="login-input" placeholder-class="input-placeholder" /> <button class="login-button" :loading="loading" @click="handleLogin" >登录</button> </view> </view> </template> <script> import { ref } from 'vue' export default { setup() { const username = ref('') const password = ref('') const loading = ref(false) const handleLogin = async () => { // 验证输入 if (!username.value.trim()) { uni.showToast({ title: '请输入用户名', icon: 'none', duration: 2000 }) return } if (!password.value) { uni.showToast({ title: '请输入密码', icon: 'none', duration: 2000 }) return } loading.value = true try { // 正确使用 uni.request 并处理返回值 const [error, response] = await uni.request({ url: 'http://172.26.26.43/dev-api/login', method: 'POST', data: { username: username.value, password: password.value }, header: { 'Content-Type': 'application/json' }, timeout: 10000 // 10秒超时 }) // 处理请求错误 if (error) { throw new Error(`请求失败: ${error.errMsg}`) } // 检查响应状态 if (response.statusCode !== 200) { throw new Error(`服务器错误: ${response.statusCode}`) } // 解析响应数据 const { data } = response const { code, message, token } = data if (code === 200) { // 存储token uni.setStorageSync('token', token) uni.showToast({ title: '登录成功!', icon: 'success', duration: 1000 }) // 登录成功后跳转 setTimeout(() => { uni.redirectTo({ url: '/pages/index/index' }) }, 1000) } else { throw new Error(`登录失败: ${message || '未知错误'}`) } } catch (error) { console.error('登录请求出错:', error) uni.showToast({ title: error.message || '登录失败,请重试', icon: 'none', duration: 2000 }) } finally { loading.value = false } } return { username, password, loading, handleLogin } } } </script> <style scoped> /* 保持之前的样式不变 */ .login-container { display: flex; justify-content: center; align-items: center; min-height: 100vh; padding: 32rpx; background-color: #f5f5f5; } .login-form { width: 100%; max-width: 600rpx; padding: 60rpx; background: #fff; border-radius: 16rpx; box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.1); } .login-title { display: block; text-align: center; margin-bottom: 60rpx; font-size: 40rpx; font-weight: bold; color: #333; } .login-input { width: 100%; height: 88rpx; padding: 0 24rpx; margin-bottom: 40rpx; border: 2rpx solid #ddd; border-radius: 12rpx; font-size: 32rpx; box-sizing: border-box; } .input-placeholder { color: #999; font-size: 32rpx; } .login-button { width: 100%; height: 88rpx; line-height: 88rpx; background-color: #007aff; color: white; font-size: 32rpx; border-radius: 12rpx; margin-top: 20rpx; } .login-button:active { background-color: #0062cc; opacity: 0.9; } </style> 用到uniapp里就登录不了
07-18
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值