uni-oaview 1.0.28 → 1.0.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/oa-area-select/oa-area-select.vue +50 -0
- package/components/oa-area-select/util.ts +15 -0
- package/components/oa-area-select-popup/index.d.ts +1 -0
- package/components/oa-area-select-popup/oa-area-select-popup.vue +156 -0
- package/components/oa-area-select-popup/region-data.ts +38 -0
- package/components/oa-multiple-select/oa-multiple-select.vue +54 -0
- package/components/oa-multiple-select-popup/oa-multiple-select-popup.vue +108 -0
- package/components/oa-page/loading-bar.vue +35 -0
- package/components/oa-page/oa-page.vue +1 -1
- package/components/oa-popup/oa-popup.vue +44 -0
- package/components/oa-select/oa-select.vue +69 -0
- package/components/oa-select-popup/oa-select-popup.vue +132 -0
- package/components/oa-single-select/oa-single-select.vue +22 -13
- package/dist/index.esm.js +32 -0
- package/imgs/icon_add.svg +10 -0
- package/package.json +5 -2
- package/dist/index.umd.js +0 -40
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<view v-bind="$attrs" class="oa-area-select" @click="() => (popupShow = true)">
|
|
3
|
+
<view class="oa-area-select-content">{{ currentLabel }}</view>
|
|
4
|
+
<uni-icons style="margin-left: 10px" type="forward" size="20" :color="'#ADB2B6'"></uni-icons>
|
|
5
|
+
</view>
|
|
6
|
+
<oa-area-select-popup
|
|
7
|
+
:title="title"
|
|
8
|
+
v-model:show="popupShow"
|
|
9
|
+
:modelValue="modelValue"
|
|
10
|
+
@update:model-value="($event:any) => emit('update:modelValue', $event)"
|
|
11
|
+
@change="changeHandler"
|
|
12
|
+
></oa-area-select-popup>
|
|
13
|
+
</template>
|
|
14
|
+
<script lang="ts" setup>
|
|
15
|
+
import { ref, watchEffect, nextTick } from 'vue';
|
|
16
|
+
import OaAreaSelectPopup from '../oa-area-select-popup/oa-area-select-popup.vue';
|
|
17
|
+
import { getCascaderNameByIds } from './util';
|
|
18
|
+
import regionData from '../oa-area-select-popup/region-data';
|
|
19
|
+
const props = defineProps<{
|
|
20
|
+
title?: string;
|
|
21
|
+
modelValue?: string[];
|
|
22
|
+
}>();
|
|
23
|
+
const popupShow = ref(false);
|
|
24
|
+
const currentLabel = ref('');
|
|
25
|
+
watchEffect(() => {
|
|
26
|
+
if (props.modelValue) {
|
|
27
|
+
currentLabel.value = getCascaderNameByIds(props.modelValue, regionData);
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
const emit = defineEmits(['change', 'update:modelValue']);
|
|
31
|
+
const changeHandler = () => {
|
|
32
|
+
setTimeout(() => {
|
|
33
|
+
emit('change', currentLabel.value);
|
|
34
|
+
});
|
|
35
|
+
};
|
|
36
|
+
</script>
|
|
37
|
+
<style lang="scss" scoped>
|
|
38
|
+
.oa-area-select {
|
|
39
|
+
display: flex;
|
|
40
|
+
align-items: center;
|
|
41
|
+
justify-content: space-between;
|
|
42
|
+
& > .oa-area-select-content {
|
|
43
|
+
flex: 1;
|
|
44
|
+
display: flex;
|
|
45
|
+
align-items: center;
|
|
46
|
+
justify-content: flex-end;
|
|
47
|
+
font-size: 16px;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
</style>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** 通过值得到级联选项的name,针对级联单选 */
|
|
2
|
+
export const getCascaderNameByIds = (ids: string[], options: any[]) => {
|
|
3
|
+
let children = options;
|
|
4
|
+
ids = ids.slice();
|
|
5
|
+
const locations = [];
|
|
6
|
+
while (ids.length) {
|
|
7
|
+
const id = ids.shift();
|
|
8
|
+
const item = children.find((item) => item.value === id);
|
|
9
|
+
if (item) {
|
|
10
|
+
locations.push(item.label);
|
|
11
|
+
children = item.children;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
return locations.join('/');
|
|
15
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
declare module 'element-china-area-data';
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<oa-popup :model-value="show" mode="bottom" @close="closeHandler" :is-mask-click="false">
|
|
3
|
+
<view class="button-box">
|
|
4
|
+
<view class="button-box-left" @click="emit('update:show', false)">取消</view>
|
|
5
|
+
<view class="button-box-center">{{ title }}</view>
|
|
6
|
+
<view class="button-box-right" @click="submit">确定</view>
|
|
7
|
+
</view>
|
|
8
|
+
<view class="search-box">
|
|
9
|
+
<view class="search-box-item">
|
|
10
|
+
<picker-view indicator-style="height: 40px;" :value="state" @change="bindChange" class="picker-view">
|
|
11
|
+
<picker-view-column style="flex-basis: 30%">
|
|
12
|
+
<view class="item" v-for="item in provinceList" :key="item.value">
|
|
13
|
+
{{ item.label }}
|
|
14
|
+
</view>
|
|
15
|
+
</picker-view-column>
|
|
16
|
+
<picker-view-column style="flex-basis: 15%">
|
|
17
|
+
<view class="item" v-for="item in cityList" :key="item.value">{{ item.label }}</view>
|
|
18
|
+
</picker-view-column>
|
|
19
|
+
<picker-view-column style="flex-basis: 40%">
|
|
20
|
+
<view class="item" v-for="item in areaList" :key="item.value">{{ item.label }}</view>
|
|
21
|
+
</picker-view-column>
|
|
22
|
+
</picker-view>
|
|
23
|
+
</view>
|
|
24
|
+
</view>
|
|
25
|
+
</oa-popup>
|
|
26
|
+
</template>
|
|
27
|
+
|
|
28
|
+
<script lang="ts" setup>
|
|
29
|
+
import { ref, watch } from 'vue';
|
|
30
|
+
import { useDebounceFn } from '@vueuse/core';
|
|
31
|
+
import regionData from './region-data';
|
|
32
|
+
import OaPopup from '../oa-popup/oa-popup.vue';
|
|
33
|
+
|
|
34
|
+
const props = defineProps<{
|
|
35
|
+
modelValue?: string[];
|
|
36
|
+
title?: string;
|
|
37
|
+
show: boolean;
|
|
38
|
+
}>();
|
|
39
|
+
const state = ref([0, 0, 0]);
|
|
40
|
+
const provinceList = ref<any[]>(regionData);
|
|
41
|
+
const cityList = ref<any[]>([]);
|
|
42
|
+
const areaList = ref<any[]>([]);
|
|
43
|
+
const init = () => {
|
|
44
|
+
provinceList.value = regionData;
|
|
45
|
+
if (props.modelValue?.length) {
|
|
46
|
+
const [province, city, area] = props.modelValue;
|
|
47
|
+
cityList.value = provinceList.value.find(({ value }) => value === province)?.children ?? [
|
|
48
|
+
{ value: 'city-empty', label: '' },
|
|
49
|
+
];
|
|
50
|
+
areaList.value = cityList.value?.find(({ value }) => value === city)?.children ?? [
|
|
51
|
+
{ value: 'area-empty', label: '' },
|
|
52
|
+
];
|
|
53
|
+
state.value = [provinceList.value.findIndex((item) => item.value === province)];
|
|
54
|
+
if (city) {
|
|
55
|
+
state.value.push(cityList.value.findIndex((item) => item.value === city));
|
|
56
|
+
} else {
|
|
57
|
+
state.value.push(0);
|
|
58
|
+
}
|
|
59
|
+
if (area) {
|
|
60
|
+
state.value.push(areaList.value.findIndex((item) => item.value === area));
|
|
61
|
+
} else {
|
|
62
|
+
state.value.push(0);
|
|
63
|
+
}
|
|
64
|
+
} else {
|
|
65
|
+
cityList.value = provinceList.value?.[0]?.children ?? [{ value: 'city-empty', label: '' }];
|
|
66
|
+
areaList.value = cityList.value?.[0]?.children ?? [{ value: 'area-empty', label: '' }];
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
const emit = defineEmits(['change', 'update:modelValue', 'colse', 'update:show']);
|
|
70
|
+
const closeHandler = () => {
|
|
71
|
+
emit('update:show', false);
|
|
72
|
+
emit('colse');
|
|
73
|
+
};
|
|
74
|
+
watch(
|
|
75
|
+
() => props.show,
|
|
76
|
+
(val) => {
|
|
77
|
+
if (val) {
|
|
78
|
+
init();
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
{ immediate: true },
|
|
82
|
+
);
|
|
83
|
+
const submit = () => {
|
|
84
|
+
const data = [provinceList.value[state.value[0]].value];
|
|
85
|
+
if (cityList.value[state.value[1]].value !== 'city-empty') {
|
|
86
|
+
data.push(cityList.value[state.value[1]].value);
|
|
87
|
+
}
|
|
88
|
+
if (areaList.value[state.value[2]].value !== 'area-empty') {
|
|
89
|
+
data.push(areaList.value[state.value[2]].value);
|
|
90
|
+
}
|
|
91
|
+
emit('update:show', false);
|
|
92
|
+
emit('update:modelValue', data);
|
|
93
|
+
emit('change', data);
|
|
94
|
+
};
|
|
95
|
+
const bindChange = useDebounceFn((e: any) => {
|
|
96
|
+
state.value = e.detail.value; // 当前选中的省/市/区的索引值
|
|
97
|
+
const selectedProvince = provinceList.value[state.value[0]]; // 获取当前选中的省数据
|
|
98
|
+
const selectedCity = selectedProvince?.children?.[state.value[1]]; // 获取当前选中的市数据
|
|
99
|
+
cityList.value = selectedProvince?.children || [{ value: 'city-empty', label: '' }]; // 根据新的省数据重新赋值市数据
|
|
100
|
+
areaList.value = selectedCity?.children || [{ value: 'area-empty', label: '' }]; // 根据新的市数据重新赋值区数据
|
|
101
|
+
}, 200);
|
|
102
|
+
</script>
|
|
103
|
+
|
|
104
|
+
<style lang="scss" scoped>
|
|
105
|
+
.button-box {
|
|
106
|
+
display: flex;
|
|
107
|
+
justify-content: space-between;
|
|
108
|
+
font-size: 14px;
|
|
109
|
+
height: 58px;
|
|
110
|
+
text-align: center;
|
|
111
|
+
line-height: 36px;
|
|
112
|
+
margin: 10px 20rpx 0;
|
|
113
|
+
&-left {
|
|
114
|
+
height: 36px;
|
|
115
|
+
font-size: 16px;
|
|
116
|
+
color: #909193;
|
|
117
|
+
}
|
|
118
|
+
&-center {
|
|
119
|
+
height: 36px;
|
|
120
|
+
font-size: 16px;
|
|
121
|
+
color: #19242c;
|
|
122
|
+
}
|
|
123
|
+
&-right {
|
|
124
|
+
height: 36px;
|
|
125
|
+
font-size: 16px;
|
|
126
|
+
color: #119af5;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
.search-box {
|
|
130
|
+
padding: 12px 24rpx 0;
|
|
131
|
+
&-item {
|
|
132
|
+
margin: 6px 12rpx;
|
|
133
|
+
overflow: hidden;
|
|
134
|
+
&-title {
|
|
135
|
+
height: 20px;
|
|
136
|
+
line-height: 20px;
|
|
137
|
+
font-size: 14px;
|
|
138
|
+
color: #333333;
|
|
139
|
+
}
|
|
140
|
+
.picker-view {
|
|
141
|
+
width: 100%;
|
|
142
|
+
height: 200px;
|
|
143
|
+
.flex-two {
|
|
144
|
+
flex: 2;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
.item {
|
|
148
|
+
height: 40px;
|
|
149
|
+
line-height: 40px;
|
|
150
|
+
align-items: center;
|
|
151
|
+
justify-content: center;
|
|
152
|
+
text-align: center;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
</style>
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { regionData } from 'element-china-area-data';
|
|
2
|
+
|
|
3
|
+
const topRegions = [
|
|
4
|
+
'110000', // 北京市
|
|
5
|
+
'120000', // 天津市
|
|
6
|
+
'310000', // 上海市
|
|
7
|
+
'500000', // 重庆市
|
|
8
|
+
'810000', // 香港特别行政区"
|
|
9
|
+
'820000', // 澳门特别行政区
|
|
10
|
+
];
|
|
11
|
+
|
|
12
|
+
// 移除顶级地区的详细辖区
|
|
13
|
+
topRegions.forEach((key) => {
|
|
14
|
+
const region = regionData.find(({ value: code }: any) => code === key);
|
|
15
|
+
delete region.children;
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
// 移除区(西湖区),保留县(淳安县)
|
|
19
|
+
regionData.forEach(({ children }: any) => {
|
|
20
|
+
if (!children) return;
|
|
21
|
+
children.forEach((city: any) => {
|
|
22
|
+
const { children } = city;
|
|
23
|
+
if (!children) return;
|
|
24
|
+
city.children = children.filter(({ label: name }: any) => !name.endsWith('区'));
|
|
25
|
+
if (!city.children.length) {
|
|
26
|
+
delete city.children;
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
// 禁用省份选择,只允许选择市/县(排除 topRegions 后)
|
|
32
|
+
regionData.forEach((data: any) => {
|
|
33
|
+
if (!topRegions.includes(data.value)) {
|
|
34
|
+
data.disabled = true;
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
export default regionData;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<view v-bind="$attrs" class="oa-multiple-select">
|
|
3
|
+
<view class="oa-multiple-select-content">
|
|
4
|
+
<text style="font-size: 16px; color: #61696f">费用归口部门</text>
|
|
5
|
+
<image
|
|
6
|
+
src="../../imgs/icon_add.svg"
|
|
7
|
+
style="width: 20px; height: 20px; padding: 0 5px 0 0"
|
|
8
|
+
@click="() => (popupShow = true)"
|
|
9
|
+
/>
|
|
10
|
+
</view>
|
|
11
|
+
</view>
|
|
12
|
+
<oa-multiple-select-popup
|
|
13
|
+
:labelKey="labelKey"
|
|
14
|
+
:valueKey="valueKey"
|
|
15
|
+
:title="title"
|
|
16
|
+
v-model:show="popupShow"
|
|
17
|
+
:modelValue="modelValue"
|
|
18
|
+
@update:model-value="($event:any) => emit('update:modelValue', $event)"
|
|
19
|
+
:options="options"
|
|
20
|
+
@change="changeHandler"
|
|
21
|
+
></oa-multiple-select-popup>
|
|
22
|
+
</template>
|
|
23
|
+
|
|
24
|
+
<script lang="ts" setup>
|
|
25
|
+
import { ref } from 'vue';
|
|
26
|
+
import OaMultipleSelectPopup from '../oa-multiple-select-popup/oa-multiple-select-popup.vue';
|
|
27
|
+
defineProps<{
|
|
28
|
+
/** 标题 */
|
|
29
|
+
title?: string;
|
|
30
|
+
modelValue: any[];
|
|
31
|
+
options: Array<any>;
|
|
32
|
+
labelKey?: string;
|
|
33
|
+
valueKey?: string;
|
|
34
|
+
/** 是否需要formItem的label,针对表单校验场合 */
|
|
35
|
+
formItemLabel?: string;
|
|
36
|
+
}>();
|
|
37
|
+
const popupShow = ref(false);
|
|
38
|
+
const emit = defineEmits(['change', 'close', 'update:modelValue']);
|
|
39
|
+
const changeHandler = (val: any) => {
|
|
40
|
+
emit('change', val);
|
|
41
|
+
};
|
|
42
|
+
</script>
|
|
43
|
+
<style scoped lang="scss">
|
|
44
|
+
.oa-multiple-select {
|
|
45
|
+
& > .oa-multiple-select-content {
|
|
46
|
+
margin-top: 5px;
|
|
47
|
+
flex: 1;
|
|
48
|
+
display: flex;
|
|
49
|
+
align-items: center;
|
|
50
|
+
justify-content: space-between;
|
|
51
|
+
font-size: 16px;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
</style>
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<oa-popup :model-value="show" mode="bottom" @close="closeHandler" :is-mask-click="false">
|
|
3
|
+
<view class="button-box">
|
|
4
|
+
<view class="button-box-left" @click="closeHandler">取消</view>
|
|
5
|
+
<view class="button-box-center">{{ title }}</view>
|
|
6
|
+
<view class="button-box-right" @click="submit">
|
|
7
|
+
确定
|
|
8
|
+
<text v-if="innerModelValue?.length">({{ innerModelValue?.length }})</text>
|
|
9
|
+
</view>
|
|
10
|
+
</view>
|
|
11
|
+
<view class="content-box">
|
|
12
|
+
<view @click="clickHandler(item)" class="content-item" v-for="item in options" :key="item[valueKey ?? 'value']">
|
|
13
|
+
<uni-icons
|
|
14
|
+
class="content-item-icon"
|
|
15
|
+
:type="innerModelValue?.includes(item[valueKey ?? 'value']) ? 'checkbox-filled' : 'circle'"
|
|
16
|
+
size="25"
|
|
17
|
+
:color="innerModelValue?.includes(item[valueKey ?? 'value']) ? '#259af5' : '#c5cace'"
|
|
18
|
+
></uni-icons>
|
|
19
|
+
<text class="content-item-text" style="margin-left: 8px">{{ item[labelKey ?? 'label'] }}</text>
|
|
20
|
+
</view>
|
|
21
|
+
</view>
|
|
22
|
+
</oa-popup>
|
|
23
|
+
</template>
|
|
24
|
+
|
|
25
|
+
<script lang="ts" setup>
|
|
26
|
+
import { ref, watch } from 'vue';
|
|
27
|
+
import OaPopup from '../oa-popup/oa-popup.vue';
|
|
28
|
+
const props = defineProps<{
|
|
29
|
+
/** 标题 */
|
|
30
|
+
title?: string;
|
|
31
|
+
/** 值,数组 */
|
|
32
|
+
modelValue: (string | number)[];
|
|
33
|
+
/** 弹窗显示 */
|
|
34
|
+
show: boolean;
|
|
35
|
+
options: Array<any>;
|
|
36
|
+
labelKey?: string;
|
|
37
|
+
valueKey?: string;
|
|
38
|
+
}>();
|
|
39
|
+
const innerModelValue = ref<(string | number)[]>([]);
|
|
40
|
+
watch([() => props.modelValue, () => props.show], () => {
|
|
41
|
+
innerModelValue.value = props.modelValue;
|
|
42
|
+
});
|
|
43
|
+
const emit = defineEmits(['change', 'update:modelValue', 'colse', 'update:show']);
|
|
44
|
+
const submit = () => {
|
|
45
|
+
emit('update:modelValue', innerModelValue.value);
|
|
46
|
+
emit(
|
|
47
|
+
'change',
|
|
48
|
+
props.options.map((item) => innerModelValue.value.includes(item[props.valueKey ?? 'value'])),
|
|
49
|
+
);
|
|
50
|
+
emit('update:show', false);
|
|
51
|
+
};
|
|
52
|
+
const closeHandler = () => {
|
|
53
|
+
emit('update:show', false);
|
|
54
|
+
emit('colse');
|
|
55
|
+
};
|
|
56
|
+
const clickHandler = (item: any) => {
|
|
57
|
+
const index = innerModelValue.value?.findIndex((i) => i === item[props.valueKey ?? 'value']);
|
|
58
|
+
if (index === -1) {
|
|
59
|
+
innerModelValue.value = [...innerModelValue.value, item[props.valueKey ?? 'value']];
|
|
60
|
+
} else {
|
|
61
|
+
innerModelValue.value = innerModelValue.value.filter((i) => i !== item[props.valueKey ?? 'value']);
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
</script>
|
|
65
|
+
<style scoped lang="scss">
|
|
66
|
+
.button-box {
|
|
67
|
+
display: flex;
|
|
68
|
+
justify-content: space-between;
|
|
69
|
+
font-size: 14px;
|
|
70
|
+
height: 58px;
|
|
71
|
+
text-align: center;
|
|
72
|
+
line-height: 36px;
|
|
73
|
+
margin: 10px 10px 0 10px;
|
|
74
|
+
&-left {
|
|
75
|
+
cursor: pointer;
|
|
76
|
+
height: 36px;
|
|
77
|
+
font-size: 16px;
|
|
78
|
+
color: #909193;
|
|
79
|
+
}
|
|
80
|
+
&-center {
|
|
81
|
+
height: 36px;
|
|
82
|
+
font-size: 16px;
|
|
83
|
+
color: #19242c;
|
|
84
|
+
}
|
|
85
|
+
&-right {
|
|
86
|
+
cursor: pointer;
|
|
87
|
+
height: 36px;
|
|
88
|
+
font-size: 16px;
|
|
89
|
+
color: #119af5;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
.content-box {
|
|
93
|
+
height: 300px;
|
|
94
|
+
overflow-y: auto;
|
|
95
|
+
& > .content-item {
|
|
96
|
+
height: 54px;
|
|
97
|
+
display: flex;
|
|
98
|
+
align-items: center;
|
|
99
|
+
border-top: 1px solid #eceef0;
|
|
100
|
+
padding: 0 16px;
|
|
101
|
+
& > .content-item-text {
|
|
102
|
+
color: #19242c;
|
|
103
|
+
font-family: PingFang SC;
|
|
104
|
+
font-size: 16px;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
</style>
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<view class="loading-bar">
|
|
3
|
+
<view class="loading-bar-inner"></view>
|
|
4
|
+
</view>
|
|
5
|
+
</template>
|
|
6
|
+
|
|
7
|
+
<script lang="ts" setup></script>
|
|
8
|
+
<style scoped lang="scss">
|
|
9
|
+
.loading-bar {
|
|
10
|
+
position: fixed;
|
|
11
|
+
top: 0;
|
|
12
|
+
left: 0;
|
|
13
|
+
width: 100%;
|
|
14
|
+
height: 2px;
|
|
15
|
+
background-color: #ddd;
|
|
16
|
+
z-index: 9999;
|
|
17
|
+
overflow: hidden;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.loading-bar-inner {
|
|
21
|
+
width: 100px;
|
|
22
|
+
height: 100%;
|
|
23
|
+
background-color: #7acfaa;
|
|
24
|
+
animation: loading-bar-animation 1s linear infinite;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
@keyframes loading-bar-animation {
|
|
28
|
+
0% {
|
|
29
|
+
transform: translateX(0);
|
|
30
|
+
}
|
|
31
|
+
100% {
|
|
32
|
+
transform: translateX(100vw);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
</style>
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<uni-popup :background-color="backgroundColor" v-bind="$attrs" ref="popupRef" @change="changeHandler">
|
|
3
|
+
<slot />
|
|
4
|
+
</uni-popup>
|
|
5
|
+
</template>
|
|
6
|
+
|
|
7
|
+
<script lang="ts" setup>
|
|
8
|
+
import type { UniPopupType } from 'uni-ui-types';
|
|
9
|
+
import { watch, ref, PropType, nextTick } from 'vue';
|
|
10
|
+
const popupRef = ref();
|
|
11
|
+
const props = defineProps({
|
|
12
|
+
modelValue: {
|
|
13
|
+
type: Boolean,
|
|
14
|
+
default: false,
|
|
15
|
+
},
|
|
16
|
+
type: {
|
|
17
|
+
type: String as PropType<UniPopupType>,
|
|
18
|
+
default: 'bottom',
|
|
19
|
+
},
|
|
20
|
+
backgroundColor: {
|
|
21
|
+
type: String as PropType<any>,
|
|
22
|
+
default: 'white',
|
|
23
|
+
},
|
|
24
|
+
});
|
|
25
|
+
watch(
|
|
26
|
+
() => props.modelValue,
|
|
27
|
+
(newV) => {
|
|
28
|
+
if (newV) {
|
|
29
|
+
nextTick(() => {
|
|
30
|
+
popupRef.value?.open(props.type ?? 'bottom');
|
|
31
|
+
});
|
|
32
|
+
} else {
|
|
33
|
+
popupRef.value?.close();
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
immediate: true,
|
|
38
|
+
},
|
|
39
|
+
);
|
|
40
|
+
const emit = defineEmits(['update:modelValue']);
|
|
41
|
+
const changeHandler = (e: { show: boolean; type: UniPopupType }) => {
|
|
42
|
+
emit('update:modelValue', e.show);
|
|
43
|
+
};
|
|
44
|
+
</script>
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<view v-bind="$attrs" class="oa-select" @click="() => (popupShow = true)">
|
|
3
|
+
<view class="oa-select-content">
|
|
4
|
+
<text v-if="modelValue || modelValue === 0">
|
|
5
|
+
{{ currentLabel }}
|
|
6
|
+
</text>
|
|
7
|
+
<text v-else class="oa-select-placeholder">{{ $attrs.placeholder ?? '请选择' }}</text>
|
|
8
|
+
</view>
|
|
9
|
+
<uni-icons style="margin-left: 10px" type="forward" size="20" :color="'#ADB2B6'"></uni-icons>
|
|
10
|
+
</view>
|
|
11
|
+
<oa-select-popup
|
|
12
|
+
:labelKey="labelKey"
|
|
13
|
+
:valueKey="valueKey"
|
|
14
|
+
:title="title"
|
|
15
|
+
v-model:show="popupShow"
|
|
16
|
+
:modelValue="modelValue"
|
|
17
|
+
@update:model-value="($event) => emit('update:modelValue', $event)"
|
|
18
|
+
:options="options"
|
|
19
|
+
@change="changeHandler"
|
|
20
|
+
>
|
|
21
|
+
<!-- 透传作用域插槽内容到孙子组件 -->
|
|
22
|
+
<template v-slot:default="slotProps">
|
|
23
|
+
<slot v-bind="slotProps"></slot>
|
|
24
|
+
</template>
|
|
25
|
+
</oa-select-popup>
|
|
26
|
+
</template>
|
|
27
|
+
<script lang="ts" setup>
|
|
28
|
+
import { ref, watchEffect } from 'vue';
|
|
29
|
+
import OaSelectPopup from '../oa-select-popup/oa-select-popup.vue';
|
|
30
|
+
const props = defineProps<{
|
|
31
|
+
title?: string;
|
|
32
|
+
modelValue?: string | number;
|
|
33
|
+
options: Array<any>;
|
|
34
|
+
labelKey?: string;
|
|
35
|
+
valueKey?: string;
|
|
36
|
+
}>();
|
|
37
|
+
const popupShow = ref(false);
|
|
38
|
+
const currentLabel = ref('');
|
|
39
|
+
watchEffect(() => {
|
|
40
|
+
if (props.modelValue && props.options.length) {
|
|
41
|
+
currentLabel.value = props.options.find((item) => item[props.valueKey ?? 'value'] === props.modelValue)[
|
|
42
|
+
props.labelKey ?? 'label'
|
|
43
|
+
];
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
const emit = defineEmits(['change', 'close', 'update:modelValue']);
|
|
47
|
+
const changeHandler = (val: any) => {
|
|
48
|
+
emit('change', val);
|
|
49
|
+
};
|
|
50
|
+
</script>
|
|
51
|
+
<style lang="scss" scoped>
|
|
52
|
+
.oa-select {
|
|
53
|
+
display: flex;
|
|
54
|
+
align-items: center;
|
|
55
|
+
justify-content: space-between;
|
|
56
|
+
& > .oa-select-content {
|
|
57
|
+
flex: 1;
|
|
58
|
+
display: flex;
|
|
59
|
+
align-items: center;
|
|
60
|
+
justify-content: flex-end;
|
|
61
|
+
font-size: 16px;
|
|
62
|
+
& > .oa-select-placeholder {
|
|
63
|
+
font-size: 16px;
|
|
64
|
+
color: #c5cace;
|
|
65
|
+
font-weight: 300;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
</style>
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<oa-popup :model-value="show" mode="bottom" @close="closeHandler" :is-mask-click="false">
|
|
3
|
+
<view class="button-box">
|
|
4
|
+
<view class="button-box-left" @click="closeHandler">取消</view>
|
|
5
|
+
<view class="button-box-center">{{ title }}</view>
|
|
6
|
+
<view class="button-box-right" @click="submit">确定</view>
|
|
7
|
+
</view>
|
|
8
|
+
<view class="search-box">
|
|
9
|
+
<view class="search-box-item">
|
|
10
|
+
<picker-view :indicator-style="indicatorStyle" :value="indexList" @change="bindChange" class="picker-view">
|
|
11
|
+
<picker-view-column>
|
|
12
|
+
<slot :columns="options">
|
|
13
|
+
<view class="item" v-for="item in options" :key="item[valueKey ?? 'value']">
|
|
14
|
+
{{ item[labelKey ?? 'label'] }}
|
|
15
|
+
</view>
|
|
16
|
+
</slot>
|
|
17
|
+
</picker-view-column>
|
|
18
|
+
</picker-view>
|
|
19
|
+
</view>
|
|
20
|
+
</view>
|
|
21
|
+
</oa-popup>
|
|
22
|
+
</template>
|
|
23
|
+
<script lang="ts" setup>
|
|
24
|
+
import { ref, nextTick, watch } from 'vue';
|
|
25
|
+
import { useDebounceFn } from '@vueuse/core';
|
|
26
|
+
import OaPopup from '../oa-popup/oa-popup.vue';
|
|
27
|
+
const props = defineProps<{
|
|
28
|
+
/** 标题 */
|
|
29
|
+
title?: string;
|
|
30
|
+
/** 值,数组 */
|
|
31
|
+
modelValue?: string | number | string[] | number[];
|
|
32
|
+
/** 弹窗显示 */
|
|
33
|
+
show: boolean;
|
|
34
|
+
options: Array<any>;
|
|
35
|
+
labelKey?: string;
|
|
36
|
+
valueKey?: string;
|
|
37
|
+
}>();
|
|
38
|
+
const indicatorStyle = `height: 40px;`;
|
|
39
|
+
const emit = defineEmits(['change', 'update:modelValue', 'colse', 'update:show']);
|
|
40
|
+
const indexList = ref<number[]>([]);
|
|
41
|
+
const currentLabel = ref('');
|
|
42
|
+
watch(
|
|
43
|
+
[() => props.show, () => props.options],
|
|
44
|
+
() => {
|
|
45
|
+
if (props.show) {
|
|
46
|
+
indexList.value = [
|
|
47
|
+
Math.max(
|
|
48
|
+
0,
|
|
49
|
+
props.options.findIndex((item) => item[props.valueKey ?? 'value'] === props.modelValue),
|
|
50
|
+
),
|
|
51
|
+
];
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
{ immediate: true },
|
|
55
|
+
);
|
|
56
|
+
const bindChange = useDebounceFn((e: any) => {
|
|
57
|
+
const val = e.detail.value;
|
|
58
|
+
nextTick(() => {
|
|
59
|
+
indexList.value = val;
|
|
60
|
+
});
|
|
61
|
+
}, 200);
|
|
62
|
+
const submit = () => {
|
|
63
|
+
const val = indexList.value;
|
|
64
|
+
const newValue = props.options[val[0]];
|
|
65
|
+
currentLabel.value = newValue[props.labelKey ?? 'label'];
|
|
66
|
+
const currentValue = newValue[props.valueKey ?? 'value'];
|
|
67
|
+
emit('update:modelValue', currentValue);
|
|
68
|
+
emit('change', newValue);
|
|
69
|
+
emit('update:show', false);
|
|
70
|
+
};
|
|
71
|
+
const closeHandler = () => {
|
|
72
|
+
emit('update:show', false);
|
|
73
|
+
emit('colse');
|
|
74
|
+
};
|
|
75
|
+
</script>
|
|
76
|
+
<style lang="scss" scoped>
|
|
77
|
+
.button-box {
|
|
78
|
+
display: flex;
|
|
79
|
+
justify-content: space-between;
|
|
80
|
+
font-size: 14px;
|
|
81
|
+
height: 58px;
|
|
82
|
+
text-align: center;
|
|
83
|
+
line-height: 36px;
|
|
84
|
+
margin: 10px 10px 0 10px;
|
|
85
|
+
&-left {
|
|
86
|
+
cursor: pointer;
|
|
87
|
+
height: 36px;
|
|
88
|
+
font-size: 16px;
|
|
89
|
+
color: #909193;
|
|
90
|
+
}
|
|
91
|
+
&-center {
|
|
92
|
+
height: 36px;
|
|
93
|
+
font-size: 16px;
|
|
94
|
+
color: #19242c;
|
|
95
|
+
}
|
|
96
|
+
&-right {
|
|
97
|
+
cursor: pointer;
|
|
98
|
+
height: 36px;
|
|
99
|
+
font-size: 16px;
|
|
100
|
+
color: #119af5;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
.search-box {
|
|
104
|
+
padding: 12px 12px 0;
|
|
105
|
+
&-item {
|
|
106
|
+
margin: 6px;
|
|
107
|
+
overflow: hidden;
|
|
108
|
+
&-title {
|
|
109
|
+
height: 20px;
|
|
110
|
+
line-height: 20px;
|
|
111
|
+
font-size: 14px;
|
|
112
|
+
color: #333333;
|
|
113
|
+
}
|
|
114
|
+
.picker-view {
|
|
115
|
+
width: 100%;
|
|
116
|
+
height: 200px;
|
|
117
|
+
.flex-two {
|
|
118
|
+
flex: 2;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
.item {
|
|
122
|
+
height: 40px;
|
|
123
|
+
line-height: 40px;
|
|
124
|
+
align-items: center;
|
|
125
|
+
justify-content: center;
|
|
126
|
+
text-align: center;
|
|
127
|
+
color: #19242c;
|
|
128
|
+
font-size: 16px;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
</style>
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
</view>
|
|
22
22
|
</template>
|
|
23
23
|
<script lang="ts" setup>
|
|
24
|
-
import { ref, nextTick, watch
|
|
24
|
+
import { ref, nextTick, watch } from 'vue';
|
|
25
25
|
import { useDebounceFn } from '@vueuse/core';
|
|
26
26
|
const props = defineProps<{
|
|
27
27
|
title?: string;
|
|
@@ -36,9 +36,18 @@
|
|
|
36
36
|
const emit = defineEmits(['updateValue', 'close', 'update:modelValue']);
|
|
37
37
|
const indexList = ref<number[]>([]);
|
|
38
38
|
let currentValue: string;
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
39
|
+
watch(
|
|
40
|
+
[() => props.modelValue, () => props.value],
|
|
41
|
+
() => {
|
|
42
|
+
if (props.modelValue) {
|
|
43
|
+
currentValue = props.value as string;
|
|
44
|
+
init();
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
immediate: true,
|
|
49
|
+
},
|
|
50
|
+
);
|
|
42
51
|
const init = () => {
|
|
43
52
|
const index = Math.max(
|
|
44
53
|
0,
|
|
@@ -46,13 +55,13 @@
|
|
|
46
55
|
);
|
|
47
56
|
indexList.value = [index];
|
|
48
57
|
};
|
|
49
|
-
init();
|
|
50
58
|
const bindChange = useDebounceFn((e: any) => {
|
|
51
59
|
const val = e.detail.value;
|
|
52
60
|
nextTick(() => {
|
|
53
61
|
indexList.value = val;
|
|
54
62
|
});
|
|
55
63
|
}, 200);
|
|
64
|
+
init();
|
|
56
65
|
const submit = () => {
|
|
57
66
|
const val = indexList.value;
|
|
58
67
|
const newValue = props.columns[val[0]];
|
|
@@ -78,11 +87,11 @@
|
|
|
78
87
|
.button-box {
|
|
79
88
|
display: flex;
|
|
80
89
|
justify-content: space-between;
|
|
81
|
-
font-size:
|
|
90
|
+
font-size: 14px;
|
|
82
91
|
height: 58px;
|
|
83
92
|
text-align: center;
|
|
84
93
|
line-height: 36px;
|
|
85
|
-
margin:
|
|
94
|
+
margin: 10px 10px 0 10px;
|
|
86
95
|
&-left {
|
|
87
96
|
cursor: pointer;
|
|
88
97
|
height: 36px;
|
|
@@ -102,19 +111,19 @@
|
|
|
102
111
|
}
|
|
103
112
|
}
|
|
104
113
|
.search-box {
|
|
105
|
-
padding:
|
|
114
|
+
padding: 12px 12px 0;
|
|
106
115
|
&-item {
|
|
107
|
-
margin:
|
|
116
|
+
margin: 6px;
|
|
108
117
|
overflow: hidden;
|
|
109
118
|
&-title {
|
|
110
|
-
height:
|
|
111
|
-
line-height:
|
|
112
|
-
font-size:
|
|
119
|
+
height: 20px;
|
|
120
|
+
line-height: 20px;
|
|
121
|
+
font-size: 14px;
|
|
113
122
|
color: #333333;
|
|
114
123
|
}
|
|
115
124
|
.picker-view {
|
|
116
125
|
width: 100%;
|
|
117
|
-
height:
|
|
126
|
+
height: 200px;
|
|
118
127
|
.flex-two {
|
|
119
128
|
flex: 2;
|
|
120
129
|
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { reportLog } from 'uniapp-log-sdk';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 上报APP启动小程序的时候的入参
|
|
5
|
+
* @param params
|
|
6
|
+
*/
|
|
7
|
+
function sendLaunchAppParamsLog(params) {
|
|
8
|
+
var _a;
|
|
9
|
+
console.log('小程序启动入参:', params);
|
|
10
|
+
// #ifndef H5
|
|
11
|
+
try {
|
|
12
|
+
var outputData = JSON.parse(JSON.stringify((_a = params === null || params === void 0 ? void 0 : params.referrerInfo) === null || _a === void 0 ? void 0 : _a.extraData));
|
|
13
|
+
outputData === null || outputData === void 0 ? true : delete outputData.token;
|
|
14
|
+
reportLog(outputData, '小程序启动入参');
|
|
15
|
+
} catch (error) {
|
|
16
|
+
console.log(error);
|
|
17
|
+
}
|
|
18
|
+
// #endif
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
var install = function install(app) {
|
|
22
|
+
app.mixin({
|
|
23
|
+
onLaunch: function onLaunch(params) {
|
|
24
|
+
sendLaunchAppParamsLog(params);
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
};
|
|
28
|
+
var index = {
|
|
29
|
+
install: install
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export { index as default };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<svg width="20px" height="20px" viewBox="0 0 20 20" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
|
3
|
+
<title>icon(svg)/icon_add1</title>
|
|
4
|
+
<g id="icon(svg)/icon_add1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
|
5
|
+
<g id="Icon/线型/跳转备份-12">
|
|
6
|
+
<path d="M16.3636364,1.81818182 C17.3677905,1.81818182 18.1818182,2.63220955 18.1818182,3.63636364 L18.1818182,16.3636364 C18.1818182,17.3677905 17.3677905,18.1818182 16.3636364,18.1818182 L3.63636364,18.1818182 C2.63220955,18.1818182 1.81818182,17.3677905 1.81818182,16.3636364 L1.81818182,3.63636364 C1.81818182,2.63220955 2.63220955,1.81818182 3.63636364,1.81818182 L16.3636364,1.81818182 Z M16.3636364,3.18181818 L3.63636364,3.18181818 C3.38958,3.18181818 3.18873038,3.37848504 3.18199281,3.62364069 L3.18181818,3.63636364 L3.18181818,16.3636364 C3.18181818,16.61042 3.37848504,16.8112696 3.62364069,16.8180072 L3.63636364,16.8181818 L16.3636364,16.8181818 C16.61042,16.8181818 16.8112696,16.621515 16.8180072,16.3763593 L16.8181818,16.3636364 L16.8181818,3.63636364 C16.8181818,3.38958 16.621515,3.18873038 16.3763593,3.18199281 L16.3636364,3.18181818 Z M10,4.54545455 C10.3765578,4.54545455 10.6818182,4.85071494 10.6818182,5.22727273 L10.6817727,9.22727273 L14.7727273,9.22727273 C15.1492851,9.22727273 15.4545455,9.53253313 15.4545455,9.90909091 C15.4545455,10.2856487 15.1492851,10.5909091 14.7727273,10.5909091 L10.6817727,10.5909091 L10.6818182,14.7727273 C10.6818182,15.1492851 10.3765578,15.4545455 10,15.4545455 C9.62344222,15.4545455 9.31818182,15.1492851 9.31818182,14.7727273 L9.31813636,10.5909091 L5.22727273,10.5909091 C4.85071494,10.5909091 4.54545455,10.2856487 4.54545455,9.90909091 C4.54545455,9.53253313 4.85071494,9.22727273 5.22727273,9.22727273 L9.31813636,9.22727273 L9.31818182,5.22727273 C9.31818182,4.85071494 9.62344222,4.54545455 10,4.54545455 Z" id="形状" fill="#19242C" fill-rule="nonzero"></path>
|
|
7
|
+
<rect id="矩形备份-24" x="0" y="0" width="20" height="20"></rect>
|
|
8
|
+
</g>
|
|
9
|
+
</g>
|
|
10
|
+
</svg>
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "uni-oaview",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.30",
|
|
4
4
|
"description": "uniapp小程序组件库",
|
|
5
|
-
"main": "dist/index.
|
|
5
|
+
"main": "dist/index.esm.js",
|
|
6
6
|
"typings": "dist/index.d.ts",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
8
8
|
"files": [
|
|
@@ -54,5 +54,8 @@
|
|
|
54
54
|
"dayjs": "1.11.7",
|
|
55
55
|
"uniapp-log-sdk": "^1.1.1",
|
|
56
56
|
"uview-plus": "^3.1.30"
|
|
57
|
+
},
|
|
58
|
+
"dependencies": {
|
|
59
|
+
"element-china-area-data": "5.0.2"
|
|
57
60
|
}
|
|
58
61
|
}
|
package/dist/index.umd.js
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
(function (global, factory) {
|
|
2
|
-
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('uniapp-log-sdk')) :
|
|
3
|
-
typeof define === 'function' && define.amd ? define(['exports', 'uniapp-log-sdk'], factory) :
|
|
4
|
-
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global["UNI-OAVIEW"] = {}, global.uniappLogSdk));
|
|
5
|
-
})(this, (function (exports, uniappLogSdk) { 'use strict';
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* 上报APP启动小程序的时候的入参
|
|
9
|
-
* @param params
|
|
10
|
-
*/
|
|
11
|
-
function sendLaunchAppParamsLog(params) {
|
|
12
|
-
var _a;
|
|
13
|
-
console.log('小程序启动入参:', params);
|
|
14
|
-
// #ifndef H5
|
|
15
|
-
try {
|
|
16
|
-
var outputData = JSON.parse(JSON.stringify((_a = params === null || params === void 0 ? void 0 : params.referrerInfo) === null || _a === void 0 ? void 0 : _a.extraData));
|
|
17
|
-
outputData === null || outputData === void 0 ? true : delete outputData.token;
|
|
18
|
-
uniappLogSdk.reportLog(outputData, '小程序启动入参');
|
|
19
|
-
} catch (error) {
|
|
20
|
-
console.log(error);
|
|
21
|
-
}
|
|
22
|
-
// #endif
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
var install = function install(app) {
|
|
26
|
-
app.mixin({
|
|
27
|
-
onLaunch: function onLaunch(params) {
|
|
28
|
-
sendLaunchAppParamsLog(params);
|
|
29
|
-
}
|
|
30
|
-
});
|
|
31
|
-
};
|
|
32
|
-
var index = {
|
|
33
|
-
install: install
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
exports["default"] = index;
|
|
37
|
-
|
|
38
|
-
Object.defineProperty(exports, '__esModule', { value: true });
|
|
39
|
-
|
|
40
|
-
}));
|