Bläddra i källkod

bug-292 修复button#form-type="submit" 第三方键盘收起不触发 <form> submit 事件
ec9fe78a88e793f813f4101fdcc708622a332bae

cc12458 7 månader sedan
förälder
incheckning
4ea29bd053

+ 4 - 26
miniprogram/components/button/button.ts

@@ -52,38 +52,16 @@ Component({
     ],
     src: "",
     isDisabled: false,
-    _lastResetTime: 0,
   },
   methods: {
-    handleSubmit(this: any) {
-      console.log(this.data.isDisabled, "handleSubmit");
-      if (this.data.isDisabled) {
-        return;
-      }
-
-      // 如果是刚刚重置的按钮(100ms内),不要立即禁用
-      const now = Date.now();
-      console.log(
-        now - this.data._lastResetTime < 100,
-        "now - this.data._lastResetTime < 100"
-      );
-      if (now - this.data._lastResetTime < 100) {
-        this.triggerEvent("submit");
-        return;
-      }
-      console.log(this.data.disableOnClick, "this.data.disableOnClick");
-      // 点击后可选地禁用按钮,防止重复提交;外部完成后请调用 resetState 或将 loading 置为 false
-      if (this.data.disableOnClick) {
-        this.setData({ isDisabled: true });
-      }
-      console.log("triggerEvent");
-      this.triggerEvent("submit");
+    onSubmit(this: any, event: any) {
+      if (this.data.isDisabled) return;
+      if (this.data.disableOnClick) this.valFailure();
+      this.triggerEvent('submit', { target: event.target }, { bubbles: true, composed: true });
     },
-
     resetState(this: any) {
       this.setData({
         isDisabled: false,
-        _lastResetTime: Date.now(),
       });
     },
 

+ 5 - 0
miniprogram/components/form/form.json

@@ -0,0 +1,5 @@
+{
+  "component": true,
+  "pureDataPattern": "^_",
+  "usingComponents": {}
+}

+ 22 - 0
miniprogram/components/form/form.ts

@@ -0,0 +1,22 @@
+// components/form/form.ts
+Component({
+  properties: {
+    _loading: { type: Boolean, value: false },
+    delay: { type: Number, value: 0 }
+  },
+  data: {
+    _model: {}
+  },
+  methods: {
+    onChange(event) {
+      const model = { ...this.data._model, ...event.detail };
+      this.setData({ _model: model });
+    },
+    onSubmit(event) {
+      setTimeout(() => {
+        if (this.data._loading) return;
+        this.triggerEvent('submit', { target: event.target, value: this.data._model }, { bubbles: true, composed: true });
+      }, this.data.delay);
+    },
+  }
+})

+ 3 - 0
miniprogram/components/form/form.wxml

@@ -0,0 +1,3 @@
+<view bind:change="onChange" mut-bind:submit="onSubmit">
+  <slot></slot>
+</view>

+ 4 - 0
miniprogram/module/user/components/field-cascader/field-cascader.ts

@@ -3,6 +3,7 @@ Component({
   behaviors: ['wx://form-field'],
   lifetimes: {},
   properties: {
+    name: { type: String, value: '' },
     title: { type: String, value: '' },
     closeOnOverlayClick: { type: Boolean, value: true },
   },
@@ -21,6 +22,9 @@ Component({
       const { value, code } = event.detail;
       const gather = value.map((name, index) => ({ name, code: code[index] }))
       this.setData({ value: gather });
+
+      const name = this.data.name;
+      if (name) this.triggerEvent('change', { [name]: gather }, { bubbles: true, composed: true });
     },
     onClose() {
       this.setData({ visible: false })

+ 4 - 2
miniprogram/module/user/components/field-picker/field-picker.ts

@@ -3,6 +3,7 @@ Component({
   behaviors: ['wx://form-field'],
   lifetimes: {},
   properties: {
+    name: { type: String, value: '' },
     title: { type: String, value: '' },
     options: { type: Array, value: [] },
     optionsColumns: { type: Number, value: 3 },
@@ -36,9 +37,10 @@ Component({
     },
     onPickerConfirm(event: any) {
       const { options } = event.detail;
-      console.log(event.detail, '123-->');
-      
       this.setData({ value: options })
+
+      const name = this.data.name;
+      if (name) this.triggerEvent('change', { [name]: options }, { bubbles: true, composed: true });
     },
     onPickerClose() {
       this.setData({ visible: false })

+ 2 - 1
miniprogram/module/user/components/field-radio/field-radio.ts

@@ -18,7 +18,8 @@ Component({
     onChange(event: { detail: { value: any } }) {
       const value = event.detail.value;
       this.setData({ value });
-      this.triggerEvent('change', value)
+      const name = this.data.name;
+      if (name) this.triggerEvent('change', { [name]: value }, { bubbles: true, composed: true });
     }
   }
 })

+ 15 - 0
miniprogram/module/user/components/user-data-edit/user-data-edit.ts

@@ -25,6 +25,21 @@ Component({
     }
   },
   methods: {
+    onChange(event) {
+      const name = event.mark.name;
+      const value = event.detail.value;
+      if (name) this.triggerEvent('change', { [name]: value }, { bubbles: true, composed: true });
+    },
+    onKeyboardheightchange(event) {
+      const name = event.mark.name;
+      if (!event.detail.height) {
+        this
+          .createSelectorQuery()
+          .select(`#${name}`)
+          .fields({ properties: ['value'] }, detail => this.onChange({ mark: { name }, detail }))
+          .exec();
+      }
+    },
     onExpand() {
       this.setData({ expanded: true });
     }

+ 9 - 3
miniprogram/module/user/components/user-data-edit/user-data-edit.wxml

@@ -12,11 +12,15 @@
 </block>
 
 <t-cell t-class="cell-field" t-class-note="cell-field__wrapper {{field.className(dirty, model, 'womenSpecialPeriod')}}" title="身高" required>
-  <input class="cell-field__inner suffix" slot="note" name="height" value="{{model['height']}}" type="number" placeholder="请输入身高" confirm-type="next" />
+  <input class="cell-field__inner suffix" slot="note"
+    name="height" mark:name="height" id="height" bind:change="onChange" bind:blur="onChange" bind:keyboardheightchange="onKeyboardheightchange"
+    value="{{model['height']}}" type="number" placeholder="请输入身高" confirm-type="next" />
   <view class="cell-field__suffix" slot="note">厘米</view>
 </t-cell>
 <t-cell t-class="cell-field" t-class-note="cell-field__wrapper" title="体重" required>
-  <input class="cell-field__inner suffix" slot="note" name="weight" value="{{model['weight']}}" type="number" placeholder="请输入体重" confirm-type="next" wx:key="weight" />
+  <input class="cell-field__inner suffix" slot="note"
+    name="weight" mark:name="weight" id="weight" bind:change="onChange" bind:blur="onChange" bind:keyboardheightchange="onKeyboardheightchange"
+    value="{{model['weight']}}" type="number" placeholder="请输入体重" confirm-type="next" wx:key="weight" />
   <view class="cell-field__suffix" slot="note">公斤</view>
 </t-cell>
 
@@ -42,7 +46,9 @@
     <field-cascader class="cell-field__inner full" slot="note" title="请选择" name="address" value="{{model['address']}}"></field-cascader>
   </t-cell>
   <t-cell t-class="cell-field" t-class-note="cell-field__wrapper" title="详细地址">
-    <input class="cell-field__inner" slot="note" name="detailAddress" value="{{model['detailAddress']}}" type="text" placeholder="请输入详细地址" confirm-type="next" />
+    <input class="cell-field__inner" slot="note"
+      name="detailAddress" mark:name="detailAddress" id="detailAddress" bind:change="onChange" bind:blur="onChange" bind:keyboardheightchange="onKeyboardheightchange"
+      value="{{model['detailAddress']}}" type="text" placeholder="请输入详细地址" confirm-type="next" />
   </t-cell>
 
   <t-cell t-class="cell-field" t-class-note="cell-field__wrapper" title="职业" bind:tap="onPicker">

+ 1 - 0
miniprogram/module/user/pages/user-edit/user-edit.json

@@ -3,6 +3,7 @@
   "component": true,
   "usingComponents": {
     "t-cell": "tdesign-miniprogram/cell/cell",
+    "form-fix": "../../../../components/form/form",
     "form-button": "../../../../components/button/button",
     "user-data-edit": "../../components/user-data-edit/user-data-edit",
     "field-radio": "../../components/field-radio/field-radio"

+ 20 - 45
miniprogram/module/user/pages/user-edit/user-edit.ts

@@ -20,6 +20,10 @@ Component({
   properties: {},
   data: {
     model: null as App.Patient.Model | null,
+    name: "",
+    cardno: "",
+    age: "",
+    sex: "",
     dirty: false,
     idCardValid: false,
   },
@@ -77,7 +81,7 @@ Component({
     onSexChange(event: WechatMiniprogram.CustomEvent) {
       const that = this as any;
       const value = (event as any)?.detail; // field-radio 直接传递选中值
-      that.setData({ ['model.sex']: value });
+      that.setData({ ['model.sex']: value.sex });
     },
     updateByCardno(cardno?: string) {
       const that = this as any;
@@ -113,64 +117,35 @@ Component({
     },
     async onSubmit(event: WechatMiniprogram.FormSubmit) {
       console.log(event, "onSubmit");
-      const that = this as any;
-      const submitBtn = that.selectComponent("#submitBtn");
-      console.log(event, "event",that.data.model);
-      that.setData({ dirty: true });
-      const data = { ...(that.data.model || {}), ...event?.detail?.value } as any;
+      this.setData({ dirty: true });
+      const data = { ...this.data.model, ...event?.detail?.value } as any;
       console.log(data, "穿的数据");
       // 如填写了身份证,进行18位身份证合法性校验
       if (data.cardno) {
         const { valid, message } = (this as any).validateIdCard18((data.cardno || '').toString());
-        if (!valid) {
-          if (submitBtn) submitBtn.resetState();
-          return getTickleContext.call(that).showWarnMessage(message || '身份证号不合法');
-        }
+        if (!valid) return this.showMessageAndDirty(message || '身份证号不合法');
       }
       // 必填:年龄、性别
-      if (!data.age) {
-        if (submitBtn) submitBtn.resetState();
-        return getTickleContext.call(that).showWarnMessage("请填写年龄");
-      }
-      if (data.sex === undefined || data.sex === null || data.sex === '') {
-        if (submitBtn) submitBtn.resetState();
-        return getTickleContext.call(that).showWarnMessage("请选择性别");
-      }
+      if (!data.age) return this.showMessageAndDirty("请填写年龄");
+      if (data.sex === undefined || data.sex === null || data.sex === '') return this.showMessageAndDirty("请选择性别");
       if (!data.patientId) data.patientId = wx.getStorageSync("patientId");
       // 表单验证
-      if (data.sex.toString() === "1" && !data.womenSpecialPeriod) {
-        if (submitBtn) submitBtn.resetState();
-        return getTickleContext
-          .call(that)
-          .showWarnMessage("请至少选择一项女性特殊期");
-      }
-      if (!data.height) {
-        if (submitBtn) submitBtn.resetState();
-        return getTickleContext.call(that).showWarnMessage("请填写身高");
-      }
-      if (!data.weight) {
-        if (submitBtn) submitBtn.resetState();
-        return getTickleContext.call(that).showWarnMessage("请填写体重");
-      }
+      if (data.sex.toString() === "1" && !data.womenSpecialPeriod) return this.showMessageAndDirty("请至少选择一项女性特殊期");
+      if (!data.height) return this.showMessageAndDirty("请填写身高");
+      if (!data.weight) return this.showMessageAndDirty("请填写体重");
       try {
         console.log(data, "data");
         await updateUserInfoMethod(<any>data)
-          .then(() => wx.navigateBack())
-          .then(() => {
-            that.getOpenerEventChannel().emit("update2", event.detail.value);
-          })
-          .catch((error) => {
-            if (submitBtn) {
-              submitBtn.resetState();
-            }
-            const msg = (error as any)?.errMsg || '更新失败';
-            getTickleContext.call(that).showWarnMessage(msg);
-          });
+        wx.navigateBack();
+        this.getOpenerEventChannel().emit("update2", event.detail.value);
       } catch (error) {
-        if (submitBtn) submitBtn.resetState();
         const msg = (error as any)?.errMsg || '更新失败';
-        getTickleContext.call(that).showWarnMessage(msg);
+        this.showMessageAndDirty(msg);
       }
     },
+    showMessageAndDirty(message: string) {
+      if (message) getTickleContext.call(this).showWarnMessage(message);
+      setTimeout(() => this.setData({ dirty: false }), 200);
+    },
   },
 });

+ 25 - 24
miniprogram/module/user/pages/user-edit/user-edit.wxml

@@ -2,31 +2,32 @@
 <wxs src="../../../../core/wxs/dictionary.wxs" module="dictionary" />
 <t-navbar title="完善信息" left-arrow />
 <scroll-view class="page-scroll__container" type="list" scroll-y style="{{containerStyle}}">
-  <form bindsubmit="onSubmit" bindinput="onFormInput">
-    <!-- <t-cell t-class="cell-border-gradient" title="手机号" note="{{model['phone']}}" /> -->
-    <t-cell title="姓名">
-      <input class="cell-field__inner" slot="note" name="name" value="{{model['name']}}" type="text" placeholder="请输入姓名" confirm-type="next" />
-    </t-cell>
-    <view class="cell-row">
-      <view class="label">身份证号</view>
-      <input class="input" name="cardno" value="{{model['cardno']}}" type="idcard" placeholder="请输入身份证号" confirm-type="next" data-field="cardno" bindinput="onFormInput" maxlength="18" />
-    </view>
-    <block wx:if="{{!idCardValid}}">
-      <t-cell title="年龄" required>
-        <input class="cell-field__inner" slot="note" name="age" value="{{model['age']}}" type="number" placeholder="请输入年龄" confirm-type="next" data-field="age" bindinput="onFormInput" style="padding-right:12%" />
-        <view class="cell-field__suffix" slot="note">岁</view>
+  <form mut-bind:submit="onSubmit" bindinput="onFormInput">
+    <form-fix _loading="{{dirty}}" delay="200">
+      <!-- <t-cell t-class="cell-border-gradient" title="手机号" note="{{model['phone']}}" /> -->
+      <t-cell title="姓名">
+        <input class="cell-field__inner" slot="note" name="name" value="{{model['name']}}" type="text" placeholder="请输入姓名" confirm-type="next" />
       </t-cell>
-      <t-cell title="性别" required>
-        <field-radio slot="note" name="sex" value="{{model['sex']}}" options="{{dictionary.options($dictionaries, 'sys_user_sex')}}" catch:change="onSexChange" />
-      </t-cell>
-    </block>
-    <block wx:else>
-      <t-cell title="年龄" note="{{model['age']}}岁" required />
-      <t-cell title="性别" note="{{dictionary.label($dictionaries, 'sys_user_sex', model['sex'])}}" required />
-    </block>
-    <user-data-edit model="{{model}}" dirty="{{dirty}}"></user-data-edit>
-    <form-button block index="1" id="submitBtn"></form-button>
-
+      <view class="cell-row">
+        <view class="label">身份证号</view>
+        <input class="input" name="cardno" value="{{model['cardno']}}" type="idcard" placeholder="请输入身份证号" confirm-type="next" data-field="cardno" bindinput="onFormInput" maxlength="18" />
+      </view>
+      <block wx:if="{{!idCardValid}}">
+        <t-cell title="年龄" required>
+          <input class="cell-field__inner" slot="note" name="age" value="{{model['age']}}" type="number" placeholder="请输入年龄" confirm-type="next" data-field="age" bindinput="onFormInput" style="padding-right:12%" />
+          <view class="cell-field__suffix" slot="note">岁</view>
+        </t-cell>
+        <t-cell title="性别" required>
+          <field-radio slot="note" name="sex" value="{{model['sex']}}" options="{{dictionary.options($dictionaries, 'sys_user_sex')}}" bind:change="onSexChange" />
+        </t-cell>
+      </block>
+      <block wx:else>
+        <t-cell title="年龄" note="{{model['age']}}岁" required />
+        <t-cell title="性别" note="{{dictionary.label($dictionaries, 'sys_user_sex', model['sex'])}}" required />
+      </block>
+      <user-data-edit model="{{model}}" dirty="{{dirty}}"></user-data-edit>
+      <form-button block index="1" loading="{{dirty}}" auto="{{true}}"></form-button>
+    </form-fix>
   </form>
 </scroll-view>