Normal view

There are new articles available, click to refresh the page.
Today — 17 September 2024Main stream

被裁第一个月,接私活搞点收入,然后继续用爱发电❤️

16 September 2024 at 23:16
HeyCaptainJack:

OK ,被裁第一个月,上周接了个私活,有收入进账了,我鼓励自己,已经非常成功了,哈哈😄,坚守理想的同时,也要顾得上家人的生活。

被裁一个月,在持续的感受自由,也在重塑自己的生活。回想上班几年,匆匆而已,忽地觉得那几年过的如重复同一天一样,打卡,做一些无意义的工作,等周末了,在 20km 范围内游玩一下,重复而麻了的感觉。

前半个月,还是会担心一些没有进账的情况。但是经过这一个月的思考,我的心态坚定下来,不去着急挣钱,做自己认为是正确的事情,哪怕那个东西短期没有收益,先去探索,去扩大自己的视野。

这一个月,定下了三个小项目的方向,代码也写了一部分,这些项目会不会产生收益,多久产生,不得而知,继续用爱发电,做自己爱做的事情。

新配的台式电脑鼠标和键盘偶尔丢键,按了没反应,何解?

By: nnegier
16 September 2024 at 21:59
nnegier: 键盘是新买的小米的 TKL 全键无冲机械键盘;
鼠标是旧的罗技的 G102 。

玩的游戏是 PUBG ,键盘丟键主要是在 Q 和 E 键,我手一直按着,但是游戏里没有反应,我得再按一下。鼠标就更离谱了,鼠标左键丟键,一直按着有时候没有反应,枪开不出来,得再按一下。键鼠都是有线插在台式机上。

这些都是偶尔但是很容易复现的事情,实在是想不通啥原因。这事和内存应该没关系吧,但我想换一下排除下看看。也有可能就是键盘和鼠标的问题。

独立开发周记 83:新 App 连续六次被拒

By: vulgur
16 September 2024 at 20:22
vulgur:

2024 ,0909-0915

这个周记的标题一改再改,因为被拒的次数不断增加。

Google Play 账户验证

这周一次性通过了 Google Play 的身份验证和银行账户验证。 之前听闻有的开发者卡在这里好久,提交各种资料就是不能通过。我也害怕这种事发生在我身上,好在没有。就是按照要求提交了身份证、水电费和银行流水,就直接通过验证了。

虽然来自 GP 的收入一直在下降,但是也是目前收入的重要组成的一部分,占到美元收入的差不多四成左右。

上周有人留言要买我的账号的 App ,向群友请教了一番,结果并不能卖多少钱,连一两特斯拉 Model Y 都不够。算了,还是别杀鸡取卵了。

Shipaton 第五周

距离截止日期还剩 3 天。 第五周生产力大爆发,一共完成了 56 个番茄钟,是最多的一周!

因为马上就要到 deadline 了,为了能够顺利提交 App ,不得不又砍掉了一个 Jar Type 。剩余的工作就是 UI 调整,修复 bug ,加入动画和声效以提高交互性。设计师列了几十个 UI 调整事项,还好我很快就完成了大部分,一天发四五个 TestFlight 的 build ,只剩几项我认为比较费时就先搁置了。

https://youtu.be/F12HzTVRrT0

连续被拒 6 次

终于,周五下午四点提交了第一版,没想到过了 30 个小时才进入审核。整个周六的精神状态都是心不在焉的,什么都干不进去,总在期待收到审核结果的邮件,然后意料之中地被拒了。第一次被拒的原因还好,只是元数据的问题,填补后顺便修复了一个小组件的问题第二次提交(周六晚上)。

在等待审核的间隙,完善了 Ship-A-Ton 的各种资料,还第一次用 Rotato 录了一个演示视频。

https://youtu.be/IRKSo2Txclc

然而,第二次被拒就是周日下午了,直到午夜连着拒绝了五次……

第二次被拒的原因:Paywall 页面里缺少付费后用户得到的功能或服务(我选择的这个 Revenue Cat Paywall 模板没有关于付费解锁内容的配置)。

第三次和第四次被拒都是同样的原因:说是 Paywall 页面无法加载,影响用户付费体验。但我这个 Paywall 是 RevenueCat 提供的,加载过程不由我控制,RC 的建议就是如果一切配置没问题的话,那就是苹果审核环境导致的,没有其他办法,只能是一遍遍的重复提交。

第五次被拒的原因:页面存在难以阅读的文字。其实就是 Onboarding 部分的大段文字颜色有些浅,而且在小屏幕的手机上会显示不全。

第六次被拒的原因有三个:

  1. 付费页面的按钮文案不符合要求,而我这还是借鉴了 Mobbin 发布的关于提高付费转化率的最佳实践。
  2. 付费后遇到错误,我猜是因为 App 销售范围和订阅的销售范围不一致导致的,因为我还没有时间备案,所以第一版就不打算在国内上架了。虽然 App 销售范围去掉了中国大陆,但是订阅的销售范围还是所有国家和地区,这里不一致,另外我也回复给审核人员说这个 App 不在中国大陆销售,请用其他国家的配置环境来审核。
  3. 技术支持 URL 留的网址不符合要求,我本以为用 Notion 搭一个包含隐私政策和使用协议的简单页面就可以了,但是苹果说必须要是能和开发者直接联系的网站才行。

第七次提交后就马上是午夜十二点了,心情已经麻木和崩溃了,十分沮丧和忐忑地入睡了。我还梦见了第七次被拒,审核员还给我发了一封巨长巨长的邮件,里面罗列了各种素材和命名的截图,说我的 App 抄袭黑神话·悟空……

还好,没有第七次被拒,一觉醒来,审核通过了!

我偏要贪图完满,搜个干净

黑神话·悟空,二周目,白金达成。 这游戏白金的达成,不是能力问题,也不是时间问题,而是运气问题。 花了两天在收集各种概率掉落的物品上,感觉我人品还不错,并没有刷到崩溃就收集全了,不过就凭这一点也应该给这个游戏减 0.1 分。

Yesterday — 16 September 2024Main stream

分享一个罗技 MX 系列鼠标(Master、Anywehre)某些场景下回滚的软件解决方案

16 September 2024 at 17:09
g1vemep0wer:

⚠️ 该方案仅适用 Mac 平台,且需要安装 hammerspoon

该脚本主要是为了解决无极滚轮容易回滚的问题,我的测试鼠标为罗技 Anywhere3s ,鼠标滚轮为 magspeed 电磁滚轮,Anywhere 2 代物理结构的滚轮也应该支持,其他系列,例如:Master 系列也应该支持

回滚场景

  1. 开启无极滚动,或者 Logi Options+ 中开启了平滑滚动
  2. 即使使用棘轮模式(刻度模式),当手指放到滚轮上,也有概率会触发回滚

原因分析

  • 由于开启了平滑滚动,滚轮任何细粒度的滚动都会触发事件,
  • 这种情况下棘轮单纯是为了手感,棘轮刻度的粒度并不严格对应事件粒度,
  • 很可能棘轮刻度感还没触发,事件已经发射了好几次

处理方案

  • 简单来说,当鼠标滚轮事件触发时,判断一下滚动方向是不是发生了变化,
  • 只有在同一个方向上滚动到一定次数后,才认为是真的发生了预期滚动

脚本地址如下:

https://github.com/xiaojundebug/hammerspoon-config/blob/main/scripts/magspeed-smooth-scrolling-fix.lua

域名解析的双 ip 停掉一个后,无法通过域名请求接口

By: cunyu1943
16 September 2024 at 10:17
cunyu1943:
  • 现有一个域名:a.com ,解析出的 ip:192.168.0.1 、192.168.0.2

  • 现象:现在灾备切换,将其中一个 ip 停掉,理论上通过 a.com 还是可以访问后台接口,但实际通过代码无法访问。

  • 已排查的情况:

    • 对方本地未做 host
    • 对方 DNS 自动获取
    • 对方服务器 curl 请求域名 & ip 均可访问
    • 对方代码中域名切换 ip 后可正常访问
  • 求教,还有什么场景没考虑到需要排查

一款同时支持 Java (1.8/17+)、 Python 、Go 的分布式调度任务平台和分布式任务重试平台

By: zsg1994
16 September 2024 at 08:42
zsg1994:

SnailJob 是一个灵活、可靠且高效的分布式任务重试和任务调度平台。其核心采用分区模式实现,具备高度可伸缩性和容错性的分布式系统。拥有完善的权限管理、强大的告警监控功能和友好的界面交互。欢迎大家接入并使用。

官网: https://snailjob.opensnail.com/ 在线体验地址: https://snailjob.opensnail.com/docs/preview.html 开源地址: https://gitee.com/aizuda/snail-job

系统截图 系统截图
系统截图 系统截图
系统截图 系统截图
系统截图 系统截图
系统截图 系统截图
系统截图 系统截图
系统截图 系统截图

凹语言打印源码位置信息

By: chai2010
16 September 2024 at 05:43
chai2010:

凹语言发布了 v0.16.0 中秋特别版本, 其中语言的变化是增加了源码位置信息的预定义常量.

  • __package__: 当前代码所在包路径, 无类型字符串常量
  • __FILE__: 当前代码所在文件名, 无类型字符串常量
  • __LINE__: 当前代码所在文件的行号, 无类型整数常量
  • __func__: 当前代码所在的具名函数或方法名字, 无类型字符串常量

可以这样打印源码位置信息:

func main {
println("__package__:", __package__)
println("__FILE__:", __FILE__)
println("__LINE__:", __LINE__)
println("__func__:", __func__)
}

执行效果如下:

$ wa run hello.wa
__package__: __main__
__FILE__: hello.wa
__LINE__: 4
__func__: main

原文: https://wa-lang.org/smalltalk/st0050.html

用 Linear 扁平风 + Magic UI 开发简洁美观的个人主页: zmh.me

15 September 2024 at 20:37
ProgramZmh:

分享最近看到一个开源项目 Magic UI 在前端圈里传疯了(零毛一条),好奇去看了官方文档预览,确实不错。

而且有很多似曾相识的动画都被集成在了里面,包括 github 、vercel 、bento 的动画等等,提供了非常简便的组件。

趁着中秋放假,把自己的个人主页改了一下,看样子还可以哈哈:zmh.me

个人主页已开源 github - zmh's portfolio,如果你也喜欢这种风格的话可以參考和 use template ,下面是部分预览。

预览预览

Before yesterdayMain stream

怎么把 webpack 打包了的文件还原出 HTML/css/js 逻辑代码来?

By: me15000
15 September 2024 at 18:06
me15000:

网上也搜了不少但是没有找到合适的工具 自己尝试看了下代码,如果一点点去看很费劲,但是可以看到一些端倪,比如可以看到 css 的定义如下:

".settings": {
                flexDirection: "column"
              },
              ".settings .wrapper": {
                flexDirection: "column",
                backgroundColor: "#ffffff",
                paddingTop: "0px",
                paddingRight: "30px",
                paddingBottom: "0px",
                paddingLeft: "30px",
                borderBottomWidth: "16px",
                borderBottomStyle: "solid",
                borderBottomColor: "#F8F8F8",
                _meta: {
                  ruleDef: [{
                    t: "a",
                    n: "class",
                    i: false,
                    a: "element",
                    v: "settings"
                  }, {
                    t: "d"
                  }, {
                    t: "a",
                    n: "class",
                    i: false,
                    a: "element",
                    v: "wrapper"
                  }]
                }
              },

那么问题是有没有已经造好了的轮子、工具,可以方便一些把这些代码剥离出来,最终翻译为 css 和 html 代码呢?

完整代码如下:

(function () {
    function e() {
      return (() => {
        var e = Object.getPrototypeOf(global) || global;
        e.chunkFileMap = e.chunkFileMap || {
          881: "node_modules/crypto-js/cipher-core.js",
          5624: "node_modules/crypto-js/core.js",
          8160: "node_modules/crypto-js/md5.js",
          5613: "node_modules/crypto-js/aes.js",
          2468: "node_modules/crypto-js/evpkdf.js",
          136: "node_modules/crypto-js/enc-base64.js",
          3139: "node_modules/crypto-js/hmac.js",
          9092: "node_modules/crypto-js/sha1.js",
          2120: "node_modules/crypto-js/pad-pkcs7.js",
          345: "node_modules/crypto-js/enc-utf8.js",
          8183: "node_modules/dayjs/dayjs.min.js",
          5634: "node_modules/dayjs/plugin/isoWeek.js",
          3716: "node_modules/ylh-quick-app-ad-sdk/utils/index.js",
          1944: "node_modules/union-quick-app-ad/components/common.js",
          6700: "manifest.js",
          5100: "cmps/em-request/index.js",
          3375: "cmps/em-request/device.js",
          3314: "cmps/em-request/extend.js",
          8006: "utils/object.js",
          2172: "global.js",
          2858: "utils/store.js",
          8789: "utils/encipher.js",
          1552: "cmps/em-spin/index.js",
          4519: "services/taskConf.js",
          942: "utils/delay.js",
          1877: "services/adConfPlus.js",
          7285: "services/adConf.js",
          6494: "cmps/em-popup-window/index.js",
          1198: "cmps/em-exit-btn/index.js",
          2694: "services/balance.js",
          7258: "utils/device.js",
          267: "cmps/em-complain/index.js",
          8182: "cmps/em-tabbar/index.js",
          2850: "cmps/em-loading/index.js",
          9160: "utils/re-date-fns.js",
          8831: "cmps/em-withdraw/switch-list/switch.js",
          7634: "cmps/em-withdraw/switch-list/index.js",
          9318: "onents/icon/icons.js",
          2714: "onents/icon/index.js",
          8475: "services/reportAdInfo.js",
          3979: "utils/network.js",
          6425: "la.js"
        };
        var t;
        var s = {
          1863: e => {
            e.exports = function (e, t, s) {
              "use strict";
  
              Object.defineProperty(t, "__esModule", {
                value: true
              });
              t.default = undefined;
              n(s("@app-module/system.prompt"));
              var a = n(s("@app-module/system.webview"));
              function n(e) {
                if (e && e.__esModule) {
                  return e;
                } else {
                  return {
                    default: e
                  };
                }
              }
              const {
                post: i
              } = request;
              t.default = {
                data: () => ({
                  aboutConfig: []
                }),
                computed: {
                  versionName() {
                    const {
                      versionName: e,
                      template: t,
                      name: s
                    } = $manifest;
                    return e;
                  }
                },
                async onInit() {
                  const {
                    tabbar: e
                  } = $manifest;
                  let {
                    data: t
                  } = await request.get(`https://xxxxx?pkg=${$manifest.package}&brand=huawei&position=relate`);
                  this.aboutConfig = t.menus;
                },
                onSuspendClick() {
                  this.isPermanentlySuspendWindowShow = true;
                },
                onReady() {},
                onClearCacheClick() {
                  this.isClearCacheWindowShow = true;
                },
                onAgreementTap() {
                  a.default.loadUrl({
                    url: this.$app.$def.agreementUrl
                  });
                },
                onPrivacyClick() {
                  a.default.loadUrl({
                    url: this.$app.$def.privacyUrl
                  });
                },
                gotoWeb(e) {
                  if (e) {
                    a.default.loadUrl({
                      url: e
                    });
                  }
                },
                onDestroy() {}
              };
              const o = t.default || e.exports;
              const r = ["public", "protected", "private"];
              if (o.data && r.some(function (e) {
                return o[e];
              })) {
                throw new Error("页面 VM 对象中的属性 data 不可与\"" + r.join(",") + "\"同时存在,请使用 private 替换 data 名称");
              }
              if (!o.data) {
                o.data = {};
                o._descriptor = {};
                r.forEach(function (e) {
                  const t = typeof o[e];
                  if (t === "object") {
                    o.data = Object.assign(o.data, o[e]);
                    for (const t in o[e]) {
                      o._descriptor[t] = {
                        access: e
                      };
                    }
                  }
                });
              }
            };
          },
          6092: e => {
            e.exports = {
              ".settings": {
                flexDirection: "column"
              },
              ".settings .wrapper": {
                flexDirection: "column",
                backgroundColor: "#ffffff",
                paddingTop: "0px",
                paddingRight: "30px",
                paddingBottom: "0px",
                paddingLeft: "30px",
                borderBottomWidth: "16px",
                borderBottomStyle: "solid",
                borderBottomColor: "#F8F8F8",
                _meta: {
                  ruleDef: [{
                    t: "a",
                    n: "class",
                    i: false,
                    a: "element",
                    v: "settings"
                  }, {
                    t: "d"
                  }, {
                    t: "a",
                    n: "class",
                    i: false,
                    a: "element",
                    v: "wrapper"
                  }]
                }
              },
              ".settings .wrapper .list": {
                width: "100%",
                height: "120px",
                alignItems: "center",
                justifyContent: "space-between",
                borderBottomWidth: "1px",
                borderBottomStyle: "solid",
                borderBottomColor: "rgba(0,0,0,0.06)",
                _meta: {
                  ruleDef: [{
                    t: "a",
                    n: "class",
                    i: false,
                    a: "element",
                    v: "settings"
                  }, {
                    t: "d"
                  }, {
                    t: "a",
                    n: "class",
                    i: false,
                    a: "element",
                    v: "wrapper"
                  }, {
                    t: "d"
                  }, {
                    t: "a",
                    n: "class",
                    i: false,
                    a: "element",
                    v: "list"
                  }]
                }
              },
              ".settings .wrapper .list-l": {
                fontSize: "30px",
                color: "#333333",
                _meta: {
                  ruleDef: [{
                    t: "a",
                    n: "class",
                    i: false,
                    a: "element",
                    v: "settings"
                  }, {
                    t: "d"
                  }, {
                    t: "a",
                    n: "class",
                    i: false,
                    a: "element",
                    v: "wrapper"
                  }, {
                    t: "d"
                  }, {
                    t: "a",
                    n: "class",
                    i: false,
                    a: "element",
                    v: "list-l"
                  }]
                }
              },
              ".settings .wrapper .list .clearstorge": {
                width: "43px",
                height: "43px",
                _meta: {
                  ruleDef: [{
                    t: "a",
                    n: "class",
                    i: false,
                    a: "element",
                    v: "settings"
                  }, {
                    t: "d"
                  }, {
                    t: "a",
                    n: "class",
                    i: false,
                    a: "element",
                    v: "wrapper"
                  }, {
                    t: "d"
                  }, {
                    t: "a",
                    n: "class",
                    i: false,
                    a: "element",
                    v: "list"
                  }, {
                    t: "d"
                  }, {
                    t: "a",
                    n: "class",
                    i: false,
                    a: "element",
                    v: "clearstorge"
                  }]
                }
              },
              ".settings .wrapper .list .more": {
                width: "30px",
                height: "30px",
                _meta: {
                  ruleDef: [{
                    t: "a",
                    n: "class",
                    i: false,
                    a: "element",
                    v: "settings"
                  }, {
                    t: "d"
                  }, {
                    t: "a",
                    n: "class",
                    i: false,
                    a: "element",
                    v: "wrapper"
                  }, {
                    t: "d"
                  }, {
                    t: "a",
                    n: "class",
                    i: false,
                    a: "element",
                    v: "list"
                  }, {
                    t: "d"
                  }, {
                    t: "a",
                    n: "class",
                    i: false,
                    a: "element",
                    v: "more"
                  }]
                }
              }
            };
          },
          287: e => {
            e.exports = {
              type: "div",
              attr: {},
              classList: ["settings"],
              children: [{
                type: "div",
                attr: {},
                classList: ["wrapper"],
                children: [{
                  type: "div",
                  attr: {},
                  classList: ["list"],
                  children: [{
                    type: "text",
                    attr: {
                      value: "当前版本"
                    },
                    classList: ["list-l"]
                  }, {
                    type: "text",
                    attr: {
                      value: function () {
                        return "V" + this.versionName;
                      }
                    }
                  }]
                }, {
                  type: "div",
                  attr: {},
                  classList: ["list"],
                  events: {
                    click: "onAgreementTap"
                  },
                  children: [{
                    type: "text",
                    attr: {
                      value: "用户协议"
                    },
                    classList: ["list-l"]
                  }, {
                    type: "image",
                    attr: {
                      src: "https://xxxxx/qa/common/mine/tianjinchangdu/right.png"
                    }
                  }]
                }, {
                  type: "div",
                  attr: {},
                  classList: ["list"],
                  events: {
                    click: "onPrivacyClick"
                  },
                  children: [{
                    type: "text",
                    attr: {
                      value: "隐私政策"
                    },
                    classList: ["list-l"]
                  }, {
                    type: "image",
                    attr: {
                      src: "https://xxxxx/qa/common/mine/tianjinchangdu/right.png"
                    }
                  }]
                }, {
                  type: "div",
                  attr: {},
                  classList: ["list"],
                  events: {
                    click: function (e) {
                      return this.gotoWeb(this.ls.like, e);
                    }
                  },
                  repeat: {
                    exp: function () {
                      return this.aboutConfig;
                    },
                    value: "ls"
                  },
                  children: [{
                    type: "text",
                    attr: {
                      value: function () {
                        return this.ls.title;
                      }
                    },
                    classList: ["list-l"]
                  }, {
                    type: "image",
                    attr: {
                      src: "https://xxxx/qa/common/mine/tianjinchangdu/right.png"
                    },
                    shown: function () {
                      return this.ls.like;
                    }
                  }]
                }]
              }]
            };
          },
          5317: (e, t, s, a, n, i, o) => {
            s(6012);
            s(8417);
            s(2342);
            var r = s(6092);
            var l = s(1863);
            a("@app-component/index", [], function (e, t, a) {
              l(a, t, e);
              if (t.__esModule && t.default) {
                a.exports = t.default;
              }
              a.exports.template = s(287);
              a.exports.style = r;
            });
            n("@app-component/index", {
              packagerVersion: undefined
            });
          }
        };
        var a = {};
        function n(e) {
          var t = a[e];
          if (t !== undefined) {
            return t.exports;
          }
          var i = a[e] = {
            exports: {}
          };
          s[e].call(i.exports, i, i.exports, n, $app_define$, $app_bootstrap$, $app_require$, $app_define_wrap$);
          return i.exports;
        }
        n.m = s;
        t = [];
        n.O = (s, a, i, o) => {
          if (!a) {
            var r = Infinity;
            for (d = 0; d < t.length; d++) {
              for (var [a, i, o] = t[d], l = true, p = 0; p < a.length; p++) {
                if ((o & false || r >= o) && Object.keys(n.O).every(e => n.O[e](a[p]))) {
                  a.splice(p--, 1);
                } else {
                  l = false;
                  $app_evaluate$(`${e.chunkFileMap[a[p]]}`);
                  if (o < r) {
                    r = o;
                  }
                }
              }
              if (l) {
                t.splice(d--, 1);
                var c = i();
                if (c !== undefined) {
                  s = c;
                }
              }
            }
            return s;
          }
          o = o || 0;
          for (var d = t.length; d > 0 && t[d - 1][2] > o; d--) {
            t[d] = t[d - 1];
          }
          t[d] = [a, i, o];
        };
        n.o = (e, t) => Object.prototype.hasOwnProperty.call(e, t);
        (() => {
          var t = {
            6638: 0
          };
          n.O.j = e => t[e] === 0;
          var s = (e, s) => {
            var a;
            var i;
            var [o, r, l] = s;
            var p = 0;
            if (o.some(e => t[e] !== 0)) {
              for (a in r) {
                if (n.o(r, a)) {
                  n.m[a] = r[a];
                }
              }
              if (l) {
                var c = l(n);
              }
            }
            for (e && e(s); p < o.length; p++) {
              i = o[p];
              if (n.o(t, i) && t[i]) {
                t[i][0]();
              }
              t[i] = 0;
            }
            return n.O(c);
          };
          var a = e.webpackChunkcom_huawei_quick = e.webpackChunkcom_huawei_quick || [];
          a.forEach(s.bind(null, 0));
          a.push = s.bind(null, a.push.bind(a));
        })();
        var i = n.O(undefined, [1552, 6494, 8831, 7634], () => n(5317));
        i = n.O(i);
      })();
    }
    if (typeof window == "undefined") {
      return e();
    }
    window.createPageHandler = e;
  })();

求推荐一款显示器,需要 4k 和反向充电,兼顾 Win 玩游戏

By: cz5424
15 September 2024 at 13:03
cz5424:

手持 MacBook Pro 和一台 Win 主机(3070 显卡),需要 MacBook 加班用,Win 玩游戏,求推荐,价位在 2000-3000 ,不超过 3000 最好

MacOs 需要 typeC 反向充电,公司买了戴尔修了一次 TypeC 没多久又烧了 TypeC 口,用过 LG 的,服役了 5 年,四个角黑了

退役老旧电脑,没卖的话,你们会用来干什么? 2024 版

By: phx13ye
15 September 2024 at 12:07
phx13ye:

除了某鱼出掉

大佬们能否分享一下别的用法,让它继续发挥余热,目前有一台笔记本电脑,配置 i5-3230M 2.60-GHz + 8G RAM + 256G SSD

  1. 试过装 batocera linux ,但是只有模拟一些比较旧的平台时性能比较好,而且找 rom 和 bios 很麻烦
  2. 装普通的 linux 发行版做家用服务器?可以介绍一下具体用法吗?

退役老旧电脑,没卖的话,你们会用来干什么? 2024 版

By: phx13ye
15 September 2024 at 12:07
phx13ye:

除了某鱼出掉

大佬们能否分享一下别的用法,让它继续发挥余热,目前有一台笔记本电脑,配置 i5-3230M 2.60-GHz + 8G RAM + 256G SSD

  1. 试过装 batocera linux ,但是只有模拟一些比较旧的平台时性能比较好,而且找 rom 和 bios 很麻烦
  2. 装普通的 linux 发行版做家用服务器?可以介绍一下具体用法吗?

一个服务的配置文件用什么格式(比如 xml, json, yaml)比较好?

By: chesha1
14 September 2024 at 22:28
chesha1:

很多服务需要一个配置文件,有一些常见格式:

  • xml: java maven ,这个是我觉得最鬼畜的,可读性极差
  • json: 很多前端相关的服务的配置
  • yaml: k8s 喜欢用这个
  • toml: 感觉比较小众,我用过的服务中,只有 cloudflare 用这个
  • 纯文本: 比如 CMakeLists.txt ,感觉年代久远的服务会更喜欢直接用文本

一个服务用什么格式的配置文件,这个有什么考量吗?用什么比较好?

技术求助:如何获取 Webhook URL 被 POST 的内容(json)到 Python 保存

By: andi
15 September 2024 at 09:33
andi: 技术求助:如何获取 Webhook URL 被 POST 的内容(json)到 python 保存

1.背景:
目标网站 A 提供了一个服务:某个信息更新后,目标网站 A 就会把此 更新消息 POST 到 设置的 Webhook URL 上
已经按照 流程 在 postman 上生成了一个 Webhook URL ,并填入 目标网站 A
信息更新后,目标网站 A 网页端确实看到信息有更新.

2.需要做的:
目前,就是不知道 如何保存每次 POST 的信息到 python 中 (POST 到 Webhook URL 的信息, 是 json)
(就是使用哪些命令,获取到 保存这个信息,因为程序其他部分 需要这个 信息,获取每次 POST 到 Webhook_URL 的 内容,下面的程序才能进行).

3.请各位技术大佬 不吝赐教,谢谢!如果可以带关键代码 那就最好了.

postman 上生成的 Webhook_URL
Webhook_URL = 'https://***.mock.pstmn.io'

花 2 周时间,用 Cursor 开发了一个 AI 处理 EXCEL 工具,能挣钱么?

By: svcvit
14 September 2024 at 14:13
svcvit:

我个人是个产品经理,没有很系统的学习过软件开发,但是工作环境一直和产研有交集,所以一些基本的前后端分离、网络请求多少都有些了解。最近 Cursor 很火,代码能力很强悍,于是,决定自己做一款产品。从 0 到 1 ,完成所有功能的开发和上线。一方面看看 Cursor 进化到什么程度,另一方面看看自己能不能真的完整的做完一款产品。

做什么?

思考有 3 个方向: 1 、受众要广,最好有很多人都有这样的需求 2 、和 AI 相关,虽然不是 All in AI 的心态,但是 AI 真的已经改变了生活了。 3 、可以收费,最好是订阅制,因为只有收费,才让自己有动力维护更新。 最终,结合自己工作当中遇到的一些同事处理 Excel 表格的需求,决定做一个 AI 帮助处理表格的功能。

调研

花一天时间看了几款 AI 处理表格的功能,因为 AI 的能力太广,很多表格的处理都是洞察,绘图,分析,生成报告,很多功能很花哨,但是真的只是随便聊聊,炫技的成分更大。综合看下来,发现 2 个痛点: 1 、功能复杂的,小白玩不转,而且生成的代码,本地需要部署环境,很多人不会 2 、绘图、洞察这些比较聊胜于无,人类自己都搞不清楚要什么的事情,让 AI 做,最后可能得到的结果,也只是看个热闹

功能

基于前面的考虑,最终决定整个产品的核心功能 1 、基于 AI 生成 Pandas 代码,帮助打工人处理表格,这样重复性任务,可以每次重新运行就好了。 2 、云端执行代码,免去安装环境配置的麻烦。

开发

不得不说,Cursor 真的让非程序员,也能干简单程序员的活,只要你有一定的产品思维,即使没有完整做过开发类的项目,也能直接上手,做一个完整的产品。以前做产品,还需要搭配程序员一起做,现在真的就可以完全独立开发了。花了 2 周时间整个产品做完上线了,虽然还有瑕疵,但是这个开发速度,已经远远超出我的意料了。

这两周,我做了些什么事?

1 、花了半天时间研究前后端框架,虽然公司做项目是 java 为主,但是个人完全不喜欢 java ,最终选择目前比较流行的 fastapi 和 nextjs ,作为项目的前后端框架。没有很深的技术调研,只是觉得流行,github 的 start 高。

2 、先做核心功能,表格上传、解析、前端渲染、GPT 聊天、websocket 响应、sandbox 运行,整个核心功能大概花了三四天时间,基本就是 Cursor 给指令,输出的代码保存下来,运行报错就让 AI 改。

3 、再做官网、多语言,如果想付费,中国人的钱是挺难挣的,未来肯定还是要做海外用户,所以一定要做中英文 2 个版本,官网简单做做,加上一些用户协议,隐私条款,就够了。这里有点坑,AI 的知识库应该是基于 Nextjs13 训练的,i18n 的很多库兼容有问题,写法也不同,运行一堆报错,而且来回改了好多轮都改不好,最后花了一天时间,重新自学了 nextjs 的文档,才搞完。这个花了两三天。

4 、继续做注册、登录、个人中心、聊天历史记录、先做后端,再做前端。这样前端可以直接识别后端代码,就生成接口请求,基本一两天就做完。Cursor 的代码基本不用改,就能完全做好。

5 、对接支付,因为之前有申请过 ITIN 账号,所以 strip 注册半天就开通了,使用 AI 生成代码,基本轻车熟路,1 天就完成了对接。就有 1 点,支付宝权限的开通,大概等了一天。

6 、研究生产环境如何部署,AI 推荐都是 docker compose ,于是按照 nextjs 打包 standalone ,fastapi 直接找个镜像,很快就运行起来了,这个花了半天。

7 、最后,找服务器,原来一直有白嫖甲骨文云,用得挺好,于是想就在甲骨文买台机器算了,结果这里还出现了插曲,直接给我账号封了,真的是无语,邮件来回沟通未果,于是,去 AWS 注册,还有 1c1g 的机器免费 12 个月,系统初始化,安装上 docker ,启动发布,就完成了。

8 、接下来整理文档,示例,一些操作说明,这部分使用 gitbook ,直接配置一下就能完成。加上 AI 自带的多语言能力,把所有翻译都做了中英文版。

基本 2 周时间,整个产品就齐活了,目前已发布: https://excel.coffbox.com/

目前使用 OpenAI 的 gpt-4o-mini 模型和 Anthropic 的 claude-3-haiku ,因为它们有更快的响应速度,且能很好的胜任目前这份工作。

如何强行吃透一座屎山代码?

14 September 2024 at 09:34
qwerthhusn: 领导叫我把一套代码的逻辑吃透,重写合入到另外一个 baseline 项目,但是写那个代码的人水平是真的次,应该是刚毕业的,都没咋写过代码就直接上手项目。(我们现在在做工业上位机项目,都是现场开发功能的,没有代码质量管理)。

这个成为屎山有点夸张了,顶多是一个屎堆,但是味儿绝对正点。

* 代码没任何注释
* 到处都是类级别的变量
* 变量和函数和类都是随意起名字 id ,根据名字完全看不出来这个 identifier 是干嘛的,需要去看引用的地方才能看出来,但是有的引用层次关系网异常复杂,绕几下都忘记我要看的是哪个变量了。
* 手拼 JSON ,Split 拆 JSON 等这种操作到处都是。
* 巨无霸代码,所有东西写在一起,有好几个 10000+行数的代码文件。

虽然我工作这么多年也见过非常多的屎山项目,以前做互联网后端,微服务兴起之前,我见到过比这大得多的多的屎山代码,全量编译都能编译个一二十分钟的都有。但是以前是只是在项目上再加点料就行了,而现在要做的是把整个项目吃透,我该怎么办?有没有啥好的策略?

PS:跑路不能算是一个好策略,我在看这坨代码的时候晕头转向,满脑子都在想着跑路,但是现在工作太难找了,经历过后疫情的裁员后找工作从希望到失望到绝望的感觉,我宁愿继续啃这坨代码。

写 RUST 写的好爽

7 September 2024 at 08:32
DollarKiller:

感觉 rust 配合 ai 写代码超级爽 效率超高的:


我使用 RUST 搭配 Codeium 和 ChatGPT 写代码的技巧

感觉 codeium 搞歧视 rust 提示很全,golang 的提示就相比少了很多

开发步骤:

  1. 确定功能和方法: 首先,先想好你需要实现的功能。然后,根据功能列出需要的方法以及每个方法的用途。

  2. 定义输入输出: 接着,明确每个方法的输入参数和返回值。如果涉及到结构体等复杂数据类型,直接将这些结构体交给 ChatGPT 来生成代码。

  3. 无需过多思考细节: 在这个过程中,你几乎不需要过多思考代码细节。只要考虑好功能模块、数据来源以及数据加工的逻辑,剩下的就可以交给 Codeium 和 ChatGPT 来完成。

示例代码:

fn example_function() {
    // 定义好方法名、功能、输入参数、返回值等,如果涉及数据库操作告诉他怎么取数据 orm 是什么 然后直接扔给 chatgpt
}

后端接口一定要保持单一职责吗

7 September 2024 at 00:17
chenxiaolani:

之前干前端的时候遇到一个需求就是需要用表格展示一些订单或者商品信息,但是跟我对接的后端哥们让我从两个接口拿。但是我想让他再单独出一个接口直接返回我所有的信息,这样我就不用请求两次接口再拼装展示到表格中; 我的想法就是: 单独一次的请求肯定比两次性能好,万一有一个请求嘎了或者慢了, 表格数据就加载慢或者不出来了。

后端那哥们的想法是:接口需要保持单一职责,再单独出一个接口就重复了。

当时刚到那家公司,也没劲跟这哥们扯犊子,不过他给的理由我也无办法反驳,但是我感觉我的想法也是对的。

大佬们遇到这种情况,最佳的做法应该是咋样的啊。

写 Go 真的好爽

By: jlak
6 September 2024 at 15:56
jlak: 写 Go 一个月了,越写越爽,最近开始用上了 Ai 辅助后真倍爽
自己也没搞清楚为什么写 Go 就会特别爽
有可能是规范和提示,这点动态语言不太完善
(但是不知道为什么 TS 就不爱用)
即使给程序来个大改也比较轻松不容易出错
还有代码是真的容易看懂
自己写的也好别人写的也好从来没想过能这么容易懂
❌
❌