| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171 |
- // components/form-picker/form-picker.ts
- interface Option {
- label: string;
- value: any;
- checked?: boolean;
- disabled?: boolean;
- mutex?: boolean;
- };
- const filtration = (selected: string[] | Set<string>, options: Option[], option?: Option): string[] => {
- const _selected = new Set(selected);
- if (option) {
- if (_selected.has(option.value)) {
- _selected.delete(option.value);
- } else {
- if (option.mutex) {
- _selected.clear();
- } else {
- for (const option of options) {
- if (option.mutex) _selected.delete(option.value);
- }
- }
- _selected.add(option.value);
- }
- }
- return [..._selected];
- }
- const reset = (values: Option[] | Option | string, options: Option[]) => {
- const selected = new Set<string>();
- const _values = Array.isArray(values) ? values : values ? [values] : [];
- for (const item of _values) {
- const value = typeof item === 'object' ? item?.value : item;
- if (value && options.find(item => item.value === value)) selected.add(value);
- }
- for (const option of options) {
- if (option.checked) selected.add(option.value);
- }
- return filtration(selected, options);
- }
- Component({
- options: {
- multipleSlots: true,
- },
- lifetimes: {
- attached() {
- }
- },
- /**
- * 组件的属性列表
- */
- properties: {
- visible: { type: Boolean, value: false },
- title: { type: String, value: '' },
- value: { type: Array, value: [] },
- options: { type: Array, value: [] },
- optionsColumns: { type: Number, value: 1 },
- itemHeight: { type: Number, value: 64 },
- multiple: { type: Boolean, value: true },
- closeOnOverlayClick: { type: Boolean, value: true },
- },
- /**
- * 组件的初始数据
- */
- data: {
- containerHeight: 350,
- gap: 8,
- selected: [] as any[],
- replenish: {} as AnyObject,
- showReplenish: false,
- replenishValue: '',
- offset: 0,
- },
- observers: {
- 'options,optionsColumns,itemHeight'(options, columns, height) {
- const rows = Math.ceil(options.length / columns);
- this.setData({ containerHeight: Math.min(rows * height + (rows - 1) * this.data.gap, 350) })
- },
- 'value, options'(values: Option[] | Option | string, options: Option[]) {
- this.setData({ selected: reset(values, options) });
- }
- },
- /**
- * 组件的方法列表
- */
- methods: {
- handle(event: WechatMiniprogram.TouchEvent) {
- const index = event.currentTarget.dataset.index;
- const option = this.data.options[index];
- if (option.disabled) return;
- const handle = () => {
- if (this.data.multiple) {
- this.setData({ selected: filtration(this.data.selected, this.data.options, option) });
- } else {
- this.setData({ selected: this.data.selected.includes(option.value) ? [] : [option.value] });
- }
- }
- if (option.label === '其他') {
- if (this.data.selected.includes(option.value)) {
- handle();
- this.setData({ [`replenish.${option.value}`]: '' })
- } else {
- this.setData({ showReplenish: true, replenishValue: '' });
- this.onSubConfirm = () => {
- if (this.data.replenishValue) {
- handle();
- this.setData({ [`replenish.${option.value}`]: this.data.replenishValue })
- }
- this.onSubCancel();
- }
- }
- } else {
- handle()
- }
- },
- onConfirm() {
- const get = (option: Option) => {
- if (!option) return null;
- const replenish = this.data.replenish[option.value];
- return {
- label: replenish ? replenish : option.label,
- value: replenish ? `${option.value}:${replenish}` : option.value
- }
- };
- this.setData({ visible: false })
- this.triggerEvent('confirm', {
- selected: this.data.selected,
- options: this.data.selected
- .map(value => get(this.data.options.find(item => item.value === value)))
- .filter(Boolean),
- })
- this.triggerEvent('close', { trigger: 'confirm-btn' });
- },
- onCancel() {
- this.setData({ visible: false });
- this.triggerEvent('cancel');
- this.triggerEvent('close', { trigger: 'cancel-btn' });
- },
- onSubConfirm() { },
- onSubCancel() {
- this.setData({ showReplenish: false, offset: 0 });
- },
- onVisibleChange(event: any) {
- if (!event.detail.visible) {
- this.triggerEvent('close', { trigger: event.detail.trigger })
- setTimeout(() => {
- this.setData({
- selected: reset(this.data.value, this.data.options),
- offset: 0
- });
- }, 100)
- };
- },
- onBlur() {
- this.setData({ offset: 0 })
- },
- onKeyboardheightchange(event: any) {
- const _height = event?.detail?.height;
- if (_height !== this.data.offset) this.setData({ offset: _height });
- }
- }
- })
|