Forráskód Böngészése

新增订单管理页面

韦祥的电脑\Administrator 10 hónapja
szülő
commit
7321ba0f17

+ 115 - 0
components/TopTabs/topTabs.vue

@@ -0,0 +1,115 @@
+<template>
+	<view class="tb">
+		<!-- <view class="searchBoxParent" v-if="showSearch">
+			<view class="searchBox">
+				<u-search :placeholder="placeholder" :clearabled="true" shape="round" @search="sousuo"
+				 height="70" bgColor="#fff" :showAction="false" borderColor="#0DBFFD" searchIconSize="26px"
+				 v-model="mysearch"></u-search>
+			</view>
+		</view> -->
+		<view class="tabs">
+			<view v-for="(item,index) in list" :key="index" @tap="changeTab(index)">
+				<text :class="index==current?'active':''">{{item.name}}</text>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		name: 'topTabs',
+		props: {
+			list: {
+				typeof: Array,
+				default: []
+			},
+			top: {
+				typeof: Number,
+				default: 0
+			},
+			placeholder: {
+				typeof: String,
+				default: ""
+			},
+			showSearch: {
+				typeof: Boolean,
+				default: true
+			}
+		},
+		data() {
+			return {
+				current: 0,
+				mysearch: ''
+			}
+		},
+		methods: {
+			sousuo() {
+				this.$emit('sousuo', this.mysearch);
+			},
+			changeTab(index) {
+				this.current = index;
+				this.$emit('changeTab', index);
+			}
+		}
+	}
+</script>
+
+<style lang="less">
+	.tb {
+		width: 100%;
+
+		top: 0;
+		left: 0;
+		z-index: 999;
+
+		.searchBoxParent {
+			width: 100%;
+			background: #fff;
+			padding: 20rpx 24rpx 6rpx;
+			box-sizing: border-box;
+
+			.searchBox {
+				width: 100%;
+				background-color: #fff;
+			}
+		}
+
+		.tabs {
+			background: #fff;
+			padding: 26rpx 0;
+			display: flex;
+			align-items: center;
+			width: 100%;
+
+			&>view {
+				width: 25%;
+				font-size: 28rpx;
+				font-family: PingFangSC-Regular, PingFang SC;
+				font-weight: 400;
+				color: black;
+				line-height: 40rpx;
+				position: relative;
+				text-align: center;
+			}
+
+			.active {
+				font-size: 32rpx;
+				font-family: PingFang-SC-Bold, PingFang-SC;
+				font-weight: bold;
+				color: black;
+				line-height: 45rpx;
+			}
+
+			.active::after {
+				position: absolute;
+				content: '';
+				width: 50rpx;
+				height: 8rpx;
+				background: #1372FF;
+				bottom: -26rpx;
+				left: 60%;
+				margin-left: -42rpx;
+			}
+		}
+	}
+</style>

+ 33 - 5
pages.json

@@ -1,6 +1,5 @@
 {
-	"pages": [
-		{
+	"pages": [{
 			"path": "pages/login/index",
 			"style": {
 				"navigationBarTitleText": "登录",
@@ -43,14 +42,43 @@
 			}
 		}
 	],
-	"subPackages": [
-		{
+	"subPackages": [{
 			"root": "pagesHouse",
 			"pages": []
 		},
 		{
 			"root": "pagesMy",
-			"pages": []
+			"pages": [{
+					"path": "orderList/orderList",
+					"style": {
+						"navigationBarTitleText": "订单列表",
+						"enablePullDownRefresh": false,
+						"navigationBarBackgroundColor": "#fff"
+					}
+				}, {
+					"path": "orderList/alreadyBook",
+					"style": {
+						"navigationBarTitleText": "订单详情",
+						"enablePullDownRefresh": false,
+						"navigationBarBackgroundColor": "#fff"
+					}
+				}, {
+					"path": "orderList/textMessage",
+					"style": {
+						"navigationBarTitleText": "发送短信",
+						"enablePullDownRefresh": false,
+						"navigationBarBackgroundColor": "#fff"
+					}
+				},
+				{
+					"path": "stayInfo/stayInfo",
+					"style": {
+						"navigationBarTitleText": "酒店民宿信息 ",
+						"enablePullDownRefresh": false
+					}
+				}
+
+			]
 		}
 	],
 	"globalStyle": {

+ 63 - 40
pages/my/index.vue

@@ -11,7 +11,7 @@
 		<view class="orders box">
 			<view class="o_top">
 				<text>订单管理</text>
-				<view>
+				<view @click="navigatorAllOrder()">
 					<text>全部</text>
 					<u-icon name="arrow-right" color="#999999" size="28"></u-icon>
 				</view>
@@ -23,7 +23,7 @@
 				</view>
 			</view>
 		</view>
-		<view class="menu box">
+		<view class="menu box" @click="stayInfo()">
 			<text>酒店民宿信息</text>
 			<u-icon name="arrow-right" color="#999999" size="28"></u-icon>
 		</view>
@@ -48,61 +48,74 @@
 					fontWeight: "bold",
 					color: '#FFFFFF'
 				},
-				avatar:'https://i.ringzle.com/file/20240107/d61321708599457bbcca1c089154e635.png',
-				name:'吴彦霖',
-				menus:[
-					{
-						img:'https://i.ringzle.com/file/20240107/83bca90dfb3f4b1fba36115dc7269219.png',
-						title:'待确认',
-						path:''
+				avatar: 'https://i.ringzle.com/file/20240107/d61321708599457bbcca1c089154e635.png',
+				name: '吴彦霖',
+				menus: [{
+						img: 'https://i.ringzle.com/file/20240107/83bca90dfb3f4b1fba36115dc7269219.png',
+						title: '待确认',
+						path: ''
 					},
 					{
-						img:'https://i.ringzle.com/file/20240107/7e7825255bbc4d06ae5d75e7bb23db71.png',
-						title:'未支付',
-						path:''
+						img: 'https://i.ringzle.com/file/20240107/7e7825255bbc4d06ae5d75e7bb23db71.png',
+						title: '未支付',
+						path: ''
 					},
 					{
-						img:'https://i.ringzle.com/file/20240107/c368a627821244929ab6477acb46fb15.png',
-						title:'已预订',
-						path:''
+						img: 'https://i.ringzle.com/file/20240107/c368a627821244929ab6477acb46fb15.png',
+						title: '已预订',
+						path: ''
 					},
 					{
-						img:'https://i.ringzle.com/file/20240107/656b5cc9e9514a08a3f2abd86d86b4ca.png',
-						title:'已取消',
-						path:''
+						img: 'https://i.ringzle.com/file/20240107/656b5cc9e9514a08a3f2abd86d86b4ca.png',
+						title: '已取消',
+						path: ''
 					}
 				]
 			}
 		},
+		
 		methods: {
-			
+			navigatorAllOrder() {
+				uni.navigateTo({
+					url: '/pagesMy/orderList/orderList'
+				})
+			},
+			stayInfo() {
+				uni.navigateTo({
+					url: '/pagesMy/stayInfo/stayInfo'
+				})
+			}
 		}
 	}
 </script>
 
 <style scoped lang="less">
-	.page{
+	.page {
 		background: #F3F4F4;
 		padding-bottom: 40rpx;
 		box-sizing: border-box;
 		overflow-y: auto;
-		.bg{
+
+		.bg {
 			width: 100%;
 			height: 360rpx;
 			padding: 0 60rpx;
 			background: url(https://i.ringzle.com/file/20240107/fc66824bcef14a3b9e19f8b966a128c7.png) no-repeat;
-			background-size: 100%  100%;
+			background-size: 100% 100%;
 			box-sizing: border-box;
 			position: relative;
 			z-index: 1;
-			.account{
+
+			.account {
 				display: flex;
 				align-items: center;
-				image{
+
+				image {
 					width: 96rpx;
 					height: 96rpx;
 				}
-				text{
+
+				text {
 					font-size: 40rpx;
 					font-family: PingFang SC, PingFang SC;
 					font-weight: 800;
@@ -111,8 +124,8 @@
 				}
 			}
 		}
-	
-		.box{
+
+		.box {
 			width: calc(100% - 60rpx);
 			margin: 0 30rpx;
 			padding: 30rpx;
@@ -120,24 +133,29 @@
 			background: #FFFFFF;
 			border-radius: 10rpx 10rpx 10rpx 10rpx;
 		}
-		.orders{
-			margin-top: -60rpx;
+
+		.orders {
+			margin-top: -25rpx;
 			position: relative;
 			z-index: 2;
-			.o_top{
+
+			.o_top {
 				display: flex;
 				align-items: center;
 				justify-content: space-between;
-				&>text{
+
+				&>text {
 					font-size: 32rpx;
 					font-family: PingFang SC, PingFang SC;
 					font-weight: 800;
 					color: #333333;
 				}
-				&>view{
+
+				&>view {
 					display: flex;
 					align-items: center;
-					&>text{
+
+					&>text {
 						font-size: 24rpx;
 						font-family: PingFang SC, PingFang SC;
 						font-weight: 400;
@@ -146,7 +164,8 @@
 					}
 				}
 			}
-			.o_menus{
+
+			.o_menus {
 				margin-top: 30rpx;
 				padding-top: 30rpx;
 				border-top: 1rpx solid #F1F1F1;
@@ -154,16 +173,19 @@
 				align-items: center;
 				justify-content: space-around;
 				flex-wrap: wrap;
-				&>view{
+
+				&>view {
 					width: 25%;
 					display: flex;
 					flex-direction: column;
 					align-items: center;
-					image{
+
+					image {
 						width: 64rpx;
 						height: 64rpx;
 					}
-					text{
+
+					text {
 						font-size: 24rpx;
 						font-family: PingFang SC, PingFang SC;
 						font-weight: 400;
@@ -173,13 +195,14 @@
 				}
 			}
 		}
-		
-		.menu{
+
+		.menu {
 			margin-top: 30rpx;
 			display: flex;
 			align-items: center;
 			justify-content: space-between;
-			text{
+
+			text {
 				font-size: 30rpx;
 				font-family: PingFang SC, PingFang SC;
 				font-weight: 400;

+ 171 - 0
pagesMy/orderList/alreadyBook.vue

@@ -0,0 +1,171 @@
+<template>
+	<view class="pages">
+		<view class="customer">
+			<view class="">
+				<span style="margin-right: 20rpx;"> 吴易航</span>
+				<span>18160883036</span>
+			</view>
+			<view class="" @click="textMessage()"><u-icon name="chat" size="34"></u-icon></view>
+		</view>
+		<view class="roomInfo">
+			<view class="info1">
+				<span>海景房-305</span>
+				<text :class="statusClass[0]">{{status[0]}}</text>
+
+			</view>
+			<view class="info2">
+				<span>2023-12-16入住 1晚</span>
+				<text style="color: #245BED;">¥200.00</text>
+
+			</view>
+			<view class="info3">
+				<span>入住人</span>
+				<text>0人 ></text>
+			</view>
+		</view>
+		<view class="orderInfo">
+			<view class="orderInfo1">
+				订单号<span class='left'>A20231213102359619119</span>
+			</view>
+			<view class="orderInfo1">
+				创建时间 <span class='left'>2023-12-11 17:27:09</span>
+			</view>
+			<view class="orderInfo1">
+				办理员工 <span class='left'>何炜亭</span>
+			</view>
+			<view class="orderInfo1">
+				取消原因<span class='left'>-</span>
+			</view>
+			<view class="orderInfo2">
+				备注 <span class='left'>-</span>
+			</view>
+		</view>
+
+	</view>
+</template>
+
+<script>
+	export default {
+
+		data() {
+			return {
+				loading: true,
+				statusClass: [
+					'green',
+					'blue',
+					'grey',
+					'orange'
+				],
+				status: [
+					'已预订',
+					'已入住',
+					'已取消',
+					'待确认'
+				],
+			}
+		},
+		methods: {
+			textMessage() {
+				uni.navigateTo({
+					url: '/pagesMy/orderList/textMessage'
+				})
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.pages {
+		background: #F9FAFC;
+		height: 100vh;
+		padding: 20rpx;
+		font-size: 28rpx;
+
+
+		.customer {
+			background: #fff;
+			padding: 20rpx;
+			border-radius: 16rpx;
+			margin-bottom: 20rpx;
+			font-weight: 700;
+			display: flex;
+			justify-content: space-between;
+		}
+
+		.roomInfo {
+			background: #fff;
+			padding: 20rpx;
+			border-radius: 16rpx;
+			margin-bottom: 20rpx;
+
+			.info1 {
+				display: flex;
+				justify-content: space-between;
+				margin-bottom: 20rpx;
+
+				.green {
+					color: #39CE77;
+				}
+
+				.blue {
+					color: #1372FF;
+				}
+
+				.grey {
+					color: #4C5F76;
+				}
+
+				.orange {
+					color: #FF9100;
+				}
+			}
+
+			.info2 {
+				margin-bottom: 20rpx;
+				display: flex;
+				justify-content: space-between;
+
+				color: #777777;
+			}
+
+			.info3 {
+				display: flex;
+				justify-content: space-between;
+				color: #777777;
+			}
+		}
+
+		.orderInfo {
+			border-radius: 16rpx;
+			background: #fff;
+			color: #777777;
+			padding: 0 20rpx;
+
+			.orderInfo1 {
+				border-bottom: 1px #f3f3f3 solid;
+				padding: 20rpx 0;
+				display: flex;
+				flex-direction: row;
+				justify-content: space-between;
+
+				.left {
+					width: 80%;
+					text-align: left;
+				}
+			}
+
+			.orderInfo2 {
+
+				padding: 20rpx 0;
+				display: flex;
+				flex-direction: row;
+				justify-content: space-between;
+
+				.left {
+					width: 80%;
+					text-align: left;
+				}
+			}
+		}
+	}
+</style>

+ 216 - 0
pagesMy/orderList/orderList.vue

@@ -0,0 +1,216 @@
+<template>
+	<view class="pages">
+		<TopTabs :list="tabList" @changeTab="changeTab" :placeholder="'输入景点名称/订单号'">
+		</TopTabs>
+		<view class="mainContain">
+			<view class="card" >
+				<view class="header">
+					<span style="font-weight: 700;">订单号:A20231213102359619119</span>
+
+					<text :class="statusClass[0]">{{status[0]}}</text>
+				</view>
+				<view class="mainContent">
+					<view class="image">
+
+					</view>
+					<view class="middle">
+						<span class="title">海景房-306</span>
+						<span class='info'>
+							<span>郑一璇</span>
+							<span>15753988251</span>
+							<span>03/11 - 03/12 (共两晚)</span>
+						</span>
+					</view>
+					<view class="price">
+						¥1288.0
+					</view>
+				</view>
+				<view class="bottom" @click="handleDetail()">
+					<view class="btn">
+						办理入住
+					</view>
+				</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	import TopTabs from '../../components/TopTabs/topTabs.vue';
+	export default {
+		components: {
+			TopTabs,
+
+		},
+		data() {
+			return {
+				statusClass: [
+					'green',
+					'blue',
+					'grey',
+					'orange'
+				],
+				status: [
+					'已预订',
+					'已入住',
+					'已取消',
+					'待确认'
+				],
+				// mt: uni.getSystemInfoSync().statusBarHeight + 44,
+				tabList: [{
+						name: '全部'
+					},
+					{
+						name: '待确认'
+					},
+					{
+						name: '待支付'
+					},
+					{
+						name: '已预订'
+					},
+					{
+						name: '已取消'
+					},
+				],
+			}
+		},
+		methods: {
+			handleDetail() {
+				uni.navigateTo({
+					url: '/pagesMy/orderList/alreadyBook'
+				})
+			},
+			changeTab(index) {
+				this.tabIdx = index;
+				// switch (index) {
+				// 	case 0:
+				// 		this.gtiList()
+				// 		break
+				// 	case 1:
+				// 		this.getiList(0)
+				// 		break
+				// 	case 2:
+				// 		this.getiList(1)
+				// 		break
+				// 	case 3:
+				// 		this.getiList(-3)
+				// }
+			},
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.pages {
+		background: #F9FAFC;
+		height: 100vh;
+
+		.green {}
+
+		.mainContain {
+			display: flex;
+			flex-direction: column;
+			padding: 0 20rpx;
+
+			.card {
+				background: #fff;
+				border-radius: 16rpx;
+				margin: 20rpx 0;
+				padding: 20rpx;
+
+				.header {
+					display: flex;
+					justify-content: space-between;
+					border-bottom: 1px #f3f3f3 solid;
+					padding: 20rpx;
+
+					.green {
+						color: #39CE77;
+					}
+
+					.blue {
+						color: #1372FF;
+					}
+
+					.grey {
+						color: #4C5F76;
+					}
+
+					.orange {
+						color: #FF9100;
+					}
+				}
+
+				.mainContent {
+					border-bottom: 1px #f3f3f3 solid;
+					display: flex;
+					padding: 20rpx 0;
+
+
+					justify-content: space-evenly;
+
+					.image {
+						background: url('https://i.ringzle.com/file/20231024/a68c2b2909d84930bbec1e5c7adbb0b4.jpg');
+						background-repeat: no-repeat;
+						background-size: cover;
+						width: 180rpx;
+						height: 180rpx;
+						border-radius: 16rpx;
+					}
+
+					.middle {
+						color: #777777;
+						display: flex;
+						flex-direction: column;
+						justify-content: space-between;
+
+
+						.title {
+							font-weight: 700;
+							font-size: 32rpx;
+							color: black;
+						}
+
+						.info {
+							color: #777777;
+							display: flex;
+							flex-direction: column;
+
+							&>span {
+								margin-top: 10rpx;
+
+							}
+						}
+					}
+
+					.price {
+						color: red;
+						text-align: center;
+						height: 100%;
+						align-items: center;
+						align-self: center;
+						font-size: 29rpx;
+						font-weight: 700;
+					}
+
+				}
+
+				.bottom {
+					padding: 30rpx 20rpx;
+					display: flex;
+					justify-content: flex-end;
+
+					.btn {
+						background: #1372FF;
+						border-radius: 35rpx;
+						color: white;
+						padding: 13rpx 34rpx;
+
+					}
+				}
+
+			}
+		}
+	}
+</style>

+ 145 - 0
pagesMy/orderList/textMessage.vue

@@ -0,0 +1,145 @@
+<template>
+	<view class="pages">
+		<view class="phoneNum">
+			接收手机号 <span style="color: #245BED;margin-left: 20rpx; font-weight: 700;">18160883036</span>
+		</view>
+		<view class="cotent">
+			<view class="card">
+				<view class="card1">
+					<span>短信模板</span>
+					<span style="color:#777777;" @click="()=>{
+						selectShow=true
+					}">请选择(非必选) ></span>
+				</view>
+			</view>
+			<view class="card">
+				<span style="margin: 20rpx 0;">
+					短信内容
+				</span>
+				<span style="margin-top: 20rpx;">
+					<u--textarea :maxlength='300' count v-model="value" placeholder="请输入短信内容"
+						height='250'></u--textarea>
+				</span>
+
+			</view>
+		</view>
+		<view class="bottom">
+			<u-radio-group size='34'>
+				<u-radio value='readed' size='34' shape="circle" label="已阅读并同意<短信内容规则>和<短信协议>"></u-radio>
+			</u-radio-group>
+			<view class="btn">
+				发送
+			</view>
+		</view>
+		<u-popup :show="selectShow" @close="close" @open="open">
+			<view class="selectShow">
+				<view class="selectShow1">
+					<text>下单提醒</text>
+				</view>
+				<view class="selectShow1">
+					<text>支付提醒</text>
+				</view>
+				<view class="selectShow1">
+					<text>退房提醒</text>
+				</view>
+				<view class="cancel selectShow1" @click="()=>{this.selectShow = false}">
+					<text>取消</text>
+				</view>
+			</view>
+
+		</u-popup>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				value: '',
+				readed: '',
+				selectShow: ''
+			}
+		},
+		methods: {
+			close() {
+				this.selectShow = false
+			},
+			open() {
+
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.pages {
+		height: 100vh;
+		background: #F9FAFC;
+
+		.selectShow1 {
+			text-align: center;
+			height: 100rpx;
+			line-height: 100rpx;
+			font-weight: 700;
+			font-size: 28rpx;
+			background: #fff;
+		}
+
+		.selectShow {
+			background: #fbfbfb;
+		}
+
+		.cancel {
+			margin-top: 20rpx;
+
+		}
+
+		.phoneNum {
+			padding: 20rpx;
+		}
+
+		.cotent {
+			padding: 20rpx;
+
+			.card {
+				background: #fff;
+				border-radius: 16rpx;
+				padding: 30rpx 20rpx;
+
+				margin-bottom: 20rpx;
+
+				.card1 {
+					display: flex;
+					flex-direction: row;
+					justify-content: space-between;
+				}
+			}
+		}
+
+		.bottom {
+			position: absolute;
+			bottom: 0;
+			height: 9%;
+			background: #fff;
+			width: 100%;
+			display: flex;
+			justify-content: center;
+			align-items: center;
+			padding: 0 30rpx;
+			box-sizing: border-box;
+			flex-direction: column;
+
+			.btn {
+				background: #33AFFC;
+				color: white;
+				text-align: center;
+				height: 73rpx;
+				line-height: 73rpx;
+				align-self: center;
+				border-radius: 35rpx;
+				width: 80%;
+
+			}
+		}
+	}
+</style>

+ 129 - 0
pagesMy/stayInfo/stayInfo.vue

@@ -0,0 +1,129 @@
+<template>
+	<view class="pages">
+		<view class="content">
+			<view class="card">
+				<view class="card1">
+					<text>位置定位</text>
+					<text>></text>
+				</view>
+			</view>
+			<view class="card">
+				<view class="card1">
+					<text>联系电话</text>
+					<text>
+						<u--input placeholder="请输入内容" border="surround" v-model="value" @change="change"></u--input>
+					</text>
+				</view>
+			</view>
+			<view class="card">
+				<view class="card1">
+					<text>酒店简介</text>
+					<span style="margin-top: 20rpx;">
+						<u--textarea :maxlength='300' count v-model="value1" placeholder="请输入酒店简介"
+							height='250'></u--textarea>
+					</span>
+				</view>
+			</view>
+			<view class="card">
+				<view class="card1">
+					<u-collapse @change="change" @close="close" @open="open">
+						<u-collapse-item title="内饰照片" name="Docs guide">
+							<text class="u-collapse-content">涵盖uniapp各个方面,给开发者方向指导和设计理念,让您茅塞顿开,一马平川</text>
+						</u-collapse-item>
+					</u-collapse>
+
+				</view>
+			</view>
+			<view class="card">
+				<view class="card1">
+					<u-collapse @change="change" @close="close" @open="open">
+						<u-collapse-item title="环境照片" name="Docs guide">
+							<text class="u-collapse-content">涵盖uniapp各个方面,给开发者方向指导和设计理念,让您茅塞顿开,一马平川</text>
+						</u-collapse-item>
+					</u-collapse>
+
+				</view>
+			</view>
+		</view>
+
+		<view class="bottom">
+
+			<view class="btn">
+				确定
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				value: '',
+				value1: ''
+			}
+		},
+		methods: {
+			change() {
+
+			},
+			close() {
+
+			},
+			open() {
+
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.pages {
+		height: 100vh;
+		background: #F9FAFC;
+
+		.content {
+			padding: 20rpx;
+
+			.card {
+				background: #fff;
+				border-radius: 16rpx;
+				padding: 30rpx 20rpx;
+
+				margin-bottom: 20rpx;
+
+				.card1 {
+					display: flex;
+					flex-direction: row;
+					justify-content: space-between;
+				}
+			}
+		}
+
+		.bottom {
+			position: absolute;
+			bottom: 0;
+			height: 9%;
+			background: #fff;
+			width: 100%;
+			display: flex;
+			justify-content: center;
+			align-items: center;
+			padding: 0 30rpx;
+			box-sizing: border-box;
+			flex-direction: column;
+
+			.btn {
+				background: #33AFFC;
+				color: white;
+				text-align: center;
+				height: 73rpx;
+				line-height: 73rpx;
+				align-self: center;
+				border-radius: 35rpx;
+				width: 80%;
+
+			}
+		}
+	}
+</style>

+ 0 - 0
pagesMy/除tabbar页面外其余我的相关页面存放此分包内.txt