Skip to content

Commit 5be73a3

Browse files
committed
🎨 待优化图标选择器
1 parent f882c5d commit 5be73a3

File tree

8 files changed

+284
-12
lines changed

8 files changed

+284
-12
lines changed

docs/form.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,27 @@ $form->item('username', '用户名')->vif("key","value")
193193
$form->item('username', '用户名')->vif("key.key","value") //支持点操作
194194
```
195195

196+
### 忽略空值(留空则不修改)
197+
198+
> 若此字段的值为 ''/null/undefined 或 空对象/空数组 则在提交的表单对象中删除键名
199+
200+
```php
201+
$form->item('password', '密码')->ignoreEmpty()
202+
```
203+
204+
### 隐藏组件
205+
206+
> 有些字段在编辑或创建状态下并不一致需要,配合ignoreEmpty使用效果更佳
207+
208+
```php
209+
## 创建时不输入密码
210+
$form->item('password', '密码')->hiddenMode('create')
211+
$form->item('password', '密码')->hiddenInCreate()
212+
213+
## 编辑时不输入密码
214+
$form->item('password', '密码')->hiddenMode('edit')
215+
$form->item('password', '密码')->hiddenInEdit()
216+
```
196217

197218

198219
### 帮助信息

resources/js/components.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ import Link from './components/widgets/Link'
7070
import Text from './components/widgets/Text'
7171
import Image from './components/widgets/Image'
7272
import Icon from './components/widgets/Icon'
73+
import IconChoose from './components/widgets/IconChoose'
7374

7475

7576
//Grid
@@ -80,6 +81,7 @@ Vue.component('IText', Text);
8081
Vue.component('IImage', Image);
8182
Vue.component('Icon', Icon);
8283
Vue.component('Boole', require('./components/widgets/Grid/Boole').default);
84+
Vue.component('IconChoose', IconChoose);
8385

8486

8587

resources/js/components/form/Form.vue

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@
103103
<script>
104104
import ItemDiaplsy from "./ItemDiaplsy";
105105
import ItemIf from "./ItemIf";
106+
import { isNull } from "../../utils";
106107
export default {
107108
components: {
108109
ItemDiaplsy,
@@ -116,7 +117,7 @@ export default {
116117
return this.attrs.mode == "edit";
117118
},
118119
ignoreKey() {
119-
return this._.map(this.attrs.formItems.filter(e=>!e.ignoreEmpty) ,'prop')
120+
return this._.map(this.attrs.formItems.filter(e => !e.ignoreEmpty || !isNull(this.formData[e.prop])) ,'prop')
120121
}
121122
},
122123
data() {
@@ -157,10 +158,11 @@ export default {
157158
this.$refs[formName].validate(valid => {
158159
if (valid) {
159160
this.loading = true;
160-
this.formData = this._.pick(this.formData, this.ignoreKey)
161+
console.log(this.ignoreKey)
162+
const formatData = this._.pick(this.formData, this.ignoreKey)
161163
if (this.isEdit) {
162164
this.$http
163-
.put(this.attrs.action, this.formData)
165+
.put(this.attrs.action, formatData)
164166
.then(({ data, code, message }) => {
165167
if (code == 200) {
166168
this.formData = this._.cloneDeep(this.attrs.defaultValues);
@@ -172,7 +174,7 @@ export default {
172174
});
173175
} else {
174176
this.$http
175-
.post(this.attrs.action, this.formData)
177+
.post(this.attrs.action, formatData)
176178
.then(({ data, code, message }) => {
177179
code == 200 && this.$router.go(-1);
178180
})
Lines changed: 223 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,223 @@
1+
<template>
2+
<div>
3+
<el-popover
4+
v-if="inputType || disabledSelected"
5+
placement="bottom-start"
6+
popper-class="pupop-select-icon"
7+
transition="el-zoom-in-top"
8+
trigger="click"
9+
v-model="popoverVisible"
10+
:disabled="disabledSelected">
11+
<!-- 弹出框内容区 -->
12+
<el-scrollbar
13+
v-if="popoverVisible"
14+
class="hide-x"
15+
:native="false"
16+
:noresize="false">
17+
<!-- 图标项 -->
18+
<div
19+
class="icon-item"
20+
v-for="item in options"
21+
:key="item"
22+
:class="{ 'is-active': isActive(item) }"
23+
@click="onClickSelected(item)">
24+
<i :class="item"></i>
25+
</div>
26+
</el-scrollbar>
27+
<!-- 页面显示内容区 -->
28+
<template slot="reference">
29+
<div :class="{
30+
'mod-select-icon': 1,
31+
'is-opened': popoverVisible,
32+
'is-active': value,
33+
'is-disabled': disabledSelected
34+
}">
35+
<!-- 显示图标 -->
36+
<div class="icon-item">
37+
<i :class="value || 'el-icon-plus'"></i>
38+
</div>
39+
<!-- 清空按钮 -->
40+
<div v-show="value" class="btn-clear">
41+
<i class="el-icon-close" @click.stop="onClickClear()"></i>
42+
</div>
43+
</div>
44+
</template>
45+
</el-popover>
46+
<el-input v-else class="mod-input" v-model.trim="value"></el-input>
47+
<el-button :disabled="disabledSelected" @click="inputType = !inputType" :type="inputType?'primary':'ghost'" icon="el-icon-edit" circle></el-button>
48+
</div>
49+
</template>
50+
51+
<script>
52+
export default {
53+
name: 'IconChoose',
54+
// 设置绑定参数
55+
model: {
56+
prop: 'value',
57+
event: 'selected',
58+
},
59+
props: {
60+
value: {
61+
default: null
62+
},
63+
disabled: Boolean,
64+
// 接收绑定参数 - 图标类名
65+
value: {
66+
type: String,
67+
required: false,
68+
},
69+
// 选项数据,图标类名数组
70+
options: {
71+
type: Array,
72+
default: () => (['mofont mo-icon-dashboard mo-menu','mofont mo-icon-admin mo-menu','el-icon-ice-cream-round','el-icon-ice-cream-square','el-icon-lollipop','el-icon-potato-strips','el-icon-milk-tea','el-icon-ice-drink','el-icon-ice-tea','el-icon-coffee','el-icon-orange','el-icon-pear','el-icon-apple','el-icon-cherry','el-icon-watermelon','el-icon-grape','el-icon-refrigerator','el-icon-goblet-square-full','el-icon-goblet-square','el-icon-goblet-full','el-icon-goblet','el-icon-cold-drink','el-icon-coffee-cup','el-icon-water-cup','el-icon-hot-water','el-icon-ice-cream','el-icon-dessert','el-icon-sugar','el-icon-tableware','el-icon-burger','el-icon-knife-fork','el-icon-fork-spoon','el-icon-chicken','el-icon-food','el-icon-dish-1','el-icon-dish','el-icon-moon-night','el-icon-moon','el-icon-cloudy-and-sunny','el-icon-partly-cloudy','el-icon-cloudy','el-icon-sunny','el-icon-sunset','el-icon-sunrise-1','el-icon-sunrise','el-icon-heavy-rain','el-icon-lightning','el-icon-light-rain','el-icon-wind-power','el-icon-baseball','el-icon-soccer','el-icon-football','el-icon-basketball','el-icon-ship','el-icon-truck','el-icon-bicycle','el-icon-mobile-phone','el-icon-service','el-icon-key','el-icon-unlock','el-icon-lock','el-icon-watch','el-icon-watch-1','el-icon-timer','el-icon-alarm-clock','el-icon-map-location','el-icon-delete-location','el-icon-add-location','el-icon-location-information','el-icon-location-outline','el-icon-location','el-icon-place','el-icon-discover','el-icon-first-aid-kit','el-icon-trophy-1','el-icon-trophy','el-icon-medal','el-icon-medal-1','el-icon-stopwatch','el-icon-mic','el-icon-copy-document','el-icon-full-screen','el-icon-switch-button','el-icon-aim','el-icon-crop','el-icon-odometer','el-icon-time','el-icon-bangzhu','el-icon-close-notification','el-icon-microphone','el-icon-turn-off-microphone','el-icon-position','el-icon-postcard','el-icon-message','el-icon-chat-line-square','el-icon-chat-dot-square','el-icon-chat-dot-round','el-icon-chat-square','el-icon-chat-line-round','el-icon-chat-round','el-icon-set-up','el-icon-turn-off','el-icon-open','el-icon-connection','el-icon-link','el-icon-cpu','el-icon-thumb','el-icon-female','el-icon-male','el-icon-guide','el-icon-news','el-icon-price-tag','el-icon-discount','el-icon-wallet','el-icon-coin','el-icon-money','el-icon-bank-card','el-icon-box','el-icon-present','el-icon-sell','el-icon-sold-out','el-icon-shopping-bag-2','el-icon-shopping-bag-1','el-icon-shopping-cart-2','el-icon-shopping-cart-1','el-icon-shopping-cart-full','el-icon-smoking','el-icon-no-smoking','el-icon-house','el-icon-table-lamp','el-icon-school','el-icon-office-building','el-icon-toilet-paper','el-icon-notebook-2','el-icon-notebook-1','el-icon-files','el-icon-collection','el-icon-receiving','el-icon-suitcase-1','el-icon-suitcase','el-icon-film','el-icon-collection-tag','el-icon-data-analysis','el-icon-pie-chart','el-icon-data-board','el-icon-data-line','el-icon-reading','el-icon-magic-stick','el-icon-coordinate','el-icon-mouse','el-icon-brush','el-icon-headset','el-icon-umbrella','el-icon-scissors','el-icon-mobile','el-icon-attract','el-icon-monitor','el-icon-search','el-icon-takeaway-box','el-icon-paperclip','el-icon-printer','el-icon-document-add','el-icon-document','el-icon-document-checked','el-icon-document-copy','el-icon-document-delete','el-icon-document-remove','el-icon-tickets','el-icon-folder-checked','el-icon-folder-delete','el-icon-folder-remove','el-icon-folder-add','el-icon-folder-opened','el-icon-folder','el-icon-edit-outline','el-icon-edit','el-icon-date','el-icon-c-scale-to-original','el-icon-view','el-icon-loading','el-icon-rank','el-icon-sort-down','el-icon-sort-up','el-icon-sort','el-icon-finished','el-icon-refresh-left','el-icon-refresh-right','el-icon-refresh','el-icon-video-play','el-icon-video-pause','el-icon-d-arrow-right','el-icon-d-arrow-left','el-icon-arrow-up','el-icon-arrow-down','el-icon-arrow-right','el-icon-arrow-left','el-icon-top-right','el-icon-top-left','el-icon-top','el-icon-bottom','el-icon-right','el-icon-back','el-icon-bottom-right','el-icon-bottom-left','el-icon-caret-top','el-icon-caret-bottom','el-icon-caret-right','el-icon-caret-left','el-icon-d-caret','el-icon-share','el-icon-menu','el-icon-s-grid','el-icon-s-check','el-icon-s-data','el-icon-s-opportunity','el-icon-s-custom','el-icon-s-claim','el-icon-s-finance','el-icon-s-comment','el-icon-s-flag','el-icon-s-marketing','el-icon-s-shop','el-icon-s-open','el-icon-s-management','el-icon-s-ticket','el-icon-s-release','el-icon-s-home','el-icon-s-promotion','el-icon-s-operation','el-icon-s-unfold','el-icon-s-fold','el-icon-s-platform','el-icon-s-order','el-icon-s-cooperation','el-icon-bell','el-icon-message-solid','el-icon-video-camera','el-icon-video-camera-solid','el-icon-camera','el-icon-camera-solid','el-icon-download','el-icon-upload2','el-icon-upload','el-icon-picture-outline-round','el-icon-picture-outline','el-icon-picture','el-icon-close','el-icon-check','el-icon-plus','el-icon-minus','el-icon-help','el-icon-s-help','el-icon-circle-close','el-icon-circle-check','el-icon-circle-plus-outline','el-icon-remove-outline','el-icon-zoom-out','el-icon-zoom-in','el-icon-error','el-icon-success','el-icon-circle-plus','el-icon-remove','el-icon-info','el-icon-question','el-icon-warning-outline','el-icon-warning','el-icon-goods','el-icon-s-goods','el-icon-star-off','el-icon-star-on','el-icon-more-outline','el-icon-more','el-icon-phone-outline','el-icon-phone','el-icon-user','el-icon-user-solid','el-icon-setting','el-icon-s-tools','el-icon-delete','el-icon-delete-solid','el-icon-eleme']),
73+
}
74+
},
75+
computed: {
76+
disabledSelected() {
77+
if (this.disabled) return true;
78+
return this.$parent.form ? this.$parent.form.disabled : false;
79+
},
80+
},
81+
data() {
82+
return {
83+
// 弹出框显示状态
84+
popoverVisible: false,
85+
inputType: true
86+
};
87+
},
88+
methods: {
89+
// 是否为当前已选项
90+
isActive(item) {
91+
return this.value === item;
92+
},
93+
// 选中图标
94+
onClickSelected(item) {
95+
this.$emit('selected', item);
96+
this.popoverVisible = false;
97+
},
98+
// 清空选项
99+
onClickClear() {
100+
this.$emit('selected', '');
101+
},
102+
},
103+
};
104+
</script>
105+
106+
<style lang="scss">
107+
@import "~element-ui/packages/theme-chalk/src/common/var.scss";
108+
.mod-input {
109+
width: 80%;
110+
}
111+
.mod-select-icon
112+
{
113+
$size: 40px;
114+
$col-count: 8;
115+
$row-count: 4;
116+
$scope: 5px;
117+
118+
position: relative;
119+
display: inline-block;
120+
width: $size;
121+
height: $size;
122+
border: 1px dashed $--border-color-base;
123+
border-radius: 5px;
124+
text-align: center;
125+
cursor: pointer;
126+
outline: none;
127+
128+
// 菜单打开状态
129+
&.is-opened, &:hover { border-color: $--color-primary; }
130+
// 禁用状态
131+
&.is-disabled:hover { border-color: $--border-color-base !important; }
132+
&.is-disabled,
133+
&.is-disabled > .icon-item,
134+
&.is-disabled > .btn-clear {
135+
background-color: $--background-color-base;
136+
}
137+
// 已选状态
138+
&.is-active {
139+
border-style: solid;
140+
border-radius: 0;
141+
> .icon-item {
142+
padding: $scope;
143+
text-align: center;
144+
cursor: pointer;
145+
> i {
146+
display: block;
147+
width: 100%;
148+
height: 100%;
149+
line-height: $size - ($scope * 2);
150+
color: $--color-white;
151+
background-color: $--color-primary;
152+
}
153+
}
154+
}
155+
> .icon-item > i { font-size: 16px; }
156+
> .icon-item > iel-icon-plus {
157+
width: 100%;
158+
line-height: $size;
159+
font-size: ($size / 2);
160+
font-weight: bold;
161+
color: $--color-info;
162+
cursor: inherit;
163+
}
164+
165+
// 清空按钮
166+
.btn-clear {
167+
width: 0;
168+
height: 0;
169+
border-width: ($size / 2) 0 0 ($size / 2);
170+
border-style: solid;
171+
border-color: $--color-danger transparent transparent transparent;
172+
position: absolute;
173+
top: 0;
174+
right: 0;
175+
cursor: pointer;
176+
> iel-icon-close {
177+
position: absolute;
178+
top: -($size / 2);
179+
right: 0;
180+
color: $--color-white;
181+
font-size: .7em;
182+
&:hover { color: darken($--color-white, 5%); }
183+
}
184+
}
185+
186+
// 弹出内容
187+
@at-root .el-popover.el-popper.pupop-select-icon {
188+
display: block;
189+
padding: 0;
190+
width: ($size + $scope * 2) * $col-count + 2px;
191+
height: ($size + $scope * 2) * $row-count;
192+
193+
> .el-scrollbar { height: 100%; }
194+
.el-scrollbar__view {
195+
}
196+
197+
.icon-item {
198+
float: left;
199+
width: $size;
200+
height: $size;
201+
line-height: $size;
202+
margin: $scope;
203+
padding: $scope;
204+
text-align: center;
205+
cursor: pointer;
206+
&:hover { background-color: $--color-info-light; }
207+
&.is-active {
208+
background-color: $--color-success-light;
209+
border: 1px solid $--color-success;
210+
}
211+
> i {
212+
display: block;
213+
width: 100%;
214+
height: 100%;
215+
font-size: 16px;
216+
line-height: $size - ($scope * 2);
217+
color: $--color-white;
218+
background-color: $--color-primary;
219+
}
220+
}
221+
}
222+
}
223+
</style>

resources/js/utils.js

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,22 @@ function getFileName(path) {
5757

5858
}
5959

60+
function isNull(argument) {
61+
const type = typeof argument
62+
switch (type) {
63+
case 'object':
64+
return window._.isEmpty(argument)
65+
case 'array':
66+
return argument.length
67+
default:
68+
return argument === "" || argument === null || argument === undefined
69+
}
70+
}
71+
6072
export {
6173
getArrayValue,
6274
flattenDeepChild,
6375
getFileUrl,
64-
getFileName
76+
getFileName,
77+
isNull
6578
}

src/Components/IconChoose.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
3+
namespace SmallRuralDog\Admin\Components;
4+
5+
class IconChoose extends GridComponent
6+
{
7+
protected $componentName = "IconChoose";
8+
9+
public static function make($value = null)
10+
{
11+
return new IconChoose($value);
12+
}
13+
14+
}

0 commit comments

Comments
 (0)