cyRefList.ts 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. import { ref, computed, Ref } from "vue";
  2. import XEUtils from "xe-utils";
  3. import { BizException, ExceptionEnum } from "@/utils/BizException";
  4. import { stringIsBlank } from "@/utils/blank-utils";
  5. declare type CodeType<T> = (keyof T & string) | ((item: T) => string);
  6. function cyRefList<T = any>(
  7. code: CodeType<T>,
  8. errMsg: (item: T) => string = () => "请勿重复添加"
  9. ): [
  10. Ref<T[]>,
  11. {
  12. push: (...items: T[]) => number;
  13. watchPush: (cb: (value: T) => void) => () => void;
  14. delIndex: (index: number) => void;
  15. clear: () => void;
  16. isEmpty: () => boolean;
  17. emptyError: (errorMsg?: string) => void;
  18. forEach: (cb: (item: T, index: number) => void) => void;
  19. eachAndReturnList: (iteration: (item: T, index: number) => any) => any[];
  20. },
  21. ] {
  22. const list = ref([]) as Ref<T[]>;
  23. const watchFunc: Function[] = [];
  24. const codeIsFunction = typeof code === "function";
  25. const codeKey = computed<string[]>(() => {
  26. return XEUtils.eachAndReturnList(list.value, item => {
  27. if (codeIsFunction) {
  28. return code(item);
  29. }
  30. return item[code];
  31. });
  32. });
  33. function sendListening(items: any) {
  34. return new Promise(resolve => {
  35. watchFunc.forEach(item => item(items));
  36. resolve(true);
  37. });
  38. }
  39. const listProxy = {
  40. push: function (...items: T[]) {
  41. const msgList: string[] = [];
  42. items.forEach((item: T) => {
  43. let key: string;
  44. if (codeIsFunction) {
  45. key = code(item);
  46. } else {
  47. key = item[code] as string;
  48. }
  49. if (stringIsBlank(key)) {
  50. BizException(ExceptionEnum.MESSAGE_ERROR, "没有找到唯一值");
  51. }
  52. if (codeKey.value.includes(key)) {
  53. const msg = errMsg(item);
  54. msgList.push(msg);
  55. }
  56. });
  57. if (msgList.length === 1) {
  58. BizException(ExceptionEnum.MESSAGE_ERROR, msgList[0]);
  59. } else if (msgList.length > 0) {
  60. BizException(ExceptionEnum.MESSAGE_HTML_ERROR, msgList.join("<br/>"));
  61. }
  62. sendListening(items).then(r => {});
  63. return list.value.push(...items);
  64. },
  65. watchPush: function (cb: (value: T) => void) {
  66. const index = watchFunc.push(cb);
  67. function stop() {
  68. watchFunc.splice(index, 0);
  69. }
  70. return stop;
  71. },
  72. delIndex: function (index: number) {
  73. list.value.splice(index, 1);
  74. },
  75. clear: function () {
  76. list.value = [];
  77. },
  78. isEmpty() {
  79. return list.value === null || list.value.length === 0;
  80. },
  81. emptyError(errorMsg = "请先选择数据") {
  82. if (this.isEmpty()) {
  83. BizException(ExceptionEnum.MESSAGE_ERROR, errorMsg);
  84. }
  85. },
  86. forEach(cb: (item: T, index: number) => void) {
  87. for (let i = 0, len = list.value.length; i < len; i++) {
  88. const item = list.value[i];
  89. cb(item, i);
  90. }
  91. },
  92. eachAndReturnList(iteration: (item: T, index: number) => any) {
  93. return XEUtils.eachAndReturnList(list, iteration);
  94. },
  95. };
  96. return [list, listProxy];
  97. }
  98. export default cyRefList;