input_ctrl.py 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. import json
  2. import logging
  3. from .framework import WebIOFuture, Global
  4. logger = logging.getLogger(__name__)
  5. def send_msg(cmd, spec=None):
  6. msg = dict(command=cmd, spec=spec, coro_id=Global.active_coro_id)
  7. Global.active_ws.write_message(json.dumps(msg))
  8. async def next_event():
  9. res = await WebIOFuture()
  10. return res
  11. async def single_input(item_spec, valid_func, preprocess_func):
  12. """
  13. Note: 鲁棒性在上层完成
  14. 将单个input构造成input_group,并获取返回值
  15. :param item_spec: 单个输入项的参数 'name' must in item_spec, 参数一定已经验证通过
  16. :param valid_func: Not None
  17. :param preprocess_func: Not None
  18. """
  19. label = item_spec['label']
  20. name = item_spec['name']
  21. # todo 是否可以原地修改spec
  22. item_spec['label'] = ''
  23. item_spec.setdefault('autofocus', True) # 如果没有设置autofocus参数,则开启参数 todo CHECKBOX, RADIO 特殊处理
  24. spec = dict(label=label, inputs=[item_spec])
  25. data = await input_control(spec, {name: preprocess_func}, {name: valid_func})
  26. return data[name]
  27. async def input_control(spec, preprocess_funcs, item_valid_funcs, form_valid_funcs=None):
  28. """
  29. 发送input命令,监听事件,验证输入项,返回结果
  30. :param spec:
  31. :param preprocess_funcs: keys 严格等于 spec中的name集合
  32. :param item_valid_funcs: keys 严格等于 spec中的name集合
  33. :param form_valid_funcs:
  34. :return:
  35. """
  36. send_msg('input_group', spec)
  37. data = await input_event_handle(item_valid_funcs, form_valid_funcs, preprocess_funcs)
  38. send_msg('destroy_form')
  39. return data
  40. def check_item(name, data, valid_func, preprocess_func):
  41. data = preprocess_func(data)
  42. error_msg = valid_func(data)
  43. if error_msg is not None:
  44. send_msg('update_input', dict(target_name=name, attributes={
  45. 'valid_status': False,
  46. 'invalid_feedback': error_msg
  47. }))
  48. return False
  49. return True
  50. async def input_event_handle(item_valid_funcs, form_valid_funcs, preprocess_funcs):
  51. """
  52. 根据提供的校验函数处理表单事件
  53. :param valid_funcs: map(name -> valid_func) valid_func 为 None 时,不进行验证
  54. valid_func: callback(data) -> error_msg
  55. :param whole_valid_func: callback(data) -> (name, error_msg)
  56. :param inputs_args:
  57. :return:
  58. """
  59. while True:
  60. event = await next_event()
  61. event_name, event_data = event['event'], event['data']
  62. if event_name == 'input_event':
  63. input_event = event_data['event_name']
  64. if input_event == 'blur':
  65. onblur_name = event_data['name']
  66. check_item(onblur_name, event_data['value'], item_valid_funcs[onblur_name],
  67. preprocess_funcs[onblur_name])
  68. elif event_name == 'from_submit':
  69. all_valid = True
  70. # 调用输入项验证函数进行校验
  71. for name, valid_func in item_valid_funcs.items():
  72. if not check_item(name, event_data[name], valid_func, preprocess_funcs[name]):
  73. all_valid = False
  74. # 调用表单验证函数进行校验
  75. if form_valid_funcs:
  76. data = {name: preprocess_funcs[name](val) for name, val in event_data.items()}
  77. v_res = form_valid_funcs(data)
  78. if v_res is not None:
  79. all_valid = False
  80. onblur_name, error_msg = v_res
  81. send_msg('update_input', dict(target_name=onblur_name, attributes={
  82. 'valid_status': False,
  83. 'invalid_feedback': error_msg
  84. }))
  85. if all_valid:
  86. break
  87. return event['data']