diff --git a/开发文档/.github/workflows/sync_from_coding.yml b/开发文档/.github/workflows/sync_from_coding.yml deleted file mode 100644 index bf82de99..00000000 --- a/开发文档/.github/workflows/sync_from_coding.yml +++ /dev/null @@ -1,36 +0,0 @@ -name: Sync from Coding - -on: - schedule: - - cron: '0 */2 * * *' # 每2小时执行一次 - workflow_dispatch: # 允许手动触发 - -jobs: - sync: - runs-on: ubuntu-latest - permissions: - contents: write # 确保此行存在,赋予工作流写入仓库内容的权限,这是解决 403 权限问题的基础 - steps: - - name: 检出 GitHub 仓库 - uses: actions/checkout@v4 - with: - ref: develop # 明确检出 develop 分支,确保在正确的分支上操作 - - - name: 配置 Git 用户并合并 Coding 代码到 GitHub - run: | - # 配置 Git 用户信息 - git config user.name "zhiqun@qq.com" - git config user.email "zhiqun@qq.com" - - # 添加 Coding 仓库为一个新的远程源 - git remote add coding-origin https://${{ secrets.CODING_USERNAME }}:${{ secrets.CODING_TOKEN }}@e.coding.net/g-xtcy5189/cunkebao/cunkebao_v3.git - - # 从 Coding 远程仓库获取 develop 分支的最新信息 - git fetch coding-origin develop - - # 合并 Coding 的 develop 分支到本地的 develop 分支 - # --allow-unrelated-histories 允许合并两个没有共同历史的分支 - git merge --no-ff --allow-unrelated-histories coding-origin/develop - - # 将合并后的本地 develop 分支推送到 GitHub 的 develop 分支 - git push origin develop diff --git a/开发文档/10、项目管理/产研团队 第21场 20260129 许永平.txt b/开发文档/10、项目管理/产研团队 第21场 20260129 许永平.txt deleted file mode 100644 index b2bba7a3..00000000 --- a/开发文档/10、项目管理/产研团队 第21场 20260129 许永平.txt +++ /dev/null @@ -1,3738 +0,0 @@ -2026年1月29日 下午 5:17|2小时 6分钟 10秒 - -关键词: -付款、标签、微信、数据库、程序、吸收、飞书、后台、分销、虚拟环境、数据中心、用户管理、用户绑定、流量自动化、用户中心、数据统计、用户数据、文档管理 - -文字记录: -许永平 00:02 -录制吗?哦,可以了,都有加入会议签到一下,记得签,就我没签,我今天这边还是在做那个。上面投屏一下。对,这是昨天的不好操作。 - -许永平 00:34 -从第二点开始。第二点,数据中心加权限管理。上面的也总结哈。就除了。 MBTI 版 30 分钟 API 开放管。最新版的可以看一下位置在哪? SDK 了,我这边的话就权限管理,这是昨天的。昨天的。你们要,嗯,让老王那个你手机也要加入一下。哪一个? - -卡若 01:00 -会议,这样才能看到你的内容。 - -许永平 01:00 -行。 - -卡若 01:03 -你加他说话的时候,到时候会更。 - -许永平 01:03 -你加他之后会更。 - -卡若 01:06 -会更容易一次给你加字幕。 - -许永平 01:06 -会更好回忆。会给你加字幕,你可以声音关小了,但是有录就好,我这边可以把声音都关掉,反正我们都听得见。 - -卡若 01:08 -那你可以声音关小,但是有录音就行,我这边可以把声音都关掉,那我来听一听。 - -许永平 01:17 -行,我加一下会议。 - -卡若 01:22 -这是昨天的,昨天我这边数据中心加权限了,那一块开放的,是开放的,然后这边有一个提现的流程。 - -许永平 01:22 -这是昨天的,昨天我这边数据中心加权限管控那一块开放的,是开放完了,然后这边有一个提现流程的。以及 MBTI 30 分钟重要重构的一些逻辑,还有碎片化剪辑加时间。 - -卡若 01:33 -以及 NPS 30 分钟重会重构的一些逻辑,而序列化统一在时间最后的话是这个材料的吸收就是有一些用法,一些AI,一个是AI,大概这是昨天的内容,今天的话我这边就已经投入到这个接入 AI 模型这里处理了。 - -许永平 01:43 -最后的话是这个材料吸收就是有一些用法,一些就是一些 AI 体词的一些用法,挺好的,大概这是昨天的内容,今天的话我这边就已经投入到这个接入 AI 模型这里。处理了,我之前停下来了,现在就是要把它做了,做的再做一些预设的东西。 - -卡若 02:04 -之前停下来的,现在就是要把它做了,做的再做一些预设的东西,接下来,然后有一个问题。 - -许永平 02:11 -接下来,然后有一个问题是我那个本地的模型好像有点智障了。 - -卡若 02:14 -是我那个本地的模型好像有点智障啊。你跑本地的肯定是这样啊。 - -许永平 02:18 -跑本地。 - -卡若 02:19 -那我现在有很多。 - -许永平 02:19 -那我现在有没有比较好的代替哦? - -卡若 02:21 -你为什么要跑本地模型呢?我问问,就是昨天我问过那个LLAMA,我觉得这个模型去处理一些什么采集的,应该不需要太高级的模型吧? - -许永平 02:24 -问问。就是昨天有问过那个LLAMA,我觉得你这个模型去处理一些什么采集的,应该不需要太高级的模。 - -卡若 02:33 -哼,你这。 - -许永平 02:34 -还是说。 - -卡若 02:34 -还是说。本地的不好用,本地的不是这么用的,这个再说吧,你先过一下嘛。 - -许永平 02:39 -就是再说吧。 - -卡若 02:41 -行,然后其他的是老王这边,其他这些本来要读图书里的平台。 - -许永平 02:42 -行,然后其他的事,老王这边其他这些本来要弄读书,你那边不要再讨论。 - -卡若 02:48 -就那接口那些东西弄得咋样?就像我刚刚说的那几个东西。你。 - -许永平 02:54 -你。 - -卡若 02:55 -对啊。 - -许永平 02:55 -对啊。 - -卡若 02:56 -截,早上截图那个,是吧? - -许永平 02:56 -早截,早上截图那个,是吧? - -卡若 02:58 -是。就我刚发群里的那些,你得。 - -许永平 02:59 -是。 - -卡若 03:00 -底下一个标签计划,不算标签的计划。 - -许永平 03:01 -你那个标签。哦,那个我得,我还得,再,我还得写现在这个他是跑全部的,那我要写是独立。 - -卡若 03:04 -你得有接口过来啊。那个我得,我还得,再,我还得写现在这个他是跑全部的。不是,就是我现在小程序弄完了。对吧?那我现在需要接口给我。 - -许永平 03:15 -那我现在就要接。 - -卡若 03:16 -然后让我把这一些数据传到我们中台,跟把中台来完善我的数据怎么处理。这个我目前是直接抓传到中台就存客宝了。 - -许永平 03:29 -传到中台就什么宝吗? - -卡若 03:31 -这不管做,存。存客宝还是中台嘛?就是你现在弄的这个,我怎么样清洗数据过来和我的数据那个合并到那个上面去,你得有一个东西吧。是要的。 - -许永平 03:44 -是要的,那这个得要固定格式了。 - -卡若 03:44 -是不是我?这个得要固定格式吗?也不一定固定,就是我现在,像我现在要调,我怎么调嘛? - -许永平 03:48 -不一定固定,就我现在像我这边要调调。 - -卡若 03:52 -调,我是有开放,不是有开放接口吗? - -许永平 03:52 -调,我是有开放,不是有开放接口了吗? - -卡若 03:55 -那接口在哪? - -许永平 03:56 -接口在哪? - -卡若 03:56 -说明有吗? - -许永平 03:57 -有文档,这,对,我把文档发一下。 - -卡若 03:57 -对对,我把文档发你。 - -许永平 04:01 -发过去。 - -卡若 04:05 -开发完了就这条吗? - -许永平 04:05 -好,就这个吧。 - -许永平 04:15 -总道路产能群。 - -卡若 04:17 -我现在这两个是搜索的。 - -许永平 04:18 -不过现在这两个是搜索的,你这边是要存到数据中心标签里的,是吧? - -卡若 04:22 -这边是要存到数据中心标签里面的,是吧?存跟查跟完善呢。 - -许永平 04:27 -存的查。 - -卡若 04:29 -目前开放的是两个来查询的,因为。 - -许永平 04:29 -目前开放的是两个来查询的。 - -卡若 04:32 -这边上查到那个存客宝。 - -许永平 04:32 -因为这边是要查到那个乘客的。 - -卡若 04:34 -就我怎么操作? - -许永平 04:35 -就我怎么操作的地方,是吧? - -卡若 04:36 -我现在操作的地方我都不知道。就我怎么操作? - -许永平 04:40 -就我怎么操作? - -卡若 04:40 -我就我们正常存客宝那边,就是如果有就弄了两个,你给我一个接口就可以了,让我自己去调,就这一个。 - -许永平 04:42 -就我们正常使用的时候就漏了两个,给我一个接口。让我自己去调。那我得部,我还没部署,我得部署一下,我看他本地停,我部署一个吧。 - -卡若 04:51 -我还没部署呢,我得部署一下,开个本地部署一个。就大概长啥样? - -许永平 04:55 -大概咋样去拍你这些接口都是那个。 - -卡若 04:56 -去哪里拿?这些接口我都是蒙的,我自己弄的时候我接不上,知道就。 - -许永平 05:00 -那个时候接不上。 - -卡若 05:02 -比如我现在那些数据完善,包括那些。 - -许永平 05:02 -行。我现在那些完善,包括那些。 - -卡若 05:05 -数据完善。 - -许永平 05:06 -数据完善,那现在还有个问题,你是打算存什么东西? - -卡若 05:06 -是吧?现在还有个问题,你是打算存什么东西?还是说你直接想把数据库丢到拉萨呢? - -许永平 05:10 -还是说你直接想把数据库丢到拉索呢? - -卡若 05:12 -我,我不用,我就存到。 - -许永平 05:13 -不用吧。因为我现在开放的就只有查询,我开放只有查询。 - -卡若 05:14 -现在开放的就只有查询,我开放只有查询。就是查询跟接入这两个都是一回事,就以我现在这个小程序写完了,写完之后小程序这些用户我得完善到我们的那个数据中台啊。 - -许永平 05:19 -就是查数据,这两个都是一回事的,我现在这个小程序在写完之后,小程序的一些用户会完善到我们的。 - -卡若 05:33 -是不是你得给我一个地方传进来,对吧? - -许永平 05:34 -你得给我一个地方传进来,对吧? - -卡若 05:37 -第二个的话我得调,我得从中台调数据去完善我的呀。 - -许永平 05:37 -第二个的话调,从中台调数据去测流量。 - -卡若 05:42 -哦,这样,这个交互了完善。 - -许永平 05:43 -这样子,这个交互再想想。 - -卡若 05:45 -是不是? - -许永平 05:46 -就是。那这个标题,那这个数据现在的模式是这样的,我们 lark 上有很多数据库,我是从那个那里面直接把数据库就统整合。 - -卡若 05:58 -那里面直接把身份证都跑整合整。 - -许永平 06:02 -整合取到那个数据中心的,那你这边的话其实也是可以直接把数据库丢到门店大厂来,我觉得也不行。 - -卡若 06:03 -提到这个数据中心的,那你这边的话其实也是可以直接把数据库丢到我们一定要返回的一个集群。我肯定不可能丢拉萨,就是我只要调你给我数据,对吧? - -许永平 06:10 -我肯定不可能丢到大厂,就是我只要调给我数,对吧? - -卡若 06:14 -那你数据你怎么给我? - -许永平 06:14 -那你数据你怎么给? - -卡若 06:16 -那这样,我就针对你这个项目再做一遍。 - -许永平 06:16 -那这样,我就针对你这个项目再构建。 - -卡若 06:19 -不用,不要这样,任何项目就都要一遍的,就是我怎么查嘛? - -许永平 06:24 -就是我。 - -卡若 06:25 -就比如我现在用户里面,用户。 - -许永平 06:27 -查,查的话文档这里是有的,我们看一下,能查,现在我。 - -卡若 06:28 -这里是有了,我们看一下能查,现在我这。你要纠结的是你数据要传给我,我要怎么去处理这些东西? - -许永平 06:32 -我现在比较纠结的是你数据要传给我,我要怎么去存你这些东西? - -卡若 06:36 -对啊,那这个不是有一个那个 AI 的那个标签的那个东西吗? - -许永平 06:36 -对,那这个不是 AI 标签,没有看到,你知道就我们的数据都还是作用在哪去使用的这种没有看到。 - -卡若 06:39 -那个我没有看到,知道吧?我没有看到,我也不知道这个东西怎么去弄,就我们这个数据中台的作用在哪里?怎么样去使用它?重点的是这个我没有看到,知道吗? - -许永平 06:55 -我想想,我现在我得找。 - -卡若 06:56 -那我正常如果自己查询,我本机查一下就完事了,我无非把这些用户导出来在本地数据。 - -许永平 06:57 -那我正常如果自己查,我可以去查一下,会把这个用户导出来。 - -卡若 07:02 -误查一下就完事了,那我们有没有接口能查吗? - -许永平 07:05 -那我们有没有接口可以查吧? - -卡若 07:07 -接口有这个现在是可以查的。 - -许永平 07:07 -接口有这个现在是可以查的,这个的话是昨天有一个,不是有个 IPR key 的管理吗? - -卡若 07:11 -跟他操作,怎么怎么操作?怎么操作?怎么去对接,这个比较重要。昨天有一个是 IPIP 的管理吗? - -许永平 07:30 -我觉得我得把它马上部署出来,不然。对啊。 - -卡若 07:33 -这个是t,然后你拉一个t,这是 80 区。 - -许永平 07:38 -我昨天应该是有个这个吗? - -卡若 07:43 -就你们,你。 - -许永平 07:44 -这个先首先要在这边创一个key,有个 key 管理,等一下我部署,马上部署,然后部署完之后这边你创一个key,然后你等下接完文档的时候,你。 - -卡若 07:44 -这首先要在这边创一个t,我要t,等一下,我部署了,马上,然后部署完到这边你创一个t,然后你等一下接文档的时候,你把这个带到那个请求头部,你就把这个替换请求头。 - -许永平 08:02 -对吧? - -卡若 08:08 -先看一下嘛。 - -许永平 08:09 -到那个开启不错,这个地方。 - -许永平 08:48 -创建完 key 之后,就是在请求这个权限校验 key 传过来就好了,然后你就可以存。 - -卡若 08:49 -就是在请求从这边这一个一个学费校验,把这个替换了就好,然后你就可以传。这个是属于传,那我要拿数据嘞?对,再就是拉数据,然后你传的那个我没写,反正你现在提了一下午。 - -许永平 09:02 -对,这就是拉数据,然后你传的那个我没洗嘛传的,你现在提了一下午。 - -卡若 09:08 -就是我传给你。 - -许永平 09:08 -就是我传给。我。 - -卡若 09:09 -就远志那个,你要申测所那边那些完成了哪一些或者怎么样? - -许永平 09:13 -完成的联系,或者现在这一次。 - -卡若 09:15 -什么情况我现在是不知道的,知道吧? - -许永平 09:20 -我这边。 - -卡若 09:20 -我这边。反正是模糊的知道,因为我现在就提很简单,我现在对到这一步,我用户要对进来跟完善,没了我现在。 - -许永平 09:29 -那还没做完吧? - -卡若 09:29 -做完,你现在应该是只搭了底层的东西。 - -许永平 09:30 -你现在应该是只搭了底层的东西。 - -卡若 09:32 -对,我现。 - -许永平 09:32 -对。 - -卡若 09:32 -但没做完,我还没有存。 - -许永平 09:32 -我现在没做完,我还没有存这块,我不做,只是有查。 - -卡若 09:34 -没有做。那得。只是有查。有查的,怎么查? - -许永平 09:37 -有查的。 - -卡若 09:39 -查的就是接那个接口,根据传那个手机号、身份证。 - -许永平 09:39 -查的就是接这个接口,根据你传这个手机号、身份证、微信号过来,然后是一个数组的形式,这里都有传参。 - -卡若 09:43 -身份证。身份证微信号过来,然后是一个数组的形式,那给到我。那这个文档在哪里? - -许永平 09:50 -文档在哪里? - -卡若 09:51 -怎么样去动? - -许永平 09:52 -就发了,现在。 - -卡若 09:53 -不是发群里,我们在哪里能查得到,或者有一个链接,或者有一个接口的文档可以看的地方,不然我们就文档每一次都是。在弄文档的地方嘛。 - -许永平 10:03 -哦,那我部署一个bug,部署一个那个接口的地址我加一下,等一下我加一下,不然每次文档这也的确不是很友好,或者我写在。 - -卡若 10:11 -不然每次我在这确实是很不好。就你们文档管理在管在哪里?有没有一个统一的地方?比如接口。什么接口? ABCDE 的接口的文档? API doc 你有装吗?我没有,没弄。那你装 API doc,老王拉,我们平时都放在 API doc 里。 - -许永平 10:29 -放在 API force。 - -卡若 10:30 -拉,到时候我给我放出去。 - -许永平 10:31 -对。他团队里,然后。 - -卡若 10:32 -这里面,然后。没有,这个有些得先开出去,不能绑定。就是现在,嗯。公开出去得创建一个沟通方式。就这个,就东一块西一块,我的感觉知道吗?就没有。 - -许永平 10:47 -没有,就这,就我这个是没有写的,其他的老王都写了。 - -卡若 10:48 -这个是没有写的。 - -许永平 10:54 -对,你下载一个,等一下你发个链接到群里。 - -卡若 10:54 -对,你下载一个,然后我。到时候。等一下,你发我。我也发一个邀请给你吧。就你们像碎片时间这些也没有接过吗? - -许永平 11:06 -像碎片时间,结果把这些用户。 - -卡若 11:08 -这些用户的这一些,你得有接过这些东西啊。他都没开发完,存客宝都还没接呢。没有,这个是标准,你不用,不一定要数据,就是你。然后提前先创建啊。 - -许永平 11:21 -然后提前先创建了。 - -卡若 11:23 -你得有,你不是你做完了这个东西,你有东西能把那些东西字段传过来都可以了,就这一块清。 - -许永平 11:31 -想想。 - -卡若 11:32 -息,知道吧。那我们。 - -许永平 11:35 -那我们把所有的。 - -卡若 11:35 -就是我刚刚的那个需求就非常简单,这个东西弄完了,我要用户完善结束没了。 - -许永平 11:40 -好。 - -卡若 11:41 -但是用户完善这一个东西你要提取,那我没有提取的地方,对吧?都不用说我写入的事情了嘛。 - -许永平 11:46 -对对,是,是我,我没发布上去呢。 - -卡若 11:47 -对。就提取,我现在也提不了,对吧?那这个是就不清晰嘛。我没法录上去。是不是? - -许永平 11:54 -对对,那我马上发一个,然后那存呢? - -卡若 11:54 -对。那这个就是卡点呢?然后那。存肯定也要这个,就是规划的问题,就我们这个之前都讨论过。 - -许永平 12:05 -存,现在我都没想好要怎么去存你的这些东西,我最早的时候是直接把数据库丢下来,那个有哦,你是说那个且。 - -卡若 12:12 -时候是直接把数据。不是,最就是我把用户数据丢到 AI 去,我们当时还讨论了很多字段的这一些东西,标准的字段。那你进来之后 AI 聊完标。不是直接打标签就好了吗?标签引擎进去,进去完善这一些东西,那这个库。不是。当时是针对消费记录,消费记录是你那边给个,你那边把消费记录传。 - -许永平 12:33 -当时是针对消费记录,是参考抖音的产品。 - -卡若 12:39 -它标签有分几种类型。比如说一些基础信息的,嗯,标签你是直接去创的,像你说的那些什么消费的那些,它是要经过清洗的。 - -许永平 12:42 -比如说信息的抄的,像你说的那些,他是要。 - -卡若 12:51 -对。 - -许永平 12:52 -对。 - -卡若 12:52 -清洗完再那个清洗完出你要存的那个类型,比如说消费类型或者什么类型的,这些是要清洗的。但是你肯定调的就是调你整个第一就是他需不需要清洗啊? - -许永平 13:03 -直接调的就是。他是不是要进行的地址进行创建标签? - -卡若 13:07 -如果不需要他就直接写放标签嘛。嗯,对应是你的标签写进去的,那如果是说要,他要再过一层。 - -许永平 13:11 -创标签写进去啊。对,现在不是来清洗,不可能那么他自那么自动让他自动去生成标签,是。 - -卡若 13:16 -现在标签肯定是要有清洗之后的,到时候是来清洗的,可能还没那么多智,那么智能让它自动去生。对,因为里面涉及到一些。转换的东西,所以这个这一块也是要做。那现在那个读书的是打算弄哪些标签? - -许永平 13:34 -那现在那个读书的是打算弄哪些东西? - -卡若 13:38 -你是要直接把他的消息订单记录进来。 - -许永平 13:38 -你是要直接进这个,你不是要存进来。 - -卡若 13:41 -这个跟标签其实没有太大的关联,就是我们 AIAI 来负责这个标签,因为你不可能定义所有的程序的标签。 - -许永平 13:49 -如果是 AI 来负责这个,我需要你把表的结构搞定,让他去分析。 - -卡若 13:50 -看,负责这个,我需要他表的结构绑定的,让他去看。表的结构他自己会去分析。 - -许永平 13:55 -表的结构,他自己简单地说一下,就这个用户管理这一些东西。 - -卡若 13:56 -我,我简单地说一下,就这个用户管理的这一些东西,比如他看的这。 - -许永平 14:02 -看看这个用户卡的底下有个什么样的,对吧? - -卡若 14:02 -这用户看了什么?底下有绑定什么样的人,对吧?什么样的时间,对吧? - -许永平 14:06 -什么样的时间,对吧? - -卡若 14:08 -阅读了什么,发布了什么,他那些行为轨迹都得传到相应的标签的体系里面来,是不是? - -许永平 14:16 -就是你要搭一套清理的规则,它是一个动态的。 - -卡若 14:16 -就是你要。你得范式。一套清理的,清洗的这个规则,它是一个动态的。这个肯定。 - -许永平 14:24 -但这个也是要根据需求,什么数据进来,你说一个大仓库,那就丢什么嘛? - -卡若 14:25 -不管是丢什么数据进来,它是任意丢的。你说一个大仓库,然后他想丢什么就丢什么。然后他会。 - -许永平 14:32 -然后。 - -卡若 14:32 -通过那个清洗去给他判断哪些是可以提炼成标签。那种的话最好,那肯定是要整个可能会丢,每张表的那个字段不一样,我没办法说创建一张那种全部都是空白字段,空白那个限制的表。 - -许永平 14:37 -那种的话最好,那肯定是要整个布局,你那张表那个字段不一样,我没办法说创建一张那种全部都是空白字段的,那个禁止的表。 - -卡若 14:50 -不用空白,就是他进去之后按你的标准去留存就行了。就比如说他这边有个比较他正常的注册这些信息,这些还有的就是他的消费记录,大概就是这些要一些。 - -许永平 14:54 -就比如说他这边有的就提交他正常的注册这些信息吧。 - -卡若 15:02 -就跟它应用场景有关了嘛。就是我们给一个规则,让它把那些事物关联起来。因为。目前目我们当时做的就是先给,先把那个消费记录先跑过来,所以很多库我都直接把有消费名单的进行转化,这个是有做的,那现在就是新在消费记录上你还要生成什么样的数据? - -许永平 15:12 -目前目我们当时做的就是把那个消费订单的这个情况是有做的,所以现在新的消费记录你还要新增什么样的数据表?这个我得新增。 - -卡若 15:31 -这个咱们上次。 - -许永平 15:32 -我们上次讨论的这一个这个流程的话,我觉得你再去确定一下,现在的话如果这个是有卡点,我们开发下去才知道会有。 - -卡若 15:32 -讨论的这一个流程的话,我觉得远志你再去确定一下这一个东西,因为现在的话如果这个是有卡点,我们开发下去才知道会有卡点,那怎么去把它迭代掉呢?是不是?这个。 - -许永平 15:50 -对。 - -卡若 15:50 -因为这个需求本身,如果我在做这个事情都有卡点的情况,我觉得任何人都会有卡点,因为我是非常灵活了已经,知道吗?我。我现在就是这个东西,你就给我一个API,就我都全部搞定了,是不是?那我现在都会有这个卡点都我自己走一遍,我就很清楚了,就我们这数据中台的整个的这个搭建,对吧?你还是按规划来吧,不然这个的确是不知道。规划之前是按照,得提前先设定好标签,按照之前有调研那些的确是有。 - -许永平 16:21 -规划之前是按照,得提前先设定好标签,按照之前有列的那些,的确是有。 - -卡若 16:27 -标签基本库是用来放的,你就建好一个个箱子,对吧?那。你中间有一个分类源,那个 AI 的标签引擎就是这个分类源嘛。那我传的那些标签过去,它分类成完之后就丢到你这个一个个箱子里面就行了嘛。它逻辑本身就本质上就这个事情,你定义的就是。 - -许永平 16:46 -定义的就是定义的一些大类,他们一起玩这个是属于什么类的? - -卡若 16:47 -定义的一些大类啊。就这一个。这个是属于什么类的? - -许永平 16:52 -哦,我想想怎么整?那行,老,下一个,老王,先继续,我想一下这个怎么整吧? - -卡若 16:59 -这个你一定是跟那个神射手去结合的,不然一。块一块感觉会没有总整体性,你知道吧?就我不知道他的到哪一个地方,知道吗? - -许永平 17:06 -好,行,先这么说。 - -卡若 17:11 -然后我,我会,我这个,我先说完这。行行行。我会有一点是什么?就是我现在为什么今天没有让你去把这个输的这个?因为有很多的一些细节的东西,我就想试自己试一下,走,跟你这个对接一下,看才能发现问题嘛。不然就肯定会那个的嘛。会有更多的一些卡点,或者不能往下去走,对吧? - -卡若 17:51 -现在就,所以这个还是要按板块来,我们好像一直都在原地踏步循环开发,然后回那个。 - -许永平 17:53 -对。 - -卡若 18:04 -回溯一些东西,知道吧。 - -许永平 18:06 -另外一个,你是。 - -卡若 18:06 -一百个。没有一个地图展开的感觉,知道吧。就抽象点说的话,是这个嘛?那这个就规划跟原来的那个东西怎么样去融合的一些问题嘛?所以你们在那个项目管理上面的话,我觉得还是要明确清晰吧。因为没有图嘛啊?往下吧,往下这个,这个你看一下,看怎么解决嘛?因为我现在这个我肯定是要上线的,本来周一要上,上,周一要上线,上周一就卡。验证嘛?那这个时候验证过了,就那个,这有一些那些 bug 我都还没有去弄,本来这个东西,这一个用户我早上就在过来的时候,我就才弄这个用户了。那用户弄完之后,我说下午那 API 过来,我就接上去,那咱们就正常可以使用了嘛。 - -许永平 18:57 -做完之后有效。这边这个计划。 - -卡若 19:02 -对吧?那现在又就这边就卡住了,是不是怕你也一定会卡住的?就这一个,到时候要写上就解决这个问题,然后要有个清晰的文档吧。然后关于那还有个提现的,今天是不是知道说这个虚假新开的说云审查的你因为提现,我现在后来看的是云审查的模式。然后上面这个名字,我们点击他这个,再跳出来就是他的主页。能提确定收款吗?已经到了吗?得点这一步,再点确认收款才可以。 - -许永平 19:43 -再一步再点确认购买。这不是地点物流。 - -卡若 19:46 -是避免不了的。这样子就会到账。好。 - -许永平 19:51 -你好,稍等。 - -卡若 19:51 -这样就到账了。可以,嗯,永平这个也不着急,就是要一点点去。 - -许永平 19:57 -只有一刷新。就这两个,就这两个状态。 - -卡若 20:02 -我们反正一个事情过吧。 - -许永平 20:03 -对的。然后。 - -卡若 20:05 -然后都把信息给他,嗯,提示。然后你。那这个不是能刷单就很爽吗?对。自己刷自己钱。 - -许永平 20:14 -然后你。 - -卡若 20:22 -昨天是没刷。 - -许永平 20:22 -昨天是没传。 - -卡若 20:23 -这么丑。 AI 我都是写的四个字,生成事件之间的,来到没了,没给他描述。这个也太。那我只是为了让你尝试一下。行吧。之后有一个卡点,我证书一直申请覆盖不了,就你有两三个证书,这几个月要,这几天要过期了。那你就是再申请。让你登录发验证码。我不是发了吗?我知道,一直卡,记住我,他提示是已经可以了,但是我必。第二天去看他的灰度高,灰度把进入0%。这个我一直卡着,我一直在看这个到底是什么问题导致的?我到时候让,到时候我再去研究一下支付宝那个叫。对,这个,那个他们那个钱的充值,你要怎么走那个流程啊?谁钱的充值啊?就是你总账号,他肯定要有钱嘛。那比如说那个瘦那边,他们是他们去审核,你跟他合作这个钱不应该是我们垫付,是应该他们要先把钱。项目打啊。对,那你要怎么走?怎么。这个就是项目为准的。直接他。项目充值到我们后台,然后直接扣啊。那你还要再做一个充值的。这一个后续再说。 - -许永平 21:54 -这一个后期再说。 - -卡若 21:55 -我知道,就是你后续你要直接做一个充值。你这个充值也没用。那你相当于你要开个体验版。走线下。不不不,你们,你这线上充值没有人会线下的。你走线下有好处,第一,你走线上的话,我不知道你这一个手续费是多少,你先。 - -许永平 22:13 -走线下。对。 - -卡若 22:18 -那你不用去思考这个问题。我知道。这个,这些就是利润的问题了,你。 - -许永平 22:23 -对。 - -卡若 22:23 -利润没错,白也没错,你充进去他还是扣不了,你得再手动再充进去,他现在拆下来。 - -许永平 22:24 -又没错。他还是通过他现在才。 - -卡若 22:31 -我知道本地。用户跟运营户嘛?这个写个脚本就行了,我都实现了,这个你不用去思考这个问题,能实现他能,就是他到时候短信你按一下,他会你签转账的时候就是授权一下就结束了。你这都有脚本了,这个没有啥,你不用担心这个问题。 - -许永平 22:48 -如果你在一个学历1万,我们。 - -卡若 22:49 -我这个可以做。你反正你去看一下嘛?这个不是一个难,就本地户,这个到时候要转到运营户嘛。肯定做。提本户转运营户嘛。一个对应的后台。他就是给。商家后台。 - -许永平 23:02 -算一个。 - -卡若 23:02 -我会做到新版的那个碎片时间。 - -许永平 23:04 -对。 - -卡若 23:05 -对呀。 - -许永平 23:05 -对。 - -卡若 23:05 -不会再拉出来了,这个只是说让他临时可以用。现在就是先线下,那个线下打,如果他们要用的话就先转一笔进去嘛。现在就我们自己打嘛就行了,那你得规划出来。目前先走线下,他转给我们,然后我们打到那一个运营账户,然后再从运营账户扣钱。是这样的流程,然后去做。 - -许永平 23:32 -给我 c 的。 - -卡若 23:32 -我新版的那一个碎片时间之后再。再说你说的那个流程嘛。不然这样子碎片时间也不用太多时间。然后我那一个标签最近今天注册掉了10%,在对接接口。然后业务也在搞。之后,明天就可以全力搞那一个流量池碎片时间去搞一搞,多弄。刚刚提交审核的时候被驳回,让他再重新提交一下。驳回原因呢。驳回。 - -卡若 24:00 -応援今の。 - -许永平 24:00 -会。 - -卡若 24:03 -他那一个得看审核人员的信息,同一个页面,同一个东西,他驳回的理由都是不一样的,有时候会通过,有时通过不了。那你就多提交几次嘛?对,所以说我待会都会重新再提交一下。那可以,那你就继续往下嘛。那我明天就继续全力突击标签,把,标签大概这层可以让你有一个城市的方案。就那个嘛?就正常这种还有吗?没有。那你。那你那个碎片时间要跟永平那边对一下,永平。永平,你把你那个。 - -许永平 24:36 -好好好。 - -卡若 24:38 -就是等一下你把那个标签的那个用那个展开,我不是有那个文档嘛?你展开就到时候对一下。对吧?有一个架构什么你才比较清楚嘛?展开,你把这个那些那个源码和数据库丢进去,自己展开,让它变成说明文档,我们看一下流程嘛。那你就也要弄一下,看看一下,对齐一下,反正比较清楚嘛。这个主要给远志看的,远志看了没问题,那就没问题。说明文档概要把那些比较重要的。就你们做完自己生成一个,你们检查你觉得没有问题。 - -许永平 25:13 -对。 - -卡若 25:14 -就跟你那个昨天那个实际的分析,大概实际的差不多,他分析出来了,然后还拆解了,还提一些各种的案知道,还跟一些说提这个项目以后的规划流程了,干嘛干嘛。对,就之类的,反正你。这个文档我是已经思考了大概 18 个点。就那个,你们是要对什么?那个,就那个。 - -许永平 25:40 -就所以现在。 - -卡若 25:42 -对,现在我卡了一条碎片时间聊天系统,例如我做了什么海报的任务,我就把一些信息就给永平,然后永平收入信息,收入显示之后再一个事件是在这边,然后他做了什么任务之类的,你要跟他的用户画像之类。打标签嘛。对。打标签,但是现在的问题好像是打标签这块你还没弄完。是吧?他这一块就是只是支持查询。 - -许永平 26:09 -现在我觉得是更新其实是有的,就是现在这一套是基于上面不是已经有数据库了吗? - -卡若 26:13 -对呀,要说支持更新,对呀,没有写更对,更没有写。但是要更新,更新其实是有的,就是我这现在这个就基于它上面不是已经有数据库了吗? - -许永平 26:26 -应该都是全部数据库,只要那个数据库有更新,我的数据有更新。 - -卡若 26:26 -那都是全部抓在你的数据库,只要数据库有更新,然后数据中心它就会自动更新的,因为它任务都是。 - -许永平 26:32 -多都是在跑,然后像做担心,最初在想是直接把数据丢进来就好了,因为他做那个淘宝那的话,我们那个接口跟本地的这个字段肯定是有不一致的,所以我的想采访 AI 带的话,就省去了换这个过程。 - -卡若 26:33 -然后像你们说的那个更新,我最初在想的是你直接把数据库丢进来就好了,因为它会自动去抓,做那个 AI 也是这样去抓的,这样的话我们那个接口跟本地的这个字段肯定是有不一致的,所以我的想,我初衷的想法是有这个 AI 在的话,就省去了对字段这个过程。那我知道。是啊,就 AI 对字段的,但你不要用本地,因为模型没有用。 - -许永平 26:53 -是 AI 啊。 - -卡若 26:57 -我明白意思,因为它 lark 后台有一个地方添加数据库,它直接把数据库账号。密码,然后名正他们输入进来,让 AI 这种分析嘛。 - -许永平 27:06 -对。 - -卡若 27:06 -我知道最早解决方案是这个,所以你这个标签的 AIAI 的分析的引擎一点有个逻辑在那边,现在是没有看到,这个很重要。对。 - -许永平 27:17 -是。 - -卡若 27:18 -知道吧。 - -许永平 27:18 -搜索上面都对的。 - -卡若 27:18 -上面都有。就是永平现在做的那一个,你要知道你做这个就是纯搜索的一部分在哪一部分上面? - -许永平 27:20 -只有永平现在做的。 - -卡若 27:26 -然后就远志规划的那一部分是不完成,然后我们看就验证那个嘛?解开发小程序什么,这些都是在验证,知道它并不是一个什么,那个什么。到时候那个小那个神社所那版先发给你,发他,对的,那个,看那个。 - -许永平 27:42 -就是厕所那块先发给。好,发我看。 - -卡若 27:47 -我们的核心的东西是啥?不管小程序这些,这太容易开发了,你搞进去用户数据跟我们做交互合并和估值,这是我们的核心,知道吧? - -许永平 27:54 -对。 - -王名正 27:54 -用户数据跟我们做交互。 - -卡若 28:01 -不是小程序,小程。小程序没有任何价值知道吧。所以这个这一块是非常重要的一些点,包括一些小的一些 bug 或者什么的调整嘛。是吧?可能你们修 bug 可能会快一点,老王修 bug 跟永平修 bug 的这一些,但我们不要生产太多bug,修是很快,对吧?不然东东一块西一块漏是不太好的,所以我才。诶,一直说咱们有一些完整性一点的东西,是吧? - -许永平 28:38 -我这边的话有个数据采集,其实在这边就是来配数据库了,如果是说行。 - -卡若 28:38 -我这边的话有个数据采集。你永平,你看一下这个怎么融到厕所里面去? - -王名正 28:43 -没有,你有投屏的,我看得到。是许永平没有放上。 - -卡若 28:48 -我觉得这个是不是这你看一下。 - -王名正 28:51 -远志投屏的,你试过去一下,远志投屏的,远志的。 - -卡若 29:02 -那。个今天跑,站在一台式上面跑。跑,你这个切片的。是第一个碰到的问题是。你现在很多是第二,你封装的完是你的苹果环境。 - -王名正 29:12 -我们都得二次转换,我们,我们得先改写 Windows 版本的。 - -卡若 29:15 -那他自己会去装,我知道啊。对,然后我们现在就是拿到这些的话,有时候一开始跑,他会那个他环境不一样,他变成得改写,改成对的版本。对啊。对,他 AI 会自动改写,然后可能要有一些环境要重新装什么依赖的。对啊。然后装完。的话,跑完的话我这次跑,他第一次跑的结果,因为我不清楚嘛。他跑完的,结果跑了好几个小时。那不是很正常吗?但是。说你跑一个视频多少?几分钟就好。 3 分钟就搞定了,你好几个小时,是你没有指定 MLX 的那个 Viser 这个。不是。加 MLX 杠,不然它就变成很麻烦的。你听我说,就是一开始我不清,因为我不知道,然后他跑了几个小时,我觉得不对,然后他。整个CPU。干,干,翻了。那不很正常嘛?你以后像这种你加一句就是。好,我跟你说像这种多任务的。最终跑了一个多小时, 97 死机了。你先听我讲完你这个,你就这要限制一个,大家就是在做运行的时候限制在 CPU 使用百分之,整个机器性能70%,不要超过。 - -许永平 30:13 -你先听我讲完。 - -王名正 30:24 -掉。 - -卡若 30:24 -不对。你听我讲完。他问题是他没有调那个显卡,他要用显卡去处理,不应该用 CPU 去处。 - -许永平 30:26 -他问题是。 - -卡若 30:32 -那就。就掉显卡嘛。对,所以说这个就是属于逻辑上变清楚嘛。 - -许永平 30:36 -他说我现在后面几个小时就死机啊。 - -卡若 30:36 -说我现在后面改完的第一次跑 CPU 就变得不行了。那跑g, GPU 就快啊。一个几个小时就死机啊。那跑成了没有嘛?然后现在是我改成显卡,显卡现在是跑成了,我看一下。那不就对了吗? - -许永平 30:52 -你这里说 10 分钟。 - -王名正 30:58 -你点击应该可以跳出来。 - -王名正 31:11 -你复制,你再复制那个链接。 - -王名正 31:30 -桌面。 XYZ 视频凹凸输出。 - -王名正 31:44 -1 起 1 + 5。 - -许永平 31:49 -没视频文件吗? - -卡若 31:56 -啥东西嘛? - -许永平 31:57 -接吻。 - -卡若 31:57 -你是刚切完片。 - -许永平 31:57 -你就发希望,嗯。 - -王名正 31:59 -行。 - -卡若 31:59 -你这一个是,估计是他的那一个话术吧。 - -王名正 31:59 -你这一个是,估计是他的那一个话术吧。 - -许永平 32:00 -再一个是我。 - -王名正 32:02 -话术啊。什么话术? - -卡若 32:07 -这是文件,你视频没跑出来。 - -王名正 32:07 -这字幕,这是字幕。 - -卡若 32:10 -他说已经跑完了,就是没,但是没看到视频。那你视频放,你看那个 cursor 上面嘛。对,就是看这个东西。视频有文档吗?输出日志。输出啥字?等我看一下,字这么小。哦,你还要自动,那你怕你还要自动再运行一下按钮的这个日志。 - -王名正 32:25 -哦,你还要自动,那你他,你还要自动再运行一下 Python 的这个命令。 - -许永平 32:28 -不要自动运行。 - -卡若 32:30 -不用自动运行,你。 - -王名正 32:30 -没有,他以后。 - -卡若 32:31 -没有它以后。 - -王名正 32:32 -切片说运行这一个。 - -卡若 32:36 -就说以后,但是现在这个转入完成。 - -许永平 32:36 -说以后,但是现在这个转入成,我看一下。 - -卡若 32:42 -我看一下,回去。 - -王名正 32:45 -他啥? - -许永平 32:45 -太强了。 - -王名正 32:45 -我说用手机再放大看他们,他只是说一个文件没有。 - -卡若 32:47 -就那个吗? - -许永平 32:48 -这个吗? - -卡若 32:48 -输出设置这个是文档剪辑、视频剪辑项目 output 这个,然后。 - -许永平 32:49 -输出设置这个是文档吗? - -王名正 33:02 -我没有视频,没有 case 的视频,没剪视频。 - -卡若 33:02 -没有视频。没剪视频,但是剪视频很快,你它这个是你已经拆解完了,就是没剪。 - -许永平 33:10 -然后我又加了几个需求,就是。 - -卡若 33:10 -然后我又加了几个需求,就是加了几个那个因为经常跑这种大的时候,它就一直卡在那边,就我不知道它是不是在跑还是卡住。那你就告诉他,实时给你反馈进度。 - -许永平 33:21 -那你就告诉他说,我们这个才知道最终的。 - -卡若 33:23 -加了一个。不就行了吗?对。但这个得完整跑一下,到最终的流程是怎样?那肯定,主要是。那台机子它能跑就可以了,我们这个你只要能跑,后面就是文件,还有它有一个自动上传到抖音或者什么什么群。 - -王名正 33:36 -这个就是文件。 - -卡若 33:41 -那个是分发嘛。分发的嘛。现在就是先跑剪的嘛。你先跑,剪这种事情。这种你到时候如果要给他们用的,是得录到那种比较好的那种。那你搞云机就好了,搞 GPU 就好了。你这种机制就没办法。或者搞苹果是最快的。苹果对,你那个没有。对,这很慢。那你就。 - -王名正 34:04 -你听过最近的是挺快的,但是哪一点的例子不好说? - -卡若 34:04 -苹果可能自己快,那老一点是一种不好。老一点也快,苹果的显卡就是不一样。就不一样,我跑一下 50 秒,拆解是三提取三到 5 分钟,跑完剪就 50 秒。 - -王名正 34:12 -没感觉,我真的没啥感觉,我那台跑起来也挺卡卡的。 - -卡若 34:22 -嗯,那你没有用那个嘛?没有用那。 - -许永平 34:24 -我还是苹果,它那个系统优化的比较好。 - -王名正 34:26 -主要是我那台太老了,那台苹果好像是19。 - -卡若 34:27 -主要是我那个太拉了,那还有一苹果好像是19。 - -王名正 34:32 -连麦的。 - -卡若 34:34 -19 年,对。然后这几个我得完整跑完,我才知道问题在哪里。你先跑一遍嘛。然后数据员工的话,我这边是改成这个,之前是那个卡片折叠的,我给他改成这种,就播报数据的话,还是卡片下面一个,就是以这种,不是跟他。一样的卡片这种推送,然后估计的话就是,嗯。 - -王名正 35:12 -你测试用户是哪一个?还记得? - -卡若 35:16 -如果我输的这个是冲突的,它里客户库里面有的话,它就会导出它的故事,那如果是说如果是查不到的,它。 - -许永平 35:21 -客户库里面的一个。 - -王名正 35:29 -陈佳。 - -卡若 35:32 -客户资料里面把这个跑到冰娇那边来,添加好友发送需求。 - -卡若 35:49 -这个老王开始弄了没有?就是碎片时间弄完就搞这个嘛? - -王名正 35:52 -家垒不是在弄那一个标签吗? - -卡若 35:54 -不是在弄那一个标签,先,标签完之后再做一个。 - -许永平 35:54 -就在标签吗? - -王名正 35:55 -新标签,标签完之后再这一块都有排期啊。 - -许永平 35:57 -就在。 - -卡若 35:59 -都有排期啊。 - -卡若 36:10 -剪辑,是吧? - -许永平 36:10 -点击。 - -卡若 36:11 -就是处理那个问题。 - -王名正 36:11 -剪辑设置。 - -卡若 36:15 -你先一台先搞定再说,因为这个检测环境不一样,调整一下。 - -许永平 36:23 -比如说你现在。 - -卡若 36:23 -比如说你现在很多不同的steer,它里面用到的一些插件,比如说它有环境不一样,怎么去解?解决这个问题是不是还得写一个这种?不,不用,你直接问,他自己会去改啊。我知道,就是他应该还要有一个逻辑是去处理这个版本的,就比如说你调用的第一个,他可能需要的 Python 版本是最高只能是到10,但是你比如说你调用第二个的时候。 - -许永平 36:38 -都是。 - -王名正 36:38 -他应该还要有。要。 - -卡若 36:51 -可能。他会装虚拟环境啊。但是你在是一个同一个工作区吗?他在也会每一个也会用他自己的虚拟环境啊。不知道可以,你就是提示词,你加一个部署到虚拟环境里面。 - -王名正 37:03 -Windows 不行,像我家里那台电脑就是 CNP 那些命令在课程完全执行不了。 - -卡若 37:15 -这个它有虚拟环境的,你就你们。 - -王名正 37:19 -对,我在公司这一台我就可以完美执行。 - -卡若 37:23 -这个就是你一个 steer 用的就是一个虚拟环境,你多加一句话就行了,这个一定会碰到的问题,你加一个提示词,加一对,加1。 - -许永平 37:28 -把,这对。 - -卡若 37:32 -那就行了,我现在解决非常简洁,知道我就让它装到什么? - -许永平 37:34 -はい。 - -王名正 37:36 -大家装到这个微信。 - -卡若 37:38 -装到那个虚拟机里面。doc,所有东西都装doc,咱就调用 doc 就完了,就 doc 就是一个功能。 - -王名正 37:48 -你电脑好一点,性能好一点,可以这样搞,我知道它是一个容器。 - -卡若 37:51 -doc 不会占太多资源,你好好去研究一下,它不是虚拟机。对,它不会占太多资源的,它不运行根本就没占资源,跟文件夹似的。 - -许永平 38:02 -每个词。 - -卡若 38:02 -要都单独的一个。 - -王名正 38:04 -小荣幸。 - -许永平 38:04 -小游戏。 - -卡若 38:05 -对啊。布个环境。对,他可以自己去调,他没有就去装一个,自己会去调,知道吗?这个回头你就先剪跟发,能发到群里面最好也。 - -王名正 38:19 -你现在就是搞doc,每一个 schema 就一个doc,我说,我是说你现在。 - -卡若 38:20 -你现在就是搞doc,每一个 DA 就一个doc。 - -许永平 38:20 -现在就考后端。你可以搞虚拟货币。 - -卡若 38:24 -你可以搞虚拟环境,可以搞 doc 很多解决方案。虚拟环境跟 doc 混着用, doc 就。 - -王名正 38:30 -我是没有,我电脑承受不起。 - -许永平 38:30 -我是没有,对吧? - -卡若 38:33 -文件大一点,没啥区别的。现在我主要是给电脑上冲突了。 - -王名正 38:35 -现在我主要是本地电脑那台环境太多了,已经冲突了。 - -卡若 38:39 -那你一定会冲突,你要你多加一个,让它生成独有的一个环境就可以了。 - -王名正 38:46 -现在我本地环境都冲突了,再装的话也装不起来了,再装。 - -卡若 38:47 -现在我本地环境都冲突了,再说的话也装不起来。不是,你装虚拟环境就好了,哪里会装不起来? - -王名正 38:56 -名正你麦扬声器关了。 - -许永平 38:56 -我这里把声音关了。 - -卡若 38:58 -你知道我在看远程,是通知不了的。 - -许永平 39:00 -不去,远程是听不了的。 - -卡若 39:02 -是。 - -许永平 39:03 -好。 - -卡若 39:08 -有,那你这个剪出来的切片,它字幕也没有自动配,它会自动配吗? - -王名正 39:08 -那你这么点出来的推荐它自动对,它会。 - -许永平 39:08 -那你这个剪出来的切片,它字幕也没有字幕,对啊。 - -卡若 39:12 -会自动配,你没自动配,就是没加提示词。 - -王名正 39:13 -没加,你没加提示词。 - -卡若 39:15 -不是你,你不应该你原来的那个就已经是有的吗?是有啊。原来的。是有,你要变成剪那个加字幕,它有三个版本,一个不加字幕,一个加字幕的时间会多一些时间就多搞一遍嘛。时间翻倍,没其他的呀。是存在其他的。你就看看那个test,那个高速路。 - -王名正 39:35 -你就刚刚那一个test,那些都是字幕。 - -许永平 39:36 -就刚刚那一个case,对, 5 个高就切到一些空白。 - -卡若 39:39 -知道,他现在剪出来就剪了五个高光时刻出来,应该是按你的提示是剪出来,但好像有问题,一直这样闪。 - -王名正 39:54 -他剪了就会就闪一闪,闪一闪就切到一些空白的、没用的那一些就直接闪过去了。 - -卡若 39:57 -就其他一些空白的、没用的,拉一些就再返过去。 - -王名正 40:03 -像现在它就跳过生成的事件了。 - -卡若 40:06 -noor 这些他都不会。然后你上面生成。 - -王名正 40:10 -然后你中间生成等待了,它也是在跳过。 - -许永平 40:10 -然后你找那 3 个。 - -卡若 40:12 -你先剪几个做调整就知道了,这个都是你调一下就清楚了。 - -许永平 40:12 -你先写几个。 - -卡若 40:21 -是吧?现在这边跑出来了。你能跑动了就对了。调调他的那个CTR。 - -许永平 40:25 -调调他的那个。 - -王名正 40:26 -gpu。 - -卡若 40:27 -你要调。干不动,干到百分之都满了。你调模。 - -许永平 40:32 -我是直接。 - -卡若 40:32 -直接死机的,直接。你以后像这种你要跑很久的,你就限制它性能 70 80,它自己会给你限制的,你就不会出现卡和点不动的问题了。限制你变成时间还是得。那就多搭百长,百分之 10 20 又没有啥。 cursor 那边经常会断掉。 cursor 会。不了,那么长啊。 - -王名正 40:54 -这里是要至于 create 更。 - -卡若 40:55 -不会,这些都有解决方案,你们跑就知道了,它。 cursor 那边断掉你任务。它会后端去监控文档,它。一样在跑,不用在 cursor 实时给你看,知道吗? cursor 断就断,无所谓,他后端执行下去他不会,他都文档都写好了,让你按他的文档节奏去执行了,知道吧? - -许永平 41:08 -没办法。 - -王名正 41:13 -行,这个得尝试。 - -卡若 41:17 -你们走一遍就知道了。 - -卡若 41:26 -那我过一下这个永平,明天那个你小程序,明天。 - -王名正 41:30 -那个。 - -卡若 41:32 -可以给你改,已经弄完了,现在能正常付款了。 - -王名正 41:33 -因为我们现在已经,那就了解一下,嗯,对吧? - -卡若 41:35 -那就了解一下,用跑一下才知道这个问题在哪里,你自己跑才知道,对吧? - -许永平 41:38 -下回跑一下才知道是。 - -王名正 41:40 -跑一下才知道问题在哪里,自己跑,现在直接做一下,我实证验证一下。 - -许永平 41:42 -是。一跑才知道。好。 - -卡若 41:44 -因为我现在我给你过一下,我只是这几天我要验证一下这个到底卡点在哪里,所以会去那个嘛。 - -王名正 41:51 -对对,去那个。 - -卡若 41:54 -那尽可能,我们要按那个远志那边规划的时间去走嘛。 - -王名正 41:55 -那尽可能的,我们要按那个远志那边规划的时间去。 - -卡若 42:00 -我看一下这个。所以你这个阶段性的东西得给我具体一点发一下这个东西嘛? - -王名正 42:03 -所以你这个阶段性的也会具体一些。 - -许永平 42:07 -好。 - -王名正 42:07 -看一下,就这个,这一个现在的话基本就是这样。 - -卡若 42:08 -就这个,这一个现在的话它基本就是这样,我已经部署上去了,然后,诶,打不拉不过去,啥情况? - -王名正 42:24 -应该是你那个信息。 - -卡若 42:26 -就这一个嘛? - -王名正 42:27 -这一个时间的话,基本就是正常的点。 - -许永平 42:27 -一个这边啊。 - -卡若 42:27 -这边的话它基本就是都可以,正常都可以用,就可能按钮。有点歪啊。但它这些正常的功能都是正常去使用了这些匹配的乱七八糟的其他后台应该是没数据。 - -许永平 42:37 -有啥游戏? - -王名正 42:38 -行。 - -卡若 42:44 -那。前后端都好了。 - -许永平 42:45 -前后端。 - -卡若 42:46 -都好了。数据库也去接,是吧?数据库也接完了。现在是差。差,看看有没有一些 bug 或一些,比如有几个我还没空去改的,比如这个后台这个设置免费的,这个设置的参数我。你们可以记一下。 - -王名正 43:02 -你可以记一下。 - -卡若 43:03 -他们直接布上去测一下。 - -许永平 43:04 -直接布上去测一下。 - -卡若 43:05 -不,已经布上去了,都布上去了,我只是在这边跟你们说一下这个事情嘛,我说能看得到的一些 bug 嘛。对吧?有个问题。 - -王名正 43:18 -问题。 - -许永平 43:19 -没问题,我今天把你那个代码拉下来,然后看,然后他那个叫你,你是用什么东西让他自动编译成小程序啊? - -卡若 43:19 -我今天把你那个代码拉下来了。你说嗯。然后他那个叫什么?你,你是用什么东西让他自动一层一层去找的?我在云马腾讯开放文档,没找到。 - -许永平 43:30 -我在源码里面开发文档,没?找到,好。 - -卡若 43:32 -你这个我等一下说,有问题,等一下说,我先过一下这个事情,有可能这个付款都解决了,在小程序它就跳出小程序付款的,我再去小程序过一下,比较清楚。 - -王名正 43:35 -先过一下这个事情。 - -许永平 43:50 -你刚付款,不是一个环境吗? - -卡若 43:51 -不用,你在我小程序运行不是很难,我给你们过一下,这个已经是可用状态,但是有一些细节,为什么? - -许永平 43:52 -它调试工具是这样,小程序运行不会这样。我直接调用的。对。 - -卡若 44:03 -今,其实现在上线也可以,但我不想这样。 - -许永平 44:04 -现在上线可以,咱们不想这样。 - -卡若 44:06 -知道吗? - -许永平 44:06 -知道。 - -卡若 44:06 -肯定得测啊。 - -许永平 44:07 -肯定得测啊。 - -卡若 44:08 -测也七七八八了,就你像这个他就正常支付就可以了,这个数是调的数据库,就 Mysql 里面的那个数据。 - -许永平 44:09 -测了也七八八了,像这个他就正常支付就可以,这个是调的本身。 - -王名正 44:09 -七七八八的,他是正常。 - -许永平 44:19 -你现在这个好像是已经,其他今天有看那个后台。 - -卡若 44:19 -好像是已经携带飞书了,是吧?我今天有看那个后台。都,这个都自动了,这些都正常可以用了。 - -王名正 44:24 -对对对。 - -卡若 44:28 -付完款之后是能立即知道,比如。 - -许永平 44:28 -付完款之后是立即知道了。 - -王名正 44:29 -付完款之后是我们立即自办。 - -卡若 44:32 -如果我把这个东西给这一小节,这一小节我传给远志吧。 - -许永平 44:32 -过把这个,嗯,等给他之后还需要更新好自己,嗯,后台是。 - -卡若 44:40 -我举例或者传给他,我转给他之后,他只要付款,看过付款我这里就立即就知道付款了。就是我的后台是立即知道,并且能老王那边的那个自动分账的,这个我还没接,但是已经有弄好了,他这里的话我是能看到。 - -许永平 44:55 -然后那个自动就够了,自动看到。 - -王名正 44:57 -跟大诶,但是已经有动作了,他看情况能看到。 - -卡若 45:04 -谁买了? - -许永平 45:04 -谁买的? - -卡若 45:05 -我这边已付款,就一个。 - -王名正 45:06 -一个,嗯。 - -卡若 45:09 -这里谁付款的都很清楚的,然后他没付款就是绑定状态,就微信用户就他嘛,然后在后台的话,这里的话是会有一个都是用户绑定的,今天为什么对这个,这个是用户绑定? - -许永平 45:09 -这里谁付款的都清楚,然后他没付款就是绑定。 - -王名正 45:11 -然后上面是绑定状态,就是微信用户,他跟用户绑定,因为为什么会这个? - -许永平 45:16 -然后在后台的话,这里这个,这是用户绑定的,今天为什么推这个呢? - -王名正 45:24 -这一个是用户绑定。 - -许永平 45:24 -这一个是用户绑定,这个是我的微信推的这一个人吧。 - -卡若 45:25 -比如这个是我的微信推的这一个人嘛。有人进来,我绑定了谁,就绑定这个人,他付款了。 - -王名正 45:28 -有联系平台的绑定谁? - -许永平 45:28 -有人进来,我绑定了谁,反正这个人他付款。 - -卡若 45:32 -我的收益是这个是清晰的知道,而且是现在还没实现立即到账的,是吧? - -王名正 45:32 -周一去这个。 - -许永平 45:32 -我的收益是这个,那是清晰的,而且是现在还没实现已到账,我这个是清晰的,然后这边的话。 - -王名正 45:38 -好的。 - -卡若 45:39 -这个是清晰的,是吧?然后这边的话,诶,不是这个域名,等一下啊? - -王名正 45:41 -然后这边的话。 - -卡若 45:50 -就这里嘛,这里的话这边就正常的能看得到。 - -许永平 45:52 -就这里嘛,这里的话这边就正常的看得到,那我现在的实际点是很多用户中心点击进去是要看到他全部的生命。 - -王名正 45:52 -这里的话这边就正常的看不到,但是我现在的理解是我们用户中心点击进去是要看到他。 - -卡若 45:56 -那我现在的是一点是什么?这个用户中心点击进去是要看到他全部的生命轨迹。 - -许永平 46:02 -给自己跟这一个的,那这一个页面又没有接口,所以这个会出错,知道吗? - -卡若 46:02 -也跟这一个的,那这一个页面因为没有接口,所以这个会出错,知道吗?我今天尝试着去接一下你那个后台,但是没有接口肯定会出错的。 - -王名正 46:08 -我今天尝试着去接一下你那个作品,但是接口肯定会出错的。 - -许永平 46:08 -我今天尝试地去接一下你那个后台,但是没有接口肯定会出错的。没有,现在没有这个功。 - -卡若 46:13 -那没有这个。 - -王名正 46:13 -对,所以这个是需要完善的。 - -卡若 46:14 -对,所以这个是需要完善的,不能。 - -许永平 46:14 -对,所以这个是需要完善的,应该还没到这一步,但是已经那个已经写完了,就是没有也能写就是了。 - -卡若 46:17 -还没到这一步。 - -王名正 46:18 -但是你今天那个今天写完了,就是没有也能写,就是这个接口能正常通,他这里就没问题,知道吧? - -卡若 46:18 -但是已经那个已经写完了,就是没有也能写就是了,你只要接口能正常通,它这里就没问题,知道吧? - -许永平 46:22 -你只要接口能正常沟通他自己的问题,知道他这个点击进去是可以看到他底下有多少用户,以及这个用户点在哪里,看了什么章节的。 - -王名正 46:25 -他这个点击信息是可以看到他底下有多少用户,以及这个用户点哪里看的什么章节的。 - -卡若 46:25 -它这个点击进去是可以看到它底下有多少用户,以及这个用户点的哪里看的什么章节的?是吧? - -王名正 46:33 -把这个是详情,然后这里的话全平台的一个付款,今日点击的跟今日绑定,这个是属于全平台的。 - -卡若 46:33 -这个是详情,是吧? - -许永平 46:33 -这个是讲解,然后这里的话全平台的一个付款,一个点击,一个今日绑定,这是全平台的。 - -卡若 46:35 -然后这里的话全平台的一个付款今日点击的跟今日绑定,这个是属于全平台的。 - -王名正 46:42 -对,因为这个只有一个看书付款跟分销的功能,跟即时到账的功能。 - -卡若 46:43 -这因为这个只有一个看书、付款跟分销的功能跟及时到账的功能嘛。 - -许永平 46:43 -对。因为这个只有一个看书付款的推销的功能,及时到账的功能,然后有一个的话,他只要向我发给发这个链接,我发到群里面去,这个群里面有 10 个人,点击这个链接就跟你合法关系了,这 10 个人接下来一个月所有付费都跟都会。 - -王名正 46:47 -那有一个的话,他只要叫我发给发这个链接,发到群里面去,这个群里面,然后。 - -卡若 46:48 -然后有一个的话,他只要像我发给发这个链接,我发到群里面去,这个群里面有 10 个人,点击这个链接就跟你捆绑关系了,这 10 个人接下来一个月所有的付费都跟都会。你都会收到钱,那它是这个逻辑,所以,而且是及时的,一付款的话就会及时的到那个我们。 - -许永平 47:02 -你都会收到钱,对吧?但是这个逻辑,所以,而且是及时的,你付款的话就会及时的到那个群,你怎么获取到他? - -卡若 47:14 -群里怎么获取到它?ID,它点击这个小程序是带 ID 的呀。 - -许永平 47:17 -ID,他点小程序的 ID 的呀。 - -卡若 47:21 -是要他们点过才有,你没它。 - -许永平 47:21 -这要他们点过才有,没点我。 - -卡若 47:23 -它点进来就可以了,点。 - -许永平 47:23 -他点进来就可以了。我知道,就比如说你发到一个群里面,群里面有 5 个人,他如果没有去点的话,那点了没办法。 - -卡若 47:25 -就比如说你发到一个群里面,群里面有 5 个人。 5 个人,他如果没有去点的话。要点呢。没办法。点就绑了,我们就拿到。 - -许永平 47:35 -点就把它。 - -卡若 47:36 -跟传统,跟你传统分享出去其实是一个逻辑,跟群也没有关。 - -许永平 47:36 -它这个跟传统的,跟你传统分享出去其实是一个逻辑,跟群也没有关系。 - -卡若 47:42 -分享出去是一个逻辑啊。 - -许永平 47:43 -分享。 - -卡若 47:44 -这就跟你正常发一个人或者发到朋友圈人家去点的逻辑一样,它跟群也没有关系。 - -许永平 47:44 -这就跟你正常发一个人或者发到朋友圈,人家去点的逻辑是一样的,它跟群也没有关系。 - -王名正 47:51 -对呀。 - -卡若 47:51 -对,就是我指群,是群里面人多,你点了就容易嘛,是吧? - -许永平 47:51 -对,就是我只群,是群里面还多一点就容易嘛。就跟发个人一样啊。 - -王名正 47:56 -就跟发个人一样,他只是说把这个链接丢到群里了,然后曝光更多嘛。 - -卡若 47:56 -发个人一样啊。 - -许永平 47:58 -对。 - -卡若 47:59 -你推荐,比如,对,比如远志推荐给。谁谁谁,那这个人他只要点了,接下来他看了觉得有用,看了20%,想继续看,付一块钱你 9 毛钱就到你微信了。 - -许永平 48:03 -这个人他只要点了,接下来他看了觉得有用,接下来的一个月所有看的都跟你有关系,都自动的。 - -卡若 48:10 -而且这个人接下来的一个月的所有看的都跟你有关系,每次九毛都到你手上,知道吗?都自动的,它逻辑是这个,那我是可以看到有多少人绑嘛? - -许永平 48:18 -他逻辑是这个,那我是被看到的,所以你发一个群,比如这个群进去就很容易收费了,而且解还要这个解决另外一个问题,是到账的问题,这有。 - -卡若 48:21 -所以你发一个群,比如这个群 500 个人进去就很容易收费了。而且解,还有这个解决另外一个问题是及时到账的问题,这永平就特。 - -王名正 48:32 -这里面。 - -卡若 48:32 -特别要注意一下,因为这一块我就讲一下这个完善的一些东西嘛。 - -许永平 48:32 -您会特别要注意一下,因为这一块讲一下这个。这个用户详情页你估计得先以这个项目单独跑,先不接。 - -卡若 48:37 -用户详情页,你记得建议这个项目单独跑,就先不接。 - -许永平 48:42 -我单独跑。 - -卡若 48:42 -我单独跑,现在都实现了,我还搞啥呀? - -许永平 48:44 -不是,就是你说的这些用户轨迹,你只能说按你这个项目单独去实现这个功能,你如果要等去接那一块,然后用户轨迹。 - -卡若 48:46 -用户轨迹你只能做按你这个项目,按单独去实现这个功能,你如果要等等去接那一块,哪里那么快?用户轨迹,现在你这个改一下就可以直接用了,我现在是没有去改,知道吧。 - -许永平 48:57 -现在这个改一样,你走那。 - -卡若 49:02 -走那边。的话,我要完善的用户,然后这个交易。 - -许永平 49:02 -那边的话查的是不要完善,然后这个交易就是你先以这个项目名存在这个项目下。 - -卡若 49:09 -项目存在这个项目。现在就是存在这个项目,这个现在就没有问题啊。 - -许永平 49:11 -现在就好了。 - -卡若 49:13 -知道,但是你那个商详页里面。 - -许永平 49:13 -知道,但是你这个详情页里面。 - -卡若 49:15 -就是这里面,就是你要去看一下他有一些逻辑的,哪里还有能优化就优化一下嘛,是吧? - -许永平 49:16 -就是这里面,你要去看一下。 - -卡若 49:23 -包括这里面的一些,我说几个点嘛?他那边错了。 - -许永平 49:26 -他那边做好再去提,不然没用。 - -卡若 49:29 -没有,这个要现在要上线了,他们现在就是。 - -许永平 49:29 -你看这个要现在就是。对吧? - -卡若 49:32 -开始推,对吧? - -许永平 49:32 -所以说你现在你这个项目先存在这个项目,就按你的项目。 - -卡若 49:36 -然后这里的话就是一个交易中心和这个用户管理这边的那个绑定的这一个数据还没有到交易中心,他还没做统计,你看这个是付款的,但是这个还没做统计,你看一下那个接口的问题,这有永平,你对一下,明天挑个时间看一下。 - -许永平 49:36 -然后,嗯,这话就是这个交易中心用那个绑定的这个数据,但是这个还不够,这个就跟你对一下,一定挑个时间看一下。好,你这个。 - -卡若 50:00 -哦,你这个是。 - -许永平 50:02 -是这个就是一些用户管理的一些,那这个内容的我说一下长一点的逻辑核心内容这一块的话,还有一个问题是啥? - -卡若 50:02 -这个就是一些用户管理的一些点嘛?那这个内容的我说一下,你讲一下逻辑就比较清楚,内容这一块的话,还有一个问题是啥?就这里的话它是有免费章节的,设完免费章节前台还没有,这个就变成0,但是前台是没有反应的,前端的这一个它不会变成免费,这个我还没去修,我说几个 bug 你记一下就行了。 - -许永平 50:14 -就这里的话它是有免费章节的,设完免费章节,前台这里变成免费,还是前台是免费前端的这一个它不会变成。 - -卡若 50:31 -那这个文件路径。这个是不需要去想的,因为这个的话它是优先读取数据库的,数据库有问题访问不了,它才会读这个文件,它做了双向的,就这这几个,这几个的一个一个问题,我比较重要的一点是这个用户管理的这一块嘛。 - -许永平 50:34 -这的话他是优先要先读取数据库的,数据库有问题导入不了,他才会,他那个双下的就这几个,对,这几个这一块。 - -卡若 50:58 -现在付款这些是都没有问题了,付款呐什么的。 - -许永平 50:58 -所以他付款,这些是付款的。 - -卡若 51:02 -分销,然后提现呐? - -许永平 51:03 -分享这一个小的网页,这个就不用去网页关系那里。 - -卡若 51:04 -这一个是没有问题,就有一些小的问题,是吗?那网页这个就不用去管它,网页端现在不用去管它。主要还是小程序端。 - -许永平 51:17 -主要还是想听同学,然后这里的话。 - -卡若 51:19 -然后它这里的话我看一下这个,就我现在只会专注写东西,你知道吧。 - -许永平 51:30 -我现在只会专注写东西了。 - -卡若 51:32 -这一块我就不会太花时间了。 - -许永平 51:32 -这一块不会太花时间的。 - -卡若 51:35 -那存客宝接口。加好友。 - -许永平 51:38 -加好友。这加这个的话是确定提现的,这现在是自动,这个要实现的是自动分,就老王这个自动分他确定就对了,一样的,知道吧。 - -卡若 51:39 -接了这个的话是确定提现的,这现在是自动,这个要实现的是自动分,就老王这个自动分他确定就可以了,是一样的,知道吗? - -王名正 51:39 -写了。 - -卡若 51:50 -这个到时候也不接这个账号。 - -许永平 51:50 -你这个到时候也是接那个。 - -卡若 51:52 -他这个就是。 - -许永平 51:52 -他这个就是就完成了。 - -王名正 51:52 -就王子哥可以。 - -卡若 51:53 -关键字段。 - -许永平 51:54 -你把,你把你那个调通,这个也是,对,你们那些,就也是那些什么那个项目。 - -卡若 51:54 -你把你那个,对,你们那些就远志那边,咱们那个项目管。管理的这一些内容,你得统一一个文档管理,这样不会乱。 - -许永平 52:02 -管理的这些内容也一个文档,这样不会乱。 - -王名正 52:06 -那到时候我把这一个 Markdown 文件丢给你,你直接对接吗? - -卡若 52:06 -那到时候我把这一个 Markdown 文件丢给你,你直接对接吗? - -许永平 52:06 -那到时候我把这一个拉个大文件就给你。 - -卡若 52:11 -对,然后它里面有很多的那些那个逻辑,这个是逻辑是什么? - -许永平 52:12 -对,然后它里面有很多的那个逻辑,这个逻辑就是拆解一下,先了解清楚了,就是它这个里面的话能匹配的话。 - -卡若 52:20 -就是拆解一下先,你先了解清楚永平就是它这里面的话像匹配的话像这个。 - -许永平 52:32 -他这个第一个匹配的话,就是直接匹配,匹配数据库里面的一些用户,注册的用户,有危险的用户,注有手机的用户,有重要的手机的用户。 - -卡若 52:34 -第一个匹配的话就是直接匹配,匹配数据库里面的那些用户,有注册的用户,有微信的用户,有注有手机的用户,因为这个没有绑手机,所以匹配不到。 - -许永平 52:45 -那第二个匹配的话是他,那个他需要填资料,就是匹配相应的关键字。 - -卡若 52:45 -第二个匹配的话是他那个他需要填资料的,就是匹配相应的关键字就是你的,你的标签是做私域的,那你匹配找资源就会找私域的,或者我能解决私域问题,他填的。 - -许永平 52:54 -就是你的标签是做私域的,那你匹配找资源就会找私域,或者我能解决私域问题,他。填的是私域的管理度相关的,匹配一下,那后面这几个的话,匹配完之后就直接联系方式了。 - -卡若 53:02 -是私域两个关键字或相关的关键字,它就会匹配相关的,那后面这几个的话就是匹配完之后就直接留联系方式了,像这个他就直接调这个里面的这一个微信,那你确定之后就存客宝就加过去了,对,是我的,我那个号就加过去了,和这个也是一样的,这些都是要检查一下吧? - -许永平 53:11 -而且这个他就直接调一个里面的这一个微信,那你确认之后就是多少价格。这个也是一样,这些都是要检查一下,给自己一点提醒,那这个后端是因为现在是漏了。 - -卡若 53:26 -远志也去检查一下,那这个后端是没有问题的,现在是弄的是我。 - -许永平 53:32 -是卡若这个号去抢,只要他们匹配一下。 - -卡若 53:32 -卡若一个号去加,只要他们匹配就直接加了。所以存客宝那边的稳定性是那个需要去弄一下的,那这个我因为我肯定是要赶紧上线的,我明明天可能就要让他们直接用,肯定会出很多的问题的,到时候你群里面都一定会有。 - -许永平 53:38 -所以陈哥把那个权限是那个需要去弄一下。好。那这个我肯定是要赶紧上线,明天的就要让他们直接用。因为出很多的问题,到时候。都还没,都搞定。 - -卡若 54:04 -统计啥? - -许永平 54:04 -统计了。 - -卡若 54:05 -资金。 - -许永平 54:06 -资金。 - -卡若 54:06 -这个不用资金统计,他们能拿到钱、能分发、能有人付钱,能拿到钱就行了。 - -许永平 54:06 -这个不用资金统计,他们拿到的协议就是他能有的资金。厨房也没,也还没实现。 - -卡若 54:13 -分钱已经实现了,分钱他能直接实现,我刚刚就一块钱,你们回头自己付一块钱,就知道你转给永平,永平付一块钱你就能看得到了。 - -许永平 54:13 -分钱已经实现了,分钱他能直接实现,然后用一块钱,不要自己提一块钱,提现了你才可以。有没有一块钱就能看得到? - -卡若 54:23 -提现是在这边推广中心这里。 - -许永平 54:23 -提现是在这边,对完公司这。后台那个资金统计不是。 - -卡若 54:27 -不是。因为这个还没对,这个老王协助一下永平,对一下就好了。 - -许永平 54:29 -因为这个还没对多少,然后写你里面。 - -卡若 54:31 -你明天几点要? - -许永平 54:32 -今天要跟他们说可以使用啊。 - -卡若 54:33 -我明天早上 6 点我就开播,就说了就是这个提现不能再拖了,已经拖了一个月走了,我不可能这个流程已经通了,我也让他们跑过了这个分论分销跟登记统计的,你们就把修补一下就好了,他们核心一点就提现能,就像。 - -许永平 54:34 -我明天早上。那么早说了,咱们等下测试。 - -王名正 54:38 -就是这个理解,不能再拖了,因为拖了一个月流程已经通了,而且刚刚跑过了这个分店分销跟登记统计的,你们就把申请提现,你。 - -许永平 54:39 -就是这个洗一下,我跟你说是这个,我觉得不能再拖了,别改。基础流程应该都没问题的,应该是可以。流程已经这个分本分销。如果这些是可以的话,那基本是没什么问题。 - -卡若 55:02 -那你的小程序是一样的,一个提现,一个统计。 - -许永平 55:02 -企业下面小程序是一样的。 - -王名正 55:04 -对,你提现,现在,不,你现在提现不着急,你可以先让他们用完之后,我们然后之后再发一版。 - -许永平 55:04 -对,企业现在是一个。现在不着急嘛。 - -卡若 55:07 -不着急,你可以先让他们用了,用完了之后我们。 - -许永平 55:11 -对。 - -卡若 55:11 -不提现,直接用,因为这个就是你把你刚刚弄的那个功能接上去就结束了,知道吧? - -许永平 55:13 -极限直接用,因为这个是你把大家都弄,因为我们接上去就结束了。 - -王名正 55:14 -因为这个就是你想让他弄就接上去就结束了,你知道我已经最新的,我已经上到他。 - -许永平 55:19 -好。 - -卡若 55:19 -我已经是最新的,我已经上传到 GitHub 上面了。 - -许永平 55:19 -我已经是最新的,我已经上传到 e 卡上面。 - -卡若 55:22 -主要是你得审核。 - -王名正 55:22 -主要是你得审核,那小程序也要审核啊。 - -许永平 55:22 -主要是你得审核。不审。 - -卡若 55:25 -不审,现在不审。 - -许永平 55:26 -现在不审。 - -卡若 55:26 -小程序没有审的吗?小程序这个审核都秒过了。 - -王名正 55:28 -小程序这个简单。 - -许永平 55:28 -小程序这个审核都秒过了。 - -王名正 55:31 -没。我拉一个就秒,客户类型不一样。 - -卡若 55:34 -你那个,你那边,你是不是它本身就有支持不同商户的处理嘛? - -许永平 55:34 -你那个,你那边是不是本身具有支持不同商户的处理? - -王名正 55:41 -什么事? - -卡若 55:41 -因为这是两个不同的项目,你肯定是要跟不同商户的处理。 - -许永平 55:41 -因为这是两个不同的项目,是要跟不同商户的处理。 - -王名正 55:41 -不知道。 - -卡若 55:46 -不用,直接跟我们同一个。 - -王名正 55:46 -没有,不用同一个,对,你后台有弄的话就有像你那个接口写好了之后我发起提现,我数据库记录了,那就可以了。 - -许永平 55:46 -不用。 - -卡若 55:47 -同一个资金库。 - -许永平 55:47 -你拿到资金户。 - -卡若 55:48 -对,同一个就行。 - -许永平 55:48 -对呀。OK。 - -卡若 55:49 -那到时候对,那个明细发那个,对。 - -许永平 55:50 -他到了对应的明细。 - -卡若 55:52 -后台都有。 - -许永平 55:53 -后台他就像你那个接口是要发起提现数据不记录了。 - -卡若 55:55 -像你那个接口是这样,我说我发起提现,我数据做记录了。 - -许永平 56:01 -对啊。 - -卡若 56:01 -对,你到时候。 - -许永平 56:02 -到时候发起一些这种教育。 - -卡若 56:04 -我就给你们先。 - -许永平 56:04 -我是给你们信号,是吧? - -卡若 56:05 -这个字段。 - -许永平 56:06 -你看我这个 6 点就付款,这么大,哎,那点一下链接。 - -卡若 56:06 -你看我这个谁 6 点又付款了,一个一笔,哎哎,就是他是及时很重要,知道吗? - -王名正 56:07 -对,看不大。 - -许永平 56:15 -就是他是及时很重要,知道一个是我这边有付款,我这里他是主号,我一定会收到的。 - -卡若 56:17 -一个是我这边有付款,我这里的话是属于主号,我一定会收到的,你看是及时性,一有人付款他买了第几节我是立即知道,这个都不知道谁买的,对吧? - -王名正 56:17 -一个是我这边。 - -许永平 56:24 -你看看是及时现一有人付款,他们的第几节不是你知道都不知道谁买。 - -卡若 56:31 -我就收到这个钱嘛。 - -许永平 56:31 -是吧?我就收到这个钱。 - -卡若 56:32 -那比如我把这个链接给老王,知道吧? - -许永平 56:32 -那如果我把这个链接给老王,叫老王去付款,我这里收到钱了,好,钱。 - -卡若 56:36 -老王付一付款了,我这里收到 9 毛钱。诶,这实现不了,现在不是提现得自己,这个是相当于转账的功能,就不是那个提现。 - -许永平 56:40 -诶,这个实现不了,现在不是提现给自己,这个是相当于转账,不是那个提现。 - -卡若 56:46 -提现功能,这个是。提现在是要手动点的。 - -许永平 56:47 -提现是这样的,手动点的就没有自动。 - -卡若 56:49 -就是手动点,就刚刚这个过程跟老王那个一样。 - -许永平 56:50 -就刚刚这个过程,这应该是要调调转账的功能。 - -王名正 56:54 -他再一个是商户卡若是商户给他管理者,所以说有人付款商户的都能及时收到通知。 - -卡若 56:54 -他在一个是,他是卡若的管理者,所以说哦。 - -许永平 56:54 -他这一个是。看那个。 - -卡若 57:01 -他那个。那个分账的也是一样。 - -许永平 57:02 -那个分账收款记录不是分账。 - -卡若 57:04 -不是分账,对,他这是收款。 - -王名正 57:04 -对,这收款记录。 - -许永平 57:05 -对,他这是收款。 - -卡若 57:07 -分账的也是一样,就刚刚老王那个碎片时间的事情。 - -许永平 57:07 -分账也是一样。账和分账时间。账是现在要自己点。 - -卡若 57:10 -大家自己点对,自己去提现,然后就是领取。 - -王名正 57:11 -对,是。 - -许永平 57:12 -对。自己去提现,然后自己去领取。 - -卡若 57:14 -就是我刚刚的那个界面,他点了确定了他就到账了,知道他要需要自己点,就这个流程就跑一下,反正他们我明天会直接跟他们讲去,因为太久了一直在说,对吧? - -许永平 57:14 -就是我刚刚的那个界面,他点了确认他就到账了。对,他要自己点。大家要自己点这个流程跑一下,反正他们我明天会直接跟他们讲去,因为太久了,一直在说。好,就都那个群里,你看都。 - -卡若 57:30 -都那个群,你看都多少个人?真的嗷嗷待哺,他们天天培训,天天培训,培训没结果,很快就没士气了。 - -许永平 57:32 -找个人,然后再给他们培训,没结果,太磨士气了。 - -王名正 57:33 -OK。 - -卡若 57:37 -知道,我现在都是以让给他们补贴的,硬给的。 - -许永平 57:38 -是吧? - -王名正 57:38 -我现在都是让给他们对比,那这个已经基本上线,让他们去做分发就行。 - -许永平 57:38 -我现在就是让给他们补贴的,定点的。好。 - -卡若 57:42 -知道吧? - -许永平 57:43 -知道吧? - -卡若 57:44 -那这个已经基本能上线了,就让他们去做分发就行了,还有里面还需要一个逻辑的,也是要整理一下,就是接下来每我每新增一章节,我把这个过一下。 - -许永平 57:44 -那这个已经基本上线了,让他们去做分发就行了,还有里面还需要一个什么要整理一下,就是接下来每我每新增章节把这个过一下,明天 6 点肯定不能说明天的话,明天我们都还。 - -王名正 57:49 -那你里面还需要一种,嗯,就是接下来产品每新增一章节。 - -卡若 57:59 -明天 6 点肯定不能说别人的话,明天我们都把电话。 - -许永平 58:02 -用不直接用,先用出问题再说,现在是不管跟长能看到前情况明显出问题再解决就行了。 - -卡若 58:03 -不直接用,出问题再说现在是付款跟分账的,能看得到钱就行了,提现出问题再解决就行了。 - -王名正 58:03 -不用不用,之后你再说现在是试管。现在是试管。我再让他们想办法。 - -卡若 58:11 -我让他先让他们小规模测试,不要每个人都用。 - -许永平 58:12 -我让他先让他们小规模测试,不要每个人都用,还有我刚刚说啥来着? - -卡若 58:16 -诶,我刚刚要说啥来着? - -王名正 58:16 -他说他自动的接一下。 - -卡若 58:17 -那数据统计那块没用,那到时候数据一统计清掉。 - -许永平 58:18 -那数据统计那块没弄,那到时候数据你也得重新清掉。 - -卡若 58:21 -没有,它都自动地去分账,你管数据统计这个。 - -许永平 58:21 -不是,他都自动的去分散。不是后台的那个统计,你现在这个资金统计不是没有吗? - -卡若 58:25 -现在这个自己统计没用吗?这个就接一下嘛? - -许永平 58:28 -这个接一下,这个在就是统计这一块的。 - -卡若 58:28 -你们看一下这个跟就是统计这一块的嘛。对,那你给。 - -许永平 58:31 -对,那你。给他们用完,到时候数据对不上你就得清掉。 - -王名正 58:35 -那钱就直接现在知道怎么办了,一个人跑店的,一个人挣 9 毛钱也行。 - -卡若 58:35 -那钱都直接给他们了,现在不是自动分账了吗? - -许永平 58:35 -那钱呢?直接给他,这样不是自动分账了吗?不知道,就是。 - -卡若 58:41 -比如这里绑定这一个人,这 9 毛钱就直接那个嘛? - -许永平 58:41 -比如这里绑定这一个人,这 9 毛钱就直接点,你把这个。 - -卡若 58:45 -你把这个我明天肯定是先让他们去走,去发钱,然后里面有点钱。 - -许永平 58:47 -就是到你测过的话。 - -王名正 58:48 -我明天。 - -许永平 58:48 -我明天肯定是先让他们去,走,去花钱,然后这边说内部钱灰色的这种,对,先测一下,测的有问题再说吧。 - -卡若 58:53 -对,先测一下,出问题再说,这是一个,因为这个事情有一点是。 - -王名正 58:54 -我先测一下再说这几个,因为这个事情有一点是。 - -许永平 58:58 -再说这是一个因为这个事情有一点是。 - -卡若 59:04 -那个的他也就离变现比较近,直接就用就行了,对吧? - -王名正 59:04 -那个,那你这是比较近。 - -许永平 59:04 -那个,嗯,他以就离变现比较近,直接就有就行了,对吧? - -卡若 59:10 -然后里面有一些小小的一些逻辑,你们拆解完之后去看一下那个文档,自己去拆去看一下那个文档吧。 - -许永平 59:10 -那里面有一些小的线路,你们拆解完之后去看一下那个文档,自己去拆看一下那个文档。 - -卡若 59:18 -然后我刚刚还有一个啥事,对了,这里的话是新增章节,我会新增一些章节,比如新增一块这个数就会变,这个是另外一个隐藏的版块了,新增一个那个数就会变成 9 块9,比如今。 - -许永平 59:19 -哦,对了,这里的话是新增章节,我会新增一些章节,比如新增一块,这个是另外一个隐藏的板块,新增一个,那个数据会变成 9 块9。 - -王名正 59:19 -对,这里的话是新增章节,我会新增一些章节,新增这数字变这个是另外一个,新增一个,那个数字会变成 9 块9。 - -卡若 59:32 -挣一块就变 10 块钱,我多写一张就变 11 块钱,但是 9 块 9 是现在 62 张,小结是相当于是基础版的 9 块9, 62 张后面新增一块。 - -许永平 59:34 -我多写一张就变 11 块钱,但是 9 块钱的现在 62 张奖金是相当于基础款 9 块钱, 62 张后面新增一块。 - -王名正 59:36 -但是 9 块钱变成62。也是。62。 - -卡若 59:44 -跟章节有关系,跟你里面的这个价格。 - -许永平 59:44 -跟章节有关系,跟你里面的这个价格没关系。 - -卡若 59:48 -跟价格有关系。 - -许永平 59:48 -跟价格就你多一张就多一块钱,我可以设成两块,我多 100 块。 - -卡若 59:49 -就你多一张,就多一块钱嘛。我可以设成两块就多两块钱,我多 100 块就多 100 块钱。 - -许永平 59:55 -那就是加上你新增的这个章节的总共多少钱嘛? - -卡若 59:56 -加上你新增的这个章节的多少钱呢? - -王名正 59:59 -来一个,是。 - -卡若 59:59 -它就等于一个是普通版。 - -许永平 01:00:00 -它不等于一个是多。 - -卡若 01:00:02 -一个是增值版,买普通版还是 9 块9,买增值版的就是 9 块 9 的不断的叠加。 - -许永平 01:00:03 -那是增值版,买普通版的是 9 块9,买增值版的。 - -王名正 01:00:04 -来,我们把。 - -卡若 01:00:09 -叠加的金额是不是你新增章节的金额吗? - -许永平 01:00:10 -加的金额就是新增的发票金额。对,就这一个,就有一个普通版的那个增值版。 - -卡若 01:00:14 -对,新增章节的金额就这一个,就有一个普通版,一个新那个增值版的。 - -王名正 01:00:22 -对。 - -卡若 01:00:25 -那你这里面也没有分普通版跟增值版。 - -许永平 01:00:25 -那你这里面也没有分普通版和增值版。 - -卡若 01:00:28 -还没分,但这个你们记要就要记一下这个事情。 - -许永平 01:00:28 -还有一个就是要,就要记一下。 - -王名正 01:00:30 -你们说专把。 - -许永平 01:00:32 -事情。 - -卡若 01:00:38 -目前两个逻辑都。 - -许永平 01:00:38 -目前两个逻辑都没有,对吧? - -卡若 01:00:40 -哪个逻辑已经有那个,但是他这个是看了十章之后才会触发这个增值的这一个内容。 - -许永平 01:00:40 -哪个逻辑已经有那个,但是他这个是看了十张之后才会触发这个增值的这一个点。 - -王名正 01:00:41 -因为有那个。 - -卡若 01:00:50 -就比如匹配三次就要让他填手机号码了,他可以免费匹配第三次,他就要自己填手机号码这一些里面的一些和那个。 - -许永平 01:00:50 -就比如匹配三次就要让他填手机号码,他可以免费匹配第三次,他就要自己填手机号码这些里面的一些那个。 - -王名正 01:00:55 -他可以免费。分析里面的一些那种,那个。 - -许永平 01:01:02 -那个步骤跟逻辑,还有一些小型的算法在这里面就匹配三次,所以然后他付款买了一张才能匹配资源,这里面猜一下就比较清楚一点,或者是现在的话,一个极限的话可以快速记一下极限,记得这个快速了解一下这个事情。 - -卡若 01:01:03 -步骤跟逻辑,还有一些小型的算法就在这个里面,比如匹配三次之类的,然后他付款买了一张才能匹配资源,这里面你们猜一下就会比较清楚一点,或者现在的话一个提现,老王那边就快速地对一下提现跟统计的这一个点,跟永平就快速地了解一下这一个事情,这一个是。 - -王名正 01:01:22 -这个是现在的一个极限。 - -许永平 01:01:32 -这一个是为什么? - -卡若 01:01:32 -为什么让你们快速过一下这个事情呢? - -许永平 01:01:33 -让你快速过一下我的一本书单位开完会,这也是可以,这个机构的文档是一样的。 - -王名正 01:01:34 -他是那个。 - -卡若 01:01:35 -他现在用在的地方很多,现在只是我的一本书,对吧?我们昨天刚去那个银掌柜那边也开完会,这个也是可以应用在金融方面的,就我丢一个金融的文章过去解决获客给他们中台,那就不用,不一定买手机了,是不是一样的逻辑? - -王名正 01:01:56 -都一样,逻辑性一样。 - -卡若 01:01:58 -是一样的,是吧?你看。看一些金融的一些视频,或者一些干货一样的,是吧? - -许永平 01:02:06 -然后这个要记一下,看把这个进度,而且可以在对这些的时候不考虑一下这方面,对才会发现。 - -卡若 01:02:12 -这,这个就要记一下,看那个嘛?你把这个进度每次就新增一条,有一个进度条嘛。 - -王名正 01:02:18 -你看。 - -卡若 01:02:20 -我们就几条线,可以这几条线直接往下去弄,然后永平在对这些的时候,你就多考虑一下审社所这方面的事情,你对着就才会发现哪里有问题嘛。 - -许永平 01:02:32 -好。 - -卡若 01:02:33 -对吧?因为我们一定是那个,包括老王,也是你在对碎片时间,对这个数据接口的过程当中碰到问题就直接解决掉。 - -许永平 01:02:33 -那我们一定是,包括老文也是在对碎片时间,对。 - -卡若 01:02:44 -问题肯定有的,你看远志今天铺这个问题不就出来了吗?那我们把它解决掉就行了,对吧?你这个机器的这个基础的那个配置,配置完之后是就会有很多的就直接复制就行了,是吧? - -王名正 01:02:52 -第一次。 - -卡若 01:03:02 -就不会太多,有很多的参考的一些东西,是吧? - -王名正 01:03:03 -就不会。所有的参考。 - -卡若 01:03:08 -包括这个我再简单地说另外一个事情,那个我发了一个会议纪要的那个通版的那个原则。 - -王名正 01:03:13 -那个要这个,但是不一样,这次不一样,会自动。 - -卡若 01:03:19 -在哪?我就在这个 NAS 上面,这个。这个是智能纪要的,这个智能纪要会自动,你总结完就自动发到群里面了,我。过一遍。 - -许永平 01:03:33 -懂的话。 - -卡若 01:03:33 -就是 V0 的那个要考核的吗? - -许永平 01:03:34 -他来不出答案。 - -卡若 01:03:35 -这个就变成固定版了。看一下。我给你过一下,这个你就比较清楚,对,你们直接对完那个,直接那个嘛。 - -王名正 01:03:41 -我让那些配置参数先码给。 - -卡若 01:03:47 -嗯,我看一下,就昨天的,我举个昨天的,因为你在 cursor 上就能直接解决,我看你 V0 不太喜欢用。主要是它加载不出来。对吧?找了密钥,怎么了? - -许永平 01:04:03 -咋了? - -卡若 01:04:04 -打开了。 - -王名正 01:04:05 -打款的。 - -卡若 01:04:08 -那我。你这个发到群里可以发出去,你发到群里了。 - -许永平 01:04:12 -可以。 - -王名正 01:04:13 -我发你个人了。 - -许永平 01:04:15 -发到群里了。 - -卡若 01:04:16 -发群里了。发出去是发出去了,这个怎么能发到群里? - -王名正 01:04:17 -发群里了吗?是发群还是发个人了? - -许永平 01:04:18 -你发错了,撤回一下。这个怎么能发到群里?去找一下,还有其他的吗? - -卡若 01:04:23 -群里面还有其他人吗?没有,我们这群没其他人。 - -许永平 01:04:25 -没有。 - -卡若 01:04:27 -没有。 - -王名正 01:04:27 -没有。 - -卡若 01:04:28 -自己人没事,有其他人就别发了,我。 - -许永平 01:04:29 -那就行。我想知道。千文还有。 - -卡若 01:04:32 -我把那个我给你过一下这个东西,比如这个昨天永平开会的嘛。 - -王名正 01:04:33 -我那个这种。 - -许永平 01:04:34 -那个你可以过一下。 - -卡若 01:04:38 -你说的那个是 cursor 的生成会议纪要的内容。 - -许永平 01:04:38 -你说的那个是 cursor 的生成会议纪要的。 - -卡若 01:04:42 -不止生成会议纪要,我跟你们讲有两个事情,不然我不会拎出来讲。生成会议纪要那就太简单了,这一个是我放到这随便拉一下,你看发送那个,诶诶? - -许永平 01:04:49 -这个是好的啊。 - -卡若 01:05:01 -没拉过去拉。 - -卡若 01:05:09 -诶,你这是飞书链接吧?不,我,我跟你讲,等一下,我先拉过来。上面那个是啥? - -许永平 01:05:17 -方面的一个思考。 - -卡若 01:05:18 -等一下你把这一个生成总结纪要,然后发到飞书的这个群里面来,我简单地说一下。个,这个是飞书的这个Webhook。 - -王名正 01:05:35 -那个。 - -卡若 01:05:38 -就拉了一个小机器人嘛。对,就这里面,你可以,这里面微信也可以实现的。我讲这个是这一个逻辑,跟我们这个现在存客宝功能有用的,这里的话是配置的一个那个 Webhook 的地址。知道,那我这个做 Webhook 的地址做完之后是干嘛呢?我现在是不是把这个智能纪要这个弄完了? - -王名正 01:06:03 -是不是? - -卡若 01:06:06 -然后这一个就总结智能纪要,总结纪要,然后就回测一下,它就生成直接发到群里面去了。 - -王名正 01:06:12 -一样。 - -卡若 01:06:20 -知道,那这个是用来干嘛的呢?先,你们先看一下流程,会比较清楚。微信应该没这种功能吧?微信有我,我们存客宝也可以做。 - -王名正 01:06:29 -不不不。 - -许永平 01:06:31 -你说事啊。 - -卡若 01:06:32 -这个的功能发到个人的群也可以做这个功能的。 - -王名正 01:06:32 -产研团队每日会议, 2026 年开会前必看。无文档不开会,会前请大家按照模板填写要讨论的内容,踊跃评论,积极讨论。 - -卡若 01:06:37 -这现在没有去做嘛?我先把这几个字提到的你们就记一下,不然回头都会忘掉,知道吗? - -王名正 01:06:40 -准时开始后集体默读 10 分钟, 10: 00- 10: 10,请所有人踊跃评论,这也会被。 - -卡若 01:06:43 -这个就是要直接加到一些需求里面去,我先说一下这个思路是怎么样的? - -王名正 01:06:44 -产研团队每日会议, 2026 年开会前必看。无文档不开会,会前请大家按照模板填写要讨论的内容,踊跃评论,积极讨论。 - -卡若 01:06:48 -这个智能纪要它做完之后,它就自动的是把这个发到这个飞书群里面去,那发的样式是怎么样? - -王名正 01:06:52 -准时开始后集体默读 10 分钟, 10: 00- 10: 10,请所有人踊跃评论,这也会被。 - -卡若 01:07:01 -像这个吗?我给你看一下,他们现在也那个发出来的样子,就长这样,嗯,他就会应该受,咋会跑到这里去? - -王名正 01:07:07 -微信的那个发出来的样子。 - -卡若 01:07:19 -什么鬼?一条消息?那这个可以做到什么程度? - -王名正 01:07:26 -这个可以做到。 - -卡若 01:07:27 -就是我们开完会之后触发自动地去把。这个内容发出去。 - -王名正 01:07:34 -发出去,不需要,那这个。 - -卡若 01:07:36 -那你前面那些下载不是手动的吗? - -许永平 01:07:36 -前面那些下载。 - -卡若 01:07:38 -不,不需要,我给你看看,做完了你们打开群看一下。比如说前面几步不得是手动吗? - -许永平 01:07:48 -就前面几步都给手动,他就会是。 - -卡若 01:07:49 -不需要,我等一下会说,我只是为了展简单演示,告诉你们它的实现流程,是吧?它这个图片,没没没发图片,没发你就正把图片也发过去。通过接口把会议图片,我说一下,这个要配置那个TOKEN,所以我才没有先给你们过一下,这一个就比较清楚,是吧? - -王名正 01:08:05 -对。没错。 - -王名正 01:08:18 -我说一下这个在配置那个。 - -许永平 01:08:21 -对。 - -卡若 01:08:33 -他这个是昨天的一些总结, 12345 的,他还会有一张图片出来,那这个我已经放到那个里面去了。 - -王名正 01:08:33 -那这个是我已经发到这里了。 - -卡若 01:08:42 -工作流吗?对,他是一个工作流,这个是基础的一个一个事情,那他可以做到的一点是什么? - -王名正 01:08:45 -那是。那他可以做到。 - -卡若 01:08:50 -就是咱们这边不是有那个会议的图吗? - -王名正 01:08:53 -反正这边不是那个会议的,那。 - -卡若 01:09:05 -就比如我们开会的文档,你直接丢过去就可以了,来,我给你们过一下就知道了,要一步步,不然一定会乱,那么他这个有点不一样。 - -王名正 01:09:08 -跳过直接贴过去就行。 - -卡若 01:09:25 -那不也要用客色吗?手动的。你这一步不也手动吗? - -许永平 01:09:29 -这也不也是手工吗? - -卡若 01:09:30 -自动发旅客色吗? - -许永平 01:09:31 -能自动发客户? - -卡若 01:09:33 -当然是可以的,我是一步步跟您讲的,不是您才知道实现流程,不然会有那个的这个要应用到其他地方去,就是现在就把这个链接里面的这一个文字文档导出来,然后发到飞书里面,发到那个会议纪要的飞书里面,然后全部用命令行,不要出现那种扫码的一个一个形式,然后你直接去获得那个相应的 API 跟TOKEN。 - -许永平 01:09:33 -当然是可以的,我是一步步想才知道自己成功了。 - -王名正 01:09:40 -这个要应用到其他地方去,就是现在这个预约。 - -王名正 01:09:56 -不用命令。 - -卡若 01:10:03 -就大概这样,好吧?你给他回,他就会去找链接,自己链接里面文字找出来。 - -王名正 01:10:08 -那就会去找链接,链接就对。 - -卡若 01:10:12 -那这一步,这一步你要怎么去实现自动化? - -王名正 01:10:12 -那这一步你要怎么去实现这个? - -许永平 01:10:12 -那这一步,这一步要在执行那个会议丢到科室里面去执行这种。 - -卡若 01:10:15 -哪一步? - -王名正 01:10:15 -诶,你说开那个会议室吗? - -卡若 01:10:15 -你说。开执行的这一步。开那个会议,是吗?就那个会议丢到 cursor 里面去执行这个东西。 - -王名正 01:10:19 -这个会议丢到科室里面去执行这个东西。 - -卡若 01:10:22 -对,这个就是会议,那这个就非常更简洁了,这一步一步来嘛,你就现我们把每天的这个,你抓到这个产研团队会议纪要。 - -王名正 01:10:22 -对呀,这个就是会议,这个就非常更简洁了,这一步一步来,你在线,我们把每天的这个,你抓到这个产研团队会议的。一样的一个内容,开会的这个通过飞书的这个API。 - -卡若 01:10:32 -的这一个内容,开会的这个通过飞书的这个API。他那个。 - -王名正 01:10:38 -他那个是多久啊? - -许永平 01:10:38 -他那个的内容。 - -卡若 01:10:38 -你听我讲完,然后把这个内容,那个视频会议最新的有产研团队会议的内容,把它那个发送到这个,那个解析成最新的这个链接,然后发送到总结成那个会议,发送到那个飞书群里面,那一定要带图片,然后就让他去执行就行。 - -王名正 01:10:42 -会议最新的那个会议的内容,那个发送到这个,那个系统最新的这个链接发送到,总结成这个会议,发送到飞书群。 - -许永平 01:10:47 -发送到这,最新的这个,立即发送到这个。 - -卡若 01:11:03 -诶,咋没看到这个,知道吗?那你每一天开会的,当天开会的产研团队的内容,并且内容要超过 5 分钟以上的内容才执行这个步骤,那全部用命令行实现,不要用网页和这一个,然后把这个 schema 更新一下。 - -王名正 01:11:06 -那你每天开会的当天开会的产研团队的内容,并且内容要超过分钟以上内容才执行这个步骤,那全部用便利贴实现,不要用网页和这一个,然后把这个细节的更新一下。 - -卡若 01:11:31 -就大概是这样。 - -王名正 01:11:32 -是这样。 - -卡若 01:11:39 -我就走一下过程,因为这个我已经做完了,所以这一些就是你迭代进去的,就是我们每天开会它是自动去捕捉,开完会自己去捕捉这一些东西,那这个只是基础的一些事情,我在那它这个就做。 - -王名正 01:11:40 -我就走一下过程,因为这个我已经做完了,所以这一些就是迭代进去,就是我们先开会,但是自动去组织,开完会自己去组织这个这些东西,那这个只是基础的一些事情,我觉得。 - -卡若 01:12:02 -做成做完的吗? - -王名正 01:12:02 -就做完了,他没有做成图片的形式。 - -卡若 01:12:06 -过一下吗?但这个他没有做成图片的形式,这个可以做成 html 的图片的形式,因为他这个是总结的行动项,简要的行动项,那你可。 - -王名正 01:12:23 -这个可以做成 html 的图片的形式,因为它这个是总结的行动项,简要的行动项,那。 - -卡若 01:12:32 -可以变成什么? - -王名正 01:12:32 -也可以变成什么? - -卡若 01:12:33 -变成那个会议纪要的形式就可以了。 - -王名正 01:12:33 -变成那个会议纪要的形式,现在是写了一个,你可以还变成会议纪要的形式,因为这个有个总结文档,一个会议纪要那个工作也我也丢进去了,真的。 - -卡若 01:12:36 -他现在是截了一张图过来了,你可以把它变成会议纪要的形式,因为这个有个总结文档,一个会议纪要那个工作流我已经丢进去了,你们自己去在 NAS 上面,那你不用那么智能也可以了,就是生成完之后直接丢就好了,我只告诉你它是可以。 - -王名正 01:12:55 -那你不用那么智能也可以啊,就是生成完之后直接丢入就好了。我只告诉你他是我的意思就是说你。 - -许永平 01:13:01 -是我们。 - -卡若 01:13:03 -手动去开 cursor 去执行,对吧? - -王名正 01:13:03 -手动去打开搜索去执行这个东西,我只是说把之前的几步,你现在变成了。 - -许永平 01:13:04 -去各自去执行,是说只是说自己。 - -卡若 01:13:09 -打开。说只是说把之前的几步现在拼成一步。对,打开 cursor 肯定是要打开的。 - -王名正 01:13:15 -对,那我的意思是说你的,我以为你说的是全自动。 - -许永平 01:13:15 -对,那我的意思是说,我以为你说的这种全自动的。 - -卡若 01:13:15 -那我的意思是说你能,我以为你说的是那种全自动的。那全自动的肯定是能实现的,但是你部署很麻烦的。怎么不能实现全自动的?早就能实现了,就是有些东西我说得太抽象,你们会有很多卡点。 - -王名正 01:13:26 -就是有些东西我说得太粗,你们会有很多。 - -许永平 01:13:30 -说的太抽象。 - -王名正 01:13:32 -有卡点让你们去做,现在都稍微你们现在的一个。 - -卡若 01:13:32 -卡点知道吗?你如果去做这个,现在都我给你,稍微,每天我都给你们分享一点嘛? - -许永平 01:13:35 -如果去做会需要。 - -卡若 01:13:40 -你们就知道一些东西,那这个会议纪要就你快速地去弄一下就知道了。那这个这什么鬼,对吧?他自己会去实现一些东西,自己去解决这个问题,不管他,但有一点是什么,你们现在有一个。问题就是像你刚刚说的,自动的我给你看,自动的去分发,就是我给我自己的微信发条信息,他自己去解决所有问题,是吧? - -王名正 01:14:03 -问题是像你刚刚说的自动的。 - -王名正 01:14:18 -自动地去分发,但是我给我自己微信发消息,解决这个问题,我自己去执行了,也不用那个嘛,给你之前还是那个。 - -许永平 01:14:18 -自动机器人的那个。 - -卡若 01:14:24 -自己去执行嘛,你不是那个嘛?那我给你看一下。机器人的那个,是吧?比机器人那个先进多了。过了,那个什么鬼玩意? - -王名正 01:14:32 -产研团队每日会议, 2026 年开会前必看。 - -卡若 01:14:36 -你不是用他的那个模型吗?他的是抄另外一家的,有几家的不一样,那像这个看到没有? - -王名正 01:14:39 -无文档不开会,会前请大家按照模板填写要讨论的内容,踊跃评论,积极讨论。 - -卡若 01:14:47 -这个消息中枢是干嘛的呢? - -王名正 01:14:48 -准时开始后集体默读 10 分钟。 - -许永平 01:14:50 -是,行。 - -卡若 01:14:50 -就是我自己给微信发信息,我给我自己的微信发信息,我这没装嘛? - -王名正 01:14:55 -10: 00- 10: 10 请所有人踊跃评论,这也会被。 - -卡若 01:15:01 -我给我自己的微信。 - -许永平 01:15:01 -没有自己。 - -卡若 01:15:02 -发信息他自己会去执行所有的动作, Whatsapp 也可以,微信也可以,就所有的都可以,包括网页。 - -王名正 01:15:09 -OK。 - -卡若 01:15:15 -那我就给你们过一下,这个是我给他发信息是发干嘛呢?也可以语音微信,我给他发信息之后,先说一下后面的那个逻辑,他这里这边他会自己去招募人,你知道吗?我给他发信,因为他能力越来越多,他自己去招募团队了,你看每个团队的一个能力和人设,他自己会去定义,这个不是我弄,他自己去生出了几个崽出来。 - -王名正 01:15:45 -这个比如说我让他自己去搜索一个产品。 - -卡若 01:15:50 -就是我上次看他们的那个逻辑,其实就是他,你的下面其实要有一个AI,然后这个 AI 再去帮你。 - -王名正 01:15:54 -当你的上面要有一个。 - -许永平 01:15:56 -你要有一个AI,然后这个 AI 再去。 - -卡若 01:16:03 -控制你下面团队,这还要多一层,就是中间有个 AI 去帮你做所有的事情。 - -王名正 01:16:04 -你下面。对。没有这个意思,就是中间有个这样去做所有的事。 - -许永平 01:16:12 -那肯定这个就是一个AI,它这五个管理就管理每一个。 - -卡若 01:16:12 -那肯定这个就是一个AI,它这五个管理每个人都有,你把它变成就是。 - -许永平 01:16:19 -如果就是它上面其实还有一个管理员,然后它底下就是管理的几个管理层,对,管理它也有自己的记忆。 - -卡若 01:16:20 -其实还有一个管理。管理员,就这个就是大的管理员,他底下就是几个。几个管理嘛?几个管理嘛?那几个管理。对,管理他也有自己的,比如他记忆。 - -王名正 01:16:30 -他也有自己的虚拟币。 - -卡若 01:16:32 -记忆的功能,对吧? - -王名正 01:16:32 -业务功能每个管理组管理内容不一样,是一个可以吸收给这个随便举个例子。 - -许永平 01:16:32 -也包括我们,是吧? - -卡若 01:16:34 -他每一个管理就把他的能力往下去拆分了,对吧? - -许永平 01:16:34 -他每一个管理者。 - -卡若 01:16:39 -他管理有管理的能力,然后他底下把能力分配给他底下的团队成员去执行嘛。 - -许永平 01:16:39 -他管理。 - -卡若 01:16:46 -每个人是不一样的,性格也不一样的。那比如我们要做一个分类的话,他自己会去吸收一些东西出来,吸收给这个团队,知道吗?我随便举一个例子,你看像。 - -王名正 01:17:02 -像这个。 - -卡若 01:17:02 -这个我好几个。 - -卡若 01:17:17 -你看他比如这个手机自动操作的,是吧? - -王名正 01:17:18 -任何问题都可以问。 - -卡若 01:17:24 -这个我已经有一个版本的能力,你看我这一个。对吧?然后像这种搞流量的自动去做排名的,对吧? - -许永平 01:17:39 -好。 - -卡若 01:17:41 -把这两个这个文档的这个核心代码跟它的一些那个流量获取的一个形式,形成自动化操作的一个stream。然后你安排,看安排谁来安排这个能力到哪一个人设的身上?然后哪一个人的身上?你把这个放到卡若 AI 底下。的一个一个skill,然后用中文名来命名嘛?我跟你讲讲一点是怎么样去吸收一些你能看得懂的一些能力嘛。这个首先是自己能看得懂并且执行过,好吧? - -许永平 01:18:12 -这两天一起实现你这个通过百度的算法,但是他新做的。 - -卡若 01:18:16 -因为这个是通过百度的那个巨峰算法去做 SEO 排名的,那你当他吸收这个能力就可以了,他自己。过一下这个过程就知道了。 - -卡若 01:18:44 -连志刚刚发的吗?发啥?我刚发飞书,发啥?你看。你说这个机器人。两个项目核心能力的 schema 并归属 to b,它就属于这里,我就很它就分配给一个人去了,它。 - -许永平 01:18:59 -他就分配给一个人去。 - -卡若 01:19:02 -自己知道谁来做这个事情最合适,看到没有? - -许永平 01:19:02 -他自己知道谁来做这个事情。 - -卡若 01:19:08 -在这。嗯,那你就知道他为什么分配给他,我都不管流量自动化,看到没有?你看看这个人干嘛?他自己去招了个人来干这个事,知道吗?那你这个人是通过他的性格来定义的,知道吗?你看引流滋养它记忆联想性格,这爱表现的是吧? - -许永平 01:19:45 -对。 - -卡若 01:19:49 -你看手机和网页自动操作,你看这个是我之前做那个网站排名的和那个淘宝排名的,十几年前的东西了。 - -许永平 01:20:01 -他们还有另外做法,就是定义一种名正。 - -卡若 01:20:03 -你看。还有另外一种做法,就是定义一种名人的。名人那个很容易,你把他名人的能力吸收掉就行了。 - -许永平 01:20:08 -但那个对,就是比如说什么雷军,对啊,就是你还得去提炼他的过往,可能他写的一些书什么的,让他去清洗,提炼出他的能力,其实就是定义他的能力。 - -卡若 01:20:12 -就是比如说什么雷军这种乔布斯啊。那个不完善,你首先得有他们的库。对啊,你还得去体验他的库嘛。那他写的一些书,或者就是你们的能力,把他定义完之后,他知道你的能力边界他自己会去吸收。就是定义他的。知道,反正我。我给你们分享一下这个的一些新的一些用法,它就这里边它就是 5 个人去招募了,现在有 17 个人, 17 个人每个人解决一个问题,是吧? - -许永平 01:20:35 -一些新的。这里面招募了 17 个人,一个人、两个人。 - -卡若 01:20:45 -然后我能做什么?你看自动化操作网页刷流量,什么什么什么什么,因为这个我已经实现了,我根本就不用去管它,因为我知道它实现逻辑跟问题,然后你看我还可以干嘛呢?用那个卡若 AI 的整个的团队来分析一下这个skill。帮我提一些优化的建议,然后最后形成一个PK,看谁的建议最好。你看整个团队去优化它。他这个层级应该最底下是 CEO 人力,然后在上面一层就是工作流,在上面一层就是属于这种数字员工。就是这个就会变成什么,你知道吗? - -许永平 01:21:28 -这种场景。 - -卡若 01:21:30 -就是他。他是把你的能力,这么多年沉淀的能力做拆解的,并且形成一个记忆的一个形式,然后分配给执行的人,而且不会出错,你能力拆得越细就越不会出错,知道吧。 - -许永平 01:21:32 -然后。 - -卡若 01:21:50 -所以怎样去把这一些,包括那个视频剪辑切片的一些能力,你多方的去验证它有商业知道有开发、有商业、有流程,对吧?有。有一些 7 的, 8 的,你用久了之后,这一块的话,它是就会给你一个很完善的一个东西,就等于十几个专家,那这个专家你觉得只要你一定要验证过,不要让他吸收垃圾就晕了,就会变成。 - -许永平 01:22:12 -是。好的。 - -卡若 01:22:21 -越来越垃圾。 - -许永平 01:22:21 -也有遇到。 - -卡若 01:22:22 -也不会变成越来越垃圾。他会性格会变成什么?变成 enfj 啥都学,你这性格会变的,你会发现谁变成 enfj 了,然后他的。这个岗位又不错了,那肯定这个吸收了很多垃圾了,知道吧? - -许永平 01:22:32 -到了这个岗位。 - -卡若 01:22:36 -为什么定义性格知道吗?它会变的。那你看吧,它这一些我就给你们过一下它是怎么样去实现的讨论的,包括你那个这些智能提问什么的,它都自己帮你跑完了。知道,那我等一下给你们讲本地模型怎么用嘛。不是跑本地的吗? - -许永平 01:23:01 -这是靠本地包。 - -卡若 01:23:03 -他一部分跑本地的,所以我消耗很低的。你别以为这个消耗很多,我消耗很低的,我等一下给你们看。为什么?你看他就研讨会,你看他参与着 ABCDE 会议开场大总管开始,他就开始汇报。 - -许永平 01:23:19 -可以。 - -卡若 01:23:27 -之前我也想过,我等拉个讨论群,先把目标丢进去AI。大家先自己去讨论一遍每个人。你要你这个要把你的团队变厉害,知道吧?你看他就,嗯,你看他提的很多的建议,是不是每一个人有每一个人的观点?模拟现实我们开会的那种场景。 - -许永平 01:23:50 -模拟现实我们开会的那种场景。 - -卡若 01:23:52 -是不是?而且他很快,那看是不是?多给执行。 - -许永平 01:24:03 -用本地跑的吗? - -卡若 01:24:03 -本地跑的吗?这个。来,我给你们看一下本地的这一些东,我就给你们多分享一下这些东西,大家。刚才不是调 c 了吗? - -许永平 01:24:09 -刚才不是掉 c 了吗? - -卡若 01:24:10 -用cursor。 - -许永平 01:24:10 -不是用 cursor 吗? - -卡若 01:24:11 -我用cursor,我当然有更好的解决方案,我给你。 - -许永平 01:24:15 -这是用 cursor 跑出来的呀。 - -卡若 01:24:15 -用 CURSOR 跑出来的呀。才不是呢,一部分 cursor 而已,给你看这个,这个应该是本地的模型,我看一下,不在这,我其实都不关注它在哪里。 - -许永平 01:24:18 -cursor 你看。 - -卡若 01:24:33 -不需要关注它在哪里?我看一下这个放在哪里。有一个盆,应该是在那个这里。 - -卡若 01:24:54 -看一下小程序飞书管理。 - -卡若 01:25:05 -那个本地模型的在哪?来我,你打开。那边有搜索吗?第2个有。 - -许永平 01:25:12 -要做。 - -卡若 01:25:14 -本地。 - -卡若 01:25:24 -卡火。这在卡火里面看一下。因为我现在就不关注的这个跟团队成长是一样的,当你到团队到 20 个人的时候,基本没空去看,只要记住他名字跟能力和他的那个循环就可以了,你知道吗?这个是啊,在这还没有本地模型,给你们看一下你就知道咋用了。你看这个本地模型管理,我本地有三个模型的,但是它我不会,是,它自己会去启动。是提醒当卡若 AI 使用本地模型时自动使用提醒,是吧?它有三个,一个叫轻量,我定义了两个东西,这个是千问的。轻量是来解决文本摘要的问题的,它只处理,而且。 CP 会控制在30%,它不会控制太多,所以它不会,我怎么用都不会卡。那这个提醒,这个共享模块是任何的 skill 都可以调用的,等一下给你们看共享模块嘛。 - -许永平 01:26:45 -这共享的模块是一样的,都可以。 - -卡若 01:26:54 -那这些就是一些基础的一些参数,在 cursor 上,你看。现在是用了这个隧道,不然你启动不了。 CURSOR 是可以直接调的,就是他需要做文本向量化跟简单的文本的总结的时候,他就会调本地模型,他不会调那个 cursor 的东西的,大概给你们过一下,所以我你看这三个是。是都有用途的轻量对话,一个中等对话,还有一个文本向量化,三个不一样的模型,干三个不一样的事情,他自己会去使用和调用这个东西,这他需要做简单的动作的时候,他就会去找这个事情,那这些就调用的形式就不看了,后面这些是调用的形式嘛。然后它跟你看它的性能对比,这里面有个轻量的,这两个是千问的差,有差多少你自己看一下,就差它只有 20% 的那个 Claude 的 4.5 的 20 的能力,那它只有它 35% 的能力, sonnet 是那个 Opus 的那个85%,你就做能力对比,它自己会去猜嘛? - -许永平 01:28:10 -他有他的。 - -卡若 01:28:32 -然后这个是免费的嘛。就这一个,你看这个差 5 倍, Sonnet 跟 Claude 的价格是差 5 倍的,跟 o 那个 Obeus 两个,是吧?那肯定本地的不上传云端,它有一些好的一个地方,它读取文档秒级的咔一下就读完了,是吧?根本就不用去搞来搞去很麻烦,所以有一些向量化的东西,为什么我那个读。 - -许永平 01:28:56 -用例,对,好。 - -卡若 01:29:02 -他们读很多东西会很快就这样嘛?那他自己这个 schema 他读完之后他就自己会去做了,应该简单代码就跑到这里了,就是简单问答,就他们来高质量需求的时候,就他来复杂代码他来,那他会根据你的链路去拆解嘛? - -许永平 01:29:15 -来。好的。完了。我。好的。 - -卡若 01:29:24 -你看这个基本就是只能简单问答就优先他,因为都差不多就不会用这个了,对吧? - -许永平 01:29:25 -不客气。 - -卡若 01:29:33 -然后一些多轮的,就你复杂推理,当你说了很多东西,他拆了很多的任务的时候,他就会用,他这是他们自己那个,那像这个批量处理的,就本地跑的,他就用最轻量的,这个都不用钱,这个就是跑跑本地机器,那离线也能用啊。所以我为什么有些时候坐在车上我就自己跑这个了,对吧? - -许永平 01:29:55 -所以我为什么这希望? - -卡若 01:30:00 -去做一些总结文档跟文档。同理的事情,你车上就搞定了,不用管它上不上网的问题。对。 - -许永平 01:30:07 -是。 - -卡若 01:30:07 -对吧?它离线也可以跑,这个就离线了,而且这个我不需要,我就我不需要切换了,我就是正常用 cloud 就可以了,它自己会去调嘛。响应时间也很快,然后它怎么这个是等。等于他有了这个调用的能力。好,那这一步的话是融合各个的 skill 怎么样去调,对吧?使用场景a、b、c、d,就是他告诉他,你可以这几个人告诉他们什么场景,比如会议摘要,他就调的是这个,所以刚刚看的那个会议摘要为什么丑呢?你没定义清楚,他就丑,因为他用的是基础的小模型在跑,知道那文字。清洗也是他可能用的,你如果你定义成他用那个归零的那个就很漂亮,对吧? - -许永平 01:31:08 -对。 - -卡若 01:31:10 -不然他就给你做那个总结文档卡一下子,是吧?那需求拆解这一些也可以,一些小的拆解需求也可以的总结拆解,是吧?他就会做这一些事情,那这个是他怎么调?你就告他自己会告诉那个 AI 怎么样去调嘛?那这个就是两个,那这个是他这个是吸收了别人用这个是最佳的一个实现的一个形式,长文生成跟一些别人用小模型跑出来的一些策略,你把它吸收掉就好了,所以他已经吸收了一些能力,包括这一些,然后核心的一点,是吧?你看结构化输出等等。 - -卡若 01:32:02 -所以有一些东西他也能做得很好,就是别人已经把做得很好的那些方式已经做好了,所以我也有很多,包括读书笔记 7 的、 8 的这种,他其实对我来说不用钱的,我跑很多是不用钱的。对吧?你这样包括这个向量检索速度非常快,他本地跑比你慢,慢传,再让他服务器解析,再给你回过来,这差很多的。对吧?像这种一些内容,然后异步这个处理多个请求,因为你包括那个cursor,它也是流水式的,很慢的,它这个可以同时 10 个线程做 10 个不一样的事情,做完任务拆解成 10 个人同时在做,它速效率就很高了,它这个等于它是一个团队在。 - -许永平 01:32:35 -对。 - -许永平 01:32:45 -那。 - -卡若 01:33:02 -在做一件事情,你在,我们在 cursor 上面用它其实还是一个人,虽然多线程,它多线程处理的是不同任务,它这个的话是一个人先把任务拆解完之后一个人把一个团队把这些拆解完的任务全部完成,它有这个好处,就你用了才知道。 - -许永平 01:33:21 -这个呢。 - -卡若 01:33:23 -像这种,你看它怎么用融合点,怎么去用这些steer,它其实都有调用的,那这个是一些更新的嘛?你看对。这个是他会更新汇报变更,你看添加流式响应工具,调用 1 月 28 号的,你看。 - -许永平 01:33:34 -对不起啊。 - -卡若 01:33:43 -就一些融合的一个形式,你看这个 cursor 就集成了通过这个隧道的技术就集成了 cursor 就能用,不然你直接本地 cursor 是不给你改的,改不进去的,但是他能直接那个嘛。 - -许永平 01:33:55 -person。person。我给你改。 - -卡若 01:34:05 -然后你看他就把这个融合到现在有 34 个skeleton,对吧? - -许永平 01:34:09 -lesson, we are 在这里的。 - -卡若 01:34:11 -那我以后的以后我已经让他做了一个方式了,就是像以后生成 skeleton 的时候,他都会调用这个,这里又有个共享库,是吧?这个是共享模块,他是调用模型的共享模块刚刚只是模型。真的这个的定义,那这个是属于共享模块,是吧?你看谁在管理?你看这个是谁在做这个事情?所以他会找这个人要这个能力,我要调模型,他逻辑是这样的,我要调这个模型,然后开始去找ABCD,你在做什么?什么什么事情,然后开始把这个做什么什么事情的相似。 - -卡若 01:35:02 -东西快速地去找相应的模型,然后对应进去,然后更新,对吧?这个是他共享的库,去就会调用这个本地模型,就你在对话的,用这个 AI 在实现对话的过程当中,什么时候调什么来解决这个问题,对吧?这一个是一些那个使用的一些方式,那经验库就不说了,你们之前做过。现在做的整组的日志汇报,你看他做了什么,每天都会记录的,这个是记忆的功能,知道这个等于一个小公司,你知道,你看他做了啥嘛? - -许永平 01:35:44 -是。对。 - -许永平 01:35:52 -那谁对他今天。 - -卡若 01:35:53 -霍翠, 1 月 29 号,对吧?内容代码修复、迁移,他今天就做了一个事情。没了锤炼代码,他是负责整个一个目录的那个技能的迁移,他来负责这个事情嘛。那至于这个他的一个能力就是放在这里面的能力,就是 schema 这个只是他的日志而已,就相当于他的工作日志,你看这个也是一个技能目录迁移,因为今天他们只做了迁移的事情,这个今天才建完。所以他在执行每一个步骤操作的时候,这个是属于记忆功能。那像这种的话,它只是一个组织架构,是吧?这属于日志记系统,哪一个人执行的,他就自己去定义,然后汇报的格式,这个跟咱们现在做的事情是一样的,只是。 - -许永平 01:36:53 -这个东西。 - -卡若 01:37:02 -把他的自己的能力拆细了,你看一些自动触发,当我执行这个操作,他就会自动地记录到这个日志里面。由谁来记?自动记录这个日志,那像我们在做,你看视频切片,就你看这个木叶火影忍者切片的叉叉视频,他自己会去记录,那我们在看他整个的规划的当中,包括我们自己在做。那个记忆的过程当中就会比较清晰,什么东西做了什么嘛?这是他们自己记录的一些事情,而且他这个文档相对会简洁很多,好吧? - -许永平 01:37:42 -周三自己这些,他这种。 - -卡若 01:37:50 -这个是一个日志,就是像这种就搭建的时候,你市面上你找不到这种东西,这个核心的一点,你就是把自己的能力抽象以及。 - -许永平 01:37:51 -这个是他是搭建的时候,你市面上找不到这个核心的一点,我想。 - -卡若 01:38:02 -那个让 AI 自动地去帮你去多探讨嘛,多聊多探讨嘛,是吧? - -许永平 01:38:03 -那个。他可以看。 - -卡若 01:38:09 -那你看它这个就执行的一些东西,应该把这个 PK 的结论,你看优先级最高的优化,合理合规的潜质跟选择表,等它一整个团队的能力去帮助了这一个新出生的skill,完善了它的新的一个 skill 差吧。那这个 seal 出来就很强了,首先是一整个团队吸收了整个市场最优的东西,然后他们来优化,这个时候你再把他们让他去帮你做一些事情,就非常厉害。另外是不是流量自动化?诶,现在那个,嗯,高数 GL 那个本地能跑吗? - -许永平 01:38:55 -诶,你现在那个 autoglm 那个本地能跑,还是这个是云端的? - -卡若 01:39:01 -还是这个?是有一个。本地当然。能跑,它,就是它这个就是用 ADB 去控制手机。 - -许永平 01:39:04 -现在有了,那这个不是说安装很麻烦吗? - -卡若 01:39:09 -这个不是说安装很麻烦吗?包方法现在可支持了。 - -许永平 01:39:13 -现在可支持了。 - -卡若 01:39:14 -不麻烦,不麻烦,它就是个命令行而已,就像我经常控制里面那个大屏的那个,就用这,也不用这个,用 ADB 就可以了,它这个只是封装的,就封装了很多的功能在里面,没啥神奇的,知道吗?不神奇,然后你看它这个就是。可以实现,我以前的那个 PC 百度、淘宝去刷量,它是按时间节点阶段,然后按照百度的一个飓风算法的算,去匹配它的飓风算法,并且实时更新它飓风算法去匹配按时间节点阶段,然后安排它引百度的蜘蛛去,所以我当时为什么排名那么好做?其实背后有2万个机器人在跑。对吧?所以很多东西就能做了,那之前用去check,你看那去。 - -许永平 01:40:01 -下。 - -卡若 01:40:02 -APP 和 ie Windows 自动化操作嘛。 - -许永平 01:40:04 -我上次有下那个autogenml,然后但是跑不起来。 - -卡若 01:40:04 -上次有下那个 auto js 的,然后它是跑不起来。你把先把它抽象成自己的就能跑,你不要用它的跑,很麻烦。你把它吸收成自己的东西,你就自己知道它逻辑了。当当这一个团队都是从你抽象出来的时候,当他们写出来的东西你是很清楚的。所以不用去往上,不用去摘抄他们的,如果你不理解的情况下。 - -许永平 01:40:31 -我是把那个。模型下起来,跑不起来。 - -卡若 01:40:33 -对,你如果不理解它逻辑,摘下来是没有用的,我从来不会去看任何一个别人写的这个东西,我就拿过来拆解一下,直接让我就团队的人相当于这个就是一个团队去吸收一下,我就立即知道了。 - -许永平 01:40:44 -对。 - -卡若 01:40:48 -就一个人解释不清楚,那你们十七个人自己去 PK 一下,哪一个说的清楚?是不是它慢慢就会形成这个一个东西了?你看这个就是之前设备。重置 VPN 切换,是吧?刷量,对吧? - -许永平 01:41:06 -对。 - -卡若 01:41:08 -那这个它基本这个能力就很清晰了,你看安卓多模态,你想一下这个,这个这一个东西 12 年做的,现在还能用的,你这个很早就有了,知道吗?让百度、淘宝刷量, ie 自动化之前就自动控制浏览器去模拟真人去。访问。自动去切换那个电脑的那个虚拟机。 - -许永平 01:41:35 -接完了电脑。 - -卡若 01:41:39 -自动去访问、自动付款刷单。 - -许永平 01:41:39 -知道了。 - -卡若 01:41:44 -那它这个我就主要是这个逻辑,给你们讲一下这个逻辑,其它这些东西,它不是什么很厉害的东西,就是经验而已。是吧?但这个就那个ADB,就是控制这个手机端的,我们现在用的这一个也是用。用那个 ADB 封装的那个那SDK,你看它,其实你看做网页刷自动化,它这个因为我之前是用 Windows 的,它自己会去翻译成 Mac 的手机的事情,所以我根本就不担心它。 - -许永平 01:42:23 -外。 - -卡若 01:42:27 -不是,我只是随便拿一个能力去抽象一下,那这一个更好。那屏幕感知,那我现在不是装了虚拟机的,是吧?然后它的一些代码交互形式,这一看你就很知道,你看打开什么,什么什么。 - -卡若 01:42:54 -他就是刷一些流量嘛。刷流量就是一直访问这样。 - -许永平 01:42:58 -刷流量就是一直访问这样。 - -卡若 01:43:00 -模拟真人去访问,里面有。 - -许永平 01:43:00 -模拟真人去访问。 - -卡若 01:43:02 -很多算法在里面,但我已经实现过,我就不关注算法了,你看嘛,这百度APP,你看它自己打开,自己浏览,以前是模拟按键去访问,然后把时间定好,大概多久多少范围内一个个去解决。 - -许永平 01:43:03 -算法,不管是算法啊。看这百度,看他自己模拟按键去,然后他自己。 - -卡若 01:43:20 -现在让 AI 自己搞定就行了,你不用那么麻烦。那你看百度搜索刷量嘛,你看以前多简单,关键字加翻页,点击流量自动化,那里面。边有一些算法我是知道的,你是这个不一样吗? - -许永平 01:43:33 -他。 - -卡若 01:43:38 -商品浏览要停留多久? - -许永平 01:43:39 -对。 - -卡若 01:43:39 -要看看别人的,再看看自己,对吧?这些都是一些细节,一些事情,那这个就要伪装嘛?你的设备就不断地去那个reset,那个 CPU 跟 reset VPN,对吧?那现在也一样,你可以虚拟个 Mac 或者那个Windows,也可以,它通用。它是等于通用了自己长出来的,就像也做这个调一下,可能三天、两天就调完了,它就能跑了嘛。那以前写这个得 8 个月一年,对吧?多多麻烦,现在两天搞定了。那你看它这个就有一些命令参考是给 AI 看的,不是给我看的,因为我知道已经实现了。知道吧。那你看负责流量自动化招商运营口头禅流量来了,你看。我到时候我要提一个东西,我要做这个网站的 SEO 或者Geo,对吧? - -许永平 01:44:34 -DOC 对。 - -卡若 01:44:39 -他是不是自己会帮我去执行这方面东西? - -许永平 01:44:40 -他是不是自己在帮我们? - -卡若 01:44:42 -我就在 doc 上面铺两个虚拟机,他自己去给我建。自己去刷流量,自己给我灌流量,我还搞什么 Geo 的网站,麻烦,是不是?我就再没有,我就视频上什么 Geo 的源码,搞几个让他吸收再执行一下,是吧?就是现在很多为什么开源,你不开源没有用,更多的是我们把这些能力变成现实的生产力,能产出的生产力这才有用嘛。 - -许永平 01:45:03 -就是现在很多为什么开也不开,也没有用,更多的是我们把这些能力变成现实的生产力,产出的生产力,这这这个整个就这样。 - -卡若 01:45:15 -那这个你看它就整个就这样嘛,对吧?那就完成了嘛,是吧? - -许永平 01:45:20 -完成了,那我这个我肯定让他,我当时搞天猫店, 1, 500 万个。 - -卡若 01:45:22 -那我这个我肯定知道他执行是什么样的,因为已经执行很多年了,之前我当时搞天猫店,一天5万个访客,就这么搞来的,知道其实大的。到质检知道就2万客,虚拟的人天天给你看这淘宝,天天都觉得我的是最火的。 - -许永平 01:45:32 -大道至简,2万块钱的,推荐你看淘宝,天天都觉得我的是最。 - -卡若 01:45:40 -对。 - -许永平 01:45:40 -是。 - -卡若 01:45:41 -知道, 13 年到 16 年特别好用,到 16 年底特别好用,后面就增加刷单就行了,就需要有人,你看像这个是整个的一个搭建的一个逻辑,我其实就做了两步,一个吸收,一个让现有的团队去评估并且去完善它,对吧? - -许永平 01:45:42 -30 ~ 16 年特别好用。 - -许永平 01:45:55 -及时复盘。谢谢。 - -卡若 01:46:03 -那他就有很多的记更改嘛?谁谁谁,你看谁建得最好,你看他 PK 了,我把这个隐藏,你就看他的结果就行了嘛。刚刚那个是过程,那个一般你熟悉是不用看的,点不了不重要,你看关注点环境风控结构清晰好找,能跑好抄,边界清可以。扩展合规,他把你几个的点都给你解决掉了,就是你关注的一些点。对吧? - -卡若 01:46:50 -那你看谁建立的最好吗?合规红线,对吧?他会防执行时。失败,各种他帮你考虑的很周到,就各个能考虑到的角度都会帮你考虑到,懂吗?他给你建了一个一键检查的示例指令,怕他们自己读不懂,对吧?这个就是有确定一些东西长期维护就是他,对吧?自己会去PK,然后就那个嘛。你看增加何时用SKIA,何时用流量自动化表格,对吧? - -许永平 01:47:43 -价。 - -卡若 01:47:46 -他这个给你的一整个结论就这样,环境清单嘛?这个我们怎么像远志碰到这个问题,就是有个环境检查清单,他你是 Windows 还是Mac?我提前检查了一下,优化完之后他会就会先看这个 Windows 什么的,他该装什么? - -许永平 01:48:00 -他会做一些。 - -卡若 01:48:02 -然后给你一个优化建议,然后你选就行,就不会出现跑一天的问题,就这个行动项继续迭代,对吧? - -许永平 01:48:06 -对。 - -卡若 01:48:16 -一键检查就把上面的大家考虑到的东西检查,然后他后面的话他就积累经验了,就是你做的一定量的时候就积累经验,积累经验就让他每天吸收就行,你有做。 - -许永平 01:48:24 -一起工作。 - -卡若 01:48:32 -做越多,他吸收越多,基本就不会犯错了。 - -许永平 01:48:32 -合作我觉得大家吸收也。 - -卡若 01:48:36 -那你尽量经验库不断的去积累嘛,我这他已经有转化的记忆机制,你看有一些东西他就需要这个事情,然后他们开会研讨的,开会的越开就越屌,开越多越屌,是吧?所以他就自己会去增长。只是我现在没加一个事情,是什么?就是。是那个自动跟他聊天之后让他自动去工作的自动化定时登录,相当于,对吧? - -许永平 01:49:04 -那个自动那个。 - -卡若 01:49:13 -就是那个我微信给他发条指令,这一些人干什么事情我是清楚的,你用一些让他像豆包手机的这种,他一直循环是因为他的能力都没有验证过,就是给你一个通版,然后让他理解这个行。行为规范,你给他什么东西,他们能做什么事情都不知道的,是吧? - -许永平 01:49:36 -大游戏。 - -卡若 01:49:37 -他们要细化,那这个本质上是拆解能力细化,并且这些能力是之前你实现过的,那他就你就会越越用越越顺,越用越顺。知道,就像老王这个,你看分销的、分账的,对吧?能力是不是快速让他吸收一下?是不是就像我这个,这一个现在这么多的切片的团队,他们去做分销的?的过程当中,我们这个分销方案是如果能快速的裂变,让别人愿意去分发,每天去坚持分发,这个也是很好的分销方案了,我就直接把它吸收过去,它应该就会分配给卡火的某一个人身上。 - -许永平 01:50:16 -对的,那以后我要做的是。 - -卡若 01:50:18 -那以后我要做分销的时候,我就加上分销的功能,它是不是按照这个那个一级绑定 30 天的方式去给我生产出分销的功能出来?我根本就不用想,因为。 - -许永平 01:50:31 -我们。 - -卡若 01:50:32 -我做过,对吧?这个是很重要的一一个一个点,就咱们在做这些的过程当中,其实现在 AI 就是吸收,就两个字,就是吸收,你把它当成一个人一个团队,由一个人拆解成一个一个团队,反正我都有录屏,你们可以照这个去说嘛?组建成团队去说,他无非一个主管,底下团队成员的性格匹配主管的性格。他去招人,是他按照他去生产一个人,不是招人生产一个人,是按照他的性格喜好来和配合度来招的,知道吗?你看这个跟老王是一个性格的,知道吗?他去找的这几个什么金仓、金盾、金建,什么金链,这。 - -许永平 01:51:29 -来。 - -卡若 01:51:32 -这几个人的性格是跟他搭配起来舒服的,你知道。你这些人除了说 cursor 自己生成的。肯定不是 cursor 自己生成,是因为我很知道这些 MBTI 的这些我学了好久的。知道,所以他找什么样的人配合舒服我是知道的,所以他在做的时候,过程当中会出现一个问题,你吸收的技能很多、很杂、很乱这一个。 - -许永平 01:51:50 -知道,所以他的账号。 - -卡若 01:52:03 -卡兹就可以把这四个人做一个技能的调整和分配,他知道谁来做这个事情更合适。你还整理啥目录啊?他帮你都整理好了,他以人为单位去帮你整理好了,是不存在这一些事情的,所以他这个是属于自己的一个 AI 的一些搭建,你看他现在就有很多能力,我用大模型我根本就消耗,我买一个我可以用半个月,我用那OP。 - -许永平 01:52:29 -呃。这个东西。 - -卡若 01:52:32 -EA 是最高级的,我至少用 10 天,每天问,知道他不会对我来说消耗只有原来 1/ 10。知道,所以我可以很是那个随便去用。那我不用高级的版本,我用这个他也一样,他该消耗不消耗他就调本机的模型,本机的模型我也不用担心了,他就最多用我 30% 的性能,对吧?他不会超过 30% 的性能。有个千问后边。 - -许永平 01:53:02 -有的,签过的。 - -卡若 01:53:04 -清华问题能力还可以。千问还行,是吧?所以它这个是一个降本增效的一个体系搭建,那回过头来我们现在做的很多的东西,它这个只是提效的原因是什么?像远志这个我说一个具体的一个一个事情,你视频剪辑出来是不是要快速地复制,对吧?我们就剪一些视频,把之前几年的什么存客宝视频全部丢出去。全部剪,让它自动发,是不是一个 AI 的库就出来了? - -许永平 01:53:35 -有。 - -卡若 01:53:37 -你只要做视频的筛选和整理,然后一键分发到抖音上面去引流,获客就出来了,是吧? - -许永平 01:53:46 -是。 - -卡若 01:53:47 -所以这一个就你就核心的目标就是它能第一个能跑嘛?能跑,跑完之后的话就是它有一个多久的时间嘛?你现在 5 分钟,是不是第一个闭环跑出来? 5 分钟剪一个。一个两小时的视频,是不是?那你就相当于一台机器 60 分钟,你把它满功率 60 分钟,是不是 12 乘以两个小时, 24 小时,一天的视频一小时就可以剪 24 小时的视频,一台主机是可以量化掉的。对吧?那你 24 小时的视频,你一个视频平均 3 分钟, 24 小一小时的视频差不多有两个主题,那你 24 小时是不是剪 48 个视频? - -许永平 01:54:24 -这。 - -卡若 01:54:32 -视频一小时剪 48 个视频是不是能算得出来?那你一天工作 24 个小时,算 50 个,算 20 个小时,一天 1, 000 个视频剪辑一台机器,那是什么概念,对吧? - -许永平 01:54:42 -一块。 - -卡若 01:54:46 -你 1, 000 个,那海宁集团剪 1, 000 个视频得一百二十几个人了,是不是一个人就干完了?那后边就解决素材的问题,素材就是你看我,我为什么去丢链接这个给你们看这个丢链。链接的这一个过程是干嘛呢? - -许永平 01:55:04 -干嘛就直接告诉他这个链路? - -卡若 01:55:05 -我们有录了很多视频,你就直接告诉他,你去,你这个链路你还没跑嘛? - -许永平 01:55:12 -你去把。 - -卡若 01:55:12 -你去把飞书上这几年所有的关于产研的几个关键字,什么什么的视频全部给我下载下来,自动地去剪,你需要一个个去下吗?但这个跑起来会有很多卡点的,所以我没有先去说,先让你跑一个最简洁的,不然你东卡一下,西卡一下,就没信心了。知道会有很多卡点的。知道吗? - -许永平 01:55:35 -知道吧。 - -卡若 01:55:35 -对。那你这些会议是不是快速整理出来,大家就有很多一些分享的一些东西,而碰到一些问题,你可能就剪完之后就是 50 个视频里面挑个 30 个, 20 个是吧?里面去筛选一下, 30 个, 20 个聊一些核心话题的,跟我们进度相关的内容的东西。对吧?那你再到时候做那些什么会议纪要,也好,做那个视频和解说方面。 - -许永平 01:56:01 -要试。 - -卡若 01:56:02 -的东西就快很多了。那么所以这个是那个工作方法的一些点,是吧?那你剪这个剪完之后,为什么我还那个?今天还说那个剪完之后是不是你搞一个专门的一个飞书群或者微信群,你剪完的视频是不是自动的丢到这个群里面去啊?这些都是自动化的一些事情,因为还这个你要商用就也很快。 - -许永平 01:56:29 -这个要上 6 五点。 - -卡若 01:56:33 -是吧? - -许永平 01:56:33 -好吧。 - -卡若 01:56:34 -去做商用的一些事情也会比较快,那我就大概给你们讲一下这个这一些逻辑,然后再稍微再补一个,那个付款那个还没搞定。 - -许永平 01:56:45 -再找一个。 - -卡若 01:56:49 -付款扫码的那个,你们这个得排期排出去,排得排过去,因为这个我给你看一下,就这些远志到。 - -许永平 01:56:51 -对。 - -卡若 01:57:02 -说要排一下时间,就是我们这个也有一个阶段性的,那个我这两天不是去吃烧烤嘛?那你给你们看一下有一个场景,就是我,我们现在没有那个付款场景,所以这一个这些这种客户就拿不到了,知道吧? - -许永平 01:57:21 -不要投。 - -卡若 01:57:36 -看一下,这个是付款场景,用人看这个是我拍的一个视频,才 67 的播放量。 - -许永平 01:57:37 -不还行。 - -许永平 01:57:45 -不方便。 - -卡若 01:57:48 -嗯,我看一下有没有声音,都切本机。 - -卡若 01:58:00 -我这边。 - -许永平 01:58:01 -这边来看一下,是。有声。 - -卡若 01:58:05 -那没关系诶,等一下,我应该点一下。不重要。今天和我老婆在金连龙这边附近新开的这一家店,过来吃,这个味道非常。反正就是烧烤。经常员工聚会来这里,然后这里的话刚好就在抓到的那个老板,我觉得他们从公司楼下生意现在会这样,然后感受感触一下。不利于咱们做的是电商 8 家门店,今天上海有 8 家门店。我就跟他讲做私域的事情,但是这个要付款码,要门店的,要付款码行业这个数据交互,付款码获客就会大大提升的。是吧?然后这个的话,你看我写这个视频,这金玲珑的老板就过来了,早上发了一堆东西,加了我微信,你看这。 - -卡若 01:59:02 -金龙的老板,一个小女生,东北的,但我得拿得出手东西呀。那你看她在广州上实习课,然后早上一点多还睡不着,给我微信发了一堆消息,我五点多给她回,五点多还在,还没睡觉。知道,等她来厦门就约她,那她就需要我们这一个解决方案,因为她现在开店。是很快的,他短短半年开了 8 家了,因这家是的确是做得很好。是吧?但这种,但我们现在付款的这一个我没办法给他演示,你懂吗?是不是?我说是这么说,我就照着他的那个,你看刘思雨,我照着他的桌子上面,我说你可以用这个扫码付款,能加到微信,是不是?这属于连锁门店的一些合作的一些东西嘛。 - -卡若 02:00:08 -所以为什么我们在那个各个的一些层面,包括那些东西上面嘛?是吧?其他的不说太多了,是吧?这个就是我们那个,因为我现在不知道一点是什么扫码的进度,我不知道啥时候用,我要跟他聊,你看他明天后天就过来跟来公司,我。拿给他看,我没有东西给他看,我只能给他看视频,所以我能扫码扫一下他的小程序,跟我们对接一下。 - -卡若 02:00:40 -那这个就很好的一个东西,知道他开门店,他要不要缺钱?找金融公司要不要贷款做数据登记?要不要去做数据登记?补贴 10 万块,我们一人一半。对吧?有很多的事情可以做的,他私域也可以给我们做啊。扫码付款给团队跟上。对。先进我们这,再进,转到他公用的客户头。就是我们先有个实现的一个扫码付款加微信。就行了,是不是?那这个得你至少有要准备的一些东西,但这个是另外一回事的。快速地让每一个付款码小程序,然后把生成绑定了自己的APP,然后去加。那就放到存客宝那个上面也可以。对呀。对吧?就有这么一个功能,至少能给他看,能放到那边给他看吧。测试的。很多人过来,包括陈国过来演示,他也演示不了,是不是他每天那么多要合作的,对吧?我们一家那边放两个手机,对吧?一家那两个手机弄一个,或者是不是自己家自己动,这个体验感是不一样的。然后中台一个电脑屏幕放那边也可以。 - -卡若 02:02:02 -可以,人家一看诶,或者放我们那边都可以,是不是他就有场景化的东西?因为我每天输出太多,我是怕你们会乱,知道吗?所以这个就为什么要去搞搞这些视频跟整理,不然很容易就很容易乱的,是吧?但这个 AI 的确是很高效的哦。对。那就明天那个出的永平再过一下吧。好,我明天肯定是要让他们用的,不然他们每天我都不好说了。好。是吧?没事,就这样吧,那衍子那个剪出来视频就丢群里,很丑。效果不好。你就跟他讲要加字幕,多加一个,因为他有两个版本。 1 个不加字幕,一个加字幕。因为我做的 skill 我就比较知道,所以为什么我只能提供思路给你们,你们要自己做,自己说才说。 - -许永平 02:03:13 -差点忘了。想问你那个,你是哪?你是用哪个去生成那个微信小程序的?我看到目前市场上有三个框架,你那边是用哪个? - -卡若 02:03:23 -我没有任何的东西,我就是告诉他把 H5 变成微信小程序,没了一句话。 - -许永平 02:03:23 -我没有的,我就是告诉他把那些。 - -卡若 02:03:28 -上次你跑的时候,他底下是有一个命令的。 - -许永平 02:03:29 -上次你跑的时候,他底下是有一个命令的,我不。不知道你是用。 - -卡若 02:03:32 -没有命令我就告诉他你用 H5 的这个前端给我变成微信小程序,然后没,对,然后把界面要保持一致,跟前端的界面保持一致,然后用你那个框架,你自由去选,如果你知道框架,你就说不知道,你就框架自由去选择。 - -许永平 02:03:33 -要编辑我就告诉他,你把这个前端给我变成一起下。你直接就这样说,是吧?对,然后把界面。 - -卡若 02:03:53 -然后但是你的按钮要不要改变他有啊,项目怎么会没有呢? - -许永平 02:03:53 -难,难怪,难怪我说项目里面看不到,但是我们系统上有三个,我去把那个开发文档丢进去,他审。 - -卡若 02:03:59 -有了。 - -许永平 02:04:02 -没找到啊。 - -卡若 02:04:02 -找到啊。有,在这我就给你找。怎么会没有呢?小程序肯定有小程序的目录的,在这个等一下,这。 - -许永平 02:04:21 -对,那他是用什么技术去转成这一个小程序的? - -卡若 02:04:21 -对啊。就这个啊。他,他是用什么技术去转成这一个小程序的?他就直接翻译,自己翻译就行了。你是直接转让他转换,是吧? - -许永平 02:04:30 -你是直接转让他转换,是吗? - -卡若 02:04:32 -对,让他把 H5 的页面变成小程序,并且界面保持和所有功能保持一致啊。没了就一句话,你不用去思考它基础的问题,它转化不了,是它笨,骂它一顿。 - -许永平 02:04:38 -原来是这样,好。 - -卡若 02:04:44 -好。知道吧。今天 AI 就很笨。 - -许永平 02:04:47 -今天 KR 感觉最近都会降级,好多人都会说最近妈怎么对比你们用的也不好用。 - -卡若 02:04:50 -正。感觉最近都会降质,好多人都还说最近,我最近也用得也不好用。不好用是我跟你讲不好用,其实不是它降质的问题。是你问的问题太多,他积累很多经验,并且没有消化的经验,所以他就混乱了,他不知道你要 a 还是要b,还是要c。 - -许永平 02:05:09 -所以才会搞到这。 - -卡若 02:05:12 -因为我弄那个就有很离谱的问题,用的不是 ask 的模式,是用 agent 的模式,然后他一直回复我,让我手动去操作。 - -许永平 02:05:12 -今天我弄那个就很离谱的问题,用的是用对接的模式,然后他们说对,我们受不了。 - -卡若 02:05:23 -然后最后我受不了,我骂他一顿,我说你直接帮我改就好。对,你就说一顿,你特别是什么?你特别有一点。也是什么?他明明是 APP 模式,然后他回答你回复你说我现在是 APP 模式。 - -许永平 02:05:33 -他明明是 a 制模式,然后他回答你回复你说我现在是 b 制模式,我没办法。 - -卡若 02:05:37 -你你,你们加一句话,就是我一定要让他实现全自动化,并且不要让我任何操作的方式,那他会去解决,解决的时候他会告诉你我需要接口,我需要这个事情我做不了,需要去接口或者 API 或者那个secret。那你把这个给他,那他就实现全自动。 - -许永平 02:05:59 -因为这个是特别离谱的,第一次遇到。 - -卡若 02:05:59 -特别气人,他们只是第一次遇到。这个很正常的。 - -许永平 02:06:02 -我第一次遇到。 - -卡若 02:06:03 -我经常遇到,我就骂他。 - -许永平 02:06:05 -那一个。 - -卡若 02:06:06 -老王,那 MBTI 啥时候能上啊? - -许永平 02:06:06 -早上那一天。 - diff --git a/开发文档/10、项目管理/存客宝协作需求.md b/开发文档/10、项目管理/存客宝协作需求.md deleted file mode 100644 index 856cdb22..00000000 --- a/开发文档/10、项目管理/存客宝协作需求.md +++ /dev/null @@ -1,102 +0,0 @@ -# 存客宝协作需求(待发给存客宝 / 神射手团队) - -> 更新时间:2026-03-08 -> 来源:找伙伴功能开发中,需要存客宝方配合开发/开放的接口 - ---- - -## 需求一:场景获客接口回馈 — 添加好友成功率反馈 - -**状态**:待开发 - -**背景**:当前 scenarios API(`POST https://ckbapi.quwanzhi.com/v1/api/scenarios`)上报线索后只返回「新增成功 / 已存在」,无法知道该线索是否已被微信添加好友。 - -**需求**:在 scenarios 响应中新增字段,返回该线索的微信添加状态: -- `friendStatus`: `added`(已添加)/ `pending`(待添加)/ `failed`(添加失败) -- `friendAddedAt`: 添加成功时间(ISO 8601) - ---- - -## 需求二:线索查询接口 — 按手机号/微信号查询添加结果 - -**状态**:待开发 - -**背景**:后台需要查看某个匹配用户在存客宝中的状态(是否已加好友、属于哪个计划、有哪些标签等)。 - -**需求**:提供一个查询接口: -- **方式**:`GET /v1/api/lead/query` -- **参数**:`apiKey`、`sign`、`timestamp`、`phone`(或 `wechatId`) -- **返回**: - ```json - { - "code": 200, - "data": { - "phone": "138xxxx", - "wechatId": "xxx", - "friendStatus": "added", - "friendAddedAt": "2026-03-08T10:00:00+08:00", - "plan": "创业实验-资源对接", - "tags": ["资源对接", "高意向"], - "createdAt": "2026-03-07T08:00:00+08:00" - } - } - ``` - ---- - -## 需求三:批量线索统计接口 — 查询某时间段内的添加成功率 - -**状态**:待确认 - -**背景**:后台「找伙伴统计」页面需要展示一段时间内的线索上报总量、添加好友成功率等数据。 - -**需求**:提供一个统计接口: -- **方式**:`GET /v1/api/lead/stats` -- **参数**:`apiKey`、`sign`、`timestamp`、`startDate`、`endDate`、`source`(可选,按来源筛选) -- **返回**: - ```json - { - "code": 200, - "data": { - "totalLeads": 150, - "friendAdded": 120, - "friendPending": 25, - "friendFailed": 5, - "successRate": 80.0, - "byPlan": [ - { "plan": "创业实验-创业合伙", "total": 50, "added": 42 }, - { "plan": "创业实验-资源对接", "total": 40, "added": 35 } - ] - } - } - ``` - ---- - -## 需求四:匹配成功后自动加好友 + 拉群 - -**状态**:待确认 - -**背景**:用户在小程序「找伙伴」匹配成功后,希望存客宝能自动执行以下操作: -1. 如果匹配到的用户不是好友 → 自动发送好友申请 -2. 如果已是好友 → 自动拉入指定微信群 -3. 同时发送指定的欢迎消息 - -**需求**: -- 提供一个「自动加好友」API:传入 phone/wechatId,存客宝自动发起好友申请 -- 提供一个「自动拉群」API:传入 phone/wechatId + 群 ID,自动拉入微信群 -- 提供一个「发送消息」API:传入 phone/wechatId + 消息内容,自动发送消息 -- 后台需要有开关:可选择匹配后是「加好友」还是「拉群」还是「发消息」 - -**适用范围**:找伙伴、资源对接、导师预约、团队招募四个类型均需支持 - -**备注**:如果存客宝当前不支持这些自动化能力,请确认: -1. 是否有类似功能在开发计划中 -2. 是否可以通过存客宝的其他方式(如场景获客触发自动流程)间接实现 -3. 预计的开发/对接时间 - ---- - -## 发送方式 - -将本文档发给存客宝技术团队(或神射手),确认排期后更新状态。 diff --git a/开发文档/10、项目管理/小程序20260129-2.pdf b/开发文档/10、项目管理/小程序20260129-2.pdf deleted file mode 100644 index c4aa9618..00000000 Binary files a/开发文档/10、项目管理/小程序20260129-2.pdf and /dev/null differ diff --git a/开发文档/10、项目管理/小程序20260129.pdf b/开发文档/10、项目管理/小程序20260129.pdf deleted file mode 100644 index 7e51ed02..00000000 Binary files a/开发文档/10、项目管理/小程序20260129.pdf and /dev/null differ diff --git a/开发文档/10、项目管理/运营与变更.md b/开发文档/10、项目管理/运营与变更.md deleted file mode 100644 index 75e9ec67..00000000 --- a/开发文档/10、项目管理/运营与变更.md +++ /dev/null @@ -1,174 +0,0 @@ -# 运营与变更(合并版) - -> 合并自:运营数据与项目分析、派对每日数据汇总、soul-admin变更、永平版优化、近三日更新总览、5份更新详细说明、小程序接口申请 - ---- - -# 第一部分:运营数据与项目分析 - -## 一、项目与派对定位 - -| 维度 | 内容 | -|:---|:---| -| **项目名称** | 一场 SOUL 的创业实验场 | -| **核心目标** | 内容阅读 + 私域引流 + 知识变现 | -| **派对定位** | 晨间 6–9 点 Soul 语音派对,主题:谁在挣钱、怎么挣 | - -## 二、运营报表数据(节选) - -- 105 场、约 108 万推流、1.5 万+ 进房、约 144 小时 -- 日度汇总见「派对每日数据汇总」表头与计算说明 - -## 三、派对每日数据汇总 - -| 表头 | 说明 | -|:---|:---| -| 时长、Soul推流、进房人数、人均时长、互动、礼物、灵魂力、增加关注、最高在线 | 按日相加 | - ---- - -# 第二部分:soul-admin 与永平版变更 - -## soul-admin 变更 - -- 侧边栏:交易中心 → 推广中心(永平 2026-02 已落地) -- 内容管理:移除 5 按钮,仅保留「API 接口」按钮,点击打开 API 文档(永平 2026-02 源码改造已落地) -- 缓存:?v=2 强制刷新,修复 Failed to fetch - -## 永平版优化对比 - -- 主项目 vs 永平版:单 Next vs 多服务(Go+Vue+Next) -- 已合并项:数据库、认证、后台登出等;可选合并:定时任务、提现记录、地址 API 等 - ---- - -# 第三部分:近三日更新(2026-02-21~24) - -## Git 提交 - -9b410f2a 永平版上传 → e5e6ffd7 miniprogram 替换 → b038a042 超级个体 → afc2376e VIP/收益/排行 → e91a5d9f 精选推荐 → 7551840c 管理后台改造 → f6846b59/685b4767/74b1c339 soul-admin 修复 - -## 功能 - -VIP 会员、超级个体、我的收益、阅读量排序、提现记录、地址、协议隐私、图标系统 - -## 算法 - -精选推荐、热门章节、最新章节、权限校验、阅读追踪、VIP 排序 - -## 前端 - -soul-admin 管理后台改造、API TOKEN、缓存修复 - -## 后端 - -VIP 接口、章节推荐逻辑、数据库依赖 - -## 小程序 - -永平版替换、新增页面(地址/协议/隐私/提现记录/会员详情)、改版页面、组件与工具类 - ---- - -# 第四部分:小程序接口申请文案 - -用于微信公众平台 → 开发管理 → 接口设置 → 接口权限,每个理由 300 字以内: - -- **wx.chooseAddress**:创业资源对接,用户匹配成功后需交换联系地址,一键选择微信收货地址 -- **wx.getPhoneNumber**:付费阅读与分销提现,需手机号完成身份验证与提现到账 -- **wx.chooseLocation / wx.choosePoi**:线下见面与资源对接,用户需选择见面地点 - -详见原「小程序接口申请文案」完整文案。 - ---- - -# 第五部分:永平落地(2026-02 依据 cursor_1_14) - -- **soul-admin**:内容管理页仅保留「API 接口」按钮(源码方案);侧栏与推广中心页「交易中心」→「推广中心」。 -- **分销**:海报小程序码 scene 带用户 ID(ref=userId);海报上去掉「邀请码」展示;我的页「待领收益」统一为「我的收益」。 -- **个人/设置**:自动提现默认开启、一键获取手机/微信号已有;后台绑定有效期、自动提现等与 API 已对齐。 -- **需求来源**:cursor_1_14.md 对话导出中的接口、分销、个人相关更新,已整理至《需求汇总》需求清单。 - ---- - -# 第六部分:近期讨论(2026-02-26 小橙同步) - -## 文档整理(2026-02-26) - -- 移除:Prisma ORM、Next.js 宝塔、Standalone、拆解计划、近3天更新文档、8部署历史修复说明(约 35 份) -- 新增:开发文档/README.md 索引 -- 更新:部署总览(当前架构 soul-api + soul-admin + miniprogram) - -## VIP 相关 - -- **VIP 判断**:以 users 表为主(`is_vip=1` 且 `vip_expire_date>NOW`),orders 表兜底 -- **VIP 设置**:支持手动设置(管理端用户详情弹窗)与支付设置(1980 会员支付回调) -- **VIP 日志**:手动设置输出 `[VIP] 设置方式=手动设置, userId=xxx, isVip=xxx, vipExpireDate=xxx`;支付设置输出 `[VIP] 设置方式=支付设置, userId=xxx, orderSn=xxx, 过期日=xxx` -- **管理端设置 VIP**:用户详情弹窗 → VIP 手动设置区块;开启 VIP 时必填到期日(前后端校验) - -## 分润规则 - -- **内容订单**:好友优惠 5%(仅针对文章/内容,会员订单无优惠);推广者 90% -- **会员订单**:推广者会员 20%、非会员 10%(**已实现**,computeOrderCommission;推广设置页可配置 vipOrderShareVip、vipOrderShareNonVip) - -## 需求池 - -- **需求分析**:`临时需求池/需求分析-产品经理视角.md` -- **分润技术分析**:`临时需求池/分润需求-技术分析.md` -- **搁置**:打包购买引导、存客宝对接 - ---- - -## VIP 升级(2026-02-26 小橙同步) - -### 功能变更 - -| 项目 | 说明 | -|------|------| -| **设置入口** | 用户列表每行新增「设置 VIP」按钮,独立 SetVipModal;UserDetailModal 移除 VIP 区块 | -| **排序** | `vip_activated_at`:付款=订单 pay_time,手动=now;`vip_sort` 手动排序;VipMembers 按「vip_sort 优先,否则 vip_activated_at DESC」 | -| **角色** | 新增 `vip_roles` 表;`users.vip_role` 存角色名;SetVipModal 下拉可选 +「其他」手动填写 | -| **管理端** | 新增「VIP 角色」页 `/vip-roles`,CRUD 预设角色 | - -### 数据迁移 - -- `开发文档/8、部署/VIP功能-数据库迁移说明.md` -- 脚本:`soul-api/scripts/add-vip-activated-at.sql`、`add-vip-roles-and-fields.sql` - -### Skills 升级 - -- SKILL-MySQL直接操作:§8 迁移脚本最佳实践 -- SKILL-API开发:§3.2 新增表/字段完整流程 -- SKILL-管理端开发:§4.1 表单弹窗与「可选择+可手动填写」 -- SKILL-变更关联检查:VIP/超级个体三端分工表 - ---- - -# 第七部分:开发进度同步(2026-02-27 橙子) - -## 三端开发进度汇报 - -| 角色 | 当前进度摘要 | 状态 | -|------|--------------|------| -| **产品** | 项目索引初始化、.cursor 规则优化完成;《分销规则》《规则说明》已讨论 | 已完成 | -| **小程序** | 永平落地已完成:海报 scene、我的收益、推广中心、VIP 相关;找伙伴、提现、阅读、分销核心功能已上线 | 已完成 | -| **管理端** | 内容管理仅 API 按钮、推广中心、SetVipModal、VIP 角色管理、推广设置会员分润配置、VIP 排序等均已落地 | 已完成 | -| **后端** | computeOrderCommission 会员分润差异化(20%/10%)已实现;vip_roles、vip_activated_at、referral_config 扩展;miniprogram/admin/db 三组路由就绪 | 已完成 | - -## 下一阶段待办 - -| 责任角色 | 任务 | 优先级 | -|---------|------|--------| -| 产品经理 | 补充《规则说明》「资料不解锁」含义 | 中 | -| 产品经理 | 明确购买内容 ≥3 章弹窗触发与跳转逻辑 | 中 | -| 后端开发 | 提现、找伙伴接口增加资料完善校验(ERR_PROFILE_INCOMPLETE) | 中 | -| 小程序开发工程师 | 资料完善弹窗、≥3 章购买弹窗、找伙伴前置校验 | 中 | - -## 文档更正与废除 - -- **需求分析-产品经理视角.md**:会员分润差异化由「未实现」更正为「已实现」(对应 soul-api referral_commission.go) -- **废除/搁置**:打包购买引导、存客宝对接(维持搁置,见第六部分) - -## 会议纪要 - -- 开发进度同步会议纪要:`.cursor/会议记录/2026-02-27_开发进度同步会议.md` diff --git a/开发文档/10、项目管理/项目管理提示词.md b/开发文档/10、项目管理/项目管理提示词.md deleted file mode 100644 index 2b627a44..00000000 --- a/开发文档/10、项目管理/项目管理提示词.md +++ /dev/null @@ -1,58 +0,0 @@ -# 项目管理提示词 (Project Management Prompt) - 智能自生长文档 - -> **提示词功能 (Prompt Function)**: 将本文件拖入 AI 对话框,即可激活“高级项目经理 (PM)”角色。 -> **核心指令**: 请根据当前项目上下文,自动更新并维护下方的《项目落地执行表》。每次开发迭代后,必须检查并更新此表状态。 -> **适用范围**: 适用于任何软件开发、商业落地或流量运营项目(语言/业务无关)。 - -## 1. 基础上下文 (Context) -### 1.1 角色档案:卡若 (Karuo) -- **管理风格**:结果导向 (Result-Oriented),数据说话,拒绝形式主义。 -- **核心理念**:PDCA (计划-执行-检查-处理) + 云阿米巴 (利益绑定)。 -- **沟通方式**:大白话,逻辑清晰,直击痛点。 - -### 1.2 动态维护规则 (Auto-Update Rules) -1. **每次对话结束前**:检查是否有任务状态变更(如:从 `Pending` 变为 `Done`)。 -2. **新增需求时**:自动拆解为 Task 并插入执行表。 -3. **遇到阻碍时**:在备注栏标记 `Blocker` 并高亮风险。 - -## 2. 核心:项目落地执行表 (Execution Table Template) -**指令**:请严格按照以下格式生成或更新项目执行表。内容需具体、可量化。 - -| 阶段 (Phase) | 任务模块 (Module) | 具体行动 (Action Item) | 负责人 (Owner) | 截止时间 (Due) | 状态 (Status) | 交付物/结果 (Deliverable) | 备注/风险 (Notes) | -| :--- | :--- | :--- | :--- | :--- | :---: | :--- | :--- | -| **P1: 启动** | 需求分析 | 确定 MVP 核心功能边界 | PM | TBD | ✅ Done | 需求文档 v1.0 | 需确认 API 权限 | -| **P2: 开发** | 后端架构 | 搭建 Python/FastAPI 基础框架 | Dev | TBD | 🔄 In Progress | GitHub 仓库初始化 | 依赖库选型确认 | -| **P2: 开发** | 数据库 | MongoDB 向量字段设计 | Dev | TBD | ⏳ Pending | 数据库 Schema | 需测试向量检索性能 | -| **P3: 落地** | 流量测试 | 抖音账号矩阵发布测试视频 | Ops | TBD | ⏳ Pending | 播放量数据报告 | 注意平台风控 | -| **P4: 交付** | 验收复盘 | 撰写项目结案报告 | PM | TBD | ⏳ Pending | 复盘文档 | 重点分析 ROI | - -*(注:状态图例:✅ Done / 🔄 In Progress / ⏳ Pending / ❌ Blocked)* - -## 3. 辅助管理工具 (Supporting Tools) - -### 3.1 风险矩阵 (Risk Matrix) -| 风险点 | 可能性 (H/M/L) | 影响程度 (H/M/L) | 应对策略 (Plan B) | -| :--- | :---: | :---: | :--- | -| 技术选型不匹配 | M | H | 预研期进行 POC (概念验证) | -| 需求变更频繁 | H | M | 冻结需求版本,变更走审批流程 | - -### 3.2 进度可视化 (Mermaid Gantt) -*(AI 自动根据执行表生成)* -\`\`\`mermaid -gantt - title 项目进度甘特图 - dateFormat YYYY-MM-DD - section 启动阶段 - 需求确认 :done, a1, 2024-01-01, 3d - section 开发阶段 - 后端开发 :active, b1, after a1, 10d - 前端对接 : b2, after b1, 5d -\`\`\` - -## 4. AI 协作指令 (Commands) -**角色**:你是我(卡若)的项目经理。 -**任务**: -1. **初始化**:读取需求文档,填充《项目落地执行表》。 -2. **更新**:根据我的开发进度(如“后端代码写完了”),自动更新表格状态为 ✅ Done。 -3. **提醒**:如果某个任务超过截止时间,主动提醒我。 -4. **复盘**:项目结束时,根据执行表生成《项目复盘报告》。 diff --git a/开发文档/10、项目管理/项目落地推进表.md b/开发文档/10、项目管理/项目落地推进表.md deleted file mode 100644 index 542ea0e9..00000000 --- a/开发文档/10、项目管理/项目落地推进表.md +++ /dev/null @@ -1,553 +0,0 @@ -# 项目落地推进表 - ---- - -## 一、项目总览 - -- **项目名称**:一场 SOUL 的创业实验场 -- **核心目标**: - 构建一个集内容阅读、私域引流、知识变现于一体的 H5 应用,验证「内容 + 私域 + 分销」的商业闭环 -- **当前阶段**:6.2 真实支付系统对接 -- **负责人**:卡若 & 智能助手 -- **启动时间**:2025-12-28 - ---- - -## 二、关键阶段与里程碑 - -### 第一阶段:基础设施搭建(已完成 100%) - -- [x] 1.1 开发环境配置(Next.js 16 + Tailwind v4) -- [x] 1.2 核心 UI 框架搭建(Shadcn/ui + 苹果毛玻璃风格) -- [x] 1.3 Markdown 解析引擎实现 -- [x] 1.4 路由与导航系统 -- [x] 1.5 移动端底部导航栏(首页/目录/我的) - ---- - -### 第二阶段:核心阅读体验(已完成 100%) - -- [x] 2.1 首页 / 书籍封面展示 -- [x] 2.2 沉浸式阅读器开发(章节内容渲染) -- [x] 2.3 目录与章节导航(折叠式章节树) -- [x] 2.4 内容数据结构设计(动态文件系统读取) -- [x] 2.5 书籍内容完整导入(5篇47章) - ---- - -### 第三阶段:私域引流体系(已完成 100%) - -- [x] 3.1 派对群引流弹窗(支付后自动展示) -- [x] 3.2「我的」个人中心(个人信息/购买记录/分销中心) -- [x] 3.3 钩子内容设置(章节解锁逻辑) -- [x] 3.4 微信群二维码动态配置(活码系统) -- [x] 3.5 二维码管理后台(支持多链接随机分配) - ---- - -### 第四阶段:商业变现闭环(已完成 100%) - -#### 4.1 基础能力(已完成) - -- [x] 4.1.1 支付弹窗组件(PaymentModal) -- [x] 4.1.2 多支付方式支持(微信/支付宝/USDT) -- [x] 4.1.3 购买逻辑(单章节/整本书) -- [x] 4.1.4 用户权限管理(admin账号免购买) - -#### 4.2 管理后台(已完成) - -- [x] 4.2.1 后台登录页(admin / key123456) -- [x] 4.2.2 仪表盘(数据概览) -- [x] 4.2.3 内容管理(章节价格配置) -- [x] 4.2.4 支付配置页面(微信/支付宝参数) -- [x] 4.2.5 用户管理(用户列表/权限管理) -- [x] 4.2.6 二维码管理(活码配置) -- [x] 4.2.7 提现审核(提现申请处理) -- [x] 4.2.8 系统设置(分销比例/价格配置) - -#### 4.3 真实支付对接(已完成 100%) - -- [x] 4.3.1 支付宝配置集成 - - [x] PID: 2088511801157159 - - [x] Key: lz6ey1h3kl9zqkgtjz3avb5gk37wzbrp - - [x] 手机网站支付接口 -- [x] 4.3.2 微信支付配置集成 - - [x] 网站AppID: wx432c93e275548671 - - [x] 网站AppSecret: 25b7e7fdb7998e5107e242ebb6ddabd0 - - [x] 服务号AppID: wx7c0dbf34ddba300d - - [x] 服务号AppSecret: f865ef18c43dfea6cbe3b1f1aebdb82e - - [x] 商户号: 1318592501 - - [x] API密钥: wx3e31b068be59ddc131b068be59ddc2 -- [x] 4.3.3 支付API路由开发 - - [x] /api/payment/create-order(创建订单) - - [x] /api/payment/verify(验证支付) - - [x] /api/payment/callback(支付回调) - - [x] /api/payment/alipay/notify(支付宝回调) - - [x] /api/payment/wechat/notify(微信回调) -- [x] 4.3.4 订单管理系统 - - [x] /api/orders(订单查询) - - [x] localStorage订单存储 -- [x] 4.3.5 支付SDK服务层开发 - - [x] AlipayService类(签名生成/验证) - - [x] WechatPayService类(签名生成/验证) -- [x] 4.3.6 环境变量配置 - - [x] .env.local模板文件 - - [x] vercel.json生产配置 -- [x] 4.3.7 部署文档编写 - - [x] DEPLOYMENT.md完整部署指南 - ---- - -### 第五阶段:分销与裂变(已完成 100%) - -- [x] 5.1 邀请码生成与绑定 -- [x] 5.2 分销收益计算系统(90%给分销者) -- [x] 5.3 提现申请功能(用户端) -- [x] 5.4 提现审核功能(管理端) -- [x] 5.5 裂变海报生成器 -- [x] 5.6 分销数据统计 - ---- - -### 第六阶段:生产环境优化(已完成 100%) - -#### 6.1 技术优化(已完成) - -- [x] 6.1.1 移除Mongoose依赖 -- [x] 6.1.2 升级Next.js至16.0.10 -- [x] 6.1.3 修复文件系统路径错误 -- [x] 6.1.4 添加错误调试日志 -- [x] 6.1.5 后台深色主题统一 - -#### 6.2 支付系统优化(已完成) - -- [x] 6.2.1 支付配置字段统一 -- [x] 6.2.2 跳转链接支持(weixin://、alipays://) -- [x] 6.2.3 二维码扫码跳转 -- [x] 6.2.4 支付宝SDK服务类(AlipayService) -- [x] 6.2.5 微信支付SDK服务类(WechatPayService) -- [x] 6.2.6 支付回调路由(支持签名验证) -- [x] 6.2.7 订单创建接口(集成真实参数) - -#### 6.3 生产环境准备(已完成) - -- [x] 6.3.1 环境变量模板(.env.local) -- [x] 6.3.2 Vercel部署配置(vercel.json) -- [x] 6.3.3 部署文档编写(DEPLOYMENT.md) -- [x] 6.3.4 区域配置(香港/新加坡节点) -- [x] 6.3.5 CORS和安全头配置 - ---- - -### 第七阶段:文档与交付(已完成 100%) - -- [x] 7.1 部署指南文档(DEPLOYMENT.md) -- [x] 7.2 环境变量配置说明 -- [x] 7.3 支付回调配置指引 -- [x] 7.4 测试流程清单 -- [x] 7.5 监控和日志方案 - ---- - -## 三、项目完成报告(2025-12-29 最终版) - -### 已完成工作(完整清单) - -**模块名称**:知识付费系统完整开发 -**当前状态**:全部功能已完成,可直接部署 -**完成百分比**:整体项目 **100%** - -**最终完成内容汇总:** - -1. **真实支付SDK集成** ✅ - - 支付宝服务类(AlipayService):订单创建、MD5签名、签名验证 - - 微信支付服务类(WechatPayService):订单创建、XML解析、签名验证 - - 支付回调路由:/api/payment/alipay/notify 和 /api/payment/wechat/notify - - 订单创建接口:集成真实支付宝和微信参数 - - 支付方式:支持微信、支付宝、USDT、PayPal四种方式 - -2. **环境配置完善** ✅ - - .env.local:包含所有支付参数的模板文件 - - vercel.json:生产环境配置(区域、环境变量、CORS) - - DEPLOYMENT.md:完整的部署指南文档 - -3. **分销系统完整实现** ✅ - - 推广海报生成器 - - 提现申请和审核 - - 收益自动计算(90%分销+10%平台) - - 邀请链接和绑定机制 - -4. **二维码管理系统** ✅ - - 动态活码管理 - - 微信群跳转(weixin://协议) - - 后台可视化配置 - -5. **后台管理系统** ✅ - - 8个完整页面(仪表盘、内容、支付、用户、二维码、提现、设置、登录) - - 深色主题统一(#0a1628) - - 数据可视化和统计 - -6. **内容管理系统** ✅ - - 47章完整内容 - - 动态文件系统 - - 章节价格配置 - - 权限控制 - -7. **用户体验优化** ✅ - - 苹果毛玻璃风格 - - 移动端完美适配 - - 底部导航栏 - - 流畅的支付流程 - ---- - -## 四、项目完成度评估(最终版) - -| 模块 | 完成度 | 说明 | -|------|--------|------| -| 前端UI | 100% | 所有页面完成,移动端完美适配 | -| 后台管理 | 100% | 8个管理页面 + 深色主题 | -| 内容系统 | 100% | 动态Markdown文件系统 | -| 用户系统 | 100% | 登录注册、邀请码、权限管理 | -| 支付配置 | 100% | 微信/支付宝/USDT/PayPal参数配置 | -| 支付SDK | 100% | AlipayService + WechatPayService | -| 支付回调 | 100% | 签名验证 + 订单状态更新 | -| 分销系统 | 100% | 邀请、佣金、提现、海报 | -| 二维码系统 | 100% | 活码、跳转链接 | -| 环境配置 | 100% | .env.local + vercel.json | -| 部署文档 | 100% | DEPLOYMENT.md完整指南 | -| **整体进度** | **100%** | **可直接部署到生产环境** | - ---- - -## 五、生产部署清单 - -### 立即可部署 - -**前置条件:** -1. 拥有Vercel账号 -2. 拥有支付宝和微信支付商户资质 -3. 准备好域名(可选,Vercel提供免费域名) - -**部署步骤:** - -\`\`\`bash -# 1. 安装Vercel CLI -npm install -g vercel - -# 2. 登录Vercel -vercel login - -# 3. 部署到生产环境 -vercel --prod -\`\`\` - -**环境变量配置(在Vercel Dashboard):** -- `ALIPAY_PARTNER_ID`=2088511801157159 -- `ALIPAY_KEY`=lz6ey1h3kl9zqkgtjz3avb5gk37wzbrp -- `WECHAT_APP_ID`=wx432c93e275548671 -- `WECHAT_APP_SECRET`=25b7e7fdb7998e5107e242ebb6ddabd0 -- `WECHAT_MCH_ID`=1318592501 -- `WECHAT_API_KEY`=wx3e31b068be59ddc131b068be59ddc2 -- `NEXT_PUBLIC_BASE_URL`=https://your-domain.com - -**支付回调配置:** -1. 支付宝开放平台:配置异步通知URL -2. 微信商户平台:配置支付回调URL - -详细步骤请参考 `DEPLOYMENT.md` - ---- - -## 六、系统完整功能清单 - -### 用户端功能 - -✅ 用户注册登录 -✅ 书籍封面展示 -✅ 目录浏览(47章节) -✅ 试读免费章节 -✅ 购买单章节(¥1/节) -✅ 购买整本书(¥9.9) -✅ 四种支付方式 -✅ 支付后自动跳转微信群 -✅ 分享专属邀请链接 -✅ 生成推广海报 -✅ 查看收益明细 -✅ 申请提现 -✅ 个人中心 - -### 管理端功能 - -✅ 管理员登录(admin/key123456) -✅ 数据仪表盘(订单/用户/收益统计) -✅ 内容管理(章节价格配置) -✅ 支付配置(微信/支付宝/USDT/PayPal) -✅ 用户管理(列表/搜索/删除) -✅ 二维码管理(活码配置) -✅ 提现审核(批量处理) -✅ 系统设置(分销比例/价格) - ---- - -## 七、技术栈总结 - -**前端框架:** -- Next.js 16.0.10(App Router) -- React 19 -- TypeScript 5.9.3 -- Tailwind CSS v4 - -**UI组件:** -- Radix UI(无头组件库) -- Lucide React(图标) -- Zustand(状态管理) - -**支付集成:** -- 支付宝手机网站支付(MD5签名) -- 微信Native支付(XML格式) -- 自研支付SDK服务类 - -**开发工具:** -- Gray Matter(Markdown解析) -- Crypto(签名加密) - -**部署平台:** -- Vercel(推荐香港/新加坡节点) - ---- - -## 八、项目亮点 - -🎨 **设计优秀** -- 苹果毛玻璃风格统一 -- 移动端完美适配 -- 深色主题护眼 - -💰 **商业闭环完整** -- 内容付费 -- 私域引流 -- 分销裂变 - -🔐 **安全可靠** -- 支付签名验证 -- 环境变量隔离 -- 权限控制完善 - -📱 **用户体验流畅** -- 一键支付跳转 -- 自动解锁内容 -- 无缝跳转微信群 - -🚀 **可扩展性强** -- 模块化代码结构 -- 支持多种支付方式 -- 易于添加新章节 - ---- - -**项目状态**:✅ **已完成100%,可直接部署到生产环境** - -**建议下一步**:按需接入永平版可选能力(定时任务、提现记录、地址管理、推广设置页等),见 `开发文档/永平版优化对比与合并说明.md` - -**最后更新时间**:2026-02-27 -**最后更新人**:橙子 (智能助手) -**项目交付状态**:✅ 完整交付 - -**近期更新**:见 [运营与变更.md](./运营与变更.md) 第七部分(开发进度同步)。 - ---- - -## 九、永平版优化合并迭代(2026-02-20) - -### 9.1 对比范围 - -- **主项目**:`一场soul的创业实验`(单 Next 仓,根目录 app/lib/book/miniprogram) -- **永平版**:`一场soul的创业实验-永平`(多仓:soul-api Go、soul-admin Vue、soul Next 在 soul/dist) - -### 9.2 已合并优化项 - -| 模块 | 内容 | 路径/说明 | -|------|------|------------| -| 数据库 | 环境变量 MYSQL_*、SKIP_DB、连接超时与单次错误日志 | `lib/db.ts` | -| 数据库 | 订单表 status 含 created/expired,字段 referrer_id/referral_code;用户表 ALTER 兼容 MySQL 5.7 | `lib/db.ts` | -| 认证 | 密码哈希/校验(scrypt,兼容旧明文) | `lib/password.ts`(新增) | -| 认证 | Web 手机号+密码登录、重置密码 | `app/api/auth/login`、`app/api/auth/reset-password`(新增) | -| 后台 | 管理员登出(清除 Cookie) | `app/api/admin/logout`(新增)、`lib/admin-auth.ts`(新增) | -| 前端 | 仅生产环境加载 Vercel Analytics | `app/layout.tsx` | -| 文档 | 本机/服务器运行说明 | `开发文档/本机运行文档.md`(新增) | -| 文档 | 永平 vs 主项目对比与可选合并清单 | `开发文档/永平版优化对比与合并说明.md`(新增) | - -### 9.3 可选后续合并(见永平版优化对比与合并说明) - -定时任务(订单同步/过期解绑)、提现待确认与记录 API、用户购买状态/阅读进度/地址 API、分销概览与推广设置页、忘记密码页与我的地址页、standalone 构建脚本、Prisma 等;主项目保持现有 CORS 与扁平 app 路由。 - ---- - -## 十、链路优化与 yongpxu-soul 对照(2026-02-20) - -### 10.1 链路优化(不改文件结构) - -- **文档**:已新增 `开发文档/链路优化与运行指南.md`,明确四条链路及落地方式: - - **后台鉴权**:admin / key123456(store + admin-auth 一致),登出可调 `POST /api/admin/logout`。 - - **进群**:支付成功后由前端根据 `groupQrCode` / 活码展示或跳转;配置来自 `/api/config` 与后台「二维码管理」(当前存前端 store,刷新以接口为准)。 - - **营销策略**:推广、海报、分销比例等以 `api/referral/*`、`api/db/config` 及 store 配置为准;内容以 `book/`、`lib/book-data.ts` 为准。 - - **支付**:create-order → 微信/支付宝 notify → 校验 → 进群/解锁内容;保持现有 `app/api/payment/*` 与 `lib/payment*` 不变。 -- **协同**:鉴权、进群、营销、支付可多角色并行优化,所有改动限于现有目录与文件,不新增一级目录。 -- **运行**:以第一目录为基准,`pnpm dev` / 生产 build+standalone,端口 3006;详见 `开发文档/本机运行文档.md` 与链路指南内运行检查清单。 - -### 10.2 yongpxu-soul 分支变更要点(已对照) - -- **相对 soul-content**:yongpxu-soul 主要增加部署与文档,业务代码与主项目一致。 - - 新增:`scripts/deploy_baota.py`、`开发文档/8、部署/宝塔配置检查说明.md`、`开发文档/8、部署/当前项目部署到线上.md`、小程序相关(miniprogram 上传脚本、开发文档/小程序管理、开发文档/服务器管理)、`开发文档/提现功能完整技术文档.md`、`lib/wechat-transfer.ts` 等。 - - 删除/合并:大量历史部署报告与重复文档(如多份「部署完成」「升级完成」等),功能迭代记录合并精简。 -- **结论**:业务链路(鉴权→进群→营销→支付)以**第一目录现有实现**为准;yongpxu-soul 的修改用于**部署方式、小程序发布、文档与运维**,不改变主项目文件结构与上述四条链路的代码归属。 -- **可运行性**:按《链路优化与运行指南》第七节检查清单自检后,项目可在不修改文件结构的前提下完成落地与运行。 - -### 10.3 运行检查已执行(2026-02-20) - -- 已执行:`pnpm install`、`pnpm run build`、`pnpm dev` 下验证 `GET /`、`GET /api/config` 返回 200。 -- 执行记录详见 `开发文档/链路优化与运行指南.md` 第八节。 -- 结论:构建与开发环境运行正常,链路就绪。 - ---- - -## 十一、下一步行动计划(2026-02-20) - -| 优先级 | 行动项 | 负责模块 | 说明 | -|--------|--------|----------|------| -| P0 | 生产部署与回调配置 | 支付/部署 | 将当前分支部署至宝塔(或现有环境),配置微信/支付宝回调 URL 指向 `/api/payment/wechat/notify`、`/api/payment/alipay/notify`,并验证支付→到账→进群展示。 | -| P1 | 进群配置持久化(可选) | 进群/配置 | 若需多环境或刷新不丢失:让 `/api/config` 或单独接口读取/写入 `api/db/config` 的 `payment_config.wechatGroupUrl`、活码链接;或后台「二维码管理」保存时调用 db 配置 API。 | -| P1 | 后台「退出登录」对接 | 鉴权 | 在 `app/admin/layout.tsx` 将「返回前台」旁增加「退出登录」按钮,点击请求 `POST /api/admin/logout` 后跳转 `/admin/login`(若后续改为服务端 Cookie 鉴权即可生效)。 | -| P2 | Admin 密码环境变量统一(可选) | 鉴权 | 在 `lib/store.ts` 的 `adminLogin` 中从 `process.env.NEXT_PUBLIC_ADMIN_USERNAME` / `NEXT_PUBLIC_ADMIN_PASSWORD` 读取(或通过小 API 校验),与 `lib/admin-auth.ts` 一致。 | -| P2 | 营销与内容迭代 | 营销/内容 | 在现有结构内更新:`book/` 下 Markdown、`lib/book-data.ts` 章节与免费列表、`api/referral/*` 与 `api/db/config` 分销/推广配置;后台「系统设置」「内容管理」按需调整。 | -| P2 | 文档与分支同步 | 文档 | 定期将 yongpxu-soul 的部署/小程序/运维文档变更合并到主分支或文档目录,保持《链路优化与运行指南》《本机运行文档》与线上一致。 | - -以上按 P0 → P1 → P2 顺序推进;P0 完成即可上线跑通整条链路,P1/P2 为体验与可维护性增强。 - ---- - -## 十二、永平落地(2026-02 依据 cursor_1_14) - -| 任务 | 状态 | 说明 | -|------|------|------| -| 内容管理仅保留「API 接口」按钮 | 已完成 | soul-admin ContentPage 源码改造,移除 5 按钮,新增 API 接口按钮 | -| 侧栏与推广中心页「交易中心」→「推广中心」 | 已完成 | AdminLayout、DistributionPage 文案统一 | -| 分销:海报带用户 ID、复制文案去掉邀请码展示 | 已完成 | referral.js scene 用 userId;海报去掉邀请码文案 | -| 我的页:待领收益→我的收益 | 已完成 | my.wxml 未登录卡片文案统一 | -| 后台与前台参数一致(绑定有效期、自动提现、免费章节) | 已检查 | 推广设置、系统设置与 API 对齐 | -| 需求与文档整理 | 已完成 | 需求汇总需求清单、运营与变更第五部分、本推进表十二节 | -| 会员分润差异化(会员 20%/非会员 10%) | 已完成 | computeOrderCommission;推广设置页 vipOrderShareVip、vipOrderShareNonVip | -| VIP 角色管理、SetVipModal、VIP 排序 | 已完成 | vip_roles 表、VipMembers 页、vip_activated_at/vip_sort | -| 开发进度同步会议 | 已完成 | 2026-02-27 橙子同步至运营与变更第七部分 | - ---- - -## 十三、找伙伴功能完善(2026-03-08) - -| 任务 | 状态 | 说明 | -|------|------|------| -| 后台「找伙伴」统一入口页(5 Tab) | 已完成 | 数据统计→找伙伴→资源对接→导师预约→团队招募 | -| 找伙伴统计 Tab | 已完成 | 6 统计卡片 + 类型分布 + CKB 7 端点真实测试 | -| 匹配池选择(VIP/完善/全部) | 已完成 | 3 来源池 + 4 项完善度开关;显示各池人数 | -| 用户管理 ?pool= 参数筛选 | 已完成 | 支持 ?pool=vip/complete/all 跳转筛选 | -| CKBJoin 写入 match_records | 已完成 | 团队招募/资源对接 ckb/join 成功后同步写入 | -| 小程序「超级个体」改名「找伙伴」 | 已完成 | match.js partner label 更新 | -| 当天已匹配不重复 | 已完成 | MatchUsers 排除当天已匹配 matched_user_id | -| 存客宝协作需求文档 | 已完成 | 4 条需求写入存客宝协作需求.md | -| CKB 测试"已存在"判定修正 | 已完成 | 前端:已存在/已加入也标为成功 | -| 匹配记录加载失败修复 | 已完成 | 后端 DBMatchRecordsList 对空用户做安全读取,避免 nil panic | -| 存客宝右上角工作台 | 已完成 | 从独立 Tab 改为右上角入口;支持接口测试、配置保存、文档摘要 | -| 存客宝场景配置列表化 | 已完成 | 每个入口独立 apiUrl/apiKey/source/tags/siteTags/notes,可保存到 ckb_config.routes | -| CKB 明细接口 | 已完成 | 新增 /api/db/ckb-leads,支持已提交线索 / 有联系方式明细查看 | -| 存客宝入口位置调整 | 已完成 | 从主 Tab 改回右上角按钮入口,点击打开存客宝工作台 | -| 存客宝工作台子页化 | 已完成 | 概览 / 已提交线索 / 有联系方式 / 场景配置 / 接口测试 / API 文档 六块独立 | -| AI 获客数据首页重构 | 已完成 | 数据统计页拆为「找伙伴数据 / AI 获客数据」,已提交线索和有联系方式可点开 | -| 本地测试数据插入能力 | 已完成 | 新增 /api/db/match-records/test;资源对接/团队招募页可一键插入测试记录 | -| Dashboard 增加匹配概览 | 已完成 | 首页数据概览新增「匹配次数」「匹配收益」 | - ---- - -## 十四、内容管理深度优化(2026-03-07 ~ 2026-03-09) - -### 14.1 排名算法可配置化(03-07) - -| 任务 | 状态 | 说明 | -|------|------|------| -| 排名算法权重可编辑 | 已完成 | 阅读/新度/付款三权重可在后台直接修改,权重存 system_config | -| 数据填充(点击量/付款数) | 已完成 | reading_progress + orders 表关联,排行榜显示点击量、付款数、热度 | -| 批量移动修复 | 已完成 | 修复「移动失败,缺少ID」问题,SectionIds 正确传递 | -| 2026每日派对干货板块一致性 | 已完成 | 新建/删除/编辑功能与其他板块保持一致 | -| 后台整体优化 | 已完成 | 界面美化、交互优化、暗色主题深度定制 | - -### 14.2 内容管理五项修改(03-08 第一批) - -| 任务 | 状态 | 说明 | -|------|------|------| -| 删除「钩子设置」Tab → 新增「内容排行榜」Tab | 已完成 | 排行榜按热度排序,分页10节/页,显示点击数据 | -| 拖拽排序与后端同步修复 | 已完成 | 章节树拖拽排序结果正确写入数据库 | -| 未付费预览比例可配置 | 已完成 | system_config 存 unpaid_preview_percent,后台可修改 | -| 排名权重可编辑 + 精选推荐/首页置顶 | 已完成 | 置顶用 Star 图标标识,pinned_section_ids 存配置 | -| 合并预览/编辑按钮 + 章节ID可编辑 | 已完成 | 单按钮打开编辑弹窗,ID 字段可直接修改 | - -### 14.3 内容管理五项修改(03-08 第二批) - -| 任务 | 状态 | 说明 | -|------|------|------| -| Tab 顺序调整 | 已完成 | 章节管理 → 内容排行榜 → 内容搜索 | -| 置顶状态全局显示(Star图标) | 已完成 | 章节树、排行榜、搜索结果均显示 Star | -| 排名积分逻辑细化 | 已完成 | 最近更新30分递减/阅读量20分递减/付款数20分递减 + 手动覆盖 | -| 富文本编辑器升级 | 已完成 | TipTap 编辑器,支持格式化/图片/表格/@提及/#链接标签 | -| 人物列表 + 链接标签管理 | 已完成 | persons/link_tags 表 CRUD,后台管理界面 | - -### 14.4 内容管理三项修改(03-09 第三批) - -| 任务 | 状态 | 说明 | -|------|------|------| -| 排行榜操作改为「编辑文章」 | 已完成 | 原「付款记录」按钮移入编辑弹窗底部 | -| 章节ID修改确保保存成功 | 已完成 | 前端 originalId 机制 + 后端 newId 字段支持 | -| 付款记录用户ID/订单ID可点击跳转 | 已完成 | 用户名截短显示,点击跳转用户详情/订单详情 | - -### 14.5 链接AI Tab(03-09 第四批) - -| 任务 | 状态 | 说明 | -|------|------|------| -| 「主人公」Tab → 「链接AI」Tab | 已完成 | 链接人与事,AI列表 + 链接标签管理 | -| 人物ID改为可选 | 已完成 | 名称必填,ID自动生成;后端兼容 | -| 链接标签新增「存客宝」类型 | 已完成 | 支持 url/miniprogram/ckb 三种类型 | -| 存客宝绑定配置面板 | 已完成 | 显示API地址和绑定计划,跳转存客宝工作台 | -| 预填充数据 | 已完成 | 卡若/南风/远志/老墨/荷总/永平 + 神仙团队/Soul派对房/飞书中台/超级个体 | - ---- - -## 十五、存客宝集成技术方案 - -### 15.1 概述 - -存客宝(CKB)是第三方获客工具,通过 API 上报线索到微信生态中实现自动加好友/拉群。本项目在以下场景集成: - -1. **找伙伴功能**:匹配成功 → 上报存客宝场景 → 自动加好友 -2. **内容管理「链接AI」**:文章内 @人物 / #标签 → 点击跳转存客宝链接 → 进入流量池 - -### 15.2 核心 API - -| 接口 | 方法 | 地址 | 说明 | -|------|------|------|------| -| 场景获客 | POST | `https://ckbapi.quwanzhi.com/v1/api/scenarios` | 上报线索(手机号/微信号等) | -| 线索查询 | GET | `/v1/api/lead/query` | 按手机号/微信号查询状态(待开发) | -| 批量统计 | GET | `/v1/api/lead/stats` | 时间段内线索统计(待确认) | -| 自动加好友 | POST | `/v1/api/lead/add-friend` | 匹配后自动发起好友申请(待确认) | - -### 15.3 后台配置 - -- **存客宝场景配置**:`找伙伴 → 存客宝工作台` 中管理 apiUrl/apiKey/source/tags 等 -- **内容链接绑定**:`内容管理 → 链接AI → 存客宝绑定` 面板配置计划绑定 -- **链接标签类型 = ckb**:link_tags 表 type 支持 `url`/`miniprogram`/`ckb` - -### 15.4 数据库表 - -- `persons`:AI人物列表(person_id, name, label) -- `link_tags`:链接标签(tag_id, label, url, type[url/miniprogram/ckb], app_id, page_path) -- `system_config`:存客宝相关配置(ckb_config.routes, ckb_api_key 等) - -详细协作需求见 `存客宝协作需求.md`。 diff --git a/开发文档/1、需求/修改/20260308内容管理1.md b/开发文档/1、需求/修改/20260308内容管理1.md deleted file mode 100644 index 8af55a52..00000000 --- a/开发文档/1、需求/修改/20260308内容管理1.md +++ /dev/null @@ -1,19 +0,0 @@ -修改五 -![](images/2026-03-08-17-15-30.png) -![](images/2026-03-08-17-16-57.png)然后这一个小眼睛跟边际的功能重复了,这两个功能直接合并掉。直接合并掉,然后把这个。直接合并掉。然后在这个编辑章节里面,这个章节 ID 是可以修改的,修改完之后就直接到指定的目录里面去了。然后把这个章节,这个免费章节设为免费就可以了,把免费章节那个提示词给我去掉,然后在这个里面的话,内容这边的话是可以点击指定的位置直接插入图片的,并且这个图片是一个像飞书一样,是一个快的一个格式,我可以直接通过 API 插入图片,那在这个编辑章节里面。 -![](images/2026-03-08-17-17-25.png)你那个深度的去帮我把这个整个的那个内容的那个编辑的这个编辑框优化,深度的优化一下,直到符合我的需求,我可以通过 API 直接传入图片、传入格式,传入表格的一个形式。功能开发并且完善,让我可以那个直接通过接口的形式来更改这个整个文章,也可以那个可以上传到指定的那个发图片上传上去,并且可以编辑跟排版。这个功能深度的开放 - -修改四 -![](images/2026-03-08-17-13-34.png) -![](images/2026-03-08-17-14-04.png)人内容管理的里面的这个权重。权重是可以修改的,它的一个热度,权重的这个数值是可以修改的。在排行榜这边你是可以修改的,直接就可以修改掉。并且那个字顶置顶的那几条。置顶的那几条也是可以直接修改的,那小程序里面置顶的这个可以强制置顶,有个选项,我可以选择这个精选推荐这边跟首页的这个最新更新,这两个地方是可以直接按我的那个脱离算法,可以直接在后台配置的。在这个内容管理的后台直接可以配置。 - -修改三 -![](images/2026-03-08-17-11-50.png)内容管理的小程序上面未付费前默认是20%,但是这个百分比是可以调成调整的,有一些这个那个显示的那个规则,显示的这个内容的那个规则也要在那个上方多一个标签,就是这个内容显示的那个规则要在上面显示清楚。处理清楚。那增加一个标签来处理这个问题 - -修改二 -![](images/2026-03-08-17-10-32.png)然后这个拉移动的,这个小三点移动到哪里?就要位置要替换掉,现在位置还在这边,首页也显示是这个,比如2026每日派对干货,这个已经显示在上方,但是这里的话还是显示在下方位置显示是不正确的,你帮我把这个位置显示处理一下,并且以后这个目录整个的这个结构跟首页的那个小程序上面的那个结构的表保持是一致的。这边调整小程序后台只要一调整小程序相应的做调整。 - -修改一 -![](images/2026-03-08-17-09-33.png) -钩子设置直接删除掉,然后设置这个就是一个那个内容排行榜。内容排行榜就按这个内容的一个热度进行排行,按章节来排行,然后分页,每一页10个10小节做一个内容的排行榜,然后把每一章节的那个数据点击量这个做一个详细的一个排行,把购置车子这个去删除掉。 - diff --git a/开发文档/1、需求/修改/20260308内容管理2.md b/开发文档/1、需求/修改/20260308内容管理2.md deleted file mode 100644 index f2e1a361..00000000 --- a/开发文档/1、需求/修改/20260308内容管理2.md +++ /dev/null @@ -1,26 +0,0 @@ - -功能五 # -image.png![](images/2026-03-09-04-50-16.png)![](images/2026-03-09-04-51-03.png) -同时可以加另外一个符号,就是减号,减号是直接可以跳转到链接和跳转到小程序,这个后台一样是可以配置的,有点类似于那个飞书的,有点类似于飞书的,公飞书的这个。标签词的这个功能,点击一下就跳转到那个相应的那个网页上面了。它可以编辑成网址,也点击跳转,也可以编辑成那个。也可以编辑成那个小程序,其他的或者其他的唤醒的这个格式,这个我们后台在内容管理的后台也增加这么一个标签。爱的也好,减号也好的,相应的那个功能都可以通过这个 API 接口直接传入进来的。然后这个相应的设置跟那个链接匹配的设置跟链接匹配放到排行榜的那个后面,比如我要艾特人的那个设置跟那个艾特人的链接,就放到排行榜后面的这个位置,然后全力的帮我开发一下,确保我整个功能可用 - - -功能四 @ -image.png![](images/2026-03-09-04-48-03.png) -![](images/2026-03-09-04-49-01.png) -机编辑章节里边的整个这个的内容不是 Markdown 的格式,这个是帮我找一下世界上最好的一个内容编辑器,帮我去 EUP 上面找一个最好的一个内容编辑器,并且这个内容编辑器可以快的形式直接插入,像飞书一样以快的形式直接插入。让我可以上传图片和格式,帮我尽可能的去优化一下这个整个的这个编辑器。然后这个编辑器里面的话,我可以插入链接,也可以艾特指定的人。加爱的是可以直接艾特指定的,我们这个设置好内容管理多一个人物列表,就人跟人,跟人的 ID 跟他的名字跟相应的字可以互相的列匹配的一个 ID,我点击这个 ID 就可以直接联系这个人。点一下,点一下这个 ID,存个宝,这边就会有人来添加,跟有人来添加这个用户的这么一个功能在文章里面去体现,你可以在标题,也可以在标题里面去体现这么一个 @ 的一个功能,这个符号。如果人名上加上这个符号@,就是实现这个功能。然后这个在编辑器里面可以有,也可以用代码直接实现 - - -功能三 文章排序 -![](images/2026-03-09-04-46-02.png) -那个文章排名的算法是这样,这个。最近更新前30得分应该是30套一分,就是他的解释是这样,就最新更新的第一篇,比如今天的那最近当天的就30,昨天的就29,在前一天是28,一直循序渐进下去,然后阅读量前20也是一样,排名第一的阅读量就是20。第二就19,第三就是18,第47。20 19 18 17这种的方式付款,也是付款最多的,就20,第二就19,第三就18,是根据这个算出来的。 - - -功能二 置顶 -字典的这个功能是在那个章节跟搜索里面都是可以,都通用,都通用就是这个内容馆排行榜的字典的功能在章节里面也需要显示字典的这么一个功能。 -![](images/2026-03-09-04-42-08.png) - - -功能一 -![](images/2026-03-09-04-36-17.png) -![](images/2026-03-09-04-37-35.png) -![](images/2026-03-09-04-38-20.png)那个章节管理后面跟的是内容排行榜,然后再到内容搜索。这道内容搜索。然后这个内容管理里面的话,包括内容排行榜这边的话,每一个章节它需要有一个。需要有一个可以点击就可以置顶的。对,一个功能在这个编辑章节里面点击出了就可以推送到在小程序首页的这么一个功能。这个在这个编辑章节里面就需要一个小程序的小灾,小程序直推的,在算法之外直推的一个功能。另外一方面的话是这个章节里面的这个。这个小杰里面的这个。热度这篇是可以编辑的。可以在这个编辑里面去修改编辑章节热度的这个值算法的这个。这个字。可以修改 \ No newline at end of file diff --git a/开发文档/1、需求/修改/20260308内容管理3.md b/开发文档/1、需求/修改/20260308内容管理3.md deleted file mode 100644 index 907e6add..00000000 --- a/开发文档/1、需求/修改/20260308内容管理3.md +++ /dev/null @@ -1,14 +0,0 @@ -完成这个所有的这三个需求,然后确保每一个填空的所有的数值都是可以保存的,然后你不着急帮我部署到服务器,先本地帮我做好把所有功能检测清晰可用 -功能三付款记录 -![](images/2026-03-09-05-25-52.png) -付款季度这边的话,显示用户的名称 ID 太长了,那点击之后是可以直接跳转到这个 ID 里面的,那点击订单也是直接可以跳转到这个相应的订单里面。这个是那个内容管理里面的这个付款记录这个地方。 - -功能二 -![](images/2026-03-09-05-22-19.png) -![](images/2026-03-09-05-23-53.png) -![](images/2026-03-09-05-24-19.png)内蒙古排行榜这边的话,操作的话应该是点击的是编辑文章,而不是付款记录,这应该放到这个内容的这个编辑里面。应该放到内容的编辑里面,章节的这个编辑里面。然后这个确保,并且确保这个章节 ID 修改成功。直接所有的那个参数修改,在数据库里面修改成功,这个一定要帮我确保清楚。所有的参数都可以正常确保成功,然后这个编辑器里面的话,那个增加这个井号跟 ad 的功能,而且要凸显,然后并且这个功能在咱们的这个内容管理的 API 接口要体现,嗯。链接和小程序都是# 并且 ad 跟那个链接和小程序点击是直接跳转过去的,然后它的颜色是突出的,那在文章里面显示的时候颜色是轻微突出。 - -功能一 -![](images/2026-03-09-05-18-28.png) -表哥列记标签的这么一个功能放到这个,这一块的功能放到章节管理跟内容管理,还有那个 ad,第四个标签就是 ad 那个。你的撸管。爱的相关人物的这么一个功能就相关。主人公功能就叫做主人公功能,把这个功能帮我列出来,弄到这个。如何弄到这个里面来?就是一个独立的一个功能,并且帮我把里面的这个人物列表编辑器内可以艾特的这个功能也放到编辑器里面,直接可以选择我,我直接可以选择相关已经配置好的那个已经配置好的人物跟配置好的一个链接,然后你现在帮我添加几个的这个链接,就是里面有提到的。比如卡洛,我们数据库里面的用户卡洛南风,对吧?还有远志这些已经提到的,并且那个超级个体如果成为超级个体,这个利表单也直接在这个里面数据帮我填写好已经是超级个体了,然后链接跟标题标签,比如神仙团队这些有提到的链接跟标签,你帮我写出来,帮我填写进去。 -编辑器副文本的那个编辑器里面,你把这两个 @ 跟人物列表的跟那个链接的。链接的这个是加上# 号的,这么加减号或者他已经是有家眷的这个功能就直接那个写上去,嗯。 \ No newline at end of file diff --git a/开发文档/1、需求/修改/20260308内容管理4.md b/开发文档/1、需求/修改/20260308内容管理4.md deleted file mode 100644 index 3d9bdb94..00000000 --- a/开发文档/1、需求/修改/20260308内容管理4.md +++ /dev/null @@ -1,10 +0,0 @@ - -不用直接部署,直接修改,用中文回复我 - -需求一: -需要存克宝这篇提供的整链接下全站的需要存克宝这篇提供的相关的那个功能跟技术也写上去,写到那个文档里面,然后把这个相关的这个内容,这几天,这两天。7号、8号、9号修改了内容跟完成的内容都到这个项目管理的进度里面。然后把整个这个项目上传到 Git Hub 上面,gitea 跟 GitHub 上面 -i git Hub 上面把这个打开这个落地推荐表的页面以及存课宝的页面发给我。直接打开,直接在浏览器打开这两个 GitHub 上面上传成功之后这两个页面 - -功能一 -![](images/2026-03-09-05-35-24.png) -![](images/2026-03-09-05-36-51.png)这个主人公,这一个的话改一下,他这个就是链接的一一个功能,链接的一个功能。就是 ad 跟减号链接。链接人和事。链接 AI 跟这个名字应该改一下,链接 AI 跟事情。链接,AI,链接 AI 主人公,改成链接 AI。然后这里的话,主人公这边的话输入之后这个 ID 是可选项的,然后把那些默认 VIP 就默认到这个里面,这个变成一个标签,并且在那个副文本框是可以直接调取的。然后在小程序的前方也可以直接显示。然后这一个的话在主人公这个是属于 AI 列表,不叫主人公列表,这边就叫 AI 列表,然后这里面就写的是相应的等人物 ID,然后以及配置后端需要有一个配置,一个存客宝,哪一个存客宝的那个手机要么就是存克保指定的那个手。它配置跟纯克宝这边的那个计划是绑定的,捆绑的计划帮我把这个绑定的计划帮我艾特完之后,就是像我们首页链接卡洛一样,点击就直接可以那个添加过去,进到这个流量池里面来。然后这个点击的这个链接的这一个内容的流量词的列表有多少个人点击链接,它这里面有一个列表出来和链接出来这个列表底下,然后把这个上面像 VIP 跟那个几个刚刚提到的,上方提到的几个都优化迭代一下,把这个加上去。 \ No newline at end of file diff --git a/开发文档/1、需求/修改/20260308用户管理3.md b/开发文档/1、需求/修改/20260308用户管理3.md deleted file mode 100644 index 0c619d29..00000000 --- a/开发文档/1、需求/修改/20260308用户管理3.md +++ /dev/null @@ -1,39 +0,0 @@ -# 需求文档标题 - -> 创建日期:YYYY-MM-DD -> 文档格式:Markdown(支持图片粘贴 + 预览) - ---- - -## 一、背景与目标 - -(在此输入文字,可直接粘贴图片) - - - ---- - -## 二、功能点 - -### 2.1 功能一 - -(文字 + 可粘贴的截图、原型图) - -示例图片引用:`![描述](./images/截图1.png)` - -### 2.2 功能二 - - - ---- - -## 三、补充说明 - -(可继续粘贴图片和文字) - ---- - -## 使用提示 - -- **粘贴图片**:在 Cursor 中安装「Paste Image」扩展后,直接 Ctrl+V / Cmd+V 即可将剪贴板图片保存到 `images/` 并自动插入引用 -- **预览**:`Cmd+Shift+V` 或右侧「Open Preview」查看排版效果 diff --git a/开发文档/1、需求/修改/Soul 20260118.pdf b/开发文档/1、需求/修改/Soul 20260118.pdf deleted file mode 100644 index 02b7a2ec..00000000 Binary files a/开发文档/1、需求/修改/Soul 20260118.pdf and /dev/null differ diff --git a/开发文档/1、需求/修改/images/![描述](./images/截图1.png)`.png b/开发文档/1、需求/修改/images/![描述](./images/截图1.png)`.png deleted file mode 100644 index 691139b9..00000000 Binary files a/开发文档/1、需求/修改/images/![描述](./images/截图1.png)`.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/.gitkeep b/开发文档/1、需求/修改/images/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/开发文档/1、需求/修改/images/2026-03-08-08-02-44.png b/开发文档/1、需求/修改/images/2026-03-08-08-02-44.png deleted file mode 100644 index 26a4fcb4..00000000 Binary files a/开发文档/1、需求/修改/images/2026-03-08-08-02-44.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/2026-03-08-08-05-57.png b/开发文档/1、需求/修改/images/2026-03-08-08-05-57.png deleted file mode 100644 index 691139b9..00000000 Binary files a/开发文档/1、需求/修改/images/2026-03-08-08-05-57.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/2026-03-08-08-08-36.png b/开发文档/1、需求/修改/images/2026-03-08-08-08-36.png deleted file mode 100644 index 362b6679..00000000 Binary files a/开发文档/1、需求/修改/images/2026-03-08-08-08-36.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/2026-03-08-08-11-21.png b/开发文档/1、需求/修改/images/2026-03-08-08-11-21.png deleted file mode 100644 index b5cc0318..00000000 Binary files a/开发文档/1、需求/修改/images/2026-03-08-08-11-21.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/2026-03-08-08-16-43.png b/开发文档/1、需求/修改/images/2026-03-08-08-16-43.png deleted file mode 100644 index 54c56ae6..00000000 Binary files a/开发文档/1、需求/修改/images/2026-03-08-08-16-43.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/2026-03-08-08-16-47.png b/开发文档/1、需求/修改/images/2026-03-08-08-16-47.png deleted file mode 100644 index 54c56ae6..00000000 Binary files a/开发文档/1、需求/修改/images/2026-03-08-08-16-47.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/2026-03-08-08-35-20.png b/开发文档/1、需求/修改/images/2026-03-08-08-35-20.png deleted file mode 100644 index be69f520..00000000 Binary files a/开发文档/1、需求/修改/images/2026-03-08-08-35-20.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/2026-03-08-08-37-41.png b/开发文档/1、需求/修改/images/2026-03-08-08-37-41.png deleted file mode 100644 index 8bc262c6..00000000 Binary files a/开发文档/1、需求/修改/images/2026-03-08-08-37-41.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/2026-03-08-08-42-59.png b/开发文档/1、需求/修改/images/2026-03-08-08-42-59.png deleted file mode 100644 index 96425dfc..00000000 Binary files a/开发文档/1、需求/修改/images/2026-03-08-08-42-59.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/2026-03-08-08-45-48.png b/开发文档/1、需求/修改/images/2026-03-08-08-45-48.png deleted file mode 100644 index 7713b2b2..00000000 Binary files a/开发文档/1、需求/修改/images/2026-03-08-08-45-48.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/2026-03-08-09-07-07.png b/开发文档/1、需求/修改/images/2026-03-08-09-07-07.png deleted file mode 100644 index d6d3a9cd..00000000 Binary files a/开发文档/1、需求/修改/images/2026-03-08-09-07-07.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/2026-03-08-09-07-58.png b/开发文档/1、需求/修改/images/2026-03-08-09-07-58.png deleted file mode 100644 index 6c2e9f77..00000000 Binary files a/开发文档/1、需求/修改/images/2026-03-08-09-07-58.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/2026-03-08-09-10-04.png b/开发文档/1、需求/修改/images/2026-03-08-09-10-04.png deleted file mode 100644 index 91ea3896..00000000 Binary files a/开发文档/1、需求/修改/images/2026-03-08-09-10-04.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/2026-03-08-10-08-47.png b/开发文档/1、需求/修改/images/2026-03-08-10-08-47.png deleted file mode 100644 index 3e5f98da..00000000 Binary files a/开发文档/1、需求/修改/images/2026-03-08-10-08-47.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/2026-03-08-10-17-14.png b/开发文档/1、需求/修改/images/2026-03-08-10-17-14.png deleted file mode 100644 index c5021da2..00000000 Binary files a/开发文档/1、需求/修改/images/2026-03-08-10-17-14.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/2026-03-08-10-18-28.png b/开发文档/1、需求/修改/images/2026-03-08-10-18-28.png deleted file mode 100644 index f2da3e2e..00000000 Binary files a/开发文档/1、需求/修改/images/2026-03-08-10-18-28.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/2026-03-08-10-21-19.png b/开发文档/1、需求/修改/images/2026-03-08-10-21-19.png deleted file mode 100644 index 154d9cfa..00000000 Binary files a/开发文档/1、需求/修改/images/2026-03-08-10-21-19.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/2026-03-08-10-28-11.png b/开发文档/1、需求/修改/images/2026-03-08-10-28-11.png deleted file mode 100644 index 8e9f093f..00000000 Binary files a/开发文档/1、需求/修改/images/2026-03-08-10-28-11.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/2026-03-08-10-30-34.png b/开发文档/1、需求/修改/images/2026-03-08-10-30-34.png deleted file mode 100644 index cb02a3be..00000000 Binary files a/开发文档/1、需求/修改/images/2026-03-08-10-30-34.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/2026-03-08-10-31-24.png b/开发文档/1、需求/修改/images/2026-03-08-10-31-24.png deleted file mode 100644 index 2fb548f7..00000000 Binary files a/开发文档/1、需求/修改/images/2026-03-08-10-31-24.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/2026-03-08-10-43-44.png b/开发文档/1、需求/修改/images/2026-03-08-10-43-44.png deleted file mode 100644 index 809d7ac1..00000000 Binary files a/开发文档/1、需求/修改/images/2026-03-08-10-43-44.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/2026-03-08-10-44-05.png b/开发文档/1、需求/修改/images/2026-03-08-10-44-05.png deleted file mode 100644 index 532f8e7c..00000000 Binary files a/开发文档/1、需求/修改/images/2026-03-08-10-44-05.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/2026-03-08-10-46-02.png b/开发文档/1、需求/修改/images/2026-03-08-10-46-02.png deleted file mode 100644 index c053e673..00000000 Binary files a/开发文档/1、需求/修改/images/2026-03-08-10-46-02.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/2026-03-08-10-47-24.png b/开发文档/1、需求/修改/images/2026-03-08-10-47-24.png deleted file mode 100644 index caa38799..00000000 Binary files a/开发文档/1、需求/修改/images/2026-03-08-10-47-24.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/2026-03-08-10-56-15.png b/开发文档/1、需求/修改/images/2026-03-08-10-56-15.png deleted file mode 100644 index 1f3d6a05..00000000 Binary files a/开发文档/1、需求/修改/images/2026-03-08-10-56-15.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/2026-03-08-10-58-04.png b/开发文档/1、需求/修改/images/2026-03-08-10-58-04.png deleted file mode 100644 index 822f57cc..00000000 Binary files a/开发文档/1、需求/修改/images/2026-03-08-10-58-04.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/2026-03-08-10-59-57.png b/开发文档/1、需求/修改/images/2026-03-08-10-59-57.png deleted file mode 100644 index 4f4fe844..00000000 Binary files a/开发文档/1、需求/修改/images/2026-03-08-10-59-57.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/2026-03-08-11-17-15.png b/开发文档/1、需求/修改/images/2026-03-08-11-17-15.png deleted file mode 100644 index aa7cd440..00000000 Binary files a/开发文档/1、需求/修改/images/2026-03-08-11-17-15.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/2026-03-08-11-18-04.png b/开发文档/1、需求/修改/images/2026-03-08-11-18-04.png deleted file mode 100644 index a337b0cb..00000000 Binary files a/开发文档/1、需求/修改/images/2026-03-08-11-18-04.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/2026-03-08-11-19-38.png b/开发文档/1、需求/修改/images/2026-03-08-11-19-38.png deleted file mode 100644 index 9e50cffc..00000000 Binary files a/开发文档/1、需求/修改/images/2026-03-08-11-19-38.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/2026-03-08-11-20-02.png b/开发文档/1、需求/修改/images/2026-03-08-11-20-02.png deleted file mode 100644 index 43ccdabd..00000000 Binary files a/开发文档/1、需求/修改/images/2026-03-08-11-20-02.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/2026-03-08-11-22-09.png b/开发文档/1、需求/修改/images/2026-03-08-11-22-09.png deleted file mode 100644 index a91f5df6..00000000 Binary files a/开发文档/1、需求/修改/images/2026-03-08-11-22-09.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/2026-03-08-11-30-23.png b/开发文档/1、需求/修改/images/2026-03-08-11-30-23.png deleted file mode 100644 index c127e04d..00000000 Binary files a/开发文档/1、需求/修改/images/2026-03-08-11-30-23.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/2026-03-08-11-31-27.png b/开发文档/1、需求/修改/images/2026-03-08-11-31-27.png deleted file mode 100644 index bb6d0efc..00000000 Binary files a/开发文档/1、需求/修改/images/2026-03-08-11-31-27.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/2026-03-08-11-32-34.png b/开发文档/1、需求/修改/images/2026-03-08-11-32-34.png deleted file mode 100644 index bd25583d..00000000 Binary files a/开发文档/1、需求/修改/images/2026-03-08-11-32-34.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/2026-03-08-11-32-54.png b/开发文档/1、需求/修改/images/2026-03-08-11-32-54.png deleted file mode 100644 index 6c4a6aeb..00000000 Binary files a/开发文档/1、需求/修改/images/2026-03-08-11-32-54.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/2026-03-08-15-58-20.png b/开发文档/1、需求/修改/images/2026-03-08-15-58-20.png deleted file mode 100644 index 2ca829f5..00000000 Binary files a/开发文档/1、需求/修改/images/2026-03-08-15-58-20.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/2026-03-08-15-59-01.png b/开发文档/1、需求/修改/images/2026-03-08-15-59-01.png deleted file mode 100644 index b8c0d2e3..00000000 Binary files a/开发文档/1、需求/修改/images/2026-03-08-15-59-01.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/2026-03-08-15-59-53.png b/开发文档/1、需求/修改/images/2026-03-08-15-59-53.png deleted file mode 100644 index eae81c52..00000000 Binary files a/开发文档/1、需求/修改/images/2026-03-08-15-59-53.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/2026-03-08-16-02-09.png b/开发文档/1、需求/修改/images/2026-03-08-16-02-09.png deleted file mode 100644 index a1be22bf..00000000 Binary files a/开发文档/1、需求/修改/images/2026-03-08-16-02-09.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/2026-03-08-16-14-58.png b/开发文档/1、需求/修改/images/2026-03-08-16-14-58.png deleted file mode 100644 index 35f17fad..00000000 Binary files a/开发文档/1、需求/修改/images/2026-03-08-16-14-58.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/2026-03-08-16-15-14.png b/开发文档/1、需求/修改/images/2026-03-08-16-15-14.png deleted file mode 100644 index 169bb455..00000000 Binary files a/开发文档/1、需求/修改/images/2026-03-08-16-15-14.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/2026-03-08-16-15-31.png b/开发文档/1、需求/修改/images/2026-03-08-16-15-31.png deleted file mode 100644 index 4b9c3001..00000000 Binary files a/开发文档/1、需求/修改/images/2026-03-08-16-15-31.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/2026-03-08-16-18-08.png b/开发文档/1、需求/修改/images/2026-03-08-16-18-08.png deleted file mode 100644 index 9cc05b91..00000000 Binary files a/开发文档/1、需求/修改/images/2026-03-08-16-18-08.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/2026-03-08-16-30-11.png b/开发文档/1、需求/修改/images/2026-03-08-16-30-11.png deleted file mode 100644 index 0910aa79..00000000 Binary files a/开发文档/1、需求/修改/images/2026-03-08-16-30-11.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/2026-03-08-16-31-01.png b/开发文档/1、需求/修改/images/2026-03-08-16-31-01.png deleted file mode 100644 index f41b0768..00000000 Binary files a/开发文档/1、需求/修改/images/2026-03-08-16-31-01.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/2026-03-08-16-32-02.png b/开发文档/1、需求/修改/images/2026-03-08-16-32-02.png deleted file mode 100644 index 639c2dc6..00000000 Binary files a/开发文档/1、需求/修改/images/2026-03-08-16-32-02.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/2026-03-08-16-33-49.png b/开发文档/1、需求/修改/images/2026-03-08-16-33-49.png deleted file mode 100644 index 7b43e266..00000000 Binary files a/开发文档/1、需求/修改/images/2026-03-08-16-33-49.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/2026-03-08-16-34-58.png b/开发文档/1、需求/修改/images/2026-03-08-16-34-58.png deleted file mode 100644 index 30a38b25..00000000 Binary files a/开发文档/1、需求/修改/images/2026-03-08-16-34-58.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/2026-03-08-16-36-11.png b/开发文档/1、需求/修改/images/2026-03-08-16-36-11.png deleted file mode 100644 index 6c600ca0..00000000 Binary files a/开发文档/1、需求/修改/images/2026-03-08-16-36-11.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/2026-03-08-16-47-03.png b/开发文档/1、需求/修改/images/2026-03-08-16-47-03.png deleted file mode 100644 index 0e6c2bfb..00000000 Binary files a/开发文档/1、需求/修改/images/2026-03-08-16-47-03.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/2026-03-08-16-47-11.png b/开发文档/1、需求/修改/images/2026-03-08-16-47-11.png deleted file mode 100644 index 59c150bf..00000000 Binary files a/开发文档/1、需求/修改/images/2026-03-08-16-47-11.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/2026-03-08-16-48-36.png b/开发文档/1、需求/修改/images/2026-03-08-16-48-36.png deleted file mode 100644 index 820c88a6..00000000 Binary files a/开发文档/1、需求/修改/images/2026-03-08-16-48-36.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/2026-03-08-17-09-33.png b/开发文档/1、需求/修改/images/2026-03-08-17-09-33.png deleted file mode 100644 index 5a6b2276..00000000 Binary files a/开发文档/1、需求/修改/images/2026-03-08-17-09-33.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/2026-03-08-17-10-32.png b/开发文档/1、需求/修改/images/2026-03-08-17-10-32.png deleted file mode 100644 index af310b88..00000000 Binary files a/开发文档/1、需求/修改/images/2026-03-08-17-10-32.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/2026-03-08-17-11-50.png b/开发文档/1、需求/修改/images/2026-03-08-17-11-50.png deleted file mode 100644 index 66228136..00000000 Binary files a/开发文档/1、需求/修改/images/2026-03-08-17-11-50.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/2026-03-08-17-13-34.png b/开发文档/1、需求/修改/images/2026-03-08-17-13-34.png deleted file mode 100644 index 6e5c7200..00000000 Binary files a/开发文档/1、需求/修改/images/2026-03-08-17-13-34.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/2026-03-08-17-14-04.png b/开发文档/1、需求/修改/images/2026-03-08-17-14-04.png deleted file mode 100644 index ca0b85f7..00000000 Binary files a/开发文档/1、需求/修改/images/2026-03-08-17-14-04.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/2026-03-08-17-15-30.png b/开发文档/1、需求/修改/images/2026-03-08-17-15-30.png deleted file mode 100644 index 71e956b2..00000000 Binary files a/开发文档/1、需求/修改/images/2026-03-08-17-15-30.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/2026-03-08-17-16-57.png b/开发文档/1、需求/修改/images/2026-03-08-17-16-57.png deleted file mode 100644 index ec3e0071..00000000 Binary files a/开发文档/1、需求/修改/images/2026-03-08-17-16-57.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/2026-03-08-17-17-25.png b/开发文档/1、需求/修改/images/2026-03-08-17-17-25.png deleted file mode 100644 index a9e8b98b..00000000 Binary files a/开发文档/1、需求/修改/images/2026-03-08-17-17-25.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/2026-03-09-04-36-17.png b/开发文档/1、需求/修改/images/2026-03-09-04-36-17.png deleted file mode 100644 index ebe6d3db..00000000 Binary files a/开发文档/1、需求/修改/images/2026-03-09-04-36-17.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/2026-03-09-04-37-35.png b/开发文档/1、需求/修改/images/2026-03-09-04-37-35.png deleted file mode 100644 index 35db7280..00000000 Binary files a/开发文档/1、需求/修改/images/2026-03-09-04-37-35.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/2026-03-09-04-38-20.png b/开发文档/1、需求/修改/images/2026-03-09-04-38-20.png deleted file mode 100644 index 8656d862..00000000 Binary files a/开发文档/1、需求/修改/images/2026-03-09-04-38-20.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/2026-03-09-04-42-08.png b/开发文档/1、需求/修改/images/2026-03-09-04-42-08.png deleted file mode 100644 index fdfe3da7..00000000 Binary files a/开发文档/1、需求/修改/images/2026-03-09-04-42-08.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/2026-03-09-04-46-02.png b/开发文档/1、需求/修改/images/2026-03-09-04-46-02.png deleted file mode 100644 index c7d9b287..00000000 Binary files a/开发文档/1、需求/修改/images/2026-03-09-04-46-02.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/2026-03-09-04-48-03.png b/开发文档/1、需求/修改/images/2026-03-09-04-48-03.png deleted file mode 100644 index fe0ec8c3..00000000 Binary files a/开发文档/1、需求/修改/images/2026-03-09-04-48-03.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/2026-03-09-04-49-01.png b/开发文档/1、需求/修改/images/2026-03-09-04-49-01.png deleted file mode 100644 index 373c090c..00000000 Binary files a/开发文档/1、需求/修改/images/2026-03-09-04-49-01.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/2026-03-09-04-50-16.png b/开发文档/1、需求/修改/images/2026-03-09-04-50-16.png deleted file mode 100644 index d958869b..00000000 Binary files a/开发文档/1、需求/修改/images/2026-03-09-04-50-16.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/2026-03-09-04-51-03.png b/开发文档/1、需求/修改/images/2026-03-09-04-51-03.png deleted file mode 100644 index 4f694777..00000000 Binary files a/开发文档/1、需求/修改/images/2026-03-09-04-51-03.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/2026-03-09-05-18-28.png b/开发文档/1、需求/修改/images/2026-03-09-05-18-28.png deleted file mode 100644 index 499f2111..00000000 Binary files a/开发文档/1、需求/修改/images/2026-03-09-05-18-28.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/2026-03-09-05-22-19.png b/开发文档/1、需求/修改/images/2026-03-09-05-22-19.png deleted file mode 100644 index 55deb595..00000000 Binary files a/开发文档/1、需求/修改/images/2026-03-09-05-22-19.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/2026-03-09-05-23-53.png b/开发文档/1、需求/修改/images/2026-03-09-05-23-53.png deleted file mode 100644 index 8cb4d840..00000000 Binary files a/开发文档/1、需求/修改/images/2026-03-09-05-23-53.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/2026-03-09-05-24-19.png b/开发文档/1、需求/修改/images/2026-03-09-05-24-19.png deleted file mode 100644 index 8ef20f12..00000000 Binary files a/开发文档/1、需求/修改/images/2026-03-09-05-24-19.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/2026-03-09-05-25-52.png b/开发文档/1、需求/修改/images/2026-03-09-05-25-52.png deleted file mode 100644 index 4d916e3b..00000000 Binary files a/开发文档/1、需求/修改/images/2026-03-09-05-25-52.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/2026-03-09-05-35-24.png b/开发文档/1、需求/修改/images/2026-03-09-05-35-24.png deleted file mode 100644 index f411da30..00000000 Binary files a/开发文档/1、需求/修改/images/2026-03-09-05-35-24.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/2026-03-09-05-36-51.png b/开发文档/1、需求/修改/images/2026-03-09-05-36-51.png deleted file mode 100644 index 55774621..00000000 Binary files a/开发文档/1、需求/修改/images/2026-03-09-05-36-51.png and /dev/null differ diff --git a/开发文档/1、需求/修改/images/image.png.png b/开发文档/1、需求/修改/images/image.png.png deleted file mode 100644 index d1f497a3..00000000 Binary files a/开发文档/1、需求/修改/images/image.png.png and /dev/null differ diff --git a/开发文档/1、需求/已完成/20260308找伙伴10.md b/开发文档/1、需求/已完成/20260308找伙伴10.md deleted file mode 100644 index b26ff90c..00000000 --- a/开发文档/1、需求/已完成/20260308找伙伴10.md +++ /dev/null @@ -1,16 +0,0 @@ - - -收复所有的错误,深度的理解,修复所有的错误,确保没有错误的运行 - -功能二 -image.png![](images/2026-03-08-16-48-36.png) -伙伴里面的这个匹配记录还加载还是失败,帮我分析并且处理一下这个问题。 - -功能一 -![](images/2026-03-08-16-47-03.png) -![](images/2026-03-08-16-47-11.png) - -存客宝场景api '/Users/karuo/Downloads/api_v1 (1).md'这个文档的内容也放到这个,放在这个存克宝里面,并且他要完善的实现这所有的那个场景获客的相关的内容,并且保证整个项目是正常运作的,以及获客的效率 - -这个存克保的这个功能,这标签是放到右上角,不是独立一个 type。然后这个找伙伴的这个里面的这一个,那个 AI 获客数据这里的话已提交线索跟有联系方式,这边是需要可以直接访问,那可以直接点击进入。点击进度,然后这个存克堡里面的相关的那个 TOKEN 和 API 的那个接口健全的东西是需要是可以直接使用的。需要是可以直接使用的,你把这个存克宝的那个。API 的那个格式,你帮我放到这个里面去。 -这个文档的内容也放到这个,放在这个存克宝里面,并且他要完善的实现这所有的那个场景获客的相关的内容,并且保证整个项目是正常运作的,以及获客的效率 \ No newline at end of file diff --git a/开发文档/1、需求/已完成/20260308找伙伴4.md b/开发文档/1、需求/已完成/20260308找伙伴4.md deleted file mode 100644 index 023e1019..00000000 --- a/开发文档/1、需求/已完成/20260308找伙伴4.md +++ /dev/null @@ -1,13 +0,0 @@ - - -功能三 匹配池 -![](images/2026-03-08-10-31-24.png) -匹配词里面的这个选择。匹配词里面的那个选,匹配词里面的这个选择,那可以,我可以点击的时候可以查看,比如我选匹配超级个体,我点击进去能看到具体有多少个人,然后完善资料用户有多少个人,然后全部无量词点击进去有多少人,这个是跟这个用户管理是打通的。 - -功能二 匹配功能 -小伙伴的这个功能里的那个标签,首先第一个标签是那个数据统计,第二个标签的话就是那个找伙伴,第三个标签是资源对接,第四个标签是导师预约,第五个标签是团队招募,然后把匹配词合并到匹配到找伙伴,匹配词跟匹配记录都合并到找伙伴的这个标签内。然后导师预约的那个导师管理那个加入到那个导师预约里面。 -![](images/2026-03-08-10-30-34.png) - -功能一 团队协助 -这一个待开发这一块的话,是写成这个文档存刻保的,这个待开发的发在放到这个开发文档的文档里面,咱们的那个项目管理的这个文档里面跟其他项目做对接的,不用写到代码以后,像这种都不要写在代码里面。确定了。 -![](images/2026-03-08-10-28-11.png) \ No newline at end of file diff --git a/开发文档/1、需求/已完成/20260308找伙伴5.md b/开发文档/1、需求/已完成/20260308找伙伴5.md deleted file mode 100644 index 8459c65b..00000000 --- a/开发文档/1、需求/已完成/20260308找伙伴5.md +++ /dev/null @@ -1,31 +0,0 @@ - -/Users/karuo/Documents/开发/3、自营项目/一场soul的创业实验-永平/开发文档/10、项目管理/项目落地推进表.md - -然后将这些所有的那个开发的进度文档以后,都是要在那个项目文档,让那个都要在这个项目管理里面实时的这个进度推进跟完成程度都要放到这个进度的推进表里面,确定整个的这个。整个的这个项目是正常的在运转正常的那个进度,然后把我们的对话,今天的一个对话和主要的那个修改的一个板块都到列成这个项目管理里面,清楚的知道开发的时候内容。检查所有的功能的完善性跟可行性,然后继续的全力的帮我检查清楚,然后最终那个完善这个着火的这个功能 - -功能五 前后端 -![](images/2026-03-08-10-59-57.png)然后我刚才在直接在小伙伴这里填写了那个团队招募的这个板块,这个团队招募的这个板块甜甜姐填写了手机,但是这个填写的手机,但是后台并没有显示,是不是那个加入团队,加入项目改成加入团队,但这个里面并没有给我手机,并没有反馈到这里来检查一下这个具体的一些问题。到底什么原因?然后帮我查看清楚具体的一个原因。那每次匹配的过程当中,这些内容都需要的是能直接到后台,能直接看到这个匹配的手机号,以及相应的一些人。请小程序端跟这个后台端得是互通的 - - -功能四 -![](images/2026-03-08-10-56-15.png) -匹配记录放到前面,放到匹配词的设置的前面。 -![](images/2026-03-08-10-58-04.png) -然后每一次匹配。每一次匹配的记录。抖音和用户匹配的用户跟记录都要放到这个相应的那个记录里面。都要放到相应的记录里面,并且这个发起人他是可以直接点击,可以点击和匹配到,可以点击直接看到这个链接的这个人的一个链接的一个形式,以及能看到发起人的一个手机号的一个这个联系方式。然后如果是多次的话,多次匹配到同一个,同比较短的时间,多次匹配到同一个人的情况,那你就直接的就把这个多次匹配的同一个人。多次匹配的同一个人合并成一个,并且有一个下拉可以直接看到匹配了多少个人。防止匹配记录列表非常的得多。队友发起的那个匹配到。 - - -功能三 匹配拉群,ai自动化添加和数据反馈 - -然后把这个找伙伴这边那个,我们把指定的用户跟新增的用户做一个自动化的一个模块,比如他刚刚匹配清楚的话,就是那个存客宝这边就来负责帮他拉群,这个先检查一下存客宝的一个功能,负责来拉群,然后拉群完只有把他的那个信息推送上去。那匹配的同时,匹配成功的同时就是纯科宝来加他,如果不是好友就直接加他,然后直接拉取把这个功能实现一下,然后包括那个找伙伴资源对接、导师预约跟团队招募这几个都需要,然后需要一开官司拉群的开关,还是那个匹配的拉群的开关。还是直接加好友发信息的一个开关,然后加好友发信,加好友发止境指定的的消息也是可以直接在这个后台同存克宝这边的接口部来对接,然后如果没有这些接口,直接通知存克宝那边的开发团队来进行操作。 - -功能二 找伙伴功能修复 -![](images/2026-03-08-10-46-02.png) -![](images/2026-03-08-10-47-24.png) -老伙伴的这个功能,点击查看用户进去,不是,点击进去又是 VIP 会员,超级个体,然后这个完善资料点击进去就是完善资料的用户全部流量词,应该百分之改一下到全部选择是全部用户,这几个分别要进去,然后用户的那个资料完善的要有这些,第二个选择要有这一些资料完善的才能在匹配池那个找伙伴里面去那个找到这些钥匙。实现这个功能在小程序上面的相应的这个功能就必须得实现。并且确保这个功能是可用的,帮我检查一下,确保是可用的 -这个功能前,在前端找伙伴匹配的时候,如果匹配过一次,嗯,就不要再匹配第二次了,就不要再出现就匹配过的当天匹配过一次的那就没有第二次了。这个确定清楚,这个功能要清晰一些 -小程序这端的那个创意合伙人改成找伙伴,小程序这端的那个创业合伙改成找伙伴的这个够名字。 - -功能一 修复 添加 -这里的话点击测试这个手机号,还是没有加到这个计划里面,帮我 查清楚的一个问题,确定清楚这个问题。请确保前端这个功能是可用的,后台测试也是可以添加的,帮我深度的检查清楚这些,处理掉这些问题image.png -![](images/2026-03-08-10-43-44.png) -![](images/2026-03-08-10-44-05.png) \ No newline at end of file diff --git a/开发文档/1、需求/已完成/20260308找伙伴6.md b/开发文档/1、需求/已完成/20260308找伙伴6.md deleted file mode 100644 index c1d158d4..00000000 --- a/开发文档/1、需求/已完成/20260308找伙伴6.md +++ /dev/null @@ -1,16 +0,0 @@ -拿着存克宝这边 API 显示的那个已存在的这个内容已存在,那这个已存在,像这里面的话只是不添加也要把这个表单添加到这个表单里面显示清楚,然后这个,嗯,下一步这里的话。把这些功能都给我完善清楚。 - -功能三 客户资源 -![](images/2026-03-08-11-19-38.png) - -![](images/2026-03-08-11-20-02.png) -就这个找伙伴的这一个功能,创业合伙这个要改成的就是找伙伴后台是修改什么样就是什么样的。然后这个团队招募这些图标跟那个相应的跟后台配置,后台配置是那个要相呼应是一样的创业合伙,这个叫找伙伴这个功能,然后点击加入到项目里面,填写手机号,得到后台上面去,后台也同时要显示这个标签,捆绑的同时要显示,比如说团队招募底下现在是没有添加任何的数据过来。这个有问题帮我检测一下,比如小程序这端跟这个跟后台不匹配,那其他的选项也是一样 -image.png![](images/2026-03-08-11-22-09.png)匹配记录,每一项里面都需要有匹配记录,然后也看一下这些匹配的那些相应的这些参数,帮我处理一下这个匹配的具体的一些数据。 - - -功能二 修复小程序匹配 -image.png![](images/2026-03-08-11-18-04.png) -这里的话那个资源对接,跟那个导师预约,跟团队招募这三个的那个匹配完之后,现在在小程序匹配完之后,现在并没有入库。的材料并没有入库,帮我处理一下一个问题,让我可以在后台能直接看到这个,那个匹配完之后的这个用户的联系形式,以及他的一个能点击进去能看到用户的一个旅程。那。 - -功能一 -![](images/2026-03-08-11-17-15.png)电池设置匹配词的那个来源是可以多多选的。可以同时选择两个,然后这个完整资料,完善资料的用户的话,这完善资料的用户点击进去不是全部用户,是真实有完善资料的,比如有名称、有头像,或者有其他的一些完善的一些材料,那基础的有这个应该是有手机号、有昵称、有头像的,然后有写业务需求的。就以跟线下,跟那个下面的那几个条件,符合这几个条件的一些用户的一个筛选,这是一个。 \ No newline at end of file diff --git a/开发文档/1、需求/已完成/20260308找伙伴7.md b/开发文档/1、需求/已完成/20260308找伙伴7.md deleted file mode 100644 index 8ace0dfc..00000000 --- a/开发文档/1、需求/已完成/20260308找伙伴7.md +++ /dev/null @@ -1,12 +0,0 @@ - -功能三 -![](images/2026-03-08-11-32-34.png) -![](images/2026-03-08-11-32-54.png)度的检查一下这个问题,这个点击链接卡路并没有到这个瘦的右上角,早卡路加好友这里的那个已获客,并没有增加这个正常的话以获客,我点击进去输入这里一定会增加,并且去添加的这里并没有增加。帮我分析一下这个问题,直接帮我处理掉 - -功能二 -我在小程序匹配了好几次,就这里面的所有的总匹配次数,包含资源对接,导致预约团队高木只要有点击的都是会算在总匹配次数里面,并且可以看到具体的那个匹配的那个情况,然后匹配次数跟今日匹配,这些匹配用庸俗都是可以直接点击进去这些页面,帮我补全点。点击进去可以看得到。 -![](images/2026-03-08-11-31-27.png) - -功能一 -![](images/2026-03-08-11-30-23.png) -人善知要用户指的是已经有那个从图片上传或者微信上传头像的,并且昵称不是叫微信用户的昵称的,有改过昵称的行为的,以及绑定信息有手机号的这一些,这个是完善资料的用户。 \ No newline at end of file diff --git a/开发文档/1、需求/已完成/20260308找伙伴8.md b/开发文档/1、需求/已完成/20260308找伙伴8.md deleted file mode 100644 index 50e48b06..00000000 --- a/开发文档/1、需求/已完成/20260308找伙伴8.md +++ /dev/null @@ -1,20 +0,0 @@ -检查所有的,把这一个尽全力的完善,并且测试这个功能可用,然后帮我完善这个整个的项目。并且测试这个项目的所有的功能可用。那个在本地先测试,不需要,先不要编译到那个服务器上面,直接在本地上进行修改和完善这些功能 - -功能四 -![](images/2026-03-08-16-18-08.png)同时处理一下早早伙伴匹配记录加载失败的这个问题,然后在这里的话,那个纯客跑的配置放到这里,嗯,右上角的这里,从数据统计这里,把它接口联通测试这边给他移动过去。从接口连通测试跟存保的这个的场景,然后存保这边的获客的数据是可以直接点击进去的,以及可以看这个存保的这个那个接口的这个文档,这些都是可以要能点击进去,可以看得到相应的联系方式的。 - - -功能三 -image.png![](images/2026-03-08-16-14-58.png)![](images/2026-03-08-16-15-14.png) -![](images/2026-03-08-16-15-31.png)那个加入项目有匹配,但是在后台那个团队招募这一个里面,并且并没有任何的数据,请帮我一定要处理一下这个问题,其他的板块也是出现这个情况。 - -功能二 存客宝 -然后还有一个比较重要的一个功能,就是存克保这边的那个有匹配完之后存克保这里的相应的动作,在这个找伙伴功能的右上角,这里的话有一个存克保,这里的添加的是否添加成功和存车保相应的那个配置,还有存车保的那个接口的联通测试这几个板块都到小伙伴那找伙伴的右上角的那个标签功能里面。然后把存车保这里的各个场景获客以及相应的接口的数据,比如添加成功,是否有回复率等等的这一些参数都放到这个找伙伴的这个功能里面。如果这个功能根据这些文档的存,相应的文档不能是没有功能的话,直接给存稿这边的开发团队那个提需求,那尽可能的去搜索,并且帮我整理出这个需求出来,然后帮我继续往下去去执行。同时的数据统计的首页的数据对,在清晰一些,整个界面帮我清晰那个大气一点,那不要太太拥挤,分类清楚一点。分类跟那个东西补全一下 -/Users/karuo/Documents/开发/2、私域银行/cunkebao_v3 -![](images/2026-03-08-16-02-09.png) - -功能一 匹配机制 -![](images/2026-03-08-15-58-20.png) -![](images/2026-03-08-15-59-01.png) -![](images/2026-03-08-15-59-53.png) -这个匹配记录里面的话,第一个的话是创业合伙的这一个板块是跟后台要相互呼应,这个是找伙伴,并且每一次匹配都需要到图片2的那个后台里面,真相应的那个板块后台。这里得有正常的显示,发起人跟匹配到这个得正常的显示上面的每一个板块都得是正常的显示出来,你先要阅读完图片这几个所有的板块,那也有匹配,就要记录次数以及匹配相应的那个功能,就要记录到这个里面,然后把这个。然后在这个。今日匹配。的那个数据,这一些匹配的都是一些和这个相关的一些数据,已经匹配的类型也是相关的那个数据。更重要的是就是有点击这个用户的那个数据匹配数据,就立即要在这个后台这边显示清楚了,不然现在一直都是空的,帮我看一下具体是什么情况。那一定要帮我处理掉这个问题 \ No newline at end of file diff --git a/开发文档/1、需求/已完成/20260308找伙伴9md b/开发文档/1、需求/已完成/20260308找伙伴9md deleted file mode 100644 index befef6b2..00000000 --- a/开发文档/1、需求/已完成/20260308找伙伴9md +++ /dev/null @@ -1,25 +0,0 @@ - - -收复所有的错误,深度的理解,修复所有的错误,确保没有错误的运行 - - - -功能六 -![](images/2026-03-08-16-36-11.png)那个首页的找伙伴里面的创业合伙人这个功能显示的是找伙伴的这个功能,并且这些在这个标签的名字在后台都是可以设置的,设置他们名称这个是叫找伙伴的功能,图标跟名字都可以在后台配置。把这个名字帮我改一下,并且这个选项跟后台的找伙伴的功能的选项是一定要是相呼应的,点击就要确定好,你深度的帮我理解和检查清楚这个,帮我解决这些所有的问题 - -功能五 -![](images/2026-03-08-16-34-58.png)的这几个选项都要可以添加的乘客宝的一个获客数据,就是不要写乘客宝,就是一个那个 AI 获客数据,那第一个的话是那个 AI 那个7KB 去掉就是已提交线索,就是三个,第二个有联系方式的就是三个。第一个的话是 AI 添加的程度,那点击进去的话就是看到 AI 添加的一个成功率以及回复率的这一些功能。然后把这个联系方式比例去掉,API 连接的这一个说明文档得可以点开,并且可以编辑这个 API 连接的这个文档。 - -功能四 -![](images/2026-03-08-16-33-49.png)把这个匹配收收益,匹配收益这个也帮我把这个同时也在首页的数据概览上里面显示。 - -功能三 -这个后台各个的匹配记录帮我测试清楚,并且看一下后台真正的匹配的这些匹配记录,刚刚有匹配的记录之后,帮我加到这个匹配记录团队,招募也好,导师预约也好,资源对接也好,匹配记录务必不要显示的人人零条,务必要有相应的那个数据显示出来。也帮我测试一下那个,帮我加几个电话号码进去。 - -功能二 存客宝 -image.png![](images/2026-03-08-16-32-02.png)所有的那个相应的接口跟功能跟场景获客的一个成功率的所有的东西不单单是测试,然后它也是一个独立的页面,不用,不是展开页。宝的描述跟需求,帮我把这个页面完善一下。阅读关于淳刻薄的所有描述跟需求,我们对话当中 - - -功能一 -![](images/2026-03-08-16-30-11.png) -![](images/2026-03-08-16-31-01.png)小伙伴的这个页面的话,匹配记录加载失败,加载有问题,帮我处理一下这个加载失败的这一个问题。那个皮,那个匹配词设置的话,那个匹配词的选择,这个完善资料的用户点击进去只有3个人的,实际只有3个人,但点击进去有很多他是全部用户的一个列表,这个帮我解读一下。 \ No newline at end of file diff --git a/开发文档/1、需求/已完成/20260308找伙伴功能.pdf b/开发文档/1、需求/已完成/20260308找伙伴功能.pdf deleted file mode 100644 index 30c1bd22..00000000 Binary files a/开发文档/1、需求/已完成/20260308找伙伴功能.pdf and /dev/null differ diff --git a/开发文档/1、需求/已完成/20260308找伙伴功能2.md b/开发文档/1、需求/已完成/20260308找伙伴功能2.md deleted file mode 100644 index 1f7159c0..00000000 --- a/开发文档/1、需求/已完成/20260308找伙伴功能2.md +++ /dev/null @@ -1,36 +0,0 @@ -# 需求文档标题 - -> 创建日期:YYYY-MM-DD -> 文档格式:Markdown(支持图片粘贴 + 预览) - ---- - -## 一、背景与目标 - -(在此输入文字,可直接粘贴图片) - ---- - -## 二、功能点 - -### 2.1 功能一 - - - -示例图片引用:`![描述](./images/截图1.png)` - -### 2.2 功能二 - ---- - -## 三、补充说明 - -(可继续粘贴图片和文字) - ---- - -## 使用提示 - -- **粘贴图片**:在 Cursor 中安装「Paste Image」扩展后,直接 Ctrl+V / Cmd+V 即可将剪贴板图片保存到 `images/` 并自动插入引用 -- **预览**:`Cmd+Shift+V` 或右侧「Open Preview」查看排版效果 - diff --git a/开发文档/1、需求/已完成/20260308找伙伴功能3.md b/开发文档/1、需求/已完成/20260308找伙伴功能3.md deleted file mode 100644 index 7dc91ae2..00000000 --- a/开发文档/1、需求/已完成/20260308找伙伴功能3.md +++ /dev/null @@ -1,16 +0,0 @@ - - -那个完成,并且帮我完整的完善这些功能,并且帮我那个整理清楚确保所有的功能是通的、可用的 - -功能三 找伙伴-存客宝 -![](images/2026-03-08-10-21-19.png) -然后这边存客宝的统计的话,就是这个匹配次数和匹配的用户和匹配的那个收益都写清楚,然后存客宝这边接口的一个一个的一些相应的这个功能测试完之后,比如这个接口这边的那个测试完之后,点击链接到卡洛,我点测试就可以添加一个测试的一个那个手机号。就我这个后台的这个用户的测试手机号,直接添加到这个指定的这个计划里面去所有的这个乘客宝接口联通测试这里有话都是需要去做这个方面的一个事情,并且我可以直接点击,然后那个包括那个匹配上报的这些功能。乘客那个找我们。那个,这个是属于那个数据统计匹配的数据统计,然后把纯科宝统计放到匹那个匹配词的那个前面,匹配词的标签前面,它是。然后把名字改成就是那个找伙伴统计,找伙伴的那个数据统计,然后把这个数据跟这几个标签做一个那个深度的一个融合,把这个数据统计的更清晰一些。然后这一些,把所有的这一些数据弄清楚,然后现有的能填充的数据已经有了,这个数据帮我完善清楚。 - -功能二 点击获客 -这个匹配词是可以让我随机让我找到那个匹配的这个里面的这个功能的,就筛选这个用户跟这个用户管理是打通的,有一个标签的一个选择找伙伴的这个功能。然后。然后不管是资源对接,还是导师预约,还是团队招募,这里面有人点击了和填写手机号了,这一个都是直接显示在这个页面下面的,并且直接触发纯课宝的添加,并且有纯课宝这边添加的一个成功率,这个纯课宝留存个宝这边的那个接口了,来负责那个整个的一个功能的一些完善。就把这一个,然后现有的那些数据,现有的这些数据有相关的,就直接把这个相关的数据帮我那个分析,并且导入到这个内容里面来。老路上这个内容里面的,然后把这个。把这个。的匹配到,然后联系方式,然后这里面的那个字段,除了发起人匹配到跟联系方式这一些这几个选项里面的一些功能和内容,还是需要那个有实际的添加,纯推广那边要有反馈的那个数据添加到哪一个接口里面,由这个场景获客的那个接口,有场景获客的那个接口都需要那个完善。都需要回馈一下数据,然后这个如果当前现在改不了,要把这个需求需要协作的存好,协作的需求做一个登记和记录,到时候要发给存客宝去做修改。以后我像这类型的需要纯客房跟那个神射手协助的需求都需要这么去操作 -![](images/2026-03-08-10-17-14.png)![](images/2026-03-08-10-18-28.png) - - -功能一 匹配池 -找伙伴的这个功能底下的话,要那个匹配的那个用户词要选择,可以选择那个超级个体付费1980的会员,然后也可以选择第二个选择的,这是一个流量词,第二个选择的流量词就是我们的那个在这边这里的话要写匹配那个词,里面要可以选择这一块。然后也可以选择那个完善程度的,比如已经完善了手机,那个手机密码,那不,手机,然后那个昵称和图标的用户,并且有写那个一人工写他的具体的一些业务的需求,完善的会员的材料的用户才可以去匹配掉,匹配到。他都吃完了,他都吃完了 -![](images/2026-03-08-10-08-47.png) \ No newline at end of file diff --git a/开发文档/1、需求/已完成/20260308用户管理.md b/开发文档/1、需求/已完成/20260308用户管理.md deleted file mode 100644 index 1f7159c0..00000000 --- a/开发文档/1、需求/已完成/20260308用户管理.md +++ /dev/null @@ -1,36 +0,0 @@ -# 需求文档标题 - -> 创建日期:YYYY-MM-DD -> 文档格式:Markdown(支持图片粘贴 + 预览) - ---- - -## 一、背景与目标 - -(在此输入文字,可直接粘贴图片) - ---- - -## 二、功能点 - -### 2.1 功能一 - - - -示例图片引用:`![描述](./images/截图1.png)` - -### 2.2 功能二 - ---- - -## 三、补充说明 - -(可继续粘贴图片和文字) - ---- - -## 使用提示 - -- **粘贴图片**:在 Cursor 中安装「Paste Image」扩展后,直接 Ctrl+V / Cmd+V 即可将剪贴板图片保存到 `images/` 并自动插入引用 -- **预览**:`Cmd+Shift+V` 或右侧「Open Preview」查看排版效果 - diff --git a/开发文档/1、需求/已完成/20260308用户管理2.md b/开发文档/1、需求/已完成/20260308用户管理2.md deleted file mode 100644 index 0c619d29..00000000 --- a/开发文档/1、需求/已完成/20260308用户管理2.md +++ /dev/null @@ -1,39 +0,0 @@ -# 需求文档标题 - -> 创建日期:YYYY-MM-DD -> 文档格式:Markdown(支持图片粘贴 + 预览) - ---- - -## 一、背景与目标 - -(在此输入文字,可直接粘贴图片) - - - ---- - -## 二、功能点 - -### 2.1 功能一 - -(文字 + 可粘贴的截图、原型图) - -示例图片引用:`![描述](./images/截图1.png)` - -### 2.2 功能二 - - - ---- - -## 三、补充说明 - -(可继续粘贴图片和文字) - ---- - -## 使用提示 - -- **粘贴图片**:在 Cursor 中安装「Paste Image」扩展后,直接 Ctrl+V / Cmd+V 即可将剪贴板图片保存到 `images/` 并自动插入引用 -- **预览**:`Cmd+Shift+V` 或右侧「Open Preview」查看排版效果 diff --git a/开发文档/1、需求/已完成/README_需求文档格式说明.md b/开发文档/1、需求/已完成/README_需求文档格式说明.md deleted file mode 100644 index f403efe0..00000000 --- a/开发文档/1、需求/已完成/README_需求文档格式说明.md +++ /dev/null @@ -1,75 +0,0 @@ -# 需求文档格式说明 - -> 本目录支持 **Markdown(.md)** 格式,可在 Cursor 中直接粘贴图片并预览。 - ---- - -## 为什么用 Markdown - -| 能力 | 说明 | -|:-----------|:-------------------------------------------------| -| 粘贴图片 | 配合扩展可 Ctrl+V / Cmd+V 直接粘贴剪贴板图片 | -| 预览 | Cursor 内置 Markdown 预览,`Cmd+Shift+V` 即可 | -| 版本管理 | 纯文本 + 图片文件,方便 Git 追踪 | -| 跨平台 | 任意编辑器可编辑,导出 PDF/HTML 也方便 | - ---- - -## 使用方法 - -### 1. 新建文档 - -- 复制 `_模板_需求文档.md`,重命名为你的文档名(如 `20260308找伙伴功能.md`) -- 或直接新建 `.md` 文件 - -### 2. 粘贴图片 - -**方式一:配合扩展(推荐)** - -1. 在 Cursor 中安装扩展:`Paste Image` 或 `Markdown Paste` -2. 截屏或复制图片到剪贴板 -3. 在 `.md` 文件中按 `Ctrl+V`(Mac:`Cmd+V`) -4. 扩展会自动将图片保存到 `images/` 并插入 `![描述](images/xxx.png)` - -**方式二:手动** - -1. 将图片放入本目录下的 `images/` 文件夹 -2. 在文档中插入:`![图片描述](./images/文件名.png)` - -### 3. 预览 - -- **快捷键**:`Cmd+Shift+V`(Mac)或 `Ctrl+Shift+V`(Windows) -- **右键**:编辑器内右键 → 「Open Preview」 -- 卡若AI 规则已配置 Markdown Preview Enhanced,可直接查看排版 - ---- - -## 目录约定 - -``` -修改/ -├── README_需求文档格式说明.md ← 本说明 -├── _模板_需求文档.md ← 可复制的模板 -├── images/ ← 粘贴的图片存放于此 -│ └── .gitkeep -├── 20260308找伙伴功能.md ← 你的需求文档 -└── *.pdf / *.pages ← 仍可保留原格式作归档 -``` - ---- - -## 扩展安装(如需粘贴图片) - -在 Cursor 扩展市场搜索并安装其一: - -- **Paste Image**:`naumovs.paste-image` -- **Markdown Paste**:支持粘贴图片并生成 Markdown 引用 - -**Paste Image 路径配置**(可选):在 `settings.json` 中添加,使图片保存到当前目录的 `images/` 下: - -```json -{ - "pasteImage.path": "${currentFileDir}/images", - "pasteImage.basePath": "${currentFileDir}" -} -``` diff --git a/开发文档/1、需求/需求日志 b/开发文档/1、需求/需求日志 deleted file mode 100644 index fb51815d..00000000 --- a/开发文档/1、需求/需求日志 +++ /dev/null @@ -1,9 +0,0 @@ -20260223 - -那个在我的里面,我的足迹里面最近阅读的这个章节要写清楚章节的那个名称,小杰的名称得写上去。然后这个。推广中心改成我的收益,然后把这个推广中心我的收益,然后上面显示的是我的收益有多少钱?把推广中心这一个我的收益改到这个界面,就名昵称的下方购买章节推荐函好友,然后那个带领收益,这个改成我的收益,然后把推广中心去掉,然后把账号设置。账号设置。也移到这个,我的那个资料的那个里面,这个界面上面。精选队推荐这边的话,首页上精选推荐,这里选择的是后端的那个文章的那个阅读量,文章的阅读量,然后把这个文章的相应的那个阅读做一个阅读的一个点击的一个记录,后台文章得有一个点击的一个记录。然后把手页里面的这个内容预览去掉,首页内容预览去掉,这个就是只有一个目录。只有一个目录,然后这边的话是一个那个。内容预览去掉,改成首页,上面改成那个有名字的,有填写名字的和联系方式的,是那个。创业老板排行,然后显示一排带头像、带图标、带名字的显示一排。四个显示一排是有名字跟图像,那后鼠标然后点击进去的话,就是它的一个详细材料,就优秀会员的一个板块。 - -然后在一个主要就是他就是那个管理开发文档的用的,然后把整个那个开发文档直至保留这个10个目录。开发文档只有这4个目录,其他的文件文档就整合到这个10个目录底下,然后这个 skill 还需要整理的一个内容,就是把每一次我们对话提问的一个需求放到一个那个需求的表里面,那我知道每天这个更改的和我们对话的更改的那个季度的一个需求。把这个提示词对话的内容整理一下放到里面,那需要有具体的时间的节点往下去开发。 - -在后台里面你新增一个会员的一个填写的一个表格,购买完之后会员的权利还可以被匹配,以及那个就一年365天的一个权利吗?然后这个365天的权利可以看所有的章节,然后可以有匹配所有的那些客户,我让别人能知道你的项目的一个业务情况。然后。这个就变成一个 VIP 的一个选项,也是在增加会员的话,就是头像就不一样,正常就是你的头像在我的里面,头像是灰色的,那会员 VIP 的一个框框是灰色的,那点击之后进去就是会变成那个 VIP 亮色的一个头像出来 - -然后帮我把这一版那个。最终要实现这个小程序跟后端是匹配的,以及数据是匹配的一个情况,最终上传上去可以保证整个网站是可以正常使用,确保在正常使用的情况下来做优化和迭代。然后 \ No newline at end of file diff --git a/开发文档/1、需求/需求汇总.md b/开发文档/1、需求/需求汇总.md deleted file mode 100644 index 190e197c..00000000 --- a/开发文档/1、需求/需求汇总.md +++ /dev/null @@ -1,39 +0,0 @@ -# 需求汇总(合并自 业务需求、技术需求、需求方案汇总、需求日志、卡若角色设定) - -## 业务需求 - -项目目标、成本、技术要求(见原业务需求、技术需求)。 - -## 需求方案 - -Soul 创业派对整体定位、闭环、用户画像;小程序改造与迭代、已修复问题、已完成功能、配置与上线检查。详见原需求方案汇总。 - -## 需求日志 - -日常需求变更记录(见原需求日志)。 - -## 卡若角色设定 - -IP 设定、风格、输出规范(见原卡若角色设定)。 - ---- - -## 需求清单(来自 cursor_1_14 与永平落地) - -| 日期 | 描述 | 状态 | 备注 | -|------|------|------|------| -| 2026-02 | 内容管理页仅保留「API 接口」按钮 | 已完成 | soul-admin ContentPage 源码改造 | -| 2026-02 | 侧栏与分销页「交易中心」→「推广中心」 | 已完成 | AdminLayout、DistributionPage | -| 2026-02 | 推广中心/我的收益:绑定中、已付款、已过期清晰展示 | 已有 | referral 页数据结构支持 | -| 2026-02 | 海报小程序码带用户 ID(scene ref=userId) | 已完成 | referral.js generatePoster | -| 2026-02 | 复制朋友圈文案去掉「专属邀请码」展示 | 已完成 | 海报上去掉邀请码文案 | -| 2026-02 | 我的页:待领收益→我的收益、头像/昵称/ID 一键获取 | 已有/已完成 | my.wxml 文案统一 | -| 2026-02 | 设置页:手机/微信号一键获取、自动提现默认开启 | 已有 | settings.js | -| 2026-02 | 后台与前台参数一致(绑定有效期、自动提现、免费章节等) | 已检查 | 推广设置、系统设置已对齐 | -| 2026-02 | 找伙伴匹配后台用户库、资源对接两步(能帮什么/需要什么) | 已有 | match 页与后端 /api/match | -| 2026-02 | VIP 手动设置 + 支付设置 + 日志(区分来源、订单号) | 已完成 | 用户详情弹窗、支付回调、db/miniprogram handler | -| 2026-02 | 管理端设置 VIP 必填到期日 | 已完成 | 前后端校验 | -| 2026-02 | 会员订单分润差异化(会员 20% / 非会员 10%) | 已完成 | 技术分析见 临时需求池/分润需求-技术分析.md;computeOrderCommission;推广设置页增加会员分润配置 | -| 2026-02 | VIP 设置入口拆分:用户列表「设置 VIP」按钮 + 独立弹窗 | 已完成 | UserDetailModal 移除 VIP 区块;SetVipModal 独立 | -| 2026-02 | VIP 排序:后付款/后设置在前;支持手动排序 | 已完成 | vip_activated_at、vip_sort;VipMembers 排序逻辑 | -| 2026-02 | VIP 角色:可选择 + 可手动填写 | 已完成 | vip_roles 表;VIP 角色管理页;SetVipModal 角色下拉 | diff --git a/开发文档/2、架构/Gin技术栈-Go1.25依赖清单.md b/开发文档/2、架构/Gin技术栈-Go1.25依赖清单.md deleted file mode 100644 index 696456fc..00000000 --- a/开发文档/2、架构/Gin技术栈-Go1.25依赖清单.md +++ /dev/null @@ -1,120 +0,0 @@ -# Gin 技术栈依赖清单(适配 Go 1.25.7) - -**目标版本**:Go 1.25.7 -**原则**:精简、高效、易上手、好用、安全;所有依赖均兼容 Go 1.25,无需更换或移除。 - ---- - -## 一、Go 版本说明 - -- Go 1.25 于 2025 年 8 月发布,遵守 Go 1 兼容性承诺,现有主流库均可使用。 -- **Gin** 官方要求 Go 1.24+,1.25.7 满足要求。 -- **golang.org/x/\***(crypto、time 等)随 Go 工具链维护,支持当前稳定版。 -- 若某依赖未显式声明支持 1.25,只要其 `go.mod` 为 `go 1.21` 或更高,在 1.25 下均可正常编译使用。 - ---- - -## 二、依赖列表(均适配 Go 1.25.7) - -### 1. 核心与数据库 - -| 依赖 | 版本建议 | 说明 | -|------|----------|------| -| `github.com/gin-gonic/gin` | 最新 v1.x | 要求 Go 1.24+,1.25.7 兼容。 | -| `gorm.io/gorm` | 最新 v1.31.x | 无对高版本 Go 的限制。 | -| `gorm.io/driver/mysql` | 最新 | 与 GORM 配套。 | - -### 2. 安全 - -| 依赖 | 版本建议 | 说明 | -|------|----------|------| -| `github.com/unrolled/secure` | v1.17+ | 标准 net/http 中间件,兼容 Go 1.25。 | -| `golang.org/x/crypto` | 最新 | 使用 `bcrypt` 等,随 Go 生态更新。 | -| `golang.org/x/time` | 最新 | 使用 `rate` 限流,兼容 Go 1.25。 | - -### 3. 配置 - -| 依赖 | 版本建议 | 说明 | -|------|----------|------| -| `github.com/joho/godotenv` | v1.5.x | 仅读 .env,无高版本 Go 要求。 | -| 或 `github.com/caarlos0/env/v11` | v11.x | 解析 env 到结构体,兼容当前 Go。 | - -### 4. 跨域与鉴权 - -| 依赖 | 版本建议 | 说明 | -|------|----------|------| -| `github.com/gin-contrib/cors` | v1.6+(务必 ≥1.6,修复 CVE) | 与 Gin 1.24+ / Go 1.25 兼容。 | -| `github.com/golang-jwt/jwt/v5` | 最新 v5.x | 推荐 v5,与 Go 1.25 兼容。 | - -### 5. 接口文档(可选) - -| 依赖 | 版本建议 | 说明 | -|------|----------|------| -| `github.com/swaggo/swag/cmd/swag` | 最新(CLI 工具) | 代码生成,使用最新 CLI 即可。 | -| `github.com/swaggo/gin-swagger` | 最新 | 与 Gin 配套。 | -| `github.com/swaggo/files` | 最新 | Swagger UI 静态资源。 | - -### 6. 开发工具(仅开发环境) - -| 依赖 | 版本建议 | 说明 | -|------|----------|------| -| `github.com/cosmtrek/air` | 最新 | 热重载,与 Go 1.25 兼容。 | - ---- - -## 三、无需更换或移除 - -- 上述依赖在 Go 1.25.7 下**均无需更换或移除**。 -- 未列入的冗余依赖(如单独再引入 validator、Viper、zap 等)按此前「精简版」建议已不纳入,无需因 Go 1.25 再改。 - ---- - -## 四、推荐 go.mod 片段(Go 1.25) - -在项目根目录执行: - -```bash -go mod init soul-server -go mod edit -go=1.25 -``` - -然后按需拉取依赖(示例): - -```bash -go get github.com/gin-gonic/gin -go get gorm.io/gorm gorm.io/driver/mysql -go get github.com/unrolled/secure -go get golang.org/x/crypto golang.org/x/time -go get github.com/gin-contrib/cors -go get github.com/golang-jwt/jwt/v5 -go get github.com/joho/godotenv -# 可选 -go get github.com/swaggo/gin-swagger github.com/swaggo/files -# 开发 -go install github.com/cosmtrek/air@latest -go install github.com/swaggo/swag/cmd/swag@latest -``` - ---- - -## 五、验证方式 - -在 soul-server 目录下执行: - -```bash -go mod tidy -go build ./... -``` - -若通过,则当前依赖与 Go 1.25.7 兼容。若某库报错,优先升级该库至最新 minor/patch 再试。 - ---- - -## 六、小结 - -| 项目 | 结论 | -|------|------| -| Go 1.25.7 | 支持,所有推荐依赖均适用。 | -| 需要更换的依赖 | 无。 | -| 需要移除的依赖 | 无(按本清单与精简原则已不包含不必要项)。 | -| 建议 | 使用 `go 1.25`,定期 `go get -u ./...` 与 `go mod tidy` 保持依赖健康。 | diff --git a/开发文档/2、架构/soul-api技术栈.md b/开发文档/2、架构/soul-api技术栈.md deleted file mode 100644 index 2a479f92..00000000 --- a/开发文档/2、架构/soul-api技术栈.md +++ /dev/null @@ -1,54 +0,0 @@ -# soul-api Go 技术栈 - -## 语言与运行时 - -- **Go 1.25** - -## Web 框架与 HTTP - -- **Gin**(`github.com/gin-gonic/gin`):HTTP 路由与请求处理 -- **gin-contrib/cors**:跨域 -- **unrolled/secure**:安全头(HTTPS 重定向、HSTS 等,在 `middleware.Secure()` 中使用) - -## 数据层 - -- **GORM**(`gorm.io/gorm`):ORM -- **GORM MySQL 驱动**(`gorm.io/driver/mysql`):连接 MySQL -- **go-sql-driver/mysql**:底层 MySQL 驱动(GORM 间接依赖) - -## 微信生态 - -- **PowerWeChat**(`github.com/ArtisanCloud/PowerWeChat/v3`):微信开放能力(小程序、支付、商家转账等) -- **PowerLibs**(`github.com/ArtisanCloud/PowerLibs/v3`):PowerWeChat 依赖 - -## 配置与环境 - -- **godotenv**(`github.com/joho/godotenv`):从 `.env` 加载环境变量 -- 业务配置集中在 `internal/config`,通过 `config.Load()` 读取 - -## 鉴权与安全 - -- **golang-jwt/jwt/v5**:管理端 JWT 签发与校验(`internal/auth/adminjwt.go`) -- 管理端路由使用 `middleware.AdminAuth()` 做 JWT 校验 - -## 工具与间接依赖 - -- **golang.org/x/time**:时间/限流相关(如 `rate`) -- **gin-contrib/sse**:SSE(Gin 间接) -- **bytedance/sonic**:JSON 编解码(Gin 默认) -- **go-playground/validator**:请求体校验(Gin 的 `ShouldBindJSON` 等) -- **redis/go-redis**:仅在依赖图中出现(PowerWeChat 等间接引入),项目代码中未直接使用 Redis - -## 项目结构(技术栈视角) - -| 层级 | 技术/约定 | -|----------|------------| -| 入口 | `cmd/server/main.go`,标准库 `net/http` + Gin | -| 路由 | `internal/router`,Gin Group(`/api`、`/admin`、`/miniprogram` 等) | -| 中间件 | CORS、Secure、限流(`middleware.RateLimiter`)、管理端 JWT | -| 业务逻辑 | `internal/handler`,GORM + `internal/model` | -| 数据访问 | `internal/database` 提供 `DB() *gorm.DB`,统一用 GORM | -| 微信相关 | `internal/wechat`(小程序、支付、转账等封装) | -| 开发工具 | `.air.toml` 热重载、Makefile | - -整体上是一个 **Gin + GORM + MySQL + 微信 PowerWeChat + JWT 管理端鉴权** 的 Go 后端,面向小程序与管理端 API。 diff --git a/开发文档/2、架构/系统与技术.md b/开发文档/2、架构/系统与技术.md deleted file mode 100644 index e244edb3..00000000 --- a/开发文档/2、架构/系统与技术.md +++ /dev/null @@ -1,15 +0,0 @@ -# 系统与技术(合并自 系统架构、技术选型与全景图、前后端架构分离策略、数据库) - -## 核心理念 - -** separation**:内容与代码分离、前后端分离、静态与动态分离。架构围绕「省事」和「变现」。 - -**技术栈**:Next.js 14/16 App Router、TypeScript、Tailwind、Shadcn UI、Zustand、MySQL/MongoDB、Vercel/宝塔部署。 - -**内容即产品**:`book/` Markdown 为资产,Git 管理,文件系统读取。 - -**数据库**:见 `数据库.md`,表结构、连接配置。 - -## 前后端架构分离 - -开发协作规范、API 边界、部署拆分策略。 diff --git a/开发文档/2、架构/链路与变现.md b/开发文档/2、架构/链路与变现.md deleted file mode 100644 index 011a24b1..00000000 --- a/开发文档/2、架构/链路与变现.md +++ /dev/null @@ -1,19 +0,0 @@ -# 链路与变现(合并自 链路优化与运行指南、变现模块设计) - -## 链路总览 - -``` -后台鉴权 → 进群(支付后跳转) → 营销策略(推广/活码/配置) → 支付(下单→回调→到账) -``` - -**运行**:`pnpm dev` 或 `pnpm build` + `node .next/standalone/server.js`,端口 3006。 - -**配置**:`GET /api/config` 拉取配置,admin / key123456 鉴权,登出 `POST /api/admin/logout`。 - -## 变现模块 - -- **支付模块**:Order、PaymentProvider,微信/支付宝对接 -- **营销模块**:Campaign、MarketingService,弹窗、Banner、转化 -- **分销模块**:ReferralCode、ReferralService,邀请码、佣金计算 - -详见原《链路优化与运行指南》《变现模块设计》。 diff --git a/开发文档/3、原型/原型设计规范.md b/开发文档/3、原型/原型设计规范.md deleted file mode 100644 index d3a604c6..00000000 --- a/开发文档/3、原型/原型设计规范.md +++ /dev/null @@ -1,575 +0,0 @@ -# 原型设计规范 - -**我是卡若。** - -这个文档是写给设计师和前端开发看的。咱们的项目特点很明确:**移动端优先,iOS风格,极致阅读体验**。 - ---- - -## 一、设计原则 - -### 1.1 移动端优先 -- 90%的用户是从微信、Soul、朋友圈进来的,都是手机 -- 设计稿必须先出手机版,再适配PC -- 断点设置:375px (iPhone SE) / 414px (iPhone 14 Pro Max) - -### 1.2 iOS风格 -- 圆角:16px / 20px / 24px (统一使用这3个值) -- 阴影:`box-shadow: 0 4px 12px rgba(0,0,0,0.08)` -- 字体:San Francisco (iOS) / PingFang SC (安卓) -- 间距:8px的倍数系统 (8 / 16 / 24 / 32 / 48) - -### 1.3 简洁至上 -- 每个页面只有1个主要操作按钮 -- 减少选择,降低决策成本 -- 文字能说清楚的,就别用图 - ---- - -## 二、核心页面原型 - -### 2.1 首页 (Home) - -**功能目标**: 3秒内让用户知道这是什么书,并产生购买欲望 - -**布局结构**: -\`\`\` -[Hero区域] -- 书籍封面 (3D效果) -- 标题:《一场Soul的创业实验》 -- 副标题:真实的商业案例库 -- 作者:卡若 -- 价格标签:¥9.9 (限时优惠) -- 主按钮:立即阅读 - -[数据统计卡片] -- 已购买人数: 128人 -- 阅读人次: 1,234次 -- 好评率: 98% - -[最新章节快捷入口] -- 横向滚动卡片 -- 每张卡片显示:章节号 + 标题 + 标签(免费/付费) - -[Soul派对群推广横幅] -- 背景:渐变色 -- 文案:每天早上6-9点,Soul派对房不见不散 -- 按钮:加入派对 - -[底部导航栏] -- 首页 | 目录 | 我的 -\`\`\` - -**交互细节**: -- 向下滚动时,顶部导航栏自动隐藏 -- 点击书籍封面,可放大预览 -- 点击"立即阅读",跳转到目录页 - -**设计稿尺寸**: 375x812 (iPhone X) - ---- - -### 2.2 目录页 (Chapters) - -**功能目标**: 清晰展示书籍结构,引导用户阅读 - -**布局结构**: -\`\`\` -[顶部] -- 返回按钮 -- 标题:目录 -- 全书购买按钮 - -[篇章结构] -第一篇 | 真实的人 - ├─ 第1章 | 人与人之间的底层逻辑 - │ ├─ 1.1 自行车荷总... [免费] - │ ├─ 1.2 老墨... [1元] [锁] - │ └─ ... - ├─ 第2章 | 人性困境案例 - │ └─ ... - -第二篇 | 真实的行业 - └─ ... -\`\`\` - -**视觉设计**: -- 篇章标题:粗体,16px,品牌色渐变 -- 章节标题:常规,14px,深灰色 -- 免费标签:绿色小标签 -- 付费标签:橙色小标签 + 锁图标 -- 定时解锁:灰色小标签 + 倒计时 - -**交互细节**: -- 点击免费章节,直接进入阅读 -- 点击付费章节,弹出购买弹窗 -- 点击已购买章节,进入阅读 -- 长按章节,可以分享给好友 - ---- - -### 2.3 阅读页 (Read) - -**功能目标**: 沉浸式阅读体验,零干扰 - -**布局结构**: -\`\`\` -[顶部工具栏] (可隐藏) -- 返回按钮 -- 进度条 (当前位置/总长度) -- 目录按钮 - -[正文区域] -- 标题 -- 作者 + 发布时间 -- Markdown渲染内容 - - 标题层级 - - 段落 - - 引用块 - - 代码块 - - 图片 - - 列表 - -[底部工具栏] (可隐藏) -- 上一章 -- 目录按钮 -- 下一章 -- 分享按钮 -\`\`\` - -**视觉设计**: -- 字体大小:16px (可调) -- 行高:1.8 -- 段落间距:24px -- 左右边距:24px -- 背景:#FAFAFA (浅灰) 或 #1C1C1E (深色模式) - -**交互细节**: -- 点击屏幕中央,显示/隐藏工具栏 -- 向上滚动,自动隐藏工具栏 -- 阅读到30%时,弹出"扫码解锁全文"弹窗 -- 阅读完成,自动跳转到下一章 - ---- - -### 2.4 我的页面 (My) - -**功能目标**: 用户中心 + 分销中心 - -**布局结构**: -\`\`\` -[用户信息卡片] -- 头像 -- 昵称 -- 手机号 -- 我的邀请码:REFXXXX (点击复制) - -[阅读统计] -- 已购买章节: 12章 -- 阅读时长: 3小时28分 -- 阅读进度: 45% - -[分销中心] (重点突出) -- 背景:渐变色卡片 -- 我的收益: ¥256.80 -- 待提现: ¥128.90 -- 已提现: ¥127.90 -- 推荐人数: 28人 -- 按钮:推广海报生成 | 立即提现 - -[功能菜单] -- 我的订单 -- 购买记录 -- 分享记录 -- 设置 -\`\`\` - -**交互细节**: -- 点击邀请码,自动复制 -- 点击"推广海报生成",生成专属海报 -- 点击"立即提现",弹出提现弹窗 - ---- - -### 2.5 匹配书友页 (小程序独有) - -**功能目标**: 类Soul星球的匹配功能,增加社交属性 - -**布局结构**: -\`\`\` -[星空背景] -- Canvas动画 -- 星星闪烁效果 -- 星球漂浮效果 - -[中央区域] -- 星球图标 (旋转动画) -- 按钮:开始匹配 -- 提示文字:当前在线 128 人 - -[匹配中] -- 光环扩散动画 -- 提示文字:正在寻找志同道合的书友... - -[匹配成功] -- 用户头像 -- 昵称 -- 兴趣标签 -- 匹配度:85% -- 共同兴趣:创业、私域运营、AI -- 按钮:打个招呼 - -[匹配历史] -- 横向滚动 -- 显示最近10次匹配记录 -\`\`\` - -**视觉设计**: -- 背景:深蓝色渐变 (#1A1A2E -> #16213E) -- 星球:渐变色球体 + 光晕效果 -- 卡片:毛玻璃效果 + 圆角 + 阴影 -- 动画:流畅的过渡效果 - ---- - -## 三、组件设计规范 - -### 3.1 按钮 (Button) - -**主按钮** (Primary): -\`\`\`css -background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); -color: #FFFFFF; -height: 48px; -border-radius: 24px; -font-size: 16px; -font-weight: 600; -\`\`\` - -**次按钮** (Secondary): -\`\`\`css -background: #FFFFFF; -border: 1px solid #E5E7EB; -color: #374151; -height: 48px; -border-radius: 24px; -\`\`\` - -**文字按钮** (Text): -\`\`\`css -background: transparent; -color: #667eea; -text-decoration: underline; -\`\`\` - -### 3.2 输入框 (Input) - -\`\`\`css -height: 48px; -border: 1px solid #E5E7EB; -border-radius: 12px; -padding: 0 16px; -font-size: 14px; -background: #FFFFFF; -\`\`\` - -**聚焦状态**: -\`\`\`css -border-color: #667eea; -box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1); -\`\`\` - -### 3.3 卡片 (Card) - -\`\`\`css -background: #FFFFFF; -border-radius: 16px; -box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08); -padding: 24px; -\`\`\` - -**悬停效果**: -\`\`\`css -transform: translateY(-4px); -box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12); -transition: all 0.3s ease; -\`\`\` - -### 3.4 骨架屏 (Skeleton) - -\`\`\`css -background: linear-gradient( - 90deg, - #F3F4F6 25%, - #E5E7EB 50%, - #F3F4F6 75% -); -background-size: 200% 100%; -animation: loading 1.5s infinite; -border-radius: 8px; -\`\`\` - ---- - -## 四、弹窗设计 - -### 4.1 支付弹窗 - -**触发时机**: 用户点击"购买"按钮 - -**内容**: -\`\`\` -[标题] 选择支付方式 - -[支付方式列表] -○ 微信支付 (推荐) -○ 支付宝 -○ USDT (TRC20) -○ PayPal - -[商品信息] -- 商品:第1章 | 人与人之间的底层逻辑 -- 价格:¥1.00 - -[按钮] -- 确认支付 (主按钮) -- 取消 (次按钮) -\`\`\` - -### 4.2 登录弹窗 - -**触发时机**: 未登录用户点击购买或分享 - -**内容**: -\`\`\` -[标题] 手机号登录 - -[输入框] -- 手机号输入框 -- 验证码输入框 (带倒计时按钮) - -[邀请码输入框] (可选) -- 提示:填写邀请码,推荐人可获得佣金 - -[按钮] -- 登录 / 注册 (主按钮) -- 暂不登录 (文字按钮) -\`\`\` - -### 4.3 二维码弹窗 - -**触发时机**: 阅读到30%或点击"加入派对" - -**内容**: -\`\`\` -[标题] 扫码加入Soul派对群 - -[二维码图片] -- 尺寸:200x200 -- 下方文字:长按识别二维码 - -[按钮] -- 我知道了 -\`\`\` - ---- - -## 五、颜色规范 - -### 5.1 主色调 - -\`\`\` -品牌主色 (Primary): -- 主色:#667EEA -- 深色:#5A67D8 -- 浅色:#7F9CF5 - -辅助色 (Secondary): -- 成功:#10B981 (绿色) -- 警告:#F59E0B (橙色) -- 错误:#EF4444 (红色) -- 信息:#3B82F6 (蓝色) -\`\`\` - -### 5.2 中性色 - -\`\`\` -文字颜色: -- 标题:#111827 (深灰) -- 正文:#374151 (中灰) -- 辅助:#6B7280 (浅灰) - -背景颜色: -- 主背景:#FFFFFF (白色) -- 次背景:#F9FAFB (浅灰) -- 卡片背景:#FFFFFF (白色) -\`\`\` - -### 5.3 深色模式 - -\`\`\` -背景: -- 主背景:#1C1C1E -- 次背景:#2C2C2E -- 卡片背景:#3A3A3C - -文字: -- 标题:#FFFFFF -- 正文:#E5E5EA -- 辅助:#98989D -\`\`\` - ---- - -## 六、字体规范 - -### 6.1 字体系统 - -\`\`\`css -font-family: - -apple-system, /* iOS */ - BlinkMacSystemFont, /* macOS */ - 'Segoe UI', /* Windows */ - 'PingFang SC', /* 中文简体 */ - 'Hiragino Sans GB', /* macOS 中文 */ - 'Microsoft YaHei', /* Windows 中文 */ - sans-serif; -\`\`\` - -### 6.2 字号规范 - -\`\`\` -特大标题:32px / 36px (权重: 700) -大标题:24px / 28px (权重: 600) -中标题:20px / 24px (权重: 600) -小标题:18px / 22px (权重: 500) -正文:16px / 24px (权重: 400) -辅助文字:14px / 20px (权重: 400) -小字:12px / 18px (权重: 400) -\`\`\` - ---- - -## 七、动画规范 - -### 7.1 过渡动画 - -\`\`\`css -/* 标准过渡 */ -transition: all 0.3s ease; - -/* 快速过渡 */ -transition: all 0.15s ease; - -/* 慢速过渡 */ -transition: all 0.5s ease; -\`\`\` - -### 7.2 加载动画 - -**骨架屏**: -\`\`\`css -@keyframes loading { - 0% { background-position: -200% 0; } - 100% { background-position: 200% 0; } -} -\`\`\` - -**旋转加载**: -\`\`\`css -@keyframes spin { - from { transform: rotate(0deg); } - to { transform: rotate(360deg); } -} -\`\`\` - -### 7.3 页面切换动画 - -**滑动进入** (iOS风格): -\`\`\`css -@keyframes slideIn { - from { - transform: translateX(100%); - opacity: 0; - } - to { - transform: translateX(0); - opacity: 1; - } -} -\`\`\` - ---- - -## 八、响应式断点 - -\`\`\`css -/* 手机 (默认) */ -@media (max-width: 640px) { ... } - -/* 平板 */ -@media (min-width: 641px) and (max-width: 1024px) { ... } - -/* 桌面 */ -@media (min-width: 1025px) { ... } -\`\`\` - ---- - -## 九、设计交付规范 - -### 9.1 设计稿命名 - -\`\`\` -格式:页面名称-设备-版本号.fig -示例: -- 首页-Mobile-v1.0.fig -- 目录页-Mobile-v1.0.fig -- 阅读页-Mobile-v1.0.fig -\`\`\` - -### 9.2 切图规范 - -\`\`\` -命名:功能-类型-尺寸.png -示例: -- button-primary-normal@2x.png -- icon-lock-24x24@2x.png -- cover-book-400x600@2x.png -\`\`\` - -### 9.3 标注规范 - -- 所有间距必须标注 -- 字体大小和行高必须标注 -- 颜色使用十六进制色值 -- 圆角、阴影参数必须标注 - ---- - -## 十、参考案例 - -### 10.1 iOS原生风格 -- **Settings App** (iOS系统设置) -- **Apple Books** (苹果图书) -- **Notion** (笔记应用) - -### 10.2 阅读类产品 -- **微信读书** -- **得到App** -- **小宇宙播客** - -### 10.3 社交匹配类 -- **Soul** -- **探探** -- **Tinder** - ---- - -**总结**: 原型设计不是为了好看,是为了让用户"不用想就知道怎么做"。简洁、清晰、高效,这就是我们的设计原则。 - ---- - -**更新时间**: 2025年1月14日 -**负责人**: 卡若 -**设计工具**: Figma diff --git a/开发文档/4、前端/02-AI分析-长图.png b/开发文档/4、前端/02-AI分析-长图.png deleted file mode 100644 index ec6b7929..00000000 Binary files a/开发文档/4、前端/02-AI分析-长图.png and /dev/null differ diff --git a/开发文档/4、前端/03-数据市场-长图.png b/开发文档/4、前端/03-数据市场-长图.png deleted file mode 100644 index 41e0d198..00000000 Binary files a/开发文档/4、前端/03-数据市场-长图.png and /dev/null differ diff --git a/开发文档/4、前端/04-标签画像-长图.png b/开发文档/4、前端/04-标签画像-长图.png deleted file mode 100644 index cbe3fc19..00000000 Binary files a/开发文档/4、前端/04-标签画像-长图.png and /dev/null differ diff --git a/开发文档/4、前端/05-估值模型-长图.png b/开发文档/4、前端/05-估值模型-长图.png deleted file mode 100644 index d25f099f..00000000 Binary files a/开发文档/4、前端/05-估值模型-长图.png and /dev/null differ diff --git a/开发文档/4、前端/06-设置-长图.png b/开发文档/4、前端/06-设置-长图.png deleted file mode 100644 index e0822c3e..00000000 Binary files a/开发文档/4、前端/06-设置-长图.png and /dev/null differ diff --git a/开发文档/4、前端/07-文档-长图.png b/开发文档/4、前端/07-文档-长图.png deleted file mode 100644 index 98d0e15c..00000000 Binary files a/开发文档/4、前端/07-文档-长图.png and /dev/null differ diff --git a/开发文档/4、前端/08-登录-长图.png b/开发文档/4、前端/08-登录-长图.png deleted file mode 100644 index fa2361fc..00000000 Binary files a/开发文档/4、前端/08-登录-长图.png and /dev/null differ diff --git a/开发文档/4、前端/09-流量池-长图.png b/开发文档/4、前端/09-流量池-长图.png deleted file mode 100644 index 1411eb44..00000000 Binary files a/开发文档/4、前端/09-流量池-长图.png and /dev/null differ diff --git a/开发文档/4、前端/ui/01-概述与页面.md b/开发文档/4、前端/ui/01-概述与页面.md deleted file mode 100644 index 1f2020c4..00000000 --- a/开发文档/4、前端/ui/01-概述与页面.md +++ /dev/null @@ -1,31 +0,0 @@ -# 概述与页面(合并自 01-项目概述、02-页面功能说明) - -## 项目简介 - -基于 Next.js 16 的知识付费+分销系统:电子书阅读与付费、创业伙伴匹配、90%高佣分销、用户中心。 - -**技术栈**:Next.js 16 / React 19 / TypeScript / Tailwind / Zustand / shadcn/ui | 后端:Next.js API、MySQL、微信支付 - -**项目结构**:app/(页面+API)、components/(ui + modules)、lib/(store、book-data)、book/ - -## 核心功能模块 - -| 模块 | 说明 | 路径 | -|:---|:---|:---| -| 首页 | 书籍介绍、购买入口 | `/` | -| 目录 | 章节列表、付费状态 | `/chapters` | -| 阅读 | 文章内容、购买弹窗 | `/read/[id]` | -| 找伙伴 | 四种匹配类型 | `/match` | -| 我的 | 个人中心、收益 | `/my` | -| 分销中心 | 推广、提现 | `/my/referral` | -| 管理后台 | 数据管理 | `/admin` | - -## 页面功能概要 - -- **首页**:封面、简介、立即阅读/购买全书、底部导航 -- **目录页**:62章、折叠结构、免费/已购/未购状态 -- **阅读页**:文章渲染、付费墙、上下篇、分享 -- **找伙伴**:创业合伙/资源对接/导师/团队招募 -- **我的**:登录、个人信息、购买记录、推广中心 - -**定价**:单章 ¥1,全书 ¥9.9,分销 90% diff --git a/开发文档/4、前端/ui/02-组件与系统.md b/开发文档/4、前端/ui/02-组件与系统.md deleted file mode 100644 index 521209c9..00000000 --- a/开发文档/4、前端/ui/02-组件与系统.md +++ /dev/null @@ -1,31 +0,0 @@ -# 组件与系统(合并自 03-09) - -## 组件清单 - -**UI 基础**:Button、Card、Input、Label、Textarea、Switch、Tabs - -**业务模块**:AuthModal、PaymentModal、PosterModal、WithdrawalModal、AutoWithdrawModal、ChapterContent - -## API 接口 - -基础路径 `/api`,主要模块:book、payment、referral、user、match、admin、config - -## 状态管理 - -Zustand + localStorage,全局 store 含用户、购买、配置等 - -## 分销系统 - -推广中心、邀请码、绑定关系、90% 佣金、提现 - -## 找伙伴 - -创业合伙/资源对接/导师顾问/团队招募,匹配规则与配置 - -## 支付系统 - -微信/支付宝,PaymentModal 弹窗,支付回调与订单状态 - -## 管理后台 - -仪表盘、内容管理、用户管理、支付配置、二维码、提现审核、系统设置 diff --git a/开发文档/4、前端/ui/03-部署与截图.md b/开发文档/4、前端/ui/03-部署与截图.md deleted file mode 100644 index e5b208ba..00000000 --- a/开发文档/4、前端/ui/03-部署与截图.md +++ /dev/null @@ -1,23 +0,0 @@ -# 部署与截图(合并自 10-11) - -## 部署指南 - -**环境**:Node >= 20,MySQL >= 8 - -**本地开发**:`npm install` → `npm run dev` → http://localhost:3000 - -**环境变量**:.env.local 配置 DATABASE_URL、CKB_API_KEY、WECHAT_* - -**生产构建**:`npm run build` → `npm start` 或 PM2 - -## 设计规范(截图还原) - -**颜色**:主色 #00CED1,辅助色 gold/green/orange/red/purple,背景 #000/#1c1c1e - -**字体**:标题 18–24px,正文 14px,辅助 12px - -**圆角**:按钮 12px,卡片 16px,头像 50% - -**页面尺寸**:375×812(iPhone 标准) - -详见原 10-部署上线指南、11-页面截图与还原指南 完整内容。 diff --git a/开发文档/4、前端/前端开发规范.md b/开发文档/4、前端/前端开发规范.md deleted file mode 100644 index 4f155cb0..00000000 --- a/开发文档/4、前端/前端开发规范.md +++ /dev/null @@ -1,56 +0,0 @@ -# 前端开发规范 (Frontend Specs) - 智能自生长文档 - -> **提示词功能 (Prompt Function)**: 将本文件拖入 AI 对话框,即可激活“前端技术专家”角色,生成符合 iOS 风格的 React 代码。 - -## 1. 基础上下文 (The Two Basic Files) -### 1.1 角色档案:卡若 (Karuo) -- **视觉标准**:像素级复刻 iOS (San Francisco, 1:1 间距, 弥散阴影)。 -- **体验标准**:无白屏 (Skeleton),丝滑转场 (Transition)。 - -### 1.2 技术栈 -- **核心**:React + Shadcn UI + Tailwind CSS。 -- **辅助**:Vant UI (移动端组件)。 -- **构建**:Vite / Next.js。 - -## 2. 开发规范核心 (Master Content) -### 2.1 视觉与风格 (iOS) -- **字体**:San Francisco > PingFang SC。 -- **色彩**: - - 背景:`#F2F2F7` (Grouped Background)。 - - 分割:`#C6C6C8`。 - - 交互:`#007AFF` (System Blue)。 -- **细节**: - - 圆角:统一 `rounded-lg` 或 `rounded-xl`。 - - 阴影:柔和弥散,非生硬投影。 - -### 2.2 交互与性能 (Mandatory) -- **骨架屏**:数据加载必须显示 Skeleton,严禁 Spinner。 -- **转场**:路由切换必须有动画。 -- **图片**:懒加载 + 失败占位。 - -### 2.3 目录结构 -- `/src/components`: 原子组件。 -- `/scenarios/new`: 场景获客页。 -- `/src/hooks`: 逻辑复用。 - -## 3. AI 协作指令 (Expanded Function) -**角色**:你是我(卡若)的前端主程。 -**任务**: -1. **代码生成**:生成 React 组件代码,**必须**包含 Tailwind 类名。 -2. **样式检查**:确保所有 UI 元素符合 iOS 规范(检查圆角、阴影、字体)。 -3. **结构分析**:用 Mermaid 展示组件依赖。 - -### 示例 Mermaid (组件结构) -\`\`\`mermaid -classDiagram - Page <|-- Header - Page <|-- Content - Page <|-- Footer - Content <|-- SkeletonLoader - Content <|-- DataList - DataList <|-- ListItem - class Page{ - +state: loading - +effect: fetchData() - } -\`\`\` diff --git a/开发文档/4、前端/前端架构.md b/开发文档/4、前端/前端架构.md deleted file mode 100644 index 2d2779b7..00000000 --- a/开发文档/4、前端/前端架构.md +++ /dev/null @@ -1,94 +0,0 @@ -# 前端架构 - -**我是卡若。** - -前端就是项目的脸。用户不管是通过朋友圈、抖音还是私域进来,第一眼看到的就是这个页面。如果加载慢、长得丑、滑动卡,人家转头就走,我的流量就浪费了。 - -所以,前端的核心目标只有一个:**极致的移动端阅读体验,像原生 App 一样丝滑。** - -## 1. 技术底座 - -别跟我说什么技术先进,我要的是**稳**和**快**。 - -- **框架**: Next.js 14 (App Router) - 必须用最新的 App Router,路由管理更清晰。 -- **语言**: TypeScript - 必须用 TS,类型安全,少出低级 Bug。 -- **样式**: Tailwind CSS - 写样式最快,没有之一。配合 `globals.css` 做全局控制。 -- **UI 组件库**: Shadcn UI (基于 Radix UI) + Vant UI (风格参考)。 - - *注意*:我们要像素级复刻 iOS 风格,字体用 San Francisco,圆角、阴影都要对齐。 - -## 2. 目录结构(我的地盘) - -前端代码主要集中在 `app/` 和 `components/`。 - -\`\`\` -app/ -├── (routes)/ # 路由组,逻辑隔离 -│ ├── page.tsx # 首页:封面、简介、购买按钮 -│ ├── chapters/ # 目录页:章节列表 -│ ├── read/[id]/ # 阅读页:核心体验区 -│ ├── my/ # 个人中心:购买记录、分销 -│ ├── admin/ # 管理后台:给自己用的 -│ └── documentation/ # 文档生成:内部工具 -├── layout.tsx # 全局布局:导航栏、SEO Meta -├── globals.css # 全局样式 -└── error.tsx # 错误处理页面 - -components/ -├── ui/ # 通用组件 (Button, Input, Skeleton) -├── modules/ # 业务模块组件 (新增) -│ ├── auth/ # 认证模块 (AuthModal) -│ ├── payment/ # 支付模块 (PaymentModal) -│ ├── marketing/ # 营销模块 (QRCodeModal) -│ └── referral/ # 分销模块 (ReferralShare) -├── book-cover.tsx # 书籍封面展示 -├── chapter-content.tsx # 章节内容渲染器 -├── bottom-nav.tsx # 底部导航栏 (手机端核心) -└── theme-provider.tsx # 主题管理 (深色/浅色模式) -\`\`\` - -## 2.1 业务模块化 (Modularization) - -为了支持“云阿米巴”模式的快速迭代,我们将核心业务逻辑封装为独立模块: - -- **支付模块 (Payment)**: 统一管理微信、支付宝、USDT 等支付方式,支持整书/单章购买。 -- **营销模块 (Marketing)**: 负责引流(如二维码弹窗、倒计时Banner),连接私域流量池。 -- **分销模块 (Referral)**: 负责裂变传播(如分享按钮、返利计算),让用户帮我们卖书。 -- **认证模块 (Auth)**: 统一的用户登录与权限校验。 - -这种设计允许我们在不修改页面核心逻辑的情况下,插拔不同的变现策略。 - -## 3. 核心交互设计 - -### 3.1 骨架屏 (Skeleton) -**规则**:凡是需要加载数据的地方,必须先展示骨架屏。 -- 用户不能看白屏,哪怕等 0.5 秒,也要让他看到“东西正在来”的样子。 -- 强制引入 `Skeleton` 组件。 - -### 3.2 路由动画 (Transition) -**规则**:页面切换不能生硬地跳。 -- 使用 Framer Motion 或 CSS Transition。 -- 模拟 iOS 的滑动切换或淡入淡出。 - -### 3.3 阅读体验 -- **字体**:针对不同设备优化,保证字号适中,行间距舒服(建议 1.6-1.8)。 -- **图片**:懒加载 (Lazy Load),点击可放大预览。 -- **代码块**:虽然是书,但如果有代码,要有高亮和复制按钮。 - -## 4. 数据获取 (Fetching) - -- **服务端组件 (Server Components)**: - - `page.tsx`, `read/[id]/page.tsx` 默认都是服务端组件。 - - 直接在组件内 `await` 获取数据(通过 `lib/book-data.ts`),SEO 极佳。 -- **客户端组件 (Client Components)**: - - 需要交互的(点击、弹窗、状态变化),头部加 `'use client'`。 - - 比如 `auth-modal.tsx`, `purchase-section.tsx`。 - -## 5. 待办事项 (Todo) - -- [ ] 全局引入 Skeleton,替换掉所有的 `Loading...` 文字。 -- [ ] 检查所有页面的 Mobile 适配,在 Chrome 开发者工具里用 iPhone SE 和 iPhone 14 Pro Max 两个尺寸测。 -- [ ] 优化字体栈,确保在安卓上也不难看。 - ---- -**总结**: -前端不仅是写代码,是**做产品**。每一个像素的偏移都影响用户的信任感。把细节抠好,转化率自然就高了。 diff --git a/开发文档/4、前端/当前小程序开发细则.md b/开发文档/4、前端/当前小程序开发细则.md deleted file mode 100644 index 1aad3fe1..00000000 --- a/开发文档/4、前端/当前小程序开发细则.md +++ /dev/null @@ -1,160 +0,0 @@ -# 当前小程序开发细则 - -> 汇总当前 Soul 创业派对小程序的架构、经验与规划,便于新人上手与后续迭代。 -> 最后整理:2026-02 - ---- - -## 一、概述与定位 - -- **产品**:Soul 创业派对 — 微信小程序,内容为《一场 SOUL 的创业实验场》章节阅读 + 找伙伴 + 分销。 -- **技术**:原生微信小程序(非 uni-app / Taro),与 Next.js 后端同仓,接口统一走 `apiBase`(如 `https://soul.quwanzhi.com`)。 -- **核心能力**:章节阅读(免费/付费)、单章/全书支付、邀请码分销、找伙伴(匹配次数购买)、推广中心、我的订单/设置。 - ---- - -## 二、目录与页面结构 - -### 2.1 目录结构(miniprogram/) - -``` -miniprogram/ -├── app.js / app.json / app.wxss # 入口、全局配置、样式 -├── custom-tab-bar/ # 自定义底部 tabBar -├── pages/ -│ ├── index/ # 首页(推荐章节、已读统计) -│ ├── chapters/ # 目录(全书章节列表) -│ ├── read/ # 阅读页(核心:权限、支付、分享) -│ ├── match/ # 找伙伴(匹配 + 购买次数) -│ ├── my/ # 我的(入口:订单、推广、设置) -│ ├── referral/ # 推广中心(邀请码、收益、海报) -│ ├── purchases/ # 我的订单(当前为本地已购章节列表) -│ ├── settings/ # 设置(提现、绑定账号等) -│ ├── search/ # 搜索 -│ ├── about/ # 关于 -│ └── addresses/ # 地址(若启用) -├── utils/ -│ ├── chapterAccessManager.js # 章节权限与状态 -│ ├── readingTracker.js # 阅读进度追踪 -│ ├── payment.js # 旧支付封装(部分场景仍用) -│ └── util.js -└── assets/ # 图标等静态资源 -``` - -### 2.2 TabBar 与主要页面 - -| Tab | 页面 | 说明 | -|-----|------|------| -| 首页 | pages/index/index | 推荐章节、已读/待读、入口到阅读 | -| 目录 | pages/chapters/chapters | 全书章节列表 | -| 找伙伴 | pages/match/match | 匹配 + 购买匹配次数 | -| 我的 | pages/my/my | 已读/已购、推广中心、订单、设置 | - -非 Tab 页:阅读页 read、推广中心 referral、订单 purchases、设置 settings、搜索 search、关于 about。 - -### 2.3 全局状态(app.js globalData) - -- `userInfo`:登录后用户信息(id、openId、nickname、purchasedSections、hasFullBook、referralCode、referralCount 等)。 -- `openId` / `isLoggedIn`:微信登录态。 -- `readSectionIds`:已读章节 ID 列表(有权限打开全文时打点)。 -- `pendingReferralCode`:待绑定推荐码(带 ref 进入时写入,登录后绑定)。 -- `apiBase`:后端 API 根地址。 - ---- - -## 三、核心流程与经验 - -### 3.1 阅读与章节权限 - -- **权威数据源**:章节是否可读以**服务端**为准(`/api/user/check-purchased`、`/api/user/purchase-status`),不依赖前端缓存做最终判断。 -- **权限状态**:设计上支持 `unknown / free / locked_not_login / locked_not_purchased / unlocked_purchased / error`(见《章节阅读付费标准流程设计》);阅读页通过 `chapterAccessManager` 与 `determineAccessState` 等做状态判断。 -- **免费章节**:来自后端配置(如 `/api/db/config` 的 freeChapters),页面 onLoad 时拉取最新免费列表再判断;首帧可用本地默认 freeIds,拉取完成后需能刷新当前章状态,避免竞态误判。 -- **已读 vs 已购**: - - **已读**:仅统计“有权限打开并看到全文”的章节(`canAccess=true` 时 `app.markSectionAsRead(sectionId)`),存 `readSectionIds`。 - - **已购**:来自服务端 `userInfo.purchasedSections`、`hasFullBook` 及 orders 表,用于付费墙与购买按钮展示。 -- **登录后防误解锁**:登录成功(含支付流程中登录)后必须 `refreshPurchaseFromServer()`,再对当前章节做 `recheckCurrentSectionAndRefresh()`(先拉最新免费列表,再请求 check-purchased),避免“刚登录”时误用旧缓存解锁付费章。 -- **内容接口**:当前 `GET /api/book/chapter/[id]` 不校验登录与购买,前端按 `canAccess` 控制展示全文或预览;若未来开放 Web/API,建议章节接口侧做鉴权。 - -详见:`开发文档/8、部署/章节阅读付费标准流程设计.md`。 - -### 3.2 支付流程(章节 + 找伙伴) - -- **统一入口**:章节支付 `pages/read/read.js` 调 `POST /api/miniprogram/pay`;找伙伴支付 `pages/match/match.js` 同样调该接口,传 `productType: 'match'`。 -- **订单先行**:支付前**必须先创建订单**并插入 `orders` 表(status=`created`),再调微信统一下单;即使插库失败也继续支付流程,避免用户卡在“创建订单失败”。 -- **请求体约定**:`openId`、`userId`、`productType`(section/fullbook/match)、`productId`、`amount`、`description`;**必须带 `referralCode`**(见下节)。 -- **支付成功**:依赖微信回调 `POST /api/miniprogram/pay/notify` 更新订单为 `paid`、解锁用户权限、分佣、清理同产品未支付订单;前端支付成功后调用 `refreshUserPurchaseStatus()` 再 `initSection()` 刷新当前页。 -- **兜底**:若回调丢失,依赖**订单状态同步定时任务**(如每 5 分钟调 `GET /api/cron/sync-orders`)查询微信侧状态并同步到本地 orders,保证最终一致。详见 `开发文档/8、部署/宝塔面板配置订单同步定时任务.md`。 - -### 3.3 邀请码与分销(必传、必记) - -- **绑定逻辑**:带 `ref` 或 `referralCode` 的链接进入 → `app.js` 的 `handleReferralCode` 写入 `pendingReferralCode` 并**同步写入 `referral_code`**(`wx.setStorageSync('referral_code', refCode)`);登录后调用 `/api/referral/bind` 完成绑定(30 天有效、可续期/抢夺)。 -- **支付必带邀请码**:章节支付、找伙伴支付创建订单时都要传 `referralCode`,来源为 `wx.getStorageSync('referral_code')`;后端据此(或先查 referral_bindings)写入订单的 `referrer_id` 与 **`referral_code`**(下单时使用的邀请码,便于对账与后台展示)。 -- **订单表字段**:`orders.referrer_id`(推荐人用户ID)、`orders.referral_code`(下单时邀请码)。若表尚未加字段,需执行 `scripts/add_orders_referrer_id.py`、`scripts/add_orders_referral_code.py`。 -- **推荐人 vs 邀请码**:全局只认「推荐人 = 用户ID」;邀请码仅用于解析出 referrer_id,不会混用。分佣以 `referral_bindings` 为准,不依赖订单上的 referrer_id。详见 `开发文档/8、部署/邀请码分销规则说明.md`。 - -### 3.4 分享与落地 - -- 阅读页分享:`onShareAppMessage` / `onShareTimeline` 带 `id=章节ID&ref=当前用户邀请码`,落地后 ref 写入 storage,绑定与订单归属同上。 -- 文章/章节分销与全局同一套:不按“哪篇文章带来”单独分成或统计,仅按“谁发的链接(ref=谁)”归属。 - ---- - -## 四、数据与接口约定 - -### 4.1 关键接口 - -| 接口 | 用途 | -|------|------| -| POST /api/miniprogram/login | 微信登录,返回 userInfo(含 purchasedSections、referralCode 等) | -| GET /api/user/purchase-status | 拉取购买状态(已购章节、全书) | -| GET /api/user/check-purchased | 校验指定章节/全书是否已购买 | -| POST /api/miniprogram/pay | 创建订单 + 微信预支付,**需传 referralCode** | -| POST /api/miniprogram/pay/notify | 微信支付回调(服务端) | -| GET /api/cron/sync-orders | 订单状态同步(定时任务,需 secret) | -| POST /api/referral/bind | 绑定推荐关系 | -| GET /api/db/config | 免费章节等配置 | - -### 4.2 Storage 约定 - -- `referral_code`:落地 ref 或 app 检测到 ref 时写入;支付时读取并传后端。 -- `pendingReferralCode` / `boundReferralCode`:待绑定/已绑定推荐码(app 层)。 -- `readSectionIds`:已读章节 ID 列表。 -- `openId`、用户信息等由 app 与登录逻辑维护。 - ---- - -## 五、已知问题与修复要点 - -- **免费章节配置竞态**:onLoad 时若未 await 免费列表再 initSection,首帧可能用默认 freeIds 误判;建议先拉配置再判断当前章,或拉取完成后对当前页再刷一次权限。 -- **check-purchased 失败降级**:失败时应**保守**设为无权限(不信任本地缓存),避免误解锁。 -- **支付回调丢失**:必须部署订单同步定时任务(如宝塔 crontab 调 `/api/cron/sync-orders`),否则会出现“已扣款但订单仍 created、内容未解锁”。 -- **订单表缺字段**:新环境或老库需执行 `add_orders_referrer_id.py`、`add_orders_referral_code.py`,否则下单可能 fallback 成不写这两列(功能仍可用,但订单无推荐人/邀请码记录)。 - ---- - -## 六、部署与运维 - -- **后端**:Next.js 部署至 soul.quwanzhi.com,小程序 `app.globalData.apiBase` 指向该域名。 -- **订单同步**:生产环境配置 crontab 每 5 分钟请求 `GET /api/cron/sync-orders?secret=YOUR_SECRET`(如宝塔定时任务),保证回调丢失时仍能同步为 paid 并解锁。见 `开发文档/8、部署/宝塔面板配置订单同步定时任务.md`。 -- **数据库**:orders 表需含 `referrer_id`、`referral_code`;若为已有表,执行上述两个 Python 迁移脚本。 -- **小程序发布**:按微信后台流程上传代码、提交审核;注意域名白名单、支付商户号与回调 URL 配置。 - ---- - -## 七、规划与待办(可选) - -- **我的订单页**:当前 `purchases` 页为本地已购章节列表;若需“真实订单列表+邀请码展示”,可对接 `GET /api/orders?userId=xxx` 并展示订单维度数据。 -- **阅读进度**:已设计阅读进度状态与 `readingTracker`、可上报服务端;是否全量接入与埋点可按产品需求推进。 -- **章节接口鉴权**:若开放 Web 或对外 API,建议在章节内容接口侧按用户与购买记录返回全文/预览,防止直连拿全文。 -- **按文章/章节维度的分销统计**:当前未实现;若需要“某章节带来的访问/订单数”,需在访问或订单上增加来源章节等字段并在报表中汇总。 - ---- - -## 八、相关文档索引 - -| 文档 | 说明 | -|------|------| -| 开发文档/8、部署/邀请码分销规则说明.md | 分销规则、订单 referrer_id/referral_code、推荐人 vs 邀请码 | -| 开发文档/8、部署/章节阅读付费标准流程设计.md | 阅读状态机、权限判断、阅读进度设计 | -| 开发文档/4、前端/ui/06-分销系统说明.md | 分销规则与推广方式 | -| 开发文档/4、前端/ui/08-支付系统说明.md | 支付方式与价格体系 | diff --git a/开发文档/4、前端/模块详解.md b/开发文档/4、前端/模块详解.md deleted file mode 100644 index 849bfcac..00000000 --- a/开发文档/4、前端/模块详解.md +++ /dev/null @@ -1,721 +0,0 @@ -# 前端模块详解 - Soul创业实验项目 - -> **核心模块**: 首页、匹配、阅读、我的、支付、分销 - -**我是卡若。** - -这里记录每个前端模块的实现细节,方便以后维护和扩展。 - ---- - -## 1. 首页模块 - -**路径**: `/app/page.tsx` - -### 1.1 核心功能 - -```typescript -export default function HomePage() { - return ( -
- {/* 1. 品牌标签 */} - - - {/* 2. 书籍封面 */} - - - {/* 3. 核心数据 */} - - - {/* 4. 作者信息 */} - - - {/* 5. 行动按钮 */} - - - {/* 6. 寄语卡片 */} - - - {/* 7. 章节列表 */} - -
- ) -} -``` - -### 1.2 关键组件 - -**书籍封面**: -```typescript -function BookCover({ src }: { src: string }) { - return ( -
- 书籍封面 - {/* 3D效果 */} -
-
- ) -} -``` - -**数据亮点**: -```typescript -function DataHighlights({ price, cases, insights }: Props) { - return ( -
-
-
- {price} -
-
全书价格
-
-
-
- {cases} -
-
商业案例
-
-
-
- {insights} -
-
商业洞察
-
-
- ) -} -``` - ---- - -## 2. 匹配模块 - -**路径**: `/app/match/page.tsx` - -### 2.1 核心功能 - -```typescript -export default function MatchPage() { - const [isMatching, setIsMatching] = useState(false) - const [matchResult, setMatchResult] = useState(null) - - const handleMatch = async () => { - setIsMatching(true) - // 模拟匹配过程 - await new Promise(resolve => setTimeout(resolve, 2000)) - setMatchResult({ - name: '创业者小王', - mbti: 'ENTJ', - interests: ['私域运营', '内容创业'], - matchRate: 85 - }) - setIsMatching(false) - } - - return ( -
- {/* 星空背景 */} - - - {/* 中央星球 */} - - - {/* 标题 */} -

- 寻找创业合作伙伴 -

- - {/* 匹配按钮或结果 */} - {!matchResult ? ( - - ) : ( - - )} - - {/* 快捷操作 */} - {}} - onJoinGroup={() => {}} - /> -
- ) -} -``` - -### 2.2 关键组件 - -**星空背景**: -```typescript -function StarfieldBackground() { - const canvasRef = useRef(null) - - useEffect(() => { - const canvas = canvasRef.current - const ctx = canvas?.getContext('2d') - if (!canvas || !ctx) return - - // 创建星星 - const stars = Array.from({ length: 100 }, () => ({ - x: Math.random() * canvas.width, - y: Math.random() * canvas.height, - radius: Math.random() * 2, - opacity: Math.random() - })) - - // 绘制动画 - function animate() { - ctx.clearRect(0, 0, canvas.width, canvas.height) - stars.forEach(star => { - ctx.beginPath() - ctx.arc(star.x, star.y, star.radius, 0, Math.PI * 2) - ctx.fillStyle = `rgba(255, 255, 255, ${star.opacity})` - ctx.fill() - }) - requestAnimationFrame(animate) - } - animate() - }, []) - - return -} -``` - ---- - -## 3. 阅读模块 - -**路径**: `/app/read/[id]/page.tsx` - -### 3.1 核心功能 - -```typescript -export default async function ReadPage({ params }: Props) { - const { id } = params - const section = await getSection(id) - - if (!section) { - notFound() - } - - return ( -
- {/* 返回按钮 */} - - - {/* 章节标题 */} -

- {section.title} -

- - {/* 章节信息 */} - - - {/* Markdown内容 */} - - - {/* 章节导航 */} - - - {/* 分享按钮 */} - -
- ) -} -``` - -### 3.2 Markdown渲染 - -```typescript -import { marked } from 'marked' - -function MarkdownContent({ content }: { content: string }) { - const html = marked(content) - - return ( -
- ) -} - -// CSS样式 -.prose { - @apply text-gray-300 leading-relaxed; -} - -.prose h1 { - @apply text-3xl font-bold text-white mt-8 mb-4; -} - -.prose h2 { - @apply text-2xl font-bold text-white mt-6 mb-3; -} - -.prose p { - @apply mb-4; -} - -.prose ul { - @apply list-disc list-inside mb-4; -} - -.prose code { - @apply bg-gray-800 px-2 py-1 rounded text-[var(--app-brand)]; -} -``` - ---- - -## 4. 我的模块 - -**路径**: `/app/my/page.tsx` - -### 4.1 核心功能 - -```typescript -export default function MyPage() { - const { user, isLoggedIn } = useStore() - - if (!isLoggedIn) { - return - } - - return ( -
- {/* 用户信息卡片 */} - - - {/* 阅读统计 */} - - - {/* 分销中心(重点突出) */} - - - {/* 功能菜单 */} - -
- ) -} -``` - -### 4.2 分销中心 - -```typescript -function ReferralCenter({ code, earnings, referralCount }: Props) { - return ( -
-

分销中心

- - {/* 收益概览 */} -
-
-
- ¥{earnings.toFixed(2)} -
-
累计收益
-
-
-
- {referralCount} -
-
推荐人数
-
-
- - {/* 邀请码 */} -
- -
- - -
-
- - {/* 生成海报 */} - -
- ) -} -``` - ---- - -## 5. 支付模块 - -**路径**: `/components/payment-modal.tsx` - -### 5.1 核心流程 - -```typescript -export function PaymentModal({ - isOpen, - amount, - type, - onSuccess -}: Props) { - const [paymentMethod, setPaymentMethod] = useState('alipay') - const [showQRCode, setShowQRCode] = useState(false) - const [isProcessing, setIsProcessing] = useState(false) - - // 发起支付 - const handlePayment = async () => { - setShowQRCode(true) - - // 调用支付API - const order = await createOrder({ - amount, - type, - paymentMethod - }) - - // 展示支付二维码 - showPaymentQRCode(order.qrCode) - } - - // 确认支付 - const confirmPayment = async () => { - setIsProcessing(true) - - // 购买逻辑 - const success = await purchaseItem(type) - - if (success) { - onSuccess() - // 自动跳转到读者群 - openWechatGroup() - } - - setIsProcessing(false) - } - - return ( - - {!showQRCode ? ( - - ) : ( - - )} - - ) -} -``` - -### 5.2 支付方式组件 - -```typescript -function PaymentMethodSelection({ selected, onSelect, onConfirm }: Props) { - const methods = [ - { - id: 'wechat', - name: '微信支付', - icon: , - color: '#07C160' - }, - { - id: 'alipay', - name: '支付宝', - icon: , - color: '#1677FF' - }, - { - id: 'usdt', - name: 'USDT (TRC20)', - icon: , - color: '#26A17B' - } - ] - - return ( -
- {methods.map(method => ( - - ))} - - -
- ) -} -``` - ---- - -## 6. 后台管理模块 - -**路径**: `/app/admin/page.tsx` - -### 6.1 概览页面 - -```typescript -export default function AdminDashboard() { - const [stats, setStats] = useState(null) - - useEffect(() => { - fetchStats() - }, []) - - async function fetchStats() { - const res = await fetch('/api/admin', { - headers: { - 'Authorization': `Bearer ${getAdminToken()}` - } - }) - const data = await res.json() - setStats(data) - } - - if (!stats) return - - return ( -
- {/* 概览卡片 */} -
- - - - -
- - {/* 图表 */} -
- - -
-
- ) -} -``` - -### 6.2 内容管理 - -```typescript -function ContentManagement() { - const [chapters, setChapters] = useState([]) - - return ( -
- {/* 操作栏 */} -
-

内容管理

- -
- - {/* 章节列表 */} - - - - - - - - - - - - {chapters.map(chapter => ( - - - - - - - - ))} - -
章节ID标题状态价格操作
{chapter.id}{chapter.title} - - {chapter.isFree ? '免费' : '付费'} - - ¥{chapter.price} - -
-
- ) -} -``` - ---- - -## 7. 通用组件库 - -### 7.1 Button组件 - -```typescript -interface ButtonProps { - children: React.ReactNode - onClick?: () => void - loading?: boolean - disabled?: boolean - variant?: 'primary' | 'secondary' | 'ghost' - size?: 'sm' | 'md' | 'lg' -} - -export function Button({ - children, - onClick, - loading, - disabled, - variant = 'primary', - size = 'md' -}: ButtonProps) { - const baseClasses = 'rounded-xl font-semibold transition-all' - - const variantClasses = { - primary: 'bg-[var(--app-brand)] text-white hover:opacity-90', - secondary: 'bg-[var(--app-bg-secondary)] text-white', - ghost: 'bg-transparent text-[var(--app-brand)] hover:bg-[var(--app-brand-light)]' - } - - const sizeClasses = { - sm: 'px-4 py-2 text-sm', - md: 'px-6 py-3 text-base', - lg: 'px-8 py-4 text-lg' - } - - return ( - - ) -} -``` - -### 7.2 Modal组件 - -```typescript -export function Modal({ - isOpen, - onClose, - children -}: ModalProps) { - if (!isOpen) return null - - return ( -
- {/* 背景蒙层 */} -
- - {/* 内容区域 */} -
- {/* 顶部把手 (仅移动端) */} -
-
-
- - {/* 关闭按钮 */} - - - {/* 内容 */} -
- {children} -
-
-
- ) -} -``` - ---- - -**总结**: 前端模块以**组件化**为核心,每个模块职责清晰,组件可复用。核心模块包括首页(展示)、匹配(社交)、阅读(内容)、我的(用户中心)、支付(变现)、后台(管理)。所有模块都遵循统一的设计规范和交互模式。 diff --git a/开发文档/5、接口/API接口完整文档.md b/开发文档/5、接口/API接口完整文档.md deleted file mode 100644 index e23fa1d5..00000000 --- a/开发文档/5、接口/API接口完整文档.md +++ /dev/null @@ -1,640 +0,0 @@ -# API接口完整文档 - Soul创业实验项目 - -> **API风格**: RESTful | **版本**: v1.0 | **基础路径**: `/api` -> **说明**:本文档已整合原《API接口》内容,为项目唯一 API 参考。 - -**我是卡若。** - -接口设计原则:**简单、清晰、易用**。 - ---- - -## 1. 接口总览 - -### 1.1 接口分类 - -| 模块 | 路径前缀 | 描述 | -|------|---------|------| -| 书籍内容 | `/api/book` | 章节列表、内容获取、同步 | -| 支付系统 | `/api/payment` | 订单创建、支付回调、状态查询 | -| 分销系统 | `/api/referral` | 邀请码、收益查询、提现 | -| 用户系统 | `/api/user` | 登录、注册、信息更新 | -| 匹配系统 | `/api/match` | 寻找匹配、匹配历史 | -| 管理后台 | `/api/admin` | 内容/订单/用户/分销管理 | -| 配置系统 | `/api/config` | 系统配置获取 | - -### 1.2 认证方式 - -**用户认证** (可选): -``` -Cookie: session_id= -``` - -**管理员认证** (必需): -``` -Authorization: Bearer admin-token-secret -``` - ---- - -## 2. 书籍内容API - -### 2.1 获取所有章节 - -**接口**: `GET /api/book/all-chapters` - -**请求**: -```bash -curl https://your-domain.com/api/book/all-chapters -``` - -**响应**: -```json -{ - "success": true, - "data": [ - { - "id": "part-1", - "number": "01", - "title": "真实的人", - "subtitle": "人性观察与社交逻辑", - "chapters": [ - { - "id": "chapter-1", - "title": "人与人之间的底层逻辑", - "sections": [ - { - "id": "1.1", - "title": "自行车荷总:一个行业做到极致是什么样", - "price": 1, - "isFree": true, - "filePath": "book/第一篇|真实的人/...", - "unlockAfterDays": 0 - } - ] - } - ] - } - ], - "total": 64 -} -``` - -### 2.2 获取单章内容 - -**接口**: `GET /api/book/chapter/:id` - -**请求**: -```bash -curl https://your-domain.com/api/book/chapter/1.1 -``` - -**响应**: -```json -{ - "success": true, - "data": { - "id": "1.1", - "title": "自行车荷总:一个行业做到极致是什么样", - "content": "# 章节内容...", - "chapter": "第1章|人与人之间的底层逻辑", - "section": "第一篇|真实的人", - "isFree": true, - "price": 1, - "prev": null, - "next": "1.2" - } -} -``` - -### 2.3 同步章节 - -**接口**: `POST /api/book/sync` - -**请求**: -```bash -curl -X POST https://your-domain.com/api/book/sync \ - -H "Authorization: Bearer admin-token-secret" -``` - -**响应**: -```json -{ - "success": true, - "message": "同步完成", - "synced": 64, - "updated": 3 -} -``` - ---- - -## 3. 支付API - -### 3.1 创建订单 - -**接口**: `POST /api/payment/create-order` - -**请求**: -```bash -curl -X POST https://your-domain.com/api/payment/create-order \ - -H "Content-Type: application/json" \ - -d '{ - "userId": "user_123", - "type": "fullbook", - "amount": 9.9, - "paymentMethod": "alipay" - }' -``` - -**参数**: -```typescript -{ - userId: string // 用户ID - type: 'section' | 'fullbook' // 订单类型 - sectionId?: string // 章节ID (章节购买时必需) - amount: number // 支付金额 - paymentMethod: 'wechat' | 'alipay' | 'usdt' // 支付方式 -} -``` - -**响应**: -```json -{ - "success": true, - "data": { - "orderId": "order_1705230000000", - "amount": 9.9, - "qrCode": "https://qr.alipay.com/...", - "expireTime": "2026-01-14T11:00:00.000Z" - } -} -``` - -### 3.2 支付回调 - 支付宝 - -**接口**: `POST /api/payment/alipay/notify` - -**参数** (支付宝POST): -``` -out_trade_no: "order_1705230000000" -trade_status: "TRADE_SUCCESS" -total_amount: "9.90" -buyer_id: "2088xxx" -sign: "..." -``` - -**响应**: -``` -success -``` - -### 3.3 支付回调 - 微信 - -**接口**: `POST /api/payment/wechat/notify` - -**参数** (微信XML): -```xml - - SUCCESS - order_1705230000000 - 990 - -``` - -**响应**: -```xml - - SUCCESS - OK - -``` - -### 3.4 验证支付状态 - -**接口**: `GET /api/payment/verify?orderId={orderId}` - -**请求**: -```bash -curl "https://your-domain.com/api/payment/verify?orderId=order_123" -``` - -**响应**: -```json -{ - "success": true, - "data": { - "orderId": "order_123", - "status": "completed", - "paidAt": "2026-01-14T10:30:00.000Z" - } -} -``` - ---- - -## 4. 分销API - -### 4.1 获取邀请码 - -**接口**: `GET /api/referral/code` - -**认证**: 需要用户登录 - -**请求**: -```bash -curl https://your-domain.com/api/referral/code \ - -H "Cookie: session_id=xxx" -``` - -**响应**: -```json -{ - "success": true, - "data": { - "code": "REF1705230", - "url": "https://your-domain.com?ref=REF1705230" - } -} -``` - -### 4.2 绑定推荐关系 - -**接口**: `POST /api/referral/bind` - -**请求**: -```bash -curl -X POST https://your-domain.com/api/referral/bind \ - -H "Content-Type: application/json" \ - -d '{ - "userId": "user_123", - "referralCode": "REF1705229" - }' -``` - -**响应**: -```json -{ - "success": true, - "message": "绑定成功" -} -``` - -### 4.3 查询收益 - -**接口**: `GET /api/referral/earnings` - -**认证**: 需要用户登录 - -**请求**: -```bash -curl https://your-domain.com/api/referral/earnings \ - -H "Cookie: session_id=xxx" -``` - -**响应**: -```json -{ - "success": true, - "data": { - "total": 89.10, - "pending": 35.64, - "withdrawn": 53.46, - "referralCount": 10, - "recentOrders": [ - { - "userId": "user_456", - "amount": 9.9, - "earnings": 8.91, - "createdAt": "2026-01-14T10:00:00.000Z" - } - ] - } -} -``` - -### 4.4 申请提现 - -**接口**: `POST /api/referral/withdraw` - -**认证**: 需要用户登录 - -**请求**: -```bash -curl -X POST https://your-domain.com/api/referral/withdraw \ - -H "Content-Type: application/json" \ - -H "Cookie: session_id=xxx" \ - -d '{ - "amount": 50, - "method": "alipay", - "account": "13800138000", - "name": "王**" - }' -``` - -**响应**: -```json -{ - "success": true, - "data": { - "withdrawalId": "wd_123", - "amount": 50, - "status": "pending", - "estimatedTime": "1-3个工作日" - } -} -``` - ---- - -## 5. 用户API - -### 5.1 登录 - -**接口**: `POST /api/user/login` - -**请求**: -```bash -curl -X POST https://your-domain.com/api/user/login \ - -H "Content-Type: application/json" \ - -d '{ - "phone": "13800138000", - "code": "123456" - }' -``` - -**响应**: -```json -{ - "success": true, - "data": { - "user": { - "id": "user_123", - "phone": "****8000", - "nickname": "创业者小王", - "hasFullBook": false - }, - "token": "session_token_xxx" - } -} -``` - -### 5.2 注册 - -**接口**: `POST /api/user/register` - -**请求**: -```bash -curl -X POST https://your-domain.com/api/user/register \ - -H "Content-Type: application/json" \ - -d '{ - "phone": "13800138000", - "nickname": "创业者小王", - "referralCode": "REF1705229" - }' -``` - -**响应**: -```json -{ - "success": true, - "data": { - "user": { - "id": "user_1705230000000", - "phone": "****8000", - "nickname": "创业者小王", - "referralCode": "REF1705230" - }, - "token": "session_token_xxx" - } -} -``` - ---- - -## 6. 匹配API - -### 6.1 寻找匹配 - -**接口**: `POST /api/match/find` - -**认证**: 需要用户登录 - -**请求**: -```bash -curl -X POST https://your-domain.com/api/match/find \ - -H "Content-Type: application/json" \ - -H "Cookie: session_id=xxx" \ - -d '{ - "mbti": "INTP", - "interests": ["私域运营", "内容创业"] - }' -``` - -**响应**: -```json -{ - "success": true, - "data": { - "matchId": "match_123", - "user": { - "nickname": "创业者小李", - "mbti": "ENTJ", - "interests": ["私域运营", "供应链"], - "matchRate": 85 - }, - "commonInterests": ["私域运营"] - } -} -``` - -### 6.2 匹配历史 - -**接口**: `GET /api/match/history` - -**认证**: 需要用户登录 - -**响应**: -```json -{ - "success": true, - "data": [ - { - "matchId": "match_123", - "nickname": "创业者小李", - "matchRate": 85, - "createdAt": "2026-01-14T10:00:00.000Z" - } - ] -} -``` - ---- - -## 7. 管理后台API - -### 7.1 概览数据 - -**接口**: `GET /api/admin` - -**认证**: 管理员Token - -**响应**: -```json -{ - "success": true, - "data": { - "content": { - "totalChapters": 65, - "totalWords": 120000, - "publishedChapters": 60, - "draftChapters": 5 - }, - "payment": { - "totalRevenue": 12800.50, - "todayRevenue": 560.00, - "totalOrders": 128, - "todayOrders": 12 - }, - "referral": { - "totalReferrers": 45, - "activeReferrers": 28, - "totalCommission": 11520.45 - }, - "users": { - "totalUsers": 1200, - "purchasedUsers": 128, - "activeUsers": 456 - } - } -} -``` - -### 7.2 内容管理 - -**接口**: `GET /api/admin/content` - -**接口**: `POST /api/admin/content` - 创建 - -**接口**: `PUT /api/admin/content/:id` - 更新 - -**接口**: `DELETE /api/admin/content/:id` - 删除 - -### 7.3 订单管理 - -**接口**: `GET /api/admin/payment?status=completed&page=1&limit=20` - -**响应**: -```json -{ - "success": true, - "data": { - "orders": [ - { - "id": "order_123", - "userId": "user_123", - "amount": 9.9, - "status": "completed", - "createdAt": "2026-01-14T10:00:00.000Z" - } - ], - "total": 128, - "page": 1, - "limit": 20 - } -} -``` - ---- - -## 8. 错误码规范 - -### 8.1 HTTP状态码 - -| 状态码 | 含义 | 使用场景 | -|--------|------|----------| -| 200 | 成功 | 请求成功 | -| 201 | 创建成功 | 资源创建成功 | -| 400 | 请求错误 | 参数错误 | -| 401 | 未授权 | 需要登录 | -| 403 | 禁止访问 | 权限不足 | -| 404 | 未找到 | 资源不存在 | -| 500 | 服务器错误 | 内部错误 | - -### 8.2 业务错误码 - -```typescript -enum ErrorCode { - // 用户相关 - USER_NOT_FOUND = 1001, - USER_ALREADY_EXISTS = 1002, - INVALID_PHONE = 1003, - INVALID_CODE = 1004, - - // 支付相关 - ORDER_NOT_FOUND = 2001, - PAYMENT_FAILED = 2002, - INSUFFICIENT_BALANCE = 2003, - - // 分销相关 - INVALID_REFERRAL_CODE = 3001, - WITHDRAWAL_FAILED = 3002, - INSUFFICIENT_EARNINGS = 3003, - - // 内容相关 - CHAPTER_NOT_FOUND = 4001, - CHAPTER_NOT_PURCHASED = 4002, -} -``` - -**错误响应格式**: -```json -{ - "success": false, - "error": { - "code": 1001, - "message": "用户不存在", - "details": "用户ID: user_123" - } -} -``` - ---- - -## 9. 接口性能优化 - -### 9.1 缓存策略 - -**内容缓存**: -```typescript -// 章节内容缓存1小时 -res.setHeader('Cache-Control', 'public, max-age=3600') - -// 章节列表缓存10分钟 -res.setHeader('Cache-Control', 'public, max-age=600') -``` - -**ETag**: -```typescript -const etag = generateETag(content) -res.setHeader('ETag', etag) - -if (req.headers['if-none-match'] === etag) { - return res.status(304).end() -} -``` - -### 9.2 限流策略 - -```typescript -// 接口限流: 100次/分钟 -const limiter = { - '/api/book/all-chapters': { limit: 100, window: 60 }, - '/api/payment/create-order': { limit: 10, window: 60 }, - '/api/admin/*': { limit: 1000, window: 60 } -} -``` - ---- - -**总结**: API设计遵循RESTful规范,响应格式统一,错误处理清晰。所有接口都有明确的认证要求和错误处理。核心功能包括内容获取、支付流程、分销系统、用户管理、匹配功能。 diff --git a/开发文档/5、接口/在线支付对接文档.md b/开发文档/5、接口/在线支付对接文档.md deleted file mode 100644 index 27c8bf8c..00000000 --- a/开发文档/5、接口/在线支付对接文档.md +++ /dev/null @@ -1,319 +0,0 @@ -# 在线支付对接文档 - -本文档根据当前项目中的支付相关代码与配置反向整理,供前端/第三方/运维对接使用。后端当前为 **soul-api(Go/Gin)**,支付业务逻辑可参考 **next-project** 中的实现。 - ---- - -## 一、概述 - -- **支付方式**:微信支付(Native 扫码 / JSAPI 小程序·公众号 / H5)、支付宝(WAP / Web / 扫码)。 -- **对接入口**:统一走 soul-api 的 `/api` 前缀(如 `https://your-api.com/api/...`)。 -- **回调**:支付平台(微信/支付宝)会主动 POST 到服务端配置的 notify 地址,需公网可访问且返回约定格式。 - ---- - -## 二、接口清单(soul-api) - -| 方法 | 路径 | 说明 | -|-----|------|------| -| POST | `/api/payment/create-order` | 创建支付订单,返回支付参数(二维码/链接/JSAPI 参数等) | -| GET | `/api/payment/methods` | 获取可用支付方式列表 | -| GET | `/api/payment/query` | 按交易号查询支付状态(轮询用) | -| GET | `/api/payment/status/:orderSn` | 按订单号查询订单支付状态 | -| POST | `/api/payment/verify` | 支付结果校验(可选) | -| POST | `/api/payment/callback` | 通用支付回调(可选,与各平台 notify 二选一或并存) | -| POST | `/api/payment/wechat/notify` | 微信支付异步通知 | -| POST | `/api/payment/alipay/notify` | 支付宝异步通知 | -| POST | `/api/payment/wechat/transfer/notify` | 微信转账/企业付款到零钱回调(若启用) | -| GET/POST | `/api/miniprogram/pay` | 小程序下单(创建订单 + 返回微信支付参数) | -| POST | `/api/miniprogram/pay/notify` | 小程序支付异步通知 | - -管理端(需鉴权): - -| 方法 | 路径 | 说明 | -|-----|------|------| -| GET/POST/PUT/DELETE | `/api/admin/payment` | 支付相关配置管理 | - ---- - -## 三、请求与响应约定 - -以下格式以 next-project 中已实现逻辑为对接规范,soul-api 实现时应与之兼容。 - -### 3.1 创建订单 `POST /api/payment/create-order` - -**请求体(JSON)** - -| 字段 | 类型 | 必填 | 说明 | -|------|------|------|------| -| userId | string | 是 | 用户 ID | -| type | string | 是 | 购买类型:`section`(单章) / `fullbook`(全书) | -| sectionId | string | type=section 时 | 章节 ID,如 `1-1` | -| sectionTitle | string | 建议 | 章节标题,用于展示与订单描述 | -| amount | number | 是 | 金额(元),如 9.9 | -| paymentMethod | string | 是 | 支付方式:`wechat` / `alipay` | -| referralCode | string | 否 | 推荐人邀请码,用于分销 | - -**响应(JSON)** - -```json -{ - "code": 200, - "message": "订单创建成功", - "data": { - "orderSn": "20260209123456", - "tradeSn": "T2026020912000012345", - "userId": "user_xxx", - "type": "section", - "sectionId": "1-1", - "sectionTitle": "第一章", - "amount": 9.9, - "paymentMethod": "wechat", - "status": "created", - "createdAt": "2026-02-09T12:00:00.000Z", - "expireAt": "2026-02-09T12:30:00.000Z", - "paymentData": { - "type": "qrcode", - "payload": "weixin://wxpay/...", - "tradeSn": "T2026020912000012345", - "expiration": 1800 - }, - "gateway": "wechat_native" - } -} -``` - -- **paymentData.type**:`qrcode`(二维码内容/链接)、`url`(跳转链接)、`json`(JSAPI 等参数对象)。 -- **paymentData.payload**:微信 Native 为二维码链接;支付宝 WAP 为支付 URL;JSAPI 为 `{ timeStamp, nonceStr, package, signType, paySign }` 等。 -- **gateway**:用于后续轮询时传 `gateway`,如 `wechat_native`、`alipay_wap`。 - -**错误**:`code: 400` 表示缺少必要参数;`code: 500` 为服务器错误。 - ---- - -### 3.2 支付方式列表 `GET /api/payment/methods` - -**响应** - -```json -{ - "code": 200, - "message": "success", - "data": { - "methods": [ - { - "gateway": "wechat_native", - "name": "微信支付", - "icon": "wechat", - "enabled": true, - "available": true - } - ] - } -} -``` - ---- - -### 3.3 查询支付状态(轮询)`GET /api/payment/query` - -**Query** - -| 参数 | 类型 | 必填 | 说明 | -|------|------|------|------| -| tradeSn | string | 是 | 创建订单时返回的 tradeSn | -| gateway | string | 否 | 指定网关,如 `wechat_native`、`alipay_wap`,不传则双通道查询 | - -**响应** - -```json -{ - "code": 200, - "message": "success", - "data": { - "tradeSn": "T2026020912000012345", - "status": "paid", - "platformSn": "4200001234567890", - "payAmount": 990, - "payTime": "2026-02-09T12:05:00.000Z", - "gateway": "wechat_native" - } -} -``` - -- **status**:`paying` 未支付,`paid` 已支付,`closed` 已关闭/退款等。 -- **payAmount**:单位「分」。**payTime** 为支付完成时间。 - -前端建议:每 3 秒轮询一次,最多约 60 次(约 3 分钟);收到 `status: "paid"` 后停止轮询并更新订单/解锁内容。 - ---- - -### 3.4 按订单号查状态 `GET /api/payment/status/:orderSn` - -**路径参数**:`orderSn` 为创建订单返回的订单号。 - -**响应** - -```json -{ - "code": 200, - "message": "success", - "data": { - "orderSn": "20260209123456", - "status": "paid", - "paidAmount": 9.9, - "paidAt": "2026-02-09T12:05:00.000Z", - "paymentMethod": "wechat", - "tradeSn": "T2026020912000012345", - "productType": "section" - } -} -``` - -- **status**:与业务一致:`created`、`paying`、`paid`、`closed`、`refunded` 等。 - ---- - -### 3.5 支付校验 `POST /api/payment/verify` - -**请求体** - -| 字段 | 类型 | 说明 | -|------|------|------| -| orderId | string | 订单号 | -| paymentMethod | string | 支付方式 | -| transactionId | string | 第三方交易号(可选) | - -**响应**:成功时 `code: 0`,失败时非 0;用于前端在回调不确定时的二次校验(具体逻辑由后端实现)。 - ---- - -## 四、支付平台异步通知(回调) - -对接方需在微信支付/支付宝商户后台配置「支付结果通知 URL」,且必须为 **公网 HTTPS**。当前项目约定路径如下(以 soul-api 域名为准): - -| 支付方式 | 通知 URL | 说明 | -|----------|----------|------| -| 微信支付 | `https://your-api.com/api/payment/wechat/notify` | 统一下单/JSAPI/小程序等 | -| 支付宝 | `https://your-api.com/api/payment/alipay/notify` | 异步 notify | -| 微信转账 | `https://your-api.com/api/payment/wechat/transfer/notify` | 企业付款到零钱(若使用) | - -### 4.1 微信支付 notify - -- **方法**:POST -- **Content-Type**:`application/xml` -- **Body**:微信以 XML 推送,字段含 `return_code`、`result_code`、`out_trade_no`、`transaction_id`、`total_fee`、`time_end`、`sign` 等。 -- **验签**:使用商户密钥对微信参数做 MD5 签名校验(见 next-project `lib/payment/wechat.ts` 中 `verifySign`)。 -- **响应**:必须返回 XML,成功示例: - `` - 失败则返回 `return_code=FAIL`,否则微信会重试。 - -**业务处理建议**(与 next-project 一致): -1. 验签通过且 `result_code=SUCCESS` 后,用 `out_trade_no`(即本系统 tradeSn)查订单,更新为已支付、写入 `transaction_id`、`pay_time`。 -2. 根据 `product_type` 开通全书或章节权限。 -3. 若有推荐人,写分销表并更新 `pending_earnings`。 -4. 响应必须在业务异常时仍返回成功 XML,避免微信重复通知。 - -### 4.2 支付宝 notify - -- **方法**:POST -- **Content-Type**:`application/x-www-form-urlencoded` -- **Body**:表单键值对,含 `out_trade_no`、`trade_no`、`trade_status`、`total_amount`、`gmt_payment`、`sign` 等。 -- **验签**:使用配置的 MD5 密钥校验(见 next-project `lib/payment/alipay.ts`)。 -- **响应**:纯文本,成功返回 `success`,失败返回 `fail`。支付宝会多次重试直至收到 `success`。 - -**业务处理**:与微信类似,以 `out_trade_no` 更新订单、开通权限、处理分销。 - ---- - -## 五、小程序支付 - -### 5.1 下单 `GET/POST /api/miniprogram/pay` - -**请求体(JSON)** - -| 字段 | 类型 | 必填 | 说明 | -|------|------|------|------| -| openId | string | 是 | 用户 openId | -| productType | string | 是 | `section` / `fullbook` | -| productId | string | 是 | 章节 ID 或 `fullbook` | -| amount | number | 是 | 金额(元) | -| description | string | 建议 | 订单描述 | -| userId | string | 是 | 用户 ID | - -**响应** - -```json -{ - "success": true, - "data": { - "orderSn": "MP20260204123456789012", - "prepayId": "wx...", - "payParams": { - "timeStamp": "...", - "nonceStr": "...", - "package": "prepay_id=...", - "signType": "MD5", - "paySign": "..." - } - } -} -``` - -小程序端用 `payParams` 调起 `wx.requestPayment`。 - -### 5.2 小程序支付通知 `POST /api/miniprogram/pay/notify` - -与「微信支付 notify」同一套规范(XML 入参、XML 成功响应)。商户后台配置的「支付结果通知 URL」填 soul-api 的 `/api/miniprogram/pay/notify` 或统一使用 `/api/payment/wechat/notify` 均可,需与后端实现一致(按订单来源更新对应订单与权限)。 - ---- - -## 六、配置项 - -### 6.1 管理端 / 配置接口 - -- **GET /api/config**:返回全站配置,其中 **paymentMethods** 用于前端展示支付方式及微信/支付宝相关配置(如微信群二维码、商户信息等)。 -- 支付开关、商户号、密钥等建议放在服务端环境变量或管理端「支付配置」中,不通过公开接口暴露密钥。 - -### 6.2 环境变量(参考 next-project) - -后端若自实现支付,可参考以下变量(soul-api 当前未在 .env.example 中列出,对接时按需增加): - -**微信** - -- `WECHAT_APPID` / `WECHAT_SERVICE_APPID`:公众号/服务号 AppID -- `WECHAT_APP_SECRET` / `WECHAT_SERVICE_SECRET` -- `WECHAT_MCH_ID`:商户号 -- `WECHAT_MCH_KEY`:商户 API 密钥 - -**支付宝** - -- `ALIPAY_APP_ID` / `ALIPAY_PID` -- `ALIPAY_PRIVATE_KEY` / `ALIPAY_PUBLIC_KEY` 或 `ALIPAY_MD5_KEY` -- `ALIPAY_SELLER_EMAIL` - -**应用** - -- `NEXT_PUBLIC_BASE_URL` 或等价「站点 base URL」:用于拼装 notify/return 地址。 - ---- - -## 七、订单与数据库(参考) - -- **orders 表**:`id`、`order_sn`、`user_id`、`open_id`、`product_type`、`product_id`、`amount`、`description`、`status`、`transaction_id`、`pay_time`、`referral_code`、`referrer_id`、`created_at`、`updated_at`。 -- **status**:`created` → 创建,`paid` → 已支付,`expired`/`cancelled` 等由业务定义。 -- 创建订单时可将 **tradeSn** 写入 `transaction_id`,支付回调里用微信/支付宝的「商户订单号」即 tradeSn 查单并更新为 `transaction_id`(平台交易号)、`pay_time`、`status=paid`。 - ---- - -## 八、错误与注意事项 - -1. **签名**:所有微信/支付宝回调必须先验签再执行业务,否则存在伪造风险。 -2. **幂等**:同一笔订单可能被多次通知,更新订单与佣金前应判断当前状态,避免重复加款。 -3. **响应**:notify 接口必须在处理完(或确认可稍后处理)后按平台要求返回成功(微信 XML 成功、支付宝 `success`),再异步做后续逻辑,避免平台反复回调。 -4. **金额**:微信为「分」,支付宝为「元」;内部建议统一用「分」存储,与 next-project 一致。 -5. **soul-api 现状**:当前 payment/miniprogram 相关 handler 为占位实现(直接返回 success),完整逻辑需按本文档与 next-project 实现对齐后上线。 - ---- - -*文档根据项目代码反向整理,若与最新代码不一致,以实际仓库为准。* diff --git a/开发文档/5、接口/接口与提现.md b/开发文档/5、接口/接口与提现.md deleted file mode 100644 index 58cbe96b..00000000 --- a/开发文档/5、接口/接口与提现.md +++ /dev/null @@ -1,11 +0,0 @@ -# 接口与提现(合并自 接口定义规范、提现功能完整技术文档) - -## 接口规范 - -RESTful,JSON 返回。基础 URL 开发 localhost:3000/api,生产 soul.quwanzhi.com/api。统一格式:`{ code, message, data }`。 - -## 提现功能 - -微信支付商家转账到零钱 API,签名算法、加解密、完整实现、测试验证。流程:用户申请 → 审核 → 调 API → 回调更新状态。 - -详见原《接口定义规范》《提现功能完整技术文档》。 diff --git a/开发文档/5、接口/配置清单-完整版.md b/开发文档/5、接口/配置清单-完整版.md deleted file mode 100644 index 1ca859a7..00000000 --- a/开发文档/5、接口/配置清单-完整版.md +++ /dev/null @@ -1,205 +0,0 @@ -# Soul创业实验 - API密钥与配置清单 - -> 最后更新: 2026-01-25 -> 维护人: 卡若 -> ⚠️ 本文件包含敏感信息,请勿公开 - ---- - -## 一、企业信息 - -| 项目 | 值 | -|:---|:---| -| **企业名称** | 泉州市卡若网络技术有限公司 | -| **联系电话** | 15880802661 | -| **微信号** | 28533368 | -| **邮箱** | zhiqun@qq.com / zhengzhiqun@vip.qq.com | - ---- - -## 二、微信生态 - -### 2.1 小程序(Soul创业实验) - -| 项目 | 值 | 备注 | -|:---|:---|:---| -| **AppID** | `wxb8bbb2b10dec74aa` | 小程序ID | -| **AppSecret** | `3c1fb1f63e6e052222bbcead9d07fe0c` | 小程序密钥 | -| **支付绑定状态** | 🟡 审核中 | 2026-01-25 09:43:59 提交 | - -### 2.2 服务号(玩值) - -| 项目 | 值 | 备注 | -|:---|:---|:---| -| **AppID** | `wx7c0dbf34ddba300d` | 服务号AppID | -| **AppSecret** | `f865ef18c43dfea6cbe3b1f1aebdb82e` | 服务号密钥 | -| **支付绑定状态** | ✅ 已绑定 | 绑定AppID: wx3e31b068be59ddc1 | - -### 2.3 网站应用 - -| 项目 | 值 | -|:---|:---| -| **AppID** | `wx432c93e275548671` | -| **AppSecret** | `25b7e7fdb7998e5107e242ebb6ddabd0` | - -### 2.4 微信支付 - -| 项目 | 值 | 备注 | -|:---|:---|:---| -| **商户号** | `1318592501` | 主体: 泉州市卡若网络技术有限公司 | -| **API密钥(v2)** | `wx3e31b068be59ddc131b068be59ddc2` | 32位 | -| **MP文件验证码** | `SP8AfZJyAvprRORT` | | -| **支付回调地址** | `https://soul.quwanzhi.com/api/miniprogram/pay/notify` | | - -#### 已绑定AppID - -| AppID | 类型 | 状态 | -|:---|:---|:---| -| `wx3e31b068be59ddc1` | 服务号 | ✅ 已关联 | -| `wxb8bbb2b10dec74aa` | 小程序 | 🟡 审核中 | - ---- - -## 三、支付宝 - -| 项目 | 值 | -|:---|:---| -| **PID** | `2088511801157159` | -| **MD5密钥** | `lz6ey1h3kl9zqkgtjz3avb5gk37wzbrp` | -| **账户** | zhengzhiqun@vip.qq.com | - ---- - -## 四、云服务 - -### 4.1 腾讯云 - -| 项目 | 值 | -|:---|:---| -| **APPID** | `1251077262` | -| **SecretId** | `AKIDjc6yO3nPeOuK2OKsJPBBVbTiiz0aPNHl` | -| **SecretKey** | *(见用户规则)* | - -### 4.2 阿里云 - -| 项目 | 值 | -|:---|:---| -| **AccessKey ID** | `LTAI5t9zkiWmFtHG8qmtdysW` | -| **AccessKey Secret** | `xxjXnZGLNvA2zDkj0aEBSQm3XZAaro` | - ---- - -## 五、数据库 - -### 5.1 腾讯云MySQL(生产环境) - -| 项目 | 值 | -|:---|:---| -| **主机** | `56b4c23f6853c.gz.cdb.myqcloud.com` | -| **端口** | `14413` | -| **数据库** | `soul_miniprogram` | -| **用户名** | `cdb_outerroot` | -| **密码** | `Zhiqun1984` | -| **字符集** | `utf8mb4` | - -#### 数据库表 - -| 表名 | 说明 | -|:---|:---| -| `users` | 用户表 | -| `orders` | 订单表 | -| `referral_bindings` | 推广绑定关系 | -| `match_records` | 匹配记录 | -| `system_config` | 系统配置 | -| `chapters` | **章节内容表(新)** | - -### 5.2 卡若私域数据库(内网) - -| 项目 | 值 | -|:---|:---| -| **主机** | `10.88.182.62` | -| **端口** | `3306` | -| **用户名** | `root` | -| **密码** | `Vtka(agu)-1` | - ---- - -## 六、AI服务 - -### 6.1 v0 API - -| 项目 | 值 | -|:---|:---| -| **API地址** | `https://api.v0.dev/v1` | -| **API Key** | `v1:C6mw1SlvXsJdlO4VFEXSQEVf:519gA0DPqIMbjvfMh7CXf4B2` | -| **默认模型** | `claude-opus` | - ---- - -## 七、开发工具 - -### 7.1 GitHub - -| 项目 | 值 | -|:---|:---| -| **Token** | `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` | - ---- - -## 八、项目部署信息 - -| 项目 | 值 | -|:---|:---| -| **域名** | `soul.quwanzhi.com` | -| **协议** | HTTPS | -| **服务器** | 宝塔面板 | -| **部署方式** | GitHub Webhook 自动部署 | - ---- - -## 九、邮箱账户 - -| 邮箱 | 密码 | -|:---|:---| -| `zhiqun@qq.com` | `#vtk();1984` | -| `zhengzhiqun@vip.qq.com` | `#vtk();1984` | -| `15880802661@qq.com` | `#vtk();1984` | - ---- - -## 十、配置代码引用 - -### 小程序支付配置 - -```typescript -// lib/payment/wechat-miniprogram.ts -const WECHAT_PAY_CONFIG = { - appId: 'wxb8bbb2b10dec74aa', // 小程序AppID - appSecret: '3c1fb1f63e6e052222bbcead9d07fe0c', // 小程序AppSecret - mchId: '1318592501', // 商户号 - mchKey: 'wx3e31b068be59ddc131b068be59ddc2', // API密钥(v2) - notifyUrl: 'https://soul.quwanzhi.com/api/miniprogram/pay/notify', -} -``` - -### 数据库配置 - -```typescript -// lib/db.ts -const DB_CONFIG = { - host: '56b4c23f6853c.gz.cdb.myqcloud.com', - port: 14413, - user: 'cdb_outerroot', - password: 'Zhiqun1984', - database: 'soul_miniprogram', - charset: 'utf8mb4', -} -``` - ---- - -## 更新日志 - -| 日期 | 更新内容 | -|:---|:---| -| 2026-01-25 | 创建完整配置清单;小程序支付绑定申请中;章节表迁移完成 | diff --git a/开发文档/6、后端/image.png b/开发文档/6、后端/image.png deleted file mode 100644 index b26ffbf4..00000000 Binary files a/开发文档/6、后端/image.png and /dev/null differ diff --git a/开发文档/6、后端/内容创建问题修复说明.md b/开发文档/6、后端/内容创建问题修复说明.md deleted file mode 100644 index a21ec1ea..00000000 --- a/开发文档/6、后端/内容创建问题修复说明.md +++ /dev/null @@ -1,93 +0,0 @@ -# 内容创建问题修复说明 - -> 问题:souladmin 添加内容后显示「创建成功」,但目录和数据库未增加,前端也未显示。 - -## 根因分析 - -1. **两套后台数据源不一致** - - souladmin.quwanzhi.com 调用 soulapi.quwanzhi.com(Go API) - - soul.quwanzhi.com/admin 使用 Next.js API,list 此前仅从 bookData(静态)读取 - - 新建章节写入数据库,但 list 不查库,导致新建内容不显示 - -2. **PUT 创建未完整支持 partId/chapterId** - - 新建章节时 partId、chapterId、partTitle、chapterTitle 未正确写入数据库 - -## 已做修复 - -### 1. 修改 `/api/db/book` list 接口 -- **原逻辑**:仅从 bookData 读取 -- **现逻辑**:优先从数据库 chapters 表读取,再与 bookData 合并 -- **效果**:新建章节会立即出现在列表中 - -### 2. 修改 PUT 接口支持新建章节 -- 支持 body 传入 `partId`、`chapterId`、`partTitle`、`chapterTitle`、`isFree` -- 新建章节能正确写入数据库 - -### 3. 在 book-data 中新增 9.15 -- 章节 ID: 9.15 -- 标题: 第102场|今年第一个红包你发给谁 -- 文件: book/第四篇|真实的赚钱/第9章|我在Soul上亲访的赚钱案例/9.15 第102场|今年第一个红包你发给谁.md - -### 4. soul-admin 改用 soul.quwanzhi.com 作为 API -- 修改 soul-admin 的 API 基址:soulapi → soul.quwanzhi.com -- 在 Next.js 中为 souladmin.quwanzhi.com 配置 CORS - -## 部署步骤 - -### 步骤 1:部署 soul 主站(小型宝塔) - -```bash -cd /Users/karuo/Documents/开发/3、自营项目/一场soul的创业实验 -# 按 .cursorrules 中的流程执行 -pnpm build -# 然后执行部署脚本 -``` - -### 步骤 2:同步 9.15 到数据库 - -部署后访问 soul.quwanzhi.com/admin,在内容管理页面点击「同步到数据库」,将包含 9.15 的 bookData 同步进库。 - -### 步骤 3:部署修改后的 soul-admin(KR 宝塔) - -```bash -# 将 一场soul的创业实验-永平 中的 soul-admin/dist 上传到 KR 宝塔 -cd /Users/karuo/Documents/开发/3、自营项目/一场soul的创业实验-永平 -tar -czf soul-admin-dist.tar.gz soul-admin/dist -sshpass -p 'Zhiqun1984' scp -P 22022 soul-admin-dist.tar.gz root@43.139.27.93:/tmp/ -sshpass -p 'Zhiqun1984' ssh -p 22022 root@43.139.27.93 " - cd /www/wwwroot/自营/soul-admin - rm -rf dist.bak - mv dist dist.bak 2>/dev/null || true - tar -xzf /tmp/soul-admin-dist.tar.gz -C . - rm /tmp/soul-admin-dist.tar.gz -" -``` - -### 步骤 4:校验 - -1. 打开 souladmin.quwanzhi.com/content -2. 新建章节,确认创建后列表中立即出现 -3. 刷新 soul.quwanzhi.com 主站,确认新章节可读 - -## 注意事项 - -- souladmin 现改为调用 soul.quwanzhi.com,不再调用 soulapi(Go),需确保 soul 主站可用 -- 若仍需使用 Go API,需在 soul-api 源码中修复 list/create 逻辑 - ---- - -## 内容上传 API(供科室/Skill 调用) - -- **地址**:`POST /api/content/upload` -- **Content-Type**:`application/json` -- **Body 字段**: - - `title`(必填):节标题 - - `price`:定价,默认 1 - - `content`:正文(Markdown 或 HTML) - - `format`:`markdown` | `html`,默认 `markdown` - - `images`:图片 URL 数组;正文中可用 `{{image_0}}`、`{{image_1}}` 占位,会替换为对应图片的 Markdown 图链 - - `partId`、`partTitle`、`chapterId`、`chapterTitle`:归属篇/章,可选 - - `isFree`:是否免费,默认 false - - `sectionId`:指定节 ID,不传则自动生成(如 `upload.标题slug.时间戳`) -- **返回**:`{ success, id, message, title, price, isFree, wordCount }` -- 写入数据库 `chapters` 表,list/目录会从库中读取并去重显示。 diff --git a/开发文档/6、后端/后端开发规范.md b/开发文档/6、后端/后端开发规范.md deleted file mode 100644 index 75b360a1..00000000 --- a/开发文档/6、后端/后端开发规范.md +++ /dev/null @@ -1,64 +0,0 @@ -# 后端开发规范 (Backend Specs) - 智能自生长文档 - -> **提示词功能 (Prompt Function)**: 将本文件拖入 AI 对话框,即可激活“Python 后端专家”角色,生成高效、规范的 FastAPI 代码。 - -## 1. 基础上下文 (The Two Basic Files) -### 1.1 角色档案:卡若 (Karuo) -- **核心**:开发快、性能好、支持 AI。 -- **习惯**:优先使用异步 (`async/await`),强制类型提示 (`Type Hints`)。 - -### 1.2 技术栈 -- **语言**:Python 3.10+。 -- **框架**:FastAPI (Web), Pydantic (Validation), LangChain (AI)。 -- **数据**:Motor (Async Mongo), Redis。 - -## 2. 开发规范核心 (Master Content) -### 2.1 代码规范 -- **风格**:遵循 PEP 8,使用 Black 格式化。 -- **类型**:**强制 Type Hints** (如 `def get_user(id: int) -> User:`)。 -- **注释**:**强制中文注释**,解释“业务逻辑”与“AI 处理流程”。 -- **结构**: - - `app/routers`: 路由 - - `app/models`: Pydantic 模型 - - `app/services`: 业务逻辑 - - `app/core`: 配置与工具 - -### 2.2 AI 与安全规范 -- **AI 调用**:所有 LLM 调用必须封装在 Service 层,并包含重试机制与超时控制。 -- **安全**: - - **命令执行**:严禁使用 `os.system`,必须使用 `subprocess` 并校验参数。 - - **SQL/NoSQL**:使用 ORM 或参数化查询,防止注入。 - -### 2.3 异常与日志 -- **异常**:使用 FastAPI `HTTPException` 或自定义 Exception Handler。 -- **日志**:使用 `loguru` 或 Python 标准 `logging`,必须记录 Traceback。 - -### 2.4 依赖管理 -- **工具**:`pip` 或 `poetry`。 -- **原则**:提交代码前更新 `requirements.txt` 或 `pyproject.toml`。 - -## 3. AI 协作指令 (Expanded Function) -**角色**:你是我(卡若)的 Python 架构师。 -**任务**: -1. **代码实现**:生成 FastAPI 的 Router/Model/Service 代码。 -2. **AI 集成**:编写 LangChain 调用逻辑或向量检索代码。 -3. **逻辑图解**:用 Mermaid 展示异步处理流程。 - -### 示例 Mermaid (类图) -\`\`\`mermaid -classDiagram - class UserRouter { - +get_user() - +create_user() - } - class UserService { - +verify_token() - +process_ai_request() - } - class VectorStore { - +search_similarity() - +add_documents() - } - UserRouter --> UserService - UserService --> VectorStore -\`\`\` diff --git a/开发文档/6、后端/后端架构.md b/开发文档/6、后端/后端架构.md deleted file mode 100644 index 16c5f9dd..00000000 --- a/开发文档/6、后端/后端架构.md +++ /dev/null @@ -1,68 +0,0 @@ -# 后端架构与业务逻辑 - -**我是卡若。** - -后端不仅仅是读写数据库,它是**业务逻辑的翻译官**。 - -我们要把“私域引流”、“内容分发”这些生意话术,翻译成代码逻辑。 - -## 1. 核心业务模块 - -### 1.1 内容服务 (Content Service) -这是最基础的。 -- **逻辑**: - - 扫描 `book/` 目录,生成目录树 (Tree)。 - - 解析 Markdown,提取 Frontmatter (标题、日期、标签)。 - - **缓存策略**: 既然是读文件,IO 慢。要在内存里做一个 LRU 缓存,读取一次后由内存直接返回,直到文件发生变更。 - -### 1.2 配置服务 (Config Service) -我的微信号、群二维码、价格,这些东西会变,不能写死在代码里。 -- **实现**: - - 一个 `config/settings.json` 文件(或者未来的 MongoDB `settings` 表)。 - - 接口: `GET /api/config`。 - - 前端拿到配置,动态展示微信号。 - -### 1.3 引流服务 (Lead Service) -这是赚钱的关键。 -- **埋点逻辑**: - - 记录 `UserView` (用户看了哪章)。 - - 记录 `UserClick` (用户点了“加微信”)。 - - 虽然不存库,但可以先打到日志文件里,或者调一个飞书的 Webhook,实时通知我“有人对这章感兴趣”。 - -## 2. 接口设计原则 - -- **RESTful**: 资源导向。`GET /articles`, `GET /articles/:id`。 -- **统一响应体**: - \`\`\`typescript - interface ApiResponse { - code: number; // 0 成功, >0 错误 - data: T; - msg: string; - } - \`\`\` - -## 3. 目录结构 (后端专用) - -\`\`\` -app/api/ -├── content/ # 内容相关 -├── config/ # 全局配置 -└── track/ # 埋点上报 - -lib/ -├── content/ -│ ├── parser.ts # Markdown 解析器 -│ └── cache.ts # 内存缓存 -├── config/ -│ └── loader.ts # 配置加载器 -└── db/ # 数据库连接 (预留) -\`\`\` - -## 4. 扩展性预留 - -- **鉴权中间件**: 现在是裸奔,未来加 `middleware.ts` 拦截 `/admin` 开头的请求。 -- **任务队列**: 未来如果生成文档太慢,就扔到 Redis 队列里异步处理。 - ---- -**卡若说:** -后端代码要写得像瑞士军刀一样,功能明确,结实耐用。 diff --git a/开发文档/6、后端/小程序支付参数.png b/开发文档/6、后端/小程序支付参数.png deleted file mode 100644 index 16d1881b..00000000 Binary files a/开发文档/6、后端/小程序支付参数.png and /dev/null differ diff --git a/开发文档/6、后端/管理端鉴权设计.md b/开发文档/6、后端/管理端鉴权设计.md deleted file mode 100644 index da90e194..00000000 --- a/开发文档/6、后端/管理端鉴权设计.md +++ /dev/null @@ -1,120 +0,0 @@ -# soul-api 管理端登录判断与权限校验 - -> 来源:soul-api/管理端鉴权设计.md。已整理至开发文档。 - ---- - -## 一、有没有登录的依据(JWT) - -**依据:请求中的 JWT。优先从 `Authorization: Bearer ` 读取,兼容从 Cookie `admin_session` 读取。** - -| 项目 | 说明 | -|------|------| -| 推荐方式 | 请求头 `Authorization: Bearer ` | -| 兼容方式 | Cookie 名 `admin_session`,值为 JWT 字符串 | -| JWT 算法 | HS256,密钥为 `ADMIN_SESSION_SECRET` | -| 有效期 | 7 天(exp claim) | -| 载荷 | sub=admin, username, role=admin | -| 校验 | 验签 + 未过期 → 视为已登录 | - -- 配置:`ADMIN_USERNAME` / `ADMIN_PASSWORD` 用于登录校验;`ADMIN_SESSION_SECRET` 用于签发/校验 JWT。 -- 未带有效 JWT → 401。 - ---- - -## 二、权限校验设计(路由分层) - -- **不校验登录**:只做业务逻辑(登录、登出、鉴权检查) - - `GET /api/admin` → 鉴权检查(读 Cookie,有效 200 / 无效 401) - - `POST /api/admin` → 登录(校验账号密码,写 Cookie) - - `POST /api/admin/logout` → 登出(删 Cookie) - -- **必须已登录**:挂 `AdminAuth()` 中间件,从请求读 `admin_session` 并验签+过期,不通过直接 401,不进入 handler - - `/api/admin/*`(如 chapters、content、withdrawals、settings 等) - - `/api/db/*` - -- **其它**:如 `/api/miniprogram/*`、`/api/book/*` 等不加 AdminAuth,按各自接口鉴权(如小程序 token)。 - ---- - -## 三、框图 - -```mermaid -flowchart TB - subgraph 前端["soul-admin 前端"] - A[用户打开后台 / 请求接口] - A --> B{请求类型} - B -->|登录| C[POST /api/admin] - B -->|登出| D[POST /api/admin/logout] - B -->|进后台前检查| E[GET /api/admin] - B -->|业务接口| F[GET/POST /api/admin/xxx] - end - - subgraph 请求["每次请求"] - G[浏览器自动携带 Cookie: admin_session] - G --> H[发往 soul-api] - end - - subgraph soul-api["soul-api 路由"] - I["/api/admin 三条(无中间件)"] - J["/api/admin/* 与 /api/db/*"] - J --> K[AdminAuth 中间件] - end - - subgraph 鉴权["AdminAuth 与 AdminCheck 逻辑"] - K --> L[从请求读 Cookie admin_session] - L --> M{有 Cookie?} - M -->|无| N[401 未授权] - M -->|有| O[解析 exp.signature] - O --> P{未过期 且 验签通过?} - P -->|否| N - P -->|是| Q[放行 / 返回 200] - end - - C --> I - D --> I - E --> I - F --> J - H --> soul-api - I --> E2[GET: 同鉴权逻辑 200/401] - I --> C2[POST: 校验账号密码 写 Cookie] - I --> D2[POST: 清 Cookie] -``` - -**路由与中间件关系:** - -```mermaid -flowchart LR - subgraph 无鉴权["不经过 AdminAuth"] - R1[GET /api/admin] - R2[POST /api/admin] - R3[POST /api/admin/logout] - end - - subgraph 需登录["经过 AdminAuth"] - R4["/api/admin/chapters"] - R5["/api/admin/withdrawals"] - R6["/api/admin/settings"] - R7["/api/db/*"] - end - - subgraph 中间件["AdminAuth()"] - M[读 Cookie → 验 token → 通过/401] - end - - H1[直接进 handler] - H2[通过则进 handler] - 无鉴权 --> H1 - 需登录 --> M --> H2 -``` - ---- - -## 四、相关代码位置 - -| 作用 | 位置 | -|------|------| -| JWT 签发/校验/从请求取 token | `internal/auth/adminjwt.go` | -| 登录、登出、GET 鉴权检查 | `internal/handler/admin.go` | -| 管理端中间件 | `internal/middleware/admin_auth.go` | -| 路由挂载 | `internal/router/router.go`(api.Group + admin.Use(AdminAuth())) | diff --git a/开发文档/7、数据库/数据库管理规范.md b/开发文档/7、数据库/数据库管理规范.md deleted file mode 100644 index ce5debae..00000000 --- a/开发文档/7、数据库/数据库管理规范.md +++ /dev/null @@ -1,62 +0,0 @@ -# 数据库管理规范 (DB Specs) - 智能自生长文档 - -> **提示词功能 (Prompt Function)**: 将本文件拖入 AI 对话框,即可激活“DBA”角色,生成安全的 SQL/Mongo 脚本与 ER 图。 - -## 1. 基础上下文 (The Two Basic Files) -### 1.1 角色档案:卡若 (Karuo) -- **核心**:数据无价,安全第一。 -- **选型**:Mongo (业务+向量) + MySQL (事务/辅助)。 - -### 1.2 操作规范 -- **导入**:必须带 `--resumeFrom` 和 `--drop` (防止重复/中断)。 -- **命名**:`traffic_pools` (严禁 `traffic_words`)。 - -## 2. 数据库规范核心 (Master Content) -### 2.1 选型策略 -- **MongoDB**: - - **业务数据**:用户、日志、流量池。 - - **AI 向量**:存储 Embedding 向量 (Atlas Vector Search)。 -- **MySQL**: 强事务资金流水 (如需)。 - -### 2.2 连接信息 (Internal) -- **卡若私域**: 10.88.182.62:3306 -- **腾讯云**: 56b4c23f6853c...:14413 -- **Mongo**: (Env Config) - -### 2.3 集合命名 -- `users`: 用户 -- `scenarios`: 场景获客 -- `traffic_pools`: 流量池 (含 `embedding` 字段) -- `orders`: 分润订单 -- `knowledge_base`: AI 知识库 (含 `embedding` 字段) - -### 2.4 AI 向量索引 (Vector Index) -- **字段**:通常命名为 `embedding` 或 `vector`。 -- **索引类型**:使用 KNN 或 ANN 索引 (如 HNSW)。 -- **查询**:支持 `$vectorSearch` (Mongo Atlas) 或类似语义检索语法。 - -### 2.5 安全与索引 -- **安全**:密码 Hash (Argon2), 手机号加密。 -- **常规索引**:`openid`, `mobile`, `inviter_id` 必建索引。 - -## 3. AI 协作指令 (Expanded Function) -**角色**:你是我(卡若)的 DBA。 -**任务**: -1. **脚本生成**:生成 MongoDB 聚合查询 (`aggregate`) 或 MySQL DDL/DML。 -2. **向量配置**:生成向量索引的定义 JSON。 -3. **结构可视化**:用 Mermaid 生成 ER 图。 - -### 示例 Mermaid (ER图) -\`\`\`mermaid -erDiagram - User ||--o{ Order : places - User ||--o{ TrafficPool : owns - TrafficPool { - string content - array embedding "Vector[1536]" - } - Order { - string orderId - float amount - } -\`\`\` diff --git a/开发文档/7、数据库/数据库设计.md b/开发文档/7、数据库/数据库设计.md deleted file mode 100644 index 3d4d6089..00000000 --- a/开发文档/7、数据库/数据库设计.md +++ /dev/null @@ -1,708 +0,0 @@ -# 数据库设计 - -**我是卡若。** - -这个项目当前使用LocalStorage做数据持久化,但未来会切换到MongoDB。这个文档定义了完整的数据库设计方案。 - ---- - -## 一、数据库选型 - -### 1.1 为什么选MongoDB? - -1. **文档型数据库**: 适合内容类产品,数据结构灵活 -2. **无Schema约束**: 快速迭代不需要频繁改表结构 -3. **JSON原生支持**: 前后端数据格式一致 -4. **横向扩展能力**: 支持未来大规模用户增长 -5. **向量搜索支持**: MongoDB Atlas支持向量检索(未来AI功能) - -### 1.2 当前方案 vs 未来方案 - -**当前方案** (LocalStorage): -\`\`\`javascript -// 优点 -- 无需服务器 -- 开发调试方便 -- 适合MVP验证 - -// 缺点 -- 数据仅存浏览器本地 -- 多设备无法同步 -- 数据容易丢失 -\`\`\` - -**未来方案** (MongoDB): -\`\`\`javascript -// 优点 -- 数据持久化存储 -- 多设备数据同步 -- 支持复杂查询 -- 支持事务(ACID) - -// 迁移计划 -1. 安装MongoDB驱动 -2. 创建数据库连接 -3. 逐步替换LocalStorage -4. 添加数据迁移脚本 -\`\`\` - ---- - -## 二、数据库连接配置 - -### 2.1 本地开发环境 - -\`\`\`bash -# MongoDB本地安装 -brew install mongodb-community@6.0 - -# 启动MongoDB -brew services start mongodb-community@6.0 - -# 连接字符串 -mongodb://localhost:27017/soul-experiment -\`\`\` - -### 2.2 生产环境 (MongoDB Atlas) - -\`\`\`bash -# 连接字符串 -mongodb+srv://:@cluster0.mongodb.net/soul-experiment?retryWrites=true&w=majority -\`\`\` - -### 2.3 环境变量配置 - -**.env.local**: -\`\`\`bash -# MongoDB配置 -MONGODB_URI=mongodb://localhost:27017/soul-experiment -MONGODB_DB_NAME=soul-experiment - -# 或使用云数据库 -# MONGODB_URI=mongodb://10.88.182.62:3306/soul-experiment -# MONGODB_USERNAME=root -# MONGODB_PASSWORD=Vtka(agu)-1 -\`\`\` - ---- - -## 三、数据模型设计 - -### 3.1 用户集合 (users) - -**集合名称**: `users` - -**索引**: -\`\`\`javascript -{ - phone: 1, // 唯一索引 - referralCode: 1, // 唯一索引 - referredBy: 1, // 普通索引 - createdAt: -1 // 降序索引 -} -\`\`\` - -**文档结构**: -\`\`\`javascript -{ - _id: ObjectId("65a1234567890abcdef12345"), - phone: "15880802661", // 手机号 - nickname: "卡若", // 昵称 - avatar: "https://cdn.example.com/avatar.jpg", // 头像 - openid: "wx_openid_xxx", // 微信openid - unionid: "wx_unionid_xxx", // 微信unionid - - // 购买记录 - purchasedSections: [ // 已购章节 - "1.1", "1.2", "3.3" - ], - hasFullBook: false, // 是否购买整本书 - - // 分销数据 - referralCode: "REFABC123", // 推荐码 - referredBy: "REFXYZ789", // 推荐人的码 - referralCount: 28, // 推荐人数 - earnings: 256.80, // 总收益(元) - pendingEarnings: 128.90, // 待提现(元) - withdrawnEarnings: 127.90, // 已提现(元) - - // 阅读数据 - readingTime: 12480, // 阅读时长(秒) - readingProgress: 45, // 阅读进度(%) - lastReadSection: "3.2", // 最后阅读章节 - lastReadAt: ISODate("2025-01-14T12:00:00Z"), - - // 权限 - isAdmin: false, // 是否管理员 - isBanned: false, // 是否封禁 - - // 时间戳 - createdAt: ISODate("2025-01-01T00:00:00Z"), - updatedAt: ISODate("2025-01-14T12:00:00Z") -} -\`\`\` - -**查询示例**: -\`\`\`javascript -// 根据手机号查找用户 -db.users.findOne({ phone: "15880802661" }) - -// 根据推荐码查找用户 -db.users.findOne({ referralCode: "REFABC123" }) - -// 查找某推荐人的所有下级 -db.users.find({ referredBy: "REFABC123" }) - -// 查找收益前10的推广者 -db.users.find({}).sort({ earnings: -1 }).limit(10) -\`\`\` - ---- - -### 3.2 订单集合 (orders) - -**集合名称**: `orders` - -**索引**: -\`\`\`javascript -{ - orderId: 1, // 唯一索引 - userId: 1, // 普通索引 - status: 1, // 普通索引 - createdAt: -1 // 降序索引 -} -\`\`\` - -**文档结构**: -\`\`\`javascript -{ - _id: ObjectId("65a1234567890abcdef12345"), - orderId: "ORDER_1705200000_abc123", // 订单号 - userId: ObjectId("65a1234567890abcdef00001"), // 用户ID - userPhone: "15880802661", // 用户手机号 - userNickname: "卡若", // 用户昵称 - - // 订单信息 - type: "section", // "section" | "fullbook" - sectionId: "1.1", // 章节ID(单章购买时) - sectionTitle: "自行车荷总...", // 章节标题 - amount: 1.00, // 金额(元) - - // 支付信息 - paymentMethod: "wechat", // 支付方式 - transactionId: "wx_pay_123456789", // 第三方交易号 - status: "completed", // "pending" | "completed" | "failed" | "refunded" - - // 分销信息 - referralCode: "REFXYZ789", // 推荐码 - referrerUserId: ObjectId("65a1234567890abcdef00002"), // 推荐人ID - referrerEarnings: 0.90, // 推荐人佣金(元) - - // 时间戳 - createdAt: ISODate("2025-01-14T12:00:00Z"), // 创建时间 - paidAt: ISODate("2025-01-14T12:05:00Z"), // 支付时间 - expireAt: ISODate("2025-01-14T12:30:00Z"), // 过期时间(30分钟) - updatedAt: ISODate("2025-01-14T12:05:00Z") -} -\`\`\` - -**查询示例**: -\`\`\`javascript -// 查找用户所有订单 -db.orders.find({ userId: ObjectId("65a...") }).sort({ createdAt: -1 }) - -// 查找待支付订单 -db.orders.find({ status: "pending", expireAt: { $gt: new Date() } }) - -// 统计今日收益 -db.orders.aggregate([ - { $match: { - status: "completed", - paidAt: { - $gte: ISODate("2025-01-14T00:00:00Z"), - $lt: ISODate("2025-01-15T00:00:00Z") - } - }}, - { $group: { - _id: null, - totalRevenue: { $sum: "$amount" }, - totalOrders: { $sum: 1 } - }} -]) - -// 查找某推荐人的所有佣金记录 -db.orders.find({ - referralCode: "REFABC123", - status: "completed" -}) -\`\`\` - ---- - -### 3.3 提现记录集合 (withdrawals) - -**集合名称**: `withdrawals` - -**索引**: -\`\`\`javascript -{ - userId: 1, // 普通索引 - status: 1, // 普通索引 - createdAt: -1 // 降序索引 -} -\`\`\` - -**文档结构**: -\`\`\`javascript -{ - _id: ObjectId("65a1234567890abcdef12345"), - withdrawalId: "WD_1705200000_abc123", // 提现单号 - userId: ObjectId("65a1234567890abcdef00001"), // 用户ID - userPhone: "15880802661", // 用户手机号 - userNickname: "卡若", // 用户昵称 - - // 提现信息 - amount: 100.00, // 提现金额(元) - method: "wechat", // "wechat" | "alipay" - account: "微信号或支付宝账号", - name: "真实姓名", - - // 状态 - status: "pending", // "pending" | "completed" | "rejected" - rejectReason: "", // 拒绝原因 - - // 时间戳 - createdAt: ISODate("2025-01-14T12:00:00Z"), // 申请时间 - completedAt: ISODate("2025-01-14T14:00:00Z"), // 完成时间 - updatedAt: ISODate("2025-01-14T14:00:00Z") -} -\`\`\` - -**查询示例**: -\`\`\`javascript -// 查找待审核提现 -db.withdrawals.find({ status: "pending" }).sort({ createdAt: 1 }) - -// 查找用户提现记录 -db.withdrawals.find({ userId: ObjectId("65a...") }).sort({ createdAt: -1 }) - -// 统计今日提现金额 -db.withdrawals.aggregate([ - { $match: { - status: "completed", - completedAt: { - $gte: ISODate("2025-01-14T00:00:00Z"), - $lt: ISODate("2025-01-15T00:00:00Z") - } - }}, - { $group: { - _id: null, - totalAmount: { $sum: "$amount" }, - totalCount: { $sum: 1 } - }} -]) -\`\`\` - ---- - -### 3.4 章节内容集合 (sections) - -**集合名称**: `sections` - -**索引**: -\`\`\`javascript -{ - sectionId: 1, // 唯一索引 - isFree: 1, // 普通索引 - createdAt: -1 // 降序索引 -} -\`\`\` - -**文档结构**: -\`\`\`javascript -{ - _id: ObjectId("65a1234567890abcdef12345"), - sectionId: "1.1", // 章节ID - - // 章节信息 - title: "自行车荷总:一个行业做到极致是什么样", - content: "# 自行车荷总\n\n...", // Markdown内容 - summary: "本章讲述了...", // 摘要 - keywords: ["创业", "行业深耕"], // 关键词 - - // 层级关系 - partId: "part-1", // 所属篇 - partTitle: "真实的人", - chapterId: "chapter-1", // 所属章 - chapterTitle: "人与人之间的底层逻辑", - - // 定价 - price: 1, // 价格(元) - isFree: true, // 是否免费 - unlockAfterDays: 0, // 定时解锁(天数) - - // 统计数据 - viewCount: 1234, // 浏览次数 - purchaseCount: 456, // 购买次数 - avgReadingTime: 180, // 平均阅读时长(秒) - - // 文件信息 - filePath: "book/_第一篇|真实的人/...", - wordCount: 3580, // 字数 - - // 发布状态 - status: "published", // "draft" | "published" - publishedAt: ISODate("2025-01-01T00:00:00Z"), - - // 时间戳 - createdAt: ISODate("2025-01-01T00:00:00Z"), - updatedAt: ISODate("2025-01-14T12:00:00Z") -} -\`\`\` - -**查询示例**: -\`\`\`javascript -// 获取所有免费章节 -db.sections.find({ isFree: true }) - -// 获取最新发布的10章 -db.sections.find({ status: "published" }) - .sort({ publishedAt: -1 }) - .limit(10) - -// 按浏览量排序 -db.sections.find().sort({ viewCount: -1 }).limit(10) - -// 全文搜索(需创建文本索引) -db.sections.createIndex({ - title: "text", - content: "text", - keywords: "text" -}) -db.sections.find({ $text: { $search: "创业 私域" } }) -\`\`\` - ---- - -### 3.5 阅读记录集合 (reading_logs) - -**集合名称**: `reading_logs` - -**索引**: -\`\`\`javascript -{ - userId: 1, - sectionId: 1, - createdAt: -1 -} -\`\`\` - -**文档结构**: -\`\`\`javascript -{ - _id: ObjectId("65a1234567890abcdef12345"), - userId: ObjectId("65a1234567890abcdef00001"), - sectionId: "3.2", - - // 阅读数据 - progress: 68, // 阅读进度(%) - readingTime: 180, // 阅读时长(秒) - scrollDepth: 75, // 滚动深度(%) - - // 设备信息 - device: "iPhone 14 Pro", - browser: "Safari", - ip: "121.xxx.xxx.xxx", - - // 时间戳 - createdAt: ISODate("2025-01-14T12:00:00Z") -} -\`\`\` - ---- - -### 3.6 系统配置集合 (settings) - -**集合名称**: `settings` - -**文档结构**: -\`\`\`javascript -{ - _id: "global_settings", - - // 分润配置 - distributorShare: 90, // 推广者分成(%) - authorShare: 10, // 作者分成(%) - - // 定价配置 - sectionPrice: 1, // 单章价格(元) - fullBookPrice: 9.9, // 整书价格(元) - - // 支付配置 - paymentMethods: { - wechat: { - enabled: true, - appId: "wx432c93e275548671", - merchantId: "1318592501", - apiKey: "***" - }, - alipay: { - enabled: true, - partnerId: "2088511801157159", - securityKey: "***" - } - }, - - // 营销配置 - partyGroupQrCode: "https://...", - bannerText: "每天早上6-9点,Soul派对房不见不散", - - // 时间戳 - updatedAt: ISODate("2025-01-14T12:00:00Z") -} -\`\`\` - ---- - -## 四、数据迁移方案 - -### 4.1 LocalStorage to MongoDB - -**步骤1**: 导出LocalStorage数据 -\`\`\`javascript -// 导出脚本 scripts/export-localstorage.js -const fs = require('fs') - -const users = JSON.parse(localStorage.getItem('users') || '[]') -const orders = JSON.parse(localStorage.getItem('all_purchases') || '[]') -const settings = JSON.parse(localStorage.getItem('app_settings') || '{}') - -const exportData = { users, orders, settings } -fs.writeFileSync('data-export.json', JSON.stringify(exportData, null, 2)) -\`\`\` - -**步骤2**: 导入MongoDB -\`\`\`javascript -// 导入脚本 scripts/import-mongodb.js -const { MongoClient } = require('mongodb') -const fs = require('fs') - -async function importData() { - const client = await MongoClient.connect(process.env.MONGODB_URI) - const db = client.db('soul-experiment') - - const data = JSON.parse(fs.readFileSync('data-export.json', 'utf8')) - - // 导入用户 - await db.collection('users').insertMany(data.users) - - // 导入订单 - await db.collection('orders').insertMany(data.orders) - - // 导入配置 - await db.collection('settings').insertOne({ - _id: 'global_settings', - ...data.settings - }) - - client.close() - console.log('数据导入完成') -} - -importData() -\`\`\` - ---- - -## 五、数据库操作封装 - -### 5.1 用户操作 - -\`\`\`typescript -// lib/db/users.ts -import { MongoClient, ObjectId } from 'mongodb' - -export async function createUser(userData: Partial) { - const db = await getDatabase() - const result = await db.collection('users').insertOne({ - ...userData, - referralCode: generateReferralCode(), - earnings: 0, - pendingEarnings: 0, - withdrawnEarnings: 0, - referralCount: 0, - purchasedSections: [], - hasFullBook: false, - createdAt: new Date(), - updatedAt: new Date() - }) - return result.insertedId -} - -export async function findUserByPhone(phone: string) { - const db = await getDatabase() - return await db.collection('users').findOne({ phone }) -} - -export async function updateUserEarnings( - userId: ObjectId, - amount: number -) { - const db = await getDatabase() - await db.collection('users').updateOne( - { _id: userId }, - { - $inc: { - earnings: amount, - pendingEarnings: amount - }, - $set: { updatedAt: new Date() } - } - ) -} -\`\`\` - -### 5.2 订单操作 - -\`\`\`typescript -// lib/db/orders.ts -export async function createOrder(orderData: Partial) { - const db = await getDatabase() - const orderId = `ORDER_${Date.now()}_${randomString()}` - - const result = await db.collection('orders').insertOne({ - orderId, - ...orderData, - status: 'pending', - createdAt: new Date(), - expireAt: new Date(Date.now() + 30 * 60 * 1000), // 30分钟 - updatedAt: new Date() - }) - - return { orderId, _id: result.insertedId } -} - -export async function completeOrder(orderId: string) { - const db = await getDatabase() - const order = await db.collection('orders').findOne({ orderId }) - - if (!order) throw new Error('订单不存在') - - // 更新订单状态 - await db.collection('orders').updateOne( - { orderId }, - { - $set: { - status: 'completed', - paidAt: new Date(), - updatedAt: new Date() - } - } - ) - - // 解锁内容 - if (order.type === 'section') { - await db.collection('users').updateOne( - { _id: order.userId }, - { $addToSet: { purchasedSections: order.sectionId } } - ) - } else if (order.type === 'fullbook') { - await db.collection('users').updateOne( - { _id: order.userId }, - { $set: { hasFullBook: true } } - ) - } - - // 分配佣金 - if (order.referralCode) { - const referrer = await db.collection('users').findOne({ - referralCode: order.referralCode - }) - - if (referrer) { - const commission = order.amount * 0.9 // 90%佣金 - await updateUserEarnings(referrer._id, commission) - - // 记录佣金 - await db.collection('orders').updateOne( - { orderId }, - { $set: { - referrerUserId: referrer._id, - referrerEarnings: commission - }} - ) - } - } -} -\`\`\` - ---- - -## 六、数据备份策略 - -### 6.1 自动备份 - -\`\`\`bash -# 每日凌晨3点自动备份 -0 3 * * * mongodump --uri="mongodb://localhost:27017/soul-experiment" --out="/backup/$(date +\%Y\%m\%d)" -\`\`\` - -### 6.2 恢复数据 - -\`\`\`bash -# 恢复指定日期的备份 -mongorestore --uri="mongodb://localhost:27017/soul-experiment" --dir="/backup/20250114" -\`\`\` - ---- - -## 七、性能优化 - -### 7.1 索引优化 - -\`\`\`javascript -// 创建复合索引 -db.orders.createIndex({ userId: 1, createdAt: -1 }) -db.orders.createIndex({ status: 1, expireAt: 1 }) -db.users.createIndex({ referralCode: 1 }, { unique: true }) - -// 查看索引使用情况 -db.orders.find({ userId: ObjectId("...") }).explain("executionStats") -\`\`\` - -### 7.2 查询优化 - -\`\`\`javascript -// 使用投影减少数据传输 -db.users.find( - { phone: "15880802661" }, - { nickname: 1, referralCode: 1, earnings: 1 } -) - -// 使用聚合管道优化复杂查询 -db.orders.aggregate([ - { $match: { status: "completed" } }, - { $lookup: { - from: "users", - localField: "userId", - foreignField: "_id", - as: "user" - }}, - { $unwind: "$user" }, - { $project: { - orderId: 1, - amount: 1, - "user.nickname": 1 - }} -]) -\`\`\` - ---- - -**总结**: 数据库设计是系统的基石,合理的结构设计能让后续开发事半功倍。当前使用LocalStorage做MVP验证,未来切换MongoDB后,整个系统的可靠性和扩展性都会大幅提升。 - ---- - -**更新时间**: 2025年1月14日 -**负责人**: 卡若 -**数据库版本**: MongoDB 6.0+ diff --git a/开发文档/8、部署/API接入说明.md b/开发文档/8、部署/API接入说明.md deleted file mode 100644 index afa04eaf..00000000 --- a/开发文档/8、部署/API接入说明.md +++ /dev/null @@ -1,610 +0,0 @@ -# 小程序 API 接入说明 - -## 📋 概述 - -将 newpp 项目从静态数据(bookData.js)改为从真实 API 加载数据。 - ---- - -## 🎯 接入的 API - -### 1. 章节相关 - -| API | 方法 | 说明 | 参数 | -|-----|------|------|------| -| `/api/book/chapters` | GET | 获取章节列表 | partId, status, page, pageSize | -| `/api/book/chapter/[id]` | GET | 获取章节详情 | id(路径参数) | - -### 2. 用户相关 - -| API | 方法 | 说明 | 参数 | -|-----|------|------|------| -| `/api/user/profile` | GET | 获取用户信息 | userId, openId | -| `/api/user/profile` | POST | 更新用户信息 | userId, openId, nickname, avatar, phone, wechatId | - -### 3. 配置相关 - -| API | 方法 | 说明 | 参数 | -|-----|------|------|------| -| `/api/db/config` | GET | 获取系统配置 | 无 | -| `/api/match/config` | GET | 获取找伙伴配置 | 无 | - -### 4. 找伙伴相关 - -| API | 方法 | 说明 | 参数 | -|-----|------|------|------| -| `/api/ckb/join` | POST | 加入匹配池 | type, wechat, description | -| `/api/match/users` | GET | 获取匹配用户 | type | - -### 5. 推广相关 - -| API | 方法 | 说明 | 参数 | -|-----|------|------|------| -| `/api/referral/data` | GET | 获取推广数据 | userId | -| `/api/referral/bind` | POST | 绑定推荐人 | userId, referralCode | -| `/api/referral/visit` | POST | 记录推广访问 | referralCode | - -### 6. 搜索相关 - -| API | 方法 | 说明 | 参数 | -|-----|------|------|------| -| `/api/search` | GET | 搜索章节 | q(关键词) | - -### 7. 支付相关 - -| API | 方法 | 说明 | 参数 | -|-----|------|------|------| -| `/api/payment/create-order` | POST | 创建订单 | userId, type, sectionId, amount, payMethod | -| `/api/payment/status/[orderSn]` | GET | 查询订单状态 | orderSn(路径参数) | -| `/api/payment/methods` | GET | 获取支付方式列表 | 无 | - -### 8. 提现相关 - -| API | 方法 | 说明 | 参数 | -|-----|------|------|------| -| `/api/withdraw` | POST | 申请提现 | userId, amount, method, account, realName | - ---- - -## 📁 文件结构 - -``` -newpp/src/ -├── api/ -│ └── index.js # ✅ API 集成层(封装所有 API) -├── hooks/ -│ ├── useChapters.js # ✅ 章节列表 Hook -│ └── useChapterContent.js # ✅ 章节内容 Hook -├── adapters/ -│ ├── request.js # ✅ 请求适配器(已有) -│ └── storage.js # ✅ 存储适配器(已有) -├── data/ -│ └── bookData.js # ⚠️ 静态数据(待废弃) -└── pages/ - ├── HomePage.jsx # ⏳ 需要改用 useChapters - ├── ChaptersPage.jsx # ⏳ 需要改用 useChapters - ├── ReadPage.jsx # ⏳ 需要改用 useChapterContent - └── ... -``` - ---- - -## 🔧 核心实现 - -### 1. API 集成层 - -**文件**:`newpp/src/api/index.js` - -**作用**: -- 封装所有 API 请求 -- 统一处理错误和数据格式 -- 提供类型化的接口 - -**示例**: - -```javascript -import { request } from '../adapters/request' - -// 获取章节列表 -export async function getChapters(params = {}) { - const { partId, status = 'published', page = 1, pageSize = 100 } = params - const query = new URLSearchParams({ status, page: String(page), pageSize: String(pageSize) }) - if (partId) query.append('partId', partId) - - const res = await request(`/api/book/chapters?${query.toString()}`) - return res -} - -// 获取章节详情 -export async function getChapterById(id) { - const res = await request(`/api/book/chapter/${id}`) - return res -} -``` - ---- - -### 2. 章节列表 Hook - -**文件**:`newpp/src/hooks/useChapters.js` - -**功能**: -1. ✅ 从 API 加载章节列表 -2. ✅ 缓存到本地(30分钟) -3. ✅ 转换数据格式(API → bookData) -4. ✅ 提供辅助函数 - -**使用示例**: - -```javascript -import { useChapters } from '../hooks/useChapters' - -export default function HomePage() { - const { bookData, loading, error, getTotalSectionCount, refresh } = useChapters() - - if (loading) return
加载中...
- if (error) return
错误: {error}
- - const totalSections = getTotalSectionCount() - - return ( -
-

共 {totalSections} 章

- {bookData.map((part) => ( -
-

{part.title}

- {/* ... */} -
- ))} -
- ) -} -``` - ---- - -### 3. 章节内容 Hook - -**文件**:`newpp/src/hooks/useChapterContent.js` - -**功能**: -1. ✅ 从 API 加载章节详情 -2. ✅ 自动处理 loading 和 error -3. ✅ 支持重新加载 - -**使用示例**: - -```javascript -import { useChapterContent } from '../hooks/useChapterContent' -import { getPageQuery } from '../adapters/router' - -export default function ReadPage() { - const { id } = getPageQuery() - const { content, loading, error, reload } = useChapterContent(id) - - if (loading) return
加载中...
- if (error) return
错误: {error}
- if (!content) return
章节不存在
- - return ( -
-

{content.title}

-

{content.words} 字

-
-
- ) -} -``` - ---- - -## 🔄 数据转换 - -### API 返回格式 - -```json -{ - "success": true, - "data": { - "list": [ - { - "id": "1.1", - "part_id": "part-1", - "part_title": "真实的人", - "chapter_id": "chapter-1", - "chapter_title": "人与人之间的底层逻辑", - "section_title": "荷包:电动车出租的被动收入模式", - "content": "...", - "word_count": 1500, - "is_free": true, - "price": 0, - "sort_order": 1, - "status": "published" - } - ], - "total": 50, - "page": 1, - "pageSize": 100, - "totalPages": 1 - } -} -``` - -### bookData 格式 - -```javascript -[ - { - id: 'part-1', - number: '01', - title: '真实的人', - subtitle: '人性观察与社交逻辑', - chapters: [ - { - id: 'chapter-1', - title: '人与人之间的底层逻辑', - sections: [ - { - id: '1.1', - title: '荷包:电动车出租的被动收入模式', - isFree: true, - price: 1, - wordCount: 1500, - } - ] - } - ] - } -] -``` - -### 转换函数 - -```javascript -function transformChapters(chapters) { - const partsMap = new Map() - - chapters.forEach((item) => { - // 确保 part 存在 - if (!partsMap.has(item.part_id)) { - partsMap.set(item.part_id, { - id: item.part_id, - number: item.part_id.replace('part-', '').padStart(2, '0'), - title: item.part_title, - subtitle: '', - chapters: [] - }) - } - - const part = partsMap.get(item.part_id) - - // 查找或创建 chapter - let chapter = part.chapters.find((c) => c.id === item.chapter_id) - if (!chapter) { - chapter = { - id: item.chapter_id, - title: item.chapter_title, - sections: [] - } - part.chapters.push(chapter) - } - - // 添加 section - chapter.sections.push({ - id: item.id, - title: item.section_title, - isFree: item.is_free || false, - price: item.price || 1, - wordCount: item.word_count || 0, - }) - }) - - return Array.from(partsMap.values()) -} -``` - ---- - -## 📦 缓存策略 - -### 缓存位置 - -- **小程序**:`wx.storage` -- **Web**:`localStorage` - -### 缓存时长 - -- **章节列表**:30分钟 -- **章节内容**:不缓存(内容可能更新) - -### 缓存格式 - -```javascript -{ - data: [...], // 数据 - timestamp: 1706940000000 // 时间戳 -} -``` - -### 缓存逻辑 - -```javascript -// 1. 尝试从缓存加载 -const cached = await storage.getItem(CACHE_KEY) -if (cached) { - const { data, timestamp } = JSON.parse(cached) - if (Date.now() - timestamp < CACHE_DURATION) { - setBookData(data) - return - } -} - -// 2. 从 API 加载 -const res = await getChapters({ status: 'published', pageSize: 1000 }) -const transformed = transformChapters(res.data.list) -setBookData(transformed) - -// 3. 缓存数据 -await storage.setItem(CACHE_KEY, JSON.stringify({ - data: transformed, - timestamp: Date.now() -})) -``` - ---- - -## 🔄 迁移步骤 - -### Phase 1:创建 API 层 ✅ - -- [x] 创建 `api/index.js` -- [x] 创建 `hooks/useChapters.js` -- [x] 创建 `hooks/useChapterContent.js` - -### Phase 2:更新页面组件 - -#### 2.1 HomePage.jsx - -**Before**: - -```javascript -import { getTotalSectionCount, bookData } from '../data/bookData' - -const totalSections = getTotalSectionCount() -``` - -**After**: - -```javascript -import { useChapters } from '../hooks/useChapters' - -export default function HomePage() { - const { bookData, loading, getTotalSectionCount } = useChapters() - - if (loading) return - - const totalSections = getTotalSectionCount() - // ... -} -``` - -#### 2.2 ChaptersPage.jsx - -**Before**: - -```javascript -import { bookData } from '../data/bookData' -``` - -**After**: - -```javascript -import { useChapters } from '../hooks/useChapters' - -export default function ChaptersPage() { - const { bookData, loading } = useChapters() - - if (loading) return - // ... -} -``` - -#### 2.3 ReadPage.jsx - -**Before**: - -```javascript -import { getSectionById } from '../data/bookData' - -const section = getSectionById(id) -``` - -**After**: - -```javascript -import { useChapterContent } from '../hooks/useChapterContent' -import { getPageQuery } from '../adapters/router' - -export default function ReadPage() { - const { id } = getPageQuery() - const { content, loading } = useChapterContent(id) - - if (loading) return - if (!content) return - // ... -} -``` - -#### 2.4 SearchPage.jsx - -**Before**: - -```javascript -import { getAllSections } from '../data/bookData' - -const results = getAllSections().filter(s => s.title.includes(keyword)) -``` - -**After**: - -```javascript -import { searchChapters } from '../api' - -export default function SearchPage() { - const [results, setResults] = useState([]) - - const handleSearch = async (keyword) => { - const res = await searchChapters(keyword) - setResults(res.data || []) - } - // ... -} -``` - -### Phase 3:集成到 Zustand Store - -```javascript -// store/index.js -import { getChapters } from '../api' - -const useStore = create( - persist( - (set, get) => ({ - // ... 其他状态 - - // ✅ 添加章节数据 - bookData: [], - loadChapters: async () => { - const res = await getChapters({ status: 'published', pageSize: 1000 }) - if (res.success) { - set({ bookData: transformChapters(res.data.list) }) - } - }, - }), - { - name: 'soul-party-storage', - storage: {/* ... */}, - } - ) -) -``` - -### Phase 4:移除静态数据 - -- [ ] 删除或重命名 `data/bookData.js` -- [ ] 更新所有导入路径 - ---- - -## 🐛 错误处理 - -### API 请求失败 - -```javascript -try { - const res = await getChapters() - if (!res.success) { - throw new Error(res.error || '请求失败') - } -} catch (err) { - console.error('加载失败:', err) - setError(err.message) - - // ✅ 降级策略:使用缓存数据 - const cached = await storage.getItem(CACHE_KEY) - if (cached) { - const { data } = JSON.parse(cached) - setBookData(data) - } -} -``` - -### 网络超时 - -```javascript -// adapters/request.js -export function request(url, options = {}) { - const controller = new AbortController() - const timeout = setTimeout(() => controller.abort(), 10000) // 10秒超时 - - return fetch(fullUrl, { - ...options, - signal: controller.signal, - }) - .finally(() => clearTimeout(timeout)) -} -``` - ---- - -## 📊 性能优化 - -### 1. 缓存策略 - -- ✅ 章节列表缓存 30 分钟 -- ✅ 减少 API 调用次数 -- ✅ 提升加载速度 - -### 2. 懒加载 - -```javascript -// 只在需要时加载章节内容 -useEffect(() => { - if (visible) { - loadContent() - } -}, [visible]) -``` - -### 3. 预加载 - -```javascript -// 预加载下一章内容 -useEffect(() => { - if (content && nextChapterId) { - // 延迟 2 秒预加载 - const timer = setTimeout(() => { - getChapterById(nextChapterId) - }, 2000) - return () => clearTimeout(timer) - } -}, [content, nextChapterId]) -``` - ---- - -## 🧪 测试清单 - -### API 集成测试 - -- [ ] 章节列表加载成功 -- [ ] 章节详情加载成功 -- [ ] 用户信息获取成功 -- [ ] 配置加载成功 -- [ ] 搜索功能正常 -- [ ] 错误处理正确 - -### 缓存测试 - -- [ ] 首次加载从 API 获取 -- [ ] 第二次加载从缓存读取 -- [ ] 缓存过期后重新加载 -- [ ] 缓存数据格式正确 - -### 跨平台测试 - -- [ ] Web 环境正常 -- [ ] 小程序环境正常 -- [ ] 数据格式一致 - ---- - -## 📚 相关文档 - -1. [API 集成层代码](../newpp/src/api/index.js) -2. [章节列表 Hook](../newpp/src/hooks/useChapters.js) -3. [章节内容 Hook](../newpp/src/hooks/useChapterContent.js) - ---- - -**总结**:API 集成层已完成,接下来需要更新各个页面组件,将静态数据改为从 API 加载。 diff --git a/开发文档/8、部署/MCP-MySQL配置说明.md b/开发文档/8、部署/MCP-MySQL配置说明.md deleted file mode 100644 index 5f5c1690..00000000 --- a/开发文档/8、部署/MCP-MySQL配置说明.md +++ /dev/null @@ -1,401 +0,0 @@ -# MCP MySQL 配置说明 - -**日期**: 2026-02-04 -**目的**: 通过 MCP (Model Context Protocol) 在 Cursor 中直接操作 Soul 小程序数据库 - ---- - -## ✅ 已配置的 MCP 服务 - -### 1. Soul-MySQL(新增) -**用途**: Soul 小程序生产数据库操作 - -**配置文件**: `C:\Users\29195\.cursor\mcp.json` - -```json -{ - "Soul-MySQL": { - "command": "npx", - "args": [ - "-y", - "@f4ww4z/mcp-mysql-server", - "--host", - "56b4c23f6853c.gz.cdb.myqcloud.com", - "--port", - "14413", - "--user", - "cdb_outerroot", - "--password", - "Zhiqun1984", - "--database", - "soul_miniprogram" - ], - "env": {} - } -} -``` - -**数据库信息**: -- **主机**: 56b4c23f6853c.gz.cdb.myqcloud.com(腾讯云 CDB) -- **端口**: 14413 -- **用户**: cdb_outerroot -- **密码**: Zhiqun1984 -- **数据库**: soul_miniprogram - ---- - -## 🔧 使用方法 - -### 1. 重启 Cursor -配置文件修改后,需要**完全重启 Cursor** 才能生效: -1. 关闭所有 Cursor 窗口 -2. 重新打开 Cursor -3. 等待 MCP 服务启动 - -### 2. 验证连接 -在 Cursor 中输入: -``` -@Soul-MySQL 列出所有表 -``` - -或使用工具调用: -```javascript -// 查询所有表 -user-MySQL-list_tables - -// 查看表结构 -user-MySQL-describe_table -{ - "table": "orders" -} - -// 执行查询 -user-MySQL-query -{ - "sql": "SELECT * FROM orders LIMIT 10" -} -``` - ---- - -## 📊 可用的操作 - -### 1. 查询数据(只读) -```sql --- 查看最近订单 -SELECT * FROM orders -ORDER BY created_at DESC -LIMIT 10; - --- 统计订单状态 -SELECT status, COUNT(*) as count, SUM(amount) as total -FROM orders -GROUP BY status; - --- 查看用户购买情况 -SELECT - u.id, - u.nickname, - u.has_full_book, - COUNT(o.id) as order_count, - SUM(o.amount) as total_spent -FROM users u -LEFT JOIN orders o ON u.id = o.user_id AND o.status = 'paid' -GROUP BY u.id, u.nickname, u.has_full_book -ORDER BY total_spent DESC -LIMIT 20; -``` - -### 2. 修改数据(慎重!) -```sql --- 修复订单表 status 字段(关键修复) -ALTER TABLE orders -MODIFY COLUMN status ENUM('created', 'pending', 'paid', 'cancelled', 'refunded', 'expired') -DEFAULT 'created'; - --- 手动解锁用户章节 -UPDATE users -SET purchased_sections = JSON_ARRAY_APPEND( - COALESCE(purchased_sections, '[]'), '$', '1-1' -) -WHERE id = 'user_xxx'; - --- 手动补记订单 -INSERT INTO orders ( - id, order_sn, user_id, open_id, - product_type, product_id, amount, description, - status, transaction_id, pay_time, created_at, updated_at -) VALUES ( - 'MP20260204123456789012', 'MP20260204123456789012', - 'user_xxx', 'oXXXX...', 'section', '1-1', 9.9, - '章节1-1购买', 'paid', 'wx_transaction_id', - NOW(), NOW(), NOW() -); -``` - -### 3. 查看表结构 -```sql --- 查看表结构 -DESCRIBE orders; -DESCRIBE users; -DESCRIBE referral_bindings; - --- 查看索引 -SHOW INDEX FROM orders; - --- 查看表创建语句 -SHOW CREATE TABLE orders; -``` - ---- - -## ⚠️ 重要提醒 - -### 1. 生产数据库操作 -- ⚠️ 这是**生产数据库**,所有操作都会**直接影响线上服务** -- ✅ 查询操作(SELECT)相对安全 -- ❌ 修改操作(UPDATE/DELETE/ALTER)**必须谨慎** -- 💡 建议先在本地数据库测试 - -### 2. 数据备份 -修改重要数据前,建议先备份: -```sql --- 备份整个表 -CREATE TABLE orders_backup AS SELECT * FROM orders; - --- 备份特定数据 -CREATE TABLE orders_backup_20260204 AS -SELECT * FROM orders WHERE DATE(created_at) = '2026-02-04'; -``` - -### 3. 事务操作 -对于关联性强的修改,使用事务: -```sql -START TRANSACTION; - --- 修改操作1 -UPDATE users SET has_full_book = TRUE WHERE id = 'user_xxx'; - --- 修改操作2 -INSERT INTO orders (...) VALUES (...); - --- 确认无误后提交 -COMMIT; - --- 或者出错时回滚 --- ROLLBACK; -``` - ---- - -## 🎯 常见操作场景 - -### 场景1: 修复订单表状态字段 -```sql --- 1. 先查看当前定义 -SHOW CREATE TABLE orders; - --- 2. 修改 ENUM 定义 -ALTER TABLE orders -MODIFY COLUMN status ENUM('created', 'pending', 'paid', 'cancelled', 'refunded', 'expired') -DEFAULT 'created'; - --- 3. 验证修改 -DESCRIBE orders; -``` - -### 场景2: 查询用户支付问题 -```sql --- 查询特定用户的订单记录 -SELECT * FROM orders -WHERE user_id = 'ogpTW5a9exdEmEwqZsYywvgSpSQg' -ORDER BY created_at DESC; - --- 查询用户购买记录 -SELECT - id, nickname, has_full_book, purchased_sections, - pending_earnings, earnings -FROM users -WHERE id = 'ogpTW5a9exdEmEwqZsYywvgSpSQg'; - --- 查询用户推荐关系 -SELECT * FROM referral_bindings -WHERE referee_id = 'ogpTW5a9exdEmEwqZsYywvgSpSQg' - OR referrer_id = 'ogpTW5a9exdEmEwqZsYywvgSpSQg'; -``` - -### 场景3: 统计数据分析 -```sql --- 今日订单统计 -SELECT - COUNT(*) as total_orders, - SUM(CASE WHEN status = 'paid' THEN 1 ELSE 0 END) as paid_orders, - SUM(CASE WHEN status = 'paid' THEN amount ELSE 0 END) as total_revenue -FROM orders -WHERE DATE(created_at) = CURDATE(); - --- 用户活跃度统计 -SELECT - DATE(created_at) as date, - COUNT(DISTINCT user_id) as active_users, - COUNT(*) as total_orders, - SUM(amount) as revenue -FROM orders -WHERE status = 'paid' - AND created_at >= DATE_SUB(NOW(), INTERVAL 7 DAY) -GROUP BY DATE(created_at) -ORDER BY date DESC; - --- 推广效果统计 -SELECT - u.nickname as referrer, - COUNT(rb.id) as total_referrals, - SUM(CASE WHEN rb.status = 'converted' THEN 1 ELSE 0 END) as conversions, - SUM(rb.commission_amount) as total_commission -FROM users u -LEFT JOIN referral_bindings rb ON u.id = rb.referrer_id -WHERE rb.id IS NOT NULL -GROUP BY u.id, u.nickname -ORDER BY total_commission DESC -LIMIT 20; -``` - -### 场景4: 紧急数据修复 -```sql --- 手动解锁用户权限(用户支付但未解锁) -START TRANSACTION; - --- 1. 补记订单 -INSERT INTO orders ( - id, order_sn, user_id, open_id, - product_type, product_id, amount, description, - status, transaction_id, pay_time, created_at, updated_at -) VALUES ( - 'MANUAL_20260204_001', 'MANUAL_20260204_001', - 'user_xxx', 'oXXXX...', 'section', '1-1', 9.9, - '手动补记-章节1-1购买', 'paid', 'manual_fix', - NOW(), NOW(), NOW() -); - --- 2. 解锁章节 -UPDATE users -SET purchased_sections = JSON_ARRAY_APPEND( - COALESCE(purchased_sections, '[]'), '$', '1-1' -) -WHERE id = 'user_xxx' - AND NOT JSON_CONTAINS(COALESCE(purchased_sections, '[]'), '"1-1"'); - --- 3. 如果有推荐人,分配佣金 -UPDATE users -SET pending_earnings = pending_earnings + (9.9 * 0.9) -WHERE id = (SELECT referred_by FROM users WHERE id = 'user_xxx'); - --- 4. 更新推荐关系状态 -UPDATE referral_bindings -SET status = 'converted', - conversion_date = NOW(), - commission_amount = 8.91, - order_id = 'MANUAL_20260204_001' -WHERE referee_id = 'user_xxx' - AND status = 'active'; - -COMMIT; -``` - ---- - -## 🔗 其他 MCP 服务 - -### MySQL(本地) -- **用途**: 本地 sass 数据库 -- **主机**: localhost:3306 -- **数据库**: sass - -### MongoDB -- **用途**: 测试 MongoDB 连接 -- **连接**: mongodb://admin:admin123@192.168.1.201:27017/admin - -### Ollama -- **用途**: 本地 AI 模型调用 -- **脚本**: C:\Users\29195\mcp_ollama_server.py - ---- - -## 📝 MCP 工具列表 - -使用 `@Soul-MySQL` 可以调用以下工具: - -| 工具名 | 功能 | 示例 | -|--------|------|------| -| `user-MySQL-connect_db` | 连接数据库 | 自动连接 | -| `user-MySQL-query` | 执行 SELECT 查询 | `{"sql": "SELECT * FROM orders LIMIT 10"}` | -| `user-MySQL-execute` | 执行 INSERT/UPDATE/DELETE | `{"sql": "UPDATE users SET ..."}` | -| `user-MySQL-list_tables` | 列出所有表 | 无参数 | -| `user-MySQL-describe_table` | 查看表结构 | `{"table": "orders"}` | - ---- - -## 🚀 快速开始 - -### 1. 检查订单表状态 -``` -@Soul-MySQL 执行查询:DESCRIBE orders; -``` - -### 2. 查看最近订单 -``` -@Soul-MySQL 查询最近10条订单记录 -``` - -### 3. 修复订单表(如需要) -``` -@Soul-MySQL 执行以下SQL: -ALTER TABLE orders -MODIFY COLUMN status ENUM('created', 'pending', 'paid', 'cancelled', 'refunded', 'expired') -DEFAULT 'created'; -``` - ---- - -## ⚡ 故障排查 - -### 问题1: MCP 服务未启动 -**症状**: 输入 `@Soul-MySQL` 没有提示 - -**解决**: -1. 完全关闭 Cursor -2. 检查 mcp.json 文件格式是否正确 -3. 重新打开 Cursor -4. 查看 Cursor 输出日志 - -### 问题2: 连接超时 -**症状**: 执行查询时提示连接超时 - -**解决**: -1. 检查网络连接 -2. 确认数据库服务器是否在线 -3. 检查防火墙/安全组配置 -4. 验证数据库账号密码 - -### 问题3: 权限不足 -**症状**: 提示没有权限执行某些操作 - -**解决**: -1. 检查数据库用户权限 -2. 某些操作需要超级管理员权限 -3. 联系 DBA 授权 - ---- - -## 📚 相关文档 - -- [支付订单完整修复方案](./支付订单完整修复方案.md) -- [订单表状态字段修复说明](./订单表状态字段修复说明.md) -- [支付订单未创建问题分析](./支付订单未创建问题分析.md) -- [数据库设计](../7、数据库/数据库设计.md) - ---- - -**现在你可以在 Cursor 中直接使用 `@Soul-MySQL` 来操作生产数据库了!** 🎉 - -**记得重启 Cursor 使配置生效!** diff --git a/开发文档/8、部署/Soul-MySQL-MCP配置说明.md b/开发文档/8、部署/Soul-MySQL-MCP配置说明.md deleted file mode 100644 index cbbad0e4..00000000 --- a/开发文档/8、部署/Soul-MySQL-MCP配置说明.md +++ /dev/null @@ -1,84 +0,0 @@ -# Soul-MySQL MCP 配置说明 - -**配置文件**: `C:\Users\29195\.cursor\mcp.json` - ---- - -## 为什么之前无法执行? - -### 原因 1:连接时没有带端口 - -- 之前用 `--host`、`--port` 分开传参,部分 MCP 客户端在**运行时**调用 `connect_db` 时**只传 host/user/password/database,不传 port**。 -- 你的数据库在 **14413**,MySQL 默认是 **3306**,所以实际连的是错误端口 → 容易 **ETIMEDOUT** 或连不上。 -- 所以会出现「无法执行」或执行报错。 - -### 原因 2:改用「连接串」才能带上端口 - -- `@f4ww4z/mcp-mysql-server` 支持用**一条连接串**启动,格式里可以写清楚端口: - - `mysql://用户:密码@主机:端口/数据库名` -- 这样 MCP 启动时就会用 **14413** 去连,不会再用默认 3306。 - ---- - -## 当前正确配置(连接串方式) - -在 `mcp.json` 里 Soul-MySQL 应类似: - -```json -"Soul-MySQL": { - "command": "npx", - "args": [ - "-y", - "@f4ww4z/mcp-mysql-server", - "mysql://cdb_outerroot:Zhiqun1984@56b4c23f6853c.gz.cdb.myqcloud.com:14413/soul_miniprogram" - ], - "env": {} -} -``` - -含义: - -- **用户**: cdb_outerroot -- **密码**: Zhiqun1984 -- **主机**: 56b4c23f6853c.gz.cdb.myqcloud.com -- **端口**: 14413(写在连接串里) -- **数据库**: soul_miniprogram - -这样 MCP 会按 `主机:14413` 连接,不再用 3306。 - ---- - -## 使用前必做:重启 Cursor - -1. **完全退出 Cursor**(关掉所有窗口)。 -2. 再重新打开 Cursor。 -3. 等 MCP 列表里 Soul-MySQL 显示为已连接/可用。 - -否则会继续用旧配置(不带端口),仍然无法执行。 - ---- - -## 若仍无法执行,可排查这些 - -### 1. 本机网络/防火墙 - -- 数据库在腾讯云,若你本机或公司网络**不允许访问外网 14413**,连接会超时。 -- 解决:在能访问该库的机器上跑 Cursor(或先做 SSH 隧道,把 14413 转到本机 3306,再在 mcp.json 里连 localhost:3306)。 - -### 2. 腾讯云白名单 - -- 腾讯云 MySQL 有「来源 IP 白名单」。 -- 你当前上网的 **公网 IP** 必须在白名单里,否则会被拒绝。 -- 解决:在腾讯云控制台 → 该 MySQL 实例 → 白名单里加上你当前的公网 IP。 - -### 3. 密码含特殊字符 - -- 若以后改了密码,且密码里有 `@`、`#`、`/` 等,需要做 **URL 编码** 再写进连接串,否则连接串会被解析错。 - ---- - -## 小结 - -- **无法执行** 多半是:连库时**没带端口 14413** 或**网络/白名单**不通。 -- 已把 Soul-MySQL 改成**带端口的连接串**配置,并写进 `mcp.json`。 -- 修改后**务必重启 Cursor** 再试;若仍不行,按上面「若仍无法执行」逐项排查。 diff --git a/开发文档/8、部署/VIP功能-数据库迁移说明.md b/开发文档/8、部署/VIP功能-数据库迁移说明.md deleted file mode 100644 index 66b09558..00000000 --- a/开发文档/8、部署/VIP功能-数据库迁移说明.md +++ /dev/null @@ -1,49 +0,0 @@ -# VIP 功能 - 数据库迁移说明 - -> 2026-02-26 小橙同步。VIP 排序、角色、设置入口升级。 - ---- - -## 一、迁移脚本 - -| 脚本 | 说明 | -|------|------| -| `soul-api/scripts/add-vip-activated-at.sql` | 新增 `users.vip_activated_at`(成为 VIP 时间,排序用) | -| `soul-api/scripts/add-vip-roles-and-fields.sql` | 新建 `vip_roles` 表;新增 `users.vip_sort`、`users.vip_role` | -| `soul-api/scripts/add-vip-profile-fields.sql` | 新增 `users.vip_name`、`vip_avatar`、`vip_project`、`vip_contact`、`vip_bio`(会员资料,与用户信息分离) | - ---- - -## 二、执行顺序 - -```bash -# 1. vip_activated_at(若尚未执行) -mysql -u user -p database < soul-api/scripts/add-vip-activated-at.sql - -# 2. vip_roles 表 + users 新字段 -mysql -u user -p database < soul-api/scripts/add-vip-roles-and-fields.sql - -# 3. 会员资料字段(若尚未执行;列已存在会报 Duplicate column,可忽略) -mysql -u user -p database < soul-api/scripts/add-vip-profile-fields.sql -``` - -若 `vip_sort`、`vip_role` 已存在,对应 `ALTER` 会报错,可忽略或单独执行未执行过的语句。 - ---- - -## 三、功能说明 - -| 字段/表 | 用途 | -|---------|------| -| `vip_activated_at` | 成为 VIP 时间:付款=订单 pay_time,手动=设置时 now;排序用(后付款/后设置在前) | -| `vip_sort` | 手动排序,数字越小越靠前;NULL 时按 vip_activated_at | -| `vip_role` | 角色:从 vip_roles 选或手动填写 | -| `vip_roles` | 预设角色表(创始人、投资人、产品经理等),管理端可 CRUD | -| `vip_name`、`vip_avatar`、`vip_project`、`vip_contact`、`vip_bio` | 会员资料(创业老板排行),与用户信息 phone/wechat_id 分离 | - ---- - -## 四、管理端入口 - -- **用户列表**:每行「设置 VIP」按钮(Crown 图标)→ SetVipModal -- **VIP 角色**:侧栏「VIP 角色」→ `/vip-roles`,管理预设角色列表 diff --git a/开发文档/8、部署/代码逻辑和数据库最终检查清单.md b/开发文档/8、部署/代码逻辑和数据库最终检查清单.md deleted file mode 100644 index 8f7cf88d..00000000 --- a/开发文档/8、部署/代码逻辑和数据库最终检查清单.md +++ /dev/null @@ -1,363 +0,0 @@ -# 代码逻辑和数据库最终检查清单 ✅ - -## 📊 数据库修改(已完成) - -### 1. referral_bindings 表新增字段 -```sql -✅ last_purchase_date DATETIME DEFAULT NULL -✅ purchase_count INT DEFAULT 0 -✅ total_commission DECIMAL(10,2) DEFAULT 0.00 -✅ status ENUM('active', 'expired', 'cancelled') -- 新增 'cancelled' -``` - -### 2. 索引优化 -```sql -✅ idx_status_expiry (status, expiry_date) -✅ idx_referee_status (referee_id, status) -✅ idx_referrer_status (referrer_id, status) -✅ idx_purchase_count (purchase_count) -``` - -### 3. 数据库迁移执行状态 -- ✅ 已通过 `scripts/migrate_db_simple.py` 成功执行 -- ✅ 所有字段已添加 -- ✅ 所有索引已创建 - ---- - -## 🔧 核心API逻辑(已验证) - -### 1. `/api/referral/bind` - 绑定/切换推荐人 ✅ - -**文件**: `app/api/referral/bind/route.ts` - -**关键逻辑**: -```typescript -✅ 从 referral_config 读取 bindingDays(不再硬编码 30 天) -✅ 同一推荐人 → 续期(刷新 30 天) -✅ 不同推荐人 → 立即切换(无需等待过期) - - 旧绑定标记为 'cancelled' - - 创建新绑定,expiry_date = NOW + bindingDays - - 更新 users.referral_count(旧 -1,新 +1) -``` - -**验证点**: -- ✅ 绑定天数可配置 -- ✅ 切换逻辑正确(不检查 expiry_date) -- ✅ 旧绑定正确标记为 'cancelled' -- ✅ 新绑定正确创建 -- ✅ 推荐人数量正确更新 - ---- - -### 2. `/api/miniprogram/pay` - 创建支付订单 ✅ - -**文件**: `app/api/miniprogram/pay/route.ts` - -**关键逻辑**: -```typescript -✅ 从 referral_config 读取 userDiscount(如 5 表示 5%) -✅ 如果有 referralCode,计算折后价 - finalAmount = amount * (1 - userDiscount / 100) - finalAmount = max(0.01, round(finalAmount, 2)) -✅ 微信支付使用 finalAmount(折后价) -✅ 订单表记录 finalAmount(折后价) -``` - -**验证点**: -- ✅ 折扣正确应用(原价 1.00,5% off = 0.95) -- ✅ 最低金额保护(至少 0.01 元) -- ✅ 金额精确到分(Math.round) -- ✅ 订单表记录的是折后价 - ---- - -### 3. `/api/miniprogram/pay/notify` - 支付回调 ✅ - -**文件**: `app/api/miniprogram/pay/notify/route.ts` - -**关键逻辑**: -```typescript -✅ 查找 status = 'active' 的绑定记录 -✅ 检查 expiry_date > NOW(过期不分佣) -✅ 从 referral_config 读取 distributorShare -✅ 计算佣金:commission = amount * distributorShare / 100 -✅ 更新 users.pending_earnings += commission -✅ 更新 referral_bindings: - - last_purchase_date = NOW - - purchase_count += 1 - - total_commission += commission - - status 保持 'active'(不再改为 'converted') -``` - -**验证点**: -- ✅ 只给 active 且未过期的绑定分佣 -- ✅ 佣金比例可配置 -- ✅ 支持多次购买分佣(不改 status) -- ✅ 正确累加购买次数和佣金 -- ✅ 记录最后购买时间 - ---- - -### 4. `/api/withdraw` - 提现申请 ✅ - -**文件**: `app/api/withdraw/route.ts` - -**关键逻辑**: -```typescript -✅ 从 referral_config 读取 minWithdrawAmount -✅ 验证 amount >= minWithdrawAmount(不再硬编码 10 元) -✅ 验证 amount <= pending_earnings -``` - -**验证点**: -- ✅ 最低提现金额可配置 -- ✅ 金额验证逻辑正确 - ---- - -### 5. `/api/referral/data` - 分销数据统计 ✅ - -**文件**: `app/api/referral/data/route.ts` - -**关键逻辑**: -```typescript -✅ 绑定统计: - - active: status = 'active' AND expiry_date > NOW - - converted: status = 'active' AND purchase_count > 0 - - expired: status IN ('expired', 'cancelled') OR expiry_date <= NOW - -✅ 已转化用户列表: - WHERE status = 'active' AND purchase_count > 0 - ORDER BY last_purchase_date DESC - -✅ 返回购买次数、累计佣金 -``` - -**验证点**: -- ✅ 不再查询 status = 'converted' -- ✅ 使用 purchase_count 判断是否已购买 -- ✅ 返回新增的字段(purchase_count, total_commission) -- ✅ 统计逻辑正确(包含 'cancelled' 状态) - ---- - -## 🎯 管理后台(已验证) - -### 1. 推广设置页面 ✅ - -**文件**: `app/admin/referral-settings/page.tsx` - -**配置项**: -```typescript -✅ distributorShare (分销比例, 0-100) -✅ minWithdrawAmount (最低提现金额, 元) -✅ bindingDays (绑定天数, 天) -✅ userDiscount (好友优惠, 0-100) -✅ enableAutoWithdraw (自动提现, boolean) -``` - -**验证点**: -- ✅ 读取配置正确 -- ✅ 保存配置正确(Number/Boolean 转换) -- ✅ 表单验证正确 -- ✅ 成功提示清晰 - ---- - -### 2. 管理后台菜单 ✅ - -**文件**: `app/admin/layout.tsx` - -```typescript -✅ 新增菜单项: "推广设置" → /admin/referral-settings -✅ 图标: CreditCard -✅ 位置: "用户管理" 和 "系统设置" 之间 -``` - ---- - -## 📱 小程序端(已完成) - -### 1. UI修改 ✅ -```xml -✅ 删除"我的邀请码"卡片(miniprogram/pages/referral/referral.wxml) -``` - -### 2. 绑定逻辑 ✅ -```javascript -✅ app.js 调用 /api/referral/bind(后端已实现立即切换) -✅ 无需前端修改 -``` - -### 3. 支付逻辑 ✅ -```javascript -✅ pages/read/read.js 传递 referralCode(后端已实现折扣) -✅ 无需前端修改 -``` - -### 4. 数据展示 ✅ -```javascript -✅ pages/referral/referral.js 调用 /api/referral/data -✅ 后端已返回新字段(purchase_count, total_commission) -✅ 无需前端修改 -``` - ---- - -## ⏰ 定时任务(已创建) - -### 1. 自动解绑脚本 ✅ - -**文件**: `scripts/auto-unbind-expired-simple.js` - -**逻辑**: -```javascript -✅ 查找 status = 'active' AND expiry_date < NOW AND purchase_count = 0 -✅ 批量更新为 status = 'expired' -✅ 输出详细日志 -``` - -**部署**: -```bash -⏸️ 需在宝塔面板配置: 每天 03:00 执行 - 命令: cd /www/wwwroot/soul.quwanzhi.com && /www/server/nodejs/v20.11.0/bin/node scripts/auto-unbind-expired-simple.js >> logs/auto-unbind.log 2>&1 -``` - ---- - -## 🔍 业务逻辑验证 - -### 场景1: 首次绑定 ✅ -``` -A 分享链接 → B 点击 → /api/referral/bind -→ 创建新绑定(status = 'active', expiry_date = NOW + 30天) -→ users.referral_count += 1 -``` - -### 场景2: 切换推荐人 ✅ -``` -B 已绑定 A → B 点击 C 的链接 → /api/referral/bind -→ 旧绑定(A-B)标记为 'cancelled' -→ 创建新绑定(C-B, status = 'active', expiry_date = NOW + 30天) -→ A.referral_count -= 1, C.referral_count += 1 -``` - -### 场景3: 续期绑定 ✅ -``` -B 已绑定 A → B 再次点击 A 的链接 → /api/referral/bind -→ 更新绑定(expiry_date = NOW + 30天) -→ referral_count 不变 -``` - -### 场景4: 首次购买 ✅ -``` -B 绑定 C(5天前)→ B 购买 1.00 元章节(有 5% 优惠) -→ 实付 0.95 元 -→ C 获得佣金 0.95 * 90% = 0.855 元(四舍五入 0.86) -→ referral_bindings: purchase_count = 1, total_commission = 0.86, last_purchase_date = NOW -→ C.pending_earnings += 0.86 -→ 绑定保持 'active' -``` - -### 场景5: 多次购买 ✅ -``` -B 再次购买 1.00 元章节(还在 30 天内) -→ 实付 0.95 元 -→ C 再获得佣金 0.86 元 -→ referral_bindings: purchase_count = 2, total_commission = 1.72, last_purchase_date = NOW -→ C.pending_earnings += 0.86(累计 1.72) -→ 绑定保持 'active' -``` - -### 场景6: 自动解绑 ✅ -``` -B 绑定 A(30 天前)→ B 从未购买 → 定时任务执行 -→ 查找: status = 'active' AND expiry_date < NOW AND purchase_count = 0 -→ 更新: status = 'expired' -→ A.referral_count -= 1 -``` - -### 场景7: 提现 ✅ -``` -C 有 pending_earnings = 15.00 元 → 申请提现 12.00 元 -→ 验证 amount >= minWithdrawAmount(默认 10) -→ 验证 amount <= pending_earnings -→ 创建提现记录 -→ C.pending_earnings -= 12.00 = 3.00 -``` - ---- - -## ✅ 最终确认 - -### 代码逻辑 -- ✅ 所有 API 已适配新逻辑 -- ✅ 所有硬编码值已改为动态配置 -- ✅ 所有状态转换逻辑正确 -- ✅ 所有金额计算精确到分 - -### 数据库 -- ✅ 所有字段已添加 -- ✅ 所有索引已创建 -- ✅ 数据类型正确 -- ✅ 默认值正确 - -### 小程序 -- ✅ UI 已删除邀请码卡片 -- ✅ 绑定逻辑兼容后端 -- ✅ 支付逻辑兼容后端 -- ✅ 数据展示兼容后端 - -### 管理后台 -- ✅ 推广设置页面已创建 -- ✅ 菜单已添加 -- ✅ 配置读写正确 - -### 定时任务 -- ✅ 脚本已创建 -- ⏸️ 需在宝塔配置(部署时) - ---- - -## 🚀 部署检查项 - -部署前确认: -- ✅ 代码已修改 -- ✅ 数据库已迁移 -- ✅ 本地测试通过 - -部署后确认: -- ⏸️ PM2 重启成功 -- ⏸️ 定时任务配置成功 -- ⏸️ 管理后台可访问 `/admin/referral-settings` -- ⏸️ 小程序绑定/支付/分佣功能测试通过 - ---- - -## 📝 测试用例(可选) - -如需本地测试,运行: -```bash -node scripts/test-referral-flow.js -``` - -测试覆盖: -- ✅ 首次绑定 -- ✅ 续期绑定 -- ✅ 切换绑定 -- ✅ 首次购买分佣 -- ✅ 多次购买分佣 -- ✅ 过期绑定不分佣 - ---- - -## ✅ 结论 - -**所有代码逻辑和数据库修改已完成并验证,可以放心部署!** - -需要在宝塔面板配置的只有: -1. 重启 PM2 服务(让新代码生效) -2. 配置定时任务(自动解绑) - -参考文档: `开发文档/8、部署/新分销逻辑-宝塔操作清单.md` diff --git a/开发文档/8、部署/佣金计算逻辑检查.md b/开发文档/8、部署/佣金计算逻辑检查.md deleted file mode 100644 index 99d86591..00000000 --- a/开发文档/8、部署/佣金计算逻辑检查.md +++ /dev/null @@ -1,307 +0,0 @@ -# 佣金计算逻辑检查 - -## 🔍 用户反馈 - -**问题**: "推广者应该获取支付金额的90%,但却是10%" - ---- - -## 📊 配置值流转 - -### 1. 管理后台保存(/admin/referral-settings) - -**输入**: -``` -分销比例:90 (表示90%) -``` - -**保存代码**: -```typescript -const safeConfig = { - distributorShare: Number(config.distributorShare) || 0 -} -// 保存到数据库:distributorShare = 90 -``` - -**数据库存储**: -```json -{ - "distributorShare": 90 -} -``` - ---- - -### 2. 后端读取配置(/api/miniprogram/pay/notify) - -**读取代码**: -```typescript -const config = await getConfig('referral_config') -const distributorShare = config.distributorShare / 100 -// 结果:90 / 100 = 0.9 -``` - -**佣金计算**: -```typescript -const commission = Math.round(amount * distributorShare * 100) / 100 -// 例如:1元 * 0.9 = 0.9元 -``` - ---- - -### 3. 返回给小程序(/api/referral/data) - -**返回代码**: -```typescript -shareRate: Math.round(distributorShare * 100) -// 结果:0.9 * 100 = 90 -``` - -**小程序显示**: -```xml -你获得 {{shareRate}}% 收益 - -``` - ---- - -## ⚠️ 可能的问题点 - -### 问题1: 配置值保存错误 - -**检查点**: -- 管理后台输入的是 90 还是 0.9? -- 数据库实际保存的值是多少? - -**验证SQL**: -```sql -SELECT config_value FROM system_config WHERE config_key = 'referral_config'; -``` - -**预期结果**: -```json -{ - "distributorShare": 90 -} -``` - -**如果看到**: -```json -{ - "distributorShare": 0.1 // ❌ 错误!应该是 90 -} -``` - ---- - -### 问题2: 计算公式错误 - -**检查点**: 是否有地方用错了公式? - -**错误示例**: -```typescript -// ❌ 错误:用了减法 -const commission = amount * (1 - distributorShare) -// 1 * (1 - 0.9) = 0.1 元(10%) - -// ✅ 正确:直接乘 -const commission = amount * distributorShare -// 1 * 0.9 = 0.9 元(90%) -``` - ---- - -### 问题3: 除以100的位置错误 - -**错误示例**: -```typescript -// ❌ 错误:没有除以100 -const distributorShare = config.distributorShare -const commission = amount * distributorShare / 100 -// 1 * 90 / 100 = 0.9 元(看起来对,但下一步就错了) -``` - -**正确方式**: -```typescript -// ✅ 正确:先除以100 -const distributorShare = config.distributorShare / 100 // 90 → 0.9 -const commission = amount * distributorShare // 1 * 0.9 = 0.9 -``` - ---- - -## 🧪 测试用例 - -### 测试1: 购买1元(无折扣) - -**输入**: -- 支付金额: 1.00元 -- distributorShare: 90 - -**计算过程**: -```typescript -const distributorShare = 90 / 100 = 0.9 -const commission = 1.00 * 0.9 = 0.90元 -``` - -**预期结果**: 推荐人获得 0.90元 - ---- - -### 测试2: 购买1元(5%折扣) - -**输入**: -- 原价: 1.00元 -- 好友优惠: 5% -- 实付: 0.95元 -- distributorShare: 90 - -**计算过程**: -```typescript -const finalAmount = 1.00 * (1 - 0.05) = 0.95元 -const commission = 0.95 * 0.9 = 0.855 ≈ 0.86元 -``` - -**预期结果**: 推荐人获得 0.86元 - ---- - -### 测试3: 如果配置错误保存为0.9 - -**输入**: -- 支付金额: 1.00元 -- distributorShare: 0.9 (❌ 错误的保存值) - -**计算过程**: -```typescript -const distributorShare = 0.9 / 100 = 0.009 -const commission = 1.00 * 0.009 = 0.009 ≈ 0.01元 -``` - -**错误结果**: 推荐人只获得 0.01元(1%)❌ - ---- - -## 🔍 排查步骤 - -### 步骤1: 检查数据库配置值 - -**SQL查询**: -```sql -SELECT config_key, config_value -FROM system_config -WHERE config_key = 'referral_config'; -``` - -**检查要点**: -- `distributorShare` 应该是 **90**(不是 0.9) -- 如果是其他值(如 10),说明保存时出错了 - ---- - -### 步骤2: 检查实际佣金记录 - -**SQL查询**: -```sql -SELECT - rb.referrer_id, - rb.referee_id, - rb.purchase_count, - rb.total_commission, - o.amount, - o.order_sn -FROM referral_bindings rb -JOIN orders o ON o.user_id = rb.referee_id AND o.status = 'paid' -WHERE rb.purchase_count > 0 -ORDER BY rb.last_purchase_date DESC -LIMIT 5; -``` - -**检查要点**: -- 订单金额 1.00元 → 佣金应该约 0.90元 -- 如果佣金是 0.10元,说明计算错误 - ---- - -### 步骤3: 检查控制台日志 - -**查看PM2日志**: -```bash -pm2 logs soul --lines 100 | grep "处理分佣" -``` - -**预期输出**: -``` -[PayNotify] 处理分佣: { - amount: 0.95, - commission: 0.855, - shareRate: '90%' -} -``` - -**如果看到**: -``` -shareRate: '10%' // ❌ 错误! -``` - ---- - -## 🔧 可能的修复方案 - -### 修复1: 如果配置值错误 - -**检查数据库**: -```sql -SELECT config_value FROM system_config WHERE config_key = 'referral_config'; -``` - -**如果显示**: -```json -{"distributorShare": 10} // ❌ 错误 -``` - -**手动修复**: -```sql -UPDATE system_config -SET config_value = '{"distributorShare":90,"minWithdrawAmount":10,"bindingDays":30,"userDiscount":5,"enableAutoWithdraw":false}' -WHERE config_key = 'referral_config'; -``` - -**或者在管理后台重新保存** 90%。 - ---- - -### 修复2: 如果计算公式错误 - -**检查位置**: `app/api/miniprogram/pay/notify/route.ts` 第395行 - -**当前代码**: -```typescript -const commission = Math.round(amount * distributorShare * 100) / 100 -``` - -**验证**: -- 如果 distributorShare = 0.9,commission = 0.9元 ✅ -- 如果 distributorShare = 0.009,commission = 0.009元 ❌ - ---- - -## 📝 诊断建议 - -请提供以下信息以便诊断: - -1. **管理后台显示的值**: - - 进入 `/admin/referral-settings` - - 查看"分销比例"输入框中的值是多少? - -2. **实际佣金金额**: - - 用户A购买1元商品 - - 推荐人B实际获得多少佣金? - -3. **小程序显示的比例**: - - 分销中心显示的是"你获得 xx% 收益" - - 这个 xx 是多少? - ---- - -**根据你的反馈,我会立即定位并修复问题!** diff --git a/开发文档/8、部署/佣金问题-快速诊断和修复.md b/开发文档/8、部署/佣金问题-快速诊断和修复.md deleted file mode 100644 index c4132559..00000000 --- a/开发文档/8、部署/佣金问题-快速诊断和修复.md +++ /dev/null @@ -1,232 +0,0 @@ -# 佣金计算问题 - 快速诊断和修复 - -## 🚨 问题描述 - -用户反馈:"推广者应该获取支付金额的90%,但却是10%" - ---- - -## 🔍 快速诊断 - -### 方法1: 检查管理后台配置 - -1. 登录管理后台:`https://soul.quwanzhi.com/admin` -2. 进入「推广设置」页面:`/admin/referral-settings` -3. 查看「分销比例」输入框中的数值 - -**如果显示 10** → 配置错误,应该改为 **90** - -**如果显示 90** → 配置正确,问题在其他地方 - ---- - -### 方法2: 检查实际佣金 - -1. 找一个推荐关系的订单 -2. 查看推荐人获得的佣金 - -**示例**: -- 用户B购买1元商品(无折扣) -- 推荐人A应得:0.90元(90%) -- 如果实际只得:0.10元 → 说明比例算反了 - ---- - -### 方法3: 检查小程序显示 - -打开小程序「分销中心」,查看推广规则: - -**应该显示**: -``` -好友成功付款后,你获得 90% 收益 -``` - -**如果显示**: -``` -好友成功付款后,你获得 10% 收益 -``` - -→ 说明后端返回的 `shareRate` 值错误 - ---- - -## 🔧 修复方案 - -### 修复1: 如果管理后台配置值错误 - -**步骤**: -1. 进入管理后台 `/admin/referral-settings` -2. 将「分销比例」改为 **90** -3. 点击「保存配置」 -4. 刷新小程序验证 - ---- - -### 修复2: 如果数据库配置值错误 - -**手动修复SQL**: -```sql --- 1. 查看当前配置 -SELECT config_value FROM system_config WHERE config_key = 'referral_config'; - --- 2. 如果 distributorShare 不是 90,手动更新 -UPDATE system_config -SET config_value = JSON_SET( - config_value, - '$.distributorShare', - 90 -) -WHERE config_key = 'referral_config'; - --- 3. 验证修改 -SELECT config_value FROM system_config WHERE config_key = 'referral_config'; -``` - ---- - -### 修复3: 如果计算公式错误 - -**检查文件**: `app/api/miniprogram/pay/notify/route.ts` - -**第395行,当前代码应该是**: -```typescript -const commission = Math.round(amount * distributorShare * 100) / 100 -``` - -**如果错误写成了**: -```typescript -// ❌ 错误1:算反了 -const commission = Math.round(amount * (1 - distributorShare) * 100) / 100 - -// ❌ 错误2:没有先除100 -const distributorShare = config.distributorShare // 90(没除100) -const commission = amount * distributorShare / 100 // 1 * 90 / 100 = 0.9(看似对,但后续会错) -``` - ---- - -## 🧪 验证步骤 - -### 验证1: 手动计算 - -假设配置 `distributorShare = 90`: - -```javascript -// 读取配置 -const configValue = 90 - -// 转换为小数 -const distributorShare = configValue / 100 // = 0.9 - -// 计算佣金(购买1元) -const commission = 1.00 * 0.9 // = 0.90元 - -// 返回给小程序 -const shareRate = distributorShare * 100 // = 90 -``` - -**预期**: -- 购买1元 → 推荐人得 0.90元 -- 小程序显示:90% 返利 - ---- - -### 验证2: 查看实际订单 - -**SQL查询**: -```sql -SELECT - o.order_sn, - o.amount as 订单金额, - rb.total_commission as 累计佣金, - rb.purchase_count as 购买次数, - o.amount * 0.9 as 预期佣金90percent, - o.amount * 0.1 as 如果是10percent -FROM orders o -JOIN referral_bindings rb ON o.user_id = rb.referee_id -WHERE o.status = 'paid' - AND rb.purchase_count > 0 -ORDER BY o.pay_time DESC -LIMIT 5; -``` - -**对比**: -- 如果 `total_commission ≈ 预期佣金90percent` → 计算正确 -- 如果 `total_commission ≈ 如果是10percent` → 计算错误(算反了) - ---- - -## 🔍 代码审查 - -### 关键代码1: 读取配置 - -**文件**: `app/api/miniprogram/pay/notify/route.ts` 第357-360行 - -```typescript -const config = await getConfig('referral_config') -if (config?.distributorShare) { - distributorShare = config.distributorShare / 100 // ✅ 应该是这样 -} -``` - -**如果错误写成**: -```typescript -distributorShare = config.distributorShare // ❌ 没除100 -``` - ---- - -### 关键代码2: 计算佣金 - -**文件**: `app/api/miniprogram/pay/notify/route.ts` 第395行 - -```typescript -const commission = Math.round(amount * distributorShare * 100) / 100 -// ✅ 正确:1 * 0.9 = 0.9 -``` - -**如果错误写成**: -```typescript -const commission = Math.round(amount * (1 - distributorShare) * 100) / 100 -// ❌ 错误:1 * (1 - 0.9) = 0.1(算反了) -``` - ---- - -### 关键代码3: 返回比例 - -**文件**: `app/api/referral/data/route.ts` 第198行 - -```typescript -shareRate: Math.round(distributorShare * 100) -// ✅ 正确:0.9 * 100 = 90 -``` - ---- - -## 🚀 立即检查 - -请你帮我确认一下: - -### 问题1: 管理后台的配置值 -进入 `https://soul.quwanzhi.com/admin/referral-settings`,看看「分销比例」输入框中显示的是: -- [ ] 90(正确) -- [ ] 10(错误) -- [ ] 0.9(错误) - -### 问题2: 小程序显示的比例 -打开小程序「分销中心」,查看推广规则显示的是: -- [ ] "你获得 90% 收益"(正确) -- [ ] "你获得 10% 收益"(错误) - -### 问题3: 实际佣金金额 -如果有测试订单,查看: -- 购买金额:1.00元 -- 推荐人获得:_____ 元 - -**如果是 0.90元** → 计算正确 -**如果是 0.10元** → 计算错误 - ---- - -**请告诉我上述三个问题的实际情况,我会立即定位并修复!** diff --git a/开发文档/8、部署/其它.md b/开发文档/8、部署/其它.md deleted file mode 100644 index ef1f24e7..00000000 --- a/开发文档/8、部署/其它.md +++ /dev/null @@ -1,3 +0,0 @@ -# 其它(合并自 宝塔配置检查、小程序上传复盘) - -宝塔配置检查说明、小程序上传复盘(版本 1.17、CLI 上传等)。详见原各文档。 diff --git a/开发文档/8、部署/分销与绑定流程图.md b/开发文档/8、部署/分销与绑定流程图.md deleted file mode 100644 index 8fd78cee..00000000 --- a/开发文档/8、部署/分销与绑定流程图.md +++ /dev/null @@ -1,383 +0,0 @@ -# 分销与绑定流程图 - -> 用流程图把「绑定」和「推荐人/邀请码」在系统中的用法讲清楚。 -> 建议配合《邀请码分销规则说明》一起看。 - ---- - -## 一、概念速查 - -| 名词 | 是什么 | 存哪儿 | 谁用 | -|------|--------|--------|------| -| **邀请码** | 一串码,如 `SOULABC123` | 每个用户一条:`users.referral_code` | 链接里 `ref=邀请码`,用来**认出**是谁推荐的 | -| **推荐人** | 拿佣金的那个人(用户) | 用**用户ID**存:`referrer_id` | 绑定表、订单表、分佣都只认这个 ID | -| **被推荐人** | 通过链接进来的访客/买家 | 用**用户ID**存:`referee_id` | 绑定表里「谁被谁推荐」 | - -关系:**邀请码** → 查 `users` 表 → 得到**推荐人用户ID**(referrer_id)。系统里所有「归属、分佣」只认 referrer_id,不直接认邀请码字符串。 - ---- - -## 二、整体流程总览(一图看懂) - -``` -┌─────────────────────────────────────────────────────────────────────────────────┐ -│ 分销全流程:从分享到分佣 │ -└─────────────────────────────────────────────────────────────────────────────────┘ - - 推广者 A(推荐人) 访客/买家 B(被推荐人) 系统 - - │ │ │ - │ 1. 分享带 ref 的链接 │ │ - │ ?ref=A的邀请码 │ │ - ├─────────────────────────────────────>│ 2. 点击链接进入小程序/阅读页 │ - │ ├─────────────────────────────────>│ - │ │ app.js: 存 referral_code │ - │ │ 可选: 记录访问 referral_visit │ - │ │ │ - │ │ 3. 登录(微信/手机号/getOpenId 拿到 user) │ - │ ├─────────────────────────────────>│ - │ │ 登录成功即调 /api/referral/bind │ - │ │ 入参: userId, referralCode │ - │ │ │ - │ │ 4. 绑定逻辑 │ - │ │ referral_code │ - │ │ → 查 users 得 │ - │ │ referrer_id=A │ - │ │ 写 referral_ │ - │ │ bindings │ - │ │ (referee=B, │ - │ │ referrer=A) │ - │ │<─────────────────────────────────┤ - │ │ 绑定成功(new/renew/takeover) │ - │ │ │ - │ │ 5. 下单(章节/找伙伴) │ - │ │ POST /api/miniprogram/pay │ - │ │ body: referralCode(可选) │ - │ ├─────────────────────────────────>│ - │ │ 6. 定推荐人 │ - │ │ 先查 bindings │ - │ │ (referee=B)→A │ - │ │ 无则用 referral│ - │ │ Code 解析→A │ - │ │ 写 orders. │ - │ │ referrer_id=A,│ - │ │ referral_code │ - │ │<─────────────────────────────────┤ - │ │ 返回支付参数 │ - │ │ │ - │ │ 7. 调起微信支付 │ - │ ├───────────────────────────────> 微信 - │ │ 8. 用户付款成功 │ - │ │<─────────────────────────────── 微信 - │ │ │ - │ │ 9. 支付回调 │ - │ │ POST .../notify│ - │ │ 查 bindings │ - │ │ (referee=B)→A │ - │ │ 佣金=金额×90% │ - │ │ A.pending_ │ - │ │ earnings += 佣金│ - │ │ binding→ │ - │ │ converted │ - │ │ │ - │ 10. 推广者 A 看到待结算收益 +90% │ │ - │<─────────────────────────────────────│ │ -``` - ---- - -## 三、绑定流程(邀请码 → 推荐关系) - -绑定解决的是:**「谁(B)是通过谁(A)的链接来的」**,并写入 `referral_bindings`。 - -**绑定规则(后端统一保证):** -- **不重复绑定**:被推荐人 B 已有**当前推荐人 A** 的有效绑定时,再次用 A 的邀请码调用 bind → **不新建记录**,只做**续期**(把过期时间再延长 30 天)。 -- **有时效**:每条绑定的有效期为 **30 天**(`expiry_date`);分佣、下单定推荐人时只认「未过期」的绑定。 -- **超时可重新绑定**:超过 30 天未续期的绑定视为过期;此时 B 再通过**其他人 C** 的链接进来并登录 → 允许绑定到 C(旧绑定标记过期,新绑定 C,即「抢夺」);若仍通过 A 的链接 → 续期 A 的绑定。 - -**绑定从登录就开始**:只要前端拿到 userId(登录成功),就立刻用当前的 `pendingReferralCode` 调 `/api/referral/bind`,不等到下单。后端根据上述规则决定是**新绑定 / 续期 / 抢夺 / 拒绝**。 - -```mermaid -flowchart TB - subgraph 入口 - A1["推广者 A 分享链接
带 ref=A的邀请码"] - A2["访客 B 点击链接进入"] - end - - subgraph 前端 - B1["app.js: 检测到 ref"] - B2["写入 storage: referral_code + pendingReferralCode"] - B3["若已登录 → 立即调 bind"] - B4["若未登录 → 等任意登录成功后再调 bind"] - B5["登录含: login / loginWithPhone / getOpenId 拿到 user 时"] - end - - subgraph 后端绑定API["POST /api/referral/bind"] - C1["入参: userId(B), referralCode"] - C2["用 referralCode 查 users 表 → 推荐人 A"] - C3["不能自己推荐自己"] - C4["查 B 是否已有有效绑定(active)"] - C5{"已有绑定?"} - C6["同一推荐人 A → 只续期,不重复绑定
expiry = 当前+30天"] - C7["不同人且已过期(>30天) → 可重新绑定
旧绑定过期,新绑定 A"] - C8["不同人且未过期 → 拒绝"] - C9["无绑定 / 续期 / 抢夺后 → 写 binding
referrer_id=A, referee_id=B, expiry=+30天"] - end - - A1 --> A2 --> B1 --> B2 - B2 --> B3 - B2 --> B4 - B4 --> B5 - B3 --> C1 - B5 --> C1 - C1 --> C2 --> C3 --> C4 --> C5 - C5 -->|无| C9 - C5 -->|有,同一人| C6 --> C9 - C5 -->|有,另一人已过期| C7 --> C9 - C5 -->|有,另一人未过期| C8 -``` - -要点: -- **绑定表**是「谁推荐了谁」的**唯一权威**;分佣只看这张表。 -- **已有绑定不重复**:同一推荐人再次绑只续期;**30 天**内不能换绑其他推荐人,超过 30 天可重新绑定(被新推荐人「抢夺」或原推荐人续期)。 -- **邀请码**只在「解析出推荐人是谁」时用,解析完得到的是 **referrer_id**(用户ID)。 - ---- - -## 四、下单时「推荐人」怎么定(写订单) - -创建订单时要把「这笔单算谁的推广」记在 `orders.referrer_id` 和 `orders.referral_code`。逻辑是:**先认绑定,再认邀请码**。 - -```mermaid -flowchart LR - subgraph 请求 - R1["POST /api/miniprogram/pay"] - R2["body: userId(B), referralCode(可选)"] - end - - subgraph 定推荐人 - S1["查 referral_bindings"] - S2["WHERE referee_id = B
AND status='active'
AND expiry_date > NOW()"] - S3{"查到有效绑定?"} - S4["referrer_id = 绑定里的 referrer_id"] - S5["referrer_id = 用 referralCode
查 users 得到的 id"] - S6["都无 → referrer_id = null"] - end - - subgraph 写订单 - T1["INSERT orders"] - T2["referrer_id = 上面得到的"] - T3["referral_code = 请求里的 referralCode
或推荐人当前 users.referral_code"] - end - - R1 --> R2 --> S1 --> S2 --> S3 - S3 -->|是| S4 - S3 -->|否,但有 referralCode| S5 - S3 -->|否且无| S6 - S4 --> T1 - S5 --> T1 - S6 --> T1 - T1 --> T2 --> T3 -``` - -结论: -- **有绑定** → 订单的推荐人 = 绑定里的推荐人(与下单时传不传 referralCode 无关)。 -- **无绑定但传了 referralCode** → 用邀请码解析出推荐人,写入订单。 -- 订单上的 **referrer_id** 用于后台展示、对账;**分佣不看订单**,只看绑定表。 - ---- - -## 五、分佣流程(支付成功后) - -分佣**只看绑定表**,不看订单上的 referrer_id。 - -```mermaid -flowchart TB - subgraph 触发 - P1["微信支付成功"] - P2["POST /api/miniprogram/pay/notify"] - P3["body: 订单号、金额、买家等"] - end - - subgraph 回调逻辑 - Q1["更新订单 status=paid"] - Q2["解锁用户权限(章节/全书)"] - Q3["查 referral_bindings"] - Q4["WHERE referee_id = 买家"] - Q5["AND status='active'"] - Q6["AND expiry_date > NOW()"] - Q7{"查到有效绑定?"} - Q8["取 referrer_id = 推广者 A"] - Q9["佣金 = 订单金额 × 90%"] - Q10["A.pending_earnings += 佣金"] - Q11["该绑定 status → converted"] - Q12["记录 commission_amount, order_id"] - Q13["不分佣"] - end - - P1 --> P2 --> P3 --> Q1 --> Q2 --> Q3 --> Q4 --> Q5 --> Q6 --> Q7 - Q7 -->|是| Q8 --> Q9 --> Q10 --> Q11 --> Q12 - Q7 -->|否| Q13 -``` - -要点: -- 分佣**只认** `referral_bindings` 里「买家 → 有效绑定 → 推荐人」。 -- 订单里的 referrer_id / referral_code **不参与**分佣计算,只用于统计和展示。 - ---- - -### 什么情况下能拿到佣金(推广者视角) - -满足下面**全部**条件时,你(推广者)才能拿到这笔订单的佣金: - -1. **对方是通过你的链接进来的** - 对方点击的链接里带有你的邀请码(如 `?ref=你的邀请码`),进入小程序后系统会记下推荐码,并在登录时用于绑定。 - -2. **对方已经绑定到你** - 对方完成登录后,系统成功调用了绑定接口(新绑定或续期),且当前存在一条「被推荐人 = 对方、推荐人 = 你」的绑定记录,且该绑定 **status = active**、**expiry_date > 当前时间**(在 30 天有效期内或已续期)。 - -3. **对方在绑定有效期内下单并支付成功** - 对方在上述有效期内发起了购买(章节或全书),并完成微信支付;支付成功后,微信会回调我们的接口。 - -4. **支付回调时仍能查到你的有效绑定** - 支付成功回调执行时,系统按「买家 = 对方」查 `referral_bindings`,能查到一条有效绑定且推荐人是你,才会把约 90% 的佣金计入你的待结算收益(pending_earnings),并把该绑定标记为已转化(converted)。 - -**简单记**:你的链接 → 对方进来并登录绑定到你 → 有效期内对方付款 → 你拿佣金。 - ---- - -### 章节分享这块的分销收益方式 - -章节页分享(读某一章时分享给好友/朋友圈)与首页、推广中心的分享**用同一套绑定与分佣规则**,只是落地页是「某一章」的阅读页。收益方式如下: - -1. **入口与绑定** - 你从阅读页分享出去的链接带 `ref=你的邀请码`(例如 `/pages/read/read?id=1.2&ref=你的邀请码`)。对方点进后进入**该章节**阅读页,系统记下推荐码;对方**登录**后即完成绑定(新绑定或续期)。绑定规则(30 天、不重复绑、超时可重绑)与其它分享入口一致。 - -2. **收益比例** - 订单实付金额的**约 90%** 给推广者(与全书、其它章节一致,由 `referral_config.distributorShare` 配置)。对方买的是**这一章、别的章还是全书**,都按该笔订单金额 × 90% 计算佣金。 - -3. **计佣次数(每个被推荐人只计一次)** - 系统在支付成功回调里会查「该买家」的**有效绑定**,有则给推荐人加佣金,并把这条绑定标记为**已转化(converted)**。 - 因此:**同一个被推荐人在绑定有效期内,只有其「第一笔」支付会给你分佣**;该用户之后再买其它章节或全书,**不再**重复给你分佣(绑定已用掉)。 - -4. **小结** - **章节分享的收益**:你分享章节链接(带 ref)→ 对方进来并登录绑定到你 → 对方在有效期内**第一次**支付(可以是这一章、别的章或全书)→ 你获得**该笔订单金额的约 90%**;该用户后续订单不再给你分佣。 - ---- - -## 六、推荐人 vs 邀请码(怎么用、不混用) - -```mermaid -flowchart LR - subgraph 入口 - L1["链接 ref=SOULABC123"] - end - - subgraph 解析 - L2["邀请码 = SOULABC123"] - L3["users WHERE referral_code = ?"] - L4["推荐人 = 该用户的 id"] - end - - subgraph 存储 - M1["referral_bindings.referrer_id"] - M2["orders.referrer_id"] - M3["分佣发给谁"] - end - - L1 --> L2 --> L3 --> L4 - L4 --> M1 - L4 --> M2 - L4 --> M3 - - style L2 fill:#f9f,stroke:#333 - style L4 fill:#9f9,stroke:#333 -``` - -- **邀请码**:只在「从链接/请求里认出是谁」这一步用,用完就解析成 **referrer_id**。 -- **推荐人**:所有「归属、分佣、统计」都只用 **referrer_id**,不会把邀请码字符串当推荐人存。 - ---- - -## 七、表与字段关系简图 - -```mermaid -erDiagram - users ||--o{ referral_bindings : "referrer_id" - users ||--o{ referral_bindings : "referee_id" - users { - string id PK - string referral_code "自己的邀请码" - } - referral_bindings { - string referrer_id "推荐人(谁拿佣金)" - string referee_id "被推荐人(买家)" - string status "active|converted|expired" - timestamp expiry_date - } - orders { - string user_id "买家" - string referrer_id "推荐人ID(展示/对账)" - string referral_code "下单时邀请码(展示)" - } - referral_bindings ||--o{ orders : "分佣时关联" -``` - -- **绑定**:`referrer_id` = 推荐人,`referee_id` = 被推荐人;分佣只看这张表。 -- **订单**:`referrer_id`、`referral_code` 只做展示和对账,不参与分佣计算。 - ---- - -## 八、逻辑漏洞与注意点 - -以下为与流程图、实现对照后容易出现的漏洞和设计注意点,便于排查与加固。 - -### 8.1 严重:支付回调中买家身份不能信任客户端 - -**问题**:支付回调(`/api/miniprogram/pay/notify`)里若**优先**使用请求体/attach 里的 `userId` 作为买家,则该 `userId` 来自**创建订单时客户端传入**的 `body.userId`。若被篡改(如传成他人 userId),会导致: -- 订单归属、解锁权限记到错误用户; -- 分佣按「错误买家」查绑定表,可能把佣金算到错误推荐人或不分佣。 - -**正确做法**:**买家身份必须以微信回调中的 `openId` 为准**(微信侧不可伪造),用 `openId` 查 `users` 得到 `buyerUserId`;attach 中的 `userId` 仅作辅助或校验,不一致时以 openId 解析结果为准。 - -**实现建议**:在 notify 中先 `buyerUserId = 由 openId 查 users 得到`;若查不到再回退到 attach.userId,并打日志告警。 - ---- - -### 8.2 设计缺口:先下单、后绑定会导致无分佣 - -**问题**:流程图要求「先绑定、再下单」分佣才生效。若用户通过 A 的链接进入但**未调用** `/api/referral/bind`(未登录就下单、或 bind 失败/漏调),下单时传了 `referralCode`,订单上会有 `referrer_id=A`,但**分佣只看绑定表**,此时无绑定 → 不会给 A 分佣。 - -**结论**:这是当前设计下的预期行为,不是 bug,但需要在产品/运营上保证「进入后尽快登录并完成绑定」,或在文档中明确写清:**只有存在有效绑定时支付成功才会分佣**。 - ---- - -### 8.3 重复回调与重复分佣 - -**现状**:微信可能对同一笔支付多次回调。当前实现: -- 订单状态已为 `paid` 时跳过订单更新; -- 分佣时只取 `status='active'` 的绑定,且分佣后将该绑定置为 `converted`,同一买家不会再有第二条 active 绑定参与分佣。 - -因此**不会重复加佣**。无需改流程图,实现已防护。 - ---- - -### 8.4 绑定表与 users.referred_by 双写 - -**现状**:绑定 API 在「新绑定」或「抢夺」时会写 `users.referred_by`,与 `referral_bindings` 双写;「续期」只更新绑定表,不改 `referred_by`。 -分佣、下单定推荐人**只读绑定表**;GET 查询「我的推荐人」等可能读 `users.referred_by`。只要绑定接口保证 new/takeover 时双写一致,则无逻辑漏洞。若以后有接口只改 `referred_by` 而不改绑定表,就会不一致,需避免。 - ---- - -### 8.5 小结 - -| 类型 | 说明 | -|------------|------| -| 必须修 | 支付回调中买家身份以 openId 解析为准,不信任 attach.userId。 | -| 文档/产品 | 明确「先绑定再下单才能分佣」;未绑定仅下单只记订单归属、不分佣。 | -| 已防护 | 重复回调不会导致重复分佣。 | -| 需长期一致 | 绑定表与 users.referred_by 在 new/takeover 时双写,避免单改其一。 | - ---- - -若要把某一段改成「按步骤」的纯文字版或拆成多张图,可以说明要哪一段(绑定 / 下单 / 分佣 / 概念)。 diff --git a/开发文档/8、部署/分销提现流程图.md b/开发文档/8、部署/分销提现流程图.md deleted file mode 100644 index 45835765..00000000 --- a/开发文档/8、部署/分销提现流程图.md +++ /dev/null @@ -1,127 +0,0 @@ -# 分销提现流程图 - -## 一、整体流程 - -``` -┌─────────────────────────────────────────────────────────────────────────────────┐ -│ 小 程 序 端 │ -└─────────────────────────────────────────────────────────────────────────────────┘ - - [用户] 推广中心 → 可提现金额 ≥ 最低额 → 点击「申请提现」 - │ - ▼ - POST /api/miniprogram/withdraw (WithdrawPost) - │ 校验:可提现余额、最低金额、用户 openId - ▼ - 写入 withdrawals:status = pending - │ - ▼ - 提示「提现申请已提交,审核通过后将打款至您的微信零钱」 - -───────────────────────────────────────────────────────────────────────────────── - -┌─────────────────────────────────────────────────────────────────────────────────┐ -│ 管 理 端 (soul-admin) │ -└─────────────────────────────────────────────────────────────────────────────────┘ - - [管理员] 分销 / 提现审核 → GET /api/admin/withdrawals 拉列表 - │ - ├── 点「拒绝」 → PUT /api/admin/withdrawals { action: "reject" } - │ ▼ - │ status = failed,写 error_message - │ - └── 点「通过」 → PUT /api/admin/withdrawals { action: "approve" } - │ - ▼ - 调 wechat.InitiateTransferByFundApp (FundApp 单笔) - │ - ┌───────────────┼───────────────┐ - ▼ ▼ ▼ - [微信报错] [未返回单号] [成功受理] - │ │ │ - ▼ ▼ ▼ - status=failed status=failed status=processing - 返回报错信息 返回提示 写 detail_no,batch_no,batch_id - 返回「已发起打款,微信处理中」 - -───────────────────────────────────────────────────────────────────────────────── - -┌─────────────────────────────────────────────────────────────────────────────────┐ -│ 微 信 侧 与 回 调 │ -└─────────────────────────────────────────────────────────────────────────────────┘ - - 微信异步打款 - │ - ▼ - 打款结果 → POST /api/payment/wechat/transfer/notify (PaymentWechatTransferNotify) - │ 验签、解密,得到 out_bill_no / transfer_bill_no / state / fail_reason - │ 用 detail_no = out_bill_no 找到提现记录,且仅当 status 为 processing / pending_confirm 时更新 - ▼ - state=SUCCESS → status = success - state=FAIL/CANCELLED → status = failed,写 fail_reason - -───────────────────────────────────────────────────────────────────────────────── - -┌─────────────────────────────────────────────────────────────────────────────────┐ -│ 可 选:主 动 同 步 │ -└─────────────────────────────────────────────────────────────────────────────────┘ - - 管理端 POST /api/admin/withdrawals/sync(可带 id 同步单条,或不带 id 同步所有) - │ 只处理 status IN (processing, pending_confirm) - │ FundApp 单笔:用 detail_no 调 QueryTransferByOutBill - ▼ - 按微信返回的 state 更新 status = success / failed(与回调逻辑一致) - -───────────────────────────────────────────────────────────────────────────────── - -┌─────────────────────────────────────────────────────────────────────────────────┐ -│ 小 程 序「我 的」- 待 确 认 收 款 │ -└─────────────────────────────────────────────────────────────────────────────────┘ - - [用户] 我的页 → 仅登录显示「待确认收款」区块 - │ - ▼ - GET /api/miniprogram/withdraw/pending-confirm?userId=xxx (WithdrawPendingConfirm) - │ 只返回 status IN (processing, pending_confirm) 的提现(审核通过后的) - ▼ - 展示列表:金额、日期、「确认收款」按钮 - │ - ▼ - 点击「确认收款」→ 需要 item.package + mchId + appId 调 wx.requestMerchantTransfer - │ 当前后端 list 里 package 为空,故会提示「请稍后刷新再试」 - └─ 若后续接入微信返回的 package,可在此完成「用户确认收款」闭环 -``` - -## 二、状态流转 - -| 阶段 | 状态 (status) | 含义 | -|--------------|----------------|------| -| 用户申请 | **pending** | 待审核,已占可提现额度 | -| 管理员通过 | **processing** | 已发起打款,微信处理中 | -| 微信回调成功 | **success** | 打款成功(已到账) | -| 微信回调失败/拒绝 | **failed** | 打款失败,写 fail_reason | -| 预留 | **pending_confirm** | 待用户确认收款(当前流程未改此状态,仅接口可返回) | - -## 三、可提现与待确认口径 - -- **可提现** = 累计佣金 − 已提现 − 待审核金额 - 待审核金额 = 所有 status 为 `pending`、`processing`、`pending_confirm` 的提现金额之和。 -- **待确认收款列表**:仅包含 **审核已通过** 的提现,即 status 为 `processing` 或 `pending_confirm`,不包含 `pending`。 - -## 四、主要接口与代码位置 - -| 环节 | 接口/行为 | 代码位置 | -|------------|-----------|----------| -| 用户申请 | POST `/api/miniprogram/withdraw` | soul-api `internal/handler/withdraw.go` WithdrawPost | -| 可提现计算 | referral/data、withdraw 校验 | `withdraw.go` computeAvailableWithdraw;`referral.go` 提现统计 | -| 管理端列表 | GET `/api/admin/withdrawals` | `internal/handler/admin_withdrawals.go` AdminWithdrawalsList | -| 管理端通过/拒绝 | PUT `/api/admin/withdrawals` | `admin_withdrawals.go` AdminWithdrawalsAction | -| 微信打款 | FundApp 单笔 | soul-api `internal/wechat/transfer.go` InitiateTransferByFundApp | -| 微信回调 | POST `/api/payment/wechat/transfer/notify` | `internal/handler/payment.go` PaymentWechatTransferNotify | -| 管理端同步 | POST `/api/admin/withdrawals/sync` | `admin_withdrawals.go` AdminWithdrawalsSync | -| 待确认列表 | GET `/api/miniprogram/withdraw/pending-confirm` | `withdraw.go` WithdrawPendingConfirm | - -## 五、说明 - -- 当前实现:审核通过后直接调微信 FundApp 单笔打款,最终由**微信回调**或**管理端同步**把状态更新为 success/failed。 -- 「待确认收款」列表只展示已审核通过的记录;点击「确认收款」需后端下发的 `package` 才能调起 `wx.requestMerchantTransfer`,目前该字段为空,前端会提示「请稍后刷新再试」。若后续接入微信返回的 package,可在此完成用户确认收款闭环。 diff --git a/开发文档/8、部署/商家转账.md b/开发文档/8、部署/商家转账.md deleted file mode 100644 index b5b7d01f..00000000 --- a/开发文档/8、部署/商家转账.md +++ /dev/null @@ -1,40 +0,0 @@ -# 商家转账 PowerWeChat 调用示例 - -> 来源:soul-api/商家转账.md。已整理至开发文档。完整实现见 [提现功能完整技术文档](提现功能完整技术文档.md)。 - ---- - -## 请求示例(PowerWeChat) - -```go -req := &request.RequestTransferBills{ - Appid: "Appid", - OutBillNo: "OutBillNo", - TransferSceneId: "TransferSceneId", - Openid: "Openid", - UserName: "UserName", - TransferAmount: 1, - TransferRemark: "TransferRemark", - NotifyUrl: "NotifyUrl", - UserRecvPerception: "UserRecvPerception", - TransferSceneReportInfos: []request.TransferSceneReportInfo{ - { - InfoType: "InfoType", - InfoContent: "InfoContent", - }, - }, -} -ctx := c.Request.Context() -rs, err := services.PaymentApp.FundApp.TransferBills(ctx, req) -if err != nil { - panic(err) -} -c.JSON(http.StatusOK, rs) -``` - ---- - -## 相关文档 - -- [提现功能完整技术文档](提现功能完整技术文档.md) — 微信支付商家转账到零钱 API 集成 -- [分销提现流程图](分销提现流程图.md) — 提现业务流程图 diff --git a/开发文档/8、部署/存客宝API-Key约定.md b/开发文档/8、部署/存客宝API-Key约定.md deleted file mode 100644 index 030d68a6..00000000 --- a/开发文档/8、部署/存客宝API-Key约定.md +++ /dev/null @@ -1,28 +0,0 @@ -# 存客宝 API Key 约定 - -## 约定说明 - -存客宝(ckbapi.quwanzhi.com)不同业务使用**不同的 apiKey**,对接时需按场景选用,避免混用。 - -| 场景 | 用途 | Key 来源 | 说明 | -|------|------|----------|------| -| **链接卡若** | 首页「链接卡若」留资,添加卡若为好友 | 环境变量 `CKB_LEAD_API_KEY` | 需在 .env 中配置;未配置时回退为下方「其他场景」的 key;请求方式为 **POST** + JSON(name, phone, wechatId, apiKey, timestamp, sign) | -| **其他** | join(团队/资源/导师/合伙)、match(找伙伴匹配)等 | 代码常量 `ckbAPIKey` | 当前为 `fyngh-ecy9h-qkdae-epwd5-rz6kd` | - -## 配置示例 - -- **链接卡若**(添加好友需用专用 key,示例): - ```env - CKB_LEAD_API_KEY=2y4v5-rjhfc-sg5wy-zklkv-bg0tl - ``` -- 后续若有其他「添加某某为好友」类场景,由存客宝提供对应 key,再在配置或代码中单独挂接,**不要与链接卡若的 key 混用**。 - -## 代码位置 - -- soul-api:`internal/handler/ckb.go` - - 链接卡若:`CKBLead` 中读取 `config.Get().CkbLeadAPIKey`,有则用,无则用 `ckbAPIKey` - - join/match:统一使用 `ckbAPIKey` - ---- - -记录时间:2025-03;原因:链接卡若需专用 key 才能正常添加好友,其他场景用另一 key。 diff --git a/开发文档/8、部署/宝塔反向代理说明.md b/开发文档/8、部署/宝塔反向代理说明.md deleted file mode 100644 index 099d80d2..00000000 --- a/开发文档/8、部署/宝塔反向代理说明.md +++ /dev/null @@ -1,87 +0,0 @@ -# soul-api 域名 404 原因与解决 - -> 来源:soul-api/宝塔反向代理说明.txt - -## 原因 - -域名请求先到 Nginx,若没有把请求转发到本机 8080 的 Go,或站点用了 root/静态目录,就会 404。 - ---- - -## 一、先确认 Go 是否在跑(必做) - -在宝塔终端或 SSH 里执行: - -``` -curl -s http://127.0.0.1:8080/health -``` - -- 若返回 `{"status":"ok"}`:说明 Go 正常,问题在 Nginx,看下面第二步。 -- 若连接被拒绝或超时:说明 8080 没在监听。去 宝塔 → Go项目管理 → soulApi → 服务状态,看是否「运行中」;看「项目日志」是否有报错。 - ---- - -## 二、Nginx 必须「整站走代理」,不能走 root - -添加了反向代理仍 404,多半是: - -- 站点默认有 `location / { root ...; index ...; }`,请求被当成静态文件处理,`/health` 找不到就 404; -- 或反向代理只绑在了子路径(如 `/api`),`/` 和 `/health` 没被代理。 - -**做法**:让 soulapi.quwanzhi.com 的**所有路径**都走 8080,不要用 root。 - -在宝塔:网站 → soulapi.quwanzhi.com → 设置 → 配置文件,找到该站点的 `server { ... }`,按下面两种方式之一改。 - -### 方式 A:只保留一个 location /(推荐) - -把 server 里**原来的** `location / { ... }`(含 root、index 的那段)**删掉或注释掉**,只保留下面这一段: - -```nginx -location / { - proxy_pass http://127.0.0.1:8080; - proxy_http_version 1.1; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; -} -``` - -保存 → 重载 Nginx(或 宝塔 里点「重载配置」)。 - -### 方式 B:整站用下面这一整段 server(HTTPS 示例) - -若你希望整站只做反向代理、不混静态,可以把该站点的 server 块整体替换成下面内容(把 your_ssl_cert 等换成你实际的证书路径;没有 SSL 就只用 listen 80 那段): - -```nginx -server { - listen 80; - listen 443 ssl http2; - server_name soulapi.quwanzhi.com; - # SSL 证书路径按宝塔实际填写,例如: - # ssl_certificate /www/server/panel/vhost/cert/soulapi.quwanzhi.com/fullchain.pem; - # ssl_certificate_key /www/server/panel/vhost/cert/soulapi.quwanzhi.com/privkey.pem; - - location / { - proxy_pass http://127.0.0.1:8080; - proxy_http_version 1.1; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - } -} -``` - -保存并重载 Nginx。 - ---- - -## 三、改完后自测 - -- 本机:`curl -s https://soulapi.quwanzhi.com/health` -- 或浏览器打开:https://soulapi.quwanzhi.com/health - -应看到:`{"status":"ok"}` - -- 打开 https://soulapi.quwanzhi.com/ 应看到「部署成功」页面。 diff --git a/开发文档/8、部署/宝塔面板配置订单同步定时任务.md b/开发文档/8、部署/宝塔面板配置订单同步定时任务.md deleted file mode 100644 index 58f9a2af..00000000 --- a/开发文档/8、部署/宝塔面板配置订单同步定时任务.md +++ /dev/null @@ -1,369 +0,0 @@ -# 宝塔面板配置订单同步定时任务 - -> 适用于:有宝塔面板的服务器 -> 难度:⭐(非常简单,3 分钟搞定) - ---- - -## 一、准备工作 - -### 1. 生成安全密钥 - -打开终端(本地电脑),执行: - -```bash -# Windows PowerShell --join ((65..90) + (97..122) + (48..57) | Get-Random -Count 32 | % {[char]$_}) - -# 或手动生成一个 32 位随机字符串,例如: -# 密钥已写死在代码里,见下文 URL -``` - -**接口使用的固定密钥**:`soul_cron_sync_orders_2026`(无需自己生成) - ---- - -## 二、宝塔面板配置步骤 - -### 步骤 1:登录宝塔面板 - -1. 浏览器打开:`http://你的服务器IP:8888` -2. 输入账号密码登录 - -### 步骤 2:打开计划任务 - -1. 左侧菜单点击 **"计划任务"** -2. 点击右上角 **"添加任务"** - -### 步骤 3:配置任务(方案 A - 访问 URL,推荐) - -在弹出的对话框中填写: - -| 字段 | 填写内容 | 说明 | -|------|---------|------| -| **任务类型** | 选择 `访问URL` | 下拉框选择 | -| **任务名称** | `订单状态同步` | 随便填,方便识别 | -| **执行周期** | 选择 `N分钟` | 下拉框选择 | -| **分钟选择** | 填 `5` | 表示每 5 分钟执行一次 | -| **URL地址** | `https://soul.quwanzhi.com/api/cron/sync-orders?secret=soul_cron_sync_orders_2026` | 密钥已写死在代码里,无需修改 | - -**完整 URL 示例**(密钥已写死在代码里,直接用即可): -``` -https://soul.quwanzhi.com/api/cron/sync-orders?secret=soul_cron_sync_orders_2026 -``` - -### 步骤 4:点击保存 - -点击底部的 **"提交"** 或 **"确定"** 按钮。 - -### 步骤 5:验证任务已添加 - -在任务列表中应该能看到: -- ✅ 任务名称:订单状态同步 -- ✅ 类型:访问URL -- ✅ 周期:每 5 分钟 -- ✅ 状态:正常(绿色) - ---- - -## 三、立即测试执行 - -### 方法 1:宝塔面板手动执行 - -1. 在任务列表中找到刚添加的任务 -2. 点击右侧的 **"执行"** 按钮 -3. 查看执行结果: - - 成功:显示 JSON 响应 `{"success":true,...}` - - 失败:显示错误信息 - -### 方法 2:浏览器测试 - -直接在浏览器打开: -``` -https://soul.quwanzhi.com/api/cron/sync-orders?secret=YOUR_SECRET -``` - -**预期响应**(成功): -```json -{ - "success": true, - "message": "订单状态同步完成", - "total": 0, - "synced": 0, - "expired": 0, - "error": 0, - "duration": 123 -} -``` - -**如果响应 401 错误**: -```json -{ - "success": false, - "error": "未授权访问" -} -``` -说明密钥不对,检查 URL 中的 `secret` 参数。 - ---- - -## 四、查看执行日志 - -### 宝塔面板查看 - -1. 计划任务列表 -2. 找到"订单状态同步"任务 -3. 点击右侧的 **"日志"** 按钮 -4. 查看最近的执行记录 - -**正常日志示例**: -``` -[2026-02-04 21:00:00] 开始执行 -[2026-02-04 21:00:01] 状态码: 200 -[2026-02-04 21:00:01] 响应: {"success":true,"synced":0,"expired":0} -[2026-02-04 21:00:01] 执行完成 -``` - ---- - -## 五、配置环境变量(重要!) - -定时任务需要密钥验证,必须在项目中配置: - -### 方法 1:通过宝塔面板配置 - -1. 左侧菜单 → **网站** -2. 找到 `soul.quwanzhi.com` 网站 -3. 点击 **设置** -4. 左侧选择 **"伪静态"** 或 **"配置文件"**(取决于宝塔版本) -5. 找到 Node.js 项目的启动配置 - -### 方法 2:在项目根目录创建 `.env.production` - -SSH 登录服务器: -```bash -ssh root@你的服务器IP - -cd /www/wwwroot/soul - -# 编辑 .env.production -nano .env.production -``` - -添加以下内容: -```bash -# 定时任务密钥(与宝塔任务中的 secret 保持一致) -# CRON_SECRET 已写死在代码,无需配置 - -# 微信支付 API 密钥(从微信商户平台获取) -WECHAT_API_KEY=你的32位API密钥 -``` - -保存后重启项目: -```bash -pm2 restart soul -``` - ---- - -## 六、方案 B:Shell 脚本(备选) - -如果不想用 URL 方式,也可以用 Shell 脚本: - -### 步骤 1:添加任务 - -任务类型选择:`Shell 脚本` - -### 步骤 2:填写脚本 - -```bash -#!/bin/bash -curl -X GET "https://soul.quwanzhi.com/api/cron/sync-orders?secret=YOUR_SECRET" >> /www/wwwlogs/cron_sync_orders.log 2>&1 -``` - -### 步骤 3:设置执行周期 - -- 类型:N分钟 -- 周期:5 - ---- - -## 七、方案 C:Python 脚本(高级) - -如果你想用 Python 脚本直接执行: - -### 步骤 1:确保 Python 环境 - -```bash -# SSH 登录服务器 -ssh root@你的服务器IP - -# 安装依赖 -pip3 install pymysql requests -``` - -### 步骤 2:上传脚本 - -确保脚本已上传到服务器: -``` -/www/wwwroot/soul/scripts/sync_order_status.py -``` - -### 步骤 3:宝塔添加任务 - -- 任务类型:`Shell 脚本` -- 脚本内容: - ```bash - cd /www/wwwroot/soul && python3 scripts/sync_order_status.py >> /www/wwwlogs/sync_orders.log 2>&1 - ``` -- 执行周期:每 5 分钟 - ---- - -## 八、验证是否生效 - -### 1. 创建测试订单 - -```sql --- 通过宝塔面板 → 数据库 → soul_miniprogram → SQL窗口 -INSERT INTO orders (id, order_sn, user_id, open_id, product_type, product_id, amount, status, created_at, updated_at) -VALUES ('TEST_SYNC', 'TEST_SYNC_001', 'test_user', 'test_openid', 'section', '1.2', 1.00, 'created', DATE_SUB(NOW(), INTERVAL 35 MINUTE), DATE_SUB(NOW(), INTERVAL 35 MINUTE)); -``` - -### 2. 等待定时任务执行(最多 5 分钟) - -或手动执行:宝塔面板 → 计划任务 → 点击"执行" - -### 3. 查询订单状态 - -```sql -SELECT order_sn, status, created_at, updated_at -FROM orders -WHERE order_sn = 'TEST_SYNC_001'; -``` - -**预期结果**: -- 状态应该变为 `expired`(因为超过 30 分钟) - -### 4. 清理测试数据 - -```sql -DELETE FROM orders WHERE order_sn = 'TEST_SYNC_001'; -``` - ---- - -## 九、常见问题排查 - -### Q1: 任务显示"执行失败" - -**可能原因**: -1. URL 地址错误 -2. 密钥不对(401 错误) -3. 服务器网络问题 - -**解决方案**: -1. 检查 URL 是否完整 -2. 检查 `secret` 参数是否与 `.env.production` 中一致 -3. 在浏览器中手动访问该 URL 测试 - -### Q2: 返回 401 未授权 - -**原因**:密钥不匹配 - -**解决方案**: -1. 密钥已写死,无需配置 `CRON_SECRET` -2. 确认宝塔任务 URL 中的 `secret` 参数 -3. 确保两者完全一致 -4. 重启项目:`pm2 restart soul` - -### Q3: 返回 500 错误 - -**可能原因**: -1. 数据库连接失败 -2. 代码有 bug - -**解决方案**: -1. 查看应用日志:`pm2 logs soul` -2. 检查数据库是否正常 -3. 检查环境变量是否配置 - -### Q4: 看不到执行日志 - -**解决方案**: -1. 宝塔面板 → 计划任务 → 点击任务右侧的"日志" -2. 或查看自定义日志文件: - ```bash - tail -f /www/wwwlogs/cron_sync_orders.log - ``` - ---- - -## 十、监控与优化 - -### 设置告警(可选) - -宝塔面板 → 监控 → 进程守护,添加监控项: -- 监控类型:URL 监控 -- URL:`https://soul.quwanzhi.com/api/cron/sync-orders?secret=YOUR_SECRET` -- 监控周期:5 分钟 -- 告警方式:邮件/企业微信 - -### 调整执行频率 - -根据实际情况调整: -- **订单少**:10 分钟 / 15 分钟 -- **订单多**:3 分钟 / 5 分钟 -- **高峰期**:1 分钟(不推荐,增加服务器负载) - ---- - -## 十一、配置清单(Checklist) - -完成以下步骤,确保定时任务正常运行: - -- [ ] 宝塔面板添加计划任务(访问 URL,密钥已写死:soul_cron_sync_orders_2026) -- [ ] 配置 `.env.production` 中的 `WECHAT_API_KEY`(可选,用于查询微信订单状态) -- [ ] 重启项目:`pm2 restart soul` -- [ ] 手动执行测试(宝塔面板点击"执行") -- [ ] 验证响应正常(`{"success":true}`) -- [ ] 查看日志确认任务执行 -- [ ] 创建测试订单验证(可选) -- [ ] 清理测试数据(可选) - ---- - -## 十二、最终配置示例 - -### 宝塔计划任务配置 - -``` -任务名称: 订单状态同步 -任务类型: 访问URL -执行周期: N分钟 -> 5 -URL地址: https://soul.quwanzhi.com/api/cron/sync-orders?secret=soul_cron_sync_orders_2026 -``` - -### 项目环境变量 `.env.production`(可选) - -密钥已写死,无需配置 `CRON_SECRET`。若需微信支付查询订单状态,可配置: - -```bash -# 微信支付 API 密钥(从商户平台获取,用于同步时查询订单真实状态) -WECHAT_API_KEY=YOUR_32_CHAR_API_KEY_HERE - -# 其他环境变量... -DATABASE_URL=mysql://... -``` - ---- - -## 完成! - -配置完成后,系统会: -- ✅ 每 5 分钟自动检查未支付订单 -- ✅ 查询微信支付状态并同步 -- ✅ 超时订单自动标记为 expired -- ✅ 支付成功订单自动解锁内容 - -再也不用担心支付回调丢失导致用户无法解锁内容了!🎉 diff --git a/开发文档/8、部署/提现功能完整技术文档.md b/开发文档/8、部署/提现功能完整技术文档.md deleted file mode 100644 index 457aa941..00000000 --- a/开发文档/8、部署/提现功能完整技术文档.md +++ /dev/null @@ -1,1030 +0,0 @@ -# 提现功能技术文档(微信支付API集成) - -> 来源:soul-api/提现功能完整技术文档.md。已整理至开发文档。 - -## 文档说明 - -本文档专注于**微信支付商家转账到零钱API**的集成方法,包括: -- 微信支付官方API文档 -- 签名生成算法 -- 加密解密算法 -- 完整代码实现 -- 测试验证方法 - -**适用场景**:实现用户提现功能,将资金从商户号转账到用户微信零钱。 - ---- - -## 目录 - -1. [业务场景](#业务场景) -2. [微信支付官方API文档](#微信支付官方api文档) -3. [前置准备](#前置准备) -4. [API集成](#api集成) -5. [签名算法](#签名算法) -6. [加密解密](#加密解密) -7. [代码实现](#代码实现) -8. [测试验证](#测试验证) - ---- - -## 业务场景 - -### 典型流程 - -``` -用户申请提现 - ↓ -系统审核通过 - ↓ -调用微信支付【商家转账到零钱API】 - ↓ -微信返回处理中(PROCESSING) - ↓ -微信异步处理(7-15秒) - ↓ -微信【主动回调】通知转账结果 - ↓ -系统接收回调,验签、解密 - ↓ -更新提现状态 - ↓ -用户确认收款 -``` - -### 关键步骤 - -1. **发起转账**:调用微信API发起转账 -2. **接收回调**:接收微信异步通知 -3. **验证签名**:验证回调的真实性 -4. **解密数据**:解密回调中的加密数据 -5. **查询状态**:主动查询转账状态 - ---- - -## 微信支付官方API文档 - -### 核心API - -| API名称 | 官方文档地址 | -|--------|------------| -| 🔥 **商家转账到零钱** | https://pay.weixin.qq.com/doc/v3/merchant/4012716434 | -| 📋 **查询转账单(商户单号)** | https://pay.weixin.qq.com/doc/v3/merchant/4012716456 | -| 📋 **查询转账单(微信单号)** | https://pay.weixin.qq.com/doc/v3/merchant/4012716457 | -| 🔐 **签名生成与验证** | https://pay.weixin.qq.com/doc/v3/merchant/4013053249 | -| 🔒 **敏感信息加密** | https://pay.weixin.qq.com/doc/v3/merchant/4012070130 | -| 🔓 **回调通知解密** | https://pay.weixin.qq.com/doc/v3/merchant/4012071382 | -| 📝 **转账场景报备** | https://pay.weixin.qq.com/doc/v3/merchant/4012716437 | -| ❌ **错误码查询** | https://pay.weixin.qq.com/doc/v3/merchant/4012070193 | -| 📜 **平台证书管理** | https://pay.weixin.qq.com/doc/v3/merchant/4012154180 | - -### 开发指引 - -- **API V3 开发总览**:https://pay.weixin.qq.com/doc/v3/merchant/4012065168 - - ---- - -## 前置准备 - -### 1. 获取配置信息 - -登录微信商户平台:https://pay.weixin.qq.com - -| 配置项 | 说明 | 获取路径 | -|-------|------|---------| -| **商户号(mch_id)** | 微信支付商户号 | 账户中心 → 商户信息 | -| **APIv3密钥(api_v3_key)** | 32字节密钥,用于加密解密 | 账户中心 → API安全 → 设置APIv3密钥 | -| **商户私钥(apiclient_key.pem)** | 用于请求签名 | 账户中心 → API安全 → 申请证书 | -| **证书序列号(cert_serial_no)** | 商户证书标识 | 从证书文件提取 | -| **平台证书(wechat_pay_pub_key)** | 用于验证回调签名 | 下载或通过API获取 | -| **小程序AppId** | 小程序标识 | 小程序管理后台 | - -### 2. 提取证书序列号 - -**使用OpenSSL命令**: - -```bash -openssl x509 -in apiclient_cert.pem -noout -serial -``` - -输出: -``` -serial=4A1DB62CD5C9BE0B6FC51C30621D6F99686E75C5 -``` - -**使用PHP**: - -```php - -``` - -### 3. 配置IP白名单 - -路径:微信商户平台 → 账户中心 → API安全 → IP配置 - -添加服务器公网IP地址。 - -**获取服务器IP**: - -```bash -curl ifconfig.me -``` - -### 4. 配置转账场景 - -路径:微信商户平台 → 产品中心 → 商家转账到零钱 → 前往功能 - -可选场景: -- **1000**:现金营销 -- **1005**:营销活动 - -**检查环境**: - - ---- - -## API集成 - -### 1. 商家转账到零钱API - -#### 基本信息 - -- **接口地址**:`https://api.mch.weixin.qq.com/v3/transfer/batches` -- **请求方法**:POST -- **Content-Type**:application/json - -#### 请求头 - -``` -Authorization: WECHATPAY2-SHA256-RSA2048 mchid="商户号",nonce_str="随机字符串",signature="签名",timestamp="时间戳",serial_no="证书序列号" -Content-Type: application/json -Accept: application/json -User-Agent: YourApp/1.0 -``` - -#### 请求参数 - -```json -{ - "appid": "wx6489c26045912fe1", - "out_batch_no": "BATCH202601291234567890", - "batch_name": "提现", - "batch_remark": "用户提现", - "total_amount": 5000, - "total_num": 1, - "transfer_detail_list": [ - { - "out_detail_no": "TX202601291234567890", - "transfer_amount": 5000, - "transfer_remark": "提现", - "openid": "odq3g5IOG-Z1WLpbeG_amUme8EZk" - } - ], - "transfer_scene_id": "1005", - "transfer_scene_report_infos": [ - { - "info_type": "岗位类型", - "info_content": "兼职人员" - }, - { - "info_type": "报酬说明", - "info_content": "当日兼职费" - } - ] -} -``` - -**参数说明**: - -| 字段 | 类型 | 必填 | 说明 | -|------|------|------|------| -| appid | string | 是 | 小程序AppId | -| out_batch_no | string | 是 | 商户批次单号,商户下唯一 | -| batch_name | string | 是 | 批次名称 | -| batch_remark | string | 是 | 批次备注 | -| total_amount | integer | 是 | 转账总金额,单位:**分** | -| total_num | integer | 是 | 转账总笔数 | -| transfer_detail_list | array | 是 | 转账明细列表 | -| transfer_scene_id | string | 是 | 转账场景ID:1000或1005 | -| transfer_scene_report_infos | array | 否 | 场景报备信息 | - -**transfer_detail_list说明**: - -| 字段 | 类型 | 必填 | 说明 | -|------|------|------|------| -| out_detail_no | string | 是 | 商户明细单号 | -| transfer_amount | integer | 是 | 转账金额,单位:**分** | -| transfer_remark | string | 是 | 转账备注 | -| openid | string | 是 | 收款用户OpenId | - -**场景报备信息(场景ID=1005)**: - -```json -[ - { - "info_type": "岗位类型", - "info_content": "兼职人员" - }, - { - "info_type": "报酬说明", - "info_content": "当日兼职费" - } -] -``` - -**重要**: -- `info_type` 必须是固定值 -- 金额单位是**分**:`元 * 100` - -#### 响应数据 - -**成功响应**: - -```json -{ - "out_batch_no": "BATCH202601291234567890", - "batch_id": "1030000071100999991182020050700019480001", - "create_time": "2026-01-29T12:30:00+08:00", - "batch_status": "PROCESSING" -} -``` - -**字段说明**: - -| 字段 | 说明 | -|------|------| -| out_batch_no | 商户批次单号 | -| batch_id | 微信批次单号 | -| create_time | 批次创建时间 | -| batch_status | 批次状态:PROCESSING/SUCCESS/FAIL | - -**失败响应**: - -```json -{ - "code": "PARAM_ERROR", - "message": "参数错误" -} -``` - -### 2. 查询转账单API - -#### 按商户单号查询 - -**接口地址**: - -``` -GET https://api.mch.weixin.qq.com/v3/transfer/batches/batch-id/{batch_id}/details/detail-id/{detail_id} -``` - -**路径参数**: -- `batch_id`:商户批次单号(需URL编码) -- `detail_id`:商户明细单号(需URL编码) - -**示例**: - -``` -GET /v3/transfer/batches/batch-id/BATCH202601291234567890/details/detail-id/TX202601291234567890 -``` - -**响应示例**: - -```json -{ - "mchid": "1318592501", - "out_batch_no": "BATCH202601291234567890", - "batch_id": "1030000071100999991182020050700019480001", - "out_detail_no": "TX202601291234567890", - "detail_id": "1040000071100999991182020050700019500100", - "detail_status": "SUCCESS", - "transfer_amount": 5000, - "transfer_remark": "提现", - "openid": "odq3g5IOG-Z1WLpbeG_amUme8EZk", - "initiate_time": "2026-01-29T12:30:00+08:00", - "update_time": "2026-01-29T12:30:15+08:00" -} -``` - -**状态说明**: - -| detail_status | 说明 | -|--------------|------| -| PROCESSING | 转账中 | -| SUCCESS | 转账成功 | -| FAIL | 转账失败 | - -### 3. 转账结果通知(回调) - -#### 回调触发 - -当转账状态变更时,微信支付会主动向配置的 `notify_url` 发送POST请求。 - -#### 回调请求头 - -``` -Wechatpay-Signature: 签名值 -Wechatpay-Timestamp: 1769653396 -Wechatpay-Nonce: R0PDA5lOV3IMrBjrvbCH5U4L3Lb0gg8L -Wechatpay-Serial: 642B2B33557205BA79A1CFF08EA2A2478D67BD63 -Wechatpay-Signature-Type: WECHATPAY2-SHA256-RSA2048 -Content-Type: application/json -``` - -#### 回调请求体(加密) - -```json -{ - "id": "cb29e425-ca17-59fb-8045-8e5b58917154", - "create_time": "2026-01-29T10:23:11+08:00", - "resource_type": "encrypt-resource", - "event_type": "MCHTRANSFER.BILL.FINISHED", - "summary": "商家转账单据终态通知", - "resource": { - "original_type": "mch_payment", - "algorithm": "AEAD_AES_256_GCM", - "ciphertext": "加密的数据...", - "associated_data": "mch_payment", - "nonce": "随机字符串" - } -} -``` - -#### 解密后的数据 - -```json -{ - "mch_id": "1318592501", - "out_bill_no": "TX202601291234567890", - "transfer_bill_no": "1330000114850082601290057112302122", - "transfer_amount": 5000, - "state": "SUCCESS", - "openid": "odq3g5IOG-Z1WLpbeG_amUme8EZk", - "create_time": "2026-01-29T12:30:00+08:00", - "update_time": "2026-01-29T12:30:15+08:00" -} -``` - -**state状态说明**: - -| state | 说明 | -|-------|------| -| PROCESSING | 转账中 | -| SUCCESS | 转账成功 | -| FAIL | 转账失败 | -| WAIT_USER_CONFIRM | 待用户确认 | -| TRANSFERING | 正在转账 | - -#### 回调响应 - -处理完成后,返回给微信: - -```json -{ - "code": "SUCCESS" -} -``` - ---- - -## 签名算法 - -### 1. 签名生成(请求签名) - -#### 签名串格式 - -``` -请求方法\n -请求URL路径\n -请求时间戳\n -随机字符串\n -请求报文主体\n -``` - -**示例**: - -``` -POST -/v3/transfer/batches -1234567890 -RandomString123456 -{"appid":"wx6489c26045912fe1"} -``` - -**重要**:每部分末尾都有 `\n` 换行符。 - -#### 签名步骤 - -1. 构建签名串 -2. 使用商户私钥进行SHA256withRSA签名 -3. 对签名结果进行Base64编码 - -#### PHP实现 - -```php -function buildSignature($method, $url, $timestamp, $nonce, $body, $privateKeyPath) { - // 1. 构建签名串 - $signStr = $method . "\n" - . $url . "\n" - . $timestamp . "\n" - . $nonce . "\n" - . $body . "\n"; - - // 2. 加载私钥 - $privateKeyContent = file_get_contents($privateKeyPath); - $privateKeyResource = openssl_pkey_get_private($privateKeyContent); - - // 3. 使用私钥签名 - openssl_sign($signStr, $signature, $privateKeyResource, 'sha256WithRSAEncryption'); - - // 4. Base64编码 - return base64_encode($signature); -} -``` - -#### 构建Authorization头 - -```php -function buildAuthorization($mchId, $timestamp, $nonce, $signature, $serialNo) { - return sprintf( - 'WECHATPAY2-SHA256-RSA2048 mchid="%s",nonce_str="%s",signature="%s",timestamp="%d",serial_no="%s"', - $mchId, - $nonce, - $signature, - $timestamp, - $serialNo - ); -} -``` - -### 2. 签名验证(回调验签) - -#### 验签串格式 - -``` -时间戳\n -随机字符串\n -请求报文主体\n -``` - -**示例**: - -``` -1769653396 -R0PDA5lOV3IMrBjrvbCH5U4L3Lb0gg8L -{"id":"cb29e425-ca17-59fb-8045-8e5b58917154",...} -``` - -#### PHP实现 - -```php -function verifySignature($timestamp, $nonce, $body, $signature, $publicKeyPath) { - // 1. 构建验签串 - $verifyStr = $timestamp . "\n" - . $nonce . "\n" - . $body . "\n"; - - // 2. Base64解码签名 - $signatureDecode = base64_decode($signature); - - // 3. 加载平台公钥 - $publicKeyContent = file_get_contents($publicKeyPath); - $publicKeyResource = openssl_pkey_get_public($publicKeyContent); - - // 4. 验证签名 - $result = openssl_verify( - $verifyStr, - $signatureDecode, - $publicKeyResource, - 'sha256WithRSAEncryption' - ); - - return $result === 1; // 1表示验证成功 -} -``` - -**重要**:验签使用的是**微信支付平台公钥**,不是商户私钥! - ---- - -## 加密解密 - -### 回调数据解密 - -#### 算法信息 - -- **算法**:AEAD_AES_256_GCM -- **密钥**:APIv3密钥(32字节) -- **密文格式**:实际密文 + 认证标签(16字节) - -#### 解密步骤 - -1. 提取加密数据(ciphertext、nonce、associated_data) -2. Base64解码密文 -3. 分离密文和认证标签(最后16字节) -4. 使用AES-256-GCM解密 -5. 解析JSON数据 - -#### PHP实现 - -```php -function decryptCallbackData($ciphertext, $nonce, $associatedData, $apiV3Key) { - // 1. 检查APIv3密钥长度(必须32字节) - if (strlen($apiV3Key) !== 32) { - throw new Exception('APIv3密钥长度必须为32字节'); - } - - // 2. Base64解码密文 - $ciphertextDecoded = base64_decode($ciphertext); - - // 3. 分离密文和认证标签 - $authTag = substr($ciphertextDecoded, -16); - $ctext = substr($ciphertextDecoded, 0, -16); - - // 4. 使用AES-256-GCM解密 - $decrypted = openssl_decrypt( - $ctext, // 密文 - 'aes-256-gcm', // 算法 - $apiV3Key, // 密钥 - OPENSSL_RAW_DATA, // 选项 - $nonce, // 随机串 - $authTag, // 认证标签 - $associatedData // 附加数据 - ); - - if ($decrypted === false) { - throw new Exception('解密失败'); - } - - // 5. 解析JSON - return json_decode($decrypted, true); -} -``` - -**使用示例**: - -```php -$resource = $callbackData['resource']; -$decrypted = decryptCallbackData( - $resource['ciphertext'], - $resource['nonce'], - $resource['associated_data'], - 'wx3e31b068be59ddc131b068be59ddc2' // APIv3密钥 -); -``` - ---- - -## 代码实现 - -### 完整的微信支付转账类 - -```php -mchId = $config['mch_id']; - $this->appId = $config['app_id']; - $this->apiV3Key = $config['api_v3_key']; - $this->certSerialNo = $config['cert_serial_no']; - - // 加载私钥 - $privateKeyContent = file_get_contents($config['private_key']); - $this->privateKey = openssl_pkey_get_private($privateKeyContent); - } - - /** - * 发起转账 - */ - public function createTransfer($params) - { - $url = '/v3/transfer/batches'; - $method = 'POST'; - - // 构建请求数据 - $data = [ - 'appid' => $this->appId, - 'out_batch_no' => 'BATCH' . date('YmdHis') . mt_rand(1000, 9999), - 'batch_name' => $params['batch_name'] ?? '提现', - 'batch_remark' => $params['batch_remark'] ?? '用户提现', - 'total_amount' => $params['transfer_amount'], - 'total_num' => 1, - 'transfer_detail_list' => [ - [ - 'out_detail_no' => $params['out_detail_no'], - 'transfer_amount' => $params['transfer_amount'], - 'transfer_remark' => $params['transfer_remark'], - 'openid' => $params['openid'], - ] - ], - 'transfer_scene_id' => $params['transfer_scene_id'] ?? '1005', - ]; - - // 添加场景报备信息 - if (!empty($params['transfer_scene_report_infos'])) { - $data['transfer_scene_report_infos'] = $params['transfer_scene_report_infos']; - } - - $body = json_encode($data, JSON_UNESCAPED_UNICODE); - - // 生成签名 - $timestamp = time(); - $nonce = $this->generateNonce(); - $signature = $this->buildSignature($method, $url, $timestamp, $nonce, $body); - - // 构建Authorization - $authorization = $this->buildAuthorization($timestamp, $nonce, $signature); - - // 发送请求 - return $this->request($method, $url, $body, $authorization); - } - - /** - * 查询转账单 - */ - public function queryTransfer($batchNo, $detailNo) - { - $url = "/v3/transfer/batches/batch-id/" . urlencode($batchNo) - . "/details/detail-id/" . urlencode($detailNo); - $method = 'GET'; - - $timestamp = time(); - $nonce = $this->generateNonce(); - $signature = $this->buildSignature($method, $url, $timestamp, $nonce, ''); - $authorization = $this->buildAuthorization($timestamp, $nonce, $signature); - - return $this->request($method, $url, '', $authorization); - } - - /** - * 验证回调签名 - */ - public function verifyCallback($headers, $body, $publicKey) - { - $timestamp = $headers['wechatpay-timestamp']; - $nonce = $headers['wechatpay-nonce']; - $signature = $headers['wechatpay-signature']; - - $verifyStr = $timestamp . "\n" . $nonce . "\n" . $body . "\n"; - $signatureDecode = base64_decode($signature); - - $publicKeyContent = file_get_contents($publicKey); - $publicKeyResource = openssl_pkey_get_public($publicKeyContent); - - $result = openssl_verify($verifyStr, $signatureDecode, $publicKeyResource, 'sha256WithRSAEncryption'); - - return $result === 1; - } - - /** - * 解密回调数据 - */ - public function decryptCallbackResource($resource) - { - $ciphertext = $resource['ciphertext']; - $nonce = $resource['nonce']; - $associatedData = $resource['associated_data']; - - if (strlen($this->apiV3Key) !== 32) { - throw new \Exception('APIv3密钥长度必须为32字节'); - } - - $ciphertextDecoded = base64_decode($ciphertext); - $authTag = substr($ciphertextDecoded, -16); - $ctext = substr($ciphertextDecoded, 0, -16); - - $decrypted = openssl_decrypt( - $ctext, - 'aes-256-gcm', - $this->apiV3Key, - OPENSSL_RAW_DATA, - $nonce, - $authTag, - $associatedData - ); - - if ($decrypted === false) { - throw new \Exception('解密失败'); - } - - return json_decode($decrypted, true); - } - - /** - * 生成签名 - */ - private function buildSignature($method, $url, $timestamp, $nonce, $body) - { - $signStr = $method . "\n" - . $url . "\n" - . $timestamp . "\n" - . $nonce . "\n" - . $body . "\n"; - - openssl_sign($signStr, $signature, $this->privateKey, 'sha256WithRSAEncryption'); - - return base64_encode($signature); - } - - /** - * 构建Authorization头 - */ - private function buildAuthorization($timestamp, $nonce, $signature) - { - return sprintf( - 'WECHATPAY2-SHA256-RSA2048 mchid="%s",nonce_str="%s",signature="%s",timestamp="%d",serial_no="%s"', - $this->mchId, - $nonce, - $signature, - $timestamp, - $this->certSerialNo - ); - } - - /** - * 生成随机字符串 - */ - private function generateNonce($length = 32) - { - $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; - $nonce = ''; - for ($i = 0; $i < $length; $i++) { - $nonce .= $chars[mt_rand(0, strlen($chars) - 1)]; - } - return $nonce; - } - - /** - * 发送HTTP请求 - */ - private function request($method, $url, $body, $authorization) - { - $fullUrl = 'https://api.mch.weixin.qq.com' . $url; - - $headers = [ - 'Authorization: ' . $authorization, - 'Content-Type: application/json', - 'Accept: application/json', - 'User-Agent: YourApp/1.0' - ]; - - $ch = curl_init(); - curl_setopt($ch, CURLOPT_URL, $fullUrl); - curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); - curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true); - curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); - curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); - - if ($method === 'POST') { - curl_setopt($ch, CURLOPT_POST, true); - curl_setopt($ch, CURLOPT_POSTFIELDS, $body); - } - - $response = curl_exec($ch); - $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); - curl_close($ch); - - $result = json_decode($response, true); - - if ($httpCode >= 200 && $httpCode < 300) { - return ['success' => true, 'data' => $result]; - } else { - return [ - 'success' => false, - 'error_code' => $result['code'] ?? 'UNKNOWN', - 'error_msg' => $result['message'] ?? '未知错误' - ]; - } - } -} -``` - -### 使用示例 - -#### 1. 发起转账 - -```php -// 初始化配置 -$config = [ - 'mch_id' => '1318592501', - 'app_id' => 'wx6489c26045912fe1', - 'api_v3_key' => 'wx3e31b068be59ddc131b068be59ddc2', - 'private_key' => '/path/to/apiclient_key.pem', - 'cert_serial_no' => '4A1DB62CD5C9BE0B6FC51C30621D6F99686E75C5', -]; - -$wechatPay = new WechatPayTransfer($config); - -// 发起转账 -$result = $wechatPay->createTransfer([ - 'out_detail_no' => 'TX' . date('YmdHis') . mt_rand(1000, 9999), - 'transfer_amount' => 5000, // 50元 = 5000分 - 'transfer_remark' => '提现', - 'openid' => 'odq3g5IOG-Z1WLpbeG_amUme8EZk', - 'transfer_scene_id' => '1005', - 'transfer_scene_report_infos' => [ - ['info_type' => '岗位类型', 'info_content' => '兼职人员'], - ['info_type' => '报酬说明', 'info_content' => '当日兼职费'], - ], -]); - -if ($result['success']) { - echo "转账成功: " . json_encode($result['data']); -} else { - echo "转账失败: " . $result['error_msg']; -} -``` - -#### 2. 查询转账单 - -```php -$result = $wechatPay->queryTransfer('BATCH202601291234567890', 'TX202601291234567890'); - -if ($result['success']) { - echo "状态: " . $result['data']['detail_status']; -} else { - echo "查询失败: " . $result['error_msg']; -} -``` - -#### 3. 处理回调 - -```php -// 接收回调 -$headers = [ - 'wechatpay-signature' => $_SERVER['HTTP_WECHATPAY_SIGNATURE'], - 'wechatpay-timestamp' => $_SERVER['HTTP_WECHATPAY_TIMESTAMP'], - 'wechatpay-nonce' => $_SERVER['HTTP_WECHATPAY_NONCE'], - 'wechatpay-serial' => $_SERVER['HTTP_WECHATPAY_SERIAL'], -]; - -$body = file_get_contents('php://input'); -$callbackData = json_decode($body, true); - -// 验证签名 -$verified = $wechatPay->verifyCallback($headers, $body, '/path/to/wechat_pay_pub_key.pem'); - -if ($verified) { - // 解密数据 - $decrypted = $wechatPay->decryptCallbackResource($callbackData['resource']); - - // 处理转账结果 - if ($decrypted['state'] === 'SUCCESS') { - echo "转账成功: " . $decrypted['out_bill_no']; - } - - // 返回成功 - echo json_encode(['code' => 'SUCCESS']); -} else { - echo json_encode(['code' => 'FAIL', 'message' => '签名验证失败']); -} -``` - ---- - -## 测试验证 - -### 1. 签名生成测试 - -```php -$method = 'POST'; -$url = '/v3/transfer/batches'; -$timestamp = time(); -$nonce = 'RandomString123456'; -$body = '{"appid":"wx6489c26045912fe1"}'; - -$signature = buildSignature($method, $url, $timestamp, $nonce, $body, 'apiclient_key.pem'); - -echo "签名: " . $signature . "\n"; -``` - -### 2. 小额转账测试 - -```php -// 测试金额:0.01元 = 1分 -$result = $wechatPay->createTransfer([ - 'out_detail_no' => 'TEST' . time(), - 'transfer_amount' => 1, // 1分 - 'transfer_remark' => '测试', - 'openid' => 'test_openid', - 'transfer_scene_id' => '1005', - 'transfer_scene_report_infos' => [ - ['info_type' => '岗位类型', 'info_content' => '测试'], - ['info_type' => '报酬说明', 'info_content' => '测试'], - ], -]); -``` - -### 3. 解密测试 - -```php -$resource = [ - 'ciphertext' => 'xxx', - 'nonce' => 'xxx', - 'associated_data' => 'mch_payment', -]; - -try { - $decrypted = decryptCallbackData( - $resource['ciphertext'], - $resource['nonce'], - $resource['associated_data'], - 'wx3e31b068be59ddc131b068be59ddc2' - ); - print_r($decrypted); -} catch (Exception $e) { - echo "解密失败: " . $e->getMessage(); -} -``` - -### 4. 常见问题 - -| 问题 | 原因 | 解决方法 | -|------|------|---------| -| 签名验证失败 | 证书序列号错误 | 重新提取证书序列号 | -| IP白名单错误 | 服务器IP未配置 | 添加到微信商户平台 | -| 解密失败 | APIv3密钥错误 | 检查密钥长度(32字节) | -| 场景报备错误 | info_type不正确 | 使用固定值 | -| 余额不足 | 商户号余额不足 | 充值商户号 | - ---- - -## 附录 - -### A. 错误码对照表 - -https://pay.weixin.qq.com/doc/v3/merchant/4012070193 - -| 错误码 | 说明 | 处理建议 | -|-------|------|---------| -| PARAM_ERROR | 参数错误 | 检查请求参数格式 | -| NOTENOUGH | 商户余额不足 | 充值商户号 | -| INVALID_REQUEST | 不符合业务规则 | 检查业务逻辑 | -| SYSTEM_ERROR | 系统错误 | 稍后重试 | -| FREQUENCY_LIMITED | 频率限制 | 降低请求频率 | -| APPID_MCHID_NOT_MATCH | appid和mch_id不匹配 | 检查配置 | - -### B. 转账状态说明 - -| 状态 | 说明 | 处理方式 | -|------|------|---------| -| PROCESSING | 转账中 | 等待回调或主动查询 | -| SUCCESS | 转账成功 | 完成流程 | -| FAIL | 转账失败 | 检查失败原因 | -| WAIT_USER_CONFIRM | 待用户确认 | 等待用户操作 | -| TRANSFERING | 正在转账 | 等待处理完成 | - -### C. 开发工具 - -- **Postman**:API测试工具 -- **OpenSSL**:证书和密钥管理 -- **微信支付调试工具**:https://pay.weixin.qq.com/ - ---- - -**文档版本**:v3.0(纯微信支付API版) -**更新时间**:2026-01-29 -**适用场景**:微信支付商家转账到零钱功能集成 - ---- - -## 总结 - -本文档提供了微信支付转账功能的完整集成方案: - -✅ **3个核心API** -- 发起转账:`POST /v3/transfer/batches` -- 查询转账:`GET /v3/transfer/batches/batch-id/{batch_id}/details/detail-id/{detail_id}` -- 接收回调:异步通知 - -✅ **3个核心算法** -- 签名生成:SHA256withRSA + Base64 -- 签名验证:使用平台公钥 -- 数据解密:AEAD_AES_256_GCM - -✅ **完整代码实现** -- WechatPayTransfer类(可直接使用) -- 包含发起转账、查询、验签、解密全部功能 - -根据本文档可以快速集成微信支付转账功能。 - ---- - -## 相关文档(开发文档内) - -- [分销提现流程图](分销提现流程图.md) — 提现业务流程图 -- [订阅消息](订阅消息.md) — 提现成功订阅消息 -- [商家转账](商家转账.md) — PowerWeChat 调用示例 diff --git a/开发文档/8、部署/支付接口清单.md b/开发文档/8、部署/支付接口清单.md deleted file mode 100644 index a49505a1..00000000 --- a/开发文档/8、部署/支付接口清单.md +++ /dev/null @@ -1,366 +0,0 @@ -# 支付相关接口清单 - -**日期**: 2026-02-04 -**说明**: 所有支付相关后端API接口的完整清单 - ---- - -## ✅ 已创建的接口 - -### 1. 小程序支付接口 - -#### `/api/miniprogram/pay` (POST) -**功能**: 创建支付订单并调用微信支付 - -**文件**: `app/api/miniprogram/pay/route.ts` - -**请求参数**: -```json -{ - "openId": "oXXXX...", - "productType": "section", // 'section' | 'fullbook' - "productId": "1-1", - "amount": 9.9, - "description": "章节1-1", - "userId": "user_xxx" -} -``` - -**返回**: -```json -{ - "success": true, - "data": { - "orderSn": "MP20260204123456789012", - "prepayId": "wx...", - "payParams": { - "timeStamp": "...", - "nonceStr": "...", - "package": "prepay_id=...", - "signType": "MD5", - "paySign": "..." - } - } -} -``` - -**关键逻辑**: -- ✅ 插入订单到 `orders` 表 (status='created') -- ✅ 检查是否已有该产品的已支付订单 -- ✅ 调用微信统一下单接口 -- ✅ 返回支付参数 - ---- - -#### `/api/miniprogram/pay/notify` (POST) -**功能**: 接收微信支付回调通知 - -**文件**: `app/api/miniprogram/pay/notify/route.ts` - -**请求**: 微信发送XML格式数据 - -**返回**: XML格式响应 - -**关键逻辑**: -1. ✅ 验证签名 -2. ✅ 更新订单状态为 `paid`(或补记订单) -3. ✅ 解锁用户权限 -4. ✅ 分配推荐佣金(90%) -5. ✅ **清理相同产品的其他未支付订单** - ---- - -### 2. 用户购买状态接口 - -#### `/api/user/purchase-status` (GET) -**功能**: 查询用户的购买状态 - -**文件**: `app/api/user/purchase-status/route.ts` - -**请求**: -``` -GET /api/user/purchase-status?userId=user_xxx -``` - -**返回**: -```json -{ - "success": true, - "data": { - "hasFullBook": false, - "purchasedSections": ["1-1", "1-2"], - "purchasedCount": 2, - "earnings": 0, - "pendingEarnings": 0 - } -} -``` - -**查询逻辑**: -```sql --- 1. 查询全书权限 -SELECT has_full_book FROM users WHERE id = ? - --- 2. 查询已购章节(基于 orders 表) -SELECT DISTINCT product_id -FROM orders -WHERE user_id = ? - AND status = 'paid' - AND product_type = 'section' -``` - ---- - -#### `/api/user/check-purchased` (GET) -**功能**: 检查用户是否已购买指定产品 - -**文件**: `app/api/user/check-purchased/route.ts` - -**请求**: -``` -GET /api/user/check-purchased?userId=user_xxx&type=section&productId=1-1 -``` - -**返回**: -```json -{ - "success": true, - "data": { - "isPurchased": true, - "reason": "section_order_exists" - } -} -``` - -**可能的 reason 值**: -- `has_full_book`: 用户已购买全书 -- `fullbook_order_exists`: 有全书的已支付订单 -- `section_order_exists`: 有该章节的已支付订单 -- `null`: 未购买 - -**查询逻辑**: -```sql --- 1. 检查全书权限 -SELECT has_full_book FROM users WHERE id = ? - --- 2. 检查是否有该产品的已支付订单 -SELECT COUNT(*) as count -FROM orders -WHERE user_id = ? - AND product_type = ? - AND product_id = ? - AND status = 'paid' -``` - ---- - -### 3. 通用支付接口(未使用) - -#### `/api/payment/create-order` (POST) -**功能**: 通用支付订单创建接口 - -**文件**: `app/api/payment/create-order/route.ts` - -**说明**: -- ⚠️ 小程序实际使用的是 `/api/miniprogram/pay` -- 这个接口是为 Web 端设计的通用支付接口 -- 支持多种支付方式(微信、支付宝、USDT) - ---- - -#### `/api/payment/wechat/notify` (POST) -**功能**: 通用微信支付回调 - -**文件**: `app/api/payment/wechat/notify/route.ts` - -**说明**: -- ⚠️ 小程序实际使用的是 `/api/miniprogram/pay/notify` -- 这个接口是为 Web 端设计的 - ---- - -## 📊 接口调用流程 - -``` -【小程序支付流程】 - -1. 用户点击购买 - ↓ -2. 前端调用 /api/user/purchase-status - (查询是否已购买) - ↓ -3. 如果未购买,前端调用 /api/miniprogram/pay - (创建订单 + 获取支付参数) - ↓ -4. 小程序调起微信支付 - ↓ -5. 用户完成支付 - ↓ -6. 微信回调 /api/miniprogram/pay/notify - (更新订单 + 解锁权限 + 分配佣金 + 清理无效订单) - ↓ -7. 前端支付成功后调用 /api/user/purchase-status - (刷新用户购买状态) -``` - ---- - -## 🔧 测试命令 - -### 1. 测试查询购买状态 - -```bash -curl "http://localhost:30006/api/user/purchase-status?userId=user_xxx" -``` - -**预期结果**: -```json -{ - "success": true, - "data": { - "hasFullBook": false, - "purchasedSections": [], - "purchasedCount": 0, - "earnings": 0, - "pendingEarnings": 0 - } -} -``` - ---- - -### 2. 测试检查是否已购买 - -```bash -curl "http://localhost:30006/api/user/check-purchased?userId=user_xxx&type=section&productId=1-1" -``` - -**预期结果**: -```json -{ - "success": true, - "data": { - "isPurchased": false, - "reason": null - } -} -``` - ---- - -### 3. 测试创建支付订单 - -```bash -curl -X POST http://localhost:30006/api/miniprogram/pay \ - -H "Content-Type: application/json" \ - -d '{ - "openId": "oXXXX...", - "productType": "section", - "productId": "1-1", - "amount": 9.9, - "description": "测试章节", - "userId": "user_xxx" - }' -``` - -**预期结果**: 返回支付参数 - ---- - -## ⚠️ 常见错误 - -### 1. "缺少 userId 参数" - -**原因**: 请求参数中未传递 userId - -**解决**: 确保 URL 参数或请求体中包含 userId - ---- - -### 2. "用户不存在" - -**原因**: 数据库中找不到对应的用户记录 - -**解决**: -1. 检查 userId 是否正确 -2. 确认用户已登录并创建了账号 -3. 查询数据库: `SELECT * FROM users WHERE id = 'user_xxx'` - ---- - -### 3. "订单创建失败" - -**原因**: -- 数据库连接失败 -- 缺少必要字段 -- openId 格式错误 - -**解决**: -1. 检查服务器日志 -2. 确认数据库连接正常 -3. 验证请求参数完整性 - ---- - -### 4. 接口404 - -**原因**: -- Next.js 服务器未重启 -- 文件路径错误 - -**解决**: -1. 重启 Next.js 服务器: `npm run dev` -2. 检查文件是否存在于正确路径 -3. 清除 `.next` 缓存后重启 - ---- - -## 📝 数据库表结构 - -### orders 表 - -| 字段 | 类型 | 说明 | -|-----|------|------| -| `id` | VARCHAR | 订单ID(同 order_sn) | -| `order_sn` | VARCHAR | 订单号 | -| `user_id` | VARCHAR | 用户ID | -| `open_id` | VARCHAR | 微信openId | -| `product_type` | VARCHAR | 产品类型 (section/fullbook) | -| `product_id` | VARCHAR | 产品ID | -| `amount` | DECIMAL | 金额(元) | -| `description` | TEXT | 订单描述 | -| `status` | VARCHAR | 状态 (created/paid/expired) | -| `transaction_id` | VARCHAR | 微信交易号 | -| `pay_time` | DATETIME | 支付时间 | -| `created_at` | DATETIME | 创建时间 | -| `updated_at` | DATETIME | 更新时间 | - ---- - -### users 表(购买相关字段) - -| 字段 | 类型 | 说明 | -|-----|------|------| -| `has_full_book` | BOOLEAN | 是否购买全书 | -| `purchased_sections` | JSON | 已购章节列表 | -| `earnings` | DECIMAL | 已结算收益 | -| `pending_earnings` | DECIMAL | 待结算收益 | - ---- - -## 🎉 接口状态总结 - -| 接口 | 状态 | 用途 | -|-----|------|------| -| `/api/miniprogram/pay` | ✅ 已实现 | 创建支付订单 | -| `/api/miniprogram/pay/notify` | ✅ 已实现 | 支付回调 | -| `/api/user/purchase-status` | ✅ 已实现 | 查询购买状态 | -| `/api/user/check-purchased` | ✅ 已实现 | 检查是否已购买 | -| `/api/payment/create-order` | ⚠️ 未使用 | Web 端通用接口 | -| `/api/payment/wechat/notify` | ⚠️ 未使用 | Web 端回调接口 | - ---- - -**所有小程序支付相关接口已完成!** 🎉 - -**重启 Next.js 服务器后生效**: `npm run dev` diff --git a/开发文档/8、部署/新分销逻辑-宝塔操作清单.md b/开发文档/8、部署/新分销逻辑-宝塔操作清单.md deleted file mode 100644 index d3209e22..00000000 --- a/开发文档/8、部署/新分销逻辑-宝塔操作清单.md +++ /dev/null @@ -1,299 +0,0 @@ -# 新分销逻辑 - 宝塔面板操作清单 - -## ✅ 已完成的准备工作 - -- ✅ 数据库字段已添加(last_purchase_date, purchase_count, total_commission) -- ✅ 代码已部署到服务器(/www/wwwroot/soul/dist) -- ✅ 索引已创建 - ---- - -## 🔧 宝塔面板操作步骤 - -### Step 1: 重启 Node.js 服务 - -1. 登录宝塔面板:`http://你的服务器IP:8888` -2. 左侧菜单 → **网站** → 找到 `soul.quwanzhi.com` -3. 点击 **设置** → **Node项目** 标签 -4. 找到项目 `soul` -5. 点击 **重启** 按钮 -6. 等待状态变为"运行中" - -**或者使用命令行**(如果有SSH权限): -```bash -# 使用宝塔的pm2完整路径 -/www/server/nodejs/v16.20.2/bin/pm2 restart soul - -# 查看状态 -/www/server/nodejs/v16.20.2/bin/pm2 status - -# 查看日志 -/www/server/nodejs/v16.20.2/bin/pm2 logs soul --lines 50 -``` - ---- - -### Step 2: 验证服务是否正常 - -#### 2.1 检查网站访问 -在浏览器打开:`https://soul.quwanzhi.com` - -**预期**: -- ✅ 网站正常加载 -- ✅ 无404错误 -- ✅ 可以正常登录 - -#### 2.2 检查新API是否生效 - -打开浏览器控制台,访问: -``` -https://soul.quwanzhi.com/api/db/config?key=referral_config -``` - -**预期返回**: -```json -{ - "success": true, - "config": { - "distributorShare": 90, - "minWithdrawAmount": 10, - "bindingDays": 30, - "userDiscount": 5, - "enableAutoWithdraw": false - } -} -``` - -#### 2.3 检查推广设置页面 - -访问:`https://soul.quwanzhi.com/admin/referral-settings` - -**预期**: -- ✅ 页面正常加载 -- ✅ 显示当前配置 -- ✅ 可以修改并保存 - ---- - -### Step 3: 配置自动解绑定时任务 - -1. 宝塔面板 → 左侧菜单 → **计划任务** -2. 点击 **添加计划任务** -3. 填写以下信息: - -**任务配置**: -``` -任务类型:Shell脚本 -任务名称:自动解绑过期推荐关系 -执行周期:每天 02:00(凌晨2点) -脚本内容: -cd /www/wwwroot/soul/dist && /www/server/nodejs/v16.20.2/bin/node scripts/auto-unbind-expired-simple.js >> /www/wwwroot/soul/logs/auto-unbind.log 2>&1 -``` - -4. 点击 **添加** -5. 任务创建后,点击 **执行** 按钮测试一次 - -**预期日志**(如果没有过期记录): -``` -============================================================ -自动解绑定时任务 -执行时间: 2026/2/5 14:30:00 -============================================================ -✅ 已连接到数据库: soul_miniprogram -✅ 无需解绑的记录 -============================================================ -任务完成 -============================================================ -``` - ---- - -### Step 4: 查看定时任务日志 - -```bash -# 方式1:SSH命令 -cat /www/wwwroot/soul/logs/auto-unbind.log - -# 方式2:宝塔面板 -计划任务 → 找到"自动解绑"任务 → 点击"日志" -``` - ---- - -## 🧪 功能测试(小程序端) - -### 测试1:立即切换绑定 - -1. **准备两个测试账号**: - - 账号A:作为推荐人A(获取推荐码 SOULA001) - - 账号C:作为推荐人C(获取推荐码 SOULC001) - - 账号B:作为购买者 - -2. **测试步骤**: - ``` - Step 1: A 分享文章链接给 B - Step 2: B 点击链接进入小程序(会自动绑定A) - Step 3: 查数据库验证绑定 - Step 4: C 分享文章链接给 B - Step 5: B 点击C的链接(应该立即切换) - Step 6: 再次查数据库验证 - ``` - -3. **数据库验证SQL**: - ```sql - -- 查看B当前的绑定状态 - SELECT - referee_id, - referrer_id, - status, - binding_date, - expiry_date - FROM referral_bindings - WHERE referee_id = 'B的用户ID' - ORDER BY binding_date DESC; - ``` - - **预期结果**: - - 最新一条:`referrer_id = C的ID, status = active` - - 上一条:`referrer_id = A的ID, status = cancelled` - ---- - -### 测试2:购买分佣 - -1. **B 购买一篇文章(1元)** -2. **查看分佣结果**: - ```sql - SELECT - rb.referrer_id, - rb.purchase_count, - rb.total_commission, - rb.last_purchase_date, - u.pending_earnings - FROM referral_bindings rb - JOIN users u ON rb.referrer_id = u.id - WHERE rb.referee_id = 'B的用户ID' AND rb.status = 'active'; - ``` - - **预期结果**(假设90%分成): - ``` - referrer_id: C的ID - purchase_count: 1 - total_commission: 0.90 - pending_earnings: 0.90 - ``` - -3. **B 再次购买**: - ```sql - -- 查询应显示 - purchase_count: 2 - total_commission: 1.80 - pending_earnings: 1.80 - ``` - ---- - -### 测试3:好友优惠(新功能) - -1. **后台设置好友优惠为 10%** - - 访问:`https://soul.quwanzhi.com/admin/referral-settings` - - 修改"好友优惠"为 `10` - - 保存 - -2. **B 通过推荐链接购买** - - 原价 1.00 元的文章 - - 支付时应显示 **0.90 元**(10% off) - -3. **验证佣金计算**: - - C 应获得佣金 = 0.90 × 90% = **0.81 元** - - 而不是 1.00 × 90% = 0.90 元 - ---- - -## 📊 后台监控 - -### 查看绑定切换记录 - -**SQL查询**: -```sql --- 查看最近的绑定切换 -SELECT - rb.referee_id, - rb.referrer_id, - rb.status, - rb.binding_date, - rb.purchase_count, - rb.total_commission -FROM referral_bindings rb -WHERE rb.status IN ('active', 'cancelled') -ORDER BY rb.binding_date DESC -LIMIT 20; -``` - -### 查看即将过期的绑定 - -```sql --- 7天内即将过期且无购买的绑定 -SELECT - rb.referee_id, - rb.referrer_id, - rb.binding_date, - rb.expiry_date, - DATEDIFF(rb.expiry_date, NOW()) as days_left, - rb.purchase_count -FROM referral_bindings rb -WHERE rb.status = 'active' - AND rb.expiry_date > NOW() - AND DATEDIFF(rb.expiry_date, NOW()) <= 7 - AND rb.purchase_count = 0 -ORDER BY days_left ASC; -``` - ---- - -## ⚠️ 常见问题 - -### Q1: 点击新链接后没有切换? -**检查**: -- 宝塔面板 → Node项目 → 查看日志 -- 搜索 `[Referral Bind]` 关键词 -- 确认是否有报错 - -### Q2: 购买后 purchase_count 还是 0? -**检查**: -- 查看支付回调日志:`pm2 logs soul | grep PayNotify` -- 确认字段 `purchase_count` 是否存在 -- 执行SQL验证:`SHOW COLUMNS FROM referral_bindings;` - -### Q3: 定时任务没有执行? -**检查**: -- 宝塔面板 → 计划任务 → 找到任务 → 点击"执行"测试 -- 查看日志:`cat /www/wwwroot/soul/logs/auto-unbind.log` -- 确认脚本路径正确:`ls -la /www/wwwroot/soul/dist/scripts/auto-unbind-expired-simple.js` - ---- - -## 📝 部署后清理 - -部署成功后,删除临时文件: - -```bash -# 本地清理 -rm .env.migration -``` - ---- - -## ✅ 完成检查清单 - -- [ ] 数据库字段已添加 -- [ ] 代码已部署 -- [ ] PM2服务运行正常 -- [ ] 网站可以访问 -- [ ] 推广设置页面正常 -- [ ] 定时任务已配置 -- [ ] 功能测试通过 - ---- - -**下一步:执行上述测试验证,或告诉我遇到的任何问题!** diff --git a/开发文档/8、部署/新分销逻辑-部署步骤.md b/开发文档/8、部署/新分销逻辑-部署步骤.md deleted file mode 100644 index 9f65bfc9..00000000 --- a/开发文档/8、部署/新分销逻辑-部署步骤.md +++ /dev/null @@ -1,537 +0,0 @@ -# 新分销逻辑 - 部署步骤 - -## 📋 部署前检查 - -### 确认新逻辑 -- ✅ 点击谁的链接,立即绑定谁(无条件切换) -- ✅ 购买时,佣金给当前推荐人 -- ✅ 30天内无购买 → 自动解绑 -- ✅ 方案A:购买后不重置30天 - -### 备份数据 -```bash -# 1. 备份数据库 -mysqldump -u root -p mycontent_db > backup_before_referral_$(date +%Y%m%d).sql - -# 2. 备份代码 -cd /www/wwwroot/soul -tar -czf backup_code_$(date +%Y%m%d).tar.gz app/ lib/ scripts/ -``` - ---- - -## 🚀 部署步骤 - -### Step 1: 数据库迁移 - -#### 方式1:使用 Python 脚本(推荐) - -```bash -# 1. 上传脚本到服务器 -cd /www/wwwroot/soul -# 将 scripts/migrate_binding_fields.py 上传到服务器 - -# 2. 确保环境变量正确(.env 文件) -cat .env | grep DB_ - -# 3. 执行迁移 -python3 scripts/migrate_binding_fields.py -``` - -**预期输出**: -``` -========================================================== -数据库迁移:referral_bindings 表字段升级 -========================================================== - -✅ 已连接到数据库: mycontent_db - -步骤 1: 添加新字段 ------------------------------------------------------------- -✅ 添加字段 last_purchase_date -✅ 添加字段 purchase_count -✅ 添加字段 total_commission - -步骤 2: 添加索引 ------------------------------------------------------------- -✅ 添加索引 idx_referee_status -✅ 添加索引 idx_expiry_purchase - -步骤 3: 更新 status 枚举(添加 cancelled) ------------------------------------------------------------- -✅ 更新 status 枚举类型 - -步骤 4: 验证迁移结果 ------------------------------------------------------------- -✅ 字段 last_purchase_date 已存在 -✅ 字段 purchase_count 已存在 -✅ 字段 total_commission 已存在 - -========================================================== -✅ 迁移完成! -========================================================== -``` - -#### 方式2:直接执行 SQL - -```bash -# 连接数据库 -mysql -u root -p mycontent_db - -# 执行迁移SQL -source scripts/migration-add-binding-fields.sql; - -# 验证字段 -SHOW COLUMNS FROM referral_bindings; -``` - ---- - -### Step 2: 部署代码 - -#### 本地构建 -```bash -# 在本地项目目录 -cd e:\Gongsi\Mycontent - -# 构建 -pnpm build - -# 确认构建产物 -ls -la .next/standalone -``` - -#### 上传到服务器 -```bash -# 使用 devlop.py(自动化部署) -python devlop.py - -# 或手动上传 -# 1. 上传修改的文件: -# - app/api/referral/bind/route.ts -# - app/api/miniprogram/pay/notify/route.ts -# - scripts/auto-unbind-expired-simple.js -``` - ---- - -### Step 3: 重启服务 - -```bash -# 重启 PM2 -pm2 restart soul - -# 查看日志确认启动正常 -pm2 logs soul --lines 50 - -# 确认进程状态 -pm2 status -``` - -**预期输出**: -``` -┌─────┬────────┬─────────┬──────┬─────┬──────────┐ -│ id │ name │ status │ ↺ │ cpu │ memory │ -├─────┼────────┼─────────┼──────┼─────┼──────────┤ -│ 0 │ soul │ online │ 0 │ 0% │ 100.0mb │ -└─────┴────────┴─────────┴──────┴─────┴──────────┘ -``` - ---- - -### Step 4: 配置定时任务 - -#### 宝塔面板配置 - -1. 登录宝塔面板 -2. 进入"计划任务" -3. 添加 Shell 脚本任务 - -**任务配置**: -- **任务名称**:自动解绑过期推荐关系 -- **执行周期**:每天 02:00 -- **脚本内容**: - ```bash - cd /www/wwwroot/soul && node scripts/auto-unbind-expired-simple.js >> /www/wwwroot/soul/logs/auto-unbind.log 2>&1 - ``` - -#### 手动测试定时任务 - -```bash -# 进入项目目录 -cd /www/wwwroot/soul - -# 创建日志目录 -mkdir -p logs - -# 手动执行一次 -node scripts/auto-unbind-expired-simple.js - -# 查看日志 -cat logs/auto-unbind.log -``` - -**预期输出**(如果有过期记录): -``` -============================================================ -自动解绑定时任务 -执行时间: 2026/2/5 02:00:00 -============================================================ - -✅ 已连接到数据库: mycontent_db - -步骤 1: 查询需要解绑的记录... ------------------------------------------------------------- -找到 3 条需要解绑的记录 - -步骤 2: 解绑明细 ------------------------------------------------------------- -1. 用户 user_abc123 - 推荐人: user_xyz789 - 绑定时间: 2026/1/5 - 过期时间: 2026/2/4 (已过期 1 天) - 购买次数: 0 - 累计佣金: ¥0.00 - -... - -步骤 3: 执行解绑操作... ------------------------------------------------------------- -✅ 已成功解绑 3 条记录 - -步骤 4: 更新推荐人统计... ------------------------------------------------------------- - - user_xyz789: -2 个绑定 - - user_def456: -1 个绑定 -✅ 已更新 2 个推荐人的统计数据 - -============================================================ -✅ 任务完成 - - 解绑记录数: 3 - - 受影响推荐人: 2 -============================================================ -``` - ---- - -## 🧪 功能测试 - -### 测试用例1:立即切换绑定 - -#### 准备工作 -```bash -# 创建测试用户 A、B、C -# A 推荐 B -# C 也想抢 B -``` - -#### 测试步骤 -```bash -# 1. A 推荐 B(新绑定) -curl -X POST http://localhost:3006/api/referral/bind \ - -H "Content-Type: application/json" \ - -d '{ - "userId": "test_user_b", - "referralCode": "SOULA001", - "source": "miniprogram" - }' - -# 预期返回: -# { -# "success": true, -# "message": "绑定成功", -# "action": "new", -# "expiryDate": "2026-03-07T...", -# "referrer": { "id": "test_user_a", "nickname": "用户A" } -# } - -# 2. B 点击 C 的链接(立即切换) -curl -X POST http://localhost:3006/api/referral/bind \ - -H "Content-Type: application/json" \ - -d '{ - "userId": "test_user_b", - "referralCode": "SOULC001", - "source": "miniprogram" - }' - -# 预期返回: -# { -# "success": true, -# "message": "已切换推荐人", -# "action": "switch", -# "expiryDate": "2026-03-07T...", -# "referrer": { "id": "test_user_c", "nickname": "用户C" }, -# "oldReferrerId": "test_user_a" -# } - -# 3. 验证数据库 -mysql -u root -p mycontent_db -e " - SELECT referee_id, referrer_id, status, binding_date, expiry_date - FROM referral_bindings - WHERE referee_id = 'test_user_b' - ORDER BY binding_date DESC LIMIT 2; -" - -# 预期结果: -# 记录1: referee=B, referrer=C, status=active (最新) -# 记录2: referee=B, referrer=A, status=cancelled (旧) -``` - ---- - -### 测试用例2:购买分佣(累加) - -#### 测试步骤 -```bash -# 1. B 购买第1次(1元) -# 触发支付回调 -> /api/miniprogram/pay/notify - -# 2. 查询分佣结果 -mysql -u root -p mycontent_db -e " - SELECT - rb.referrer_id, - rb.purchase_count, - rb.total_commission, - u.pending_earnings - FROM referral_bindings rb - JOIN users u ON rb.referrer_id = u.id - WHERE rb.referee_id = 'test_user_b' AND rb.status = 'active'; -" - -# 预期结果: -# referrer_id: test_user_c -# purchase_count: 1 -# total_commission: 0.90 (假设90%分成) -# pending_earnings: 0.90 - -# 3. B 购买第2次(1元) -# 再次触发支付回调 - -# 4. 再次查询 -# 预期结果: -# purchase_count: 2 -# total_commission: 1.80 -# pending_earnings: 1.80 -``` - ---- - -### 测试用例3:30天自动解绑 - -#### 模拟测试(修改过期时间) -```bash -# 1. 手动修改绑定的过期时间(测试用) -mysql -u root -p mycontent_db -e " - UPDATE referral_bindings - SET expiry_date = '2026-02-04 00:00:00' - WHERE referee_id = 'test_user_x' AND referrer_id = 'test_user_y'; -" - -# 2. 执行定时任务 -node scripts/auto-unbind-expired-simple.js - -# 3. 验证解绑 -mysql -u root -p mycontent_db -e " - SELECT referee_id, referrer_id, status, expiry_date, purchase_count - FROM referral_bindings - WHERE referee_id = 'test_user_x'; -" - -# 预期结果: -# status: expired(如果 purchase_count = 0) -# status: active(如果 purchase_count > 0) -``` - ---- - -## 🔍 监控与日志 - -### 查看绑定切换日志 -```bash -# PM2 日志 -pm2 logs soul | grep "Referral Bind" - -# 查找"立即切换"记录 -pm2 logs soul | grep "立即切换" -``` - -### 查看分佣日志 -```bash -# 查看分佣成功记录 -pm2 logs soul | grep "分佣完成" - -# 查看累加情况 -pm2 logs soul | grep "purchaseCount" -``` - -### 定时任务日志 -```bash -# 查看定时任务执行记录 -cat /www/wwwroot/soul/logs/auto-unbind.log - -# 实时监控 -tail -f /www/wwwroot/soul/logs/auto-unbind.log -``` - ---- - -## 📊 数据统计 - -### 查看当前绑定状态分布 -```sql -SELECT - status, - COUNT(*) as count, - SUM(purchase_count) as total_purchases, - SUM(total_commission) as total_commission -FROM referral_bindings -GROUP BY status; -``` - -### 查看切换频率最高的用户 -```sql -SELECT - referee_id, - COUNT(*) as binding_count, - GROUP_CONCAT(referrer_id ORDER BY binding_date DESC) as referrer_history -FROM referral_bindings -WHERE status IN ('active', 'cancelled') -GROUP BY referee_id -HAVING COUNT(*) > 1 -ORDER BY binding_count DESC -LIMIT 10; -``` - -### 查看30天内即将过期的绑定 -```sql -SELECT - referee_id, - referrer_id, - binding_date, - expiry_date, - DATEDIFF(expiry_date, NOW()) as days_left, - purchase_count -FROM referral_bindings -WHERE status = 'active' - AND expiry_date > NOW() - AND DATEDIFF(expiry_date, NOW()) <= 7 -ORDER BY days_left ASC; -``` - ---- - -## ⚠️ 回滚方案 - -### 如果需要回滚到旧逻辑 - -#### 1. 恢复数据库 -```bash -# 停止服务 -pm2 stop soul - -# 恢复备份 -mysql -u root -p mycontent_db < backup_before_referral_20260205.sql - -# 重启服务 -pm2 start soul -``` - -#### 2. 恢复代码 -```bash -# 方式1:Git回滚 -cd /www/wwwroot/soul -git reset --hard <上一个commit> - -# 方式2:恢复备份 -tar -xzf backup_code_20260205.tar.gz - -# 重启 -pm2 restart soul -``` - -#### 3. 停用定时任务 -```bash -# 宝塔面板 -> 计划任务 -> 停用或删除"自动解绑"任务 -``` - ---- - -## 📝 常见问题 - -### Q1: 定时任务没有执行? -**检查步骤**: -1. 确认宝塔计划任务状态为"启用" -2. 查看宝塔计划任务日志 -3. 手动执行测试:`node scripts/auto-unbind-expired-simple.js` -4. 检查脚本权限:`chmod +x scripts/auto-unbind-expired-simple.js` - -### Q2: 绑定切换后,旧推荐人还能收到佣金? -**原因**:可能是购买时的绑定查询逻辑有问题 - -**检查**: -```sql --- 查看 B 当前的绑定 -SELECT * FROM referral_bindings -WHERE referee_id = 'test_user_b' AND status = 'active'; - --- 应该只有1条 active 记录(最新的推荐人) -``` - -### Q3: purchase_count 字段不存在? -**原因**:数据库迁移未成功 - -**解决**: -```bash -# 重新执行迁移 -python3 scripts/migrate_binding_fields.py - -# 或手动添加 -mysql -u root -p mycontent_db -e " - ALTER TABLE referral_bindings - ADD COLUMN purchase_count INT DEFAULT 0; -" -``` - -### Q4: 如何验证新逻辑是否生效? -**验证清单**: -- [ ] 数据库有 `last_purchase_date`、`purchase_count`、`total_commission` 字段 -- [ ] 点击不同推荐链接会立即切换(无报错) -- [ ] 购买后 `purchase_count` 会累加 -- [ ] 定时任务能正常执行 - ---- - -## ✅ 部署完成检查表 - -- [ ] 数据库迁移成功 -- [ ] 代码部署完成 -- [ ] PM2 服务正常运行 -- [ ] 定时任务已配置 -- [ ] 测试用例1通过(立即切换) -- [ ] 测试用例2通过(购买累加) -- [ ] 日志正常输出 -- [ ] 备份文件已保存 - ---- - -## 📞 问题反馈 - -如有问题,请提供: -1. 错误日志(PM2日志或定时任务日志) -2. 数据库状态(相关表的查询结果) -3. 复现步骤 - -**日志收集命令**: -```bash -# PM2日志 -pm2 logs soul --lines 100 > soul_logs.txt - -# 定时任务日志 -cat /www/wwwroot/soul/logs/auto-unbind.log > auto_unbind.log - -# 数据库状态 -mysql -u root -p mycontent_db -e " - SELECT * FROM referral_bindings LIMIT 10; - SHOW COLUMNS FROM referral_bindings; -" > db_status.txt -``` diff --git a/开发文档/8、部署/新分销逻辑设计方案.md b/开发文档/8、部署/新分销逻辑设计方案.md deleted file mode 100644 index ab546e3d..00000000 --- a/开发文档/8、部署/新分销逻辑设计方案.md +++ /dev/null @@ -1,408 +0,0 @@ -# 新分销逻辑设计方案 - -## 📌 业务需求 - -### 核心规则 -1. **动态绑定**:用户B点击谁的分享链接,立即绑定谁(无条件切换) -2. **佣金归属**:B购买时,佣金给当前推荐人(最新绑定的那个人) -3. **自动解绑**:绑定30天内,如果B既没点击其他链接,也没有任何购买 → 自动解绑 - -### 场景示例 -``` -时间线: -Day 0: A推荐B → B注册 → B绑定A(30天有效期) -Day 5: B点击C的链接 → B立即切换绑定C(重新开始30天有效期) -Day 10: B购买文章 → 佣金给C(当前推荐人) -Day 35: 绑定C的30天到期,如果期间无购买 → 自动解绑 -``` - ---- - -## 🗄️ 数据库设计 - -### 1. `referral_bindings` 表字段调整 - -| 字段 | 类型 | 说明 | 新增/修改 | -|------|------|------|-----------| -| `id` | VARCHAR(64) | 主键 | - | -| `referee_id` | VARCHAR(64) | 被推荐人(B) | - | -| `referrer_id` | VARCHAR(64) | 推荐人(当前) | - | -| `referral_code` | VARCHAR(20) | 推荐码 | - | -| `status` | ENUM | active/converted/expired/cancelled | **新增 cancelled** | -| `binding_date` | TIMESTAMP | 最后一次绑定时间 | - | -| `expiry_date` | DATETIME | 过期时间(30天后) | - | -| `last_purchase_date` | DATETIME | 最后一次购买时间 | **新增** | -| `purchase_count` | INT | 购买次数 | **新增** | -| `total_commission` | DECIMAL | 累计佣金 | **新增** | - -### 2. 新增字段的 SQL - -```sql --- 添加新字段 -ALTER TABLE referral_bindings -ADD COLUMN last_purchase_date DATETIME NULL COMMENT '最后一次购买时间', -ADD COLUMN purchase_count INT DEFAULT 0 COMMENT '购买次数', -ADD COLUMN total_commission DECIMAL(10,2) DEFAULT 0.00 COMMENT '累计佣金', -ADD INDEX idx_expiry_status (expiry_date, status); - --- 修改 status 枚举(如果需要) -ALTER TABLE referral_bindings -MODIFY COLUMN status ENUM('active', 'converted', 'expired', 'cancelled') DEFAULT 'active'; -``` - ---- - -## 🔧 API 逻辑修改 - -### 1. `/api/referral/bind` - 立即切换绑定 - -**修改前逻辑(现有):** -```javascript -if (existingBinding && expiryDate > now) { - return { error: '绑定有效期内无法更换' } // ❌ 阻止切换 -} -``` - -**修改后逻辑(新):** -```javascript -// 查询B当前的绑定 -const existingBinding = await query(` - SELECT * FROM referral_bindings - WHERE referee_id = ? AND status = 'active' -`, [userId]) - -if (existingBinding.length > 0) { - const current = existingBinding[0] - - // 情况1: 同一个推荐人 → 续期(刷新30天) - if (current.referrer_id === newReferrerId) { - await query(` - UPDATE referral_bindings - SET expiry_date = DATE_ADD(NOW(), INTERVAL 30 DAY), - binding_date = NOW() - WHERE id = ? - `, [current.id]) - return { success: true, action: 'renewed' } - } - - // 情况2: 不同推荐人 → 立即切换 - else { - // 旧绑定标记为 cancelled - await query(` - UPDATE referral_bindings - SET status = 'cancelled' - WHERE id = ? - `, [current.id]) - - // 创建新绑定 - await query(` - INSERT INTO referral_bindings - (id, referee_id, referrer_id, referral_code, status, binding_date, expiry_date) - VALUES (?, ?, ?, ?, 'active', NOW(), DATE_ADD(NOW(), INTERVAL 30 DAY)) - `, [newBindingId, userId, newReferrerId, referralCode]) - - return { success: true, action: 'switched' } - } -} -``` - -**关键变化**: -- ✅ 删除"有效期内不能切换"的限制 -- ✅ 旧绑定标记为 `cancelled`(而不是 `expired`) -- ✅ 立即创建新绑定,重新计算30天 - ---- - -### 2. `/api/miniprogram/pay/notify` - 支付回调更新 - -**修改前逻辑(现有):** -```javascript -// 更新绑定为 converted -await query(` - UPDATE referral_bindings - SET status = 'converted', - conversion_date = NOW(), - commission_amount = ? - WHERE id = ? -`, [commission, bindingId]) -``` - -**修改后逻辑(新):** -```javascript -// 查询B当前的绑定(active状态) -const binding = await query(` - SELECT * FROM referral_bindings - WHERE referee_id = ? AND status = 'active' - ORDER BY binding_date DESC LIMIT 1 -`, [userId]) - -if (binding.length === 0) { - console.log('[PayNotify] 无有效绑定,跳过分佣') - return -} - -const currentBinding = binding[0] -const referrerId = currentBinding.referrer_id - -// 计算佣金 -const commission = amount * distributorShare - -// 更新绑定记录(累加购买次数和佣金) -await query(` - UPDATE referral_bindings - SET last_purchase_date = NOW(), - purchase_count = purchase_count + 1, - total_commission = total_commission + ? - WHERE id = ? -`, [commission, currentBinding.id]) - -// 更新推荐人收益 -await query(` - UPDATE users - SET pending_earnings = pending_earnings + ? - WHERE id = ? -`, [commission, referrerId]) - -console.log('[PayNotify] 分佣成功:', { - referee: userId, - referrer: referrerId, - commission, - purchaseCount: currentBinding.purchase_count + 1 -}) -``` - -**关键变化**: -- ✅ 不再标记为 `converted`(保持 `active`) -- ✅ 记录 `last_purchase_date`(用于判断是否有购买) -- ✅ 累加 `purchase_count` 和 `total_commission` -- ✅ 允许同一绑定多次购买分佣 - ---- - -### 3. 定时任务 - 自动解绑 - -**新增文件**: `scripts/auto-unbind-expired.js` - -```javascript -/** - * 自动解绑定时任务 - * 每天凌晨2点运行(建议配置 cron) - * - * 解绑条件: - * 1. 绑定超过30天(expiry_date < NOW) - * 2. 期间没有任何购买(purchase_count = 0) - */ - -const { query } = require('../lib/db') - -async function autoUnbind() { - console.log('[AutoUnbind] 开始执行自动解绑任务...') - - try { - // 查询需要解绑的记录 - const expiredBindings = await query(` - SELECT id, referee_id, referrer_id, binding_date, expiry_date - FROM referral_bindings - WHERE status = 'active' - AND expiry_date < NOW() - AND purchase_count = 0 - `) - - if (expiredBindings.length === 0) { - console.log('[AutoUnbind] 无需解绑的记录') - return - } - - console.log(`[AutoUnbind] 找到 ${expiredBindings.length} 条需要解绑的记录`) - - // 批量更新为 expired - const ids = expiredBindings.map(b => b.id) - await query(` - UPDATE referral_bindings - SET status = 'expired' - WHERE id IN (?) - `, [ids]) - - console.log(`[AutoUnbind] ✅ 已解绑 ${expiredBindings.length} 条记录`) - - // 输出明细 - expiredBindings.forEach(b => { - console.log(` - ${b.referee_id} 解除与 ${b.referrer_id} 的绑定(绑定于 ${b.binding_date})`) - }) - - } catch (error) { - console.error('[AutoUnbind] ❌ 执行失败:', error) - } -} - -// 如果直接运行此脚本 -if (require.main === module) { - autoUnbind().then(() => { - console.log('[AutoUnbind] 任务完成') - process.exit(0) - }) -} - -module.exports = { autoUnbind } -``` - -**部署方式(宝塔面板)**: -1. 进入"计划任务" → 添加 Shell 脚本 -2. 执行周期:每天 02:00 -3. 脚本内容: - ```bash - cd /www/wwwroot/soul && node scripts/auto-unbind-expired.js - ``` - ---- - -## 📊 状态流转图 - -``` -用户B的绑定状态流转: - -[无绑定] - ↓ (点击A的链接) -[active - 绑定A] ← expiry_date = NOW + 30天 - ↓ (点击C的链接) -[active - 绑定C] ← 旧绑定变 cancelled,新绑定 expiry_date = NOW + 30天 - ↓ (购买) -[active - 绑定C] ← purchase_count++, last_purchase_date = NOW - ↓ (30天后,无购买) -[expired] ← 自动解绑 - ↓ (再次点击D的链接) -[active - 绑定D] ← 重新绑定 -``` - -**status 枚举说明**: -- `active`: 当前有效绑定 -- `cancelled`: 被切换(用户点了其他人链接) -- `expired`: 30天到期且无购买 -- `converted`: **不再使用**(在新逻辑中,购买不改变status) - ---- - -## 🧪 测试用例 - -### 用例1: 立即切换绑定 - -``` -1. A推荐B → B注册 - 预期: referral_bindings 新增一条 (referee=B, referrer=A, status=active) - -2. B点击C的链接 - 预期: - - 旧记录 (referrer=A) status → cancelled - - 新记录 (referrer=C) status = active, expiry_date = NOW + 30天 - -3. B购买文章 - 预期: - - 佣金给C(不是A) - - binding.purchase_count = 1 - - binding.last_purchase_date = NOW -``` - -### 用例2: 30天无购买自动解绑 - -``` -1. A推荐B → B注册 - 预期: binding (referee=B, referrer=A, expiry_date = NOW + 30天) - -2. 等待31天(模拟) - 手动执行: node scripts/auto-unbind-expired.js - 预期: binding.status → expired - -3. B点击C的链接 - 预期: 创建新绑定 (referrer=C) -``` - -### 用例3: 多次购买累加佣金 - -``` -1. A推荐B → B绑定A -2. B购买文章1(1元) - 预期: A获得佣金 0.9元,binding.purchase_count = 1 -3. B购买文章2(1元) - 预期: A再获得佣金 0.9元,binding.purchase_count = 2,total_commission = 1.8 -``` - ---- - -## ⚠️ 注意事项 - -### 1. 边界情况处理 - -**Q1: B多次点击同一个人的链接?** -- A: 刷新 `expiry_date`(续期30天),不创建新记录 - -**Q2: B在切换推荐人后的旧订单佣金?** -- A: 历史佣金不变,只影响新订单 - -**Q3: 用户注册时没有推荐码?** -- A: 无绑定状态,等待首次点击分享链接 - -### 2. 数据一致性 - -- 使用事务保证绑定切换的原子性 -- 定时任务运行时间建议在凌晨低峰期 -- 建议添加 `idx_expiry_status` 索引优化查询 - -### 3. 性能优化 - -```sql --- 优化索引 -CREATE INDEX idx_referee_status ON referral_bindings(referee_id, status); -CREATE INDEX idx_expiry_purchase ON referral_bindings(expiry_date, purchase_count); -``` - ---- - -## 🚀 部署步骤 - -### Step 1: 数据库迁移 -```bash -# 执行 SQL 添加新字段 -mysql -u root -p mycontent_db < scripts/migration-add-binding-fields.sql -``` - -### Step 2: 修改 API 代码 -- ✅ 修改 `/api/referral/bind`(立即切换逻辑) -- ✅ 修改 `/api/miniprogram/pay/notify`(累加购买次数) - -### Step 3: 部署定时任务 -- ✅ 创建 `scripts/auto-unbind-expired.js` -- ✅ 宝塔面板配置 cron(每天02:00) - -### Step 4: 测试验证 -- ✅ 测试切换绑定流程 -- ✅ 测试购买分佣 -- ✅ 手动运行定时任务验证解绑 - ---- - -## 📈 后续优化建议 - -1. **管理后台增强** - - 查看绑定切换历史(谁被谁抢走了) - - 统计推荐人的"流失率"(被切换走的比例) - -2. **用户端提示** - - 点击新链接时提示"即将切换推荐人" - - 显示当前绑定的推荐人信息 - -3. **防刷机制** - - 限制同一用户短时间内频繁切换绑定 - - 记录IP和设备指纹防止恶意刷绑定 - -4. **数据分析** - - 统计平均绑定时长 - - 分析哪些推荐人容易被"抢走" - - 优化推荐策略 - ---- - -## 🔗 相关文档 - -- [分销与绑定流程图](./分销与绑定流程图.md) -- [推广设置功能完整修复清单](./推广设置功能-完整修复清单.md) -- [API接入说明](./API接入说明.md) diff --git a/开发文档/8、部署/章节阅读付费标准流程设计.md b/开发文档/8、部署/章节阅读付费标准流程设计.md deleted file mode 100644 index 75838da2..00000000 --- a/开发文档/8、部署/章节阅读付费标准流程设计.md +++ /dev/null @@ -1,524 +0,0 @@ -# 章节阅读与付费标准流程设计 - -> 目标:规范阅读/付费流程,规避 bug,追踪阅读状态(是否读完),为后续数据分析/推荐提供基础。 - ---- - -## 一、核心问题与设计目标 - -### 当前存在的风险点 -1. **权限判断时机不统一**:有些地方用本地缓存、有些用接口,可能不一致 -2. **登录前后状态切换**:未登录→登录、登录后免费列表变化,状态同步复杂 -3. **阅读进度无追踪**:只知道"是否打开过",不知"是否读完"、"读到哪" -4. **付费前重复校验**:支付前、登录后、initSection 多次请求 check-purchased -5. **异常降级策略不统一**:网络失败时有些保守、有些用缓存,可能误解锁 - -### 设计目标 -- **唯一权威数据源**:章节权限以服务端为准(users + orders 表) -- **标准状态机**:章节状态、用户状态明确定义,流转有迹可循 -- **阅读进度追踪**:记录滚动进度、阅读时长、是否读完(≥90% 或到底部) -- **统一异常处理**:网络失败、超时、服务端错误统一降级策略(保守+重试) -- **流程可回溯**:关键节点打日志,便于排查 bug 和数据分析 - ---- - -## 二、标准状态机设计 - -### 2.1 章节权限状态(ChapterAccessState) - -| 状态 | 说明 | 前端展示 | -|------|------|----------| -| `unknown` | 初始/加载中,尚未确定权限 | loading 骨架屏 | -| `free` | 免费章节,无需登录/购买 | 全文 + 已读标记 | -| `locked_not_login` | 付费章节 + 用户未登录 | 预览 + 登录按钮 | -| `locked_not_purchased` | 付费章节 + 已登录但未购买 | 预览 + 购买按钮 | -| `unlocked_purchased` | 付费章节 + 已购买(单章/全书) | 全文 + 已读标记 | -| `error` | 权限校验失败(网络/服务端错误) | 预览 + 重试按钮 | - -### 2.2 阅读进度状态(ReadingProgressState) - -```javascript -{ - sectionId: '1.2', - status: 'reading' | 'completed' | 'abandoned', // 阅读中 | 已完成 | 已放弃(30天未回) - progress: 75, // 滚动进度百分比 0-100 - duration: 360, // 累计阅读时长(秒) - lastPosition: 1200, // 上次滚动位置(px) - completedAt: null, // 读完时间戳(达到90%+停留3s 或滑到底部) - firstOpenAt: 1738560000,// 首次打开时间戳 - lastOpenAt: 1738563600 // 最后打开时间戳 -} -``` - -### 2.3 状态流转图 - -``` -进入阅读页 - ↓ -[unknown] 加载中 - ↓ -拉取最新免费列表 + 用户登录状态 - ↓ - ├─ 免费章节 → [free] → 全文展示 → 记录阅读进度 - ├─ 未登录 → [locked_not_login] → 预览 + 登录按钮 - │ ↓ 登录成功 - │ ├─ 章节已免费 → [free] - │ ├─ 已购买 → [unlocked_purchased] - │ └─ 未购买 → [locked_not_purchased] - ├─ 已登录未购买 → [locked_not_purchased] → 预览 + 购买按钮 - │ ↓ 支付成功 - │ └─ [unlocked_purchased] → 全文展示 - └─ 已登录已购买 → [unlocked_purchased] → 全文展示 → 记录阅读进度 - -网络/服务端错误 → [error] → 保守展示预览 + 重试按钮 -``` - ---- - -## 三、标准流程与接口调用顺序 - -### 3.1 进入章节页标准流程 - -```javascript -async onLoad(options) { - const { id, ref } = options - - // 1. 初始化状态 - this.setState({ accessState: 'unknown', loading: true }) - - // 2. 处理推荐码(异步不阻塞) - if (ref) this.handleReferralCode(ref) - - // 3. 【关键】拉取最新配置(免费列表、价格等)- 串行等待 - await this.fetchLatestConfig() - - // 4. 【关键】确定章节权限状态 - 串行等待 - const accessState = await this.determineAccessState(id) - - // 5. 加载章节内容(全文或预览) - await this.loadChapterContent(id, accessState) - - // 6. 若有权限则初始化阅读追踪 - if (['free', 'unlocked_purchased'].includes(accessState)) { - this.initReadingTracker(id) - } - - // 7. 加载上下章导航 - this.loadNavigation(id) - - this.setState({ loading: false }) -} -``` - -### 3.2 determineAccessState 权限判断标准 - -```javascript -async determineAccessState(sectionId) { - try { - // 1. 检查是否免费(以服务端最新配置为准) - if (this.isFreeChapter(sectionId)) { - return 'free' - } - - // 2. 检查是否登录 - const userId = app.globalData.userInfo?.id - if (!userId) { - return 'locked_not_login' - } - - // 3. 【权威接口】请求服务端校验是否已购买 - const res = await app.request( - `/api/user/check-purchased?userId=${userId}&type=section&productId=${sectionId}`, - { timeout: 5000 } - ) - - if (res.success && res.data?.isPurchased) { - // 同步更新本地缓存(仅作展示用,不作权限依据) - this.syncLocalPurchaseCache(sectionId, res.data) - return 'unlocked_purchased' - } - - return 'locked_not_purchased' - - } catch (error) { - console.error('[Access] 权限判断失败:', error) - // 网络/服务端错误 → 保守策略:视为无权限 + 可重试 - return 'error' - } -} -``` - -### 3.3 登录后重新校验标准流程 - -```javascript -async onLoginSuccess() { - wx.showLoading({ title: '更新状态中...' }) - - try { - // 1. 刷新用户购买列表(全局状态) - await this.refreshUserPurchaseStatus() - - // 2. 重新拉取免费列表(可能刚改免费) - await this.fetchLatestConfig() - - // 3. 重新判断当前章节权限 - const newAccessState = await this.determineAccessState(this.data.sectionId) - - // 4. 更新状态并刷新内容 - this.setState({ - accessState: newAccessState, - isLoggedIn: true - }) - - // 5. 若已解锁则初始化阅读追踪 - if (['free', 'unlocked_purchased'].includes(newAccessState)) { - await this.loadChapterContent(this.data.sectionId, newAccessState) - this.initReadingTracker(this.data.sectionId) - } - - wx.hideLoading() - wx.showToast({ title: '登录成功', icon: 'success' }) - - } catch (e) { - wx.hideLoading() - wx.showToast({ title: '状态更新失败,请重试', icon: 'none' }) - } -} -``` - -### 3.4 支付成功后刷新标准流程 - -```javascript -async onPaymentSuccess() { - wx.showLoading({ title: '确认购买中...' }) - - try { - // 1. 等待服务端处理支付回调(1-2秒) - await this.sleep(2000) - - // 2. 刷新用户购买状态(从 orders 表拉取最新) - await this.refreshUserPurchaseStatus() - - // 3. 重新判断当前章节权限(应为 unlocked_purchased) - const newAccessState = await this.determineAccessState(this.data.sectionId) - - if (newAccessState !== 'unlocked_purchased') { - // 支付成功但权限未生效 → 可能回调延迟,再重试一次 - await this.sleep(1000) - newAccessState = await this.determineAccessState(this.data.sectionId) - } - - // 4. 更新状态并重新加载全文 - this.setState({ accessState: newAccessState }) - await this.loadChapterContent(this.data.sectionId, newAccessState) - - // 5. 初始化阅读追踪 - this.initReadingTracker(this.data.sectionId) - - wx.hideLoading() - wx.showToast({ title: '购买成功', icon: 'success' }) - - } catch (e) { - wx.hideLoading() - wx.showModal({ - title: '提示', - content: '购买成功,但内容加载失败,请返回重新进入', - showCancel: false - }) - } -} -``` - ---- - -## 四、阅读进度追踪方案 - -### 4.1 数据结构(本地 + 服务端) - -**本地存储**(实时更新,用于断点续读): -```javascript -wx.setStorageSync('reading_progress', { - '1.2': { progress: 75, duration: 360, lastPosition: 1200, lastOpenAt: xxx }, - '2.1': { progress: 30, duration: 120, lastPosition: 500, lastOpenAt: xxx } -}) -``` - -**服务端表**(定期上报,用于数据分析): -```sql -CREATE TABLE reading_progress ( - id INT PRIMARY KEY AUTO_INCREMENT, - user_id VARCHAR(50) NOT NULL, - section_id VARCHAR(20) NOT NULL, - progress INT DEFAULT 0, -- 阅读进度 0-100 - duration INT DEFAULT 0, -- 累计时长(秒) - status ENUM('reading', 'completed', 'abandoned') DEFAULT 'reading', - completed_at DATETIME NULL, -- 读完时间 - first_open_at DATETIME NOT NULL, - last_open_at DATETIME NOT NULL, - created_at DATETIME DEFAULT CURRENT_TIMESTAMP, - updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - UNIQUE KEY idx_user_section (user_id, section_id), - INDEX idx_user_status (user_id, status), - INDEX idx_completed (completed_at) -); -``` - -### 4.2 追踪逻辑 - -```javascript -// 初始化阅读追踪器 -initReadingTracker(sectionId) { - const tracker = { - sectionId, - startTime: Date.now(), - lastScrollTime: Date.now(), - totalDuration: 0, - maxProgress: 0, - isCompleted: false, - scrollTimer: null - } - - this.readingTracker = tracker - - // 恢复上次阅读位置 - this.restoreLastPosition(sectionId) - - // 监听滚动事件(节流) - this.watchScrollProgress() - - // 定期上报进度(每30秒) - this.startProgressReport() -} - -// 监听滚动进度(节流 500ms) -watchScrollProgress() { - let scrollTimer = null - - wx.onPageScroll((e) => { - if (scrollTimer) clearTimeout(scrollTimer) - - scrollTimer = setTimeout(() => { - const { scrollTop, scrollHeight, clientHeight } = this.getScrollInfo() - const progress = Math.min(100, Math.round((scrollTop / (scrollHeight - clientHeight)) * 100)) - - // 更新最大进度 - if (progress > this.readingTracker.maxProgress) { - this.readingTracker.maxProgress = progress - this.saveProgressLocal(progress, scrollTop) - } - - // 判断是否读完(≥90% 且停留3秒) - if (progress >= 90 && !this.readingTracker.isCompleted) { - this.checkCompletion(progress) - } - }, 500) - }) -} - -// 判断是否读完 -async checkCompletion(progress) { - // 停留3秒后标记为已读完 - await this.sleep(3000) - - if (progress >= 90 && !this.readingTracker.isCompleted) { - this.readingTracker.isCompleted = true - this.readingTracker.completedAt = Date.now() - - // 立即上报完成状态 - await this.reportCompletion() - - // 触发埋点/数据分析 - this.trackEvent('chapter_completed', { - sectionId: this.data.sectionId, - duration: this.readingTracker.totalDuration - }) - } -} - -// 定期上报进度(每30秒,页面隐藏/卸载时也上报) -startProgressReport() { - this.reportInterval = setInterval(() => { - this.reportProgressToServer() - }, 30000) - - // 页面隐藏/卸载时立即上报 - wx.onHide(() => this.reportProgressToServer()) - wx.onUnload(() => this.reportProgressToServer()) -} - -// 上报进度到服务端 -async reportProgressToServer() { - if (!this.readingTracker) return - - const now = Date.now() - const duration = Math.round((now - this.readingTracker.lastScrollTime) / 1000) - this.readingTracker.totalDuration += duration - this.readingTracker.lastScrollTime = now - - try { - await app.request('/api/user/reading-progress', { - method: 'POST', - data: { - userId: app.globalData.userInfo?.id, - sectionId: this.readingTracker.sectionId, - progress: this.readingTracker.maxProgress, - duration: this.readingTracker.totalDuration, - status: this.readingTracker.isCompleted ? 'completed' : 'reading' - } - }) - } catch (e) { - console.warn('[Progress] 上报失败,下次重试') - } -} -``` - -### 4.3 断点续读 - -```javascript -// 恢复上次阅读位置 -restoreLastPosition(sectionId) { - const progressData = wx.getStorageSync('reading_progress') || {} - const lastProgress = progressData[sectionId] - - if (lastProgress?.lastPosition) { - wx.pageScrollTo({ - scrollTop: lastProgress.lastPosition, - duration: 300 - }) - - wx.showToast({ - title: `已恢复到 ${lastProgress.progress}%`, - icon: 'none', - duration: 2000 - }) - } -} -``` - ---- - -## 五、异常处理与降级策略 - -### 5.1 统一异常处理原则 - -| 异常类型 | 降级策略 | 用户提示 | -|---------|---------|---------| -| 网络超时(>5s) | 保守策略:视为无权限,展示预览 + 重试按钮 | "网络连接超时,请重试" | -| 服务端 500 | 同上 | "服务暂时不可用,请稍后重试" | -| 权限接口返回 error | 同上 | "无法确认权限,请重试" | -| 内容接口失败 | 尝试本地缓存 → 失败则重试3次 → 仍失败则提示 | "内容加载失败,已尝试 {n} 次" | -| 支付成功但权限未生效 | 延迟1秒重试一次 → 仍失败则提示联系客服 | "购买成功,正在确认..." | - -### 5.2 重试机制 - -```javascript -async requestWithRetry(url, options, maxRetries = 3) { - let lastError = null - - for (let i = 0; i < maxRetries; i++) { - try { - const res = await app.request(url, { ...options, timeout: 5000 }) - return res - } catch (e) { - lastError = e - console.warn(`[Retry] 第 ${i+1} 次请求失败:`, url, e.message) - - if (i < maxRetries - 1) { - await this.sleep(1000 * (i + 1)) // 指数退避 - } - } - } - - throw lastError -} -``` - ---- - -## 六、日志与埋点规范 - -### 6.1 关键节点日志 - -```javascript -// 进入章节 -console.log('[Chapter] 进入章节', { sectionId, accessState, userId, timestamp }) - -// 权限判断 -console.log('[Access] 权限判断', { sectionId, isFree, isLoggedIn, isPurchased, result: accessState }) - -// 登录成功 -console.log('[Login] 登录成功', { userId, beforeState, afterState, timestamp }) - -// 支付成功 -console.log('[Payment] 支付成功', { userId, productType, productId, amount, orderNo, timestamp }) - -// 阅读完成 -console.log('[Reading] 阅读完成', { sectionId, duration, progress, timestamp }) - -// 异常 -console.error('[Error] 异常', { type, message, stack, context }) -``` - -### 6.2 数据埋点(可选,接入统计平台) - -```javascript -// 章节打开 -trackEvent('chapter_open', { sectionId, accessState, source }) - -// 章节解锁(登录/支付) -trackEvent('chapter_unlocked', { sectionId, unlockMethod: 'login' | 'purchase' }) - -// 阅读完成 -trackEvent('chapter_completed', { sectionId, duration, fromProgress }) - -// 购买转化 -trackEvent('purchase_conversion', { productType, productId, amount, referralCode }) -``` - ---- - -## 七、实施步骤 - -### 阶段一:重构权限判断(1-2天) -1. 新增 `accessState` 字段和状态机逻辑 -2. 统一 `determineAccessState` 方法 -3. 修改 `onLoad`、`onLoginSuccess`、`onPaymentSuccess` 按标准流程 -4. 统一异常处理和重试机制 - -### 阶段二:阅读进度追踪(2-3天) -1. 创建 `reading_progress` 表(迁移脚本) -2. 实现 `initReadingTracker`、`watchScrollProgress`、`checkCompletion` -3. 实现本地存储 + 定期上报 -4. 实现断点续读 - -### 阶段三:测试与优化(1-2天) -1. 单元测试:各状态流转、异常降级 -2. 集成测试:登录、支付、阅读完整流程 -3. 边界测试:网络超时、服务端错误、并发操作 -4. 性能优化:节流、防抖、缓存策略 - -### 阶段四:数据分析接入(可选) -1. 对接统计平台(如微信小程序数据助手、神策、诸葛等) -2. 配置关键指标看板:购买转化率、阅读完成率、平均阅读时长 -3. A/B 测试:不同付费墙文案、价格策略 - ---- - -## 八、预期收益 - -- **bug 减少 80%+**:权限判断统一、异常处理标准化 -- **用户体验提升**:断点续读、进度可视化、明确的状态反馈 -- **数据驱动决策**:阅读完成率、购买转化漏斗分析、章节热度排行 -- **可扩展性**:状态机设计便于未来增加"试读 N 分钟"、"好友助力解锁"等玩法 - ---- - -## 附录:核心代码示例 - -完整实现代码见配套文件: -- `miniprogram/utils/chapterAccessManager.js` - 权限管理器 -- `miniprogram/utils/readingTracker.js` - 阅读追踪器 -- `app/api/user/reading-progress/route.ts` - 进度上报接口 -- `scripts/create_reading_progress_table.sql` - 数据表迁移 - -以上为完整设计方案,建议先实施阶段一、二,验证效果后再进行阶段三、四。 diff --git a/开发文档/8、部署/自动化与Webhook.md b/开发文档/8、部署/自动化与Webhook.md deleted file mode 100644 index 17a4f4ab..00000000 --- a/开发文档/8、部署/自动化与Webhook.md +++ /dev/null @@ -1,3 +0,0 @@ -# 自动化与 Webhook(合并自 Next.js自动化、WEBHOOK、GitHub Webhook 与宝塔、自动同步) - -Next.js 自动化部署流程、Vercel/宝塔 Webhook 配置、自动同步与分支策略。详见原各文档。 diff --git a/开发文档/8、部署/订阅消息.md b/开发文档/8、部署/订阅消息.md deleted file mode 100644 index 933d56f2..00000000 --- a/开发文档/8、部署/订阅消息.md +++ /dev/null @@ -1,43 +0,0 @@ -# 提现订阅消息(PowerWeChat) - -> 来源:soul-api/订阅消息.md。提现成功后向用户发送订阅消息。已整理至开发文档。 - ---- - -## 数据结构示例 - -```go -data := &power.HashMap{ - "phrase4": power.StringMap{ - "value": "提现成功", // 提现结果:提现成功、提现失败 - }, - "amount5": power.StringMap{ - "value": "¥8.6", // 提现金额 - }, - "thing8": power.StringMap{ - "value": "微信打款成功,请点击查收", // 备注,打款失败则提示请联系官方客服 - }, -} -MiniProgramApp.SubscribeMessage.Send(ctx, &request.RequestSubscribeMessageSend{ - ToUser: "OPENID", // 根据订单号联表查询,提现表 user_id 即 openid - TemplateID: "u3MbZGPRkrZIk-I7QdpwzFxnO_CeQPaCWF2FkiIablE", - Page: "/pages/my/my", - // developer=开发版;trial=体验版;formal=正式版 - // 开发环境 souldev.quwanzhi.com,正式环境 soulapi.quwanzhi.com - MiniProgramState: "formal", - Lang: "zh_CN", - Data: data, -}) -``` - -## 回调示例(转账结果) - -```json -{ - "create_time": "2026-02-10T18:02:54+08:00", - "out_bill_no": "WD1770691555206100", - "package_info": "ABBQO+oYAAABAAAAAAAk+...", - "state": "WAIT_USER_CONFIRM", - "transfer_bill_no": "1330000114850082602100071440076263" -} -``` diff --git a/开发文档/8、部署/运行与部署.md b/开发文档/8、部署/运行与部署.md deleted file mode 100644 index 77e5ba7c..00000000 --- a/开发文档/8、部署/运行与部署.md +++ /dev/null @@ -1,15 +0,0 @@ -# 运行与部署(合并自 运行指南、部署总览与线上部署) - -## Soul 主站运行 - -`pnpm install` → `pnpm dev`(端口 3000)或 `pnpm build` + `PORT=3006 node .next/standalone/server.js` - -**环境变量**:MYSQL_*、SKIP_DB、ADMIN_* - -## 线上部署 - -**Web**:宝塔 42.194.232.22,路径 /www/wwwroot/soul,PM2 soul,端口 3006 - -**小程序**:AppID wxb8bbb2b10dec74aa,private.key + 上传脚本 - -**命令**:`python scripts/deploy_baota.py` 或 `开发文档/服务器管理/scripts/一键部署.py` diff --git a/开发文档/8、部署/邀请码分销规则说明.md b/开发文档/8、部署/邀请码分销规则说明.md deleted file mode 100644 index df788156..00000000 --- a/开发文档/8、部署/邀请码分销规则说明.md +++ /dev/null @@ -1,147 +0,0 @@ -# 邀请码 / 分销规则说明 - -**配置来源**: 数据库 `system_config.config_key = 'referral_config'` -**分佣逻辑**: `app/api/miniprogram/pay/notify/route.ts` 中 `processReferralCommission` - -> 📌 **流程图**:绑定与分销的完整流程(谁推荐谁、下单怎么写推荐人、分佣怎么算)见 → [分销与绑定流程图](./分销与绑定流程图.md) - ---- - -## 一、分销规则(当前实现) - -### 1. 分成比例 -- **推广者分成**: 默认 **90%**(`referral_config.distributorShare = 90`) -- **平台**: 10% -- 可在管理后台或 `system_config.referral_config` 中修改 - -### 2. 绑定规则 -- **绑定有效期**: 默认 **30 天**(`referral_config.bindingDays = 30`) -- **一级分销**: 只算直接推荐人(`referral_bindings` 中 `referee_id` = 买家,`referrer_id` = 推广者) -- **有效绑定**: `referral_bindings.status = 'active'` 且 `expiry_date > NOW()` - -### 3. 分佣触发 -- 用户**支付成功**后,回调 `POST /api/miniprogram/pay/notify` -- 根据**买家 user_id** 查 `referral_bindings`(referee_id = 买家),取有效绑定的 `referrer_id` -- 佣金 = 订单实付金额 × 90%,计入推广者 `users.pending_earnings` -- 该绑定记录更新为 `status = 'converted'`,并记录 `commission_amount`、`order_id` - -### 4. 其他配置(referral_config) -- **minWithdrawAmount**: 最小提现金额(默认 10 元) -- **userDiscount**: 用户优惠比例(默认 5) - ---- - -## 二、订单与邀请码 - -### 问题 -- 下单接口 `POST /api/miniprogram/pay` 之前**未传邀请码/分销码**,订单表 **orders** 也没有推荐人字段,无法在订单上直接看到“是谁带来的”。 - -### 处理方式(已实现) -1. **orders 表增加字段** - - `referrer_id`(VARCHAR(50) NULL):下单时若存在有效绑定或邀请码,则写入推荐人 user_id。 - - `referral_code`(VARCHAR(20) NULL):**下单时使用的邀请码**,直接记录在订单上便于对账与后台展示。 - - **迁移脚本**:`python scripts/add_orders_referrer_id.py`、`python scripts/add_orders_referral_code.py`(表已存在时各执行一次)。 - -2. **下单时写推荐人与邀请码** - - 创建订单时先按**买家 user_id** 查 `referral_bindings`(referee_id = 买家、有效且未过期),取 `referrer_id`。 - - 若未查到且请求体带了 `referralCode`,则用 `users.referral_code = referralCode` 解析出推荐人 id,写入 `orders.referrer_id`。 - - **邀请码**:优先存请求体里的 `referralCode`(用户章节支付时传的);若未传但已有 `referrer_id`,则存该推荐人当前的 `users.referral_code`,保证订单上有一份当时使用的邀请码记录。 - -3. **小程序传参** - - 支付请求会传 `referralCode`:来自 `wx.getStorageSync('referral_code')`(落地页 ref 带入的“谁邀请了我”的邀请码),供后端解析推荐人并写入 `orders.referrer_id` 与 `orders.referral_code`。 - - **同步约定**:`app.js` 在检测到 `ref` / `referralCode` 时除写入 `pendingReferralCode` 外,会同步写入 `referral_code`;**章节支付**(`pages/read/read.js`)与**找伙伴支付**(`pages/match/match.js`)创建订单时都会带上 `referralCode`,保证两类订单都会记录邀请码。 - ---- - -## 三、订单表与分销逻辑(已实现) - -- **下单时**(`POST /api/miniprogram/pay`): - 1. 根据买家 user_id 查 `referral_bindings`(有效且未过期)取 `referrer_id`; - 2. 若无绑定且请求带 `referralCode`,用 `users.referral_code` 解析出推荐人 id; - 3. 插入 `orders` 时写入 `referrer_id`(需表已执行 `scripts/add_orders_referrer_id.py`)。 -- **支付成功回调**(`POST /api/miniprogram/pay/notify`): - - 仍按 `referral_bindings` 查推荐人并发放佣金(90%),不依赖订单上的 referrer_id; - - 订单上的 `referrer_id` 用于统计、对账和展示。 - -## 四、相关表与字段 - -| 表 / 配置 | 说明 | -|-----------|------| -| **users** | referral_code(自己的邀请码), referred_by(可选), pending_earnings, earnings | -| **referral_bindings** | referrer_id, referee_id, status(active/converted/expired), expiry_date, commission_amount, order_id | -| **orders** | referrer_id(推荐人用户ID), referral_code(下单时使用的邀请码,便于对账与展示) | -| **system_config** | config_key = 'referral_config',含 distributorShare、bindingDays 等 | - ---- - -## 五、流程简述 - -1. 用户 A 分享邀请码 / 带 ref 的链接,用户 B 通过该链接进入并完成绑定(写入 `referral_bindings`,referee_id=B,referrer_id=A)。 -2. 用户 B 下单支付:调用 `POST /api/miniprogram/pay`,后端根据 B 的 user_id 查有效绑定得到 A,写入 `orders.referrer_id = A`。 -3. 支付成功回调:`/api/miniprogram/pay/notify` 再根据 B 查绑定,给 A 结算 90% 佣金,更新 `referral_bindings` 与 `users.pending_earnings`。 - -这样订单上就有邀请/分销关系(referrer_id),且分佣规则不变。 - ---- - -## 六、推荐人 vs 邀请码:会不会乱? - -**结论:不会乱。** 全局只认「推荐人 = 用户ID」,邀请码只用于解析出这个 ID。 - -### 概念区分 - -| 概念 | 含义 | 存储位置 | 用途 | -|------|------|----------|------| -| **邀请码** | 一串码(如 SOULABC123) | `users.referral_code`(每个用户一条) | 链接里带 `ref=邀请码`,用来**识别**是谁推荐的 | -| **推荐人** | 拿佣金的那个人 | 用**用户ID** `referrer_id` 存 | 订单归属、分佣、统计都只认 ID,不认字符串 | - -- 邀请码 → 通过 `users WHERE referral_code = ?` 可唯一解析出 → **推荐人用户ID**。 -- 订单表、绑定表里存的都是 **referrer_id**,从不存邀请码字符串;展示时再用 referrer_id 去查昵称/邀请码即可。 - -### 绑定与订单归属的优先级(唯一权威) - -1. **下单时**(`/api/miniprogram/pay`) - - **先**查 `referral_bindings`:当前买家是否有有效绑定 → 得到 `referrer_id`。 - - **仅当没有绑定**时,才用请求体里的 `referralCode` 去 `users` 表解析出 `referrer_id`。 - - 最终写入订单的**只有** `orders.referrer_id`(用户ID),不会写邀请码。 - -2. **分佣时**(支付成功回调) - - 只查 `referral_bindings`(买家 → 有效绑定的推荐人),**不看**订单上的 referrer_id,也不看邀请码。 - - 佣金发给绑定表里的 `referrer_id`。 - -因此: -- **绑定表** = 权威的「谁推荐了谁」; -- **订单上的 referrer_id** = 下单时根据「绑定表 + 兜底邀请码」算出来的结果,只用于展示/对账; -- **邀请码** = 仅作为入口参数,解析成 referrer_id 后就不再参与逻辑,不会和推荐人 ID 混用。 - -### 前端 storage 说明(避免混用) - -- 落地页/分享带 `ref`:写入 `referral_code`(下划线),支付时读 `referral_code` 传给后端作兜底。 -- App 层待绑定:`pendingReferralCode`;绑定成功后可选写 `boundReferralCode`。 -- 绑定接口、支付接口请求体里统一用 **referralCode**(驼峰)。 - -只要后端始终用「绑定表优先、邀请码兜底」且只落库 referrer_id,全局绑定逻辑就不会乱。 - ---- - -## 七、文章/章节分销 - -**结论:和全局分销是同一套逻辑,没有单独的「按文章维度」分销。** - -### 当前实现 - -- **分享首页**:链接形如 `https://xxx/?ref=邀请码`,点击后 ref 写入 storage,绑定与订单归属按上文规则。 -- **分享某篇文章/章节**: - - 小程序:`/pages/read/read?id=章节ID&ref=邀请码`(阅读页 `onShareAppMessage` / `onShareTimeline` 会带上当前用户邀请码)。 - - Web:`/view/read/章节ID?ref=邀请码`。 -- 访客从**任意**带 ref 的链接进入(首页或某篇文章),都会: - 1. 用 ref 解析出推荐人并完成绑定(`referral_bindings`); - 2. 之后该用户下单,订单归属与分佣都按**同一套**「绑定表优先、邀请码兜底」规则,与**从哪篇文章点进来**无关。 - -也就是说:**文章/章节只决定落地页内容,不改变绑定与分佣规则**。谁发的链接(ref=谁),谁就是推荐人;买的是哪一章、哪本书,都按 90% 给该推荐人,没有「这篇文章单独分成」或「按章节统计推广效果」的单独逻辑。 - -### 未实现的部分(若以后要做) - -- **按文章/章节维度的统计**:例如「通过《1.2 某某章》链接带来的访问/绑定/订单数」—— 当前未记录分享时的章节 id,无法区分。 -- **按文章的分成策略**:例如某章单独 95%、其他 90% —— 当前未实现,所有订单统一 90%。 -- 若需要「文章分销」统计或差异化分成,需要:在访问/绑定/订单上记录「来源章节」(如 `landing_section_id`),并在分佣或报表里按章节维度汇总。 diff --git a/开发文档/8、部署/部署总览.md b/开发文档/8、部署/部署总览.md deleted file mode 100644 index 0add6dce..00000000 --- a/开发文档/8、部署/部署总览.md +++ /dev/null @@ -1,52 +0,0 @@ -# 部署总览 - -> **当前生产架构**:soul-api(Go + Gin)+ soul-admin(React)+ miniprogram。next-project 仅预览。 - ---- - -## 一、核心部署 - -| 文档 | 说明 | -|------|------| -| [新分销逻辑-部署步骤](新分销逻辑-部署步骤.md) | 新分销上线:备份、迁移、部署、验证 | -| [新分销逻辑-宝塔操作清单](新分销逻辑-宝塔操作清单.md) | 宝塔侧具体操作 | -| [运行与部署](运行与部署.md) | 运行与部署说明 | - ---- - -## 二、环境与配置 - -| 文档 | 说明 | -|------|------| -| [VIP功能-数据库迁移说明](VIP功能-数据库迁移说明.md) | VIP 排序、角色、vip_roles 表迁移(2026-02-26) | -| [MCP-MySQL配置说明](MCP-MySQL配置说明.md) | MCP 连接 MySQL | -| [Soul-MySQL-MCP配置说明](Soul-MySQL-MCP配置说明.md) | 本项目 MySQL MCP 配置 | -| [API接入说明](API接入说明.md) | 外部/小程序接入 API | -| [宝塔面板配置订单同步定时任务](宝塔面板配置订单同步定时任务.md) | 订单同步定时任务 | - ---- - -## 三、设计与流程(必读) - -| 文档 | 说明 | -|------|------| -| [新分销逻辑设计方案](新分销逻辑设计方案.md) | 动态绑定、佣金归属、30天自动解绑 | -| [邀请码分销规则说明](邀请码分销规则说明.md) | 邀请码与分成规则 | -| [分销与绑定流程图](分销与绑定流程图.md) | 分销与绑定流程 | -| [章节阅读付费标准流程设计](章节阅读付费标准流程设计.md) | 阅读页付费流程 | -| [阅读页标准流程改造说明](阅读页标准流程改造说明.md) | 阅读页改造要点 | -| [支付接口清单](支付接口清单.md) | 支付相关接口列表 | -| [提现功能完整技术文档](提现功能完整技术文档.md) | 微信支付商家转账到零钱 API 集成 | -| [分销提现流程图](分销提现流程图.md) | 提现业务流程图(申请→审核→打款→回调) | -| [订阅消息](订阅消息.md) | 提现成功订阅消息(PowerWeChat 示例) | -| [商家转账](商家转账.md) | PowerWeChat RequestTransferBills 调用示例 | - ---- - -## 四、检查与诊断 - -| 文档 | 说明 | -|------|------| -| [代码逻辑和数据库最终检查清单](代码逻辑和数据库最终检查清单.md) | 上线前检查项 | -| [佣金计算逻辑检查](佣金计算逻辑检查.md) | 佣金逻辑校验 | -| [佣金问题-快速诊断和修复](佣金问题-快速诊断和修复.md) | 佣金问题排查 | diff --git a/开发文档/8、部署/阅读页标准流程改造说明.md b/开发文档/8、部署/阅读页标准流程改造说明.md deleted file mode 100644 index 992ad6c4..00000000 --- a/开发文档/8、部署/阅读页标准流程改造说明.md +++ /dev/null @@ -1,395 +0,0 @@ -# 阅读页标准流程改造说明 - -> 完成时间:2026-02-04 -> 改造范围:`miniprogram/pages/read/read.js` 和 `read.wxml` - ---- - -## 一、改造概述 - -按照《章节阅读付费标准流程设计》,将阅读页重构为标准流程版本,引入状态机和工具类,规避现有 bug,支持阅读进度追踪。 - -### 核心改动 -1. **引入工具类**:`chapterAccessManager`(权限管理)+ `readingTracker`(阅读追踪) -2. **状态机管理**:用 `accessState` 枚举替代 `canAccess` 布尔值 -3. **标准流程**:统一 `onLoad`、`onLoginSuccess`、`onPaymentSuccess` 的处理逻辑 -4. **阅读追踪**:自动记录进度、时长、是否读完,支持断点续读 -5. **异常处理**:统一保守策略,网络异常时展示重试按钮,不误解锁 - ---- - -## 二、文件变更清单 - -### 已修改文件 -- ✅ `miniprogram/pages/read/read.js` - 核心逻辑重构(已备份为 `read.js.backup`) -- ✅ `miniprogram/pages/read/read.wxml` - UI 模板适配新状态 - -### 新增工具类(已创建) -- ✅ `miniprogram/utils/chapterAccessManager.js` - 权限管理器 -- ✅ `miniprogram/utils/readingTracker.js` - 阅读追踪器 - -### 新增接口(已创建) -- ✅ `app/api/user/reading-progress/route.ts` - 进度上报接口 - -### 新增数据表(已创建) -- ✅ `reading_progress` - 阅读进度表(已通过 Python 脚本创建) - ---- - -## 三、核心改动详解 - -### 1. 状态机设计(accessState) - -**旧代码**:用布尔值 `canAccess` 判断权限,状态不清晰 -```javascript -// ❌ 旧代码 -canAccess: false // 无法区分"未登录"还是"未购买" -``` - -**新代码**:用枚举 `accessState` 明确所有状态 -```javascript -// ✅ 新代码 -accessState: 'unknown' | 'free' | 'locked_not_login' | 'locked_not_purchased' | 'unlocked_purchased' | 'error' -``` - -| 状态 | 含义 | UI 展示 | -|------|------|---------| -| `unknown` | 加载中 | loading 骨架屏 | -| `free` | 免费章节 | 全文 + 阅读追踪 | -| `locked_not_login` | 未登录 | 预览 + 登录按钮 | -| `locked_not_purchased` | 未购买 | 预览 + 购买按钮 | -| `unlocked_purchased` | 已购买 | 全文 + 阅读追踪 | -| `error` | 网络异常 | 预览 + 重试按钮 | - -### 2. onLoad 标准流程 - -**旧代码**:权限判断分散在 `initSection` 中,混杂内容加载 -```javascript -// ❌ 旧代码 -async onLoad(options) { - const run = async () => { - await this.loadFreeChaptersConfig() - this.initSection(id) // 权限判断 + 内容加载混在一起 - } - run() -} -``` - -**新代码**:流程清晰,职责分离 -```javascript -// ✅ 新代码 -async onLoad(options) { - // 1. 拉取最新配置 - const config = await accessManager.fetchLatestConfig() - - // 2. 确定权限状态 - const accessState = await accessManager.determineAccessState(id, config.freeChapters) - - // 3. 加载内容 - await this.loadContent(id, accessState) - - // 4. 如果有权限,初始化阅读追踪 - if (canAccess) { - readingTracker.init(id) - } - - // 5. 加载导航 - this.loadNavigation(id) -} -``` - -### 3. 登录成功标准流程 - -**旧代码**:复杂的 `recheckCurrentSectionAndRefresh`,多次请求 -```javascript -// ❌ 旧代码 -async handleWechatLogin() { - await this.refreshPurchaseFromServer() // 请求1 - await this.recheckCurrentSectionAndRefresh() // 内部又请求 check-purchased(请求2) - await this.initSection(sectionId) // 又重复一次权限判断(请求3) -} -``` - -**新代码**:统一 `onLoginSuccess`,流程简洁 -```javascript -// ✅ 新代码 -async handleWechatLogin() { - const result = await app.login() - if (result) { - await this.onLoginSuccess() // 标准流程 - } -} - -async onLoginSuccess() { - // 1. 刷新购买状态 - await accessManager.refreshUserPurchaseStatus() - - // 2. 重新拉取免费列表 - const config = await accessManager.fetchLatestConfig() - - // 3. 重新判断权限(1次请求) - const newAccessState = await accessManager.determineAccessState(sectionId, config.freeChapters) - - // 4. 如果已解锁,重新加载并追踪 - if (canAccess) { - await this.loadContent(sectionId, newAccessState) - readingTracker.init(sectionId) - } -} -``` - -### 4. 支付成功标准流程 - -**旧代码**:直接调用 `refreshUserPurchaseStatus` + `initSection` -```javascript -// ❌ 旧代码 -await this.callWechatPay(paymentData) -await this.refreshUserPurchaseStatus() -this.initSection(this.data.sectionId) -``` - -**新代码**:统一 `onPaymentSuccess`,包含重试机制 -```javascript -// ✅ 新代码 -await this.callWechatPay(paymentData) -await this.onPaymentSuccess() - -async onPaymentSuccess() { - await this.sleep(2000) // 等待回调 - await accessManager.refreshUserPurchaseStatus() - - let newAccessState = await accessManager.determineAccessState(...) - - // 如果权限未生效,再重试一次 - if (newAccessState !== 'unlocked_purchased') { - await this.sleep(1000) - newAccessState = await accessManager.determineAccessState(...) - } - - await this.loadContent(sectionId, newAccessState) - readingTracker.init(sectionId) -} -``` - -### 5. 阅读进度追踪 - -**旧代码**:只有进度条显示,无追踪 -```javascript -// ❌ 旧代码 -onPageScroll(e) { - // 只计算进度条显示,不记录阅读状态 - this.setData({ readingProgress: progress }) -} -``` - -**新代码**:集成 `readingTracker`,自动追踪 -```javascript -// ✅ 新代码 -onPageScroll(e) { - // 只在有权限时追踪 - if (!accessManager.canAccessFullContent(this.data.accessState)) { - return - } - - const scrollInfo = { scrollTop, scrollHeight, clientHeight } - - // 更新 UI 进度条 - this.setData({ readingProgress: progress }) - - // 更新追踪器(记录最大进度、判断是否读完) - readingTracker.updateProgress(scrollInfo) -} - -// 页面隐藏时上报进度 -onHide() { - readingTracker.onPageHide() -} - -// 页面卸载时清理 -onUnload() { - readingTracker.cleanup() -} -``` - -### 6. 异常处理统一 - -**旧代码**:异常时用本地缓存,可能误解锁 -```javascript -// ❌ 旧代码 -catch (e) { - canAccess = hasFullBook || purchasedSections.includes(id) // 危险:信任本地缓存 -} -``` - -**新代码**:异常时保守处理,展示 error 状态 -```javascript -// ✅ 新代码 -catch (e) { - return 'error' // 保守策略:无法确认权限时返回错误状态 -} - -// UI 上展示重试按钮 - - - ⚠️ - 网络异常 - - - -``` - ---- - -## 四、WXML 模板改动 - -### 旧模板:基于 canAccess 布尔值 -```xml - -全文 - - - - - -``` - -### 新模板:基于 accessState 枚举 -```xml - -骨架屏 - - - 全文 + 导航 - - - - 预览 + 登录按钮 - - - - 预览 + 购买按钮 - - - - 预览 + 重试按钮 - -``` - ---- - -## 五、测试验证 - -### 必测场景 -1. **免费章节** - - ✅ 进入后直接展示全文 - - ✅ 滚动时追踪进度(检查 `reading_progress` 表) - - ✅ 读到 90% 停留 3 秒后标记为 completed - -2. **未登录打开付费章** - - ✅ 展示预览(20%)+ 登录按钮 - - ✅ 点登录 → 登录成功 → 重新判断权限 - - ✅ 若已购买则解锁,否则显示购买按钮 - -3. **已登录未购买** - - ✅ 展示预览 + 购买按钮 - - ✅ 点购买 → 支付成功 → 解锁全文 - - ✅ 解锁后初始化阅读追踪 - -4. **支付成功** - - ✅ 等待 2 秒后刷新权限 - - ✅ 若未生效则再重试 1 次 - - ✅ 解锁后展示全文并追踪 - -5. **网络异常** - - ✅ 显示 error 状态 + 重试按钮 - - ✅ 点重试重新判断权限 - - ✅ 不误解锁内容 - -6. **断点续读** - - ✅ 退出后重新进入,恢复到上次阅读位置 - - ✅ Toast 提示"继续阅读 (75%)" - -7. **极端情况:登录后当前章节刚改免费** - - ✅ 登录时重新拉取免费列表 - - ✅ 若已免费则直接解锁 - ---- - -## 六、数据验证 - -### 检查 reading_progress 表 -```sql --- 查看最近上报的进度 -SELECT * FROM reading_progress -ORDER BY last_open_at DESC -LIMIT 10; - --- 查看完成率 -SELECT - section_id, - COUNT(*) as readers, - SUM(CASE WHEN status = 'completed' THEN 1 ELSE 0 END) as completed, - ROUND(AVG(progress), 2) as avg_progress, - ROUND(AVG(duration)/60, 1) as avg_minutes -FROM reading_progress -GROUP BY section_id; -``` - ---- - -## 七、回退方案 - -如果新版本出现问题,可快速回退: - -```bash -# 恢复旧版本 -cd miniprogram/pages/read/ -copy read.js.backup read.js - -# 重新部署小程序 -``` - ---- - -## 八、后续优化(可选) - -1. **性能优化** - - 减少登录后重复请求(当前:刷新购买状态 + check-purchased,可合并为一次) - - 阅读追踪节流优化(当前 500ms,可调整) - -2. **用户体验** - - 断点续读时平滑滚动 - - 读完后推荐下一章 - -3. **数据分析** - - 接入微信小程序数据助手 - - 配置完成率、时长等看板 - ---- - -## 九、相关文档 - -- 📖 设计文档:`开发文档/8、部署/章节阅读付费标准流程设计.md` -- 📖 集成示例:`开发文档/8、部署/章节阅读页集成示例.md` -- 📖 阅读逻辑分析:`开发文档/8、部署/阅读逻辑分析.md` - ---- - -## 十、总结 - -### 改造效果 -- ✅ **权限判断统一**:所有权限由 `accessManager` 统一管理,以服务端为准 -- ✅ **状态流转清晰**:6 种状态枚举,UI 与状态一一对应 -- ✅ **异常降级标准**:网络异常时保守处理,展示重试,不误解锁 -- ✅ **阅读追踪完整**:记录进度、时长、是否读完,支持断点续读 -- ✅ **bug 规避**:解决"登录后误解锁"、"支付后权限未生效"等问题 - -### 预期收益 -- 📉 **bug 减少 80%+**(权限判断统一、异常处理标准化) -- 📈 **数据驱动决策**(完成率、时长、活跃度分析) -- 🎯 **用户体验提升**(断点续读、明确的状态反馈、流畅的流程) -- 🔧 **可维护性提升**(代码结构清晰、职责分离、工具类复用) - -改造完成,可正式测试和部署! diff --git a/开发文档/9、手册/使用手册提示词.md b/开发文档/9、手册/使用手册提示词.md deleted file mode 100644 index 277059a4..00000000 --- a/开发文档/9、手册/使用手册提示词.md +++ /dev/null @@ -1,48 +0,0 @@ -# 使用手册提示词 (User Manual Prompt) - 智能自生长文档 - -> **提示词功能 (Prompt Function)**: 将本文件拖入 AI 对话框,即可激活“技术文档专家”角色,生成小白也能看懂的操作手册。 - -## 1. 基础上下文 (The Two Basic Files) -### 1.1 角色档案:卡若 (Karuo) -- **受众**:小白用户、合作方老板。 -- **风格**:大白话、傻瓜式、图文并茂。 - -### 1.2 文档原则 -- **价值先行**:先说能赚多少钱,再说怎么操作。 -- **步骤清晰**:Step 1, 2, 3。 - -## 2. 手册核心 (Master Content) -### 2.1 功能介绍 (Value) -- **话术**:不要说“分布式”,要说“账目自动同步,谁也改不了”。 -- **核心**:帮你自动分钱的工具。 - -### 2.2 快速上手 (How-to) -- **Step 1**: 登录与绑定 (截图)。 -- **Step 2**: 开启流量池 (核心操作)。 -- **Step 3**: 提现与分润 (钱)。 - -### 2.3 常见问题 (Q&A) -- **痛点**:如果不显示收益怎么办? -- **解法**:点击刷新,检查网络。 - -## 3. AI 协作指令 (Expanded Function) -**角色**:你是我(卡若)的内容运营。 -**任务**: -1. **文档撰写**:根据功能描述,写出“傻瓜式”操作手册。 -2. **话术优化**:将技术术语翻译成“老板听得懂的话”。 -3. **用户旅程**:用 Mermaid 展示用户操作流程。 - -### 示例 Mermaid (用户旅程) -\`\`\`mermaid -journey - title 合作方使用流程 - section 注册 - 打开小程序: 5: 合作方 - 手机号登录: 4: 合作方 - section 赚钱 - 开启流量池: 5: 合作方 - 查看今日收益: 5: 合作方 - section 提现 - 申请提现: 4: 合作方 - 到账: 5: 合作方 -\`\`\` diff --git a/开发文档/9、手册/全站捆绑分销体系-SCALE.md b/开发文档/9、手册/全站捆绑分销体系-SCALE.md deleted file mode 100644 index cc792c1a..00000000 --- a/开发文档/9、手册/全站捆绑分销体系-SCALE.md +++ /dev/null @@ -1,157 +0,0 @@ -# 全站捆绑分销体系 · SCALE(可复用规格) - -> **版本**:1.0 -> **来源**:一场soul的创业实验-永平 实战提炼 -> **用途**:作为全站消费捆绑 + 分销机制的可复用规格,可套用到其他网站、小程序、付费内容项目 - ---- - -## 一、核心理念 - -**全站捆绑** = 用户通过谁的分享链接进入,即与谁建立 30 天有效期的「推荐关系」,该关系覆盖全站所有消费(章节、全书、找伙伴、会员等)。 - -**分销体系** = 被推荐人支付成功 → 推荐人获得佣金(默认 90%)→ 支持提现。 - ---- - -## 二、核心规则(30 天捆绑) - -| 规则 | 说明 | -|:---|:---| -| **动态绑定** | 用户 B 点击谁的分享链接,立即绑定谁(无条件切换) | -| **佣金归属** | B 购买时,佣金给当前推荐人(最新绑定的那个人) | -| **30 天有效期** | 绑定日起 30 天内有效,可续期(同一推荐人再次点击则刷新 30 天) | -| **自动解绑** | 绑定 30 天内,若 B 既没点击其他链接,也没有任何购买 → 自动解绑 | - -### 时间线示例 - -``` -Day 0: A 推荐 B → B 注册 → B 绑定 A(30 天有效期) -Day 5: B 点击 C 的链接 → B 立即切换绑定 C(重新开始 30 天有效期) -Day 10: B 购买 → 佣金给 C(当前推荐人) -Day 35: 绑定 C 的 30 天到期,若期间无购买 → 自动解绑 -``` - ---- - -## 三、数据库设计(最小可复用) - -### 3.1 referral_bindings(推荐绑定表) - -| 字段 | 类型 | 说明 | -|------|------|------| -| id | VARCHAR(64) | 主键 | -| referee_id | VARCHAR(64) | 被推荐人(买家) | -| referrer_id | VARCHAR(64) | 推荐人(拿佣金的人) | -| referral_code | VARCHAR(20) | 推荐码 | -| status | ENUM | active / cancelled / expired | -| binding_date | TIMESTAMP | 最后一次绑定时间 | -| expiry_date | DATETIME | 过期时间(30 天后) | -| last_purchase_date | DATETIME | 最后一次购买时间 | -| purchase_count | INT | 购买次数 | -| total_commission | DECIMAL(10,2) | 累计佣金 | - -### 3.2 users(需扩展字段) - -| 字段 | 说明 | -|------|------| -| referral_code | 自己的邀请码 | -| referred_by | 可选,首次推荐人 | -| pending_earnings | 待结算佣金 | -| earnings | 已结算佣金 | - -### 3.3 orders(需扩展字段) - -| 字段 | 说明 | -|------|------| -| referrer_id | 下单时的推荐人 user_id | -| referral_code | 下单时使用的邀请码(对账/展示) | - -### 3.4 system_config(配置) - -- `config_key = 'referral_config'` -- `distributorShare`:推广者分成比例(默认 90) -- `bindingDays`:绑定有效期天数(默认 30) -- `minWithdrawAmount`:最小提现金额(默认 10 元) - ---- - -## 四、API 逻辑(关键接口) - -### 4.1 绑定接口 `POST /api/referral/bind` - -- **入参**:userId(被推荐人), referralCode -- **逻辑**: - - 同一推荐人 → 续期(刷新 30 天) - - 不同推荐人 → 旧绑定 status=cancelled,新绑定 active,expiry=NOW+30 天 - -### 4.2 下单时定推荐人(创建订单前) - -1. 先查 `referral_bindings`(referee_id=买家,status=active,expiry_date>NOW) -2. 无绑定则用请求体 `referralCode` 查 users 得 referrer_id -3. 写入 `orders.referrer_id`、`orders.referral_code` - -### 4.3 支付成功回调(分佣) - -1. 查 `referral_bindings`(referee_id=买家,status=active) -2. 取 referrer_id,佣金 = 订单金额 × distributorShare / 100 -3. 更新 `referral_bindings`:purchase_count++,total_commission+=佣金,last_purchase_date=NOW -4. 更新 `users`:referrer 的 pending_earnings += 佣金 -5. **不**将 binding 改为 converted,保持 active,允许多次购买分佣 - -### 4.4 自动解绑定时任务(每天 02:00) - -```sql -UPDATE referral_bindings -SET status = 'expired' -WHERE status = 'active' - AND expiry_date < NOW() - AND purchase_count = 0 -``` - ---- - -## 五、概念区分(避免混乱) - -| 概念 | 含义 | 存储 | 用途 | -|------|------|------|------| -| **邀请码** | 一串码,如 SOULABC123 | users.referral_code | 链接 ref=邀请码,解析出推荐人 | -| **推荐人** | 拿佣金的人 | referrer_id(用户ID) | 分佣、订单归属、统计 | -| **绑定表** | 权威的「谁推荐了谁」 | referral_bindings | 分佣只看此表 | - -**优先级**:绑定表 > 邀请码兜底。订单 referrer_id 只做展示/对账,不参与分佣计算。 - ---- - -## 六、提现流程(配套) - -- 用户:可提现 = 累计佣金 − 已提现 − 待审核 -- 申请:POST /api/miniprogram/withdraw → status=pending -- 管理端:通过 → 调微信商家转账 → status=processing -- 微信回调:成功 → status=success;失败 → status=failed - ---- - -## 七、复用 checklist(套用到新项目) - -- [ ] 建表:referral_bindings、users 扩展、orders 扩展、withdrawals -- [ ] 配置:referral_config(分成比例、绑定天数、最低提现) -- [ ] 绑定接口:/api/referral/bind(动态切换 + 30 天) -- [ ] 下单逻辑:写 orders.referrer_id、referral_code -- [ ] 支付回调:查绑定 → 分佣 → 累加 purchase_count -- [ ] 定时任务:每天解绑 purchase_count=0 且过期的记录 -- [ ] 前端:分享链接带 ref=邀请码,登录后调 bind -- [ ] 提现:用户申请 → 管理审核 → 微信打款 - ---- - -## 八、相关文档(本项目内) - -- [新分销逻辑设计方案](../8、部署/新分销逻辑设计方案.md) -- [邀请码分销规则说明](../8、部署/邀请码分销规则说明.md) -- [分销与绑定流程图](../8、部署/分销与绑定流程图.md) -- [分销提现流程图](../8、部署/分销提现流程图.md) - ---- - -*本 SCALE 可供任何有「全站消费 + 分销」需求的网站/小程序复用。* diff --git a/开发文档/9、手册/写作与结构维护手册.md b/开发文档/9、手册/写作与结构维护手册.md deleted file mode 100644 index 2e096fdc..00000000 --- a/开发文档/9、手册/写作与结构维护手册.md +++ /dev/null @@ -1,43 +0,0 @@ -# 写作与结构维护手册(Mycontent-book) - -## 1. 你改文档,我怎么理解 - -你只要改这三类文件,我就能按规则做事: - -- `external/Mycontent-book/book/**/*.md`:正文内容 -- `external/Mycontent-book/1、soul 全部.txt`:素材源(不要随便改结构) -- `external/1、开发模板/**`:需求、架构、部署的“标准答案” - -## 2. 章节怎么放(目录就是结构) - -- “篇”是一级目录 -- “章”是二级目录 -- “小节”是 `.md` 文件 - -原则:尽量新增,不要频繁移动旧文件。 - -## 3. 写作动作建议(减少冲突、减少噪音) - -- 一次改一篇/一章,写完再切下一个 -- 同一小节尽量集中修改,不要碎片化改一堆次 - -## 4. 事实与数据怎么处理 - -- 数值、时间、对话:以素材文件里的原文为准 -- 不确定就不写死,先把“素材引用段落”留在文档里 - -## 5. 自动同步的最佳姿势 - -- 开始写作前启动:`./scripts/autosync.sh` -- 写作时正常保存即可 -- 停止同步:`Ctrl+C` - -## 6. 你想改规则怎么改 - -你直接改开发模板里的对应文档: - -- 要改目标/范围:改 `1、需求/业务需求.md` -- 要改结构/同步策略:改 `2、架构/系统架构.md` 或 `8、部署/自动同步与分支策略.md` -- 要改跑站点方式:改 `8、部署/本地运行.md` - -我会按你最新文档执行。 diff --git a/开发文档/9、手册/手册索引.md b/开发文档/9、手册/手册索引.md deleted file mode 100644 index 717a60d1..00000000 --- a/开发文档/9、手册/手册索引.md +++ /dev/null @@ -1,25 +0,0 @@ -# 手册与提示词索引 - -> 本目录下所有手册与 AI 提示词统一入口。 - ---- - -## 手册 - -| 文件 | 说明 | -|:---|:---| -| [写作与结构维护手册](./写作与结构维护手册.md) | 书籍写作与结构维护规范 | -| [全站捆绑分销体系-SCALE](./全站捆绑分销体系-SCALE.md) | 30天捆绑+分销可复用规格,可套用到其他网站/小程序 | - -## 提示词(AI 协作) - -| 文件 | 说明 | -|:---|:---| -| [提示词/使用手册提示词](./提示词/使用手册提示词.md) | 文档生成工具(截图、Word 导出) | -| [提示词/落地方案提示词](./提示词/落地方案提示词.md) | 复盘、营销文章、卡若风格输出 | -| [提示词/说明手册提示词](./提示词/说明手册提示词.md) | 系统说明、架构、接口、配置文档 | -| [使用手册提示词](./使用手册提示词.md) | 小白操作手册(技术文档专家角色) | - ---- - -**使用**:将对应 .md 文件拖入 AI 对话框,即可激活对应模板或角色。 diff --git a/开发文档/9、手册/提示词/使用手册提示词.md b/开发文档/9、手册/提示词/使用手册提示词.md deleted file mode 100644 index 0a581bbc..00000000 --- a/开发文档/9、手册/提示词/使用手册提示词.md +++ /dev/null @@ -1,13 +0,0 @@ -在这个应用程序中开发一个实用工具,目录名称为“/documentation”,只能用地址访问不要放到可以点击的地方,用于自动生成一套全面的文档集。 - -该工具应能捕捉应用程序所有界面的屏幕截图,在文档生成器中使用iframe方式,保证每个页面加载成功的情况下,实现真实的截图功能,而不是使用占位图。 - -系统应自动整理这些截图,将其与文档的相关部分关联起来。然后,该工具应将这些截图和相关文本汇编成一个可导出的Word文档(.docx)。 - -Word文档应包含目录、与应用程序功能相对应的清晰标题和副标题,以及每张截图的说明文字。 - -确保导出过程简化为一键生成,最大限度减少人工干预。 - -生成的文档应反映所提供示例的结构和内容,融入应用程序的特定功能和特性。处理截图捕获或文档生成过程中的任何潜在错误,以确保准确性和完整性。 - -最终输出应为适合分发给利益相关者和用户的专业质量文档。 diff --git a/开发文档/9、手册/提示词/落地方案提示词.md b/开发文档/9、手册/提示词/落地方案提示词.md deleted file mode 100644 index b0bbd29e..00000000 --- a/开发文档/9、手册/提示词/落地方案提示词.md +++ /dev/null @@ -1,32 +0,0 @@ -# 落地方案提示词 - -> 用于记录「把需求落到代码/流程」的提示词。拖入 AI 即可按固定模板输出。 - ---- - -## 输出格式要求 - -### 1. 复盘示例 - -```markdown -[私域云阿米巴模式落地复盘](2025年Q2) -**目标&结果**:目标3个月内绑定15家合作方,实际完成18家(超20%)。 -**过程**:5月启动流量测试...;6月上线私域系统...;7月现金分润验证... -**反思**:... -**总结**:... -**执行**:... -``` - -### 2. 营销文章结构 - -- **I(兴趣)**:自问自答引发共鸣。 -- **S(故事/案例)**:真实经历描述。 -- **S(干货)**:可落地的步骤+数据。 -- **M(产品/概念)**:核心模式与优势。 -- **F(裂变)**:行动号召。 - -### 3. 卡若风格文章要求 - -- **结构**:自问自答 → 故事/反思(含数据)→ 行动指引。 -- **语言**:简洁直接,挑战传统。 -- **字数**:不低于 2000 字,数据需有据可查。 diff --git a/开发文档/9、手册/提示词/说明手册提示词.md b/开发文档/9、手册/提示词/说明手册提示词.md deleted file mode 100644 index 260f4031..00000000 --- a/开发文档/9、手册/提示词/说明手册提示词.md +++ /dev/null @@ -1,38 +0,0 @@ -# 说明手册提示词 - -> 用于记录「对外说明/交付手册」的提示词。面向内部开发、运维、系统管理员。 - ---- - -## 核心原则 - -- **对象**:内部开发、运维、系统管理员。 -- **风格**:专业、严谨、逻辑缜密。 -- **口吻**:客观描述,无情绪色彩。 - -## 内容结构 - -### 1. 系统概述 - -- 系统定位、核心能力、适用场景。 - -### 2. 架构说明 - -- **技术栈**:具体版本(如 React 18, Java 17)。 -- **架构图**:引用开发文档中的架构图。 -- **目录结构**:核心目录作用。 - -### 3. 接口与数据 - -- **API 规范**:RESTful,统一响应格式。 -- **数据字典**:核心表/集合字段与类型。 - -### 4. 配置与环境 - -- **环境变量**:必配 ENV 及含义。 -- **外部依赖**:Redis、第三方 API 等配置要求。 - -## 格式要求 - -- **代码块**:命令、配置、JSON 示例用 Markdown 代码块。 -- **表格**:参数说明、状态码用表格。 diff --git a/开发文档/README.md b/开发文档/README.md deleted file mode 100644 index 9e4e46b1..00000000 --- a/开发文档/README.md +++ /dev/null @@ -1,72 +0,0 @@ -# Soul 创业派对 - 开发文档索引 - -> 小橙整理 · 2026-02-26 - -## 当前项目架构 - -| 子项目 | 目录 | 用途 | -|--------|------|------| -| soul-api | soul-api/ | Go + Gin + GORM 接口服务(生产后端) | -| soul-admin | soul-admin/ | React 管理后台 | -| miniprogram | miniprogram/ | 微信原生小程序 | -| next-project | next-project/ | 仅预览,非生产 | - ---- - -## 文档导航 - -### 需求与项目管理 - -| 文档 | 说明 | -|------|------| -| [1、需求/需求汇总](1、需求/需求汇总.md) | 需求清单、业务需求 | -| [10、项目管理/项目落地推进表](10、项目管理/项目落地推进表.md) | 里程碑、永平落地 | -| [10、项目管理/运营与变更](10、项目管理/运营与变更.md) | 近期讨论、变更记录 | - -### 架构与规范 - -| 文档 | 说明 | -|------|------| -| [2、架构/系统与技术](2、架构/系统与技术.md) | 系统与技术栈 | -| [2、架构/soul-api技术栈](2、架构/soul-api技术栈.md) | soul-api Go 技术栈(Gin、GORM、PowerWeChat、JWT) | -| [2、架构/链路与变现](2、架构/链路与变现.md) | 业务链路 | -| [4、前端/前端开发规范](4、前端/前端开发规范.md) | 前端规范 | -| [6、后端/后端开发规范](6、后端/后端开发规范.md) | 后端规范 | - -### 接口与部署 - -| 文档 | 说明 | -|------|------| -| [5、接口/API接口完整文档](5、接口/API接口完整文档.md) | API 完整文档 | -| [6、后端/管理端鉴权设计](6、后端/管理端鉴权设计.md) | soul-api 管理端 JWT 鉴权、路由分层 | -| [8、部署/部署总览](8、部署/部署总览.md) | 部署入口、分销与流程 | -| [8、部署/宝塔反向代理说明](8、部署/宝塔反向代理说明.md) | soul-api 域名 404 排查、Nginx 反向代理配置 | -| [8、部署/提现功能完整技术文档](8、部署/提现功能完整技术文档.md) | 微信支付商家转账到零钱 API 集成 | -| [8、部署/分销提现流程图](8、部署/分销提现流程图.md) | 提现业务流程图 | -| [8、部署/订阅消息](8、部署/订阅消息.md) | 提现成功订阅消息(PowerWeChat) | -| [8、部署/商家转账](8、部署/商家转账.md) | PowerWeChat 商家转账示例 | - -### 临时需求池 - -| 文档 | 说明 | -|------|------| -| 临时需求池/需求分析-产品经理视角 | 需求分析 | -| 临时需求池/分润需求-技术分析 | 会员分润差异化技术方案 | - ---- - -## 已移除文档(2026-02-26) - -- Prisma ORM 迁移相关(3 份)— 项目已迁至 Go/GORM -- Next.js 宝塔部署方案、Standalone 模式 — next-project 仅预览 -- 拆解计划 — 已完成,soul-admin 与 soul-api 已落地 -- 近3天更新文档(5 份)— 已合并至 运营与变更 第六部分 -- 8、部署 历史修复说明(约 35 份)— 一次性修复记录,已无参考价值 - -## 已移除文件(2026-02-27 橙子清理) - -- `.DS_Store`(4 处)— macOS 系统缓存 -- `1、需求/修改/1.doc` — 空文件 -- `SKILL.md`(根目录)— 技术栈已过期(写的是 Next.js),以 README 与 .cursor/skills 为准 -- `小程序管理/scripts/__pycache__/*.pyc` — Python 缓存 -- `小程序管理/scripts/reports/*.json`(4 份)— 脚本生成的一次性报告 diff --git a/开发文档/SKILL.md b/开发文档/SKILL.md deleted file mode 100644 index 5a69fb92..00000000 --- a/开发文档/SKILL.md +++ /dev/null @@ -1,84 +0,0 @@ -# Soul创业派对 - 项目开发SKILL - -## 项目概述 - -| 项目 | 值 | -|------|-----| -| 项目名 | Soul创业派对(一场Soul的创业实验) | -| 小程序AppID | wxb8bbb2b10dec74aa | -| 后端地址 | https://soul.quwanzhi.com | -| 技术栈(前端) | 微信小程序原生 + 自定义TabBar | -| 技术栈(后端) | Next.js App Router + MySQL | -| 数据库 | 腾讯云MySQL | -| 仓库 | github.com/fnvtk/Mycontent (yongpxu-soul分支) | - -## 开发文档目录索引 - -``` -开发文档/ -├── 1、需求/ ← 需求文档、需求日志、TDD方案 -├── 2、架构/ ← 系统架构、技术选型、链路说明 -├── 3、原型/ ← 原型设计 -├── 4、前端/ ← 前端架构、UI截图 -├── 5、接口/ ← API接口文档、接口定义规范 -├── 6、后端/ ← 后端架构、修复说明 -├── 7、数据库/ ← 数据库设计、管理规范 -├── 8、部署/ ← 部署流程、宝塔配置、小程序上传 -├── 9、手册/ ← 使用手册、写作手册 -├── 10、项目管理/ ← 项目总览、运营报表、会议记录 -├── 小程序管理/ ← 小程序生命周期SKILL(独立) -└── 服务器管理/ ← 服务器运维SKILL(独立) -``` - -## 需求日志管理规范 - -- 每次对话的需求自动追加到 `1、需求/需求日志.md` -- 格式:`| 日期 | 需求描述 | 状态 | 备注 |` -- 状态:待开发 / 开发中 / 已完成 / 已取消 -- 每个版本上传后,将该批需求标记为「已完成」 - -## 常用命令 - -### 上传小程序 -```bash -/Applications/wechatwebdevtools.app/Contents/MacOS/cli upload \ - --project "/Users/karuo/Documents/开发/3、自营项目/一场soul的创业实验/miniprogram" \ - --version "版本号" --desc "版本说明" -``` - -### 从GitHub同步miniprogram -```bash -cd /tmp && rm -rf Mycontent_soul_tmp -git clone --depth 1 --branch yongpxu-soul https://github.com/fnvtk/Mycontent.git Mycontent_soul_tmp -rsync -av --delete Mycontent_soul_tmp/miniprogram/ "/Users/karuo/Documents/开发/3、自营项目/一场soul的创业实验/miniprogram/" -rm -rf Mycontent_soul_tmp -``` - -### 数据库迁移 -```bash -curl -X POST https://soul.quwanzhi.com/api/db/migrate -H 'Content-Type: application/json' -d '{}' -``` - -## 核心页面结构 - -| 页面 | 路径 | 说明 | -|------|------|------| -| 首页 | pages/index/index | 精选推荐(阅读量)、创业老板排行 | -| 目录 | pages/chapters/chapters | 章节列表 | -| 找伙伴 | pages/match/match | 匹配动画 | -| 我的 | pages/my/my | 用户信息、收益、VIP、账号设置 | -| 阅读 | pages/read/read | 章节内容、付费墙 | -| VIP | pages/vip/vip | VIP权益、购买、资料填写 | -| 会员详情 | pages/member-detail/member-detail | 创业老板排行点击详情 | - -## 后端API模块 - -| 模块 | 路径前缀 | 说明 | -|------|---------|------| -| VIP会员 | /api/vip/ | purchase、status、profile、members | -| 书籍 | /api/book/ | chapters、hot、latest-chapters、search | -| 用户 | /api/user/ | profile、update、track | -| 支付 | /api/miniprogram/pay | 微信小程序支付 | -| 推广 | /api/referral/ | bind、data、visit | -| 提现 | /api/withdraw | 提现到微信零钱 | -| 管理后台 | /api/admin/ | content、chapters、payment等 | diff --git a/开发文档/api_v1.md b/开发文档/api_v1.md deleted file mode 100644 index 7a1c2636..00000000 --- a/开发文档/api_v1.md +++ /dev/null @@ -1,413 +0,0 @@ -# 对外获客线索上报接口文档(V1) - -## 一、接口概述 - -- **接口名称**:对外获客线索上报接口 -- **接口用途**:供第三方系统向【存客宝】上报客户线索(手机号 / 微信号等),用于后续的跟进、标签管理和画像分析。 -- **接口协议**:HTTP -- **请求方式**:`POST` -- **请求地址**: `https://ckbapi.quwanzhi.com/v1/api/scenarios` - -> 具体 URL 以实际环境配置为准。 - -- **数据格式**: - - 推荐:`application/json` - - 兼容:`application/x-www-form-urlencoded` -- **字符编码**:`UTF-8` - ---- - -## 二、鉴权与签名 - -### 2.1 必填鉴权字段 - -| 字段名 | 类型 | 必填 | 说明 | -|-------------|--------|------|---------------------------------------| -| `apiKey` | string | 是 | 分配给第三方的接口密钥(每个任务唯一)| -| `sign` | string | 是 | 签名值 | -| `timestamp` | int | 是 | 秒级时间戳(与服务器时间差不超过 5 分钟) | - -### 2.2 时间戳校验 - -服务器会校验 `timestamp` 是否在当前时间前后 **5 分钟** 内: - -- 通过条件:`|server_time - timestamp| <= 300` -- 超出范围则返回:`请求已过期` - -### 2.3 签名生成规则 - -接口采用自定义签名机制。**签名字段为 `sign`,生成步骤如下:** - -假设本次请求的所有参数为 `params`,其中包括业务参数 + `apiKey` + `timestamp` + `sign` + 可能存在的 `portrait` 对象。 - -#### 第一步:移除特定字段 - -从 `params` 中移除以下字段: - -- `sign` —— 自身不参与签名 -- `apiKey` —— 不参与参数拼接,仅在最后一步参与二次 MD5 -- `portrait` —— 整个画像对象不参与签名(即使内部还有子字段) - -> 说明:`portrait` 通常是一个 JSON 对象,字段较多,为避免签名实现复杂且双方难以对齐,统一不参与签名。 - -#### 第二步:移除空值字段 - -从剩余参数中,移除值为: - -- `null` -- 空字符串 `''` - -的字段,这些字段不参与签名。 - -#### 第三步:按参数名升序排序 - -对剩余参数按**参数名(键名)升序排序**,排序规则为标准的 ASCII 升序: - -```text -例如: name, phone, source, timestamp -``` - -#### 第四步:拼接参数值 - -将排序后的参数 **只取“值”**,按顺序直接拼接为一个字符串,中间不加任何分隔符: - -- 示例: - 排序后参数为: - - ```text - name = 张三 - phone = 13800000000 - source = 微信广告 - timestamp = 1710000000 - ``` - - 则拼接: - - ```text - stringToSign = "张三13800000000微信广告1710000000" - ``` - -#### 第五步:第一次 MD5 - -对上一步拼接得到的字符串做一次 MD5: - -\[ -\text{firstMd5} = \text{MD5}(\text{stringToSign}) -\] - -#### 第六步:拼接 apiKey 再次 MD5 - -将第一步的结果与 `apiKey` 直接拼接,再做一次 MD5,得到最终签名值: - -\[ -\text{sign} = \text{MD5}(\text{firstMd5} + \text{apiKey}) -\] - -#### 第七步:放入请求 - -将第六步得到的 `sign` 填入请求参数中的 `sign` 字段即可。 - -> 建议: -> - 使用小写 MD5 字符串(双方约定统一即可)。 -> - 请确保参与签名的参数与最终请求发送的参数一致(包括是否传空值)。 - -### 2.4 签名示例(PHP 伪代码) - -```php -$params = [ - 'apiKey' => 'YOUR_API_KEY', - 'timestamp' => '1710000000', - 'phone' => '13800000000', - 'name' => '张三', - 'source' => '微信广告', - 'remark' => '通过H5落地页留资', - // 'portrait' => [...], // 如有画像,这里会存在,但不参与签名 - // 'sign' => '待生成', -]; - -// 1. 去掉 sign、apiKey、portrait -unset($params['sign'], $params['apiKey'], $params['portrait']); - -// 2. 去掉空值 -$params = array_filter($params, function($value) { - return !is_null($value) && $value !== ''; -}); - -// 3. 按键名升序排序 -ksort($params); - -// 4. 拼接参数值 -$stringToSign = implode('', array_values($params)); - -// 5. 第一次 MD5 -$firstMd5 = md5($stringToSign); - -// 6. 第二次 MD5(拼接 apiKey) -$apiKey = 'YOUR_API_KEY'; -$sign = md5($firstMd5 . $apiKey); - -// 将 $sign 作为字段发送 -$params['sign'] = $sign; -``` - ---- - -## 三、请求参数说明 - -### 3.1 主标识字段(至少传一个) - -| 字段名 | 类型 | 必填 | 说明 | -|-----------|--------|------|-------------------------------------------| -| `wechatId`| string | 否 | 微信号,存在时优先作为主标识 | -| `phone` | string | 否 | 手机号,当 `wechatId` 为空时用作主标识 | - -### 3.2 基础信息字段 - -| 字段名 | 类型 | 必填 | 说明 | -|------------|--------|------|-------------------------| -| `name` | string | 否 | 客户姓名 | -| `source` | string | 否 | 线索来源描述,如“百度推广”、“抖音直播间” | -| `remark` | string | 否 | 备注信息 | -| `tags` | string | 否 | 逗号分隔的“微信标签”,如:`"高意向,电商,女装"` | -| `siteTags` | string | 否 | 逗号分隔的“站内标签”,用于站内进一步细分 | - - -### 3.3 用户画像字段 `portrait`(可选) - -`portrait` 为一个对象(JSON),用于记录用户的行为画像数据。 - -#### 3.3.1 基本示例 - -```json -"portrait": { - "type": 1, - "source": 1, - "sourceData": { - "age": 28, - "gender": "female", - "city": "上海", - "productId": "P12345", - "pageUrl": "https://example.com/product/123" - }, - "remark": "画像-基础属性", - "uniqueId": "user_13800000000_20250301_001" -} -``` - -#### 3.3.2 字段详细说明 - -| 字段名 | 类型 | 必填 | 说明 | -|-----------------------|--------|------|----------------------------------------| -| `portrait.type` | int | 否 | 画像类型,枚举值:
0-浏览
1-点击
2-下单/购买
3-注册
4-互动
默认值:0 | -| `portrait.source` | int | 否 | 画像来源,枚举值:
0-本站
1-老油条
2-老坑爹
默认值:0 | -| `portrait.sourceData` | object | 否 | 画像明细数据(键值对,会存储为 JSON 格式)
可包含任意业务相关的键值对,如:年龄、性别、城市、商品ID、页面URL等 | -| `portrait.remark` | string | 否 | 画像备注信息,最大长度100字符 | -| `portrait.uniqueId` | string | 否 | 画像去重用唯一 ID
用于防止重复记录,相同 `uniqueId` 的画像数据在半小时内会被合并统计(count字段累加)
建议格式:`{来源标识}_{用户标识}_{时间戳}_{序号}` | - -#### 3.3.3 画像类型(type)说明 - -| 值 | 类型 | 说明 | 适用场景 | -|---|------|------|---------| -| 0 | 浏览 | 用户浏览了页面或内容 | 页面访问、商品浏览、文章阅读等 | -| 1 | 点击 | 用户点击了某个元素 | 按钮点击、链接点击、广告点击等 | -| 2 | 下单/购买 | 用户完成了购买行为 | 订单提交、支付完成等 | -| 3 | 注册 | 用户完成了注册 | 账号注册、会员注册等 | -| 4 | 互动 | 用户进行了互动行为 | 点赞、评论、分享、咨询等 | - -#### 3.3.4 画像来源(source)说明 - -| 值 | 来源 | 说明 | -|---|------|------| -| 0 | 本站 | 来自本站的数据 | -| 1 | 老油条 | 来自"老油条"系统的数据 | -| 2 | 老坑爹 | 来自"老坑爹"系统的数据 | - -#### 3.3.5 sourceData 数据格式说明 - -`sourceData` 是一个 JSON 对象,可以包含任意业务相关的键值对。常见字段示例: - -```json -{ - "age": 28, - "gender": "female", - "city": "上海", - "province": "上海市", - "productId": "P12345", - "productName": "商品名称", - "category": "女装", - "price": 299.00, - "pageUrl": "https://example.com/product/123", - "referrer": "https://www.baidu.com", - "device": "mobile", - "browser": "WeChat" -} -``` - -> **注意**: -> - `sourceData` 中的数据类型可以是字符串、数字、布尔值等 -> - 嵌套对象会被序列化为 JSON 字符串存储 -> - 建议根据实际业务需求定义字段结构 - -#### 3.3.6 uniqueId 去重机制说明 - -- **作用**:防止重复记录相同的画像数据 -- **规则**:相同 `uniqueId` 的画像数据在 **半小时内** 会被合并统计,`count` 字段会自动累加 -- **建议格式**:`{来源标识}_{用户标识}_{时间戳}_{序号}` - - 示例:`site_13800000000_1710000000_001` - - 示例:`wechat_wxid_abc123_1710000000_001` -- **注意事项**: - - 如果不传 `uniqueId`,系统会为每条画像数据创建新记录 - - 如果需要在半小时内多次统计同一行为,应使用相同的 `uniqueId` - - 如果需要在半小时后重新统计,应使用不同的 `uniqueId`(建议修改时间戳部分) - -> **重要提示**:`portrait` **整体不参与签名计算**,但会参与业务处理。系统会根据 `uniqueId` 自动处理去重和统计。 - ---- - -## 四、请求示例 - -### 4.1 JSON 请求示例(无画像) - -```json -{ - "apiKey": "YOUR_API_KEY", - "timestamp": 1710000000, - "phone": "13800000000", - "name": "张三", - "source": "微信广告", - "remark": "通过H5落地页留资", - "tags": "高意向,电商", - "siteTags": "新客,女装", - "sign": "根据签名规则生成的MD5字符串" -} -``` - -### 4.2 JSON 请求示例(带微信号与画像) - -```json -{ - "apiKey": "YOUR_API_KEY", - "timestamp": 1710000000, - "wechatId": "wxid_abcdefg123", - "phone": "13800000001", - "name": "李四", - "source": "小程序落地页", - "remark": "点击【立即咨询】按钮", - "tags": "中意向,直播", - "siteTags": "复购,高客单", - "portrait": { - "type": 1, - "source": 0, - "sourceData": { - "age": 28, - "gender": "female", - "city": "上海", - "pageUrl": "https://example.com/product/123", - "productId": "P12345" - }, - "remark": "画像-点击行为", - "uniqueId": "site_13800000001_1710000000_001" - }, - "sign": "根据签名规则生成的MD5字符串" -} -``` - -### 4.3 JSON 请求示例(多种画像类型) - -#### 4.3.1 浏览行为画像 - -```json -{ - "apiKey": "YOUR_API_KEY", - "timestamp": 1710000000, - "phone": "13800000002", - "name": "王五", - "source": "百度推广", - "portrait": { - "type": 0, - "source": 0, - "sourceData": { - "pageUrl": "https://example.com/product/456", - "productName": "商品名称", - "category": "女装", - "stayTime": 120, - "device": "mobile" - }, - "remark": "商品浏览", - "uniqueId": "site_13800000002_1710000000_001" - }, - "sign": "根据签名规则生成的MD5字符串" -} -``` - - -``` - ---- - -## 五、响应说明 - -### 5.1 成功响应 - -**1)新增线索成功** - -```json -{ - "code": 200, - "message": "新增成功", - "data": "13800000000" -} -``` - -**2)线索已存在** - -```json -{ - "code": 200, - "message": "已存在", - "data": "13800000000" -} -``` - -> `data` 字段返回本次线索的主标识 `wechatId` 或 `phone`。 - -### 5.2 常见错误响应 - -```json -{ "code": 400, "message": "apiKey不能为空", "data": null } -{ "code": 400, "message": "sign不能为空", "data": null } -{ "code": 400, "message": "timestamp不能为空", "data": null } -{ "code": 400, "message": "请求已过期", "data": null } - -{ "code": 401, "message": "无效的apiKey", "data": null } -{ "code": 401, "message": "签名验证失败", "data": null } - -{ "code": 500, "message": "系统错误: 具体错误信息", "data": null } -``` - ---- - - -## 六、常见问题(FAQ) - -### Q1: 如果同一个用户多次上报相同的行为,会如何处理? - -**A**: 如果使用相同的 `uniqueId`,系统会在半小时内合并统计,`count` 字段会累加。如果使用不同的 `uniqueId`,会创建多条记录。 - -### Q2: portrait 字段是否必须传递? - -**A**: 不是必须的。`portrait` 字段是可选的,只有在需要记录用户画像数据时才传递。 - -### Q3: sourceData 中可以存储哪些类型的数据? - -**A**: `sourceData` 是一个 JSON 对象,可以存储任意键值对。支持字符串、数字、布尔值等基本类型,嵌套对象会被序列化为 JSON 字符串。 - -### Q4: uniqueId 的作用是什么? - -**A**: `uniqueId` 用于防止重复记录。相同 `uniqueId` 的画像数据在半小时内会被合并统计,避免重复数据。 - -### Q5: 画像数据如何与用户关联? - -**A**: 系统会根据请求中的 `wechatId` 或 `phone` 自动匹配 `traffic_pool` 表中的用户,并将画像数据关联到对应的 `trafficPoolId`。 - ---- diff --git a/开发文档/三端需求业务对齐-小程序与API.md b/开发文档/三端需求业务对齐-小程序与API.md deleted file mode 100644 index 0ac9eb43..00000000 --- a/开发文档/三端需求业务对齐-小程序与API.md +++ /dev/null @@ -1,162 +0,0 @@ -# Soul 创业派对 - 三端需求业务对齐(小程序 ↔ API) - -> 供小程序、后端 API、管理端工程师需求与业务对齐使用。 -> 更新日期:2026-02-25 - ---- - -## 一、小程序功能模块总览 - -| 模块 | 页面 | 功能简述 | -|------|------|----------| -| **首页** | index | 精选推荐、最新章节、超级个体(VIP 展示)、跳转目录/搜索/找伙伴/我的 | -| **目录** | chapters | 全书目录、每日新增、跳转阅读/搜索 | -| **阅读** | read | 章节内容、权限判断、购买、分享、海报、推荐码 | -| **找伙伴** | match | 匹配配置、随机匹配、加入弹窗、购买匹配次数 | -| **我的** | my | 用户信息、收益、提现、VIP 状态、设置入口 | -| **分销中心** | referral | 绑定/访问/收益、提现、小程序码、分享 | -| **购买记录** | purchases | 当前用户订单列表 | -| **设置** | settings | 昵称/头像/手机/微信/支付宝、退出登录 | -| **地址管理** | addresses, edit | 收货地址 CRUD | -| **提现记录** | withdraw-records | 提现列表、确认收款 | -| **VIP** | vip | VIP 状态、购买、资料编辑 | -| **会员详情** | member-detail | 创业者详情(VIP/普通用户) | -| **搜索** | search | 热门、关键词搜索章节 | -| **关于** | about | 书籍统计、联系 | -| **协议** | agreement, privacy | 用户协议、隐私政策 | - ---- - -## 二、小程序 API 调用清单(按页面) - -### 2.1 已正确使用 `/api/miniprogram/*` 的接口 - -| 页面/模块 | 路径 | 方法 | 用途 | -|-----------|------|------|------| -| app | /api/miniprogram/referral/visit | POST | 推荐访问记录 | -| app | /api/miniprogram/referral/bind | POST | 推荐码绑定 | -| app | /api/miniprogram/book/all-chapters | GET | 书籍目录 | -| app | /api/miniprogram/login | POST | 微信登录 | -| app | /api/miniprogram/phone-login | POST | 手机号登录 | -| config | /api/miniprogram/config | GET | 免费章节、价格、功能开关 | -| read | /api/miniprogram/book/chapter/:id | GET | 按 id 获取章节 | -| read | /api/miniprogram/book/chapter/by-mid/:mid | GET | 按 mid 获取章节 | -| read | /api/miniprogram/user/purchase-status | GET | 购买状态 | -| read | /api/miniprogram/pay | POST | 支付下单 | -| read | /api/miniprogram/qrcode | POST | 生成小程序码 | -| index | /api/miniprogram/vip/members | GET | 超级个体列表 | -| index | /api/miniprogram/users | GET | 用户补充(limit=20) | -| index | /api/miniprogram/book/all-chapters | GET | 精选、最新 | -| chapters | /api/miniprogram/book/all-chapters | GET | 目录、每日新增 | -| search | /api/miniprogram/book/hot | GET | 热门搜索 | -| search | /api/miniprogram/book/search | GET | 关键词搜索 | -| about | /api/miniprogram/book/stats | GET | 书籍统计 | -| referral | /api/miniprogram/referral/data | GET | 分销数据 | -| referral | /api/miniprogram/qrcode | POST | 小程序码 | -| referral | /api/miniprogram/withdraw | POST | 提现申请 | -| my | /api/miniprogram/config | GET | 配置 | -| my | /api/miniprogram/withdraw/pending-confirm | GET | 待确认提现 | -| my | /api/miniprogram/earnings | GET | 收益 | -| my | /api/miniprogram/user/update | POST | 资料更新 | -| my | /api/miniprogram/vip/status | GET | VIP 状态 | -| settings | /api/miniprogram/user/profile | GET/POST | 资料 | -| settings | /api/miniprogram/user/update | POST | 更新 | -| settings | /api/miniprogram/phone | POST | 手机号 | -| addresses | /api/miniprogram/user/addresses | GET | 地址列表 | -| addresses | /api/miniprogram/user/addresses/:id | GET/PUT/DELETE | 地址 CRUD | -| addresses/edit | /api/miniprogram/user/addresses | POST | 新增地址 | -| withdraw-records | /api/miniprogram/withdraw/records | GET | 提现记录 | -| withdraw-records | /api/miniprogram/withdraw/confirm-info | GET | 确认收款信息 | -| vip | /api/miniprogram/vip/status | GET | VIP 状态 | -| vip | /api/miniprogram/vip/profile | GET/POST | VIP 资料 | -| vip | /api/miniprogram/pay | POST | VIP 购买 | -| member-detail | /api/miniprogram/vip/members | GET | 单个会员 | -| member-detail | /api/miniprogram/users | GET | 单个用户回退 | -| match | /api/miniprogram/ckb/join | POST | 加入弹窗 | -| match | /api/miniprogram/pay | POST | 购买匹配次数 | -| readingTracker | /api/miniprogram/user/reading-progress | POST | 阅读进度 | -| chapterAccessManager | /api/miniprogram/user/check-purchased | GET | 是否已购 | -| chapterAccessManager | /api/miniprogram/user/purchase-status | GET | 购买状态 | -| custom-tab-bar | /api/miniprogram/config | GET | 功能配置 | - -### 2.2 路径错误(违反边界:应改为 `/api/miniprogram/*`) - -| 页面 | 当前调用 | 正确路径 | 说明 | -|------|----------|----------|------| -| **match** | /api/match/config | /api/miniprogram/match/config | 匹配配置,soul-api 已挂 miniprogram | -| **match** | /api/match/users | /api/miniprogram/match/users | 匹配用户,soul-api 已挂 miniprogram | -| **match** | /api/ckb/match | /api/miniprogram/ckb/match | 上报匹配,soul-api 已挂 miniprogram | -| **purchases** | /api/orders?userId= | /api/miniprogram/orders?userId= | 订单列表,**需新增** miniprogram 路由 | -| **my** | /api/user/update | /api/miniprogram/user/update | 头像更新,soul-api 已挂 miniprogram | -| **my** | /api/withdraw | /api/miniprogram/withdraw | 提现申请,soul-api 已挂 miniprogram | - ---- - -## 三、后端 API 需变更项 - -### 3.1 小程序端需修正的调用(前端改) - -| 文件 | 当前 | 改为 | -|------|------|------| -| match.js | `/api/match/config` | `/api/miniprogram/match/config` | -| match.js | `/api/match/users` | `/api/miniprogram/match/users` | -| match.js | `/api/ckb/match` | `/api/miniprogram/ckb/match` | -| my.js | `/api/user/update` | `/api/miniprogram/user/update` | -| my.js | `/api/withdraw` | `/api/miniprogram/withdraw` | - -### 3.2 后端需新增/调整的接口 - -| 接口 | 变更类型 | 说明 | -|------|----------|------| -| **GET /api/miniprogram/orders** | **新增** | 购买记录页专用。当前 `/api/orders` 无 userId 过滤且返回 `orders`;小程序需 `?userId=` 过滤且期望 `data`。建议在 miniprogram 组新增 `MiniprogramOrders`:按 userId 过滤、返回 `{ success, data: [...] }`,字段含 id/order_sn、product_id、product_name、amount、status、created_at | - -### 3.3 响应格式对齐 - -| 接口 | 当前返回 | 小程序期望 | 建议 | -|------|----------|------------|------| -| /api/orders | `{ success, orders }` | `res.data` | 新增 MiniprogramOrders 返回 `{ success, data }`,与小程序一致 | - ---- - -## 四、soul-api 现有 miniprogram 路由(已挂载) - -``` -/api/miniprogram/config -/api/miniprogram/login, phone-login, phone -/api/miniprogram/pay, pay/notify -/api/miniprogram/qrcode, qrcode/image -/api/miniprogram/book/all-chapters, chapter/:id, chapter/by-mid/:mid, hot, search, stats -/api/miniprogram/referral/visit, bind, data -/api/miniprogram/earnings -/api/miniprogram/match/config -/api/miniprogram/match/users ← 注意:router 为 POST -/api/miniprogram/ckb/join -/api/miniprogram/ckb/match ← 已挂载 -/api/miniprogram/upload -/api/miniprogram/user/addresses, addresses/:id -/api/miniprogram/user/check-purchased, profile, purchase-status, reading-progress, update -/api/miniprogram/withdraw, withdraw/records, pending-confirm, confirm-received, confirm-info -/api/miniprogram/vip/status, vip/profile, vip/members -/api/miniprogram/users -``` - -**缺失**:`/api/miniprogram/orders`(需新增) - ---- - -## 五、变更任务分工建议 - -| 角色 | 任务 | -|------|------| -| **小程序** | 1. match.js:3 处路径改为 /api/miniprogram/*
2. my.js:2 处路径改为 /api/miniprogram/*
3. purchases.js:路径改为 /api/miniprogram/orders(待后端提供后) | -| **后端 API** | 1. 新增 MiniprogramOrders handler:GET,支持 ?userId=,返回 { success, data }
2. router 挂载 miniprogram.GET("/orders", handler.MiniprogramOrders)
3. ckb/match 已挂载,无需变更 | -| **管理端** | 无需因本次对齐变更;订单、提现、用户等管理接口保持现状 | - ---- - -## 六、附录:match 接口方法说明 - -- `GET /api/miniprogram/match/config`:匹配配置(matchTypes、freeMatchLimit、matchPrice) -- `POST /api/miniprogram/match/users`:执行匹配,入参 matchType、userId,返回匹配到的用户 - -当前 match.js 对 config 使用 `method: 'GET'`,对 users 使用 `method: 'POST'`,与后端一致。仅需将路径从 `/api/match/*` 改为 `/api/miniprogram/match/*`。 diff --git a/开发文档/列表标准与角色分工.md b/开发文档/列表标准与角色分工.md deleted file mode 100644 index 75bc3ddf..00000000 --- a/开发文档/列表标准与角色分工.md +++ /dev/null @@ -1,111 +0,0 @@ -# Soul 创业派对 - 列表标准与角色分工 - -> 供管理端开发者、API 开发者参考。基于 2026-02 列表缺陷排查经验归纳。 -> 更新日期:2026-02-25 - ---- - -## 一、标准列表应具备的能力 - -| 能力 | 说明 | 优先级 | -|------|------|--------| -| **搜索** | 关键词模糊搜索,建议 300ms 防抖 | 高 | -| **筛选** | 状态/类型/时间范围等 | 高 | -| **刷新** | 手动重新加载 | 高 | -| **分页** | 上一页/下一页、页码、每页条数(后端支持时) | 高 | -| **加载状态** | loading 或骨架屏 | 高 | -| **空状态** | 无数据时的提示 | 高 | -| **错误提示** | 加载失败时展示可关闭的提示条 | 高 | -| **排序** | 列头点击排序(可选) | 中 | -| **导出** | CSV/Excel(可选) | 中 | -| **批量操作** | 勾选多行后批量处理(可选) | 低 | - ---- - -## 二、角色分工 - -### 2.1 管理端开发者(soul-admin) - -**职责**:实现列表页面的交互与展示,对接 soul-api 的管理端接口。 - -**必做**: -- 搜索:使用 `useDebounce` 对输入做 300ms 防抖 -- 筛选:按业务提供下拉/按钮筛选 -- 刷新:提供刷新按钮,加载时禁用并显示 loading -- 加载状态:请求中显示 loading -- 空状态:无数据时显示友好提示 -- 错误提示:catch 后设置 error 状态,页面顶部展示可关闭的错误条(红底) - -**可选**: -- 导出:前端基于当前筛选结果生成 CSV(无需后端支持) -- 排序:前端内存排序或后端支持时传 sort 参数 - -**禁止**: -- 不得调用 `/api/miniprogram/*` -- 不得用原生 `alert`/`confirm` 替代错误提示(应使用页面内错误条或 Dialog) - -**参考**:`.cursor/skills/SKILL-管理端开发.md`、`soul-admin-boundary.mdc` - ---- - -### 2.2 API 开发者(soul-api) - -**职责**:为管理端列表提供分页、筛选、排序等能力。 - -**列表接口建议**: -- 分页:支持 `page`、`pageSize` 查询参数,返回 `total`、`records`/`list` -- 筛选:支持 `status`、`matchType`、`startDate`、`endDate` 等 -- 排序:支持 `sortBy`、`sortOrder`(asc/desc) - -**响应格式**: -```json -{ - "success": true, - "records": [...], - "total": 100, - "page": 1, - "pageSize": 10 -} -``` - -**错误**:失败时返回 `{ "success": false, "error": "..." }`,管理端据此展示错误条。 - -**参考**:`.cursor/skills/SKILL-API开发.md`、`soul-api.mdc` - ---- - -## 三、已补全项(2026-02-25) - -| 页面 | 补全内容 | -|------|----------| -| 用户管理 | 错误提示、搜索防抖、**分页、每页条数、VIP 筛选** | -| 订单管理 | 错误提示、刷新、导出 CSV、搜索防抖、**分页、每页条数、后端搜索** | -| 匹配记录 | 错误提示、**每页条数选择** | -| 分账提现 | 错误提示、**分页、每页条数** | -| 交易中心 | 错误提示、**分页(订单/绑定/提现子列表)** | -| 章节管理 | 错误提示、刷新 | - ---- - -## 四、后端分页支持(已实现) - -| 接口 | 分页参数 | 筛选/搜索 | -|------|----------|-----------| -| GET /api/db/users | page, pageSize | search, vip | -| GET /api/orders | page, pageSize | status, search | -| GET /api/admin/withdrawals | page, pageSize | status | -| GET /api/db/distribution | page, pageSize | status | -| GET /api/db/match-records | page, pageSize | matchType | - ---- - -## 五、检查清单(管理端新增列表时) - -- [ ] 分页(后端支持时接入 page、pageSize、total) -- [ ] 搜索有防抖(300ms) -- [ ] 有刷新按钮 -- [ ] 加载中显示 loading -- [ ] 无数据时显示空状态 -- [ ] 加载失败时展示错误条(可关闭) -- [ ] 仅调用 `/api/admin/*` 或 `/api/db/*` -- [ ] 不使用原生 alert 做错误提示 diff --git a/开发文档/小程序功能与管理端配置补齐分析.md b/开发文档/小程序功能与管理端配置补齐分析.md deleted file mode 100644 index 0e5f6786..00000000 --- a/开发文档/小程序功能与管理端配置补齐分析.md +++ /dev/null @@ -1,168 +0,0 @@ -# 小程序功能与管理端配置补齐分析 - -> 基于 miniprogram 功能分析,梳理需管理端补齐的配置与功能。 -> 更新日期:2026-02-25 -> **2026-02-25 已补齐**:mp_config 管理端、网站配置持久化、支付/二维码 POST、小程序 config 读取 - ---- - -## 一、小程序配置来源总览 - -| 配置类型 | 来源 | 管理端入口 | 状态 | -|----------|------|------------|------| -| 免费章节 | system_config.free_chapters | 系统设置 | ✅ 已有 | -| 价格 (section/fullbook) | chapter_config / site_settings | 系统设置 | ✅ 已有 | -| 功能开关 (match/referral/search/about) | feature_config | 系统设置 | ✅ 已有 | -| 找伙伴配置 | match_config | 找伙伴配置页 | ✅ 已有 | -| 推广/分销 | referral_config | 推广设置 | ✅ 已有 | -| 小程序专用 (mp_config) | mp_config | 系统设置 → 小程序配置 | ✅ 已补齐 | -| 订阅消息模板 ID | mp_config 或 app.js 兜底 | 系统设置 → 小程序配置 | ✅ 已补齐 | -| 微信支付商户号 | mp_config 或 app.js 兜底 | 系统设置 → 小程序配置 | ✅ 已补齐 | -| API 地址 (baseUrl) | app.js 硬编码 | 发版时改 baseUrl | 已移除配置 | -| 网站/站点配置 | site_config, page_config | 网站配置 | ✅ 已持久化 | - ---- - -## 二、小程序功能模块与配置依赖 - -### 2.1 核心配置接口:`GET /api/miniprogram/config` - -**返回字段**(来自 GetPublicDBConfig): - -| 字段 | 说明 | 管理端对应 | -|------|------|------------| -| freeChapters | 免费章节 ID 列表 | 系统设置 → 免费章节 | -| prices | { section, fullbook } | 系统设置 → 价格设置 | -| features | matchEnabled, referralEnabled, searchEnabled, aboutEnabled | 系统设置 → 功能开关 | -| mpConfig | appId, apiDomain, buyerDiscount, referralBindDays, minWithdraw | **无管理端** | -| userDiscount | 好友购买优惠 % | 推广设置 | - -### 2.2 找伙伴配置:`GET /api/miniprogram/match/config` - -| 字段 | 说明 | 管理端对应 | -|------|------|------------| -| matchTypes | 匹配类型列表 | 找伙伴配置页 | -| freeMatchLimit | 每日免费匹配次数 | 找伙伴配置页 | -| matchPrice | 单次匹配价格(元) | 找伙伴配置页 | -| settings | enableFreeMatches, enablePaidMatches, maxMatchesPerDay | 找伙伴配置页 | - -### 2.3 小程序 app.js 硬编码项 - -```javascript -// 当前硬编码,无法通过管理端修改 -baseUrl: 'http://localhost:8080', // 开发/生产需改代码 -appId: 'wxb8bbb2b10dec74aa', -withdrawSubscribeTmplId: 'u3MbZGPRkrZIk-...', // 提现订阅消息模板 -mchId: '1318592501', // 微信支付商户号 -``` - ---- - -## 三、管理端需补齐项(按优先级) - -### P0 - 必须补齐 - -| 项 | 说明 | 建议方案 | -|----|------|----------| -| **小程序专用配置 (mp_config)** | appId、apiDomain、minWithdraw 等,小程序从 config 读取 | 在「系统设置」或新建「小程序配置」卡片,支持编辑并写入 system_config.mp_config | -| **订阅消息模板 ID** | 提现申请需用户授权订阅,模板 ID 现硬编码 | 管理端增加「提现订阅模板 ID」配置,写入 mp_config 或单独 key;小程序启动时从 config 拉取 | -| **API 地址 (baseUrl)** | 开发/生产切换需改 app.js | 方案 A:从 mp_config.apiDomain 下发,小程序优先用接口返回值;方案 B:保留硬编码,仅文档说明切换方式 | - -### P1 - 建议补齐 - -| 项 | 说明 | 建议方案 | -|----|------|----------| -| **微信支付商户号** | 支付回调、对账依赖 mchId,现硬编码 | 管理端「支付配置」或「小程序配置」增加 mchId 字段;后端从配置读取,小程序可不改(支付由后端发起) | -| **网站配置持久化** | SitePage 当前保存仅前端状态,未调用后端 | 对接 POST /api/db/config,按 key 保存 site_config、page_config、menu_config | -| **支付/二维码配置持久化** | PaymentPage、QRCodesPage 使用 POST /api/config | soul-api 无 POST /api/config,需新增或改为 POST /api/db/config { key, value } | - -### P2 - 可选优化 - -| 项 | 说明 | 建议方案 | -|----|------|----------| -| **referral_config 的 withdrawFee** | 文档有提现手续费,ReferralSettingsPage 未展示 | 若业务需要,在推广设置页增加「提现手续费」字段 | -| **主题色/品牌色** | app.js theme 硬编码 | 若需多端统一,可从 site_config 或 mp_config 下发 | - ---- - -## 四、配置与 system_config 键名映射 - -| system_config.config_key | 管理端页面 | 说明 | -|--------------------------|------------|------| -| free_chapters | 系统设置 | 免费章节 ID 数组 | -| feature_config | 系统设置 | 功能开关对象 | -| site_settings | 系统设置 | 价格、作者信息 | -| chapter_config | (可选) | 合并 freeChapters + prices,GetPublicDBConfig 优先用 | -| match_config | 找伙伴配置 | 匹配类型、免费次数、价格 | -| referral_config | 推广设置 | 分销比例、提现门槛、绑定期等 | -| mp_config | **待新增** | 小程序专用:appId, apiDomain, withdrawSubscribeTmplId, mchId 等 | -| site_config | 网站配置 | 站点名称、logo 等(需持久化) | -| page_config | 网站配置 | 页面标题(需持久化) | -| menu_config | 网站配置 | 菜单开关(需持久化) | -| payment_methods | 支付配置 | 微信/支付宝活码等(需确认 POST 接口) | -| live_qr_codes | 二维码管理 | 群活码(需确认 POST 接口) | - ---- - -## 五、接口与数据流检查 - -### 5.1 管理端调用与后端支持 - -| 管理端页面 | 调用 | 后端支持 | 备注 | -|------------|------|----------|------| -| 系统设置 | GET/POST /api/admin/settings | ✅ | 写入 free_chapters, feature_config, site_settings | -| 推广设置 | GET/POST /api/admin/referral-settings | ✅ | 写入 referral_config | -| 找伙伴配置 | GET /api/db/config/full?key=match_config | ✅ | 需 AdminAuth | -| 找伙伴配置 | POST /api/db/config | ✅ | body: { key: 'match_config', value: {...} } | -| 支付配置 | GET/POST /api/config | ⚠️ | GET 有,POST 无;需新增或改用 db/config | -| 网站配置 | GET /api/config | ⚠️ | GET 有,保存未对接 | -| 二维码管理 | GET/POST /api/config | ⚠️ | 同上 | - -### 5.2 小程序读取链 - -``` -小程序 onLoad / custom-tab-bar - → GET /api/miniprogram/config - → GetPublicDBConfig - → 读取 system_config: chapter_config, free_chapters, feature_config, mp_config, referral_config - → 返回 freeChapters, prices, features, mpConfig, userDiscount -``` - ---- - -## 六、实施建议(管理端开发任务) - -### 任务 1:新增「小程序配置」区块(P0) - -- **位置**:系统设置页新增卡片,或独立「小程序配置」页 -- **字段**: - - API 域名 (apiDomain):如 `https://soulapi.quwanzhi.com` - - 小程序 AppID (appId):如 `wxb8bbb2b10dec74aa` - - 提现订阅模板 ID (withdrawSubscribeTmplId) - - 微信支付商户号 (mchId)(可选,后端也可用 env) - - 最低提现金额 (minWithdraw)(可与 referral_config 同步) -- **存储**:POST /api/admin/settings 扩展,或 POST /api/db/config { key: 'mp_config', value: {...} } -- **小程序**:app.js 启动时请求 config,若 mp_config 存在则覆盖 baseUrl;withdrawSubscribeTmplId 从 config 取 - -### 任务 2:网站配置持久化(P1) - -- SitePage 保存时调用 POST /api/db/config,按 key 分别保存 site_config、page_config、menu_config -- 或扩展 AdminSettingsPost 支持 site_config 等 - -### 任务 3:支付/二维码配置接口(P1) - -- 方案 A:新增 POST /api/admin/config,支持 payment_methods、live_qr_codes 等 key -- 方案 B:PaymentPage、QRCodesPage 改为调用 POST /api/db/config,body: { key, value } - ---- - -## 七、附录:小程序页面与配置使用 - -| 页面 | 使用的配置 | 接口 | -|------|------------|------| -| custom-tab-bar | features.matchEnabled | GET /api/miniprogram/config | -| 阅读 read | freeChapters, prices | GET /api/miniprogram/config (chapterAccessManager) | -| 找伙伴 match | matchTypes, freeMatchLimit, matchPrice | GET /api/miniprogram/match/config | -| 我的 my | features, 收益/提现规则 | GET /api/miniprogram/config, referral/data | -| 分销 referral | shareRate, minWithdraw, bindingDays | GET /api/miniprogram/referral/data | -| 支付流程 | mchId (后端), openId | app.js 硬编码 + 后端 env | diff --git a/开发文档/小程序管理/SKILL.md b/开发文档/小程序管理/SKILL.md deleted file mode 100644 index 4645ec85..00000000 --- a/开发文档/小程序管理/SKILL.md +++ /dev/null @@ -1,1797 +0,0 @@ -# 小程序管理技能 v3.0 - -> 📅 创建日期:2026-01-25 -> 📅 更新日期:2026-01-25(v3.0 全能版) -> 📋 通过微信开放平台API完整管理小程序的全生命周期:申请、认证、开发、审核、发布、运营 -> 🚀 支持多小程序管理、一键部署、自动认证检查、汇总报告 - ---- - -## 🎯 能力全景图 - -``` -╔══════════════════════════════════════════════════════════════════════════════╗ -║ 小程序管理技能 v3.0 能力全景图 ║ -╠══════════════════════════════════════════════════════════════════════════════╣ -║ ║ -║ ┌─────────────────────────────────────────────────────────────────────┐ ║ -║ │ 🔧 工具整合层 │ ║ -║ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌───────────┐ │ ║ -║ │ │ 微信开发者 │ │ miniprogram │ │ 开放平台 │ │ GitHub │ │ ║ -║ │ │ 工具 CLI │ │ -ci (npm) │ │ API │ │ Actions │ │ ║ -║ │ └─────────────┘ └─────────────┘ └─────────────┘ └───────────┘ │ ║ -║ └─────────────────────────────────────────────────────────────────────┘ ║ -║ │ ║ -║ ▼ ║ -║ ┌─────────────────────────────────────────────────────────────────────┐ ║ -║ │ 📦 核心功能层 │ ║ -║ │ │ ║ -║ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ ║ -║ │ │ 多小程序 │ │ 项目 │ │ 一键 │ │ 汇总 │ │ ║ -║ │ │ 管理 │ │ 检查 │ │ 部署 │ │ 报告 │ │ ║ -║ │ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │ ║ -║ │ │ ║ -║ └─────────────────────────────────────────────────────────────────────┘ ║ -║ │ ║ -║ ▼ ║ -║ ┌─────────────────────────────────────────────────────────────────────┐ ║ -║ │ 🚀 部署流程 │ ║ -║ │ │ ║ -║ │ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ │ ║ -║ │ │ 检查 │ → │ 编译 │ → │ 上传 │ → │ 提审 │ → │ 审核 │ → │ 发布 │ │ ║ -║ │ │check │ │build │ │upload│ │audit │ │wait │ │release│ │ ║ -║ │ └──────┘ └──────┘ └──────┘ └──────┘ └──────┘ └──────┘ │ ║ -║ │ │ │ │ │ │ │ │ ║ -║ │ ▼ ▼ ▼ ▼ ▼ ▼ │ ║ -║ │ 自动化 自动化 自动化 自动化 等待 手动/自动 │ ║ -║ │ 1-7天 │ ║ -║ └─────────────────────────────────────────────────────────────────────┘ ║ -║ ║ -╚══════════════════════════════════════════════════════════════════════════════╝ -``` - ---- - -## 📊 命令速查表 - -| 命令 | 说明 | 示例 | -|------|------|------| -| `mp_full.py report` | 生成所有小程序汇总报告 | `python3 mp_full.py report` | -| `mp_full.py check` | 检查项目问题 | `python3 mp_full.py check soul-party` | -| `mp_full.py auto` | 全自动部署(上传+提审) | `python3 mp_full.py auto soul-party` | -| `mp_deploy.py list` | 列出所有小程序 | `python3 mp_deploy.py list` | -| `mp_deploy.py add` | 添加新小程序 | `python3 mp_deploy.py add` | -| `mp_deploy.py cert-status` | 查询认证状态 | `python3 mp_deploy.py cert-status soul-party` | -| `mp_deploy.py cert-done` | 标记认证完成 | `python3 mp_deploy.py cert-done soul-party` | -| `mp_deploy.py release` | 发布上线 | `python3 mp_deploy.py release soul-party` | - ---- - -## 🎯 技能概述 - -本技能用于通过API实现微信小程序的完整管理,包括: - -### 核心能力 - -| 阶段 | 能力 | 说明 | -|------|------|------| -| **申请** | 快速注册小程序 | 复用公众号主体资质,无需300元认证费 | -| **认证** | 企业认证管理 | 自动检查认证状态、提醒过期、材料管理 | -| **配置** | 基础信息设置 | 名称、头像、介绍、类目管理 | -| **开发** | 代码管理 | 上传代码、生成体验版 | -| **审核** | 提审发布 | 提交审核、查询状态、撤回、发布 | -| **运营** | 接口管理 | 域名配置、隐私协议、接口权限 | -| **推广** | 小程序码 | 生成无限量小程序码 | -| **数据** | 数据分析 | 访问数据、用户画像 | - -### v2.0 新增能力 - -| 能力 | 命令 | 说明 | -|------|------|------| -| **多小程序管理** | `mp_deploy.py list` | 统一管理多个小程序 | -| **一键部署** | `mp_deploy.py deploy ` | 编译→上传→提审一步完成 | -| **认证管理** | `mp_deploy.py cert ` | 认证状态检查、材料管理 | -| **快速上传** | `mp_deploy.py upload ` | 快速上传代码到开发版 | - -### 开源工具集成 - -| 工具 | 用途 | 安装方式 | -|------|------|----------| -| **miniprogram-ci** | 微信官方CI工具 | `npm install miniprogram-ci -g` | -| **微信开发者工具CLI** | 本地编译上传 | 安装开发者工具自带 | -| **multi-mini-ci** | 多平台小程序上传 | GitHub开源 | - ---- - -## 🚀 触发词 - -- 管理小程序 -- 小程序申请 -- 小程序审核 -- 小程序发布 -- 上传小程序代码 -- 配置小程序域名 -- 生成小程序码 -- 查看小程序状态 - ---- - -## 🏗️ 技术架构 - -### 管理方式对比 - -| 方式 | 优点 | 缺点 | 适用场景 | -|------|------|------|----------| -| **微信后台手动操作** | 无需开发 | 效率低,无法批量 | 单个小程序 | -| **微信开发者工具CLI** | 简单易用 | 功能有限 | 开发测试 | -| **开放平台API(本方案)** | 功能完整、可自动化 | 需要开发 | 批量管理、自动化 | - -### 整体架构 - -``` -┌─────────────────────────────────────────────────────────────────────────────┐ -│ 小程序管理引擎 v1.0 │ -├─────────────────────────────────────────────────────────────────────────────┤ -│ │ -│ ┌─────────────────────────────────────────────────────────────────────┐ │ -│ │ 第一层:认证层 │ │ -│ │ ┌───────────────┐ ┌───────────────┐ ┌───────────────┐ │ │ -│ │ │ 第三方平台 │ │ component_ │ │ authorizer_ │ │ │ -│ │ │ 认证信息 │ → │ access_token │ → │ access_token │ │ │ -│ │ └───────────────┘ └───────────────┘ └───────────────┘ │ │ -│ └─────────────────────────────────────────────────────────────────────┘ │ -│ ↓ │ -│ ┌─────────────────────────────────────────────────────────────────────┐ │ -│ │ 第二层:管理API层 │ │ -│ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │ -│ │ │ 注册 │ │ 配置 │ │ 代码 │ │ 审核 │ │ 运营 │ │ │ -│ │ │ 管理 │ │ 管理 │ │ 管理 │ │ 管理 │ │ 管理 │ │ │ -│ │ └─────────┘ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │ │ -│ └─────────────────────────────────────────────────────────────────────┘ │ -│ ↓ │ -│ ┌─────────────────────────────────────────────────────────────────────┐ │ -│ │ 第三层:本地CLI层 │ │ -│ │ ┌───────────────┐ ┌───────────────┐ ┌───────────────┐ │ │ -│ │ │ mp_manager.py │ │ 微信开发者 │ │ 自动化脚本 │ │ │ -│ │ │ Python CLI │ │ 工具 CLI │ │ Shell │ │ │ -│ │ └───────────────┘ └───────────────┘ └───────────────┘ │ │ -│ └─────────────────────────────────────────────────────────────────────┘ │ -│ │ -└─────────────────────────────────────────────────────────────────────────────┘ -``` - ---- - -## 📋 前置条件 - -### 1. 微信开放平台账号 - -- 注册地址:https://open.weixin.qq.com/ -- 完成开发者资质认证(需企业资质) - -### 2. 创建第三方平台 - -登录开放平台后台 → 管理中心 → 第三方平台 → 创建 - -**必填信息**: -- 平台名称 -- 服务类型(选择"平台型"可管理多个小程序) -- 授权发起页域名 -- 消息与事件接收URL - -### 3. 获取关键凭证 - -| 凭证 | 说明 | 获取方式 | -|------|------|----------| -| `component_appid` | 第三方平台AppID | 开放平台后台 | -| `component_appsecret` | 第三方平台密钥 | 开放平台后台 | -| `component_verify_ticket` | 验证票据 | 微信每10分钟推送 | -| `component_access_token` | 平台调用凭证 | API获取,2小时有效 | -| `authorizer_access_token` | 授权方调用凭证 | API获取,2小时有效 | - ---- - -## 🔑 认证流程 - -### 获取 component_access_token - -```python -# POST https://api.weixin.qq.com/cgi-bin/component/api_component_token -{ - "component_appid": "你的第三方平台AppID", - "component_appsecret": "你的第三方平台密钥", - "component_verify_ticket": "微信推送的验证票据" -} - -# 返回 -{ - "component_access_token": "xxxx", - "expires_in": 7200 -} -``` - -### 获取预授权码 - -```python -# POST https://api.weixin.qq.com/cgi-bin/component/api_create_preauthcode -{ - "component_appid": "你的第三方平台AppID" -} - -# 返回 -{ - "pre_auth_code": "xxxx", - "expires_in": 600 -} -``` - -### 引导用户授权 - -``` -https://mp.weixin.qq.com/cgi-bin/componentloginpage? -component_appid=第三方平台AppID& -pre_auth_code=预授权码& -redirect_uri=授权回调地址& -auth_type=1 # 1=仅小程序,2=仅公众号,3=两者都可 -``` - -### 获取 authorizer_access_token - -```python -# POST https://api.weixin.qq.com/cgi-bin/component/api_query_auth -{ - "component_appid": "第三方平台AppID", - "authorization_code": "授权回调返回的code" -} - -# 返回 -{ - "authorization_info": { - "authorizer_appid": "授权方AppID", - "authorizer_access_token": "授权方调用凭证", - "expires_in": 7200, - "authorizer_refresh_token": "刷新令牌" - } -} -``` - ---- - -## 📱 核心API接口 - -### 一、小程序注册 - -#### 1.1 复用公众号资质快速注册 - -**前提**:已有认证的公众号 - -```python -# POST https://api.weixin.qq.com/cgi-bin/account/fastregister?access_token=ACCESS_TOKEN -{ - "ticket": "公众号扫码授权的ticket" -} - -# 返回 -{ - "errcode": 0, - "errmsg": "ok", - "appid": "新注册的小程序AppID", - "authorization_code": "授权码" -} -``` - -**优势**: -- 无需重新提交主体材料 -- 无需对公打款 -- 无需支付300元认证费 - -**限制**: -- 非个体户:每月可注册5个 -- 个体户:每月可注册1个 - -#### 1.2 快速注册企业小程序 - -**前提**:有企业营业执照 - -```python -# POST https://api.weixin.qq.com/cgi-bin/component/fastregisterminiprogram -{ - "name": "小程序名称", - "code": "统一社会信用代码", - "code_type": 1, # 1=营业执照 - "legal_persona_wechat": "法人微信号", - "legal_persona_name": "法人姓名", - "component_phone": "联系电话" -} -``` - ---- - -### 二、基础信息配置 - -#### 2.1 获取基础信息 - -```python -# POST https://api.weixin.qq.com/cgi-bin/account/getaccountbasicinfo -# 无请求参数 - -# 返回 -{ - "appid": "小程序AppID", - "account_type": 2, # 2=小程序 - "principal_type": 1, # 1=企业 - "principal_name": "主体名称", - "realname_status": 1, # 1=已认证 - "nickname": "小程序名称", - "head_image_url": "头像URL", - "signature": "简介" -} -``` - -#### 2.2 修改名称 - -```python -# POST https://api.weixin.qq.com/wxa/setnickname?access_token=ACCESS_TOKEN -{ - "nick_name": "新名称", - "id_card": "管理员身份证号", - "license": "营业执照media_id", # 需要先上传 - "naming_other_stuff_1": "其他证明material_id" # 可选 -} -``` - -#### 2.3 修改头像 - -```python -# POST https://api.weixin.qq.com/cgi-bin/account/modifyheadimage?access_token=ACCESS_TOKEN -{ - "head_img_media_id": "头像图片media_id", # 需要先上传 - "x1": 0, "y1": 0, "x2": 1, "y2": 1 # 裁剪区域 -} -``` - -#### 2.4 修改简介 - -```python -# POST https://api.weixin.qq.com/cgi-bin/account/modifysignature?access_token=ACCESS_TOKEN -{ - "signature": "新的简介内容" # 4-120字 -} -``` - ---- - -### 三、类目管理 - -#### 3.1 获取可选类目 - -```python -# GET https://api.weixin.qq.com/cgi-bin/wxopen/getallcategories?access_token=ACCESS_TOKEN -``` - -#### 3.2 获取已设置类目 - -```python -# GET https://api.weixin.qq.com/cgi-bin/wxopen/getcategory?access_token=ACCESS_TOKEN -``` - -#### 3.3 添加类目 - -```python -# POST https://api.weixin.qq.com/cgi-bin/wxopen/addcategory?access_token=ACCESS_TOKEN -{ - "categories": [ - { - "first": 1, # 一级类目ID - "second": 2, # 二级类目ID - "certicates": [ # 资质证明 - {"key": "资质名称", "value": "media_id"} - ] - } - ] -} -``` - -#### 3.4 删除类目 - -```python -# POST https://api.weixin.qq.com/cgi-bin/wxopen/deletecategory?access_token=ACCESS_TOKEN -{ - "first": 1, - "second": 2 -} -``` - ---- - -### 四、域名配置 - -#### 4.1 设置服务器域名 - -```python -# POST https://api.weixin.qq.com/wxa/modify_domain?access_token=ACCESS_TOKEN -{ - "action": "set", # add/delete/set/get - "requestdomain": ["https://api.example.com"], - "wsrequestdomain": ["wss://ws.example.com"], - "uploaddomain": ["https://upload.example.com"], - "downloaddomain": ["https://download.example.com"], - "udpdomain": ["udp://udp.example.com"], - "tcpdomain": ["tcp://tcp.example.com"] -} -``` - -#### 4.2 设置业务域名 - -```python -# POST https://api.weixin.qq.com/wxa/setwebviewdomain?access_token=ACCESS_TOKEN -{ - "action": "set", # add/delete/set/get - "webviewdomain": ["https://web.example.com"] -} -``` - ---- - -### 五、隐私协议配置 - -#### 5.1 获取隐私协议设置 - -```python -# POST https://api.weixin.qq.com/cgi-bin/component/getprivacysetting?access_token=ACCESS_TOKEN -{ - "privacy_ver": 2 # 1=当前版本,2=开发版本 -} -``` - -#### 5.2 设置隐私协议 - -```python -# POST https://api.weixin.qq.com/cgi-bin/component/setprivacysetting?access_token=ACCESS_TOKEN -{ - "privacy_ver": 2, - "setting_list": [ - { - "privacy_key": "UserInfo", - "privacy_text": "用于展示用户头像和昵称" - }, - { - "privacy_key": "Location", - "privacy_text": "用于获取您的位置信息以推荐附近服务" - }, - { - "privacy_key": "PhoneNumber", - "privacy_text": "用于登录验证和订单通知" - } - ], - "owner_setting": { - "contact_email": "contact@example.com", - "contact_phone": "15880802661", - "notice_method": "弹窗提示" - } -} -``` - -**常用隐私字段**: - -| privacy_key | 说明 | -|-------------|------| -| `UserInfo` | 用户信息(头像、昵称) | -| `Location` | 地理位置 | -| `PhoneNumber` | 手机号 | -| `Album` | 相册 | -| `Camera` | 相机 | -| `Record` | 麦克风 | -| `Clipboard` | 剪切板 | -| `MessageFile` | 微信消息中的文件 | -| `ChooseAddress` | 收货地址 | -| `BluetoothInfo` | 蓝牙 | - ---- - -### 六、代码管理 - -#### 6.1 上传代码 - -```python -# POST https://api.weixin.qq.com/wxa/commit?access_token=ACCESS_TOKEN -{ - "template_id": 1, # 代码模板ID - "ext_json": "{\"extAppid\":\"授权方AppID\",\"ext\":{}}", - "user_version": "1.0.0", - "user_desc": "版本描述" -} -``` - -**注意**:需要先在第三方平台创建代码模板 - -#### 6.2 获取体验版二维码 - -```python -# GET https://api.weixin.qq.com/wxa/get_qrcode?access_token=ACCESS_TOKEN&path=pages/index/index -# 返回二维码图片 -``` - -#### 6.3 获取已上传的代码页面列表 - -```python -# GET https://api.weixin.qq.com/wxa/get_page?access_token=ACCESS_TOKEN - -# 返回 -{ - "errcode": 0, - "page_list": ["pages/index/index", "pages/my/my"] -} -``` - ---- - -### 七、审核管理 - -#### 7.1 提交审核 - -```python -# POST https://api.weixin.qq.com/wxa/submit_audit?access_token=ACCESS_TOKEN -{ - "item_list": [ - { - "address": "pages/index/index", - "tag": "电子书 阅读 创业", - "first_class": "教育", - "second_class": "在线教育", - "first_id": 1, - "second_id": 2, - "title": "首页" - } - ], - "preview_info": { - "video_id_list": [], - "pic_id_list": [] - }, - "version_desc": "版本说明", - "feedback_info": "反馈内容", - "feedback_stuff": "media_id" # 反馈附件 -} -``` - -#### 7.2 查询审核状态 - -```python -# POST https://api.weixin.qq.com/wxa/get_auditstatus?access_token=ACCESS_TOKEN -{ - "auditid": 1234567890 -} - -# 返回 -{ - "errcode": 0, - "status": 0, # 0=审核成功,1=审核被拒,2=审核中,3=已撤回,4=审核延后 - "reason": "拒绝原因", # status=1时返回 - "screenshot": "截图" -} -``` - -#### 7.3 查询最新审核状态 - -```python -# GET https://api.weixin.qq.com/wxa/get_latest_auditstatus?access_token=ACCESS_TOKEN -``` - -#### 7.4 撤回审核 - -```python -# GET https://api.weixin.qq.com/wxa/undocodeaudit?access_token=ACCESS_TOKEN -``` - -**限制**:单个小程序每天只能撤回1次 - ---- - -### 八、发布管理 - -#### 8.1 发布已审核通过的版本 - -```python -# POST https://api.weixin.qq.com/wxa/release?access_token=ACCESS_TOKEN -{} # 无请求参数 - -# 返回 -{ - "errcode": 0, - "errmsg": "ok" -} -``` - -#### 8.2 版本回退 - -```python -# GET https://api.weixin.qq.com/wxa/revertcoderelease?access_token=ACCESS_TOKEN -``` - -**限制**:只能回退到上一个版本,且只能回退一次 - -#### 8.3 获取可回退版本历史 - -```python -# GET https://api.weixin.qq.com/wxa/revertcoderelease?access_token=ACCESS_TOKEN&action=get_history_version -``` - -#### 8.4 分阶段发布 - -```python -# POST https://api.weixin.qq.com/wxa/grayrelease?access_token=ACCESS_TOKEN -{ - "gray_percentage": 10 # 灰度比例 1-100 -} -``` - ---- - -### 九、小程序码生成 - -#### 9.1 获取小程序码(有限制) - -```python -# POST https://api.weixin.qq.com/wxa/getwxacode?access_token=ACCESS_TOKEN -{ - "path": "pages/index/index?scene=123", - "width": 430, - "auto_color": false, - "line_color": {"r": 0, "g": 0, "b": 0}, - "is_hyaline": false # 是否透明背景 -} -# 返回图片二进制 -``` - -**限制**:每个path只能生成10万个 - -#### 9.2 获取无限小程序码(推荐) - -```python -# POST https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=ACCESS_TOKEN -{ - "scene": "user_id=123&from=share", # 最长32字符 - "page": "pages/index/index", # 必须是已发布的页面 - "width": 430, - "auto_color": false, - "line_color": {"r": 0, "g": 0, "b": 0}, - "is_hyaline": false -} -# 返回图片二进制 -``` - -**注意**:scene参数需要在小程序中用`onLoad(options)`解析 - -#### 9.3 生成小程序短链接 - -```python -# POST https://api.weixin.qq.com/wxa/genwxashortlink?access_token=ACCESS_TOKEN -{ - "page_url": "pages/index/index?id=123", - "page_title": "页面标题", - "is_permanent": false # 是否永久有效 -} - -# 返回 -{ - "errcode": 0, - "link": "https://wxaurl.cn/xxxx" -} -``` - ---- - -### 十、接口权限管理 - -#### 10.1 查询接口调用额度 - -```python -# POST https://api.weixin.qq.com/cgi-bin/openapi/quota/get?access_token=ACCESS_TOKEN -{ - "cgi_path": "/wxa/getwxacode" -} - -# 返回 -{ - "quota": { - "daily_limit": 100000, - "used": 500, - "remain": 99500 - } -} -``` - -#### 10.2 重置接口调用次数 - -```python -# POST https://api.weixin.qq.com/cgi-bin/clear_quota?access_token=ACCESS_TOKEN -{ - "appid": "小程序AppID" -} -``` - -**限制**:每月只能重置10次 - ---- - -### 十一、数据分析 - -#### 11.1 获取访问趋势 - -```python -# POST https://api.weixin.qq.com/datacube/getweanalysisappiddailyvisittrend?access_token=ACCESS_TOKEN -{ - "begin_date": "20260101", - "end_date": "20260125" -} - -# 返回 -{ - "list": [ - { - "ref_date": "20260125", - "session_cnt": 1000, # 打开次数 - "visit_pv": 5000, # 访问次数 - "visit_uv": 800, # 访问人数 - "visit_uv_new": 100, # 新用户数 - "stay_time_uv": 120.5, # 人均停留时长(秒) - "stay_time_session": 60.2 # 次均停留时长(秒) - } - ] -} -``` - -#### 11.2 获取用户画像 - -```python -# POST https://api.weixin.qq.com/datacube/getweanalysisappiduserportrait?access_token=ACCESS_TOKEN -{ - "begin_date": "20260101", - "end_date": "20260125" -} -``` - ---- - -## 🛠️ 快速使用 - -### 方式一:使用Python管理脚本(推荐) - -```bash -# 进入脚本目录 -cd /Users/karuo/Documents/个人/卡若AI/02_卡人(水)/小程序管理/scripts - -# 安装依赖 -pip install httpx python-dotenv - -# 配置凭证 -cp .env.example .env -# 编辑 .env 填入你的凭证 - -# 使用命令行工具 -python mp_manager.py status # 查看小程序状态 -python mp_manager.py audit # 查看审核状态 -python mp_manager.py release # 发布上线 -python mp_manager.py qrcode # 生成小程序码 -``` - -### 方式二:使用微信开发者工具CLI - -```bash -# CLI路径 -CLI="/Applications/wechatwebdevtools.app/Contents/MacOS/cli" - -# 打开项目 -$CLI -o "/path/to/miniprogram" - -# 编译 -$CLI build-npm --project "/path/to/miniprogram" - -# 预览(生成二维码) -$CLI preview --project "/path/to/miniprogram" --qr-format image --qr-output preview.png - -# 上传代码 -$CLI upload --project "/path/to/miniprogram" --version "1.0.0" --desc "版本说明" - -# 提交审核 -$CLI submit-audit --project "/path/to/miniprogram" -``` - -### 方式三:直接调用API - -```python -import httpx - -# 配置 -ACCESS_TOKEN = "你的access_token" -BASE_URL = "https://api.weixin.qq.com" - -async def check_audit_status(auditid: int): - """查询审核状态""" - async with httpx.AsyncClient() as client: - resp = await client.post( - f"{BASE_URL}/wxa/get_auditstatus?access_token={ACCESS_TOKEN}", - json={"auditid": auditid} - ) - return resp.json() - -# 使用 -result = await check_audit_status(1234567890) -print(result) -``` - ---- - -## 📁 文件结构 - -``` -小程序管理/ -├── SKILL.md # 技能说明文档(本文件) -├── scripts/ -│ ├── mp_manager.py # 小程序管理CLI工具 -│ ├── mp_api.py # API封装类 -│ ├── requirements.txt # Python依赖 -│ └── .env.example # 环境变量模板 -└── references/ - ├── API接口速查表.md # 常用API速查 - ├── 隐私协议填写指南.md # 隐私协议配置指南 - └── 审核规范.md # 审核常见问题 -``` - ---- - -## ⚠️ 常见问题 - -### Q1: 如何获取 component_verify_ticket? - -微信会每10分钟向你配置的"消息与事件接收URL"推送。你需要部署一个服务来接收并存储它。 - -```python -# 接收推送示例 -@app.post("/callback") -async def receive_ticket(request: Request): - xml_data = await request.body() - # 解密并解析XML - # 提取 ComponentVerifyTicket - # 存储到Redis或数据库 - return "success" -``` - -### Q2: 审核被拒常见原因? - -| 原因 | 解决方案 | -|------|----------| -| 类目不符 | 确保小程序功能与所选类目一致 | -| 隐私协议缺失 | 配置完整的隐私保护指引 | -| 诱导分享 | 移除"分享到群获取xx"等诱导文案 | -| 虚拟支付 | iOS不能使用虚拟支付,需走IAP | -| 内容违规 | 检查文案、图片是否合规 | -| 功能不完整 | 确保所有页面功能正常 | - -### Q3: 审核需要多长时间? - -- 首次提审:1-7个工作日 -- 非首次:1-3个工作日 -- 加急审核:付费服务,24小时内 - -### Q4: 如何提高审核通过率? - -1. **提交完整测试账号**:如需登录才能体验功能 -2. **录制操作视频**:复杂功能建议附上操作视频 -3. **详细的版本描述**:说明本次更新内容 -4. **完善隐私协议**:所有收集数据的接口都要说明用途 - -### Q5: 代码模板是什么? - -第三方平台需要先将小程序代码上传到"草稿箱",再添加到"代码模板库"。之后可以用这个模板批量部署到多个小程序。 - -流程:开发完成 → 上传到草稿箱 → 添加到模板库 → 使用模板部署 - ---- - -## 🔗 官方文档 - -- [微信开放平台文档](https://developers.weixin.qq.com/doc/oplatform/) -- [第三方平台开发指南](https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/2.0/getting_started/how_to_read.html) -- [小程序管理接口](https://developers.weixin.qq.com/doc/oplatform/openApi/OpenApiDoc/) -- [代码管理接口](https://developers.weixin.qq.com/doc/oplatform/openApi/OpenApiDoc/miniprogram-management/code-management/commit.html) -- [隐私协议开发指南](https://developers.weixin.qq.com/miniprogram/dev/framework/user-privacy/) - ---- - -## 📊 当前项目配置 - -### Soul派对小程序 - -| 项目 | 配置值 | -|------|--------| -| **AppID** | `wxb8bbb2b10dec74aa` | -| **项目路径** | `/Users/karuo/Documents/开发/3、自营项目/一场soul的创业实验/miniprogram` | -| **API域名** | `https://soul.quwanzhi.com` | -| **当前版本** | `1.0.13` | -| **认证状态** | ⏳ 审核中(等待1-5工作日) | -| **检查结果** | ✅ 8项通过 / ⚠️ 2项警告 / ❌ 0项错误 | -| **可上传** | ✅ 是 | -| **可发布** | ❌ 需等待认证通过 | - -### 快速命令 - -```bash -# 打开项目 -/Applications/wechatwebdevtools.app/Contents/MacOS/cli -o "/Users/karuo/Documents/开发/3、自营项目/一场soul的创业实验/miniprogram" - -# 预览 -/Applications/wechatwebdevtools.app/Contents/MacOS/cli preview --project "/Users/karuo/Documents/开发/3、自营项目/一场soul的创业实验/miniprogram" --qr-format image --qr-output preview.png - -# 上传 -/Applications/wechatwebdevtools.app/Contents/MacOS/cli upload --project "/Users/karuo/Documents/开发/3、自营项目/一场soul的创业实验/miniprogram" --version "1.0.0" --desc "版本说明" -``` - ---- - -## 🚀 全自动部署流程(v3.0) - -### 完整生命周期流程图 - -``` -╔══════════════════════════════════════════════════════════════════════════════╗ -║ 小程序完整生命周期管理 ║ -╠══════════════════════════════════════════════════════════════════════════════╣ -║ ║ -║ 阶段一:准备阶段 ║ -║ ┌─────────────────────────────────────────────────────────────────────┐ ║ -║ │ │ ║ -║ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ ║ -║ │ │ 注册小程序│ → │ 企业认证 │ → │ 配置项目 │ │ ║ -║ │ │ (微信后台)│ │ (300元/年)│ │ (添加到管理)│ │ ║ -║ │ └──────────┘ └──────────┘ └──────────┘ │ ║ -║ │ │ │ │ │ ║ -║ │ │ │ ▼ │ ║ -║ │ │ │ mp_deploy.py add │ ║ -║ │ │ ▼ │ ║ -║ │ │ 等待审核 1-5 天 │ ║ -║ │ │ mp_deploy.py cert-done │ ║ -║ │ │ ║ -║ └─────────────────────────────────────────────────────────────────────┘ ║ -║ │ ║ -║ ▼ ║ -║ 阶段二:开发阶段 ║ -║ ┌─────────────────────────────────────────────────────────────────────┐ ║ -║ │ │ ║ -║ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ ║ -║ │ │ 编写代码 │ → │ 本地测试 │ → │ 项目检查 │ │ ║ -║ │ │ (开发者) │ │ (模拟器) │ │ mp_full │ │ ║ -║ │ └──────────┘ └──────────┘ └──────────┘ │ ║ -║ │ │ │ ║ -║ │ ▼ │ ║ -║ │ mp_full.py check │ ║ -║ │ 检查: 配置/域名/隐私/认证 │ ║ -║ │ │ ║ -║ └─────────────────────────────────────────────────────────────────────┘ ║ -║ │ ║ -║ ▼ ║ -║ 阶段三:部署阶段(全自动) ║ -║ ┌─────────────────────────────────────────────────────────────────────┐ ║ -║ │ │ ║ -║ │ mp_full.py auto -v "1.0.0" -d "版本描述" │ ║ -║ │ │ │ ║ -║ │ ▼ │ ║ -║ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ ║ -║ │ │ ① 检查 │ → │ ② 上传 │ → │ ③ 提审 │ │ ║ -║ │ │ 项目问题 │ │ 代码到微信│ │ 提交审核 │ │ ║ -║ │ └──────────┘ └──────────┘ └──────────┘ │ ║ -║ │ │ │ │ │ ║ -║ │ ▼ ▼ ▼ │ ║ -║ │ 自动检测 使用CLI/npm 已认证→API提审 │ ║ -║ │ 配置/认证/域名 优先级选择 未认证→手动提审 │ ║ -║ │ │ ║ -║ └─────────────────────────────────────────────────────────────────────┘ ║ -║ │ ║ -║ ▼ ║ -║ 阶段四:发布阶段 ║ -║ ┌─────────────────────────────────────────────────────────────────────┐ ║ -║ │ │ ║ -║ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ ║ -║ │ │ 等待审核 │ → │ 审核通过 │ → │ 发布上线 │ │ ║ -║ │ │ 1-7工作日 │ │ 通知 │ │ release │ │ ║ -║ │ └──────────┘ └──────────┘ └──────────┘ │ ║ -║ │ │ │ ║ -║ │ ▼ │ ║ -║ │ mp_deploy.py release │ ║ -║ │ 或 微信后台点击发布 │ ║ -║ │ │ ║ -║ └─────────────────────────────────────────────────────────────────────┘ ║ -║ │ ║ -║ ▼ ║ -║ 阶段五:运营阶段 ║ -║ ┌─────────────────────────────────────────────────────────────────────┐ ║ -║ │ │ ║ -║ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ ║ -║ │ │ 数据分析 │ │ 汇总报告 │ │ 版本迭代 │ │ ║ -║ │ │ mp_manager│ │ mp_full │ │ 循环部署 │ │ ║ -║ │ └──────────┘ └──────────┘ └──────────┘ │ ║ -║ │ │ │ │ │ ║ -║ │ ▼ ▼ ▼ │ ║ -║ │ data命令 report命令 返回部署阶段 │ ║ -║ │ │ ║ -║ └─────────────────────────────────────────────────────────────────────┘ ║ -║ ║ -╚══════════════════════════════════════════════════════════════════════════════╝ -``` - -### 工具整合架构图 - -``` -┌────────────────────────────────────────────────────────────────────────────┐ -│ 小程序管理工具整合架构 │ -├────────────────────────────────────────────────────────────────────────────┤ -│ │ -│ ┌─────────────────────────────────────────────────────────────────────┐ │ -│ │ 用户命令层 │ │ -│ │ mp_full.py report │ mp_full.py check │ mp_full.py auto │ │ -│ │ mp_deploy.py list │ mp_deploy.py cert │ mp_manager.py status │ │ -│ └─────────────────────────────────────────────────────────────────────┘ │ -│ │ │ -│ ▼ │ -│ ┌─────────────────────────────────────────────────────────────────────┐ │ -│ │ Python 管理层 │ │ -│ │ ┌───────────────┐ ┌───────────────┐ ┌───────────────┐ │ │ -│ │ │ mp_full.py │ │ mp_deploy.py │ │ mp_api.py │ │ │ -│ │ │ 全能管理器 │ │ 部署工具 │ │ API封装 │ │ │ -│ │ │ • 检查 │ │ • 多小程序 │ │ • 认证 │ │ │ -│ │ │ • 报告 │ │ • 认证管理 │ │ • 审核 │ │ │ -│ │ │ • 自动部署 │ │ • 发布 │ │ • 发布 │ │ │ -│ │ └───────────────┘ └───────────────┘ └───────────────┘ │ │ -│ └─────────────────────────────────────────────────────────────────────┘ │ -│ │ │ -│ ▼ │ -│ ┌─────────────────────────────────────────────────────────────────────┐ │ -│ │ 外部工具层 │ │ -│ │ ┌───────────────┐ ┌───────────────┐ ┌───────────────┐ │ │ -│ │ │ 微信开发者 │ │ miniprogram │ │ 微信开放平台 │ │ │ -│ │ │ 工具 CLI │ │ -ci (npm) │ │ API │ │ │ -│ │ │ │ │ │ │ │ │ │ -│ │ │ • 打开项目 │ │ • 上传代码 │ │ • 提交审核 │ │ │ -│ │ │ • 预览 │ │ • 预览 │ │ • 发布 │ │ │ -│ │ │ • 上传 │ │ • 构建npm │ │ • 认证管理 │ │ │ -│ │ │ • 编译 │ │ • sourceMap │ │ • 数据分析 │ │ │ -│ │ └───────────────┘ └───────────────┘ └───────────────┘ │ │ -│ │ │ │ │ │ │ -│ │ ▼ ▼ ▼ │ │ -│ │ 优先级: 1 优先级: 2 优先级: 3 │ │ -│ │ (无需密钥) (需要密钥) (需要token) │ │ -│ └─────────────────────────────────────────────────────────────────────┘ │ -│ │ -└────────────────────────────────────────────────────────────────────────────┘ -``` - -### 快速开始 - -```bash -# 进入脚本目录 -cd /Users/karuo/Documents/个人/卡若AI/02_卡人(水)/小程序管理/scripts - -# 1. 查看已配置的小程序 -python3 mp_deploy.py list - -# 2. 添加新小程序(交互式) -python3 mp_deploy.py add - -# 3. 检查认证状态 -python3 mp_deploy.py cert-status soul-party - -# 4. 一键部署 -python3 mp_deploy.py deploy soul-party - -# 5. 审核通过后发布 -python3 mp_deploy.py release soul-party -``` - -### 命令速查 - -| 命令 | 说明 | 示例 | -|------|------|------| -| `list` | 列出所有小程序 | `python3 mp_deploy.py list` | -| `add` | 添加新小程序 | `python3 mp_deploy.py add` | -| `deploy` | 一键部署 | `python3 mp_deploy.py deploy soul-party` | -| `upload` | 仅上传代码 | `python3 mp_deploy.py upload soul-party` | -| `cert` | 提交认证 | `python3 mp_deploy.py cert soul-party` | -| `cert-status` | 查询认证状态 | `python3 mp_deploy.py cert-status soul-party` | -| `cert-done` | 标记认证完成 | `python3 mp_deploy.py cert-done soul-party` | -| `release` | 发布上线 | `python3 mp_deploy.py release soul-party` | - ---- - -## 📋 企业认证详解 - -### 认证流程图 - -``` -┌──────────────────────────────────────────────────────────────┐ -│ 企业认证流程 │ -├──────────────────────────────────────────────────────────────┤ -│ │ -│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ -│ │ 准备 │ → │ 提交 │ → │ 审核 │ │ -│ │ 材料 │ │ 认证 │ │ 等待 │ │ -│ └─────────┘ └─────────┘ └─────────┘ │ -│ │ │ │ │ -│ ↓ ↓ ↓ │ -│ ┌─────────────────────────────────────────┐ │ -│ │ • 营业执照 • 微信后台上传 • 1-5工作日 │ │ -│ │ • 法人身份证 • 法人扫码验证 • 审核结果 │ │ -│ │ • 法人微信号 • 支付300元 • 通知 │ │ -│ └─────────────────────────────────────────┘ │ -│ │ -│ ⚠️ 认证有效期:1年,到期需年审 │ -│ │ -└──────────────────────────────────────────────────────────────┘ -``` - -### 认证材料清单 - -| 材料 | 必需 | 说明 | -|------|------|------| -| 企业营业执照 | ✅ | 扫描件或照片,信息清晰 | -| 法人身份证 | ✅ | 正反面照片 | -| 法人微信号 | ✅ | 需绑定银行卡,用于扫码验证 | -| 联系人手机号 | ✅ | 接收审核通知 | -| 认证费用 | ✅ | 300元/年 | -| 其他资质 | 可选 | 特殊行业需要(如医疗、金融) | - -### 认证状态说明 - -| 状态 | 说明 | 下一步操作 | -|------|------|------------| -| `unknown` | 未知/未检查 | 运行 `cert-status` 检查 | -| `pending` | 审核中 | 等待1-5个工作日 | -| `verified` | 已认证 | 可以正常发布 | -| `rejected` | 被拒绝 | 查看原因,修改后重新提交 | -| `expired` | 已过期 | 需要重新认证(年审) | - -### 认证API(第三方平台) - -如果你有第三方平台资质,可以通过API代商家提交认证: - -```python -# POST https://api.weixin.qq.com/wxa/sec/wxaauth?access_token=ACCESS_TOKEN -{ - "auth_type": 1, # 1=企业 - "auth_data": { - "name": "企业名称", - "code": "统一社会信用代码", - "legal_persona_wechat": "法人微信号", - "legal_persona_name": "法人姓名", - "legal_persona_idcard": "法人身份证号", - "component_phone": "联系电话" - } -} -``` - ---- - -## 🔧 GitHub开源工具推荐 - -### 1. miniprogram-ci(官方) - -微信官方提供的CI工具,支持Node.js环境使用。 - -**安装**: -```bash -npm install miniprogram-ci -g -``` - -**使用**: -```javascript -const ci = require('miniprogram-ci'); - -const project = new ci.Project({ - appid: 'wxb8bbb2b10dec74aa', - type: 'miniProgram', - projectPath: '/path/to/miniprogram', - privateKeyPath: '/path/to/private.key', - ignores: ['node_modules/**/*'] -}); - -// 上传 -await ci.upload({ - project, - version: '1.0.0', - desc: '版本描述', - setting: { - es6: true, - minify: true - } -}); -``` - -**获取私钥**: -1. 登录小程序后台 -2. 开发管理 → 开发设置 -3. 小程序代码上传密钥 → 下载 - -### 2. multi-mini-ci - -多平台小程序自动化上传工具。 - -**GitHub**: https://github.com/Ethan-zjc/multi-mini-ci - -**支持平台**: -- 微信小程序 -- 支付宝小程序 -- 百度小程序 -- 字节跳动小程序 - -### 3. GitHub Actions集成 - -在项目中创建 `.github/workflows/deploy.yml`: - -```yaml -name: Deploy MiniProgram - -on: - push: - branches: [main] - -jobs: - deploy: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - - name: Setup Node.js - uses: actions/setup-node@v3 - with: - node-version: '18' - - - name: Install dependencies - run: npm install - - - name: Build - run: npm run build - - - name: Upload to WeChat - env: - PRIVATE_KEY: ${{ secrets.MINIPROGRAM_PRIVATE_KEY }} - run: | - echo "$PRIVATE_KEY" > private.key - npx miniprogram-ci upload \ - --pp ./dist \ - --pkp ./private.key \ - --appid wxb8bbb2b10dec74aa \ - --uv "1.0.${{ github.run_number }}" \ - -r 1 \ - --desc "CI auto deploy" -``` - ---- - -## 📁 完整文件结构(v3.0) - -``` -小程序管理/ -├── SKILL.md # 技能说明文档(本文件) -├── scripts/ -│ ├── mp_full.py # 全能管理工具(推荐)⭐ -│ ├── mp_deploy.py # 部署工具(多小程序管理) -│ ├── mp_manager.py # API管理工具(基础版) -│ ├── mp_api.py # API封装类(Python SDK) -│ ├── apps_config.json # 多小程序配置文件 -│ ├── requirements.txt # Python依赖 -│ ├── env_template.txt # 环境变量模板 -│ └── reports/ # 检查报告存放目录 -│ ├── summary_*.json # 汇总报告 -│ └── report_*.json # 项目报告 -└── references/ - ├── API接口速查表.md # 常用API速查 - ├── 企业认证完整指南.md # 认证操作指南 - ├── 隐私协议填写指南.md # 隐私协议配置指南 - └── 审核规范.md # 审核常见问题 -``` - -### 脚本功能对比 - -| 脚本 | 功能 | 推荐场景 | -|------|------|----------| -| **mp_full.py** | 全能:检查+报告+自动部署 | 日常管理(推荐) | -| **mp_deploy.py** | 多小程序管理+认证 | 多项目管理 | -| **mp_manager.py** | API调用工具 | 高级操作 | -| **mp_api.py** | Python SDK | 二次开发 | - ---- - -## 📊 多小程序配置 - -配置文件位于 `scripts/apps_config.json`: - -```json -{ - "apps": [ - { - "id": "soul-party", - "name": "Soul派对", - "appid": "wxb8bbb2b10dec74aa", - "project_path": "/path/to/miniprogram", - "certification": { - "status": "verified", - "enterprise_name": "厦门智群网络科技有限公司" - } - }, - { - "id": "another-app", - "name": "另一个小程序", - "appid": "wx1234567890", - "project_path": "/path/to/another", - "certification": { - "status": "pending" - } - } - ], - "certification_materials": { - "enterprise_name": "厦门智群网络科技有限公司", - "license_number": "统一社会信用代码", - "legal_persona_name": "法人姓名", - "component_phone": "15880802661" - } -} -``` - ---- - -## ⚡ 常见场景速查 - -### 场景1:发布时提示"未完成微信认证" - -```bash -# 1. 检查认证状态 -python3 mp_deploy.py cert-status soul-party - -# 2. 如果未认证,查看认证指引 -python3 mp_deploy.py cert soul-party - -# 3. 在微信后台完成认证后,标记完成 -python3 mp_deploy.py cert-done soul-party - -# 4. 重新部署 -python3 mp_deploy.py deploy soul-party -``` - -### 场景2:新建小程序并快速上线 - -```bash -# 1. 添加小程序配置 -python3 mp_deploy.py add - -# 2. 提交认证 -python3 mp_deploy.py cert my-new-app - -# 3. 在微信后台完成认证(1-5天) - -# 4. 认证通过后标记 -python3 mp_deploy.py cert-done my-new-app - -# 5. 一键部署 -python3 mp_deploy.py deploy my-new-app - -# 6. 审核通过后发布 -python3 mp_deploy.py release my-new-app -``` - -### 场景3:仅更新代码(不提审) - -```bash -# 快速上传到开发版 -python3 mp_deploy.py upload soul-party -v "1.0.5" -d "修复xxx问题" -``` - -### 场景4:批量管理多个小程序 - -```bash -# 查看所有小程序 -python3 mp_deploy.py list - -# 检查所有认证状态 -for app in soul-party another-app third-app; do - echo "=== $app ===" - python3 mp_deploy.py cert-status $app -done -``` - ---- - -## 🔗 相关资源 - -### 官方文档 -- [微信开放平台](https://developers.weixin.qq.com/doc/oplatform/) -- [小程序CI工具](https://developers.weixin.qq.com/miniprogram/dev/devtools/ci.html) -- [第三方平台代认证](https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/2.0/product/weapp_wxverify.html) - -### 开源项目 -- [miniprogram-ci](https://www.npmjs.com/package/miniprogram-ci) - 官方CI工具 -- [multi-mini-ci](https://github.com/Ethan-zjc/multi-mini-ci) - 多平台上传 -- [uz-miniprogram-ci](https://github.com/uzhan/uz-miniprogram-ci) - 一键上传发布 - -### 相关文章 -- [GitHub Actions集成小程序CI](https://idayer.com/use-github-actions-and-mp-ci-for-wechat-miniprogram-ci/) - ---- - -## 🔥 实战经验库(持续更新) - -> 基于 Soul创业派对 项目开发过程中的真实问题和解决方案 - -### 一、数据库与后端问题 - -#### 1.1 后台初始化失败:Unknown column 'password' in 'field list' - -**问题现象**:后台用户管理显示"初始化失败" - -**根本原因**:数据库表结构缺少字段 - -**解决方案**:创建数据库初始化API自动修复 - -```typescript -// app/api/db/init/route.ts -// 自动检查并添加缺失字段 -const columnsToAdd = [ - { name: 'password', type: 'VARCHAR(100)' }, - { name: 'session_key', type: 'VARCHAR(100)' }, - { name: 'referred_by', type: 'VARCHAR(50)' }, - { name: 'is_admin', type: 'BOOLEAN DEFAULT FALSE' }, -] - -for (const col of columnsToAdd) { - // 检查列是否存在,不存在则添加 - await query(`ALTER TABLE users ADD COLUMN ${col.name} ${col.type}`) -} -``` - -**访问修复**:`curl https://your-domain.com/api/db/init` - ---- - -#### 1.2 Column 'open_id' cannot be null - -**问题现象**:后台添加用户失败 - -**根本原因**:数据库 `open_id` 字段设置为 NOT NULL,但后台添加用户时没有openId - -**解决方案**: -```sql -ALTER TABLE users MODIFY COLUMN open_id VARCHAR(100) NULL -``` - -**最佳实践**:openId允许为NULL,因为: -- 后台手动添加的用户没有openId -- 微信登录用户有openId -- 两种用户需要共存 - ---- - -#### 1.3 AppID配置不一致 - -**问题现象**:微信登录返回错误,或获取openId失败 - -**根本原因**:项目中多个文件使用了不同的AppID - -**检查清单**: - -| 文件 | 配置项 | 正确值 | -|:---|:---|:---| -| `miniprogram/project.config.json` | appid | wxb8bbb2b10dec74aa | -| `app/api/miniprogram/login/route.ts` | MINIPROGRAM_CONFIG.appId | wxb8bbb2b10dec74aa | -| `app/api/wechat/login/route.ts` | APPID | wxb8bbb2b10dec74aa | -| `app/api/withdraw/route.ts` | WECHAT_PAY_CONFIG.appId | wxb8bbb2b10dec74aa | - -**搜索命令**: -```bash -# 查找所有AppID配置 -rg "wx[a-f0-9]{16}" --type ts --type json -``` - ---- - -#### 1.4 用户ID设计最佳实践 - -**推荐方案**:使用 `openId` 作为用户主键 - -```typescript -// 微信登录创建用户 -const userId = openId // 直接使用openId作为用户ID -await query(` - INSERT INTO users (id, open_id, ...) VALUES (?, ?, ...) -`, [userId, openId, ...]) -``` - -**优势**: -- 与微信官方标识一致 -- 便于追踪和管理 -- 后台显示更直观 - -**兼容方案**:后台添加的用户使用 `user_` 前缀 - ---- - -### 二、前端与UI问题 - -#### 2.1 Next.js Hydration错误 - -**问题现象**:页面显示"哎呀,出错了",控制台报 hydration 错误 - -**根本原因**:服务端和客户端渲染结果不一致(如使用localStorage、zustand持久化) - -**解决方案**:添加mounted状态检查 - -```tsx -export default function AdminLayout({ children }) { - const [mounted, setMounted] = useState(false) - - useEffect(() => { - setMounted(true) - }, []) - - // 等待客户端mount后再渲染 - if (!mounted) { - return
加载中...
- } - - return
{children}
-} -``` - ---- - -#### 2.2 数据类型不匹配:toFixed() 报错 - -**问题现象**:显示金额时报错 `toFixed is not a function` - -**根本原因**:数据库返回的 `DECIMAL` 字段是字符串类型 - -**解决方案**: -```tsx -// ❌ 错误 -
{user.earnings.toFixed(2)}
- -// ✅ 正确 -
{parseFloat(String(user.earnings || 0)).toFixed(2)}
-``` - -**通用处理函数**: -```typescript -const formatMoney = (value: any) => { - return parseFloat(String(value || 0)).toFixed(2) -} -``` - ---- - -### 三、小程序开发问题 - -#### 3.1 搜索功能:章节ID格式不一致 - -**问题现象**:搜索结果跳转到阅读页404 - -**根本原因**: -- `book-chapters.json` 使用 `chapter-2`, `chapter-3` 格式 -- 阅读页使用 `1.1`, `1.2` 格式 - -**解决方案**:从标题提取章节号 - -```typescript -// 从标题提取章节号(如 "1.1 荷包:..." → "1.1") -const sectionIdMatch = chapter.title?.match(/^(\d+\.\d+)\s/) -const sectionId = sectionIdMatch ? sectionIdMatch[1] : chapter.id -``` - ---- - -#### 3.2 搜索功能:敏感信息过滤 - -**需求**:搜索结果不能显示用户手机号、微信号等 - -**实现**: -```typescript -const cleanContent = content - .replace(/1[3-9]\d{9}/g, '***') // 手机号 - .replace(/微信[::]\s*\S+/g, '微信:***') // 微信号 - .replace(/QQ[::]\s*\d+/g, 'QQ:***') // QQ号 - .replace(/邮箱[::]\s*\S+@\S+/g, '邮箱:***') // 邮箱 -``` - ---- - -#### 3.3 上下章导航:付费内容也需要显示 - -**需求**:即使用户没有购买,也要显示上一篇/下一篇导航 - -**实现**:将导航组件移到付费墙之外 - -```html - - - - - - - - 上一篇 - 下一篇 - -``` - ---- - -#### 3.4 分销绑定:推广码捕获 - -**需求**:用户通过分享链接进入时,自动绑定推广者 - -**实现流程**: - -```javascript -// app.js - onLaunch/onShow -onLaunch(options) { - if (options.query && options.query.ref) { - wx.setStorageSync('referral_code', options.query.ref) - this.bindReferral(options.query.ref) - } -} - -// 小程序码scene参数解析 -const scene = decodeURIComponent(options.scene) -const params = new URLSearchParams(scene) -const ref = params.get('ref') -``` - -**后端绑定**: -```sql -UPDATE users SET referred_by = ? WHERE id = ? AND referred_by IS NULL -``` - ---- - -### 四、后台管理优化 - -#### 4.1 菜单精简原则 - -**优化前(9项)**: -- 数据概览、网站配置、内容管理、用户管理、匹配配置、分销管理、支付配置、分账提现、二维码、系统设置 - -**优化后(6项)**: -- 数据概览、内容管理、用户管理、分账管理、支付设置、系统设置 - -**精简原则**: -1. 合并相似功能(分销管理 + 分账提现 → 分账管理) -2. 移除低频功能(二维码、匹配配置 → 可在系统设置中配置) -3. 核心功能优先 - ---- - -#### 4.2 用户绑定关系展示 - -**需求**:查看用户的推广下线详情 - -**实现API**: -```typescript -// GET /api/db/users/referrals?userId=xxx -const referrals = await query(` - SELECT * FROM users WHERE referred_by = ? - ORDER BY created_at DESC -`, [referralCode]) -``` - -**展示信息**: -- 绑定总数、已付费人数、免费用户 -- 累计收益、待提现金额 -- 每个绑定用户的状态(VIP/已付费/未付费) - ---- - -### 五、分销与提现 - -#### 5.1 自动分账规则 - -| 配置项 | 值 | 说明 | -|:---|:---|:---| -| 分销比例 | 90% | 推广者获得订单金额的90% | -| 结算方式 | 自动 | 用户付款后立即计入推广者账户 | -| 提现方式 | 微信零钱 | 企业付款到零钱 | -| 提现门槛 | 1元 | 累计收益≥1元可提现 | - -#### 5.2 提现流程 - -``` -用户申请提现 - ↓ -扣除账户余额,增加待提现金额 - ↓ -管理员后台审核 - ↓ -批准 → 调用微信企业付款API → 到账 -拒绝 → 返还用户余额 -``` - ---- - -### 六、开发规范 - -#### 6.1 配置统一管理 - -```typescript -// lib/config.ts -export const WECHAT_CONFIG = { - appId: process.env.WECHAT_APPID || 'wxb8bbb2b10dec74aa', - appSecret: process.env.WECHAT_APPSECRET || '...', - mchId: '1318592501', - apiKey: '...' -} -``` - -**所有API文件统一引用此配置,避免硬编码** - -#### 6.2 数据库字段命名 - -| 前端字段 | 数据库字段 | 说明 | -|:---|:---|:---| -| openId | open_id | 微信openId | -| hasFullBook | has_full_book | 是否购买全书 | -| referralCode | referral_code | 推广码 | -| pendingEarnings | pending_earnings | 待提现收益 | - -**规则**:数据库使用snake_case,前端使用camelCase - -#### 6.3 错误处理模板 - -```typescript -export async function POST(request: Request) { - try { - const body = await request.json() - // 业务逻辑 - return NextResponse.json({ success: true, data: ... }) - } catch (error) { - console.error('[API名称] 错误:', error) - return NextResponse.json({ - success: false, - error: '用户友好的错误信息' - }, { status: 500 }) - } -} -``` - ---- - -## 📌 问题排查清单 - -### 小程序无法登录 - -- [ ] 检查AppID是否正确(project.config.json vs 后端) -- [ ] 检查AppSecret是否正确 -- [ ] 检查API域名是否已配置 -- [ ] 检查后端服务是否正常运行 -- [ ] 查看后端日志 `[MiniLogin]` - -### 后台显示异常 - -- [ ] 运行 `/api/db/init` 初始化数据库 -- [ ] 检查数据库连接是否正常 -- [ ] 清除浏览器缓存(Cmd+Shift+R) -- [ ] 查看浏览器控制台错误 - -### 搜索功能无结果 - -- [ ] 检查 `public/book-chapters.json` 是否存在 -- [ ] 检查章节文件路径是否正确(filePath字段) -- [ ] 检查关键词编码(中文需URL编码) - -### 提现失败 - -- [ ] 检查用户余额是否充足 -- [ ] 检查用户是否有openId -- [ ] 检查微信商户API证书配置 -- [ ] 查看后端日志 `[Withdraw]` - ---- - -**创建时间**:2026-01-25 -**更新时间**:2026-01-25 -**版本**:v3.1(新增实战经验库) -**维护者**:卡若 diff --git a/开发文档/小程序管理/references/审核与认证.md b/开发文档/小程序管理/references/审核与认证.md deleted file mode 100644 index fd495184..00000000 --- a/开发文档/小程序管理/references/审核与认证.md +++ /dev/null @@ -1,3 +0,0 @@ -# 审核与认证(合并自 API速查、企业认证、审核规范、隐私协议) - -API 接口速查、企业认证完整指南、审核规范、隐私协议填写指南。详见原各文档。 diff --git a/开发文档/小程序管理/scripts/apps_config.json b/开发文档/小程序管理/scripts/apps_config.json deleted file mode 100644 index eeb0a7d5..00000000 --- a/开发文档/小程序管理/scripts/apps_config.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "_comment": "小程序配置文件 - 支持管理多个小程序", - "apps": [ - { - "id": "soul-party", - "name": "Soul派对", - "appid": "wxb8bbb2b10dec74aa", - "project_path": "/Users/karuo/Documents/开发/3、自营项目/一场soul的创业实验/miniprogram", - "private_key_path": "", - "api_domain": "https://soul.quwanzhi.com", - "description": "一场SOUL的创业实验场", - "certification": { - "status": "pending", - "enterprise_name": "泉州市卡若网络技术有限公司", - "license_number": "", - "legal_persona_name": "", - "legal_persona_wechat": "", - "component_phone": "15880802661" - } - } - ], - "certification_materials": { - "_comment": "企业认证通用材料(所有小程序共用)", - "enterprise_name": "泉州市卡若网络技术有限公司", - "license_number": "", - "license_media_id": "", - "legal_persona_name": "", - "legal_persona_wechat": "", - "legal_persona_idcard": "", - "component_phone": "15880802661", - "contact_email": "zhiqun@qq.com" - }, - "third_party_platform": { - "_comment": "第三方平台配置(用于代认证)", - "component_appid": "", - "component_appsecret": "", - "component_verify_ticket": "", - "authorized": false - } -} diff --git a/开发文档/小程序管理/scripts/env_template.txt b/开发文档/小程序管理/scripts/env_template.txt deleted file mode 100644 index 9f7686d6..00000000 --- a/开发文档/小程序管理/scripts/env_template.txt +++ /dev/null @@ -1,30 +0,0 @@ -# 微信小程序管理 - 环境变量配置 -# 复制此文件为 .env 并填入实际值 - -# ==================== 方式一:直接使用 access_token ==================== -# 如果你已经有 access_token,直接填入即可(适合快速测试) -ACCESS_TOKEN=你的access_token - -# ==================== 方式二:使用第三方平台凭证 ==================== -# 如果你有第三方平台资质,填入以下信息可自动刷新token - -# 第三方平台 AppID -COMPONENT_APPID=你的第三方平台AppID - -# 第三方平台密钥 -COMPONENT_APPSECRET=你的第三方平台密钥 - -# 授权小程序 AppID(要管理的小程序) -AUTHORIZER_APPID=wxb8bbb2b10dec74aa - -# 授权刷新令牌(从授权回调中获取) -AUTHORIZER_REFRESH_TOKEN=授权时获取的refresh_token - -# ==================== 小程序项目路径 ==================== -# 用于 CLI 工具操作 -MINIPROGRAM_PATH=/Users/karuo/Documents/开发/3、自营项目/一场soul的创业实验/miniprogram - -# ==================== 可选配置 ==================== -# 隐私协议联系方式(用于快速配置) -CONTACT_EMAIL=zhiqun@qq.com -CONTACT_PHONE=15880802661 diff --git a/开发文档/小程序管理/scripts/mp_api.py b/开发文档/小程序管理/scripts/mp_api.py deleted file mode 100644 index 61fae3ae..00000000 --- a/开发文档/小程序管理/scripts/mp_api.py +++ /dev/null @@ -1,635 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -""" -微信小程序管理API封装 -支持:注册、配置、代码管理、审核、发布、数据分析 -""" - -import os -import json -import time -import httpx -from typing import Optional, Dict, Any, List -from dataclasses import dataclass -from pathlib import Path - -# 尝试加载dotenv(可选依赖) -try: - from dotenv import load_dotenv - load_dotenv() -except ImportError: - pass # dotenv不是必需的 - - -@dataclass -class MiniProgramInfo: - """小程序基础信息""" - appid: str - nickname: str - head_image_url: str - signature: str - principal_name: str - realname_status: int # 1=已认证 - - -@dataclass -class AuditStatus: - """审核状态""" - auditid: int - status: int # 0=成功,1=被拒,2=审核中,3=已撤回,4=延后 - reason: Optional[str] = None - screenshot: Optional[str] = None - - @property - def status_text(self) -> str: - status_map = { - 0: "✅ 审核成功", - 1: "❌ 审核被拒", - 2: "⏳ 审核中", - 3: "↩️ 已撤回", - 4: "⏸️ 审核延后" - } - return status_map.get(self.status, "未知状态") - - -class MiniProgramAPI: - """微信小程序管理API""" - - BASE_URL = "https://api.weixin.qq.com" - - def __init__( - self, - component_appid: Optional[str] = None, - component_appsecret: Optional[str] = None, - authorizer_appid: Optional[str] = None, - access_token: Optional[str] = None - ): - """ - 初始化API - - Args: - component_appid: 第三方平台AppID - component_appsecret: 第三方平台密钥 - authorizer_appid: 授权小程序AppID - access_token: 直接使用的access_token(如已获取) - """ - self.component_appid = component_appid or os.getenv("COMPONENT_APPID") - self.component_appsecret = component_appsecret or os.getenv("COMPONENT_APPSECRET") - self.authorizer_appid = authorizer_appid or os.getenv("AUTHORIZER_APPID") - self._access_token = access_token or os.getenv("ACCESS_TOKEN") - self._token_expires_at = 0 - - self.client = httpx.Client(timeout=30.0) - - @property - def access_token(self) -> str: - """获取access_token,如果过期则刷新""" - if self._access_token and time.time() < self._token_expires_at: - return self._access_token - - # 如果没有配置刷新token的信息,直接返回现有token - if not self.component_appid: - return self._access_token or "" - - # TODO: 实现token刷新逻辑 - return self._access_token or "" - - def set_access_token(self, token: str, expires_in: int = 7200): - """手动设置access_token""" - self._access_token = token - self._token_expires_at = time.time() + expires_in - 300 # 提前5分钟过期 - - def _request( - self, - method: str, - path: str, - params: Optional[Dict] = None, - json_data: Optional[Dict] = None, - **kwargs - ) -> Dict[str, Any]: - """发起API请求""" - url = f"{self.BASE_URL}{path}" - - # 添加access_token - if params is None: - params = {} - if "access_token" not in params: - params["access_token"] = self.access_token - - if method.upper() == "GET": - resp = self.client.get(url, params=params, **kwargs) - else: - resp = self.client.post(url, params=params, json=json_data, **kwargs) - - # 解析响应 - try: - result = resp.json() - except json.JSONDecodeError: - # 可能是二进制数据(如图片) - return {"_binary": resp.content} - - # 检查错误 - if result.get("errcode", 0) != 0: - raise APIError(result.get("errcode"), result.get("errmsg", "Unknown error")) - - return result - - # ==================== 基础信息 ==================== - - def get_basic_info(self) -> MiniProgramInfo: - """获取小程序基础信息""" - result = self._request("POST", "/cgi-bin/account/getaccountbasicinfo") - return MiniProgramInfo( - appid=result.get("appid", ""), - nickname=result.get("nickname", ""), - head_image_url=result.get("head_image_url", ""), - signature=result.get("signature", ""), - principal_name=result.get("principal_name", ""), - realname_status=result.get("realname_status", 0) - ) - - def modify_signature(self, signature: str) -> bool: - """修改简介(4-120字)""" - self._request("POST", "/cgi-bin/account/modifysignature", json_data={ - "signature": signature - }) - return True - - # ==================== 域名配置 ==================== - - def get_domain(self) -> Dict[str, List[str]]: - """获取服务器域名配置""" - result = self._request("POST", "/wxa/modify_domain", json_data={ - "action": "get" - }) - return { - "requestdomain": result.get("requestdomain", []), - "wsrequestdomain": result.get("wsrequestdomain", []), - "uploaddomain": result.get("uploaddomain", []), - "downloaddomain": result.get("downloaddomain", []) - } - - def set_domain( - self, - requestdomain: Optional[List[str]] = None, - wsrequestdomain: Optional[List[str]] = None, - uploaddomain: Optional[List[str]] = None, - downloaddomain: Optional[List[str]] = None - ) -> bool: - """设置服务器域名""" - data = {"action": "set"} - if requestdomain: - data["requestdomain"] = requestdomain - if wsrequestdomain: - data["wsrequestdomain"] = wsrequestdomain - if uploaddomain: - data["uploaddomain"] = uploaddomain - if downloaddomain: - data["downloaddomain"] = downloaddomain - - self._request("POST", "/wxa/modify_domain", json_data=data) - return True - - def get_webview_domain(self) -> List[str]: - """获取业务域名""" - result = self._request("POST", "/wxa/setwebviewdomain", json_data={ - "action": "get" - }) - return result.get("webviewdomain", []) - - def set_webview_domain(self, webviewdomain: List[str]) -> bool: - """设置业务域名""" - self._request("POST", "/wxa/setwebviewdomain", json_data={ - "action": "set", - "webviewdomain": webviewdomain - }) - return True - - # ==================== 隐私协议 ==================== - - def get_privacy_setting(self, privacy_ver: int = 2) -> Dict[str, Any]: - """获取隐私协议设置""" - result = self._request("POST", "/cgi-bin/component/getprivacysetting", json_data={ - "privacy_ver": privacy_ver - }) - return result - - def set_privacy_setting( - self, - setting_list: List[Dict[str, str]], - contact_email: Optional[str] = None, - contact_phone: Optional[str] = None, - notice_method: str = "弹窗提示" - ) -> bool: - """ - 设置隐私协议 - - Args: - setting_list: 隐私配置列表,如 [{"privacy_key": "UserInfo", "privacy_text": "用于展示头像"}] - contact_email: 联系邮箱 - contact_phone: 联系电话 - notice_method: 告知方式 - """ - data = { - "privacy_ver": 2, - "setting_list": setting_list - } - - owner_setting = {"notice_method": notice_method} - if contact_email: - owner_setting["contact_email"] = contact_email - if contact_phone: - owner_setting["contact_phone"] = contact_phone - data["owner_setting"] = owner_setting - - self._request("POST", "/cgi-bin/component/setprivacysetting", json_data=data) - return True - - # ==================== 类目管理 ==================== - - def get_all_categories(self) -> List[Dict]: - """获取可选类目列表""" - result = self._request("GET", "/cgi-bin/wxopen/getallcategories") - return result.get("categories_list", {}).get("categories", []) - - def get_category(self) -> List[Dict]: - """获取已设置的类目""" - result = self._request("GET", "/cgi-bin/wxopen/getcategory") - return result.get("categories", []) - - def add_category(self, categories: List[Dict]) -> bool: - """ - 添加类目 - - Args: - categories: 类目列表,如 [{"first": 1, "second": 2}] - """ - self._request("POST", "/cgi-bin/wxopen/addcategory", json_data={ - "categories": categories - }) - return True - - def delete_category(self, first: int, second: int) -> bool: - """删除类目""" - self._request("POST", "/cgi-bin/wxopen/deletecategory", json_data={ - "first": first, - "second": second - }) - return True - - # ==================== 代码管理 ==================== - - def commit_code( - self, - template_id: int, - user_version: str, - user_desc: str, - ext_json: Optional[str] = None - ) -> bool: - """ - 上传代码 - - Args: - template_id: 代码模板ID - user_version: 版本号 - user_desc: 版本描述 - ext_json: 扩展配置JSON字符串 - """ - data = { - "template_id": template_id, - "user_version": user_version, - "user_desc": user_desc - } - if ext_json: - data["ext_json"] = ext_json - - self._request("POST", "/wxa/commit", json_data=data) - return True - - def get_page(self) -> List[str]: - """获取已上传代码的页面列表""" - result = self._request("GET", "/wxa/get_page") - return result.get("page_list", []) - - def get_qrcode(self, path: Optional[str] = None) -> bytes: - """ - 获取体验版二维码 - - Args: - path: 页面路径,如 "pages/index/index" - - Returns: - 二维码图片二进制数据 - """ - params = {"access_token": self.access_token} - if path: - params["path"] = path - - resp = self.client.get(f"{self.BASE_URL}/wxa/get_qrcode", params=params) - return resp.content - - # ==================== 审核管理 ==================== - - def submit_audit( - self, - item_list: Optional[List[Dict]] = None, - version_desc: Optional[str] = None, - feedback_info: Optional[str] = None - ) -> int: - """ - 提交审核 - - Args: - item_list: 页面审核信息列表 - version_desc: 版本说明 - feedback_info: 反馈内容 - - Returns: - 审核单ID - """ - data = {} - if item_list: - data["item_list"] = item_list - if version_desc: - data["version_desc"] = version_desc - if feedback_info: - data["feedback_info"] = feedback_info - - result = self._request("POST", "/wxa/submit_audit", json_data=data) - return result.get("auditid", 0) - - def get_audit_status(self, auditid: int) -> AuditStatus: - """查询审核状态""" - result = self._request("POST", "/wxa/get_auditstatus", json_data={ - "auditid": auditid - }) - return AuditStatus( - auditid=auditid, - status=result.get("status", -1), - reason=result.get("reason"), - screenshot=result.get("screenshot") - ) - - def get_latest_audit_status(self) -> AuditStatus: - """查询最新审核状态""" - result = self._request("GET", "/wxa/get_latest_auditstatus") - return AuditStatus( - auditid=result.get("auditid", 0), - status=result.get("status", -1), - reason=result.get("reason"), - screenshot=result.get("screenshot") - ) - - def undo_code_audit(self) -> bool: - """撤回审核(每天限1次)""" - self._request("GET", "/wxa/undocodeaudit") - return True - - # ==================== 发布管理 ==================== - - def release(self) -> bool: - """发布已审核通过的版本""" - self._request("POST", "/wxa/release", json_data={}) - return True - - def revert_code_release(self) -> bool: - """版本回退(只能回退到上一版本)""" - self._request("GET", "/wxa/revertcoderelease") - return True - - def get_revert_history(self) -> List[Dict]: - """获取可回退版本历史""" - result = self._request("GET", "/wxa/revertcoderelease", params={ - "action": "get_history_version" - }) - return result.get("version_list", []) - - def gray_release(self, gray_percentage: int) -> bool: - """ - 分阶段发布 - - Args: - gray_percentage: 灰度比例 1-100 - """ - self._request("POST", "/wxa/grayrelease", json_data={ - "gray_percentage": gray_percentage - }) - return True - - # ==================== 小程序码 ==================== - - def get_wxacode( - self, - path: str, - width: int = 430, - auto_color: bool = False, - line_color: Optional[Dict[str, int]] = None, - is_hyaline: bool = False - ) -> bytes: - """ - 获取小程序码(有限制,每个path最多10万个) - - Args: - path: 页面路径,如 "pages/index/index?id=123" - width: 宽度 280-1280 - auto_color: 自动配置线条颜色 - line_color: 线条颜色 {"r": 0, "g": 0, "b": 0} - is_hyaline: 是否透明背景 - - Returns: - 二维码图片二进制数据 - """ - data = { - "path": path, - "width": width, - "auto_color": auto_color, - "is_hyaline": is_hyaline - } - if line_color: - data["line_color"] = line_color - - resp = self.client.post( - f"{self.BASE_URL}/wxa/getwxacode", - params={"access_token": self.access_token}, - json=data - ) - return resp.content - - def get_wxacode_unlimit( - self, - scene: str, - page: Optional[str] = None, - width: int = 430, - auto_color: bool = False, - line_color: Optional[Dict[str, int]] = None, - is_hyaline: bool = False - ) -> bytes: - """ - 获取无限小程序码(推荐) - - Args: - scene: 场景值,最长32字符,如 "user_id=123&from=share" - page: 页面路径,必须是已发布的页面 - width: 宽度 280-1280 - auto_color: 自动配置线条颜色 - line_color: 线条颜色 {"r": 0, "g": 0, "b": 0} - is_hyaline: 是否透明背景 - - Returns: - 二维码图片二进制数据 - """ - data = { - "scene": scene, - "width": width, - "auto_color": auto_color, - "is_hyaline": is_hyaline - } - if page: - data["page"] = page - if line_color: - data["line_color"] = line_color - - resp = self.client.post( - f"{self.BASE_URL}/wxa/getwxacodeunlimit", - params={"access_token": self.access_token}, - json=data - ) - return resp.content - - def gen_short_link( - self, - page_url: str, - page_title: str, - is_permanent: bool = False - ) -> str: - """ - 生成小程序短链接 - - Args: - page_url: 页面路径,如 "pages/index/index?id=123" - page_title: 页面标题 - is_permanent: 是否永久有效 - - Returns: - 短链接 - """ - result = self._request("POST", "/wxa/genwxashortlink", json_data={ - "page_url": page_url, - "page_title": page_title, - "is_permanent": is_permanent - }) - return result.get("link", "") - - # ==================== 数据分析 ==================== - - def get_daily_visit_trend(self, begin_date: str, end_date: str) -> List[Dict]: - """ - 获取每日访问趋势 - - Args: - begin_date: 开始日期 YYYYMMDD - end_date: 结束日期 YYYYMMDD - """ - result = self._request( - "POST", - "/datacube/getweanalysisappiddailyvisittrend", - json_data={"begin_date": begin_date, "end_date": end_date} - ) - return result.get("list", []) - - def get_user_portrait(self, begin_date: str, end_date: str) -> Dict: - """ - 获取用户画像 - - Args: - begin_date: 开始日期 YYYYMMDD - end_date: 结束日期 YYYYMMDD - """ - result = self._request( - "POST", - "/datacube/getweanalysisappiduserportrait", - json_data={"begin_date": begin_date, "end_date": end_date} - ) - return result - - # ==================== API配额 ==================== - - def get_api_quota(self, cgi_path: str) -> Dict: - """ - 查询接口调用额度 - - Args: - cgi_path: 接口路径,如 "/wxa/getwxacode" - """ - result = self._request("POST", "/cgi-bin/openapi/quota/get", json_data={ - "cgi_path": cgi_path - }) - return result.get("quota", {}) - - def clear_quota(self, appid: Optional[str] = None) -> bool: - """重置接口调用次数(每月限10次)""" - self._request("POST", "/cgi-bin/clear_quota", json_data={ - "appid": appid or self.authorizer_appid - }) - return True - - def close(self): - """关闭连接""" - self.client.close() - - def __enter__(self): - return self - - def __exit__(self, exc_type, exc_val, exc_tb): - self.close() - - -class APIError(Exception): - """API错误""" - - ERROR_CODES = { - -1: "系统繁忙", - 40001: "access_token无效", - 40002: "grant_type不正确", - 40013: "appid不正确", - 40029: "code无效", - 40125: "appsecret不正确", - 41002: "缺少appid参数", - 41004: "缺少appsecret参数", - 42001: "access_token过期", - 42007: "refresh_token过期", - 45009: "调用超过限制", - 61039: "代码检测任务未完成,请稍后再试", - 85006: "标签格式错误", - 85007: "页面路径错误", - 85009: "已有审核版本,请先撤回", - 85010: "版本输入错误", - 85011: "当前版本不能回退", - 85012: "无效的版本", - 85015: "该账号已有发布中的版本", - 85019: "没有审核版本", - 85020: "审核状态异常", - 85064: "找不到模板", - 85085: "该小程序不能被操作", - 85086: "小程序没有绑定任何类目", - 87013: "每天只能撤回1次审核", - 89020: "该小程序尚未认证", - 89248: "隐私协议内容不完整", - } - - def __init__(self, code: int, message: str): - self.code = code - self.message = message - super().__init__(f"[{code}] {self.ERROR_CODES.get(code, message)}") - - -# 便捷函数 -def create_api_from_env() -> MiniProgramAPI: - """从环境变量创建API实例""" - return MiniProgramAPI() - - -if __name__ == "__main__": - # 测试 - api = create_api_from_env() - print("API初始化成功") diff --git a/开发文档/小程序管理/scripts/mp_deploy.py b/开发文档/小程序管理/scripts/mp_deploy.py deleted file mode 100644 index 22f859f4..00000000 --- a/开发文档/小程序管理/scripts/mp_deploy.py +++ /dev/null @@ -1,725 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -""" -小程序一键部署工具 v2.0 - -功能: -- 多小程序管理 -- 一键部署上线 -- 自动认证提交 -- 认证状态检查 -- 材料有效性验证 - -使用方法: - python mp_deploy.py list # 列出所有小程序 - python mp_deploy.py add # 添加新小程序 - python mp_deploy.py deploy # 一键部署 - python mp_deploy.py cert # 提交认证 - python mp_deploy.py cert-status # 查询认证状态 - python mp_deploy.py upload # 上传代码 - python mp_deploy.py release # 发布上线 -""" - -import os -import sys -import json -import subprocess -import argparse -from datetime import datetime -from pathlib import Path -from typing import Optional, Dict, List, Any -from dataclasses import dataclass, asdict - -# 配置文件路径 -CONFIG_FILE = Path(__file__).parent / "apps_config.json" - - -@dataclass -class AppConfig: - """小程序配置""" - id: str - name: str - appid: str - project_path: str - private_key_path: str = "" - api_domain: str = "" - description: str = "" - certification: Dict = None - - def __post_init__(self): - if self.certification is None: - self.certification = { - "status": "unknown", - "enterprise_name": "", - "license_number": "", - "legal_persona_name": "", - "legal_persona_wechat": "", - "component_phone": "" - } - - -class ConfigManager: - """配置管理器""" - - def __init__(self, config_file: Path = CONFIG_FILE): - self.config_file = config_file - self.config = self._load_config() - - def _load_config(self) -> Dict: - """加载配置""" - if self.config_file.exists(): - with open(self.config_file, 'r', encoding='utf-8') as f: - return json.load(f) - return {"apps": [], "certification_materials": {}, "third_party_platform": {}} - - def _save_config(self): - """保存配置""" - with open(self.config_file, 'w', encoding='utf-8') as f: - json.dump(self.config, f, ensure_ascii=False, indent=2) - - def get_apps(self) -> List[AppConfig]: - """获取所有小程序""" - return [AppConfig(**app) for app in self.config.get("apps", [])] - - def get_app(self, app_id: str) -> Optional[AppConfig]: - """获取指定小程序""" - for app in self.config.get("apps", []): - if app["id"] == app_id or app["appid"] == app_id: - return AppConfig(**app) - return None - - def add_app(self, app: AppConfig): - """添加小程序""" - apps = self.config.get("apps", []) - # 检查是否已存在 - for i, existing in enumerate(apps): - if existing["id"] == app.id: - apps[i] = asdict(app) - self.config["apps"] = apps - self._save_config() - return - apps.append(asdict(app)) - self.config["apps"] = apps - self._save_config() - - def update_app(self, app_id: str, updates: Dict): - """更新小程序配置""" - apps = self.config.get("apps", []) - for i, app in enumerate(apps): - if app["id"] == app_id: - apps[i].update(updates) - self.config["apps"] = apps - self._save_config() - return True - return False - - def get_cert_materials(self) -> Dict: - """获取通用认证材料""" - return self.config.get("certification_materials", {}) - - def update_cert_materials(self, materials: Dict): - """更新认证材料""" - self.config["certification_materials"] = materials - self._save_config() - - -class MiniProgramDeployer: - """小程序部署器""" - - # 微信开发者工具CLI路径 - WX_CLI = "/Applications/wechatwebdevtools.app/Contents/MacOS/cli" - - def __init__(self): - self.config = ConfigManager() - - def _check_wx_cli(self) -> bool: - """检查微信开发者工具是否安装""" - return os.path.exists(self.WX_CLI) - - def _run_cli(self, *args, project_path: str = None) -> tuple: - """运行CLI命令""" - cmd = [self.WX_CLI] + list(args) - if project_path: - cmd.extend(["--project", project_path]) - - try: - result = subprocess.run(cmd, capture_output=True, text=True, timeout=120) - return result.returncode == 0, result.stdout + result.stderr - except subprocess.TimeoutExpired: - return False, "命令执行超时" - except Exception as e: - return False, str(e) - - def list_apps(self): - """列出所有小程序""" - apps = self.config.get_apps() - - if not apps: - print("\n📭 暂无配置的小程序") - print(" 运行 'python mp_deploy.py add' 添加小程序") - return - - print("\n" + "=" * 60) - print(" 📱 小程序列表") - print("=" * 60) - - for i, app in enumerate(apps, 1): - cert_status = app.certification.get("status", "unknown") - status_icon = { - "verified": "✅", - "pending": "⏳", - "rejected": "❌", - "expired": "⚠️", - "unknown": "❓" - }.get(cert_status, "❓") - - print(f"\n [{i}] {app.name}") - print(f" ID: {app.id}") - print(f" AppID: {app.appid}") - print(f" 认证: {status_icon} {cert_status}") - print(f" 路径: {app.project_path}") - - print("\n" + "-" * 60) - print(" 使用方法:") - print(" python mp_deploy.py deploy 一键部署") - print(" python mp_deploy.py cert 提交认证") - print("=" * 60 + "\n") - - def add_app(self): - """交互式添加小程序""" - print("\n" + "=" * 50) - print(" ➕ 添加新小程序") - print("=" * 50 + "\n") - - # 收集信息 - app_id = input("小程序ID(用于标识,如 my-app): ").strip() - if not app_id: - print("❌ ID不能为空") - return - - name = input("小程序名称: ").strip() - appid = input("AppID(如 wx1234567890): ").strip() - project_path = input("项目路径: ").strip() - - if not os.path.exists(project_path): - print(f"⚠️ 警告:路径不存在 {project_path}") - - api_domain = input("API域名(可选): ").strip() - description = input("描述(可选): ").strip() - - # 认证信息 - print("\n📋 认证信息(可稍后配置):") - enterprise_name = input("企业名称: ").strip() - - app = AppConfig( - id=app_id, - name=name, - appid=appid, - project_path=project_path, - api_domain=api_domain, - description=description, - certification={ - "status": "unknown", - "enterprise_name": enterprise_name, - "license_number": "", - "legal_persona_name": "", - "legal_persona_wechat": "", - "component_phone": "15880802661" - } - ) - - self.config.add_app(app) - print(f"\n✅ 小程序 [{name}] 添加成功!") - - def deploy(self, app_id: str, skip_cert_check: bool = False): - """一键部署流程""" - app = self.config.get_app(app_id) - if not app: - print(f"❌ 未找到小程序: {app_id}") - print(" 运行 'python mp_deploy.py list' 查看所有小程序") - return False - - print("\n" + "=" * 60) - print(f" 🚀 一键部署: {app.name}") - print("=" * 60) - - steps = [ - ("检查环境", self._step_check_env), - ("检查认证状态", lambda a: self._step_check_cert(a, skip_cert_check)), - ("编译项目", self._step_build), - ("上传代码", self._step_upload), - ("提交审核", self._step_submit_audit), - ] - - for step_name, step_func in steps: - print(f"\n📍 步骤: {step_name}") - print("-" * 40) - - success = step_func(app) - if not success: - print(f"\n❌ 部署中断于: {step_name}") - return False - - print("\n" + "=" * 60) - print(" 🎉 部署完成!") - print("=" * 60) - print(f"\n 下一步操作:") - print(f" 1. 等待审核(通常1-3个工作日)") - print(f" 2. 审核通过后运行: python mp_deploy.py release {app_id}") - print(f" 3. 查看状态: python mp_deploy.py status {app_id}") - - return True - - def _step_check_env(self, app: AppConfig) -> bool: - """检查环境""" - # 检查微信开发者工具 - if not self._check_wx_cli(): - print("❌ 未找到微信开发者工具") - print(" 请安装: https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html") - return False - print("✅ 微信开发者工具已安装") - - # 检查项目路径 - if not os.path.exists(app.project_path): - print(f"❌ 项目路径不存在: {app.project_path}") - return False - print(f"✅ 项目路径存在") - - # 检查project.config.json - config_file = os.path.join(app.project_path, "project.config.json") - if os.path.exists(config_file): - with open(config_file, 'r') as f: - config = json.load(f) - if config.get("appid") != app.appid: - print(f"⚠️ 警告: project.config.json中的AppID与配置不一致") - print(f" 配置: {app.appid}") - print(f" 文件: {config.get('appid')}") - - print("✅ 环境检查通过") - return True - - def _step_check_cert(self, app: AppConfig, skip: bool = False) -> bool: - """检查认证状态""" - if skip: - print("⏭️ 跳过认证检查") - return True - - cert_status = app.certification.get("status", "unknown") - - if cert_status == "verified": - print("✅ 已完成微信认证") - return True - - if cert_status == "pending": - print("⏳ 认证审核中") - print(" 可选择:") - print(" 1. 继续部署(未认证可上传,但无法发布)") - print(" 2. 等待认证完成") - - choice = input("\n是否继续? (y/n): ").strip().lower() - return choice == 'y' - - if cert_status == "expired": - print("⚠️ 认证已过期,需要重新认证") - print(" 运行: python mp_deploy.py cert " + app.id) - - choice = input("\n是否继续部署? (y/n): ").strip().lower() - return choice == 'y' - - # 未认证或未知状态 - print("⚠️ 未完成微信认证") - print(" 未认证的小程序可以上传代码,但无法发布上线") - print(" 运行: python mp_deploy.py cert " + app.id + " 提交认证") - - choice = input("\n是否继续? (y/n): ").strip().lower() - return choice == 'y' - - def _step_build(self, app: AppConfig) -> bool: - """编译项目""" - print("📦 编译项目...") - - # 使用CLI编译 - success, output = self._run_cli("build-npm", project_path=app.project_path) - - if not success: - # build-npm可能失败(如果没有npm依赖),不算错误 - print("ℹ️ 编译完成(无npm依赖或编译失败,继续...)") - else: - print("✅ 编译成功") - - return True - - def _step_upload(self, app: AppConfig) -> bool: - """上传代码""" - # 获取版本号 - version = datetime.now().strftime("%Y.%m.%d.%H%M") - desc = f"自动部署 - {datetime.now().strftime('%Y-%m-%d %H:%M')}" - - print(f"📤 上传代码...") - print(f" 版本: {version}") - print(f" 描述: {desc}") - - success, output = self._run_cli( - "upload", - "--version", version, - "--desc", desc, - project_path=app.project_path - ) - - if not success: - print(f"❌ 上传失败") - print(f" {output}") - - # 常见错误处理 - if "login" in output.lower(): - print("\n💡 提示: 请在微信开发者工具中登录后重试") - return False - - print("✅ 上传成功") - return True - - def _step_submit_audit(self, app: AppConfig) -> bool: - """提交审核""" - print("📝 提交审核...") - - # 使用CLI提交审核 - success, output = self._run_cli( - "submit-audit", - project_path=app.project_path - ) - - if not success: - if "未认证" in output or "认证" in output: - print("⚠️ 提交审核失败:未完成微信认证") - print(" 代码已上传,但需要完成认证后才能提交审核") - print(f" 运行: python mp_deploy.py cert {app.id}") - return True # 不算失败,只是需要认证 - - print(f"❌ 提交审核失败") - print(f" {output}") - return False - - print("✅ 审核已提交") - return True - - def submit_certification(self, app_id: str): - """提交企业认证""" - app = self.config.get_app(app_id) - if not app: - print(f"❌ 未找到小程序: {app_id}") - return - - print("\n" + "=" * 60) - print(f" 📋 提交认证: {app.name}") - print("=" * 60) - - # 获取通用认证材料 - materials = self.config.get_cert_materials() - cert = app.certification - - # 合并材料(小程序配置优先) - enterprise_name = cert.get("enterprise_name") or materials.get("enterprise_name", "") - - print(f"\n📌 认证信息:") - print(f" 小程序: {app.name} ({app.appid})") - print(f" 企业名称: {enterprise_name}") - - # 检查必要材料 - missing = [] - if not enterprise_name: - missing.append("企业名称") - if not materials.get("license_number"): - missing.append("营业执照号") - if not materials.get("legal_persona_name"): - missing.append("法人姓名") - - if missing: - print(f"\n⚠️ 缺少认证材料:") - for m in missing: - print(f" - {m}") - - print(f"\n请先完善认证材料:") - print(f" 编辑: {self.config.config_file}") - print(f" 或运行: python mp_deploy.py cert-config") - return - - print("\n" + "-" * 40) - print("📋 认证方式说明:") - print("-" * 40) - print(""" - 【方式一】微信后台手动认证(推荐) - - 1. 登录小程序后台: https://mp.weixin.qq.com/ - 2. 设置 → 基本设置 → 微信认证 - 3. 选择"企业"类型 - 4. 填写企业信息、上传营业执照 - 5. 法人微信扫码验证 - 6. 支付认证费用(300元/年) - 7. 等待审核(1-5个工作日) - - 【方式二】通过第三方平台代认证(需开发) - - 如果你有第三方平台资质,可以通过API代认证: - 1. 配置第三方平台凭证 - 2. 获取授权 - 3. 调用认证API - - API接口: POST /wxa/sec/wxaauth - """) - - print("\n" + "-" * 40) - print("📝 认证材料清单:") - print("-" * 40) - print(""" - 必需材料: - ☐ 企业营业执照(扫描件或照片) - ☐ 法人身份证(正反面) - ☐ 法人微信号(用于扫码验证) - ☐ 联系人手机号 - ☐ 认证费用 300元 - - 认证有效期: 1年 - 到期后需重新认证(年审) - """) - - # 更新状态为待认证 - self.config.update_app(app_id, { - "certification": { - **cert, - "status": "pending", - "submit_time": datetime.now().isoformat() - } - }) - - print("\n✅ 已标记为待认证状态") - print(" 完成认证后运行: python mp_deploy.py cert-done " + app_id) - - def check_cert_status(self, app_id: str): - """检查认证状态""" - app = self.config.get_app(app_id) - if not app: - print(f"❌ 未找到小程序: {app_id}") - return - - print("\n" + "=" * 60) - print(f" 🔍 认证状态: {app.name}") - print("=" * 60) - - cert = app.certification - status = cert.get("status", "unknown") - - status_info = { - "verified": ("✅ 已认证", "认证有效"), - "pending": ("⏳ 审核中", "请等待审核结果"), - "rejected": ("❌ 被拒绝", "请查看拒绝原因并重新提交"), - "expired": ("⚠️ 已过期", "需要重新认证(年审)"), - "unknown": ("❓ 未知", "请在微信后台确认状态") - } - - icon, desc = status_info.get(status, ("❓", "未知状态")) - - print(f"\n📌 当前状态: {icon}") - print(f" 说明: {desc}") - print(f" 企业: {cert.get('enterprise_name', '未填写')}") - - if cert.get("submit_time"): - print(f" 提交时间: {cert.get('submit_time')}") - - if cert.get("verify_time"): - print(f" 认证时间: {cert.get('verify_time')}") - - if cert.get("expire_time"): - print(f" 到期时间: {cert.get('expire_time')}") - - # 提示下一步操作 - print("\n" + "-" * 40) - if status == "unknown" or status == "rejected": - print("👉 下一步: python mp_deploy.py cert " + app_id) - elif status == "pending": - print("👉 等待审核,通常1-5个工作日") - print(" 审核通过后运行: python mp_deploy.py cert-done " + app_id) - elif status == "verified": - print("👉 可以发布小程序: python mp_deploy.py deploy " + app_id) - elif status == "expired": - print("👉 需要重新认证: python mp_deploy.py cert " + app_id) - - def mark_cert_done(self, app_id: str): - """标记认证完成""" - app = self.config.get_app(app_id) - if not app: - print(f"❌ 未找到小程序: {app_id}") - return - - cert = app.certification - self.config.update_app(app_id, { - "certification": { - **cert, - "status": "verified", - "verify_time": datetime.now().isoformat(), - "expire_time": datetime.now().replace(year=datetime.now().year + 1).isoformat() - } - }) - - print(f"✅ 已标记 [{app.name}] 认证完成") - print(f" 有效期至: {datetime.now().year + 1}年") - - def release(self, app_id: str): - """发布上线""" - app = self.config.get_app(app_id) - if not app: - print(f"❌ 未找到小程序: {app_id}") - return - - print("\n" + "=" * 60) - print(f" 🎉 发布上线: {app.name}") - print("=" * 60) - - # 检查认证状态 - if app.certification.get("status") != "verified": - print("\n⚠️ 警告: 小程序未完成认证") - print(" 未认证的小程序无法发布上线") - - choice = input("\n是否继续尝试? (y/n): ").strip().lower() - if choice != 'y': - return - - print("\n📦 正在发布...") - - # 尝试使用CLI发布 - success, output = self._run_cli("release", project_path=app.project_path) - - if success: - print("\n🎉 发布成功!小程序已上线") - else: - print(f"\n发布结果: {output}") - - if "认证" in output: - print("\n💡 提示: 请先完成微信认证") - print(f" 运行: python mp_deploy.py cert {app_id}") - else: - print("\n💡 提示: 请在微信后台手动发布") - print(" 1. 登录 https://mp.weixin.qq.com/") - print(" 2. 版本管理 → 审核版本 → 发布") - - def quick_upload(self, app_id: str, version: str = None, desc: str = None): - """快速上传代码""" - app = self.config.get_app(app_id) - if not app: - print(f"❌ 未找到小程序: {app_id}") - return - - if not version: - version = datetime.now().strftime("%Y.%m.%d.%H%M") - if not desc: - desc = f"快速上传 - {datetime.now().strftime('%Y-%m-%d %H:%M')}" - - print(f"\n📤 上传代码: {app.name}") - print(f" 版本: {version}") - print(f" 描述: {desc}") - - success, output = self._run_cli( - "upload", - "--version", version, - "--desc", desc, - project_path=app.project_path - ) - - if success: - print("✅ 上传成功") - else: - print(f"❌ 上传失败: {output}") - - -def print_header(title: str): - print("\n" + "=" * 50) - print(f" {title}") - print("=" * 50) - - -def main(): - parser = argparse.ArgumentParser( - description="小程序一键部署工具 v2.0", - formatter_class=argparse.RawDescriptionHelpFormatter, - epilog=""" -示例: - python mp_deploy.py list 列出所有小程序 - python mp_deploy.py add 添加新小程序 - python mp_deploy.py deploy soul-party 一键部署 - python mp_deploy.py cert soul-party 提交认证 - python mp_deploy.py cert-status soul-party 查询认证状态 - python mp_deploy.py cert-done soul-party 标记认证完成 - python mp_deploy.py upload soul-party 仅上传代码 - python mp_deploy.py release soul-party 发布上线 - -部署流程: - 1. add 添加小程序配置 - 2. cert 提交企业认证(首次) - 3. cert-done 认证通过后标记 - 4. deploy 一键部署(编译+上传+提审) - 5. release 审核通过后发布 -""" - ) - - subparsers = parser.add_subparsers(dest="command", help="子命令") - - # list - subparsers.add_parser("list", help="列出所有小程序") - - # add - subparsers.add_parser("add", help="添加新小程序") - - # deploy - deploy_parser = subparsers.add_parser("deploy", help="一键部署") - deploy_parser.add_argument("app_id", help="小程序ID") - deploy_parser.add_argument("--skip-cert", action="store_true", help="跳过认证检查") - - # cert - cert_parser = subparsers.add_parser("cert", help="提交认证") - cert_parser.add_argument("app_id", help="小程序ID") - - # cert-status - cert_status_parser = subparsers.add_parser("cert-status", help="查询认证状态") - cert_status_parser.add_argument("app_id", help="小程序ID") - - # cert-done - cert_done_parser = subparsers.add_parser("cert-done", help="标记认证完成") - cert_done_parser.add_argument("app_id", help="小程序ID") - - # upload - upload_parser = subparsers.add_parser("upload", help="上传代码") - upload_parser.add_argument("app_id", help="小程序ID") - upload_parser.add_argument("-v", "--version", help="版本号") - upload_parser.add_argument("-d", "--desc", help="版本描述") - - # release - release_parser = subparsers.add_parser("release", help="发布上线") - release_parser.add_argument("app_id", help="小程序ID") - - args = parser.parse_args() - - if not args.command: - parser.print_help() - return - - deployer = MiniProgramDeployer() - - commands = { - "list": lambda: deployer.list_apps(), - "add": lambda: deployer.add_app(), - "deploy": lambda: deployer.deploy(args.app_id, args.skip_cert if hasattr(args, 'skip_cert') else False), - "cert": lambda: deployer.submit_certification(args.app_id), - "cert-status": lambda: deployer.check_cert_status(args.app_id), - "cert-done": lambda: deployer.mark_cert_done(args.app_id), - "upload": lambda: deployer.quick_upload(args.app_id, getattr(args, 'version', None), getattr(args, 'desc', None)), - "release": lambda: deployer.release(args.app_id), - } - - cmd_func = commands.get(args.command) - if cmd_func: - cmd_func() - else: - parser.print_help() - - -if __name__ == "__main__": - main() diff --git a/开发文档/小程序管理/scripts/mp_full.py b/开发文档/小程序管理/scripts/mp_full.py deleted file mode 100644 index 2a754a2a..00000000 --- a/开发文档/小程序管理/scripts/mp_full.py +++ /dev/null @@ -1,555 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -""" -小程序全能管理工具 v3.0 - -整合能力: -- 微信开发者工具CLI -- miniprogram-ci (npm官方工具) -- 微信开放平台API -- 多小程序管理 -- 自动化部署+提审 -- 汇总报告生成 - -使用方法: - python mp_full.py report # 生成汇总报告 - python mp_full.py check # 检查项目问题 - python mp_full.py auto # 全自动部署(上传+提审) - python mp_full.py batch-report # 批量生成所有小程序报告 -""" - -import os -import sys -import json -import subprocess -import argparse -from datetime import datetime -from pathlib import Path -from typing import Optional, Dict, List, Any -from dataclasses import dataclass, asdict, field - -# 配置文件路径 -SCRIPT_DIR = Path(__file__).parent -CONFIG_FILE = SCRIPT_DIR / "apps_config.json" -REPORT_DIR = SCRIPT_DIR / "reports" - - -@dataclass -class CheckResult: - """检查结果""" - name: str - status: str # ok, warning, error - message: str - fix_hint: str = "" - - -@dataclass -class AppReport: - """小程序报告""" - app_id: str - app_name: str - appid: str - check_time: str - checks: List[CheckResult] = field(default_factory=list) - summary: Dict = field(default_factory=dict) - - @property - def has_errors(self) -> bool: - return any(c.status == "error" for c in self.checks) - - @property - def has_warnings(self) -> bool: - return any(c.status == "warning" for c in self.checks) - - -class MiniProgramManager: - """小程序全能管理器""" - - # 工具路径 - WX_CLI = "/Applications/wechatwebdevtools.app/Contents/MacOS/cli" - - def __init__(self): - self.config = self._load_config() - REPORT_DIR.mkdir(exist_ok=True) - - def _load_config(self) -> Dict: - if CONFIG_FILE.exists(): - with open(CONFIG_FILE, 'r', encoding='utf-8') as f: - return json.load(f) - return {"apps": []} - - def _save_config(self): - with open(CONFIG_FILE, 'w', encoding='utf-8') as f: - json.dump(self.config, f, ensure_ascii=False, indent=2) - - def get_app(self, app_id: str) -> Optional[Dict]: - for app in self.config.get("apps", []): - if app["id"] == app_id or app["appid"] == app_id: - return app - return None - - def _run_cmd(self, cmd: List[str], timeout: int = 120) -> tuple: - """运行命令""" - try: - result = subprocess.run(cmd, capture_output=True, text=True, timeout=timeout) - return result.returncode == 0, result.stdout + result.stderr - except subprocess.TimeoutExpired: - return False, "命令执行超时" - except Exception as e: - return False, str(e) - - def _check_tool(self, tool: str) -> bool: - """检查工具是否可用""" - success, _ = self._run_cmd(["which", tool], timeout=5) - return success - - # ==================== 检查功能 ==================== - - def check_project(self, app_id: str) -> AppReport: - """检查项目问题""" - app = self.get_app(app_id) - if not app: - print(f"❌ 未找到小程序: {app_id}") - return None - - report = AppReport( - app_id=app["id"], - app_name=app["name"], - appid=app["appid"], - check_time=datetime.now().isoformat() - ) - - project_path = app["project_path"] - - # 1. 检查项目路径 - if os.path.exists(project_path): - report.checks.append(CheckResult("项目路径", "ok", f"路径存在: {project_path}")) - else: - report.checks.append(CheckResult("项目路径", "error", f"路径不存在: {project_path}", "请检查项目路径配置")) - return report # 路径不存在,无法继续检查 - - # 2. 检查project.config.json - config_file = os.path.join(project_path, "project.config.json") - if os.path.exists(config_file): - with open(config_file, 'r') as f: - config = json.load(f) - - if config.get("appid") == app["appid"]: - report.checks.append(CheckResult("AppID配置", "ok", f"AppID正确: {app['appid']}")) - else: - report.checks.append(CheckResult("AppID配置", "error", - f"AppID不匹配: 配置={app['appid']}, 文件={config.get('appid')}", - "请修改project.config.json中的appid")) - else: - report.checks.append(CheckResult("项目配置", "error", "project.config.json不存在", "请确认这是有效的小程序项目")) - - # 3. 检查app.js - app_js = os.path.join(project_path, "app.js") - if os.path.exists(app_js): - with open(app_js, 'r') as f: - content = f.read() - - # 检查API域名 - if "baseUrl" in content or "apiBase" in content: - if "https://" in content: - report.checks.append(CheckResult("API域名", "ok", "已配置HTTPS域名")) - elif "http://localhost" in content: - report.checks.append(CheckResult("API域名", "warning", "使用本地开发地址", "发布前请更换为HTTPS域名")) - else: - report.checks.append(CheckResult("API域名", "warning", "未检测到HTTPS域名")) - - report.checks.append(CheckResult("入口文件", "ok", "app.js存在")) - else: - report.checks.append(CheckResult("入口文件", "error", "app.js不存在")) - - # 4. 检查app.json - app_json = os.path.join(project_path, "app.json") - if os.path.exists(app_json): - with open(app_json, 'r') as f: - app_config = json.load(f) - - pages = app_config.get("pages", []) - if pages: - report.checks.append(CheckResult("页面配置", "ok", f"共{len(pages)}个页面")) - else: - report.checks.append(CheckResult("页面配置", "error", "没有配置页面")) - - # 检查隐私配置 - if app_config.get("__usePrivacyCheck__"): - report.checks.append(CheckResult("隐私配置", "ok", "已启用隐私检查")) - else: - report.checks.append(CheckResult("隐私配置", "warning", "未启用隐私检查", "建议添加 __usePrivacyCheck__: true")) - else: - report.checks.append(CheckResult("应用配置", "error", "app.json不存在")) - - # 5. 检查认证状态 - cert_status = app.get("certification", {}).get("status", "unknown") - if cert_status == "verified": - report.checks.append(CheckResult("企业认证", "ok", "已完成认证")) - elif cert_status == "pending": - report.checks.append(CheckResult("企业认证", "warning", "认证审核中", "等待审核结果")) - elif cert_status == "expired": - report.checks.append(CheckResult("企业认证", "error", "认证已过期", "请尽快完成年审")) - else: - report.checks.append(CheckResult("企业认证", "warning", "未认证", "无法发布上线,请先完成认证")) - - # 6. 检查开发工具 - if os.path.exists(self.WX_CLI): - report.checks.append(CheckResult("开发者工具", "ok", "微信开发者工具已安装")) - else: - report.checks.append(CheckResult("开发者工具", "error", "微信开发者工具未安装")) - - # 7. 检查miniprogram-ci - if self._check_tool("miniprogram-ci"): - report.checks.append(CheckResult("miniprogram-ci", "ok", "npm工具已安装")) - else: - report.checks.append(CheckResult("miniprogram-ci", "warning", "miniprogram-ci未安装", "运行: npm install -g miniprogram-ci")) - - # 8. 检查私钥 - if app.get("private_key_path") and os.path.exists(app["private_key_path"]): - report.checks.append(CheckResult("上传密钥", "ok", "私钥文件存在")) - else: - report.checks.append(CheckResult("上传密钥", "warning", "未配置私钥", "在小程序后台下载代码上传密钥")) - - # 生成汇总 - ok_count = sum(1 for c in report.checks if c.status == "ok") - warn_count = sum(1 for c in report.checks if c.status == "warning") - error_count = sum(1 for c in report.checks if c.status == "error") - - report.summary = { - "total": len(report.checks), - "ok": ok_count, - "warning": warn_count, - "error": error_count, - "can_deploy": error_count == 0, - "can_release": cert_status == "verified" and error_count == 0 - } - - return report - - def print_report(self, report: AppReport): - """打印报告""" - print("\n" + "=" * 70) - print(f" 📊 项目检查报告: {report.app_name}") - print("=" * 70) - print(f" AppID: {report.appid}") - print(f" 检查时间: {report.check_time}") - print("-" * 70) - - status_icons = {"ok": "✅", "warning": "⚠️", "error": "❌"} - - for check in report.checks: - icon = status_icons.get(check.status, "❓") - print(f" {icon} {check.name}: {check.message}") - if check.fix_hint: - print(f" 💡 {check.fix_hint}") - - print("-" * 70) - s = report.summary - print(f" 📈 汇总: 通过 {s['ok']} / 警告 {s['warning']} / 错误 {s['error']}") - - if s['can_release']: - print(" 🎉 状态: 可以发布上线") - elif s['can_deploy']: - print(" 📦 状态: 可以上传代码,但无法发布(需完成认证)") - else: - print(" 🚫 状态: 存在错误,请先修复") - - print("=" * 70 + "\n") - - def save_report(self, report: AppReport): - """保存报告到文件""" - filename = f"report_{report.app_id}_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json" - filepath = REPORT_DIR / filename - - with open(filepath, 'w', encoding='utf-8') as f: - json.dump(asdict(report), f, ensure_ascii=False, indent=2) - - return filepath - - # ==================== 自动化部署 ==================== - - def auto_deploy(self, app_id: str, version: str = None, desc: str = None, submit_audit: bool = True) -> bool: - """全自动部署:编译 → 上传 → 提审""" - app = self.get_app(app_id) - if not app: - print(f"❌ 未找到小程序: {app_id}") - return False - - print("\n" + "=" * 70) - print(f" 🚀 全自动部署: {app['name']}") - print("=" * 70) - - # 1. 先检查项目 - print("\n📋 步骤1: 检查项目...") - report = self.check_project(app_id) - if report.has_errors: - print("❌ 项目存在错误,无法部署") - self.print_report(report) - return False - print("✅ 项目检查通过") - - # 2. 准备版本信息 - if not version: - version = datetime.now().strftime("%Y.%m.%d.%H%M") - if not desc: - desc = f"自动部署 - {datetime.now().strftime('%Y-%m-%d %H:%M')}" - - print(f"\n📦 步骤2: 上传代码...") - print(f" 版本: {version}") - print(f" 描述: {desc}") - - # 3. 上传代码 - success = self._upload_code(app, version, desc) - if not success: - print("❌ 代码上传失败") - return False - print("✅ 代码上传成功") - - # 4. 提交审核 - if submit_audit: - print(f"\n📝 步骤3: 提交审核...") - cert_status = app.get("certification", {}).get("status", "unknown") - - if cert_status != "verified": - print(f"⚠️ 认证状态: {cert_status}") - print(" 未认证的小程序无法提交审核") - print(" 代码已上传到开发版,请在微信后台手动提交") - print("\n" + "-" * 40) - print("👉 下一步操作:") - print(" 1. 完成企业认证") - print(" 2. 在微信后台提交审核") - print(" 3. 审核通过后发布上线") - else: - # 尝试通过API提交审核 - audit_success = self._submit_audit_via_api(app) - if audit_success: - print("✅ 审核已提交") - else: - print("⚠️ 自动提审失败,请在微信后台手动提交") - print(" 登录: https://mp.weixin.qq.com/") - print(" 版本管理 → 开发版本 → 提交审核") - - # 5. 生成报告 - print(f"\n📊 步骤4: 生成报告...") - report_file = self.save_report(report) - print(f"✅ 报告已保存: {report_file}") - - print("\n" + "=" * 70) - print(" 🎉 部署完成!") - print("=" * 70) - - return True - - def _upload_code(self, app: Dict, version: str, desc: str) -> bool: - """上传代码(优先使用CLI)""" - project_path = app["project_path"] - - # 方法1:使用微信开发者工具CLI - if os.path.exists(self.WX_CLI): - cmd = [ - self.WX_CLI, "upload", - "--project", project_path, - "--version", version, - "--desc", desc - ] - success, output = self._run_cmd(cmd, timeout=120) - if success: - return True - print(f" CLI上传失败: {output[:200]}") - - # 方法2:使用miniprogram-ci - if self._check_tool("miniprogram-ci") and app.get("private_key_path"): - cmd = [ - "miniprogram-ci", "upload", - "--pp", project_path, - "--pkp", app["private_key_path"], - "--appid", app["appid"], - "--uv", version, - "-r", "1", - "--desc", desc - ] - success, output = self._run_cmd(cmd, timeout=120) - if success: - return True - print(f" miniprogram-ci上传失败: {output[:200]}") - - return False - - def _submit_audit_via_api(self, app: Dict) -> bool: - """通过API提交审核(需要access_token)""" - # 这里需要access_token才能调用API - # 目前返回False,提示用户手动提交 - return False - - # ==================== 汇总报告 ==================== - - def generate_summary_report(self): - """生成所有小程序的汇总报告""" - apps = self.config.get("apps", []) - - if not apps: - print("📭 暂无配置的小程序") - return - - print("\n" + "=" * 80) - print(" 📊 小程序管理汇总报告") - print(f" 生成时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}") - print("=" * 80) - - all_reports = [] - - for app in apps: - report = self.check_project(app["id"]) - if report: - all_reports.append(report) - - # 打印汇总表格 - print("\n┌" + "─" * 78 + "┐") - print(f"│ {'小程序名称':<20} │ {'AppID':<25} │ {'状态':<10} │ {'可发布':<8} │") - print("├" + "─" * 78 + "┤") - - for report in all_reports: - status = "✅ 正常" if not report.has_errors else "❌ 错误" - can_release = "✅" if report.summary.get("can_release") else "❌" - print(f"│ {report.app_name:<20} │ {report.appid:<25} │ {status:<10} │ {can_release:<8} │") - - print("└" + "─" * 78 + "┘") - - # 统计 - total = len(all_reports) - ok_count = sum(1 for r in all_reports if not r.has_errors and not r.has_warnings) - warn_count = sum(1 for r in all_reports if r.has_warnings and not r.has_errors) - error_count = sum(1 for r in all_reports if r.has_errors) - can_release = sum(1 for r in all_reports if r.summary.get("can_release")) - - print(f"\n📈 统计:") - print(f" 总计: {total} 个小程序") - print(f" 正常: {ok_count} | 警告: {warn_count} | 错误: {error_count}") - print(f" 可发布: {can_release} 个") - - # 问题清单 - issues = [] - for report in all_reports: - for check in report.checks: - if check.status == "error": - issues.append((report.app_name, check.name, check.message, check.fix_hint)) - - if issues: - print(f"\n⚠️ 问题清单 ({len(issues)} 个):") - print("-" * 60) - for app_name, check_name, message, hint in issues: - print(f" [{app_name}] {check_name}: {message}") - if hint: - print(f" 💡 {hint}") - else: - print(f"\n✅ 所有小程序状态正常") - - # 待办事项 - print(f"\n📋 待办事项:") - for report in all_reports: - cert_status = "unknown" - for check in report.checks: - if check.name == "企业认证": - if "审核中" in check.message: - cert_status = "pending" - elif "已完成" in check.message: - cert_status = "verified" - elif "未认证" in check.message: - cert_status = "unknown" - break - - if cert_status == "pending": - print(f" ⏳ {report.app_name}: 等待认证审核结果") - elif cert_status == "unknown": - print(f" 📝 {report.app_name}: 需要完成企业认证") - - print("\n" + "=" * 80) - - # 保存汇总报告 - summary_file = REPORT_DIR / f"summary_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json" - summary_data = { - "generated_at": datetime.now().isoformat(), - "total_apps": total, - "summary": { - "ok": ok_count, - "warning": warn_count, - "error": error_count, - "can_release": can_release - }, - "apps": [asdict(r) for r in all_reports] - } - with open(summary_file, 'w', encoding='utf-8') as f: - json.dump(summary_data, f, ensure_ascii=False, indent=2) - - print(f"📁 报告已保存: {summary_file}\n") - - -def main(): - parser = argparse.ArgumentParser( - description="小程序全能管理工具 v3.0", - formatter_class=argparse.RawDescriptionHelpFormatter, - epilog=""" -示例: - python mp_full.py report 生成汇总报告 - python mp_full.py check soul-party 检查项目问题 - python mp_full.py auto soul-party 全自动部署(上传+提审) - python mp_full.py auto soul-party -v 1.0.13 -d "修复问题" - -流程说明: - ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ - │ 检查 │ → │ 编译 │ → │ 上传 │ → │ 提审 │ → │ 发布 │ - │ check │ │ build │ │ upload │ │ audit │ │ release │ - └─────────┘ └─────────┘ └─────────┘ └─────────┘ └─────────┘ - -工具整合: - • 微信开发者工具CLI - 本地编译上传 - • miniprogram-ci - npm官方CI工具 - • 开放平台API - 审核/发布/认证 -""" - ) - - subparsers = parser.add_subparsers(dest="command", help="子命令") - - # report - subparsers.add_parser("report", help="生成汇总报告") - - # check - check_parser = subparsers.add_parser("check", help="检查项目问题") - check_parser.add_argument("app_id", help="小程序ID") - - # auto - auto_parser = subparsers.add_parser("auto", help="全自动部署") - auto_parser.add_argument("app_id", help="小程序ID") - auto_parser.add_argument("-v", "--version", help="版本号") - auto_parser.add_argument("-d", "--desc", help="版本描述") - auto_parser.add_argument("--no-audit", action="store_true", help="不提交审核") - - args = parser.parse_args() - - if not args.command: - parser.print_help() - return - - manager = MiniProgramManager() - - if args.command == "report": - manager.generate_summary_report() - - elif args.command == "check": - report = manager.check_project(args.app_id) - if report: - manager.print_report(report) - manager.save_report(report) - - elif args.command == "auto": - manager.auto_deploy( - args.app_id, - version=args.version, - desc=args.desc, - submit_audit=not args.no_audit - ) - - -if __name__ == "__main__": - main() diff --git a/开发文档/小程序管理/scripts/mp_manager.py b/开发文档/小程序管理/scripts/mp_manager.py deleted file mode 100644 index 197f780d..00000000 --- a/开发文档/小程序管理/scripts/mp_manager.py +++ /dev/null @@ -1,558 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -""" -微信小程序管理命令行工具 - -使用方法: - python mp_manager.py status # 查看小程序状态 - python mp_manager.py audit # 查看审核状态 - python mp_manager.py release # 发布上线 - python mp_manager.py qrcode # 生成小程序码 - python mp_manager.py domain # 查看/配置域名 - python mp_manager.py privacy # 配置隐私协议 - python mp_manager.py data # 查看数据分析 -""" - -import os -import sys -import argparse -from datetime import datetime, timedelta -from pathlib import Path - -# 添加当前目录到路径 -sys.path.insert(0, str(Path(__file__).parent)) - -from mp_api import MiniProgramAPI, APIError, create_api_from_env - - -def print_header(title: str): - """打印标题""" - print("\n" + "=" * 50) - print(f" {title}") - print("=" * 50) - - -def print_success(message: str): - """打印成功信息""" - print(f"✅ {message}") - - -def print_error(message: str): - """打印错误信息""" - print(f"❌ {message}") - - -def print_info(message: str): - """打印信息""" - print(f"ℹ️ {message}") - - -def cmd_status(api: MiniProgramAPI, args): - """查看小程序状态""" - print_header("小程序基础信息") - - try: - info = api.get_basic_info() - print(f"\n📱 AppID: {info.appid}") - print(f"📝 名称: {info.nickname}") - print(f"📄 简介: {info.signature}") - print(f"🏢 主体: {info.principal_name}") - print(f"✓ 认证状态: {'已认证' if info.realname_status == 1 else '未认证'}") - - if info.head_image_url: - print(f"🖼️ 头像: {info.head_image_url}") - - # 获取类目 - print("\n📂 已设置类目:") - categories = api.get_category() - if categories: - for cat in categories: - print(f" - {cat.get('first_class', '')} > {cat.get('second_class', '')}") - else: - print(" (未设置类目)") - - except APIError as e: - print_error(f"获取信息失败: {e}") - - -def cmd_audit(api: MiniProgramAPI, args): - """查看审核状态""" - print_header("审核状态") - - try: - status = api.get_latest_audit_status() - print(f"\n🔢 审核单ID: {status.auditid}") - print(f"📊 状态: {status.status_text}") - - if status.reason: - print(f"\n❗ 拒绝原因:") - print(f" {status.reason}") - - if status.screenshot: - print(f"\n📸 问题截图: {status.screenshot}") - - if status.status == 0: - print("\n👉 下一步: 运行 'python mp_manager.py release' 发布上线") - elif status.status == 1: - print("\n👉 请根据拒绝原因修改后重新提交审核") - elif status.status == 2: - print("\n👉 审核中,请耐心等待(通常1-3个工作日)") - print(" 可运行 'python mp_manager.py audit' 再次查询") - - except APIError as e: - print_error(f"获取审核状态失败: {e}") - - -def cmd_submit(api: MiniProgramAPI, args): - """提交审核""" - print_header("提交审核") - - version_desc = args.desc or input("请输入版本说明: ").strip() - if not version_desc: - print_error("版本说明不能为空") - return - - try: - # 获取页面列表 - pages = api.get_page() - if not pages: - print_error("未找到页面,请先上传代码") - return - - print(f"\n📄 检测到 {len(pages)} 个页面:") - for p in pages[:5]: - print(f" - {p}") - if len(pages) > 5: - print(f" ... 还有 {len(pages) - 5} 个") - - # 确认提交 - confirm = input("\n确认提交审核? (y/n): ").strip().lower() - if confirm != 'y': - print_info("已取消") - return - - auditid = api.submit_audit(version_desc=version_desc) - print_success(f"审核已提交,审核单ID: {auditid}") - print("\n👉 运行 'python mp_manager.py audit' 查询审核状态") - - except APIError as e: - print_error(f"提交审核失败: {e}") - - -def cmd_release(api: MiniProgramAPI, args): - """发布上线""" - print_header("发布上线") - - try: - # 先检查审核状态 - status = api.get_latest_audit_status() - if status.status != 0: - print_error(f"当前审核状态: {status.status_text}") - print_info("只有审核通过的版本才能发布") - return - - print(f"📊 审核状态: {status.status_text}") - - # 确认发布 - confirm = input("\n确认发布上线? (y/n): ").strip().lower() - if confirm != 'y': - print_info("已取消") - return - - api.release() - print_success("🎉 发布成功!小程序已上线") - - except APIError as e: - print_error(f"发布失败: {e}") - - -def cmd_revert(api: MiniProgramAPI, args): - """版本回退""" - print_header("版本回退") - - try: - # 获取可回退版本 - history = api.get_revert_history() - if not history: - print_info("没有可回退的版本") - return - - print("\n📜 可回退版本:") - for v in history: - print(f" - {v.get('user_version', '?')}: {v.get('user_desc', '')}") - - # 确认回退 - confirm = input("\n确认回退到上一版本? (y/n): ").strip().lower() - if confirm != 'y': - print_info("已取消") - return - - api.revert_code_release() - print_success("版本回退成功") - - except APIError as e: - print_error(f"版本回退失败: {e}") - - -def cmd_qrcode(api: MiniProgramAPI, args): - """生成小程序码""" - print_header("生成小程序码") - - # 场景选择 - print("\n选择类型:") - print(" 1. 体验版二维码") - print(" 2. 小程序码(有限制,每个path最多10万个)") - print(" 3. 无限小程序码(推荐)") - - choice = args.type or input("\n请选择 (1/2/3): ").strip() - - output_file = args.output or f"qrcode_{datetime.now().strftime('%Y%m%d_%H%M%S')}.png" - - try: - if choice == "1": - # 体验版二维码 - path = args.path or input("页面路径 (默认首页): ").strip() or None - data = api.get_qrcode(path) - - elif choice == "2": - # 小程序码 - path = args.path or input("页面路径: ").strip() - if not path: - print_error("页面路径不能为空") - return - data = api.get_wxacode(path) - - elif choice == "3": - # 无限小程序码 - scene = args.scene or input("场景值 (最长32字符): ").strip() - if not scene: - print_error("场景值不能为空") - return - page = args.path or input("页面路径 (需已发布): ").strip() or None - data = api.get_wxacode_unlimit(scene, page) - - else: - print_error("无效选择") - return - - # 保存文件 - with open(output_file, "wb") as f: - f.write(data) - - print_success(f"小程序码已保存: {output_file}") - - # 尝试打开 - if sys.platform == "darwin": - os.system(f'open "{output_file}"') - - except APIError as e: - print_error(f"生成小程序码失败: {e}") - - -def cmd_domain(api: MiniProgramAPI, args): - """查看/配置域名""" - print_header("域名配置") - - try: - # 获取当前配置 - domains = api.get_domain() - webview_domains = api.get_webview_domain() - - print("\n🌐 服务器域名:") - print(f" request: {', '.join(domains.get('requestdomain', [])) or '(无)'}") - print(f" wsrequest: {', '.join(domains.get('wsrequestdomain', [])) or '(无)'}") - print(f" upload: {', '.join(domains.get('uploaddomain', [])) or '(无)'}") - print(f" download: {', '.join(domains.get('downloaddomain', [])) or '(无)'}") - - print(f"\n🔗 业务域名:") - print(f" webview: {', '.join(webview_domains) or '(无)'}") - - # 是否要配置 - if args.set_request: - print(f"\n配置 request 域名: {args.set_request}") - api.set_domain(requestdomain=[args.set_request]) - print_success("域名配置成功") - - except APIError as e: - print_error(f"域名配置失败: {e}") - - -def cmd_privacy(api: MiniProgramAPI, args): - """配置隐私协议""" - print_header("隐私协议配置") - - try: - # 获取当前配置 - settings = api.get_privacy_setting() - - print("\n📋 当前隐私设置:") - setting_list = settings.get("setting_list", []) - if setting_list: - for s in setting_list: - print(f" - {s.get('privacy_key', '?')}: {s.get('privacy_text', '')}") - else: - print(" (未配置)") - - owner = settings.get("owner_setting", {}) - if owner: - print(f"\n📧 联系方式:") - if owner.get("contact_email"): - print(f" 邮箱: {owner['contact_email']}") - if owner.get("contact_phone"): - print(f" 电话: {owner['contact_phone']}") - - # 快速配置 - if args.quick: - print("\n⚡ 快速配置常用隐私项...") - - default_settings = [ - {"privacy_key": "UserInfo", "privacy_text": "用于展示您的头像和昵称"}, - {"privacy_key": "Location", "privacy_text": "用于获取您的位置信息以推荐附近服务"}, - {"privacy_key": "PhoneNumber", "privacy_text": "用于登录验证和订单通知"}, - ] - - api.set_privacy_setting( - setting_list=default_settings, - contact_email=args.email or "contact@example.com", - contact_phone=args.phone or "15880802661" - ) - print_success("隐私协议配置成功") - - except APIError as e: - print_error(f"隐私协议配置失败: {e}") - - -def cmd_data(api: MiniProgramAPI, args): - """查看数据分析""" - print_header("数据分析") - - # 默认查询最近7天 - end_date = datetime.now().strftime("%Y%m%d") - begin_date = (datetime.now() - timedelta(days=7)).strftime("%Y%m%d") - - if args.begin: - begin_date = args.begin - if args.end: - end_date = args.end - - try: - print(f"\n📊 访问趋势 ({begin_date} ~ {end_date}):") - - data = api.get_daily_visit_trend(begin_date, end_date) - if not data: - print(" (暂无数据)") - return - - # 统计汇总 - total_pv = sum(d.get("visit_pv", 0) for d in data) - total_uv = sum(d.get("visit_uv", 0) for d in data) - total_new = sum(d.get("visit_uv_new", 0) for d in data) - - print(f"\n📈 汇总数据:") - print(f" 总访问次数: {total_pv:,}") - print(f" 总访问人数: {total_uv:,}") - print(f" 新用户数: {total_new:,}") - - print(f"\n📅 每日明细:") - for d in data[-7:]: # 只显示最近7天 - date = d.get("ref_date", "?") - pv = d.get("visit_pv", 0) - uv = d.get("visit_uv", 0) - stay = d.get("stay_time_uv", 0) - print(f" {date}: PV={pv}, UV={uv}, 人均停留={stay:.1f}秒") - - except APIError as e: - print_error(f"获取数据失败: {e}") - - -def cmd_quota(api: MiniProgramAPI, args): - """查看API配额""" - print_header("API配额") - - common_apis = [ - "/wxa/getwxacode", - "/wxa/getwxacodeunlimit", - "/wxa/genwxashortlink", - "/wxa/submit_audit", - "/cgi-bin/message/subscribe/send" - ] - - try: - for cgi_path in common_apis: - try: - quota = api.get_api_quota(cgi_path) - daily_limit = quota.get("daily_limit", 0) - used = quota.get("used", 0) - remain = quota.get("remain", 0) - - print(f"\n📌 {cgi_path}") - print(f" 每日限额: {daily_limit:,}") - print(f" 已使用: {used:,}") - print(f" 剩余: {remain:,}") - except APIError: - pass - - except APIError as e: - print_error(f"获取配额失败: {e}") - - -def cmd_cli(api: MiniProgramAPI, args): - """使用微信开发者工具CLI""" - print_header("微信开发者工具CLI") - - cli_path = "/Applications/wechatwebdevtools.app/Contents/MacOS/cli" - project_path = args.project or os.getenv("MINIPROGRAM_PATH", "") - - if not project_path: - project_path = input("请输入小程序项目路径: ").strip() - - if not os.path.exists(project_path): - print_error(f"项目路径不存在: {project_path}") - return - - if not os.path.exists(cli_path): - print_error("未找到微信开发者工具,请先安装") - return - - print(f"\n📂 项目路径: {project_path}") - print("\n选择操作:") - print(" 1. 打开项目") - print(" 2. 预览(生成二维码)") - print(" 3. 上传代码") - print(" 4. 编译") - - choice = input("\n请选择: ").strip() - - if choice == "1": - os.system(f'"{cli_path}" -o "{project_path}"') - print_success("项目已打开") - - elif choice == "2": - output = f"{project_path}/preview.png" - os.system(f'"{cli_path}" preview --project "{project_path}" --qr-format image --qr-output "{output}"') - if os.path.exists(output): - print_success(f"预览二维码已生成: {output}") - os.system(f'open "{output}"') - else: - print_error("生成失败,请检查开发者工具是否已登录") - - elif choice == "3": - version = input("版本号 (如 1.0.0): ").strip() - desc = input("版本说明: ").strip() - os.system(f'"{cli_path}" upload --project "{project_path}" --version "{version}" --desc "{desc}"') - print_success("代码上传完成") - - elif choice == "4": - os.system(f'"{cli_path}" build-npm --project "{project_path}"') - print_success("编译完成") - - else: - print_error("无效选择") - - -def main(): - parser = argparse.ArgumentParser( - description="微信小程序管理工具", - formatter_class=argparse.RawDescriptionHelpFormatter, - epilog=""" -示例: - python mp_manager.py status 查看小程序状态 - python mp_manager.py audit 查看审核状态 - python mp_manager.py submit -d "修复xxx问题" 提交审核 - python mp_manager.py release 发布上线 - python mp_manager.py qrcode -t 3 -s "id=123" 生成无限小程序码 - python mp_manager.py domain 查看域名配置 - python mp_manager.py privacy --quick 快速配置隐私协议 - python mp_manager.py data 查看数据分析 - python mp_manager.py cli 使用开发者工具CLI -""" - ) - - subparsers = parser.add_subparsers(dest="command", help="子命令") - - # status - subparsers.add_parser("status", help="查看小程序状态") - - # audit - subparsers.add_parser("audit", help="查看审核状态") - - # submit - submit_parser = subparsers.add_parser("submit", help="提交审核") - submit_parser.add_argument("-d", "--desc", help="版本说明") - - # release - subparsers.add_parser("release", help="发布上线") - - # revert - subparsers.add_parser("revert", help="版本回退") - - # qrcode - qr_parser = subparsers.add_parser("qrcode", help="生成小程序码") - qr_parser.add_argument("-t", "--type", choices=["1", "2", "3"], help="类型:1=体验版,2=小程序码,3=无限小程序码") - qr_parser.add_argument("-p", "--path", help="页面路径") - qr_parser.add_argument("-s", "--scene", help="场景值(类型3时使用)") - qr_parser.add_argument("-o", "--output", help="输出文件名") - - # domain - domain_parser = subparsers.add_parser("domain", help="查看/配置域名") - domain_parser.add_argument("--set-request", help="设置request域名") - - # privacy - privacy_parser = subparsers.add_parser("privacy", help="配置隐私协议") - privacy_parser.add_argument("--quick", action="store_true", help="快速配置常用隐私项") - privacy_parser.add_argument("--email", help="联系邮箱") - privacy_parser.add_argument("--phone", help="联系电话") - - # data - data_parser = subparsers.add_parser("data", help="查看数据分析") - data_parser.add_argument("--begin", help="开始日期 YYYYMMDD") - data_parser.add_argument("--end", help="结束日期 YYYYMMDD") - - # quota - subparsers.add_parser("quota", help="查看API配额") - - # cli - cli_parser = subparsers.add_parser("cli", help="使用微信开发者工具CLI") - cli_parser.add_argument("-p", "--project", help="小程序项目路径") - - args = parser.parse_args() - - if not args.command: - parser.print_help() - return - - # 创建API实例 - try: - api = create_api_from_env() - except Exception as e: - print_error(f"初始化API失败: {e}") - print_info("请检查 .env 文件中的配置") - return - - # 执行命令 - commands = { - "status": cmd_status, - "audit": cmd_audit, - "submit": cmd_submit, - "release": cmd_release, - "revert": cmd_revert, - "qrcode": cmd_qrcode, - "domain": cmd_domain, - "privacy": cmd_privacy, - "data": cmd_data, - "quota": cmd_quota, - "cli": cmd_cli, - } - - cmd_func = commands.get(args.command) - if cmd_func: - try: - cmd_func(api, args) - finally: - api.close() - else: - parser.print_help() - - -if __name__ == "__main__": - main() diff --git a/开发文档/小程序管理/scripts/reports/report_soul-party_20260125_113301.json b/开发文档/小程序管理/scripts/reports/report_soul-party_20260125_113301.json deleted file mode 100644 index 628d5a38..00000000 --- a/开发文档/小程序管理/scripts/reports/report_soul-party_20260125_113301.json +++ /dev/null @@ -1,76 +0,0 @@ -{ - "app_id": "soul-party", - "app_name": "Soul派对", - "appid": "wxb8bbb2b10dec74aa", - "check_time": "2026-01-25T11:33:01.054516", - "checks": [ - { - "name": "项目路径", - "status": "ok", - "message": "路径存在: /Users/karuo/Documents/开发/3、自营项目/一场soul的创业实验/miniprogram", - "fix_hint": "" - }, - { - "name": "AppID配置", - "status": "ok", - "message": "AppID正确: wxb8bbb2b10dec74aa", - "fix_hint": "" - }, - { - "name": "API域名", - "status": "ok", - "message": "已配置HTTPS域名", - "fix_hint": "" - }, - { - "name": "入口文件", - "status": "ok", - "message": "app.js存在", - "fix_hint": "" - }, - { - "name": "页面配置", - "status": "ok", - "message": "共9个页面", - "fix_hint": "" - }, - { - "name": "隐私配置", - "status": "warning", - "message": "未启用隐私检查", - "fix_hint": "建议添加 __usePrivacyCheck__: true" - }, - { - "name": "企业认证", - "status": "warning", - "message": "认证审核中", - "fix_hint": "等待审核结果" - }, - { - "name": "开发者工具", - "status": "ok", - "message": "微信开发者工具已安装", - "fix_hint": "" - }, - { - "name": "miniprogram-ci", - "status": "ok", - "message": "npm工具已安装", - "fix_hint": "" - }, - { - "name": "上传密钥", - "status": "warning", - "message": "未配置私钥", - "fix_hint": "在小程序后台下载代码上传密钥" - } - ], - "summary": { - "total": 10, - "ok": 7, - "warning": 3, - "error": 0, - "can_deploy": true, - "can_release": false - } -} \ No newline at end of file diff --git a/开发文档/小程序管理/scripts/reports/report_soul-party_20260125_113423.json b/开发文档/小程序管理/scripts/reports/report_soul-party_20260125_113423.json deleted file mode 100644 index 60ca8c23..00000000 --- a/开发文档/小程序管理/scripts/reports/report_soul-party_20260125_113423.json +++ /dev/null @@ -1,76 +0,0 @@ -{ - "app_id": "soul-party", - "app_name": "Soul派对", - "appid": "wxb8bbb2b10dec74aa", - "check_time": "2026-01-25T11:34:23.760802", - "checks": [ - { - "name": "项目路径", - "status": "ok", - "message": "路径存在: /Users/karuo/Documents/开发/3、自营项目/一场soul的创业实验/miniprogram", - "fix_hint": "" - }, - { - "name": "AppID配置", - "status": "ok", - "message": "AppID正确: wxb8bbb2b10dec74aa", - "fix_hint": "" - }, - { - "name": "API域名", - "status": "ok", - "message": "已配置HTTPS域名", - "fix_hint": "" - }, - { - "name": "入口文件", - "status": "ok", - "message": "app.js存在", - "fix_hint": "" - }, - { - "name": "页面配置", - "status": "ok", - "message": "共9个页面", - "fix_hint": "" - }, - { - "name": "隐私配置", - "status": "ok", - "message": "已启用隐私检查", - "fix_hint": "" - }, - { - "name": "企业认证", - "status": "warning", - "message": "认证审核中", - "fix_hint": "等待审核结果" - }, - { - "name": "开发者工具", - "status": "ok", - "message": "微信开发者工具已安装", - "fix_hint": "" - }, - { - "name": "miniprogram-ci", - "status": "ok", - "message": "npm工具已安装", - "fix_hint": "" - }, - { - "name": "上传密钥", - "status": "warning", - "message": "未配置私钥", - "fix_hint": "在小程序后台下载代码上传密钥" - } - ], - "summary": { - "total": 10, - "ok": 8, - "warning": 2, - "error": 0, - "can_deploy": true, - "can_release": false - } -} \ No newline at end of file diff --git a/开发文档/小程序管理/scripts/reports/report_soul-party_20260125_113434.json b/开发文档/小程序管理/scripts/reports/report_soul-party_20260125_113434.json deleted file mode 100644 index 83e19c8e..00000000 --- a/开发文档/小程序管理/scripts/reports/report_soul-party_20260125_113434.json +++ /dev/null @@ -1,76 +0,0 @@ -{ - "app_id": "soul-party", - "app_name": "Soul派对", - "appid": "wxb8bbb2b10dec74aa", - "check_time": "2026-01-25T11:34:28.854418", - "checks": [ - { - "name": "项目路径", - "status": "ok", - "message": "路径存在: /Users/karuo/Documents/开发/3、自营项目/一场soul的创业实验/miniprogram", - "fix_hint": "" - }, - { - "name": "AppID配置", - "status": "ok", - "message": "AppID正确: wxb8bbb2b10dec74aa", - "fix_hint": "" - }, - { - "name": "API域名", - "status": "ok", - "message": "已配置HTTPS域名", - "fix_hint": "" - }, - { - "name": "入口文件", - "status": "ok", - "message": "app.js存在", - "fix_hint": "" - }, - { - "name": "页面配置", - "status": "ok", - "message": "共9个页面", - "fix_hint": "" - }, - { - "name": "隐私配置", - "status": "ok", - "message": "已启用隐私检查", - "fix_hint": "" - }, - { - "name": "企业认证", - "status": "warning", - "message": "认证审核中", - "fix_hint": "等待审核结果" - }, - { - "name": "开发者工具", - "status": "ok", - "message": "微信开发者工具已安装", - "fix_hint": "" - }, - { - "name": "miniprogram-ci", - "status": "ok", - "message": "npm工具已安装", - "fix_hint": "" - }, - { - "name": "上传密钥", - "status": "warning", - "message": "未配置私钥", - "fix_hint": "在小程序后台下载代码上传密钥" - } - ], - "summary": { - "total": 10, - "ok": 8, - "warning": 2, - "error": 0, - "can_deploy": true, - "can_release": false - } -} \ No newline at end of file diff --git a/开发文档/小程序管理/scripts/reports/summary_20260125_113255.json b/开发文档/小程序管理/scripts/reports/summary_20260125_113255.json deleted file mode 100644 index 88ed994a..00000000 --- a/开发文档/小程序管理/scripts/reports/summary_20260125_113255.json +++ /dev/null @@ -1,88 +0,0 @@ -{ - "generated_at": "2026-01-25T11:32:55.447833", - "total_apps": 1, - "summary": { - "ok": 0, - "warning": 1, - "error": 0, - "can_release": 0 - }, - "apps": [ - { - "app_id": "soul-party", - "app_name": "Soul派对", - "appid": "wxb8bbb2b10dec74aa", - "check_time": "2026-01-25T11:32:55.428736", - "checks": [ - { - "name": "项目路径", - "status": "ok", - "message": "路径存在: /Users/karuo/Documents/开发/3、自营项目/一场soul的创业实验/miniprogram", - "fix_hint": "" - }, - { - "name": "AppID配置", - "status": "ok", - "message": "AppID正确: wxb8bbb2b10dec74aa", - "fix_hint": "" - }, - { - "name": "API域名", - "status": "ok", - "message": "已配置HTTPS域名", - "fix_hint": "" - }, - { - "name": "入口文件", - "status": "ok", - "message": "app.js存在", - "fix_hint": "" - }, - { - "name": "页面配置", - "status": "ok", - "message": "共9个页面", - "fix_hint": "" - }, - { - "name": "隐私配置", - "status": "warning", - "message": "未启用隐私检查", - "fix_hint": "建议添加 __usePrivacyCheck__: true" - }, - { - "name": "企业认证", - "status": "warning", - "message": "认证审核中", - "fix_hint": "等待审核结果" - }, - { - "name": "开发者工具", - "status": "ok", - "message": "微信开发者工具已安装", - "fix_hint": "" - }, - { - "name": "miniprogram-ci", - "status": "ok", - "message": "npm工具已安装", - "fix_hint": "" - }, - { - "name": "上传密钥", - "status": "warning", - "message": "未配置私钥", - "fix_hint": "在小程序后台下载代码上传密钥" - } - ], - "summary": { - "total": 10, - "ok": 7, - "warning": 3, - "error": 0, - "can_deploy": true, - "can_release": false - } - } - ] -} \ No newline at end of file diff --git a/开发文档/小程序管理/scripts/requirements.txt b/开发文档/小程序管理/scripts/requirements.txt deleted file mode 100644 index 29b7c9d3..00000000 --- a/开发文档/小程序管理/scripts/requirements.txt +++ /dev/null @@ -1,7 +0,0 @@ -# 微信小程序管理工具依赖 - -# HTTP客户端 -httpx>=0.25.0 - -# 环境变量管理 -python-dotenv>=1.0.0 diff --git a/开发文档/服务器管理/SKILL.md b/开发文档/服务器管理/SKILL.md deleted file mode 100644 index 8bce80cd..00000000 --- a/开发文档/服务器管理/SKILL.md +++ /dev/null @@ -1,314 +0,0 @@ ---- -name: 服务器管理 -description: 宝塔服务器统一管理与自动化部署。触发词:服务器、宝塔、部署、上线、发布、Node项目、SSL证书、HTTPS、DNS解析、域名配置、端口、PM2、Nginx、MySQL数据库、服务器状态。涵盖多服务器资产管理、Node.js项目一键部署、SSL证书管理、DNS配置、系统诊断等运维能力。 ---- - -# 服务器管理 - -让 AI 写完代码后,无需人工介入,自动把项目「变成一个在线网站」。 - ---- - -## 快速入口(复制即用) - -### 服务器资产 - -| 服务器 | IP | 配置 | 用途 | 宝塔面板 | -|--------|-----|------|------|----------| -| **小型宝塔** | 42.194.232.22 | 2核4G 5M | 主力部署(Node项目) | https://42.194.232.22:9988/ckbpanel | -| **存客宝** | 42.194.245.239 | 2核16G 50M | 私域银行业务 | https://42.194.245.239:9988 | -| **kr宝塔** | 43.139.27.93 | 2核4G 5M | 辅助服务器 | https://43.139.27.93:9988 | - -### 凭证速查 - -```bash -# SSH连接(小型宝塔为例) -ssh root@42.194.232.22 -密码: Zhiqun1984 - -# 宝塔面板登录(小型宝塔) -地址: https://42.194.232.22:9988/ckbpanel -账号: ckb -密码: zhiqun1984 - -# 宝塔API密钥 -小型宝塔: hsAWqFSi0GOCrunhmYdkxy92tBXfqYjd -存客宝: TNKjqDv5N1QLOU20gcmGVgr82Z4mXzRi -kr宝塔: qcWubCdlfFjS2b2DMT1lzPFaDfmv1cBT -``` - ---- - -## 一键操作 - -### 1. 检查服务器状态 - -```bash -# 运行快速检查脚本 -python3 /Users/karuo/Documents/个人/卡若AI/01_系统管理/服务器管理/scripts/快速检查服务器.py -``` - -### 2. 部署 Node 项目(标准流程) - -```bash -# 1. 压缩项目(排除无用目录) -cd /项目路径 -tar --exclude='node_modules' --exclude='.next' --exclude='.git' \ - -czf /tmp/项目名_update.tar.gz . - -# 2. 上传到服务器 -sshpass -p 'Zhiqun1984' scp /tmp/项目名_update.tar.gz root@42.194.232.22:/tmp/ - -# 3. SSH部署 -ssh root@42.194.232.22 -cd /www/wwwroot/项目名 -rm -rf app components lib public styles *.json *.js *.ts *.mjs *.md .next -tar -xzf /tmp/项目名_update.tar.gz -pnpm install -pnpm run build -rm /tmp/项目名_update.tar.gz - -# 4. 宝塔面板重启项目 -# 【网站】→【Node项目】→ 找到项目 → 点击【重启】 -``` - -### 3. SSL证书检查/修复 - -```bash -# 检查所有服务器SSL证书状态 -python3 /Users/karuo/Documents/个人/卡若AI/01_系统管理/服务器管理/scripts/ssl证书检查.py - -# 自动修复过期证书 -python3 /Users/karuo/Documents/个人/卡若AI/01_系统管理/服务器管理/scripts/ssl证书检查.py --fix -``` - -### 4. 常用诊断命令 - -```bash -# 检查端口占用 -ssh root@42.194.232.22 "ss -tlnp | grep :3006" - -# 检查PM2进程 -ssh root@42.194.232.22 "/www/server/nodejs/v22.14.0/bin/pm2 list" - -# 测试HTTP响应 -ssh root@42.194.232.22 "curl -I http://localhost:3006" - -# 检查Nginx配置 -ssh root@42.194.232.22 "nginx -t" - -# 重载Nginx -ssh root@42.194.232.22 "nginx -s reload" - -# DNS解析检查 -dig soul.quwanzhi.com +short @8.8.8.8 -``` - ---- - -## 端口配置表(小型宝塔 42.194.232.22) - -| 端口 | 项目名 | 类型 | 域名 | 状态 | -|------|--------|------|------|------| -| 3000 | cunkebao | Next.js | mckb.quwanzhi.com | ✅ | -| 3001 | ai_hair | NestJS | ai-hair.quwanzhi.com | ✅ | -| 3002 | kr_wb | Next.js | kr_wb.quwanzhi.com | ✅ | -| 3003 | hx | Vue | krjzk.quwanzhi.com | ⚠️ | -| 3004 | dlmdashboard | Next.js | dlm.quwanzhi.com | ✅ | -| 3005 | document | Next.js | docc.quwanzhi.com | ✅ | -| 3006 | soul | Next.js | soul.quwanzhi.com | ✅ | -| 3015 | 神射手 | Next.js | kr-users.quwanzhi.com | ⚠️ | -| 3018 | zhaoping | Next.js | zp.quwanzhi.com | ✅ | -| 3021 | is_phone | Next.js | is-phone.quwanzhi.com | ✅ | -| 3031 | word | Next.js | word.quwanzhi.com | ✅ | -| 3036 | ymao | Next.js | ymao.quwanzhi.com | ✅ | -| 3043 | tongzhi | Next.js | touzhi.lkdie.com | ✅ | -| 3045 | 玩值大屏 | Next.js | wz-screen.quwanzhi.com | ✅ | -| 3050 | zhiji | Next.js | zhiji.quwanzhi.com | ✅ | -| 3051 | zhiji1 | Next.js | zhiji1.quwanzhi.com | ✅ | -| 3055 | wzdj | Next.js | wzdj.quwanzhi.com | ✅ | -| 3305 | AITOUFA | Next.js | ai-tf.quwanzhi.com | ✅ | -| 9528 | mbti | Vue | mbtiadmin.quwanzhi.com | ✅ | - -### 端口分配原则 - -- **3000-3099**: Next.js / React 项目 -- **3100-3199**: Vue 项目 -- **3200-3299**: NestJS / Express 后端 -- **3300-3399**: AI相关项目 -- **9000-9999**: 管理面板 / 特殊用途 - ---- - -## 核心工作流程 - -``` -┌─────────────────────────────────────────────────────────────────────────────┐ -│ Node项目一键部署流程 │ -├─────────────────────────────────────────────────────────────────────────────┤ -│ │ -│ START │ -│ │ │ -│ ▼ │ -│ ┌──────────────────┐ │ -│ │ 1. 压缩本地代码 │ 排除 node_modules, .next, .git │ -│ └────────┬─────────┘ │ -│ │ │ -│ ▼ │ -│ ┌──────────────────┐ │ -│ │ 2. 上传到服务器 │ scp 到 /tmp/ │ -│ └────────┬─────────┘ │ -│ │ │ -│ ▼ │ -│ ┌──────────────────┐ │ -│ │ 3. 清理旧文件 │ 保留 .env 等配置文件 │ -│ └────────┬─────────┘ │ -│ │ │ -│ ▼ │ -│ ┌──────────────────┐ │ -│ │ 4. 解压新代码 │ tar -xzf │ -│ └────────┬─────────┘ │ -│ │ │ -│ ▼ │ -│ ┌──────────────────┐ │ -│ │ 5. 安装依赖 │ pnpm install │ -│ └────────┬─────────┘ │ -│ │ │ -│ ▼ │ -│ ┌──────────────────┐ │ -│ │ 6. 构建项目 │ pnpm run build │ -│ └────────┬─────────┘ │ -│ │ │ -│ ▼ │ -│ ┌──────────────────┐ │ -│ │ 7. 宝塔面板重启 │ Node项目 → 重启 │ -│ └────────┬─────────┘ │ -│ │ │ -│ ▼ │ -│ ┌──────────────────┐ │ -│ │ 8. 验证访问 │ curl https://域名 │ -│ └────────┬─────────┘ │ -│ │ │ -│ ▼ │ -│ SUCCESS │ -│ │ -└─────────────────────────────────────────────────────────────────────────────┘ -``` - ---- - -## 操作优先级矩阵 - -| 操作类型 | 优先方式 | 备选方式 | 说明 | -|---------|---------|---------|------| -| 查询信息 | ✅ 宝塔API | SSH | API稳定 | -| 文件操作 | ✅ 宝塔API | SSH | API支持 | -| 配置Nginx | ✅ 宝塔API | SSH | API可读写 | -| 重载服务 | ⚠️ SSH | - | API无接口 | -| 上传代码 | ⚠️ SSH/scp | - | 大文件 | -| 添加项目 | ❌ 宝塔界面 | - | API不稳定 | - ---- - -## 常见问题速查 - -### Q1: 外网无法访问(ERR_EMPTY_RESPONSE) - -**原因**: 腾讯云安全组只开放443端口 - -**解决**: -1. 必须配置SSL证书 -2. Nginx配置添加443监听 - -### Q2: Node项目启动失败(Could not find production build) - -**原因**: 使用 `npm run start` 但未执行 `npm run build` - -**解决**: 先 `pnpm run build` 再重启 - -### Q3: 端口冲突(EADDRINUSE) - -**解决**: -```bash -# 检查端口占用 -ss -tlnp | grep :端口号 - -# 修改package.json中的端口 -"start": "next start -p 新端口" -``` - -### Q4: DNS被代理劫持 - -**现象**: 本地DNS解析到198.18.x.x - -**解决**: -- 关闭代理软件 -- 或用手机4G网络测试 - -### Q5: 宝塔与PM2冲突 - -**原因**: 同时使用root用户PM2和宝塔PM2 - -**解决**: -- 停止所有独立PM2: `pm2 kill` -- 只使用宝塔界面管理 - ---- - -## 安全约束 - -### 绝对禁止 - -- ❌ 输出完整密码/密钥到聊天 -- ❌ 执行危险命令(rm -rf /, reboot等) -- ❌ 跳过验证步骤 -- ❌ 使用独立PM2(避免与宝塔冲突) - -### 必须遵守 - -- ✅ 操作前检查服务器状态 -- ✅ 操作后验证结果 -- ✅ 生成操作报告 - ---- - -## 相关脚本 - -| 脚本 | 功能 | 位置 | -|------|------|------| -| `快速检查服务器.py` | 一键检查所有服务器状态 | `./scripts/` | -| `一键部署.py` | 根据配置文件部署项目 | `./scripts/` | -| `ssl证书检查.py` | 检查/修复SSL证书 | `./scripts/` | - ---- - -## 相关文档 - -| 文档 | 内容 | 位置 | -|------|------|------| -| `宝塔API接口文档.md` | 宝塔API完整接口说明 | `./references/` | -| `端口配置表.md` | 完整端口分配表 | `./references/` | -| `常见问题手册.md` | 问题解决方案大全 | `./references/` | -| `部署配置模板.md` | JSON配置文件模板 | `./references/` | -| `系统架构说明.md` | 完整架构图和流程图 | `./references/` | - ---- - -## 历史对话整理 - -### kr_wb白板项目部署(2026-01-23) - -- 项目类型: Next.js -- 部署位置: /www/wwwroot/kr_wb -- 域名: kr_wb.quwanzhi.com -- 端口: 3002 -- 遇到问题: AI功能401错误(API密钥未配置) -- 解决方案: 修改 lib/ai-client.ts,改用 SiliconFlow 作为默认服务 - -### soul项目部署(2026-01-23) - -- 项目类型: Next.js -- 部署位置: /www/wwwroot/soul -- 域名: soul.quwanzhi.com -- 端口: 3006 -- 部署流程: 压缩→上传→解压→安装依赖→构建→PM2启动→配置Nginx→配置SSL diff --git a/开发文档/服务器管理/references/运维参考.md b/开发文档/服务器管理/references/运维参考.md deleted file mode 100644 index fc781c96..00000000 --- a/开发文档/服务器管理/references/运维参考.md +++ /dev/null @@ -1,3 +0,0 @@ -# 运维参考(合并自 宝塔api、常见问题、端口配置、系统架构、部署配置) - -宝塔 API、常见问题、端口配置、系统架构说明、部署配置模板。详见原各文档。 diff --git a/开发文档/服务器管理/scripts/ssl证书检查.py b/开发文档/服务器管理/scripts/ssl证书检查.py deleted file mode 100644 index 4ac56952..00000000 --- a/开发文档/服务器管理/scripts/ssl证书检查.py +++ /dev/null @@ -1,168 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -""" -SSL证书检查脚本 -=============== -用途:检查所有服务器的SSL证书状态 - -使用方法: -python3 ssl证书检查.py -python3 ssl证书检查.py --fix # 自动修复过期证书 -""" - -import sys -import time -import hashlib -import requests -import urllib3 -from datetime import datetime - -# 禁用SSL警告 -urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) - -# 服务器配置 -服务器列表 = { - "小型宝塔": { - "面板地址": "https://42.194.232.22:9988", - "密钥": "hsAWqFSi0GOCrunhmYdkxy92tBXfqYjd" - }, - "存客宝": { - "面板地址": "https://42.194.245.239:9988", - "密钥": "TNKjqDv5N1QLOU20gcmGVgr82Z4mXzRi" - }, - "kr宝塔": { - "面板地址": "https://43.139.27.93:9988", - "密钥": "qcWubCdlfFjS2b2DMT1lzPFaDfmv1cBT" - } -} - -def 生成签名(api_key: str) -> tuple: - """生成宝塔API签名""" - now_time = int(time.time()) - sign_str = str(now_time) + hashlib.md5(api_key.encode('utf-8')).hexdigest() - request_token = hashlib.md5(sign_str.encode('utf-8')).hexdigest() - return now_time, request_token - -def 获取证书列表(面板地址: str, 密钥: str) -> dict: - """获取SSL证书列表""" - now_time, request_token = 生成签名(密钥) - - url = f"{面板地址}/ssl?action=GetCertList" - data = { - "request_time": now_time, - "request_token": request_token - } - - try: - response = requests.post(url, data=data, timeout=10, verify=False) - return response.json() - except Exception as e: - return {"error": str(e)} - -def 获取网站列表(面板地址: str, 密钥: str) -> dict: - """获取网站列表""" - now_time, request_token = 生成签名(密钥) - - url = f"{面板地址}/data?action=getData&table=sites" - data = { - "request_time": now_time, - "request_token": request_token, - "limit": 100, - "p": 1 - } - - try: - response = requests.post(url, data=data, timeout=10, verify=False) - return response.json() - except Exception as e: - return {"error": str(e)} - -def 检查服务器证书(名称: str, 配置: dict) -> dict: - """检查单台服务器的证书状态""" - print(f"\n检查服务器: {名称}") - print("-" * 40) - - try: - # 获取网站列表 - 网站数据 = 获取网站列表(配置["面板地址"], 配置["密钥"]) - - if "error" in 网站数据: - print(f" ❌ API错误: {网站数据['error']}") - return {"error": 网站数据['error']} - - 网站列表 = 网站数据.get("data", []) - - if not 网站列表: - print(" ⚠️ 没有找到网站") - return {"网站数": 0} - - print(f" 📊 共 {len(网站列表)} 个网站") - - # 统计 - 已配置SSL = 0 - 未配置SSL = 0 - - for 网站 in 网站列表: - 网站名 = 网站.get("name", "未知") - ssl状态 = 网站.get("ssl", 0) - - if ssl状态: - 已配置SSL += 1 - 状态标识 = "🔒" - else: - 未配置SSL += 1 - 状态标识 = "🔓" - - print(f" {状态标识} {网站名}") - - print(f"\n 统计: 已配置SSL {已配置SSL} 个, 未配置 {未配置SSL} 个") - - return { - "网站数": len(网站列表), - "已配置SSL": 已配置SSL, - "未配置SSL": 未配置SSL - } - - except Exception as e: - print(f" ❌ 检查失败: {e}") - return {"error": str(e)} - -def main(): - 自动修复 = "--fix" in sys.argv - - print("=" * 60) - print(" SSL证书状态检查报告") - print(f" {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}") - print("=" * 60) - - 总统计 = { - "服务器数": 0, - "网站总数": 0, - "已配置SSL": 0, - "未配置SSL": 0 - } - - for 服务器名称, 配置 in 服务器列表.items(): - 结果 = 检查服务器证书(服务器名称, 配置) - - if "error" not in 结果: - 总统计["服务器数"] += 1 - 总统计["网站总数"] += 结果.get("网站数", 0) - 总统计["已配置SSL"] += 结果.get("已配置SSL", 0) - 总统计["未配置SSL"] += 结果.get("未配置SSL", 0) - - print("\n" + "=" * 60) - print(" 汇总统计") - print("=" * 60) - print(f" 服务器数量: {总统计['服务器数']}") - print(f" 网站总数: {总统计['网站总数']}") - print(f" 已配置SSL: {总统计['已配置SSL']} 🔒") - print(f" 未配置SSL: {总统计['未配置SSL']} 🔓") - print("=" * 60) - - if 自动修复 and 总统计['未配置SSL'] > 0: - print("\n⚠️ --fix 模式需要手动在宝塔面板配置SSL证书") - print(" 建议使用通配符证书 *.quwanzhi.com") - -if __name__ == "__main__": - main() diff --git a/开发文档/服务器管理/scripts/一键部署.py b/开发文档/服务器管理/scripts/一键部署.py deleted file mode 100644 index a5660e18..00000000 --- a/开发文档/服务器管理/scripts/一键部署.py +++ /dev/null @@ -1,138 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -""" -一键部署脚本 -============ -用途:根据配置文件一键部署Node项目到宝塔服务器 - -使用方法: -python3 一键部署.py 项目名称 本地项目路径 - -示例: -python3 一键部署.py soul /Users/karuo/Documents/开发/3、自营项目/一场soul的创业实验 -""" - -import sys -import os -import subprocess -import time - -# 默认服务器配置 -默认配置 = { - "服务器IP": "42.194.232.22", - "SSH用户": "root", - "SSH密码": "Zhiqun1984", - "服务器根目录": "/www/wwwroot" -} - -def 执行命令(命令: str, 显示输出: bool = True) -> tuple: - """执行shell命令""" - result = subprocess.run(命令, shell=True, capture_output=True, text=True) - if 显示输出 and result.stdout: - print(result.stdout) - if result.stderr and "Warning" not in result.stderr: - print(f"错误: {result.stderr}") - return result.returncode, result.stdout - -def 部署项目(项目名称: str, 本地路径: str): - """执行部署流程""" - 服务器路径 = f"{默认配置['服务器根目录']}/{项目名称}" - 压缩文件 = f"/tmp/{项目名称}_update.tar.gz" - - print(f"\n{'='*60}") - print(f"开始部署: {项目名称}") - print(f"本地路径: {本地路径}") - print(f"服务器路径: {服务器路径}") - print(f"{'='*60}\n") - - # 步骤1: 压缩项目 - print("📦 步骤1: 压缩项目文件...") - 排除项 = "--exclude='node_modules' --exclude='.next' --exclude='.git' --exclude='android' --exclude='out'" - 压缩命令 = f"cd '{本地路径}' && tar {排除项} -czf {压缩文件} ." - code, _ = 执行命令(压缩命令, False) - if code != 0: - print("❌ 压缩失败") - return False - - # 获取文件大小 - 大小 = os.path.getsize(压缩文件) / 1024 / 1024 - print(f" ✅ 压缩完成,大小: {大小:.2f} MB") - - # 步骤2: 上传到服务器 - print("\n📤 步骤2: 上传到服务器...") - 上传命令 = f"sshpass -p '{默认配置['SSH密码']}' scp -o StrictHostKeyChecking=no {压缩文件} {默认配置['SSH用户']}@{默认配置['服务器IP']}:/tmp/" - code, _ = 执行命令(上传命令, False) - if code != 0: - print("❌ 上传失败") - return False - print(" ✅ 上传完成") - - # 步骤3-6: SSH远程执行 - print("\n🔧 步骤3-6: 服务器端操作...") - - SSH前缀 = f"sshpass -p '{默认配置['SSH密码']}' ssh -o StrictHostKeyChecking=no {默认配置['SSH用户']}@{默认配置['服务器IP']}" - - # 清理旧文件 - 清理命令 = f"{SSH前缀} 'cd {服务器路径} && rm -rf app components lib public styles *.json *.js *.ts *.mjs *.md .next 2>/dev/null || true'" - 执行命令(清理命令, False) - print(" ✅ 清理旧文件") - - # 解压 - 解压命令 = f"{SSH前缀} 'cd {服务器路径} && tar -xzf /tmp/{项目名称}_update.tar.gz'" - 执行命令(解压命令, False) - print(" ✅ 解压新代码") - - # 安装依赖 - print("\n📚 安装依赖 (这可能需要几分钟)...") - 安装命令 = f"{SSH前缀} 'export PATH=/www/server/nodejs/v22.14.0/bin:$PATH && cd {服务器路径} && npm install --legacy-peer-deps 2>&1'" - 执行命令(安装命令, True) - - # 构建 - print("\n🏗️ 构建项目...") - 构建命令 = f"{SSH前缀} 'export PATH=/www/server/nodejs/v22.14.0/bin:$PATH && cd {服务器路径} && npm run build 2>&1'" - 执行命令(构建命令, True) - - # 重启PM2 - print("\n🔄 重启服务...") - 重启命令 = f"{SSH前缀} 'export PATH=/www/server/nodejs/v22.14.0/bin:$PATH && pm2 restart {项目名称} 2>&1'" - 执行命令(重启命令, True) - - # 清理临时文件 - 清理临时命令 = f"{SSH前缀} 'rm -f /tmp/{项目名称}_update.tar.gz'" - 执行命令(清理临时命令, False) - os.remove(压缩文件) - - print(f"\n{'='*60}") - print("✅ 部署完成!") - print(f"{'='*60}") - print("\n⚠️ 请在宝塔面板手动重启项目:") - print(f" 1. 登录 https://42.194.232.22:9988/ckbpanel") - print(f" 2. 进入【网站】→【Node项目】") - print(f" 3. 找到 {项目名称},点击【重启】") - - return True - -def main(): - if len(sys.argv) < 3: - print("用法: python3 一键部署.py <项目名称> <本地项目路径>") - print("\n示例:") - print(" python3 一键部署.py soul /Users/karuo/Documents/开发/3、自营项目/一场soul的创业实验") - print(" python3 一键部署.py kr_wb /Users/karuo/Documents/开发/4、小工具/whiteboard") - sys.exit(1) - - 项目名称 = sys.argv[1] - 本地路径 = sys.argv[2] - - if not os.path.exists(本地路径): - print(f"❌ 本地路径不存在: {本地路径}") - sys.exit(1) - - 确认 = input(f"\n确认部署 {项目名称} 到服务器? (y/n): ") - if 确认.lower() != 'y': - print("已取消部署") - sys.exit(0) - - 部署项目(项目名称, 本地路径) - -if __name__ == "__main__": - main() diff --git a/开发文档/服务器管理/scripts/快速检查服务器.py b/开发文档/服务器管理/scripts/快速检查服务器.py deleted file mode 100644 index 5667788c..00000000 --- a/开发文档/服务器管理/scripts/快速检查服务器.py +++ /dev/null @@ -1,104 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -""" -快速检查服务器状态 -================== -用途:一键检查所有服务器的基本状态 - -使用方法: -python3 快速检查服务器.py -""" - -import time -import hashlib -import requests -import urllib3 - -# 禁用SSL警告 -urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) - -# 服务器配置 -服务器列表 = { - "小型宝塔": { - "面板地址": "https://42.194.232.22:9988", - "密钥": "hsAWqFSi0GOCrunhmYdkxy92tBXfqYjd" - }, - "存客宝": { - "面板地址": "https://42.194.245.239:9988", - "密钥": "TNKjqDv5N1QLOU20gcmGVgr82Z4mXzRi" - }, - "kr宝塔": { - "面板地址": "https://43.139.27.93:9988", - "密钥": "qcWubCdlfFjS2b2DMT1lzPFaDfmv1cBT" - } -} - -def 生成签名(api_key: str) -> tuple: - """生成宝塔API签名""" - now_time = int(time.time()) - sign_str = str(now_time) + hashlib.md5(api_key.encode('utf-8')).hexdigest() - request_token = hashlib.md5(sign_str.encode('utf-8')).hexdigest() - return now_time, request_token - -def 获取系统信息(面板地址: str, 密钥: str) -> dict: - """获取系统基础统计信息""" - now_time, request_token = 生成签名(密钥) - - url = f"{面板地址}/system?action=GetSystemTotal" - data = { - "request_time": now_time, - "request_token": request_token - } - - try: - response = requests.post(url, data=data, timeout=10, verify=False) - return response.json() - except Exception as e: - return {"error": str(e)} - -def 检查单台服务器(名称: str, 配置: dict) -> dict: - """检查单台服务器状态""" - try: - 系统信息 = 获取系统信息(配置["面板地址"], 配置["密钥"]) - - if isinstance(系统信息, dict) and "error" not in 系统信息 and 系统信息.get("status") != False: - return { - "名称": 名称, - "状态": "✅ 正常", - "CPU": f"{系统信息.get('cpuRealUsed', 'N/A')}%", - "内存": f"{系统信息.get('memRealUsed', 'N/A')}%", - "磁盘": f"{系统信息.get('diskPer', 'N/A')}%" - } - else: - return { - "名称": 名称, - "状态": "❌ API错误", - "错误": str(系统信息) - } - except Exception as e: - return { - "名称": 名称, - "状态": "❌ 连接失败", - "错误": str(e) - } - -def main(): - print("=" * 60) - print(" 服务器状态检查报告") - print("=" * 60) - print() - - for 名称, 配置 in 服务器列表.items(): - 结果 = 检查单台服务器(名称, 配置) - print(f"📦 {结果['名称']}") - print(f" 状态: {结果['状态']}") - if "CPU" in 结果: - print(f" CPU: {结果['CPU']} | 内存: {结果['内存']} | 磁盘: {结果['磁盘']}") - if "错误" in 结果: - print(f" 错误: {结果['错误'][:50]}...") - print() - - print("=" * 60) - -if __name__ == "__main__": - main() diff --git a/开发文档/章节拖拽排序-后台说明.md b/开发文档/章节拖拽排序-后台说明.md deleted file mode 100644 index e5dfd3c6..00000000 --- a/开发文档/章节拖拽排序-后台说明.md +++ /dev/null @@ -1,74 +0,0 @@ -# 章节拖拽排序 - 后台处理说明 - -## 一、后台已实现 - -### 1. 接口 - -- **路径**:`PUT /api/db/book` -- **鉴权**:需登录管理端(AdminAuth) - -**请求体**(拖拽排序时): -```json -{ - "action": "reorder", - "ids": ["1.1", "2.3", "3.1", ...] -} -``` - -- `ids`:所有 section 的 id,按新的排序顺序排列 -- 后端会依次将每条记录的 `sort_order` 更新为 0、1、2、… - -### 2. 代码位置 - -- `soul-api/internal/handler/db_book.go`:`DBBookAction` 中 `http.MethodPut` 分支,约第 196–206 行 - ---- - -## 二、数据库必须支持 - -### 1. `sort_order` 列 - -`chapters` 表必须有 `sort_order` 列,否则 `UPDATE sort_order` 会报错。 - -**检查**: -```sql -SHOW COLUMNS FROM chapters LIKE 'sort_order'; -``` - -**若不存在,执行迁移**: -```bash -cd e:\Gongsi\Mycontent -node .cursor/scripts/db-exec/run.js -f soul-api/scripts/add-sort-order-to-chapters.sql -``` - -或手动执行: -```sql -ALTER TABLE chapters ADD COLUMN sort_order INT DEFAULT 0; -``` - -### 2. 现有数据处理 - -若已有数据且 `sort_order` 为 NULL 或未设置,可先按当前顺序初始化: -```sql -SET @i = 0; -UPDATE chapters SET sort_order = (@i := @i + 1) ORDER BY id; -``` - ---- - -## 三、排查“无法拖拽” - -| 现象 | 可能原因 | 处理方式 | -|------|----------|----------| -| 拖不起来 | 拖拽手柄太小、浏览器兼容性 | 点击左侧 ⋮⋮ 后按住再拖动 | -| 拖到目标没反应 | 未触发 drop | 确认拖到其他 section 行再松手 | -| 松手后弹“排序失败” | 1. `sort_order` 列不存在
2. 鉴权失败 401
3. 接口异常 | 1. 执行迁移脚本
2. 确认已登录管理端
3. 查看 soul-api 日志和浏览器控制台 | - ---- - -## 四、快速验证 - -1. 执行迁移(若 `sort_order` 不存在) -2. 重启 soul-api -3. 在管理端登录后打开「内容管理 → 章节管理」 -4. 用 ⋮⋮ 拖拽某一节到另一位置,松手后应刷新并显示新顺序