浏览代码

feat: mobile fix

jiangzixin 1 年之前
父节点
当前提交
02a41f2b7a

二进制
uniapp/components/.DS_Store


+ 75 - 0
uniapp/components/cus-selects-fan/README.md

@@ -0,0 +1,75 @@
+# cus-selects-fan
+
+## 属性说明
+
+|属性名|类型|默认值|说明|
+| -- | -- | --|--|
+| value | String | '' | 选择的内容 |
+| data | Array | [] | 下拉选择的数据 |
+| valueType | Object |  {label:'label',value:'value'}  | 下拉选择数据的别名 |
+| clearable | Boolean | false| 是否可以清空选项 |
+| filterable | Boolean | false | 是否可搜索 |
+| searchType | Number | 1 | 搜索类型,1:模糊搜素2:精确搜索 |
+| placeholder | String | '请选择' | 占位符 |
+| showTitle | Boolean | true | 是否显示标题占位图 |
+| noDataText | String | ‘暂无数据’ | 选项为空时显示的文字 |
+| arrLeft | Number|  20 | 选项区域的箭头巨左的间距 |
+| size | Number | 240 | 选择框的宽 |
+
+|事件|
+| @change 选中的值 |
+
+## 使用示例
+
+```html
+	//基础用法
+	<cus-selects v-model="value"></cus-selects>
+	
+	//可清空
+	<cus-selects v-model="value" :clearable='true'></cus-selects>
+	// 模糊搜索
+	<cus-selects v-model="value" :clearable='true' :filterable='true' :searchType='1'></cus-selects>
+	// 精确搜索
+	<cus-selects v-model="value" @change='change' :clearable='true' :filterable='true' :searchType='2'></cus-selects>
+	
+	//传入的数据以及别名
+	<cus-selects :data="selectList" v-model="value" @change='change' :clearable='true' :valueType="alias"></cus-selects>
+	
+```
+
+```javascript
+import cusSelects from '@/components/cus-selects-fan/cus-selects-fan.vue'
+export default {
+  components: {
+    cusSelects
+  },
+  data() {
+    return {
+      value:'',
+	  selectList:[ //根据自己需求获得的下拉数据,如果数据不是{label:'',value:''}结构的就需要起一个别名来代指一下,就需要valueType
+	  	{
+	  		id:1,
+	  		title:'hahah',
+	  	},
+	  	{
+	  		id:2,
+	  		title:'hahah1',
+	  	},
+	  	{
+	  		id:3,
+	  		title:'hahah3',
+	  	}
+	  ],
+	  alias:{ //别名来代指一下
+	  	label:'title',
+	  	value:'id'
+	  },
+    }
+  },
+  methods: {
+    change(e) {
+      console.log(e) //这里返回的是value值
+    },
+  },
+}
+```

+ 400 - 0
uniapp/components/cus-selects-fan/cus-selects-fan.vue

@@ -0,0 +1,400 @@
+<template>
+	<view class="select_wrap" :style="{'width': size +'px'}">
+		<view :class="['select_input',isClick?'select_input_select':'']" ref="select-input">
+			<view class="input_info" @click.stop="openSelect" v-if="!readonly">
+				<input placeholder-style="font-size: 14px;color: #a0a9b0;" :focus="isClick" @input="selectData" :value="selLabel" type="text" :readonly="readonly" :disabled="readonly" autocomplete="off" :placeholder="placeholder" class="text_tips">
+			</view>
+			<view class="input_info" @click.stop="openSelect" v-else>
+				<view :placeholder="placeholder" class="text_tips">{{selLabel}} <text v-if="!selLabel">{{placeholder}}</text> </view>
+			</view>
+			<view class="icon_arrow" @click="clearItem">
+				<view v-if="(!value&&!clearable) || (value&&!clearable) || (!value&&clearable) && !filterable" :class="['arrow',show?'arrow_down':'arrow_up']" ></view>
+				<view class="arrow-clear" v-if="value&&clearable">x</view>
+			</view>
+		</view>
+		<view class="select_modal_con" v-if="show"
+			@touchmove.stop.prevent="() => {}">
+			<!-- #ifdef APP-ANDROID -->
+			<scroll-view scroll-y="true" class="select_modal select_modal_scroll">
+				<view class="select_content" ref="select_content">
+					<view v-for="(item, index) in showData" :key="index" class="select_content_li" :class="{'selected': value == item[valueType.value]}" @click="change(item)">{{item[valueType.label]}}</view>
+					<view class="select_content_li" v-if="!showData.length">{{noDataText}}</view>
+				</view>
+			</scroll-view>
+			<!--  #endif -->
+			<!-- #ifndef APP-ANDROID -->
+				<view class="select_modal">
+					<view class="select_content" ref="select_content">
+						<view v-for="(item, index) in showData" :key="index" class="select_content_li" :class="{'selected': value == item[valueType.value]}" @click="change(item)">{{item[valueType.label]}}</view>
+						<view class="select_content_li" v-if="!showData.length">{{noDataText}}</view>
+					</view>
+				</view>
+			<!--  #endif -->
+			<view class="cons_arrow" :style="{'left': arrLeft +'px'}"></view>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		props: {
+			data: {
+				type: Array,
+				default: () => [{
+						label: '2022-02',
+						value: '02'
+					},
+					{
+						label: '2022-01',
+						value: '01'
+					},
+					{
+						label: '2021-12',
+						value: '12'
+					},
+					{
+						label: '2021-11',
+						value: '11'
+					},
+					{
+						label: '2021-10',
+						value: '10'
+					},
+					{
+						label: '2021-09',
+						value: '09'
+					}
+				]
+			},
+			valueType: {
+				type: Object,
+				default:()=>{
+					return {
+						label:'label',
+						value:'value'
+					}
+				} 
+			},
+			value: {
+				type: [String,Number],
+				default: ''
+			},
+			clearable:{
+				type: Boolean,
+				default: false
+			},
+			filterable:{
+				type: Boolean,
+				default: false
+			},
+			searchType:{
+				type: Number,
+				default: 1
+			},
+			placeholder:{
+				type: String,
+				default: '请选择'
+			},
+			noDataText:{
+				type: String,
+				default: '暂无数据'
+			},
+			arrLeft:{
+				type: Number,
+				default: 20
+			},
+			size:{
+				type: Number,
+				default: 240
+			}
+		},
+		data() {
+			return {
+				show: false,
+				readonly:true,
+				isClick:false,
+				totalArr:[],
+				showData:[],
+				selLabel:''
+			}
+		},
+		watch:{
+			'filterable':{
+				immediate:true,
+				deep:true,
+				handler(news){
+					this.readonly = !news
+				}
+			},
+			'data':{
+				immediate:true,
+				deep:true,
+				handler(news){
+					this.showData = news
+					this.totalArr = news
+				}
+			},
+			'value':{
+				immediate:true,
+				deep:true,
+				handler(news){
+					console.log(news,'value',this.data,this.valueType.value)
+					if(news){
+						let index = this.data.findIndex(ite=>ite[this.valueType.value]==news)
+						if(index==-1){
+							uni.showToast({
+								title:'传入的value不存在',
+								icon:'none',
+								duration:1500
+							})
+						}else{
+							this.selLabel = this.data[index][this.valueType.label]
+						}
+					}
+				}
+			}
+		},
+		created() {},
+		methods: {
+			openSelect(){
+				console.log('openSelect[[[]]]')
+				// if(!this.filterable){
+				// 	this.show=!this.show
+				// }
+				this.show=!this.show
+				this.isClick = !this.isClick
+			},
+			change(item) {
+				if (this.value != item[this.valueType]) {
+					this.$emit('input', item[this.valueType.value])
+					this.$emit('change', item[this.valueType.value])
+				}
+				this.selLabel = item[this.valueType.label]
+				this.show = false
+				this.isClick = false
+				this.showData = this.data
+			},
+			clearItem(){
+				if(this.clearable){
+					this.$emit('input', '')
+					this.$emit('change', '')
+				}
+				this.selLabel = ''
+				
+			},
+			selectData(e){
+				let sel = e.detail.value
+				if(sel){
+					let arrCons = []
+					let selVal = []
+					this.data.forEach(item=>{
+						arrCons.push(item)
+					})
+					arrCons.forEach((item)=>{
+						if(this.searchType==1){
+							if(item[this.valueType.label].indexOf(sel)!=-1){
+								selVal.push(item)
+							}
+						}else{
+							if(item[this.valueType.label]==sel){
+								selVal.push(item)
+							}
+						}
+						
+					})
+					this.show = true
+					this.showData = selVal
+				}else{
+					this.showData = this.data
+				}
+			}
+		},
+		beforeDestroy() {}
+	}
+</script>
+
+<style lang="less" scoped>
+	.select_wrap {
+		width: 240px;
+		display: inline-block;
+		position: relative;
+
+		.select_input {
+			-webkit-appearance: none;
+			background-color: #fff;
+			background-image: none;
+			border-radius: 4px;
+			border: 1px solid #dcdfe6;
+			box-sizing: border-box;
+			color: #606266;
+			display: inline-block;
+			font-size: inherit;
+			height: 40px;
+			line-height: 40px;
+			outline: none;
+			padding: 0 15px;
+			box-sizing: border-box;
+			transition: border-color .2s cubic-bezier(.645, .045, .355, 1);
+			width: 100%;
+			padding-right: 30px;
+
+			.input_info {
+				font-size: 18px;
+				width: 100%;
+				height: 100%;
+				.text_tips{
+					height: 100%;
+					text{
+						font-size: 14px;
+						color: #a0a9b0;
+					}
+				}
+			}
+
+			.icon_arrow {
+				position: absolute;
+				width: 30px;
+				height: 40px;
+				right: 0;
+				top: 0;
+				text-align: center;
+				color: #c0c4cc;
+				cursor: pointer;
+				display: flex;
+				justify-content: center;
+				align-items: center;
+				z-index: 999;
+				.arrow {
+					width: 10px;
+					height: 10px;
+					background-color: transparent;
+					/* 模块背景为透明 */
+					border-color: #c0c4cc;
+					border-style: solid;
+					border-width: 1px 1px 0 0;
+					box-sizing: border-box;
+					transition: all .3s;
+					box-sizing: border-box;
+					/*箭头方向可以自由切换角度*/
+				}
+				.arrow_down{
+					transform: rotate(-45deg);
+					margin-top: 5px;
+				}
+				.arrow_up{
+					transform: rotate(135deg);
+					margin-top: -5px;
+				}
+				.arrow-clear{
+					width: 14px;
+					height: 14px;
+					border: 1px solid #e4e7ed;
+					color: #e4e7ed;
+					border-radius: 50%;
+					display: flex;
+					justify-content: center;
+					align-items: center;
+					font-size: 12px;
+				}
+			}
+		}
+		.select_input_select{
+			border-color: #409eff;
+		}
+	}
+
+	.select_modal_con {
+		width: 100%;
+		transform-origin: center top;
+		z-index: 2062;
+		position: absolute;
+		top: 40px;
+		left: 0;
+		border: 1px solid #e4e7ed;
+		border-radius: 4px;
+		background-color: #fff;
+		box-shadow: 0 2px 12px 0 rgba(0, 0, 0, .1);
+		box-sizing: border-box;
+		margin-top: 12px;
+
+		.cons_arrow {
+			position: absolute;
+			display: block;
+			width: 0;
+			height: 0;
+			border-color: transparent;
+			border-style: solid;
+			top: -6px;
+			left: 10%;
+			margin-right: 3px;
+			border-top-width: 0;
+			border-bottom-color: #ebeef5;
+
+		}
+
+		.cons_arrow:after {
+			content: " ";
+			border-width: 6px;
+			position: absolute;
+			display: block;
+			width: 0;
+			height: 0;
+			border-color: transparent;
+			border-style: solid;
+			top: 1px;
+			margin-left: -6px;
+			border-top-width: 0;
+			border-bottom-color: #fff;
+		}
+	}
+
+	.select_modal {
+		overflow: scroll;
+		height: 160px;
+		.select_content{
+			list-style: none;
+			padding: 6px 0;
+			margin: 0;
+			box-sizing: border-box;
+			.select_content_li {
+				font-size: 14px;
+				padding: 0 20px;
+				position: relative;
+				white-space: nowrap;
+				overflow: hidden;
+				text-overflow: ellipsis;
+				color: #606266;
+				height: 34px;
+				line-height: 34px;
+				box-sizing: border-box;
+				cursor: pointer;
+				&.selected {
+					color: #409eff;
+					font-weight: 700;
+					background-color: #f5f7fa;
+				}
+			}
+			
+			.select_content_li:hover {
+				background-color: #f5f7fa;
+			}
+		}
+		
+
+		
+	}
+	.select_modal_scroll{
+		overflow: hidden;
+		height: 160px;
+	}
+
+	// .select_content {
+	// 	background-color: #fff;
+
+	// 	.select_content_li {
+	// 		padding: 12rpx;
+
+
+	// 	}
+	// }
+</style>

+ 1 - 1
uniapp/manifest.json

@@ -1,6 +1,6 @@
 {
     "name" : "人才图谱",
-    "appid" : "__UNI__BF50585",
+    "appid" : "__UNI__919686E",
     "description" : "",
     "versionName" : "2.2.4",
     "versionCode" : 104,

+ 16 - 0
uniapp/package.json

@@ -0,0 +1,16 @@
+{
+    "id": "cus-selects-fan",
+    "name": "下拉选择,单选,精准搜索,模糊搜索,清除选择",
+    "displayName": "下拉选择,单选,精准搜索,模糊搜索,清除选择",
+    "version": "1.0.11",
+    "description": "自定义下拉选择 可以清除选择,可以模糊搜素,可以精准搜索 (有问题请在评论区留言-我会收到邮件,请各位可以给3-5颗小星星哦,小星星就是我更新优化的动力哦)",
+    "keywords": [
+        "自定义下拉选择"
+    ],
+    "dcloudext": {
+        "category": [
+            "前端组件",
+            "通用组件"
+        ]
+    }
+}

+ 28 - 28
uniapp/pages/policy/list.vue

@@ -12,34 +12,34 @@
                 <view class="m-l-12" v-if="policyCengci.length > 0">匹配成功</view>
                 <view class="m-l-12" v-else>暂未匹配到政策</view>
             </view>
-			<block v-if="policyCengci.length > 0">
-				<view class="flex row-center m-t-14 white p-l-20 p-r-20" >根据您的条件AI智能计算可能符合以下政策,具体以实际申报为准</view>
-			</block>
-			
+            <block v-if="policyCengci.length > 0">
+                <view class="flex row-center m-t-14 white p-l-20 p-r-20">根据您的条件AI智能计算可能符合以下政策,具体以实际申报为准</view>
+            </block>
+
             <view class="m-t-22 p-l-24 p-r-24">
                 <view class="top-line"></view>
                 <view class="list">
                     <view class="bg-white p-t-18 p-l-24 p-r-24 p-b-34">
-						<!-- 人才层次 -->
-						<u-tabs :list="policyCengci" name="title" :is-scroll="true" :current="currentTab" :bold="false"
-							active-color="#DD4250" height="80" font-size="24" @change="changeTab" />
+                        <!-- 人才层次 -->
+                        <u-tabs :list="policyCengci" name="title" :is-scroll="true" :current="currentTab" :bold="false"
+                            active-color="#DD4250" height="80" font-size="24" @change="changeTab" />
                         <!-- 标签 -->
-						<view class="flex">
-							<view>您可能符合的认定条款:</view>
-							<rich-text :nodes="policyCengci[currentTab].content"></rich-text>
-						</view>
-                        <view class="flex flex-wrap">
+                        <view class="muted">您可能符合的认定条款:</view>
+                        <view class="m-t-10 primary bold">
+                            <rich-text :nodes="policyCengci[currentTab].content"></rich-text>
+                        </view>
+                        <view class="flex flex-wrap m-t-16">
                             <view class="tag-item" :class="{ 'tat-active': activeIndex == index }"
-                                v-for="(item, index) in policyList" :key="index" @tap="changeTag(index)">{{ item.title }}
+                                v-for="(item, index) in policyList" :key="index" @tap="changeTag(index)">
+                                {{ item.title }}
                             </view>
                         </view>
                         <view v-for="(item, index) in policyList" :key="index" v-if="activeIndex == index">
 
                             <!-- <view class="detail">{{ item.content }}</view> -->
-                             <rich-text :nodes="item.content"></rich-text>
+                            <rich-text :nodes="item.content"></rich-text>
                             <view class="flex row-center">
-                                <view class="user-logout flex col-center row-center white"
-                                    @tap="goDetail(item)">
+                                <view class="user-logout flex col-center row-center white" @tap="goDetail(item)">
                                     <view class="m-r-12">查看“{{ item.title }}”详情</view>
                                     <u-icon name="arrow-rightward" size="28"></u-icon>
                                 </view>
@@ -70,14 +70,14 @@
         data() {
             return {
                 activeIndex: 0,
-				policyList: [],
-				policyCengci: [],
-				currentTab: 0,
+                policyList: [],
+                policyCengci: [],
+                currentTab: 0,
             }
         },
         onLoad(option) {
-           this.policyList = uni.getStorageSync('policyList');
-           this.policyCengci = uni.getStorageSync('policyCengci');
+            this.policyList = uni.getStorageSync('policyList');
+            this.policyCengci = uni.getStorageSync('policyCengci');
         },
         onShow() {
             // this.getHomeFun();
@@ -94,17 +94,17 @@
             changeTag(index) {
                 this.activeIndex = index;
             },
-            goDetail(item){
+            goDetail(item) {
                 uni.setStorageSync('policyDetail', item);
                 uni.navigateTo({
-                    url: '/pages/policy/detail?id=' + item.id+ '&title=' + item.title,
+                    url: '/pages/policy/detail?id=' + item.id + '&title=' + item.title,
                 })
             },
-			// 改变当前的Tabs位置
-			changeTab(index) {
-				this.currentTab = index;
-				//todo 切换关联的政策列表
-			},
+            // 改变当前的Tabs位置
+            changeTab(index) {
+                this.currentTab = index;
+                //todo 切换关联的政策列表
+            },
         },
         computed: {
 

+ 49 - 13
uniapp/pages/policy/talent.vue

@@ -7,7 +7,7 @@
             </view>
             <view class="content-box bg-white m-t-30">
                 <view class="detail-cell row-between u-border-bottom" v-for="(item, index) in surveyList"
-                    @tap="pickerShow(item.name)">
+                    @tap="pickerShow(item.name)" v-if="item.type != 'array'">
                     <view class="width75">
                         {{item.description}}
                     </view>
@@ -27,10 +27,11 @@
                             </u-checkbox>
                         </u-checkbox-group>
                     </view>
-					
-					<view class="text-right flex-1" v-if="item.type == 'text'">
-					    <input type="text" v-model="info[item.name]" placeholder="请输入">
-					</view>
+
+                    <view class="text-right flex-1" v-if="item.type == 'text'">
+                        <cus-selects :data="item.value" v-model="info[item.name]" :clearable='true' :filterable='true'
+                            :searchType='1' arrLeft='300' placeholder='输入搜索'></cus-selects>
+                    </view>
                 </view>
 
 
@@ -58,6 +59,7 @@
 </template>
 
 <script>
+    import cusSelects from '@/components/cus-selects-fan/cus-selects-fan.vue'
     import {
         mapGetters,
         mapActions
@@ -71,6 +73,9 @@
     } from '@/utils/tools'
     const app = getApp()
     export default {
+        components: {
+            cusSelects
+        },
         data() {
             return {
                 show: {},
@@ -137,10 +142,19 @@
                         if (item.type == 'radio' || item.type == 'select') {
                             this.info[item.name] = item.value[0]
                         }
+                        //初始化模糊搜索框
+                        if (item.type == 'text') {
+                            item.value.forEach((value, key) => {
+                                item.value[key] = {
+                                    label: key+1 + '、' + value,
+                                    value: value
+                                }
+                            })
+                        }
+
                         //checkbox多选判断,初始化checked状态
                         if (item.type == 'checkbox') {
                             item.checked = []
-                            console.log(item.value)
                             item.value.forEach((value, key) => {
                                 item.checked[key] = false
                             })
@@ -149,15 +163,15 @@
                     })
                 }
             },
+
             //提交表单
             async handleConsult() {
-                // //todo API验证码
-                // if (this.captcha == '' || this.captcha != 'abcd') {
-                //     this.$toast({
-                //         title: '验证码错误'
-                //     })
-                //     return false;
-                // }
+                if (!this.info.code) {
+                    this.$toast({
+                        title: '请输入验证码'
+                    })
+                    return false;
+                }
                 const {
                     status,
                     data,
@@ -307,4 +321,26 @@
             color: #333333;
         }
     }
+
+    /deep/ .select_input {
+        border: none !important;
+    }
+     /deep/ .select_modal_con {
+            position: sticky;
+            // left: -100px;
+            margin-left: -200rpx;
+            width: 700rpx;
+            
+        .select_modal {
+            height: 100%;
+        }
+        .select_content_li {
+            text-align: left !important;
+            white-space: normal !important;
+            overflow: auto !important;
+            height: auto !important;
+            line-height: normal !important;
+            margin-bottom: 16rpx !important;
+        }
+    }
 </style>