This commit is contained in:
梁朝伟 2022-07-05 16:28:26 +08:00
parent 3c65fc7606
commit 56159bd2fd
14 changed files with 639 additions and 6 deletions

View File

@ -0,0 +1,16 @@
{
"navigationBarTitleText": "人员管理",
"usingComponents": {
"l-button": "../../lin-ui/button/index",
"l-card": "../../lin-ui/card/index",
"l-tag": "../../lin-ui/tag/index",
"l-icon": "../../lin-ui/icon/index",
"l-status-show": "../../lin-ui/status-show/index",
"l-search-bar": "../../lin-ui/search-bar/index",
"l-price": "../../lin-ui/price/index",
"divider": "../../components/divider/index",
"fab": "../../components/fab/index",
"l-checkbox": "../../lin-ui/checkbox/index",
"l-message": "../../lin-ui/message/index"
}
}

View File

@ -0,0 +1,68 @@
/** index.wxss **/
@import "../../config/styles/_base.less";
@import "../../config/styles/_mixins.less";
page {
height: 100%;
background-color: @background-color-base;
}
.container {
height: 100%;
display: flex;
flex: 1;
flex-direction: column;
box-sizing: border-box;
align-items: stretch;
padding: 0;
.safe-area-inset-bottom();
}
.search-bar {
background-color: #fff;
padding-top: 10rpx;
padding-bottom: 10rpx;
z-index: 1;
}
.card-view {
margin-top: @size-spacing-small !important;
}
.content {
display: flex;
flex: 1;
flex-direction: column;
font-size: 28rpx;
color: @text-color;
}
.col {
display: flex;
flex-direction: column;
}
.row {
display: flex;
align-items: center;
}
.name {
font-size: @size-font-large;
color: @title-color;
}
.mobile {
font-size: @size-font-base;
color: @text-color;
}
.img {
width: 140rpx;
height: 140rpx;
margin-right: @size-spacing-small;
border-radius: 50%;
background-color: @background-color-base;
}
.card-view {
margin: @size-spacing-small;
padding: @size-spacing-small;
margin-bottom: 0;
background-color: #fff;
}

View File

@ -0,0 +1,188 @@
export default OakComponent(
{
path: 'userSearch:search',
entity: 'user',
projection: {
id: 1,
name: 1,
nickname: 1,
mobile$user: {
$entity: 'mobile',
data: {
id: 1,
userId: 1,
mobile: 1,
},
},
// extraFile$entity: {
// $entity: 'extraFile',
// data: {
// id: 1,
// tag1: 1,
// origin: 1,
// bucket: 1,
// objectId: 1,
// filename: 1,
// extra1: 1,
// type: 1,
// entity: 1,
// extension: 1,
// },
// filter: {
// tag1: 'avatar',
// },
// indexFrom: 0,
// count: 1,
// },
},
filters: [
// {
// filter: async ({ onLoadOptions }) => {
// return {
// id: {
// $in: {
// entity: 'mobile',
// data: {
// userId: 1,
// },
// filter: {
// mobile: {
// $eq: '111111111112',
// }
// }
// }
// }
// };
// },
// '#name': 'mobile',
// },
],
isList: false,
formData: async function ({ data: users, params, features }) {
const isRoot = await features.token.isRoot();
const filter = await this.getFilterByName('name');
return {
users: users?.map((ele: any) => {
const { mobile$user, extraFile$entity } =
ele || {};
const mobile = mobile$user && mobile$user[0]?.mobile;
const avatar =
extraFile$entity &&
extraFile$entity[0] &&
composeFileUrl(extraFile$entity[0]);
const user2 = Object.assign({}, ele, {
mobile,
avatar,
});
return user2;
}),
searchValue: (
filter?.$or as [{ name: { $includes: string } }]
)[0].name.$includes,
isRoot,
};
},
properties: {
},
data: {},
lifetimes: {
ready() {
const searchStr = wx.getStorageSync('user_searchList') as string;
if (searchStr.length) {
const searchArr = JSON.parse(searchStr) as Array<string>;
this.addNamedFilter({
filter: {
id: {
$in: {
entity: 'mobile',
data: {
userId: 1,
},
filter: {
$or: searchArr.map(ele => {
{
mobile: {
$eq: ele
}
}
})
}
}
}
},
'#name': 'mobile',
})
}
}
},
methods: {
async searchChange(input: any) {
},
async searchCancel() {
this.setState({
searchValue: '',
})
},
async searchConfirm(input: any) {
const { value } = this.resolveInput(input);
if (value.length < 11) {
this.setState({
msgType: 'warning',
showMsg: true,
content: '手机号位数不足11位'
})
return;
}
const searchStr = wx.getStorageSync('user_searchList') as string;
let searchArr: Array<string> = [];
if (!searchStr) {
searchArr.push(value)
}
else {
searchArr = JSON.parse(searchStr) as Array<string>;
}
wx.setStorageSync('user_searchList', JSON.stringify(searchArr));
this.addNamedFilter({
filter: {
id: {
$in: {
entity: 'mobile',
data: {
userId: 1,
},
filter: {
mobile: {
$eq: value,
}
}
}
}
},
'#name': 'mobile',
});
this.refresh();
},
goUpsertUser() {
const { entity, entityId } = this.props;
this.navigateTo({
url: '../../user/manage/upsert/index',
});
},
handleCardClick(event: any) {
const { entity, entityId } = this.props;
const { dataset } = this.resolveInput(event);
const { id } = dataset!;
this.navigateTo({
url: '../detail/index',
oakId: id,
entity,
entityId,
relations: JSON.stringify(['manager', 'owner']),
});
},
},
}
);

View File

@ -0,0 +1,30 @@
<!-- index.wxml -->
<view class="container">
<view class="search-bar">
<l-search-bar placeholder="输入手机号" shape="circle" value="{{searchValue}}" bind:lincancel="searchCancel" bind:linclear="searchCancel" bind:linchange="searchChange" bind:linconfirm="searchConfirm" />
</view>
<block wx:if="{{ users && users.length > 0 }}">
<block wx:for="{{users}}" wx:key="index" wx:for-item="item">
<view class="card-view">
<view class="row">
<l-checkbox key="{{item.id || '1'}}" checked="{{false}}"></l-checkbox>
<image mode="aspectFill" class="img" src="{{item.avatar}}" lazy-load></image>
<view class="col">
<text class="name">{{item.name}}</text>
<text class="mobile">{{item.nickname}}</text>
<text class="mobile">{{item.mobile}}</text>
</view>
</view>
</view>
</block>
<block wx:if="{{isRoot}}">
<fab bind:click="goUpsertUser">
<l-icon name="add" type="material" color="#fff" size="48" />
</fab>
</block>
</block>
<block wx:elif="{{isRoot}}">
<l-status-show show="{{true}}" type="data" button-text="添加人员" bind:lintap="goUpsertUser"></l-status-show>
</block>
<l-message type="{{msgType}}" show="{{showMsg}}" content="{{content}}" />
</view>

View File

@ -1,5 +1,5 @@
/** index.wxss **/
@import "../../../styles/base.less";
@import "../../../config/_base.less";
.page-body {
height: 100vh;

View File

@ -1,4 +1,4 @@
@import "../../../styles/base.less";
@import "../../../config/_base.less";
.container {
height: 100vh;
background-color: @background-color-base;

View File

@ -1,5 +1,5 @@
/** index.wxss **/
@import "../../../styles/base.less";
@import "../../../config/_base.less";
.page-body {
height: 100vh;

View File

@ -1,5 +1,5 @@
/** index.wxss **/
@import "../../../styles/base.less";
@import "../../../config/_base.less";
page {
height: 100%;

View File

@ -0,0 +1,16 @@
{
"navigationBarTitleText": "人员管理",
"usingComponents": {
"l-button": "../../../lin-ui/button/index",
"l-card": "../../../lin-ui/card/index",
"l-tag": "../../../lin-ui/tag/index",
"l-icon": "../../../lin-ui/icon/index",
"l-status-show": "../../../lin-ui/status-show/index",
"l-search-bar": "../../../lin-ui/search-bar/index",
"l-price": "../../../lin-ui/price/index",
"divider": "../../../components/divider/index",
"fab": "../../../components/fab/index",
"l-checkbox": "../../../lin-ui/checkbox/index",
"l-message": "../../../lin-ui/message/index"
}
}

View File

@ -0,0 +1,75 @@
/** index.wxss **/
@import "../../../config/styles/_base.less";
@import "../../../config/styles/_mixins.less";
page {
height: 100%;
background-color: @background-color-base;
}
.container {
height: 100%;
display: flex;
flex: 1;
flex-direction: column;
box-sizing: border-box;
align-items: stretch;
padding: 0;
.safe-area-inset-bottom();
}
.search-bar {
display: flex;
height: 40px;
background-color: #fff;
z-index: 1;
}
.col {
padding: @size-spacing-small;
display: flex;
flex-direction: column;
}
.row {
display: flex;
flex-wrap: wrap;
align-items: center;
}
.title {
font-size: @size-font-base;
margin-bottom: @size-spacing-small;
}
.drawer-view {
position: fixed;
top: 40px;
width: 100%;
background-color: @background-color-base;
}
.drawer-item {
display: flex;
align-items: center;
height: 38px;
color: @text-color;
margin-top: 1px;
padding: 0rpx @size-spacing-small;
background-color: #fff;
}
.search-value {
color: @error-color;
}
.null {
text-align: center;
}
.delete-btn {
padding: @size-spacing-small;
font-size: @size-font-base;
display: flex;
justify-content: center;
align-items: center;
color: @default-color;
}
.tag {
margin: 4rpx;
}

View File

@ -0,0 +1,217 @@
export default OakPage(
{
path: 'userSearch:search',
entity: 'user',
projection: {
id: 1,
name: 1,
nickname: 1,
mobile$user: {
$entity: 'mobile',
data: {
id: 1,
userId: 1,
mobile: 1,
},
},
},
filters: [
{
filter: {
id: {
$in: {
entity: 'mobile',
data: {
userId: 1,
},
filter: {
mobile: {
$eq: '11111111112',
}
}
}
}
},
'#name': 'userSearch'
}
],
isList: true,
formData: async function ({ data: users, params, features }) {
const { searchValue, go } = this.data;
go && this.goPage(users);
const isRoot = await features.token.isRoot();
let nodeStr = '';
const userIds: Array<string> = [];
if (users.length) {
for (let i = 0; i < users.length; i++) {
userIds.push(users[i].id);
const { mobile$user, name } = users[i] || {};
let itemStr: String = name || '';
const mobile = mobile$user && mobile$user[0]?.mobile;
if (!mobile && !name) {
continue;
}
if (mobile) {
itemStr += " " + mobile;
}
const itemStr2 = itemStr.replace(searchValue, `<span class='search-value'>${searchValue}</span>`)
nodeStr += `<div class="drawer-item" bind:tap="itemClick"><span>${itemStr2}</span></divider>`
}
}
return {
users,
userIds,
nodeStr,
isRoot,
showList: !!userIds.length
};
},
properties: {
toUrl: String,
},
data: {
go: false,
showList: false,
},
lifetimes: {
ready() {
const searchStr = wx.getStorageSync('user_searchList') as string;
if (searchStr.length) {
this.setState({
searchArr: JSON.parse(searchStr),
})
}
}
},
methods: {
setFilter(value: string) {
this.addNamedFilter({
filter: {
$or: [
{
name: {
$includes: value!,
},
},
{
id: {
$in: {
entity: 'mobile',
data: {
userId: 1,
},
filter: {
mobile: {
$includes: value!,
}
}
}
}
}
],
},
'#name': 'userSearch',
});
},
goPage(data: any) {
const { toUrl } = this.data;
const userIds = data?.map((ele: any) => ele.id);
this.navigateTo({
url: toUrl,
userIds,
});
this.setState({
go: false,
})
},
tagClick(event: any) {
const { value } = event.currentTarget.dataset;
this.setFilter(value);
this.setState({
go: true,
})
this.refresh();
},
itemClick(event: any) {
//由于rich-text屏蔽了所有子节点的事件所以这里根据触摸点进行判断
//搜索栏高度40px 每个可点击项38px
const { toUrl, searchValue, userIds } = this.data;
const { pageY } = event.touches[0];
const index = Math.floor((pageY - 40) / 38);
if (index + 1 > userIds.length) {
this.setState({
showList: false,
})
return;
}
const searchStr = wx.getStorageSync('user_searchList') as string;
let searchArr: Array<string> = [];
if (!searchStr) {
searchArr.push(searchValue)
}
else {
searchArr = JSON.parse(searchStr) as Array<string>;
if (!searchArr.includes(searchValue)) {
searchArr.push(searchValue);
}
}
wx.setStorageSync('user_searchList', JSON.stringify(searchArr));
this.navigateTo({
url: toUrl,
userIds: userIds[index],
})
},
clearSearchHistory() {
this.setState({
searchArr: [],
});
wx.setStorageSync('user_searchList', '');
},
async searchChange(input: any) {
const { value } = this.resolveInput(input);
if (!value) {
this.setState({
searchValue: value,
showList: false,
})
return;
}
this.setFilter(value);
this.setState({
searchValue: value,
})
this.refresh();
},
async searchCancel() {
this.setState({
searchValue: '',
showList: false,
})
},
async searchConfirm(input: any) {
const { value } = this.resolveInput(input);
const searchStr = wx.getStorageSync('user_searchList') as string;
let searchArr: Array<string> = [];
if (!searchStr) {
searchArr.push(value)
this.setState({
searchArr,
})
}
else {
searchArr = JSON.parse(searchStr) as Array<string>;
if (!searchArr.includes(value)) {
searchArr.push(value);
}
this.setState({
searchArr,
})
}
wx.setStorageSync('user_searchList', JSON.stringify(searchArr));
this.setFilter(value);
this.refresh();
},
},
}
);

View File

@ -0,0 +1,23 @@
<!-- index.wxml -->
<view class="container">
<view class="search-bar">
<l-search-bar style="width: 100%; margin: auto 0rpx" placeholder="输入手机号/姓名" shape="circle" value="{{searchValue}}" bind:lincancel="searchCancel" bind:linclear="searchCancel" bind:linchange="searchChange" bind:linconfirm="goPage" />
</view>
<block wx:if="{{showList}}">
<view class="drawer-view">
<rich-text nodes="{{nodeStr}}" bind:tap="itemClick"></rich-text>
</view>
</block>
<view wx:if="{{searchArr.length}}" class="col">
<text class="title">搜索历史</text>
<view class="row">
<l-tag wx:for="{{searchArr}}" bind:tap="tagClick" wx:key="index" wx:for-item="searchItem" class="tag" data-value="searchItem">
{{searchItem}}
</l-tag>
</view>
<view class="delete-btn" bind:tap="clearSearchHistory">
<l-icon name="delete" size="28"></l-icon>
<text style="margin-left: 4px">清空搜索历史</text>
</view>
</view>
</view>

View File

@ -1,5 +1,5 @@
/** index.wxss **/
@import "../../../styles/base.less";
@import "../../../config/_base.less";
@import "../../../styles/mixins.less";
.page-body {

View File

@ -1,5 +1,5 @@
/** index.wxss **/
@import "../../../styles/base.less";
@import "../../../config/_base.less";
@import "../../../styles/mixins.less";
.page-body {