@v2coding/ui 0.1.1 → 0.1.6

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.
@@ -0,0 +1,236 @@
1
+ <template>
2
+ <div class="ui-field-latlng" v-loading="loading">
3
+ <div class="map"></div>
4
+ <div class="info" v-show="!loading">
5
+ <div class="input-item searchbox">
6
+ <div class="input-item-prepend">
7
+ <span class="input-item-text">搜索关键字</span>
8
+ </div>
9
+ <!-- form="__ignore__" 避免 enter提交表单 -->
10
+ <input ref="input" type="text" form="__ignore__" placeholder="请输入...">
11
+ <div ref="output" class="search-result"></div>
12
+ </div>
13
+ </div>
14
+ </div>
15
+ </template>
16
+
17
+ <script>
18
+ import gcoord from 'gcoord';
19
+ import {getAMap} from '../../config/config.amap';
20
+ import FieldMixin from './field.mixin';
21
+
22
+ const CoordTypes = {
23
+ bd09: gcoord.BD09,
24
+ gcj02: gcoord.GCJ02,
25
+ wgs84: gcoord.WGS84,
26
+ };
27
+
28
+ export default {
29
+ name: 'ui-field-latlng',
30
+ mixins: [FieldMixin],
31
+ props: {
32
+ coordType: {
33
+ type: String,
34
+ default: 'wgs84',
35
+ validator: (val) => Object.keys(CoordTypes).includes(val),
36
+ },
37
+ },
38
+ data() {
39
+ return {
40
+ loading: true,
41
+ keyword: '',
42
+ };
43
+ },
44
+ computed: {
45
+ point() {
46
+ if (!this.value) {
47
+ return null;
48
+ }
49
+ if (!this.isValidPoint(this.value)) {
50
+ return null;
51
+ }
52
+ const [lat, lng] = this.value.split(',');
53
+ return {lat: +lat, lng: +lng};
54
+ },
55
+ },
56
+ watch: {
57
+ point(p) {
58
+ this.onPointChange(p);
59
+ },
60
+ },
61
+ methods: {
62
+ init() {
63
+ getAMap(['AMap.ToolBar', 'AMap.Geolocation', 'AMap.AutoComplete']).then((AMap) => {
64
+ this.initMap(AMap);
65
+ this.loading = false;
66
+ this.done();
67
+ });
68
+ },
69
+ initMap(AMap) {
70
+ const map = new AMap.Map(this.$el.querySelector('.map'), {
71
+ zoom: 11,
72
+ });
73
+
74
+ map.addControl(new AMap.ToolBar({position: 'RT'}));
75
+ map.addControl(new AMap.Geolocation({position: 'RB'}));
76
+ const auto = new AMap.AutoComplete({
77
+ input: this.$refs.input,
78
+ output: this.$refs.output,
79
+ });
80
+
81
+ map.on('click', this.onMapClick);
82
+ auto.on('select', (event) => {
83
+ if (!event.poi || !event.poi.location) {
84
+ return;
85
+ }
86
+ map.setZoomAndCenter(16, event.poi.location);
87
+ });
88
+
89
+ this.map = map;
90
+
91
+ this.onPointChange(this.point);
92
+ },
93
+ isValidPoint(val) {
94
+ const [lat, lng] = val.split(',');
95
+ return !(isNaN(+lat) || isNaN(+lng));
96
+ },
97
+ onMapClick({lnglat}) {
98
+ let {lat, lng} = lnglat;
99
+ // 当前地图是 GCJ02 坐标系
100
+ if (this.coordType !== 'gcj02') {
101
+ [lng, lat] = gcoord.transform([lng, lat], gcoord.GCJ02, CoordTypes[this.coordType]);
102
+ lng = lng.toFixed(7) / 1;
103
+ lat = lat.toFixed(7) / 1;
104
+ }
105
+ this.onChange([lat, lng].join(','));
106
+ },
107
+ onPointChange(point) {
108
+ if (!this.map) {
109
+ return;
110
+ }
111
+ this.map.clearMap();
112
+ if (!point) {
113
+ return;
114
+ }
115
+ let {lng, lat} = point;
116
+ // 当前地图是 GCJ02 坐标系
117
+ if (this.coordType !== 'gcj02') {
118
+ [lng, lat] = gcoord.transform([lng, lat], CoordTypes[this.coordType], gcoord.GCJ02);
119
+ }
120
+ // eslint-disable-next-line no-undef
121
+ const marker = new AMap.Marker({position: new AMap.LngLat(lng, lat)});
122
+ this.map.add(marker);
123
+ this.map.setCenter([lng, lat]);
124
+ },
125
+ },
126
+ };
127
+ </script>
128
+
129
+ <style lang="less">
130
+ .ui-field-latlng {
131
+ width: 100%;
132
+ height: 280px;
133
+ position: relative;
134
+
135
+ .map {
136
+ width: 100%;
137
+ height: 100%;
138
+ }
139
+
140
+ .info {
141
+ position: absolute;
142
+ top: 0;
143
+ left: 0;
144
+ right: 0;
145
+ bottom: 0;
146
+ pointer-events: none;
147
+
148
+ .searchbox {
149
+ left: 12px;
150
+ top: 12px;
151
+ background-color: #fff;
152
+ box-shadow: 0 0 3px rgba(0, 0, 0, .5);
153
+ pointer-events: initial;
154
+ border-radius: 3px;
155
+ padding: 3px;
156
+
157
+ .search-result {
158
+ position: absolute;
159
+ top: calc(100% - 2px);
160
+ left: 0;
161
+ right: 0;
162
+ background-color: #fefefe;
163
+ box-shadow: 0 1px 3px #999 ;
164
+ visibility: hidden;
165
+ border-radius: 0 0 3px 3px;
166
+
167
+ .auto-item {
168
+ white-space: nowrap;
169
+ font-size: 12px;
170
+ cursor: pointer;
171
+ padding: 4px;
172
+ line-height: 14px;
173
+ }
174
+ }
175
+ }
176
+ }
177
+
178
+ .input-item {
179
+ position: relative;
180
+ display: inline-flex;
181
+ align-items: center;
182
+ width: 220px;
183
+ font-size: 12px;
184
+
185
+ .input-item-prepend {
186
+ margin-right: -1px;
187
+
188
+ .input-item-text {
189
+ padding: 0.25em 0.5em;
190
+ display: block;
191
+ text-justify: distribute-all-lines;
192
+ text-align-last: justify;
193
+ align-items: center;
194
+ margin-bottom: 0;
195
+ font-weight: 400;
196
+ line-height: 1.5;
197
+ color: #495057;
198
+ text-align: center;
199
+ white-space: nowrap;
200
+ background-color: #e9ecef;
201
+ border: 1px solid #ced4da;
202
+ border-radius: .25rem 0 0 .25rem;
203
+ box-sizing: border-box;
204
+ }
205
+ }
206
+
207
+ input {
208
+ position: relative;
209
+ flex: 1 1 auto;
210
+ width: 1%;
211
+ margin: 0;
212
+ background: #fff;
213
+ padding: 0.25em 0.5em;
214
+ display: inline-block;
215
+ line-height: 1.5;
216
+ color: #495057;
217
+ vertical-align: middle;
218
+ border: 1px solid #ced4da;
219
+ border-radius: 0 .25rem .25rem 0;
220
+ appearance: none;
221
+ box-sizing: border-box;
222
+
223
+ &:focus {
224
+ border-color: #80bdff;
225
+ outline: 0;
226
+ box-shadow: 0 0 0 0.1rem rgba(128, 189, 255, .1);
227
+ }
228
+ }
229
+ }
230
+
231
+ .amap-logo,
232
+ .amap-copyright {
233
+ display: none !important;
234
+ }
235
+ }
236
+ </style>
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <div class="history" v-show="visible">
3
- <scroll-nav ref="menus" class="history-tabs">
3
+ <scroll-view ref="menus" class="history-tabs">
4
4
  <div
5
5
  v-for="item in items"
6
6
  :key="item.path"
@@ -10,7 +10,7 @@
10
10
  <span class="ellipsis" :title="item.title">{{ item.title }}</span>
11
11
  <i class="el-icon-close" @click.stop="onTabRemove(item.path)"></i>
12
12
  </div>
13
- </scroll-nav>
13
+ </scroll-view>
14
14
  <div class="contextmenu" :style="contextmenu">
15
15
  <div
16
16
  class="modal"
@@ -54,8 +54,11 @@
54
54
  </template>
55
55
 
56
56
  <script>
57
+ import ScrollView from '../scroll-view/scroll-view';
58
+
57
59
  export default {
58
- name: "History",
60
+ name: "ui-history",
61
+ components: {ScrollView},
59
62
  props: {
60
63
  items: Array,
61
64
  current: null,
@@ -106,7 +109,7 @@ export default {
106
109
  this.$emit("remove-history", { type: "current", name: path });
107
110
  },
108
111
  onContextMenu(event) {
109
- const container = this.$el.querySelector(".scroll-nav__nav");
112
+ const container = this.$el.querySelector(".ui-scroll-view__nav");
110
113
  const index = this.getChildContainIndex(container, event.target);
111
114
  const rect = this.$el.getBoundingClientRect();
112
115
  if (index !== -1) {
@@ -159,15 +162,13 @@ export default {
159
162
  </script>
160
163
 
161
164
  <style lang="scss">
162
- @import "../../assets/style/var";
163
-
164
165
  .history {
165
166
  flex: none;
166
167
  height: 40px;
167
168
  position: relative;
168
169
  margin: 10px 0 0;
169
170
 
170
- .history-tabs.scroll-nav__nav-wrap {
171
+ .history-tabs.ui-scroll-view__nav-wrap {
171
172
  left: 0;
172
173
  right: 0;
173
174
  top: 0;
@@ -175,11 +176,11 @@ export default {
175
176
  position: absolute;
176
177
  align-items: flex-end;
177
178
 
178
- .scroll-nav__nav-scroll {
179
+ .ui-scroll-view__nav-scroll {
179
180
  flex: 1;
180
181
  }
181
182
 
182
- .scroll-nav__nav-control {
183
+ .ui-scroll-view__nav-control {
183
184
  width: 20px;
184
185
  height: 30px;
185
186
 
@@ -193,7 +194,7 @@ export default {
193
194
  }
194
195
  }
195
196
 
196
- .scroll-nav__nav {
197
+ .ui-scroll-view__nav {
197
198
  align-items: flex-end;
198
199
  }
199
200
 
@@ -9,7 +9,7 @@
9
9
 
10
10
  <script>
11
11
  export default {
12
- name: 'minimize',
12
+ name: 'ui-minimize',
13
13
  props: {
14
14
  direction: {
15
15
  validator: (val) => ['top', 'right', 'bottom', 'left'].indexOf(val) !== -1,
@@ -0,0 +1,202 @@
1
+ <template>
2
+ <document-title :title="title">
3
+ <multipane class="router-search-page" >
4
+ <div class="page-search-conditions" :class="{collapse}" :style="searchConditionsStyle">
5
+ <div v-show="!collapse" class="search-content">
6
+ <slot name="search"></slot>
7
+ </div>
8
+ <div class="indicator" @click="toggleCollapse"></div>
9
+ </div>
10
+ <multipane-resizer v-show="!collapse"/>
11
+ <div class="page-search-content" :class="{'page-content-direction-row': direction === 'row'}">
12
+ <slot></slot>
13
+ </div>
14
+ </multipane>
15
+ </document-title>
16
+ </template>
17
+
18
+ <script>
19
+ import {Multipane, MultipaneResizer} from 'vue-multipane';
20
+ import DocumentTitle from '../document-title';
21
+
22
+ export default {
23
+ name: 'ui-search-page',
24
+ components: {
25
+ Multipane,
26
+ MultipaneResizer,
27
+ DocumentTitle,
28
+ },
29
+ props: {
30
+ value: {
31
+ type: String,
32
+ default: '360px',
33
+ },
34
+ min: {
35
+ type: String,
36
+ default: '200px',
37
+ },
38
+ max: {
39
+ type: String,
40
+ default: '600px',
41
+ },
42
+ direction: {
43
+ type: String,
44
+ validator: (val) => ['row', 'column'].includes(val),
45
+ default: 'column',
46
+ },
47
+ },
48
+ data() {
49
+ return {
50
+ collapse: false,
51
+ }
52
+ },
53
+ computed: {
54
+ title() {
55
+ return this.$route.meta.name || '';
56
+ },
57
+ searchConditionsStyle() {
58
+ let width = this.value;
59
+ let min = this.min;
60
+ if (this.collapse) {
61
+ min = 0;
62
+ width = 0;
63
+ }
64
+ return {
65
+ width: width,
66
+ minWidth: min,
67
+ maxWidth: this.max,
68
+ };
69
+ },
70
+ },
71
+ methods: {
72
+ toggleCollapse() {
73
+ this.collapse = !this.collapse;
74
+ },
75
+ },
76
+ };
77
+ </script>
78
+
79
+ <style lang="scss">
80
+
81
+ .router-search-page {
82
+ height: 100%;
83
+
84
+ .page-search-conditions {
85
+ display: flex;
86
+ flex-direction: column;
87
+ position: relative;
88
+
89
+ .search-content {
90
+ flex: 1;
91
+ display: flex;
92
+ flex-direction: column;
93
+ }
94
+
95
+ .indicator {
96
+ position: absolute;
97
+ top: 50%;
98
+ right: 0;
99
+ transform: translateY(-50%);
100
+ width: 14px;
101
+ height: 36px;
102
+ opacity: 0.3;
103
+ background-color: #ccc;
104
+ transition-duration: 200ms;
105
+ transition-property: background-color, opacity;
106
+ transition-timing-function: ease-in-out;
107
+ display: flex;
108
+ align-items: center;
109
+ justify-content: center;
110
+ flex-direction: column;
111
+ border-radius: 4px 0 0 4px;
112
+ cursor: pointer;
113
+
114
+ &:hover {
115
+ opacity: 1;
116
+ background-color: var(--color-primary);
117
+ }
118
+
119
+ &:hover:before {
120
+ transform: rotate(24deg);
121
+ }
122
+ &:hover:after {
123
+ transform: rotate(-24deg);
124
+ }
125
+
126
+ &::before,
127
+ &::after {
128
+ content: '';
129
+ display: block;
130
+ position: relative;
131
+ width: 2px;
132
+ height: 10px;
133
+ background-color: #fff;
134
+ transition: all 300ms ease-in-out;
135
+ }
136
+ &::before {
137
+ bottom: -1px;
138
+ }
139
+ &::after {
140
+ top: -1px;
141
+ }
142
+ }
143
+
144
+ &.collapse {
145
+ z-index: 2;
146
+
147
+ .indicator {
148
+ border-radius: 0 4px 4px 0;
149
+ right: -14px;
150
+
151
+ &:hover:before {
152
+ transform: rotate(-24deg);
153
+ }
154
+ &:hover:after {
155
+ transform: rotate(24deg);
156
+ }
157
+ }
158
+ }
159
+ }
160
+
161
+ .page-search-content {
162
+ flex: 1;
163
+ position: relative;
164
+ display: flex;
165
+ flex-direction: column;
166
+ overflow: auto;
167
+
168
+ &.page-search-content-direction-row {
169
+ flex-direction: row;
170
+ }
171
+ }
172
+
173
+ &.layout-v > .multipane-resizer {
174
+ margin: 0;
175
+ left: 0;
176
+ position: relative;
177
+
178
+ &.collapse {
179
+ display: none;
180
+ }
181
+
182
+ &:before {
183
+ display: block;
184
+ content: "";
185
+ width: 3px;
186
+ height: 40px;
187
+ position: absolute;
188
+ top: 50%;
189
+ left: 50%;
190
+ transform: translate(-50%, -50%);
191
+ border-left: 1px solid #ccc;
192
+ border-right: 1px solid #ccc;
193
+ }
194
+
195
+ &:hover {
196
+ &:before {
197
+ border-color: #999;
198
+ }
199
+ }
200
+ }
201
+ }
202
+ </style>
@@ -1,14 +1,14 @@
1
1
  <template>
2
- <div :class="['scroll-nav__nav-wrap', `is-${direction}`]">
3
- <div :class="['scroll-nav__nav-control scroll-nav__nav-prev', scrollable ? 'scroll-nav__nav-active' : '', scrollable && scrollable.prev ? '' : 'is-disabled']" @click="scrollPrev">
2
+ <div :class="['ui-scroll-view__nav-wrap', `is-${direction}`]">
3
+ <div :class="['ui-scroll-view__nav-control ui-scroll-view__nav-prev', scrollable ? 'ui-scroll-view__nav-active' : '', scrollable && scrollable.prev ? '' : 'is-disabled']" @click="scrollPrev">
4
4
  <slot name="prev" :disabled="scrollable && !scrollable.prev"><div class="menu-nav-control"></div></slot>
5
5
  </div>
6
- <div ref="navScroll" class="scroll-nav__nav-scroll">
7
- <div ref="nav" :class="['scroll-nav__nav', `is-${direction}`]" :style="navStyle">
6
+ <div ref="navScroll" class="ui-scroll-view__nav-scroll">
7
+ <div ref="nav" :class="['ui-scroll-view__nav', `is-${direction}`]" :style="navStyle">
8
8
  <slot></slot>
9
9
  </div>
10
10
  </div>
11
- <div :class="['scroll-nav__nav-control scroll-nav__nav-next', scrollable ? 'scroll-nav__nav-active' : '', scrollable && scrollable.next ? '' : 'is-disabled']" @click="scrollNext">
11
+ <div :class="['ui-scroll-view__nav-control ui-scroll-view__nav-next', scrollable ? 'ui-scroll-view__nav-active' : '', scrollable && scrollable.next ? '' : 'is-disabled']" @click="scrollNext">
12
12
  <slot name="next" :disabled="scrollable && !scrollable.next"><div class="menu-nav-control"></div></slot>
13
13
  </div>
14
14
  </div>
@@ -22,7 +22,7 @@ const firstUpperCase = str => {
22
22
  };
23
23
 
24
24
  export default {
25
- name: 'ScrollNav',
25
+ name: 'ui-scroll-view',
26
26
  props: {
27
27
  direction: {
28
28
  type: String,
@@ -154,7 +154,7 @@ export default {
154
154
  </script>
155
155
 
156
156
  <style lang="less">
157
- .scroll-nav__nav-wrap {
157
+ .ui-scroll-view__nav-wrap {
158
158
  overflow: hidden;
159
159
  position: relative;
160
160
  display: flex;
@@ -169,10 +169,10 @@ export default {
169
169
  flex-direction: column;
170
170
  }
171
171
 
172
- .scroll-nav__nav-scroll {
172
+ .ui-scroll-view__nav-scroll {
173
173
  overflow: hidden;
174
174
 
175
- .scroll-nav__nav {
175
+ .ui-scroll-view__nav {
176
176
  position: relative;
177
177
  transition: transform .3s;
178
178
  display: flex;
@@ -189,7 +189,7 @@ export default {
189
189
  }
190
190
  }
191
191
 
192
- &.is-row .scroll-nav__nav-control {
192
+ &.is-row .ui-scroll-view__nav-control {
193
193
  flex: none;
194
194
  width: 50px;
195
195
  height: 100%;
@@ -200,7 +200,7 @@ export default {
200
200
  justify-content: center;
201
201
  visibility: hidden;
202
202
 
203
- &.scroll-nav__nav-active {
203
+ &.ui-scroll-view__nav-active {
204
204
  visibility: visible;
205
205
  }
206
206
 
@@ -233,7 +233,7 @@ export default {
233
233
  }
234
234
  }
235
235
 
236
- &.scroll-nav__nav-prev {
236
+ &.ui-scroll-view__nav-prev {
237
237
  .menu-nav-control::before {
238
238
  transform: rotate(18deg);
239
239
  }
@@ -243,7 +243,7 @@ export default {
243
243
  }
244
244
  }
245
245
 
246
- &.scroll-nav__nav-next {
246
+ &.ui-scroll-view__nav-next {
247
247
  .menu-nav-control::before {
248
248
  transform: rotate(-18deg);
249
249
  }
@@ -253,7 +253,7 @@ export default {
253
253
  }
254
254
  }
255
255
 
256
- &.scroll-nav__nav-prev:hover {
256
+ &.ui-scroll-view__nav-prev:hover {
257
257
  .menu-nav-control::before {
258
258
  transform: rotate(30deg);
259
259
  }
@@ -263,7 +263,7 @@ export default {
263
263
  }
264
264
  }
265
265
 
266
- &.scroll-nav__nav-next:hover {
266
+ &.ui-scroll-view__nav-next:hover {
267
267
  .menu-nav-control::before {
268
268
  transform: rotate(-30deg);
269
269
  }
@@ -286,7 +286,7 @@ export default {
286
286
  &.is-column {
287
287
  height: 100%;
288
288
 
289
- .scroll-nav__nav-control {
289
+ .ui-scroll-view__nav-control {
290
290
  flex: none;
291
291
  width: 100%;
292
292
  height: 35px;
@@ -297,7 +297,7 @@ export default {
297
297
  justify-content: center;
298
298
  visibility: hidden;
299
299
 
300
- &.scroll-nav__nav-active {
300
+ &.ui-scroll-view__nav-active {
301
301
  visibility: visible;
302
302
  }
303
303
 
@@ -330,7 +330,7 @@ export default {
330
330
  }
331
331
  }
332
332
 
333
- &.scroll-nav__nav-prev {
333
+ &.ui-scroll-view__nav-prev {
334
334
  .menu-nav-control::before {
335
335
  transform: rotate(-18deg);
336
336
  }
@@ -340,7 +340,7 @@ export default {
340
340
  }
341
341
  }
342
342
 
343
- &.scroll-nav__nav-next {
343
+ &.ui-scroll-view__nav-next {
344
344
  .menu-nav-control::before {
345
345
  transform: rotate(18deg);
346
346
  }
@@ -350,7 +350,7 @@ export default {
350
350
  }
351
351
  }
352
352
 
353
- &.scroll-nav__nav-prev:hover {
353
+ &.ui-scroll-view__nav-prev:hover {
354
354
  .menu-nav-control::before {
355
355
  transform: rotate(-30deg);
356
356
  }
@@ -360,7 +360,7 @@ export default {
360
360
  }
361
361
  }
362
362
 
363
- &.scroll-nav__nav-next:hover {
363
+ &.ui-scroll-view__nav-next:hover {
364
364
  .menu-nav-control::before {
365
365
  transform: rotate(30deg);
366
366
  }