Commit 46600559 authored by 王向前's avatar 王向前

添加部门信息、管理员设置、公司信息

parent f1a0bb95
......@@ -128,6 +128,34 @@ const routes = [
title: '修改密码',
},
},
{
path: '/pages/system/department/department',
name: 'department',
meta: {
title: '部门管理',
},
},
{
path: '/pages/system/txl/txl',
name: 'txl',
meta: {
title: '通讯录',
},
},
{
path: '/pages/system/glysetting/glysetting',
name: 'glysetting',
meta: {
title: '管理员设置',
},
},
{
path: '/pages/system/gsinfo/gsinfo',
name: 'gsinfo',
meta: {
title: '公司信息',
},
},
]
export default routes
/**
数据验证(表单验证)
来自 grace.hcoder.net
作者 hcoder 深海
版权声明 :
GraceUI 的版权约束是不能转售或者将 GraceUI 直接发布到公开渠道!
侵权必究,请遵守版权约定!
*/
module.exports = {
error:'',
check : function (data, rule){
for(var i = 0; i < rule.length; i++){
if (!rule[i].checkType){return true;}
if (!rule[i].name) {return true;}
if (!rule[i].errorMsg) {return true;}
if (!data[rule[i].name]) {this.error = rule[i].errorMsg; return false;}
switch (rule[i].checkType){
case 'string':
var reg = new RegExp('^.{' + rule[i].checkRule + '}$');
if(!reg.test(data[rule[i].name])) {this.error = rule[i].errorMsg; return false;}
break;
case 'int':
var reg = new RegExp('^(-[1-9]|[1-9])[0-9]{' + rule[i].checkRule + '}$');
if(!reg.test(data[rule[i].name])) {this.error = rule[i].errorMsg; return false;}
break;
break;
case 'between':
if (!this.isNumber(data[rule[i].name])){
this.error = rule[i].errorMsg;
return false;
}
var minMax = rule[i].checkRule.split(',');
minMax[0] = Number(minMax[0]);
minMax[1] = Number(minMax[1]);
if (data[rule[i].name] > minMax[1] || data[rule[i].name] < minMax[0]) {
this.error = rule[i].errorMsg;
return false;
}
break;
case 'betweenD':
var reg = /^-?[1-9][0-9]?$/;
if (!reg.test(data[rule[i].name])) { this.error = rule[i].errorMsg; return false; }
var minMax = rule[i].checkRule.split(',');
minMax[0] = Number(minMax[0]);
minMax[1] = Number(minMax[1]);
if (data[rule[i].name] > minMax[1] || data[rule[i].name] < minMax[0]) {
this.error = rule[i].errorMsg;
return false;
}
break;
case 'betweenF':
var reg = /^-?[0-9][0-9]?.+[0-9]+$/;
if (!reg.test(data[rule[i].name])){this.error = rule[i].errorMsg; return false;}
var minMax = rule[i].checkRule.split(',');
minMax[0] = Number(minMax[0]);
minMax[1] = Number(minMax[1]);
if (data[rule[i].name] > minMax[1] || data[rule[i].name] < minMax[0]) {
this.error = rule[i].errorMsg;
return false;
}
break;
case 'same':
if (data[rule[i].name] != rule[i].checkRule) { this.error = rule[i].errorMsg; return false;}
break;
case 'notsame':
if (data[rule[i].name] == rule[i].checkRule) { this.error = rule[i].errorMsg; return false; }
break;
case 'email':
var reg = /^\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/;
if (!reg.test(data[rule[i].name])) { this.error = rule[i].errorMsg; return false; }
break;
case 'phoneno':
var reg = /^1[0-9]{10,10}$/;
if (!reg.test(data[rule[i].name])) { this.error = rule[i].errorMsg; return false; }
break;
case 'zipcode':
var reg = /^[0-9]{6}$/;
if (!reg.test(data[rule[i].name])) { this.error = rule[i].errorMsg; return false; }
break;
case 'reg':
var reg = new RegExp(rule[i].checkRule);
if (!reg.test(data[rule[i].name])) { this.error = rule[i].errorMsg; return false; }
break;
case 'in':
if(rule[i].checkRule.indexOf(data[rule[i].name]) == -1){
this.error = rule[i].errorMsg; return false;
}
break;
case 'notnull':
if(data[rule[i].name] == null || data[rule[i].name].length < 1){this.error = rule[i].errorMsg; return false;}
break;
}
}
return true;
},
isNumber : function (checkVal){
checkVal = Number(checkVal);
if(checkVal == NaN){return false;}
return true;
}
}
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
<template>
<view class="me-tabs">
<scroll-view :id="viewId" :scroll-left="scrollLeft" scroll-x scroll-with-animation :scroll-animation-duration="300">
<view class="tabs-item tabs-flex tabs-scroll">
<view class="tab-item" v-for="(tab, i) in tabs" :key="i" @click="tabClick(i)" :ref="'refTabItem' + i">{{ tab.name }}</view>
</view>
</scroll-view>
</view>
</template>
<script>
export default {
data() {
return {
tabs: [],
viewId:
'id_' +
Math.random()
.toString(36)
.substr(2, 16),
scrollLeft: 0,
warpWidth: 0
};
},
computed: {
isScroll() {
return this.tabWidth && this.tabs.length; // 指定了tabWidth的宽度,则支持水平滑动
},
tabHeightPx() {
return uni.upx2px(this.height);
},
tabHeightVal() {
return 48 + 'px';
},
tabWidthPx() {
return uni.upx2px(this.tabWidth);
},
tabWidthVal() {
return this.isScroll ? this.tabWidthPx + 'px' : '';
},
lineLeft() {
if (this.isScroll) {
return this.tabWidthPx * this.value + this.tabWidthPx / 2 + 'px'; // 需转为px (用rpx的话iOS真机显示有误差)
} else {
return (100 / this.tabs.length) * (this.value + 1) - 100 / (this.tabs.length * 2) + '%';
}
}
},
watch: {
value() {
this.scrollCenter(); // 水平滚动到中间
}
},
methods: {
tabClick(i) {
this.tabs.splice(i + 1, this.tabs.length);
this.$emit('change', this.tabs[i]);
},
async addTab(item) {
this.tabs.push(item);
setTimeout(() => {
let query = uni.createSelectorQuery();
query = query.in(this); // 支付宝小程序不支持in(this),而字节跳动小程序必须写in(this), 否则都取不到值
query
.select('.tab-item')
.boundingClientRect(data => {
this.warpWidth += data.width;
this.scrollLeft = this.warpWidth;
})
.exec();
}, 100);
},
async removeTab(index) {
this.tabs.splice(index);
},
async scrollCenter() {
if (!this.isScroll) return;
if (!this.warpWidth) {
// tabs容器的宽度
let rect = await this.initWarpRect();
this.warpWidth = rect ? rect.width : uni.getSystemInfoSync().windowWidth; // 某些情况下取不到宽度,暂时取屏幕宽度
}
let tabLeft = this.tabWidthPx * this.value + this.tabWidthPx / 2; // 当前tab中心点到左边的距离
let diff = tabLeft - this.warpWidth / 2; // 如果超过tabs容器的一半,则滚动差值
this.scrollLeft = diff;
// #ifdef MP-TOUTIAO
this.scrollTimer && clearTimeout(this.scrollTimer);
this.scrollTimer = setTimeout(() => {
// 字节跳动小程序,需延时再次设置scrollLeft,否则tab切换跨度较大时不生效
this.scrollLeft = Math.ceil(diff);
}, 400);
// #endif
},
initWarpRect() {
return new Promise(resolve => {
setTimeout(() => {
// 延时确保dom已渲染, 不使用$nextclick
let query = uni.createSelectorQuery();
// #ifndef MP-ALIPAY
query = query.in(this); // 支付宝小程序不支持in(this),而字节跳动小程序必须写in(this), 否则都取不到值
// #endif
query
.select('#' + this.viewId)
.boundingClientRect(data => {
resolve(data);
})
.exec();
}, 20);
});
}
},
mounted() {
this.scrollCenter(); // 滚动到当前下标
}
};
</script>
<style lang="scss">
.me-tabs {
position: relative;
font-size: 24rpx;
background-color: #fff;
box-sizing: border-box;
overflow-y: hidden;
height: 48px;
&.tabs-fixed {
z-index: 990;
position: fixed;
top: var(--window-top);
left: 0;
width: 100%;
}
.tabs-item {
position: relative;
white-space: nowrap;
box-sizing: border-box;
}
// 平分的方式显示item
.tabs-flex {
display: flex;
.tab-item {
color: #666;
font-size: 14px;
margin-right: 10px;
position: relative;
padding-right: 22px;
color: #3173ff;
position: relative;
text-align: center;
box-sizing: border-box;
height: 48px;
line-height: 48px;
&::after {
content: '';
background: url(../../static/icon/tab-link.png);
position: absolute;
height: 48px;
width: 18px;
right: 0px;
top: 0px;
}
&:last-child {
margin-right: 0px;
color: #999;
&::after {
content: none;
}
}
}
}
.tabs-scroll {
.tab-item {
display: inline-block;
}
}
}
</style>
......@@ -19,6 +19,7 @@ Vue.use(appcommon)
Vue.prototype.$store=store;
Vue.prototype.$tip=tip;
Vue.prototype.$config=configService;
Vue.prototype.$eventHub=new Vue();
import interfacepage from './pages/index/index.vue'
Vue.component('interfacepage',interfacepage)
import people from './pages/user/people.vue'
......
......@@ -67,6 +67,49 @@
}
}
},
{
"path": "pages/system/department/department",
"style": {
"navigationBarTitleText": "",
"enablePullDownRefresh": false,
"app-plus": {
"bounce": "none"
}
}
},
{
"path": "pages/system/gsinfo/gsinfo",
"style": {
"navigationBarTitleText": "",
"enablePullDownRefresh": false,
"app-plus": {
"bounce": "none"
}
}
}, {
"path": "pages/system/glysetting/glysetting",
"style": {
"navigationBarTitleText": "",
"enablePullDownRefresh": false,
"app-plus": {
"bounce": "none"
}
}
}, {
"path": "pages/system/txl/txl",
"style": {
"navigationBarTitleText": "",
"enablePullDownRefresh": false,
"app-plus": {
"bounce": "none"
}
}
},
{
"path": "pages/kqgl/gzrb/index",
"style": {
......
This diff is collapsed.
<template>
<view class="">
<cu-header bgColor="bg-blue" isBack="true">
<block slot="content">
{{title}}</text>
</block>
<block slot="right">
</block>
</cu-header>
<view :style="[{top:CustomBar + 'px'}]">
<view class="cu-bar bg-white solid-bottom">
<view class="action">
<text class="font_weight">当前管理员</text>
</view>
</view>
<scroll-view scroll-y="true">
<view class="cu-list menu">
<view class="cu-item menu-avatar" v-for="(item,index) in myList" :key="index">
<view class="cu-avatar round lg"> <image style="border-radius: 50%;height: 36px;width: 36px;" src="../../../static/icon/tx.jpg"></image></view>
<view class="content text-overflow" style="display: block;padding: 0 10px;">
<view class="text-cut" style="color: black;font-size: 14px;"> {{item.username}}</view>
<!-- <view class="text-cut text-gray text-sm text-cut">{{item.userid}}</view> -->
</view>
<view class="action text-right" @tap="removeGlySetting(item)" v-show="isSuperuser">
<button class="bg-orange" size="mini">
移除
</button>
</view>
</view>
</view>
</scroll-view>
<view class="cu-list menu margin-top" v-show="isSuperuser">
<view class="cu-item menu-avatar" @tap="setNewGly">
<view class="cu-avatar " style="background-color: #eee;">
<uni-icons type="plusempty" size="24"></uni-icons>
</view>
<view class="content text-overflow" style="display: block;padding: 0 10px;">
<view class="text-cut" style="color: black;font-size: 14px;">添加新管理员</view>
</view>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
title:"管理员设置",
myList:[],
modalName:null,
modalNameX:null,
API:'',
CustomBar:this.CustomBar,
usercx:"",
formData:{},
userinfo:{
bmid:""
}
}
},
computed:{
isSuperuser(){
return this.$store.state.isSuperuser
}
},
filters:{
formatTime: function(time) {
if(time!=null&&time!="")
{
var date = new Date(time);
return date.Format("yy-MM-dd hh:mm")
}else{
return "";
}
},
formatDate:function(time){
if(time!=null&&time!="")
{
var date = new Date(time);
return date.Format("yyyy-MM-dd")
}else{
return "";
}
},
},
methods: {
hideModal(){
this.modalNameX=null
},
queryUser(){
let _that=this;
_that.$http.post(_that.API.userApi,{superFlag:"Y"}).then(res => {
if (res.data.success) {
_that.myList=res.data.data.records;
_that.options.status="noMore"
} else {
_that.myList=[];
}
_that.$forceUpdate()
});
},
setNewGly(){
this.$Router.push({name:"userlist",params:{type:"gly"}})
},
agreeSp(item){
let _that=this;
_that.userinfo=item;
_that.modalNameX="bottomModal";
_that.$forceUpdate()
},
disagreeSp(item){
let _that=this;
this.$tip.confirm("是否确认不通过?").then(r=>{
if(r.confirm){
_that.$http.post(_that.API.userFailApi,{id:item.id}).then(res => {
if (res.data.success) {
_that.queryUser();
_that.$tip.success("操作成功");
} else {
_that.$tip.toast(res.data.message||"操作失败");
}
_that.modalName=null;
_that.$forceUpdate()
});
}
})
},
removeGlySetting(user){
let _that=this;
if(this.myList.length<2){
this.$tip.alert("当前管理员不允许删除");
return false
}
this.$tip.confirm("是否移除该管理员?").then(r=>{
if(r.confirm){
apiService.removeGlySetting({id:user.id}).then(res => {
if (res.data.success) {
_that.$tip.success("操作成功");
_that.queryUser();
} else {
_that.$tip.toast(res.data.message||"操作失败");
}
_that.$forceUpdate()
});
}
})
},
addGly(user){
let _that=this;
apiService.addGlySetting({id:user.userid}).then(res => {
if (res.data.success) {
_that.$tip.success("操作成功");
_that.queryUser();
} else {
_that.$tip.toast(res.data.message||"操作失败");
}
_that.$forceUpdate()
});
}
},
onLoad() {
let _this=this;
this.queryUser();
this.$eventHub.$on("updateGly",function(value){
_this.addGly(value)
_this.$forceUpdate();
})
},
onUnload() {
this.$eventHub.$off('updateGly');
}
}
</script>
<style scoped>
page{
/* background: white; */
width: 100%;
height: 100%;
}
/deep/ .cu-list.menu>.cu-item{
min-height: 54px;
}
/deep/ .cu-avatar{
background-color: transparent;
}
/deep/ .cu-list.menu>.cu-item .content{
text-align: left;
}
/deep/.font_weight{
font-weight: bolder;
font-size: 16px;
}
</style>
<template>
<view class="page">
<cu-header :isBack="true" bgColor="bg-blue">
<block slot="content">
{{taskTitle}}
</block>
</cu-header>
<view :style="[{top:CustomBar + 'px'}]">
<!-- <web-view class="webview" :src="imp"></web-view> -->
<view id="container">
<h1 class="font_weight">苏州格物信息有限公司</h1>
<p class="text_indent">苏州格物信息技术有限公司成立于2015年,是一家专注于智能制造整体解决方案和企业数字化产品研究、开发及销售的高科技企业,总部及研发基地设立于风景秀丽的江南水乡苏州,并在全国各地设有分支机构。</p>
<p class="text_indent">
公司技术和研发实力雄厚,是国家 863 项目的参与者,并被政府认定为“高新技术企业”、“民营高科技企业”。为了开发出真正适合企业需求的产品,特聘请各行业专家作为咨询顾问,使用户得到优质的服务和最好的投资回报。
</p>
<p class="text_indent">
公司自成立以来,始终坚持以人才为本、诚信立业的经营原则,荟萃业界精英,将国外先进的信息技术、管理方法及企业经验与国内企业的具体实际相结台,为企业提供全方位的数字化整体解决方案,帮助企业提高管理水平和竞争能力,使企业在激烈的市场竞争中始终保持竞争力,实现企业快速、稳定地发展。
</p>
<p class="text_indent">
最好的产品、最好的服务、最好的信誉,苏州格物信息技术有限公司已在装备制造、冶金、煤矿、化工、机械加工、电子、汽配、注塑、冲压、轨道交通等诸多行业取得辉煌成绩。
</p>
<p class="text_indent font_weight">
期待成为您最可信赖的长期合作伙伴。
</p>
<image src="../../../static/icon/gavel.png" mode="webix" style="width: 100%;height: 160px;"></image>
<p class="text_indent font_weight">
联系我们
</p>
<p class="text_indent">
<ul>
<li>联系方式:0512-6802 8813 / 159 9573 9622</li>
<li>电子邮件:sales@gavelinfo.com</li>
<li>官方网站:<a href="https://www.gavelinfo.com/">https://www.gavelinfo.com</a></li>
</ul>
</p>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
CustomBar:this.CustomBar,
taskTitle:"关于我们",
}
},
methods: {
}
}
</script>
<style scoped>
page {
background-color: #fff;
font: 13px/20px normal Helvetica, Arial, sans-serif;
color: #4F5155;
}
a {
color: #003399;
background-color: transparent;
font-weight: normal;
}
h1 {
color: #444;
background-color: transparent;
border-bottom: 1px solid #D0D0D0;
font-size: 16px;
font-weight: normal;
margin: 0 0 14px 0;
padding: 14px 15px 10px 15px;
}
.title {
font-size: 14px;
font-weight: bolder;
color:#007aff;
}
code {
font-family: Consolas, Monaco, Courier New, Courier, monospace;
font-size: 12px;
background-color: #f9f9f9;
border: 1px solid #D0D0D0;
color: #002166;
display: block;
margin: 14px 0 14px 0;
padding: 12px 10px 12px 10px;
}
#container {
margin: 0;
box-shadow: 0 0 8px #D0D0D0;
-webkit-box-shadow: 0 0 8px #D0D0D0;
-moz-box-shadow: 0 0 8px #D0D0D0;
padding: 10px;
}
p {
margin: 12px 15px 12px 15px;
}
.p_left {
margin: 0px;
}
.p_left_k {
margin-left: -13px;
}
.p_width {
font-weight: 800;
}
.p_mleft {
margin-left: -14px;
}
.text_indent {
text-indent: 1em;
margin-left: 0;
}
.font_weight {
font-weight: bold;
}
span.text_indent {
display: block;
}
ol {
display: block;
list-style-type: decimal;
margin-block-start: 1em;
margin-block-end: 1em;
margin-inline-start: 0px;
margin-inline-end: 0px;
padding-inline-start: 10px!important;
padding-left: 10px;
}
li {
display: list-item;
text-align: -webkit-match-parent;
}
#hadsky-tools {
display: none;
}
</style>
<template>
<view class="bg-white">
<cu-header bgColor="bg-blue" isBack="true">
<block slot="content">
{{title}}</text>
</block>
<block slot="right">
</block>
</cu-header>
<view class="bg-white">
<city-select
placeholder="搜索"
@cityClick="cityClick"
:formatName="formatName"
:obtainCitys="obtainCitys"
:isSearch="true"
></city-select>
</view>
</view>
</template>
<script>
import citySelect from '@/components/city-select/city-select.vue';
import apiService from '@/api/api.js';
export default {
data() {
return {
API:apiService.API,
title:"通讯录",
formatName: 'username',
//显示的城市数据
obtainCitys: []
}
},
components: {
citySelect
},
methods: {
queryUser(){
let _that=this;
_that.$http.post(_that.API.userApi,{}).then(res => {
if (res.data.success) {
_that.obtainCitys=res.data.data.records;
_that.options.status="noMore"
} else {
_that.obtainCitys=[];
}
_that.$forceUpdate()
});
},
cityClick(v){
if(v.phone){
this.telphone(v.phone)
}
},
telphone(phone){
// 获取设备平台
let platform = uni.getSystemInfoSync().platform
switch (platform) {
case 'android':
uni.showActionSheet({
itemList: [phone,'呼叫'],
success:function(res){
console.log(res);
if(res.tapIndex==1){
plus.device.dial(phone,false)
}
},
complete: function(res) {
console.log("安卓失败",res)
}
})
break;
case 'ios':
// 使用uni-app提供的借口
uni.makePhoneCall({
phoneNumber: phone
})
break;
default:
// 调试器工具
}
}
},
onLoad(){
this.queryUser();
}
}
</script>
<style scoped>
page{
background: white;
width: 100%;
height: 100%;
}
/deep/.city-select-main{
background-color: white;
}
</style>
## 1.1.19(2024-07-18)
- 修复 初始值传入 null 导致input报错的bug
## 1.1.18(2024-04-11)
- 修复 easyinput组件双向绑定问题
## 1.1.17(2024-03-28)
- 修复 在头条小程序下丢失事件绑定的问题
## 1.1.16(2024-03-20)
- 修复 在密码输入情况下 清除和小眼睛覆盖bug 在edge浏览器下显示双眼睛bug
## 1.1.15(2024-02-21)
- 新增 左侧插槽:left
## 1.1.14(2024-02-19)
- 修复 onBlur的emit传值错误
## 1.1.12(2024-01-29)
- 补充 adjust-position文档属性补充
## 1.1.11(2024-01-29)
- 补充 adjust-position属性传递值:(Boolean)当键盘弹起时,是否自动上推页面
## 1.1.10(2024-01-22)
- 去除 移除无用的log输出
## 1.1.9(2023-04-11)
- 修复 vue3 下 keyboardheightchange 事件报错的bug
## 1.1.8(2023-03-29)
- 优化 trim 属性默认值
## 1.1.7(2023-03-29)
- 新增 cursor-spacing 属性
## 1.1.6(2023-01-28)
- 新增 keyboardheightchange 事件,可监听键盘高度变化
## 1.1.5(2022-11-29)
- 优化 主题样式
## 1.1.4(2022-10-27)
- 修复 props 中背景颜色无默认值的bug
## 1.1.0(2022-06-30)
- 新增 在 uni-forms 1.4.0 中使用可以在 blur 时校验内容
- 新增 clear 事件,点击右侧叉号图标触发
- 新增 change 事件 ,仅在输入框失去焦点或用户按下回车时触发
- 优化 组件样式,组件获取焦点时高亮显示,图标颜色调整等
## 1.0.5(2022-06-07)
- 优化 clearable 显示策略
## 1.0.4(2022-06-07)
- 优化 clearable 显示策略
## 1.0.3(2022-05-20)
- 修复 关闭图标某些情况下无法取消的 bug
## 1.0.2(2022-04-12)
- 修复 默认值不生效的 bug
## 1.0.1(2022-04-02)
- 修复 value 不能为 0 的 bug
## 1.0.0(2021-11-19)
- 优化 组件 UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-easyinput](https://uniapp.dcloud.io/component/uniui/uni-easyinput)
## 0.1.4(2021-08-20)
- 修复 在 uni-forms 的动态表单中默认值校验不通过的 bug
## 0.1.3(2021-08-11)
- 修复 在 uni-forms 中重置表单,错误信息无法清除的问题
## 0.1.2(2021-07-30)
- 优化 vue3 下事件警告的问题
## 0.1.1
- 优化 errorMessage 属性支持 Boolean 类型
## 0.1.0(2021-07-13)
- 组件兼容 vue3,如何创建 vue3 项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
## 0.0.16(2021-06-29)
- 修复 confirmType 属性(仅 type="text" 生效)导致多行文本框无法换行的 bug
## 0.0.15(2021-06-21)
- 修复 passwordIcon 属性拼写错误的 bug
## 0.0.14(2021-06-18)
- 新增 passwordIcon 属性,当 type=password 时是否显示小眼睛图标
- 修复 confirmType 属性不生效的问题
## 0.0.13(2021-06-04)
- 修复 disabled 状态可清出内容的 bug
## 0.0.12(2021-05-12)
- 新增 组件示例地址
## 0.0.11(2021-05-07)
- 修复 input-border 属性不生效的问题
## 0.0.10(2021-04-30)
- 修复 ios 遮挡文字、显示一半的问题
## 0.0.9(2021-02-05)
- 调整为 uni_modules 目录规范
- 优化 兼容 nvue 页面
/**
* @desc 函数防抖
* @param func 目标函数
* @param wait 延迟执行毫秒数
* @param immediate true - 立即执行, false - 延迟执行
*/
export const debounce = function(func, wait = 1000, immediate = true) {
let timer;
return function() {
let context = this,
args = arguments;
if (timer) clearTimeout(timer);
if (immediate) {
let callNow = !timer;
timer = setTimeout(() => {
timer = null;
}, wait);
if (callNow) func.apply(context, args);
} else {
timer = setTimeout(() => {
func.apply(context, args);
}, wait)
}
}
}
/**
* @desc 函数节流
* @param func 函数
* @param wait 延迟执行毫秒数
* @param type 1 使用表时间戳,在时间段开始的时候触发 2 使用表定时器,在时间段结束的时候触发
*/
export const throttle = (func, wait = 1000, type = 1) => {
let previous = 0;
let timeout;
return function() {
let context = this;
let args = arguments;
if (type === 1) {
let now = Date.now();
if (now - previous > wait) {
func.apply(context, args);
previous = now;
}
} else if (type === 2) {
if (!timeout) {
timeout = setTimeout(() => {
timeout = null;
func.apply(context, args)
}, wait)
}
}
}
}
{
"id": "uni-easyinput",
"displayName": "uni-easyinput 增强输入框",
"version": "1.1.19",
"description": "Easyinput 组件是对原生input组件的增强",
"keywords": [
"uni-ui",
"uniui",
"input",
"uni-easyinput",
"输入框"
],
"repository": "https://github.com/dcloudio/uni-ui",
"engines": {
"HBuilderX": ""
},
"directories": {
"example": "../../temps/example_temps"
},
"dcloudext": {
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": ""
},
"declaration": {
"ads": "无",
"data": "无",
"permissions": "无"
},
"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
"type": "component-vue"
},
"uni_modules": {
"dependencies": [
"uni-scss",
"uni-icons"
],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y",
"alipay": "n"
},
"client": {
"App": {
"app-vue": "y",
"app-nvue": "y"
},
"H5-mobile": {
"Safari": "y",
"Android Browser": "y",
"微信浏览器(Android)": "y",
"QQ浏览器(Android)": "y"
},
"H5-pc": {
"Chrome": "y",
"IE": "y",
"Edge": "y",
"Firefox": "y",
"Safari": "y"
},
"小程序": {
"微信": "y",
"阿里": "y",
"百度": "y",
"字节跳动": "y",
"QQ": "y"
},
"快应用": {
"华为": "u",
"联盟": "u"
},
"Vue": {
"vue2": "y",
"vue3": "y"
}
}
}
}
}
\ No newline at end of file
### Easyinput 增强输入框
> **组件名:uni-easyinput**
> 代码块: `uEasyinput`
easyinput 组件是对原生input组件的增强 ,是专门为配合表单组件[uni-forms](https://ext.dcloud.net.cn/plugin?id=2773)而设计的,easyinput 内置了边框,图标等,同时包含 input 所有功能
### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-easyinput)
#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839
\ No newline at end of file
## 1.4.13(2024-10-08)
- 修复 校验规则在抖音开发者工具上不生效的bug,详见:[https://ask.dcloud.net.cn/question/191933](https://ask.dcloud.net.cn/question/191933)
## 1.4.12 (2024-9-21)
- 修复 form上次修改的问题
## 1.4.11 (2024-9-14)
- 修复 binddata的兼容性问题
## 1.4.10(2023-11-03)
- 优化 labelWidth 描述错误
## 1.4.9(2023-02-10)
- 修复 required 参数无法动态绑定
## 1.4.8(2022-08-23)
- 优化 根据 rules 自动添加 required 的问题
## 1.4.7(2022-08-22)
- 修复 item 未设置 require 属性,rules 设置 require 后,星号也显示的 bug,详见:[https://ask.dcloud.net.cn/question/151540](https://ask.dcloud.net.cn/question/151540)
## 1.4.6(2022-07-13)
- 修复 model 需要校验的值没有声明对应字段时,导致第一次不触发校验的bug
## 1.4.5(2022-07-05)
- 新增 更多表单示例
- 优化 子表单组件过期提示的问题
- 优化 子表单组件uni-datetime-picker、uni-data-select、uni-data-picker的显示样式
## 1.4.4(2022-07-04)
- 更新 删除组件日志
## 1.4.3(2022-07-04)
- 修复 由 1.4.0 引发的 label 插槽不生效的bug
## 1.4.2(2022-07-04)
- 修复 子组件找不到 setValue 报错的bug
## 1.4.1(2022-07-04)
- 修复 uni-data-picker 在 uni-forms-item 中报错的bug
- 修复 uni-data-picker 在 uni-forms-item 中宽度不正确的bug
## 1.4.0(2022-06-30)
- 【重要】组件逻辑重构,部分用法用旧版本不兼容,请注意兼容问题
- 【重要】组件使用 Provide/Inject 方式注入依赖,提供了自定义表单组件调用 uni-forms 校验表单的能力
- 新增 model 属性,等同于原 value/modelValue 属性,旧属性即将废弃
- 新增 validateTrigger 属性的 blur 值,仅 uni-easyinput 生效
- 新增 onFieldChange 方法,可以对子表单进行校验,可替代binddata方法
- 新增 子表单的 setRules 方法,配合自定义校验函数使用
- 新增 uni-forms-item 的 setRules 方法,配置动态表单使用可动态更新校验规则
- 优化 动态表单校验方式,废弃拼接name的方式
## 1.3.3(2022-06-22)
- 修复 表单校验顺序无序问题
## 1.3.2(2021-12-09)
-
## 1.3.1(2021-11-19)
- 修复 label 插槽不生效的bug
## 1.3.0(2021-11-19)
- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-forms](https://uniapp.dcloud.io/component/uniui/uni-forms)
## 1.2.7(2021-08-13)
- 修复 没有添加校验规则的字段依然报错的Bug
## 1.2.6(2021-08-11)
- 修复 重置表单错误信息无法清除的问题
## 1.2.5(2021-08-11)
- 优化 组件文档
## 1.2.4(2021-08-11)
- 修复 表单验证只生效一次的问题
## 1.2.3(2021-07-30)
- 优化 vue3下事件警告的问题
## 1.2.2(2021-07-26)
- 修复 vue2 下条件编译导致destroyed生命周期失效的Bug
- 修复 1.2.1 引起的示例在小程序平台报错的Bug
## 1.2.1(2021-07-22)
- 修复 动态校验表单,默认值为空的情况下校验失效的Bug
- 修复 不指定name属性时,运行报错的Bug
- 优化 label默认宽度从65调整至70,使required为true且四字时不换行
- 优化 组件示例,新增动态校验示例代码
- 优化 组件文档,使用方式更清晰
## 1.2.0(2021-07-13)
- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
## 1.1.2(2021-06-25)
- 修复 pattern 属性在微信小程序平台无效的问题
## 1.1.1(2021-06-22)
- 修复 validate-trigger属性为submit且err-show-type属性为toast时不能弹出的Bug
## 1.1.0(2021-06-22)
- 修复 只写setRules方法而导致校验不生效的Bug
- 修复 由上个办法引发的错误提示文字错位的Bug
## 1.0.48(2021-06-21)
- 修复 不设置 label 属性 ,无法设置label插槽的问题
## 1.0.47(2021-06-21)
- 修复 不设置label属性,label-width属性不生效的bug
- 修复 setRules 方法与rules属性冲突的问题
## 1.0.46(2021-06-04)
- 修复 动态删减数据导致报错的问题
## 1.0.45(2021-06-04)
- 新增 modelValue 属性 ,value 即将废弃
## 1.0.44(2021-06-02)
- 新增 uni-forms-item 可以设置单独的 rules
- 新增 validate 事件增加 keepitem 参数,可以选择那些字段不过滤
- 优化 submit 事件重命名为 validate
## 1.0.43(2021-05-12)
- 新增 组件示例地址
## 1.0.42(2021-04-30)
- 修复 自定义检验器失效的问题
## 1.0.41(2021-03-05)
- 更新 校验器
- 修复 表单规则设置类型为 number 的情况下,值为0校验失败的Bug
## 1.0.40(2021-03-04)
- 修复 动态显示uni-forms-item的情况下,submit 方法获取值错误的Bug
## 1.0.39(2021-02-05)
- 调整为uni_modules目录规范
- 修复 校验器传入 int 等类型 ,返回String类型的Bug
This diff is collapsed.
/**
* 简单处理对象拷贝
* @param {Obejct} 被拷贝对象
* @@return {Object} 拷贝对象
*/
export const deepCopy = (val) => {
return JSON.parse(JSON.stringify(val))
}
/**
* 过滤数字类型
* @param {String} format 数字类型
* @@return {Boolean} 返回是否为数字类型
*/
export const typeFilter = (format) => {
return format === 'int' || format === 'double' || format === 'number' || format === 'timestamp';
}
/**
* 把 value 转换成指定的类型,用于处理初始值,原因是初始值需要入库不能为 undefined
* @param {String} key 字段名
* @param {any} value 字段值
* @param {Object} rules 表单校验规则
*/
export const getValue = (key, value, rules) => {
const isRuleNumType = rules.find(val => val.format && typeFilter(val.format));
const isRuleBoolType = rules.find(val => (val.format && val.format === 'boolean') || val.format === 'bool');
// 输入类型为 number
if (!!isRuleNumType) {
if (!value && value !== 0) {
value = null
} else {
value = isNumber(Number(value)) ? Number(value) : value
}
}
// 输入类型为 boolean
if (!!isRuleBoolType) {
value = isBoolean(value) ? value : false
}
return value;
}
/**
* 获取表单数据
* @param {String|Array} name 真实名称,需要使用 realName 获取
* @param {Object} data 原始数据
* @param {any} value 需要设置的值
*/
export const setDataValue = (field, formdata, value) => {
formdata[field] = value
return value || ''
}
/**
* 获取表单数据
* @param {String|Array} field 真实名称,需要使用 realName 获取
* @param {Object} data 原始数据
*/
export const getDataValue = (field, data) => {
return objGet(data, field)
}
/**
* 获取表单类型
* @param {String|Array} field 真实名称,需要使用 realName 获取
*/
export const getDataValueType = (field, data) => {
const value = getDataValue(field, data)
return {
type: type(value),
value
}
}
/**
* 获取表单可用的真实name
* @param {String|Array} name 表单name
* @@return {String} 表单可用的真实name
*/
export const realName = (name, data = {}) => {
const base_name = _basePath(name)
if (typeof base_name === 'object' && Array.isArray(base_name) && base_name.length > 1) {
const realname = base_name.reduce((a, b) => a += `#${b}`, '_formdata_')
return realname
}
return base_name[0] || name
}
/**
* 判断是否表单可用的真实name
* @param {String|Array} name 表单name
* @@return {String} 表单可用的真实name
*/
export const isRealName = (name) => {
const reg = /^_formdata_#*/
return reg.test(name)
}
/**
* 获取表单数据的原始格式
* @@return {Object|Array} object 需要解析的数据
*/
export const rawData = (object = {}, name) => {
let newData = JSON.parse(JSON.stringify(object))
let formData = {}
for(let i in newData){
let path = name2arr(i)
objSet(formData,path,newData[i])
}
return formData
}
/**
* 真实name还原为 array
* @param {*} name
*/
export const name2arr = (name) => {
let field = name.replace('_formdata_#', '')
field = field.split('#').map(v => (isNumber(v) ? Number(v) : v))
return field
}
/**
* 对象中设置值
* @param {Object|Array} object 源数据
* @param {String| Array} path 'a.b.c' 或 ['a',0,'b','c']
* @param {String} value 需要设置的值
*/
export const objSet = (object, path, value) => {
if (typeof object !== 'object') return object;
_basePath(path).reduce((o, k, i, _) => {
if (i === _.length - 1) {
// 若遍历结束直接赋值
o[k] = value
return null
} else if (k in o) {
// 若存在对应路径,则返回找到的对象,进行下一次遍历
return o[k]
} else {
// 若不存在对应路径,则创建对应对象,若下一路径是数字,新对象赋值为空数组,否则赋值为空对象
o[k] = /^[0-9]{1,}$/.test(_[i + 1]) ? [] : {}
return o[k]
}
}, object)
// 返回object
return object;
}
// 处理 path, path有三种形式:'a[0].b.c'、'a.0.b.c' 和 ['a','0','b','c'],需要统一处理成数组,便于后续使用
function _basePath(path) {
// 若是数组,则直接返回
if (Array.isArray(path)) return path
// 若有 '[',']',则替换成将 '[' 替换成 '.',去掉 ']'
return path.replace(/\[/g, '.').replace(/\]/g, '').split('.')
}
/**
* 从对象中获取值
* @param {Object|Array} object 源数据
* @param {String| Array} path 'a.b.c' 或 ['a',0,'b','c']
* @param {String} defaultVal 如果无法从调用链中获取值的默认值
*/
export const objGet = (object, path, defaultVal = 'undefined') => {
// 先将path处理成统一格式
let newPath = _basePath(path)
// 递归处理,返回最后结果
let val = newPath.reduce((o, k) => {
return (o || {})[k]
}, object);
return !val || val !== undefined ? val : defaultVal
}
/**
* 是否为 number 类型
* @param {any} num 需要判断的值
* @return {Boolean} 是否为 number
*/
export const isNumber = (num) => {
return !isNaN(Number(num))
}
/**
* 是否为 boolean 类型
* @param {any} bool 需要判断的值
* @return {Boolean} 是否为 boolean
*/
export const isBoolean = (bool) => {
return (typeof bool === 'boolean')
}
/**
* 是否有必填字段
* @param {Object} rules 规则
* @return {Boolean} 是否有必填字段
*/
export const isRequiredField = (rules) => {
let isNoField = false;
for (let i = 0; i < rules.length; i++) {
const ruleData = rules[i];
if (ruleData.required) {
isNoField = true;
break;
}
}
return isNoField;
}
/**
* 获取数据类型
* @param {Any} obj 需要获取数据类型的值
*/
export const type = (obj) => {
var class2type = {};
// 生成class2type映射
"Boolean Number String Function Array Date RegExp Object Error".split(" ").map(function(item, index) {
class2type["[object " + item + "]"] = item.toLowerCase();
})
if (obj == null) {
return obj + "";
}
return typeof obj === "object" || typeof obj === "function" ?
class2type[Object.prototype.toString.call(obj)] || "object" :
typeof obj;
}
/**
* 判断两个值是否相等
* @param {any} a 值
* @param {any} b 值
* @return {Boolean} 是否相等
*/
export const isEqual = (a, b) => {
//如果a和b本来就全等
if (a === b) {
//判断是否为0和-0
return a !== 0 || 1 / a === 1 / b;
}
//判断是否为null和undefined
if (a == null || b == null) {
return a === b;
}
//接下来判断a和b的数据类型
var classNameA = toString.call(a),
classNameB = toString.call(b);
//如果数据类型不相等,则返回false
if (classNameA !== classNameB) {
return false;
}
//如果数据类型相等,再根据不同数据类型分别判断
switch (classNameA) {
case '[object RegExp]':
case '[object String]':
//进行字符串转换比较
return '' + a === '' + b;
case '[object Number]':
//进行数字转换比较,判断是否为NaN
if (+a !== +a) {
return +b !== +b;
}
//判断是否为0或-0
return +a === 0 ? 1 / +a === 1 / b : +a === +b;
case '[object Date]':
case '[object Boolean]':
return +a === +b;
}
//如果是对象类型
if (classNameA == '[object Object]') {
//获取a和b的属性长度
var propsA = Object.getOwnPropertyNames(a),
propsB = Object.getOwnPropertyNames(b);
if (propsA.length != propsB.length) {
return false;
}
for (var i = 0; i < propsA.length; i++) {
var propName = propsA[i];
//如果对应属性对应值不相等,则返回false
if (a[propName] !== b[propName]) {
return false;
}
}
return true;
}
//如果是数组类型
if (classNameA == '[object Array]') {
if (a.toString() == b.toString()) {
return true;
}
return false;
}
}
This diff is collapsed.
{
"id": "uni-forms",
"displayName": "uni-forms 表单",
"version": "1.4.13",
"description": "由输入框、选择器、单选框、多选框等控件组成,用以收集、校验、提交数据",
"keywords": [
"uni-ui",
"表单",
"校验",
"表单校验",
"表单验证"
],
"repository": "https://github.com/dcloudio/uni-ui",
"engines": {
"HBuilderX": ""
},
"directories": {
"example": "../../temps/example_temps"
},
"dcloudext": {
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": ""
},
"declaration": {
"ads": "无",
"data": "无",
"permissions": "无"
},
"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
"type": "component-vue"
},
"uni_modules": {
"dependencies": [
"uni-scss",
"uni-icons"
],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y",
"alipay": "n"
},
"client": {
"App": {
"app-vue": "y",
"app-nvue": "y"
},
"H5-mobile": {
"Safari": "y",
"Android Browser": "y",
"微信浏览器(Android)": "y",
"QQ浏览器(Android)": "y"
},
"H5-pc": {
"Chrome": "y",
"IE": "y",
"Edge": "y",
"Firefox": "y",
"Safari": "y"
},
"小程序": {
"微信": "y",
"阿里": "y",
"百度": "y",
"字节跳动": "y",
"QQ": "y",
"京东": "u"
},
"快应用": {
"华为": "u",
"联盟": "u"
},
"Vue": {
"vue2": "y",
"vue3": "y"
}
}
}
}
}
## Forms 表单
> **组件名:uni-forms**
> 代码块: `uForms`、`uni-forms-item`
> 关联组件:`uni-forms-item`、`uni-easyinput`、`uni-data-checkbox`、`uni-group`。
uni-app的内置组件已经有了 `<form>`组件,用于提交表单内容。
然而几乎每个表单都需要做表单验证,为了方便做表单验证,减少重复开发,`uni ui` 又基于 `<form>`组件封装了 `<uni-forms>`组件,内置了表单验证功能。
`<uni-forms>` 提供了 `rules`属性来描述校验规则、`<uni-forms-item>`子组件来包裹具体的表单项,以及给原生或三方组件提供了 `binddata()` 来设置表单值。
每个要校验的表单项,不管input还是checkbox,都必须放在`<uni-forms-item>`组件中,且一个`<uni-forms-item>`组件只能放置一个表单项。
`<uni-forms-item>`组件内部预留了显示error message的区域,默认是在表单项的底部。
另外,`<uni-forms>`组件下面的各个表单项,可以通过`<uni-group>`包裹为不同的分组。同一`<uni-group>`下的不同表单项目将聚拢在一起,同其他group保持垂直间距。`<uni-group>`仅影响视觉效果。
### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-forms)
#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment