consumer模块完成度95%,检查消费者前端bug并修复
This commit is contained in:
@@ -109,35 +109,74 @@
|
||||
|
||||
1. 布局方式
|
||||
- 只支持 display: flex
|
||||
- 不支持 display: grid
|
||||
- 不支持 display: grid、display: block
|
||||
- 不支持 gap
|
||||
- 不支持 table、grid、grid-template-columns
|
||||
|
||||
2. 单位与计算
|
||||
- 不支持 calc()
|
||||
- 不支持的单位: vh
|
||||
- 不支持的单位: vh、vw
|
||||
- property value `100%` is not supported for min-height (supported values are: number|pixel)
|
||||
- property value `60%` is not supported for max-height (supported values are: number|pixel)
|
||||
- property value `calc(33.33% - 10px)` is not supported for min-width
|
||||
- height 不支持 vh 单位,需要使用具体的像素值或百分比
|
||||
|
||||
3. 选择器
|
||||
- [APP-ANDROID] 不支持伪类选择器
|
||||
- [APP-IOS] 不支持伪类选择器
|
||||
- ERROR: Selector `.login-button[disabled]` is not supported. uvue only support classname selector
|
||||
|
||||
4. 其他样式
|
||||
4. font-weight 限制
|
||||
- font-weight 只支持: normal | bold | 400 | 700
|
||||
- 不支持: 100, 300, 500, 600, 900 等其他数值
|
||||
|
||||
5. border-radius 限制
|
||||
- border-radius 不支持百分比单位 (如 50%)
|
||||
- 需要使用具体的像素值 (如 border-radius: 9px 实现圆形)
|
||||
|
||||
6. line-height 限制
|
||||
- line-height 不支持 normal 值
|
||||
- 需要使用具体的数值或像素值 (如 line-height: 36px 或 line-height: 1.5)
|
||||
|
||||
7. position 限制
|
||||
- position 不支持 sticky 值
|
||||
- 只支持: relative | absolute | fixed
|
||||
|
||||
8. 不支持的 CSS 属性
|
||||
- outline 属性不支持
|
||||
- aspect-ratio 属性不支持,需要用具体的 width 和 height 值
|
||||
- text-decoration 属性不支持(如 line-through)
|
||||
- align-items 不支持 baseline 值,只支持 center | flex-start | flex-end | stretch
|
||||
- 不支持后代选择器(如 .parent text),只支持类名选择器
|
||||
|
||||
9. 其他样式
|
||||
- WARNING: `backdrop-filter` is not a standard property name
|
||||
- style property `white-space` is only supported on `<text>|<button>`
|
||||
- ERROR: property value `all` is not supported for `transition-property`
|
||||
|
||||
================================================================================
|
||||
六、scroll-view 使用
|
||||
六、UTS 模板表达式限制
|
||||
================================================================================
|
||||
|
||||
1. 条件语句必须使用布尔类型
|
||||
- 错误码: UTS110111120
|
||||
- 不支持 || 运算符的隐式类型转换
|
||||
- 错误写法: {{ value || '默认值' }}
|
||||
- 正确写法: {{ value != null && value != '' ? value : '默认值' }}
|
||||
|
||||
2. 模板中的类型判断
|
||||
- 所有条件表达式必须返回布尔值
|
||||
- 不能使用 truthy/falsy 值作为条件
|
||||
|
||||
================================================================================
|
||||
七、scroll-view 使用
|
||||
================================================================================
|
||||
|
||||
- scroll-view 在 uni-app-x 中不是用 scroll-y=true
|
||||
- 而是要用 direction="vertical"
|
||||
|
||||
================================================================================
|
||||
七、异步与回调
|
||||
八、异步与回调
|
||||
================================================================================
|
||||
|
||||
- uni.showModal 的 success 回调不能是 async 函数
|
||||
@@ -146,7 +185,7 @@
|
||||
- 解决方案:使用普通函数 function name(): Type {} 代替箭头函数
|
||||
|
||||
================================================================================
|
||||
八、响应式数据
|
||||
九、响应式数据
|
||||
================================================================================
|
||||
|
||||
- 对于需要整体替换的数组,推荐使用 ref 而非 reactive
|
||||
@@ -155,7 +194,7 @@
|
||||
- 对于可能为 null 的参数,需要显式检查后再传递给函数
|
||||
|
||||
================================================================================
|
||||
九、类型导入
|
||||
十、类型导入
|
||||
================================================================================
|
||||
|
||||
- 类型导入需要使用 type 关键字
|
||||
@@ -165,7 +204,7 @@
|
||||
- 返回的是 result,resultdata 一般可以 as Array<T>
|
||||
|
||||
================================================================================
|
||||
十、常见错误速查
|
||||
十一、常见错误速查
|
||||
================================================================================
|
||||
|
||||
1. "Unresolved reference" - 函数未定义或顺序错误
|
||||
@@ -179,7 +218,7 @@
|
||||
9. "参数类型不匹配" - 参数类型错误,需要显式类型转换
|
||||
|
||||
================================================================================
|
||||
十一、简明速记(100+条)
|
||||
十二、简明速记(100+条)
|
||||
================================================================================
|
||||
|
||||
1. 表单优先用 form 组件
|
||||
@@ -197,84 +236,89 @@
|
||||
13. 类型推断严格,必要时用 as Type 明确类型
|
||||
14. 不支持 Intersection Type
|
||||
15. picker 用 picker-view 或 uni.showActionSheet 替代
|
||||
16. 样式只支持 display: flex,不支持 gap、grid、calc()、伪类选择器
|
||||
16. 样式只支持 display: flex,不支持 gap、grid、calc()、伪类选择器、display: block
|
||||
17. scroll-view 用 direction="vertical"
|
||||
18. 不支持 table、grid、vh 单位、min-width: 100% 等
|
||||
19. 组件事件如 picker-view 用 UniPickerViewChangeEvent
|
||||
20. 时间选择用 uni_modules/lime-date-time-picker
|
||||
21. 类型转换建议用 utils/utis 下的 UTSJSONObject
|
||||
22. 在 uts setup 的 android 模式下,调用的函数必须在调用之前定义
|
||||
23. 箭头函数不支持默认参数值,改用显式传参或普通函数定义
|
||||
24. 不支持 Number()、String() 构造函数,用 as 类型转换
|
||||
25. 不支持 Object.keys(),用 JSON.stringify() 或 for 循环
|
||||
26. 不支持 typeof xxx === 'function',用 try-catch 替代
|
||||
27. 不支持 as unknown as 语法
|
||||
28. parseInt() 参数必须是 string 类型
|
||||
29. decodeURIComponent() 返回可空类型,需要处理 null
|
||||
30. charCodeAt() 返回可空类型,需要处理 null
|
||||
31. 不支持内联对象类型,需要在 types 文件中单独定义
|
||||
32. UTSJSONObject.get() 返回可空类型 Any?,需要处理 null 并转换为具体类型
|
||||
33. Array<any> 元素不能直接访问属性,需转换为 UTSJSONObject 或定义明确类型
|
||||
34. 类型定义中属性可能为 null 时,必须声明为可空类型(如 any | null)
|
||||
35. switch 语句在某些版本可能有问题,建议用 if-else 替代
|
||||
36. 模板中可选链 ?.length 需要改为显式判断:v-if="arr != null && arr.length > 0"
|
||||
37. 解构赋值 const { data, error } 在 UTS 中可能有问题,建议用 response.data 方式访问
|
||||
38. response.data 返回 Any?,赋值前需要判断 null 并类型转换
|
||||
39. 空数组 [] 无法推断类型,需要显式声明:let arr: Array<any> = [] 或先判断 null 再转换
|
||||
40. ref 对象字面量需要定义类型:const obj = ref<MyType>({...} as MyType),否则属性访问会报错
|
||||
41. if 条件必须是 boolean,可空类型要用 != null 判断,if (obj != null) 而非 if (obj)
|
||||
42. throw 语句不能抛出 Any 类型,需要处理错误而非抛出
|
||||
43. 模板中可选链 ?.property 需要改为三元表达式:obj != null ? obj.property : ''
|
||||
44. ref<any> 在模板中无法访问属性,必须定义明确类型,ref<MyType | null>(null)
|
||||
45. 展开运算符 [...arr] 不支持,需要手动复制数组
|
||||
46. Array.from(new Set()) 不支持,需要手动去重
|
||||
47. Promise.all 可能有问题,建议改为顺序执行
|
||||
48. .sort(() => Math.random() - 0.5) 随机排序不支持,需要手动实现
|
||||
49. 数组索引访问 arr[index] 可能越界,建议用 if-else 替代数组查找
|
||||
50. 事件对象 e.detail.value 需要转换为 UTSJSONObject 后访问
|
||||
51. String() 构造函数不支持,用 as string 类型转换
|
||||
52. 数组类型简写 string[] 需要改为 Array<string>
|
||||
53. any 类型参数不能直接访问属性,需要转换为 UTSJSONObject 后使用 get/getString/getNumber 方法
|
||||
54. 模板中 !变量 取反不支持,改为显式判断:v-if="str == ''" 或 v-if="bool == false"
|
||||
55. 模板中 :class="{ 'class': condition }" 对象语法可能有问题,改为三元表达式::class="condition ? 'class' : ''"
|
||||
56. supabase .update() 参数需要 UTSJSONObject 类型,用 new UTSJSONObject() 创建并用 .set() 设置属性
|
||||
57. ref<Array<any>> 在模板中无法访问元素属性,必须定义明确的类型后才能访问
|
||||
58. 函数参数可以用联合类型:func(item: TypeA | TypeB)
|
||||
59. JSON.stringify(UTSJSONObject) 可能有问题,需要手动拼接字符串
|
||||
60. UTSJSONObject.keys() 方法不存在,无法获取键列表
|
||||
61. 联合类型参数不能直接访问属性,需要先类型转换:const id = (item as TypeA).id
|
||||
62. 某些 uni API 可能不存在(如 navigateToMiniProgram),需要检查或替换
|
||||
63. JSON.parse(JSON.stringify(obj)) 复杂转换可能有问题,简化处理
|
||||
64. showModal success 回调不能是 async 函数,需要改为同步或使用 Promise
|
||||
65. supa.auth.signOut() 等 supabase auth 方法可能不支持,需要简化处理
|
||||
66. 模板中可空字符串判断 userInfo.phone ? 改为 userInfo.phone != null && userInfo.phone != ''
|
||||
67. Promise.all() 可能有问题,建议改为顺序执行或 setTimeout
|
||||
68. .then() 回调可能有问题,建议用 async/await 或直接调用
|
||||
69. let res: any = null 不支持,改为 let res: any = {} 或其他默认值
|
||||
70. 类型定义中没有的字段不能赋值,检查类型定义后移除多余字段
|
||||
71. ref<Array<any>> 在模板中无法访问元素属性,必须定义明确的类型
|
||||
72. 模板中复杂表达式如 parseFloat(String(x)) 不支持,简化为直接比较
|
||||
73. forEach 不支持,改用 for 循环
|
||||
74. any 类型数组元素不能直接访问属性,需转换为 UTSJSONObject
|
||||
75. showModal success 回调不能是 async 函数,需要改为同步调用独立 async 函数
|
||||
76. 被生命周期钩子调用的函数必须在钩子之前定义,包括 onMounted、watch、onUnmounted 等
|
||||
77. 箭头函数不支持默认参数值,改用显式传参或普通函数定义
|
||||
78. 对象字面量赋值给 ref<Type> 需要显式类型声明:const obj: Type = {...} as Type
|
||||
79. 模板中访问对象属性时,类型定义必须包含该属性,否则报 "找不到名称" 错误
|
||||
80. !variable 取反操作不支持,改为 variable == '' 或 variable == false
|
||||
81. supa.auth 方法不支持,需要简化处理或移除
|
||||
82. setInterval 回调中使用外部变量,需要先声明:let timer: number = 0,然后在回调中赋值
|
||||
83. $t() 国际化函数在模板中可能有问题,建议使用硬编码文本或自定义翻译函数
|
||||
84. profile.username ?? $t('xxx') 混合表达式不支持,改为条件判断:profile != null && profile.username != null ? profile.username : '默认值'
|
||||
85. 可选链操作符 ?. 在某些场景不支持,如 currentPage?.options,需要改为 if 判断
|
||||
86. as any[] 类型转换后无法访问属性,需要使用正确的类型如 UTSJSONObject
|
||||
87. 可空类型 string | null 传给需要 string 的函数,需要显式类型转换:redirect as string
|
||||
88. setInterval 回调中修改外部变量,需要用 ref 而不是 let 声明变量,避免 smart cast 问题
|
||||
89. 非空断言操作符 ! 在某些场景仍无法解决类型问题,建议简化逻辑避免复杂类型转换
|
||||
90. decodeURIComponent 函数参数类型严格,可空类型即便使用 ! 也可能报错,建议简化或避免使用
|
||||
91. getCurrentPages() 获取页面 options 复杂且容易出错,建议简化跳转逻辑
|
||||
92. 模板中内联箭头函数不支持类型注解,如 @input="(e: any) => ..." 会报错,改用 v-model
|
||||
93. :class="{ disabled: codeDisabled }" 对象语法可能有问题,改为三元表达式 :class="codeDisabled ? 'disabled' : ''"
|
||||
18. 不支持 table、grid、vh/vw 单位、min-height/max-height 百分比等
|
||||
19. font-weight 只支持 normal/bold/400/700,不支持 300/500/600 等数值
|
||||
20. border-radius 不支持百分比(50%),用具体像素值(9px)实现圆形
|
||||
21. line-height 不支持 normal,用具体数值(36px)或倍数(1.5)
|
||||
22. position 不支持 sticky,只支持 relative/absolute/fixed
|
||||
23. 不支持 outline、aspect-ratio、text-decoration 等 CSS 属性
|
||||
24. align-items 不支持 baseline,只支持 center/flex-start/flex-end/stretch
|
||||
25. 组件事件如 picker-view 用 UniPickerViewChangeEvent
|
||||
26. 时间选择用 uni_modules/lime-date-time-picker
|
||||
27. 类型转换建议用 utils/utis 下的 UTSJSONObject
|
||||
28. 在 uts setup 的 android 模式下,调用的函数必须在调用之前定义
|
||||
29. 箭头函数不支持默认参数值,改用显式传参或普通函数定义
|
||||
30. 不支持 Number()、String() 构造函数,用 as 类型转换
|
||||
31. 不支持 Object.keys(),用 JSON.stringify() 或 for 循环
|
||||
32. 不支持 typeof xxx === 'function',用 try-catch 替代
|
||||
33. 不支持 as unknown as 语法
|
||||
34. parseInt() 参数必须是 string 类型
|
||||
35. decodeURIComponent() 返回可空类型,需要处理 null
|
||||
36. charCodeAt() 返回可空类型,需要处理 null
|
||||
37. 不支持内联对象类型,需要在 types 文件中单独定义
|
||||
38. UTSJSONObject.get() 返回可空类型 Any?,需要处理 null 并转换为具体类型
|
||||
39. Array<any> 元素不能直接访问属性,需转换为 UTSJSONObject 或定义明确类型
|
||||
40. 类型定义中属性可能为 null 时,必须声明为可空类型(如 any | null)
|
||||
41. switch 语句在某些版本可能有问题,建议用 if-else 替代
|
||||
42. 模板中可选链 ?.length 需要改为显式判断:v-if="arr != null && arr.length > 0"
|
||||
43. 解构赋值 const { data, error } 在 UTS 中可能有问题,建议用 response.data 方式访问
|
||||
44. response.data 返回 Any?,赋值前需要判断 null 并类型转换
|
||||
45. 空数组 [] 无法推断类型,需要显式声明:let arr: Array<any> = [] 或先判断 null 再转换
|
||||
46. ref 对象字面量需要定义类型:const obj = ref<MyType>({...} as MyType),否则属性访问会报错
|
||||
47. if 条件必须是 boolean,可空类型要用 != null 判断,if (obj != null) 而非 if (obj)
|
||||
48. throw 语句不能抛出 Any 类型,需要处理错误而非抛出
|
||||
49. 模板中可选链 ?.property 需要改为三元表达式:obj != null ? obj.property : ''
|
||||
50. ref<any> 在模板中无法访问属性,必须定义明确类型,ref<MyType | null>(null)
|
||||
51. 展开运算符 [...arr] 不支持,需要手动复制数组
|
||||
52. Array.from(new Set()) 不支持,需要手动去重
|
||||
53. Promise.all 可能有问题,建议改为顺序执行
|
||||
54. .sort(() => Math.random() - 0.5) 随机排序不支持,需要手动实现
|
||||
55. 数组索引访问 arr[index] 可能越界,建议用 if-else 替代数组查找
|
||||
56. 事件对象 e.detail.value 需要转换为 UTSJSONObject 后访问
|
||||
57. String() 构造函数不支持,用 as string 类型转换
|
||||
58. 数组类型简写 string[] 需要改为 Array<string>
|
||||
59. any 类型参数不能直接访问属性,需要转换为 UTSJSONObject 后使用 get/getString/getNumber 方法
|
||||
60. 模板中 !变量 取反不支持,改为显式判断:v-if="str == ''" 或 v-if="bool == false"
|
||||
61. 模板中 :class="{ 'class': condition }" 对象语法可能有问题,改为三元表达式::class="condition ? 'class' : ''"
|
||||
62. supabase .update() 参数需要 UTSJSONObject 类型,用 new UTSJSONObject() 创建并用 .set() 设置属性
|
||||
63. ref<Array<any>> 在模板中无法访问元素属性,必须定义明确的类型后才能访问
|
||||
64. 函数参数可以用联合类型:func(item: TypeA | TypeB)
|
||||
65. JSON.stringify(UTSJSONObject) 可能有问题,需要手动拼接字符串
|
||||
66. UTSJSONObject.keys() 方法不存在,无法获取键列表
|
||||
67. 联合类型参数不能直接访问属性,需要先类型转换:const id = (item as TypeA).id
|
||||
68. 某些 uni API 可能不存在(如 navigateToMiniProgram),需要检查或替换
|
||||
69. JSON.parse(JSON.stringify(obj)) 复杂转换可能有问题,简化处理
|
||||
69. showModal success 回调不能是 async 函数,需要改为同步或使用 Promise
|
||||
70. supa.auth.signOut() 等 supabase auth 方法可能不支持,需要简化处理
|
||||
71. 模板中可空字符串判断 userInfo.phone ? 改为 userInfo.phone != null && userInfo.phone != ''
|
||||
72. .then() 回调可能有问题,建议用 async/await 或直接调用
|
||||
73. let res: any = null 不支持,改为 let res: any = {} 或其他默认值
|
||||
74. 类型定义中没有的字段不能赋值,检查类型定义后移除多余字段
|
||||
75. ref<Array<any>> 在模板中无法访问元素属性,必须定义明确的类型
|
||||
76. 模板中复杂表达式如 parseFloat(String(x)) 不支持,简化为直接比较
|
||||
77. forEach 不支持,改用 for 循环
|
||||
78. any 类型数组元素不能直接访问属性,需转换为 UTSJSONObject
|
||||
79. showModal success 回调不能是 async 函数,需要改为同步调用独立 async 函数
|
||||
80. 被生命周期钩子调用的函数必须在钩子之前定义,包括 onMounted、watch、onUnmounted 等
|
||||
81. 箭头函数不支持默认参数值,改用显式传参或普通函数定义
|
||||
82. 对象字面量赋值给 ref<Type> 需要显式类型声明:const obj: Type = {...} as Type
|
||||
83. 模板中访问对象属性时,类型定义必须包含该属性,否则报 "找不到名称" 错误
|
||||
84. !variable 取反操作不支持,改为 variable == '' 或 variable == false
|
||||
85. supa.auth 方法不支持,需要简化处理或移除
|
||||
86. setInterval 回调中使用外部变量,需要先声明:let timer: number = 0,然后在回调中赋值
|
||||
87. $t() 国际化函数在模板中可能有问题,建议使用硬编码文本或自定义翻译函数
|
||||
88. profile.username ?? $t('xxx') 混合表达式不支持,改为条件判断:profile != null && profile.username != null ? profile.username : '默认值'
|
||||
89. 可选链操作符 ?. 在某些场景不支持,如 currentPage?.options,需要改为 if 判断
|
||||
90. as any[] 类型转换后无法访问属性,需要使用正确的类型如 UTSJSONObject
|
||||
91. 可空类型 string | null 传给需要 string 的函数,需要显式类型转换:redirect as string
|
||||
92. setInterval 回调中修改外部变量,需要用 ref 而不是 let 声明变量,避免 smart cast 问题
|
||||
93. 非空断言操作符 ! 在某些场景仍无法解决类型问题,建议简化逻辑避免复杂类型转换
|
||||
94. decodeURIComponent 函数参数类型严格,可空类型即便使用 ! 也可能报错,建议简化或避免使用
|
||||
95. getCurrentPages() 获取页面 options 复杂且容易出错,建议简化跳转逻辑
|
||||
96. 模板中内联箭头函数不支持类型注解,如 @input="(e: any) => ..." 会报错,改用 v-model
|
||||
97. :class="{ disabled: codeDisabled }" 对象语法可能有问题,改为三元表达式 :class="codeDisabled ? 'disabled' : ''"
|
||||
94. 使用外部类型定义时,确保所有属性都有默认值,避免 null 导致类型不匹配
|
||||
95. Supabase insert/update 在 .uvue 文件中直接调用可能报类型错误,建议封装到 .uts 服务文件中调用
|
||||
96. 可空类型属性在模板中使用时需要处理 null:profile.gender ?? 'other'
|
||||
@@ -289,7 +333,7 @@
|
||||
105. 使用辅助函数 safeGetString、safeGetNumber 处理数据库字段
|
||||
|
||||
================================================================================
|
||||
十二、构造函数限制
|
||||
十三、构造函数限制
|
||||
================================================================================
|
||||
|
||||
1. 不支持 Number() 构造函数,使用 as number 类型转换
|
||||
@@ -297,7 +341,7 @@
|
||||
3. 示例:Number(x) → x as number,String(i) → i as string
|
||||
|
||||
================================================================================
|
||||
十三、取反操作符限制
|
||||
十四、取反操作符限制
|
||||
================================================================================
|
||||
|
||||
1. 不支持 !变量 的取反操作符用于判断空
|
||||
@@ -305,7 +349,7 @@
|
||||
3. 示例:!this.selectedSkuId → (this.selectedSkuId == null || this.selectedSkuId === '')
|
||||
|
||||
================================================================================
|
||||
十四、parseInt/parseFloat 限制
|
||||
十五、parseInt/parseFloat 限制
|
||||
================================================================================
|
||||
|
||||
1. parseInt() 参数必须是 string 类型
|
||||
@@ -313,7 +357,7 @@
|
||||
3. 示例:parseInt(this.quantity) 错误,quantity 是 number,直接用 this.quantity
|
||||
|
||||
================================================================================
|
||||
十五、Object.keys() 不支持
|
||||
十六、Object.keys() 不支持
|
||||
================================================================================
|
||||
|
||||
1. 不支持 Object.keys() 方法
|
||||
@@ -321,21 +365,21 @@
|
||||
3. UTSJSONObject 可用 .keys() 方法(但某些版本可能不支持)
|
||||
|
||||
================================================================================
|
||||
十六、typeof 函数检查不支持
|
||||
十七、typeof 函数检查不支持
|
||||
================================================================================
|
||||
|
||||
1. 不支持 typeof xxx === 'function' 语法
|
||||
2. 替代方案:使用 try-catch 包裹方法调用
|
||||
|
||||
================================================================================
|
||||
十七、as unknown as 语法不支持
|
||||
十八、as unknown as 语法不支持
|
||||
================================================================================
|
||||
|
||||
1. 不支持 as unknown as 双重类型转换
|
||||
2. 直接使用 as 目标类型:obj as UTSJSONObject
|
||||
|
||||
================================================================================
|
||||
十八、可空类型方法返回值
|
||||
十九、可空类型方法返回值
|
||||
================================================================================
|
||||
|
||||
1. decodeURIComponent() 返回 String?,需要处理 null
|
||||
@@ -343,7 +387,7 @@
|
||||
3. 示例:const code = str.charCodeAt(i); if (code != null) { ... }
|
||||
|
||||
================================================================================
|
||||
十九、内联对象类型不支持
|
||||
二十、内联对象类型不支持
|
||||
================================================================================
|
||||
|
||||
1. 不支持 Array<{id: string, name: string}> 这种内联类型定义
|
||||
@@ -351,28 +395,28 @@
|
||||
3. 示例:定义 type ItemType = { id: string, name: string },然后使用 Array<ItemType>
|
||||
|
||||
================================================================================
|
||||
二十、eventChannel 不支持
|
||||
二十一、eventChannel 不支持
|
||||
================================================================================
|
||||
|
||||
1. uni.navigateTo 的 success 回调中 res.eventChannel 不支持
|
||||
2. 替代方案:使用 Storage 或全局变量传递数据
|
||||
|
||||
================================================================================
|
||||
二十一、链式调用问题
|
||||
二十二、链式调用问题
|
||||
================================================================================
|
||||
|
||||
1. .map().join() 链式调用可能导致类型推断失败
|
||||
2. 替代方案:使用 for 循环或分步处理
|
||||
|
||||
================================================================================
|
||||
二十二、v-model 类型限制
|
||||
二十三、v-model 类型限制
|
||||
================================================================================
|
||||
|
||||
1. input 的 v-model 期望 string 类型
|
||||
2. 如果变量是 number,使用 :value="variable.toString()" 替代 v-model
|
||||
|
||||
================================================================================
|
||||
二十三、setup 模式函数定义顺序(重要)
|
||||
二十四、setup 模式函数定义顺序(重要)
|
||||
================================================================================
|
||||
|
||||
在 <script setup lang="uts"> 中,函数定义顺序至关重要:
|
||||
@@ -447,7 +491,7 @@
|
||||
- 解决:调整函数定义顺序,确保被调用的函数先定义
|
||||
|
||||
================================================================================
|
||||
二十四、箭头函数限制(重要)
|
||||
二十五、箭头函数限制(重要)
|
||||
================================================================================
|
||||
|
||||
1. 箭头函数不支持默认参数值
|
||||
@@ -475,7 +519,7 @@
|
||||
- 解决:移除默认参数,改用显式传参或普通函数定义
|
||||
|
||||
================================================================================
|
||||
二十五、数组元素属性访问(重要)
|
||||
二十六、数组元素属性访问(重要)
|
||||
================================================================================
|
||||
|
||||
1. Array<any> 元素属性访问问题
|
||||
@@ -505,7 +549,7 @@
|
||||
- 解决:转换为 UTSJSONObject 或定义明确类型
|
||||
|
||||
================================================================================
|
||||
二十六、类型定义与可空类型(重要)
|
||||
二十七、类型定义与可空类型(重要)
|
||||
================================================================================
|
||||
|
||||
1. 类型定义中可空类型的处理
|
||||
@@ -543,7 +587,7 @@
|
||||
- 解决:修改类型定义为可空类型,或处理 null 情况
|
||||
|
||||
================================================================================
|
||||
二十七、模板中的可空类型处理(重要)
|
||||
二十八、模板中的可空类型处理(重要)
|
||||
================================================================================
|
||||
|
||||
1. 模板中可选链限制
|
||||
@@ -563,7 +607,7 @@
|
||||
- 解决:显式判断 null 后再访问属性
|
||||
|
||||
================================================================================
|
||||
二十八、解构赋值限制(重要)
|
||||
二十九、解构赋值限制(重要)
|
||||
================================================================================
|
||||
|
||||
1. UTS 中解构赋值可能有问题
|
||||
@@ -583,7 +627,7 @@
|
||||
- 避免使用解构赋值
|
||||
|
||||
================================================================================
|
||||
二十九、API 响应数据处理(重要)
|
||||
三十、API 响应数据处理(重要)
|
||||
================================================================================
|
||||
|
||||
1. response.data 返回 Any? 类型
|
||||
@@ -630,7 +674,7 @@
|
||||
- 解决:显式声明数组类型
|
||||
|
||||
================================================================================
|
||||
三十、ref 对象字面量类型(重要)
|
||||
三十一、ref 对象字面量类型(重要)
|
||||
================================================================================
|
||||
|
||||
1. ref 对象字面量必须定义类型
|
||||
@@ -665,7 +709,7 @@
|
||||
- 解决:定义 type 并在 ref 中指定泛型类型
|
||||
|
||||
================================================================================
|
||||
三十一、if 条件与可空类型(重要)
|
||||
三十二、if 条件与可空类型(重要)
|
||||
================================================================================
|
||||
|
||||
1. if 条件必须是 boolean 类型
|
||||
@@ -695,7 +739,7 @@
|
||||
- 解决:使用 != null 判断
|
||||
|
||||
================================================================================
|
||||
三十二、throw 语句限制(重要)
|
||||
三十三、throw 语句限制(重要)
|
||||
================================================================================
|
||||
|
||||
1. throw 语句不能抛出 Any 类型
|
||||
@@ -727,7 +771,7 @@
|
||||
- 解决:处理错误而非抛出,或创建 Error 对象
|
||||
|
||||
================================================================================
|
||||
三十三、模板中的可选链与属性访问(重要)
|
||||
三十四、模板中的可选链与属性访问(重要)
|
||||
================================================================================
|
||||
|
||||
1. 模板中可选链限制
|
||||
@@ -769,7 +813,7 @@
|
||||
- 解决:定义明确类型,使用三元表达式代替可选链
|
||||
|
||||
================================================================================
|
||||
三十四、数组操作限制(重要)
|
||||
三十五、数组操作限制(重要)
|
||||
================================================================================
|
||||
|
||||
1. 展开运算符 [...arr] 不支持
|
||||
|
||||
@@ -2,54 +2,108 @@
|
||||
|
||||
## 一、功能概述
|
||||
|
||||
本文档描述商城消费者端的推销模式功能,包含以下三大模块:
|
||||
1. **分享免单系统** - 用户分享商品,达成条件后免单
|
||||
2. **会员等级系统** - 用户等级享受不同优惠价格
|
||||
3. **经销点返利系统** - 经销点销售返利
|
||||
本文档描述商城消费者端的推销模式功能,**该功能为商家级别功能**,即:
|
||||
|
||||
- **商家可自主开启/关闭**自己店铺的推销模式
|
||||
- 只有**开启了推销模式的商家**,其店铺订单才会显示"分享免单"按钮
|
||||
- **会员等级系统**为全局功能,适用于所有商家
|
||||
- **经销点返利系统**为商家级别功能,由商家自行配置
|
||||
|
||||
### 1.1 核心变更说明
|
||||
|
||||
| 功能模块 | 作用范围 | 说明 |
|
||||
|---------|---------|------|
|
||||
| 分享免单系统 | 商家级别 | 商家开启后,其订单才显示分享免单入口 |
|
||||
| 会员等级系统 | 全局 | 所有用户统一等级体系 |
|
||||
| 经销点返利系统 | 商家级别 | 商家自行创建和管理经销点 |
|
||||
| 用户余额系统 | 商家级别 | 每个商家有独立的用户余额池 |
|
||||
|
||||
---
|
||||
|
||||
## 二、分享免单系统
|
||||
## 二、商家推销模式配置
|
||||
|
||||
### 2.1 功能描述
|
||||
|
||||
用户购买商品后,可分享商品链接给其他用户(二级用户)。当二级用户通过分享链接购买该商品累计达到指定数量(默认4件)时,原用户可获得免单奖励,免单金额存入账户余额。
|
||||
|
||||
### 2.2 业务流程
|
||||
|
||||
```
|
||||
用户A购买商品 → 生成分享链接 → 分享给用户B/C/D
|
||||
↓
|
||||
二级用户通过链接购买
|
||||
↓
|
||||
累计购买数量达标(4件)
|
||||
↓
|
||||
用户A获得免单奖励
|
||||
↓
|
||||
奖励金额存入余额
|
||||
↓
|
||||
商家微信返现后清零余额
|
||||
```
|
||||
|
||||
### 2.3 数据库设计
|
||||
|
||||
#### 2.3.1 分享记录表 ml_share_records
|
||||
### 2.1 商家推销设置表 ml_merchant_promotion_config
|
||||
|
||||
| 字段名 | 类型 | 说明 |
|
||||
|--------|------|------|
|
||||
| id | UUID | 主键 |
|
||||
| merchant_id | UUID | 商家ID(关联ml_shops.merchant_id) |
|
||||
| promotion_enabled | BOOLEAN | 是否开启推销模式(默认false) |
|
||||
| share_free_enabled | BOOLEAN | 是否开启分享免单(默认false) |
|
||||
| distribution_enabled | BOOLEAN | 是否开启经销点返利(默认false) |
|
||||
| required_count | INT | 分享免单所需购买数(默认4) |
|
||||
| reward_type | VARCHAR(20) | 奖励类型:product_price-商品价格,fixed-固定金额 |
|
||||
| fixed_reward_amount | DECIMAL(10,2) | 固定奖励金额(reward_type=fixed时使用) |
|
||||
| created_at | TIMESTAMPTZ | 创建时间 |
|
||||
| updated_at | TIMESTAMPTZ | 更新时间 |
|
||||
|
||||
### 2.2 商家用户余额表 ml_merchant_user_balance
|
||||
|
||||
> 每个商家的用户余额独立计算,用户在不同商家有不同余额
|
||||
|
||||
| 字段名 | 类型 | 说明 |
|
||||
|--------|------|------|
|
||||
| id | UUID | 主键 |
|
||||
| merchant_id | UUID | 商家ID |
|
||||
| user_id | UUID | 用户ID |
|
||||
| balance | DECIMAL(10,2) | 当前余额 |
|
||||
| frozen_balance | DECIMAL(10,2) | 冻结余额 |
|
||||
| total_earned | DECIMAL(10,2) | 累计获得 |
|
||||
| total_withdrawn | DECIMAL(10,2) | 累计提现 |
|
||||
| updated_at | TIMESTAMPTZ | 更新时间 |
|
||||
| UNIQUE(merchant_id, user_id) | | 联合唯一约束 |
|
||||
|
||||
---
|
||||
|
||||
## 三、分享免单系统
|
||||
|
||||
### 3.1 功能描述
|
||||
|
||||
用户购买商品后,可分享商品链接给其他用户(二级用户)。当二级用户通过分享链接购买该商品累计达到指定数量时,原用户可获得免单奖励。
|
||||
|
||||
**重要变更:**
|
||||
- 只有开启了分享免单功能的商家,其订单才显示分享免单入口
|
||||
- 分享免单所需购买数由商家自行设置(默认4人)
|
||||
- 奖励金额可以是商品价格或固定金额
|
||||
|
||||
### 3.2 业务流程
|
||||
|
||||
```
|
||||
商家开启推销模式 → 用户购买商品 → 订单详情显示"分享免单"按钮
|
||||
↓
|
||||
用户点击创建分享记录
|
||||
↓
|
||||
分享给好友B/C/D
|
||||
↓
|
||||
好友通过分享码购买
|
||||
↓
|
||||
累计购买数量达标
|
||||
↓
|
||||
用户获得免单奖励
|
||||
↓
|
||||
奖励存入该商家下的用户余额
|
||||
```
|
||||
|
||||
### 3.3 数据库设计
|
||||
|
||||
#### 3.3.1 分享记录表 ml_share_records
|
||||
|
||||
| 字段名 | 类型 | 说明 |
|
||||
|--------|------|------|
|
||||
| id | UUID | 主键 |
|
||||
| merchant_id | UUID | 商家ID(新增) |
|
||||
| user_id | UUID | 分享用户ID |
|
||||
| product_id | UUID | 商品ID |
|
||||
| order_id | UUID | 关联订单ID |
|
||||
| share_code | VARCHAR(20) | 分享码(唯一) |
|
||||
| required_count | INT | 需要的购买数量(默认4) |
|
||||
| required_count | INT | 需要的购买数量 |
|
||||
| current_count | INT | 当前已购买数量 |
|
||||
| status | INT | 状态:0-进行中,1-已完成,2-已失效 |
|
||||
| reward_amount | DECIMAL(10,2) | 奖励金额 |
|
||||
| created_at | TIMESTAMPTZ | 创建时间 |
|
||||
| completed_at | TIMESTAMPTZ | 完成时间 |
|
||||
|
||||
#### 2.3.2 二级购买记录表 ml_secondary_purchases
|
||||
#### 3.3.2 二级购买记录表 ml_secondary_purchases
|
||||
|
||||
| 字段名 | 类型 | 说明 |
|
||||
|--------|------|------|
|
||||
@@ -60,60 +114,52 @@
|
||||
| quantity | INT | 购买数量 |
|
||||
| created_at | TIMESTAMPTZ | 创建时间 |
|
||||
|
||||
#### 2.3.3 免单奖励记录表 ml_free_order_rewards
|
||||
#### 3.3.3 免单奖励记录表 ml_free_order_rewards
|
||||
|
||||
| 字段名 | 类型 | 说明 |
|
||||
|--------|------|------|
|
||||
| id | UUID | 主键 |
|
||||
| merchant_id | UUID | 商家ID(新增) |
|
||||
| user_id | UUID | 获得奖励的用户ID |
|
||||
| share_record_id | UUID | 关联分享记录ID |
|
||||
| amount | DECIMAL(10,2) | 奖励金额 |
|
||||
| status | INT | 状态:0-待处理,1-已发放,2-已清零 |
|
||||
| balance_before | DECIMAL(10,2) | 发放前余额 |
|
||||
| balance_after | DECIMAL(10,2) | 发放后余额 |
|
||||
| cleared_at | TIMESTAMPTZ | 清零时间 |
|
||||
| cleared_by | UUID | 清零操作人 |
|
||||
| created_at | TIMESTAMPTZ | 创建时间 |
|
||||
|
||||
### 2.4 API 接口
|
||||
### 3.4 前端逻辑变更
|
||||
|
||||
| 接口 | 方法 | 说明 |
|
||||
|------|------|------|
|
||||
| /api/share/create | POST | 创建分享记录,生成分享码 |
|
||||
| /api/share/info | GET | 获取分享详情和进度 |
|
||||
| /api/share/validate | GET | 验证分享码有效性 |
|
||||
| /api/share/my-records | GET | 获取我的分享记录列表 |
|
||||
| /api/share/rewards | GET | 获取我的免单奖励记录 |
|
||||
| /api/admin/clear-balance | POST | 商家清零用户余额(后台) |
|
||||
#### 3.4.1 订单列表页/订单详情页
|
||||
|
||||
### 2.5 前端页面
|
||||
```typescript
|
||||
// 判断是否显示分享免单按钮
|
||||
async function checkShareFreeEnabled(merchantId: string): Promise<boolean> {
|
||||
const config = await supabaseService.getMerchantPromotionConfig(merchantId)
|
||||
return config?.promotion_enabled && config?.share_free_enabled
|
||||
}
|
||||
|
||||
#### 2.5.1 分享弹窗(订单详情页)
|
||||
- 显示分享链接/二维码
|
||||
- 显示当前进度(X/4)
|
||||
- 分享按钮(微信好友、朋友圈)
|
||||
// 在订单卡片中
|
||||
<view v-if="order.status >= 2 && order.status <= 4 && isShareFreeEnabled(order.merchant_id)"
|
||||
class="share-free-row" @click="shareForFree(order)">
|
||||
<text>🎁 分享免单</text>
|
||||
</view>
|
||||
```
|
||||
|
||||
#### 2.5.2 我的分享页
|
||||
- 分享记录列表
|
||||
- 每条记录显示:商品信息、进度、状态
|
||||
- 邀请好友按钮
|
||||
#### 3.4.2 我的余额页
|
||||
|
||||
#### 2.5.3 我的余额页
|
||||
- 余额显示
|
||||
- 免单奖励记录
|
||||
- 提现说明(联系商家微信)
|
||||
- 需要按商家分组显示余额
|
||||
- 或显示总余额,点击查看各商家余额明细
|
||||
|
||||
---
|
||||
|
||||
## 三、会员等级系统
|
||||
## 四、会员等级系统
|
||||
|
||||
### 3.1 功能描述
|
||||
### 4.1 功能描述
|
||||
|
||||
商家可设置多个会员等级,每个等级对应不同的优惠折扣。用户可通过以下方式升级:
|
||||
1. 商家手动设置等级
|
||||
2. 累计消费金额自动升级
|
||||
会员等级系统为**全局功能**,用户等级在所有商家通用。用户可通过累计消费金额自动升级,或由商家手动设置等级。
|
||||
|
||||
### 3.2 等级设置
|
||||
### 4.2 等级设置(全局配置)
|
||||
|
||||
| 等级 | 名称 | 升级条件 | 折扣 |
|
||||
|------|------|---------|------|
|
||||
@@ -124,92 +170,33 @@
|
||||
| 4 | 钻石会员 | 累计消费10000元 | 88折 |
|
||||
| 5 | VIP会员 | 商家手动设置 | 85折 |
|
||||
|
||||
### 3.3 数据库设计
|
||||
### 4.3 数据库设计
|
||||
|
||||
#### 3.3.1 会员等级配置表 ml_member_levels
|
||||
|
||||
| 字段名 | 类型 | 说明 |
|
||||
|--------|------|------|
|
||||
| id | INT | 等级ID |
|
||||
| name | VARCHAR(50) | 等级名称 |
|
||||
| min_amount | DECIMAL(10,2) | 升级最低消费金额 |
|
||||
| discount | DECIMAL(5,4) | 折扣率(0.85表示85折) |
|
||||
| icon | VARCHAR(200) | 等级图标 |
|
||||
| description | TEXT | 等级说明 |
|
||||
| sort_order | INT | 排序 |
|
||||
| status | INT | 状态:0-禁用,1-启用 |
|
||||
|
||||
#### 3.3.2 用户会员信息扩展(ml_user_profiles 扩展字段)
|
||||
|
||||
| 字段名 | 类型 | 说明 |
|
||||
|--------|------|------|
|
||||
| member_level | INT | 当前会员等级 |
|
||||
| total_spent | DECIMAL(10,2) | 累计消费金额 |
|
||||
| level_updated_at | TIMESTAMPTZ | 等级更新时间 |
|
||||
| manual_level | BOOLEAN | 是否手动设置等级 |
|
||||
| manual_level_by | UUID | 手动设置操作人 |
|
||||
|
||||
#### 3.3.3 会员等级变更记录表 ml_member_level_logs
|
||||
|
||||
| 字段名 | 类型 | 说明 |
|
||||
|--------|------|------|
|
||||
| id | UUID | 主键 |
|
||||
| user_id | UUID | 用户ID |
|
||||
| old_level | INT | 原等级 |
|
||||
| new_level | INT | 新等级 |
|
||||
| reason | VARCHAR(200) | 变更原因 |
|
||||
| operator_id | UUID | 操作人(自动则为空) |
|
||||
| created_at | TIMESTAMPTZ | 创建时间 |
|
||||
|
||||
### 3.4 API 接口
|
||||
|
||||
| 接口 | 方法 | 说明 |
|
||||
|------|------|------|
|
||||
| /api/member/levels | GET | 获取会员等级列表 |
|
||||
| /api/member/my-info | GET | 获取我的会员信息 |
|
||||
| /api/member/upgrade-check | POST | 检查并升级会员等级 |
|
||||
| /api/admin/set-member-level | POST | 商家手动设置用户等级 |
|
||||
|
||||
### 3.5 前端页面
|
||||
|
||||
#### 3.5.1 会员中心页
|
||||
- 当前等级显示
|
||||
- 等级进度条
|
||||
- 等级权益说明
|
||||
- 升级攻略
|
||||
|
||||
#### 3.5.2 商品详情页
|
||||
- 显示会员价
|
||||
- 显示折扣信息
|
||||
保持原有设计不变,会员等级为全局配置。
|
||||
|
||||
---
|
||||
|
||||
## 四、经销点返利系统
|
||||
## 五、经销点返利系统
|
||||
|
||||
### 4.1 功能描述
|
||||
### 5.1 功能描述
|
||||
|
||||
商家可创建多个经销点,每个经销点有独立的推广码。经销点通过推广码产生的订单可获得返利,返利按单数计算。
|
||||
商家可创建多个经销点,每个经销点有独立的推广码。经销点通过推广码产生的订单可获得返利。
|
||||
|
||||
### 4.2 返利规则
|
||||
**重要变更:**
|
||||
- 经销点返利为商家级别功能
|
||||
- 商家需先开启经销点功能才能使用
|
||||
|
||||
| 单数范围 | 返利金额/单 |
|
||||
|---------|------------|
|
||||
| 1-10单 | 2元/单 |
|
||||
| 11-50单 | 3元/单 |
|
||||
| 51-100单 | 4元/单 |
|
||||
| 100单以上 | 5元/单 |
|
||||
### 5.2 数据库设计
|
||||
|
||||
### 4.3 数据库设计
|
||||
|
||||
#### 4.3.1 经销点表 ml_distribution_points
|
||||
#### 5.2.1 经销点表 ml_distribution_points
|
||||
|
||||
| 字段名 | 类型 | 说明 |
|
||||
|--------|------|------|
|
||||
| id | UUID | 主键 |
|
||||
| merchant_id | UUID | 商家ID(新增) |
|
||||
| name | VARCHAR(100) | 经销点名称 |
|
||||
| contact_name | VARCHAR(50) | 联系人 |
|
||||
| contact_phone | VARCHAR(20) | 联系电话 |
|
||||
| address | VARCHAR(200) | 地址 |
|
||||
| invite_code | VARCHAR(20) | 邀请码(唯一) |
|
||||
| owner_id | UUID | 负责人用户ID |
|
||||
| status | INT | 状态:0-禁用,1-启用 |
|
||||
@@ -218,156 +205,92 @@
|
||||
| balance | DECIMAL(10,2) | 可提现余额 |
|
||||
| created_at | TIMESTAMPTZ | 创建时间 |
|
||||
|
||||
#### 4.3.2 经销点订单关联表 ml_distribution_orders
|
||||
|
||||
| 字段名 | 类型 | 说明 |
|
||||
|--------|------|------|
|
||||
| id | UUID | 主键 |
|
||||
| distribution_id | UUID | 经销点ID |
|
||||
| order_id | UUID | 订单ID |
|
||||
| user_id | UUID | 下单用户ID |
|
||||
| order_amount | DECIMAL(10,2) | 订单金额 |
|
||||
| rebate_amount | DECIMAL(10,2) | 返利金额 |
|
||||
| status | INT | 状态:0-待结算,1-已结算 |
|
||||
| settled_at | TIMESTAMPTZ | 结算时间 |
|
||||
| created_at | TIMESTAMPTZ | 创建时间 |
|
||||
|
||||
#### 4.3.3 返利配置表 ml_rebate_config
|
||||
|
||||
| 字段名 | 类型 | 说明 |
|
||||
|--------|------|------|
|
||||
| id | UUID | 主键 |
|
||||
| min_orders | INT | 最小单数 |
|
||||
| max_orders | INT | 最大单数 |
|
||||
| rebate_per_order | DECIMAL(10,2) | 每单返利金额 |
|
||||
| status | INT | 状态 |
|
||||
|
||||
#### 4.3.4 返利提现记录表 ml_rebate_withdrawals
|
||||
|
||||
| 字段名 | 类型 | 说明 |
|
||||
|--------|------|------|
|
||||
| id | UUID | 主键 |
|
||||
| distribution_id | UUID | 经销点ID |
|
||||
| amount | DECIMAL(10,2) | 提现金额 |
|
||||
| status | INT | 状态:0-待处理,1-已完成,2-已拒绝 |
|
||||
| handled_by | UUID | 处理人 |
|
||||
| handled_at | TIMESTAMPTZ | 处理时间 |
|
||||
| created_at | TIMESTAMPTZ | 创建时间 |
|
||||
|
||||
### 4.4 API 接口
|
||||
|
||||
| 接口 | 方法 | 说明 |
|
||||
|------|------|------|
|
||||
| /api/distribution/info | GET | 获取经销点信息 |
|
||||
| /api/distribution/orders | GET | 获取经销点订单列表 |
|
||||
| /api/distribution/rebate-summary | GET | 获取返利统计 |
|
||||
| /api/distribution/withdraw | POST | 申请提现 |
|
||||
| /api/admin/distributions | GET | 获取经销点列表(后台) |
|
||||
| /api/admin/create-distribution | POST | 创建经销点(后台) |
|
||||
| /api/admin/settle-rebate | POST | 结算返利(后台) |
|
||||
|
||||
### 4.5 前端页面
|
||||
|
||||
#### 4.5.1 经销点中心页(经销点负责人)
|
||||
- 经销点信息
|
||||
- 今日/本月订单数
|
||||
- 累计返利
|
||||
- 可提现余额
|
||||
- 申请提现按钮
|
||||
|
||||
#### 4.5.2 经销点订单页
|
||||
- 订单列表
|
||||
- 筛选(日期、状态)
|
||||
- 每单返利金额显示
|
||||
|
||||
---
|
||||
|
||||
## 五、用户余额系统
|
||||
## 六、余额变动记录表
|
||||
|
||||
### 5.1 数据库设计
|
||||
|
||||
#### 5.1.1 用户余额表 ml_user_balance
|
||||
### 6.1 ml_balance_records(按商家区分)
|
||||
|
||||
| 字段名 | 类型 | 说明 |
|
||||
|--------|------|------|
|
||||
| id | UUID | 主键 |
|
||||
| merchant_id | UUID | 商家ID(新增) |
|
||||
| user_id | UUID | 用户ID |
|
||||
| balance | DECIMAL(10,2) | 当前余额 |
|
||||
| frozen_balance | DECIMAL(10,2) | 冻结余额 |
|
||||
| total_earned | DECIMAL(10,2) | 累计获得 |
|
||||
| total_withdrawn | DECIMAL(10,2) | 累计提现 |
|
||||
| updated_at | TIMESTAMPTZ | 更新时间 |
|
||||
|
||||
#### 5.1.2 余额变动记录表 ml_balance_records
|
||||
|
||||
| 字段名 | 类型 | 说明 |
|
||||
|--------|------|------|
|
||||
| id | UUID | 主键 |
|
||||
| user_id | UUID | 用户ID |
|
||||
| type | VARCHAR(50) | 类型:free_order-免单,rebate-返利,withdraw-提现,clear-清零 |
|
||||
| amount | DECIMAL(10,2) | 变动金额(正数增加,负数减少) |
|
||||
| type | VARCHAR(50) | 类型 |
|
||||
| amount | DECIMAL(10,2) | 变动金额 |
|
||||
| balance_before | DECIMAL(10,2) | 变动前余额 |
|
||||
| balance_after | DECIMAL(10,2) | 变动后余额 |
|
||||
| related_id | UUID | 关联ID |
|
||||
| description | VARCHAR(200) | 描述 |
|
||||
| operator_id | UUID | 操作人(系统操作为空) |
|
||||
| operator_id | UUID | 操作人 |
|
||||
| created_at | TIMESTAMPTZ | 创建时间 |
|
||||
|
||||
---
|
||||
|
||||
## 六、前端页面汇总
|
||||
## 七、API 接口变更
|
||||
|
||||
### 6.1 消费者端新增页面
|
||||
### 7.1 新增接口
|
||||
|
||||
| 页面 | 路径 | 说明 |
|
||||
| 接口 | 方法 | 说明 |
|
||||
|------|------|------|
|
||||
| 我的分享 | /pages/mall/consumer/share/my-shares | 分享记录列表 |
|
||||
| 分享详情 | /pages/mall/consumer/share/detail | 分享进度详情 |
|
||||
| 我的余额 | /pages/mall/consumer/balance/index | 余额和奖励记录 |
|
||||
| 会员中心 | /pages/mall/consumer/member/index | 会员等级信息 |
|
||||
| 会员权益 | /pages/mall/consumer/member/benefits | 等级权益说明 |
|
||||
| /api/merchant/promotion-config | GET | 获取商家推销配置 |
|
||||
| /api/merchant/user-balance | GET | 获取用户在某商家的余额 |
|
||||
| /api/merchant/user-balance-list | GET | 获取用户所有商家余额列表 |
|
||||
|
||||
### 6.2 经销点端页面(可选独立入口)
|
||||
### 7.2 修改接口
|
||||
|
||||
| 页面 | 路径 | 说明 |
|
||||
|------|------|------|
|
||||
| 经销点中心 | /pages/distribution/index | 经销点首页 |
|
||||
| 经销点订单 | /pages/distribution/orders | 订单列表 |
|
||||
| 返利记录 | /pages/distribution/rebates | 返利记录 |
|
||||
| 提现申请 | /pages/distribution/withdraw | 提现页面 |
|
||||
| 接口 | 变更说明 |
|
||||
|------|---------|
|
||||
| /api/share/create | 新增merchant_id参数 |
|
||||
| /api/share/my-records | 按merchant_id筛选 |
|
||||
| /api/balance/info | 新增merchant_id参数 |
|
||||
|
||||
---
|
||||
|
||||
## 七、开发优先级
|
||||
## 八、前端页面变更
|
||||
|
||||
### 第一阶段(核心功能)
|
||||
1. 用户余额系统
|
||||
2. 分享免单系统
|
||||
3. 会员等级系统
|
||||
### 8.1 消费者端
|
||||
|
||||
### 第二阶段(扩展功能)
|
||||
1. 经销点返利系统
|
||||
2. 后台管理功能
|
||||
3. 数据统计报表
|
||||
| 页面 | 变更说明 |
|
||||
|------|---------|
|
||||
| 订单列表/详情 | 根据商家配置显示分享免单按钮 |
|
||||
| 我的余额 | 按商家分组显示余额,或显示余额列表 |
|
||||
| 我的分享 | 按商家筛选分享记录 |
|
||||
|
||||
### 8.2 商家端(新增)
|
||||
|
||||
| 页面 | 说明 |
|
||||
|------|------|
|
||||
| 推销模式设置 | 开启/关闭分享免单、经销点功能 |
|
||||
| 用户余额管理 | 查看用户余额、清零操作 |
|
||||
| 经销点管理 | 创建、编辑经销点 |
|
||||
|
||||
---
|
||||
|
||||
## 八、注意事项
|
||||
## 九、开发优先级
|
||||
|
||||
1. **安全性**
|
||||
- 分享码唯一且不可预测
|
||||
- 防止刷单作弊(同一用户多次购买不计入)
|
||||
- 余额变动需有完整记录
|
||||
### 第一阶段
|
||||
1. 商家推销配置表(SQL)
|
||||
2. 修改用户余额表结构(按商家区分)
|
||||
3. 修改分享记录表结构(添加merchant_id)
|
||||
4. 前端:根据商家配置显示分享免单按钮
|
||||
|
||||
2. **性能**
|
||||
- 高频查询使用缓存
|
||||
- 大数据量分页处理
|
||||
### 第二阶段
|
||||
1. 商家端推销模式设置页面
|
||||
2. 用户余额按商家分组显示
|
||||
3. 经销点返利系统
|
||||
|
||||
3. **合规性**
|
||||
- 返利模式需符合当地法规
|
||||
- 用户协议需明确说明规则
|
||||
---
|
||||
|
||||
4. **扩展性**
|
||||
- 返利规则可配置
|
||||
- 会员等级可扩展
|
||||
- 支持多种分享渠道
|
||||
## 十、SQL变更清单
|
||||
|
||||
需要执行以下SQL变更:
|
||||
|
||||
1. **新增商家推销配置表** `ml_merchant_promotion_config`
|
||||
2. **修改用户余额表** 添加merchant_id字段,改为联合唯一约束
|
||||
3. **修改分享记录表** 添加merchant_id字段
|
||||
4. **修改余额记录表** 添加merchant_id字段
|
||||
5. **修改免单奖励表** 添加merchant_id字段
|
||||
6. **修改经销点表** 添加merchant_id字段
|
||||
|
||||
详细SQL语句见:`promotion_system_tables_v2.sql`
|
||||
|
||||
Reference in New Issue
Block a user