metaRules.js 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. // 元规则(Meta Rule)字典
  2. // 每个元规则定义编号、名称、配置字段,并提供 buildDescription / buildParams
  3. // 用于在规则列表中自动渲染"规则描述"和"规则参数"
  4. // 规则组类型选项
  5. export const GROUP_TYPES = [
  6. { value: 'debitCard', label: '借记卡圈客规则' },
  7. { value: 'creditCard', label: '信用卡圈客规则' }
  8. ]
  9. // 规则逻辑
  10. export const LOGIC_OPTIONS = [
  11. { value: 'AND', label: '且(AND)' },
  12. { value: 'OR', label: '或(OR)' }
  13. ]
  14. // 状态
  15. export const STATUS_OPTIONS = [
  16. { value: 'draft', label: '新建' },
  17. { value: 'online', label: '已上线' }
  18. ]
  19. // 常用比较运算符(用于 TRB / 余额 / 年龄等数值字段)
  20. const NUMERIC_OPS = [
  21. { value: '>', label: '大于 >' },
  22. { value: '<', label: '小于 <' },
  23. { value: '=', label: '等于 =' },
  24. { value: '>=', label: '大于等于 >=' },
  25. { value: '<=', label: '小于等于 <=' },
  26. { value: '!=', label: '不等于 !=' }
  27. ]
  28. // 日期比较运算符
  29. const DATE_OPS = [
  30. { value: '<', label: '在...前' },
  31. { value: '>', label: '在...后' },
  32. { value: '=', label: '在...当日' }
  33. ]
  34. // 集合运算符
  35. const SET_OPS = [
  36. { value: 'in', label: '属于' },
  37. { value: 'not_in', label: '不属于' },
  38. { value: '=', label: '等于' },
  39. { value: '!=', label: '不等于' }
  40. ]
  41. // =============================================
  42. // 工具函数
  43. // =============================================
  44. function formatMonthCN(yyyymm) {
  45. if (!yyyymm) return ''
  46. const [y, m] = yyyymm.split('-')
  47. return `${y}年${parseInt(m, 10)}月`
  48. }
  49. function formatMonthCompact(yyyymm) {
  50. return yyyymm ? yyyymm.replace('-', '') : ''
  51. }
  52. function formatDateSlash(yyyymmdd) {
  53. if (!yyyymmdd) return ''
  54. const [y, m, d] = yyyymmdd.split('-')
  55. return `${y}/${parseInt(m, 10)}/${parseInt(d, 10)}`
  56. }
  57. function formatAmount(num) {
  58. if (num === '' || num === null || num === undefined) return ''
  59. const n = Number(num)
  60. if (Number.isNaN(n)) return String(num)
  61. if (n >= 10000) return `${n / 10000}万`
  62. return String(n)
  63. }
  64. function dateOpSuffix(op) {
  65. return { '<': '前', '>': '后', '=': '当日' }[op] || op || ''
  66. }
  67. // =============================================
  68. // 元规则列表
  69. // =============================================
  70. export const META_RULES = [
  71. {
  72. code: '001',
  73. name: '开户时间(open_date)',
  74. paramKey: 'open_date',
  75. fields: [
  76. {
  77. key: 'accountType', label: '账户类型', type: 'select', required: true,
  78. options: [
  79. { value: 'I', label: 'I类账户' },
  80. { value: 'II', label: 'II类账户' },
  81. { value: 'III', label: 'III类账户' }
  82. ]
  83. },
  84. { key: 'operator', label: '比较方式', type: 'select', required: true, options: DATE_OPS },
  85. { key: 'date', label: '开户时间', type: 'datePicker', required: true }
  86. ],
  87. buildDescription(c) {
  88. if (!c.accountType || !c.date) return ''
  89. return `开户时间(${c.accountType}类账户)在${formatDateSlash(c.date)}${dateOpSuffix(c.operator)}`
  90. },
  91. buildParams(c) {
  92. if (!c.operator || !c.date) return ''
  93. return `{open_date,${c.operator},(${c.date})}`
  94. }
  95. },
  96. {
  97. code: '010',
  98. name: 'MSC',
  99. paramKey: 'MSC',
  100. fields: [
  101. { key: 'operator', label: 'MSC表达式', type: 'select', required: true, options: SET_OPS },
  102. {
  103. key: 'values', label: 'MSC值', type: 'multiSelect', required: true,
  104. options: [
  105. { value: 'premier', label: 'premier(卓越理财)' },
  106. { value: 'advance', label: 'advance(运筹理财)' },
  107. { value: 'excellence', label: 'excellence(卓越理财·尊尚)' },
  108. { value: 'global', label: 'global(环球私人银行)' }
  109. ]
  110. }
  111. ],
  112. buildDescription(c) {
  113. const vals = (c.values || []).join('/')
  114. if (!vals) return ''
  115. const opText = c.operator === 'not_in' || c.operator === '!=' ? '≠' : '='
  116. return `MSC${opText}${vals}`
  117. },
  118. buildParams(c) {
  119. const vals = (c.values || []).join('/')
  120. if (!c.operator || !vals) return ''
  121. return `{MSC,${c.operator},(${vals})}`
  122. }
  123. },
  124. {
  125. code: '050',
  126. name: 'TRB值-Avg TRB口径(不含家庭账户余额)',
  127. paramKey: 'Avg_TRB',
  128. fields: [
  129. { key: 'month', label: '开始月份', type: 'monthPicker', required: true },
  130. { key: 'nm', label: '连续达标月数/时间范围(月)', type: 'nm', required: false, defaultValue: { n: 3, m: 6 } },
  131. { key: 'operator', label: 'Avg TRB表达式', type: 'select', required: true, options: NUMERIC_OPS },
  132. { key: 'amount', label: 'Avg TRB值', type: 'number', required: true, min: 0 }
  133. ],
  134. buildDescription(c) {
  135. if (!c.month || !c.operator || c.amount === '' || c.amount == null) return ''
  136. const n = c.nm && c.nm.n ? `(连续${c.nm.n}个月达标)` : ''
  137. return `${formatMonthCN(c.month)}月末 TRB值-Avg TRB口径(不含家庭账户余额)${c.operator}${formatAmount(c.amount)}${n}`
  138. },
  139. buildParams(c) {
  140. if (!c.month || !c.operator) return ''
  141. const month = formatMonthCompact(c.month)
  142. const nm = c.nm && c.nm.n ? `;{${c.nm.n}/${c.nm.m || ''}}` : ''
  143. return `{month,=,${month}};{Avg_TRB,${c.operator},${c.amount}}${nm}`
  144. }
  145. },
  146. {
  147. code: '051',
  148. name: '月末余额(End of day balance)',
  149. paramKey: 'balance',
  150. fields: [
  151. { key: 'month', label: '开始月份', type: 'monthPicker', required: true },
  152. { key: 'nm', label: '连续达标月数/时间范围(月)', type: 'nm', required: false, defaultValue: { n: 3, m: 6 } },
  153. { key: 'operator', label: '余额表达式', type: 'select', required: true, options: NUMERIC_OPS },
  154. { key: 'amount', label: '余额值', type: 'number', required: true, min: 0 }
  155. ],
  156. buildDescription(c) {
  157. if (!c.month || !c.operator || c.amount === '' || c.amount == null) return ''
  158. const n = c.nm && c.nm.n ? `(连续${c.nm.n}个月达标)` : ''
  159. return `${formatMonthCN(c.month)}月末 End of day balance (所有资金含产品)${c.operator}${formatAmount(c.amount)}${n}`
  160. },
  161. buildParams(c) {
  162. if (!c.month || !c.operator) return ''
  163. const month = formatMonthCompact(c.month)
  164. const nm = c.nm && c.nm.n ? `;{${c.nm.n}/${c.nm.m || ''}}` : ''
  165. return `{month,=,${month}};{balance,${c.operator},${c.amount}}${nm}`
  166. }
  167. }
  168. ]
  169. // 元规则下拉显示文本:编号-名称
  170. export function metaRuleLabel(meta) {
  171. return `${meta.code}-${meta.name}`
  172. }
  173. // 根据 code 查询元规则
  174. export function getMetaRule(code) {
  175. return META_RULES.find((m) => m.code === code)
  176. }
  177. // 计算一条规则的描述
  178. export function buildRuleDescription(metaCode, config) {
  179. const meta = getMetaRule(metaCode)
  180. if (!meta || !meta.buildDescription) return ''
  181. return meta.buildDescription(config || {})
  182. }
  183. // 计算一条规则的参数
  184. export function buildRuleParams(metaCode, config) {
  185. const meta = getMetaRule(metaCode)
  186. if (!meta || !meta.buildParams) return ''
  187. return meta.buildParams(config || {})
  188. }