WWW.YOUINFO.SITE
标签聚合 多年

/tag/多年

LinuxDo 最新话题 · 2026-06-11 22:06:14+08:00 · tech

叱咤北京高校圈的明星摊贩“鹅腿阿姨”,刚进军市中心的国贸商圈没几天,就被上班族们识破,她十几年来都在“挂鹅腿卖鸭腿”。 “鹅腿阿姨”本名陈秀凤,近年在北京大学、清华大学等中国顶尖高校附近摆摊卖烧烤鹅腿走红。她在2023年曾因从北大转到清华门口摆摊,而引发“清北人鹅腿阿姨之争”,不少学生顶着寒风在深夜排队抢购的场面,还一度登上微博热搜。 据媒体报道,陈秀凤2011年初开始摆摊卖鹅腿,2016年起开放微信预订后,业务逐渐扩展至北京海淀区的高校圈,微信配送群多达五六十个。 早在2023年,就有学生在知乎发帖质疑,陈秀凤以鸭腿充当鹅腿销售。不过,贴文引发“鹅腿阿姨”粉丝们的反驳与声讨,争议很快不了了之。 2024年,又有学生反映陈秀凤售卖的鹅腿泛绿光,内部有绿色疑似霉斑的物质;陈秀凤声称这是葱汁榨汁腌制浸泡造成的“纯绿色食品”。质疑声还是未能阻挡“鹅腿阿姨”被学子们越捧越红。 2024年有学生反映陈秀凤售卖的鹅腿泛绿光,内部有绿色疑似霉斑的物质。(互联网) 本月4日,陈秀凤在朋友圈宣布要“勇闯国贸CBD”,不料没过几天,就被国贸上班族举报货不对板。她本周在微信订购群里承认,原始食材鹅腿“已断货十五年有余”,目前的原材料是鸭腿,后续会“写清楚”。 陈秀凤还称,“鹅腿阿姨”叫了十几年,不存在欺诈等行为,“本来就是小本生意,也没有故意存在欺诈宣传”。 迟到了十几年的真相,让“鹅腿阿姨”的顾客们大为震惊。一名北大学生感叹:“一想到我这么喜欢的‘鹅腿’其实是鸭腿,我就手脚冰凉、遍体生寒…” 陈秀凤告诉媒体,她2011年开始卖烧烤时确实是用鹅腿,但大约一两个月后货源断了,找了很多地方找不到符合要求的鹅腿,就改用鸭腿。但网传微信群截图显示,她对外一直宣称卖的是“鹅腿”。 登北大讲堂分享创业故事 卖了十多年鸭腿的“鹅腿阿姨”,不仅没有被学生识破,还在2024年的国际劳动妇女节受邀到北大百周年纪念讲堂演讲,分享她的创业之路。 2024年3月,陈秀凤(右)受邀出席论坛,向北大学子们分享她的创业故事。(北京大学官微) 据《北京青年报》报道,陈秀凤在分享中提到,她老家在江苏连云港,早年曾在北大西南门卖水果,后来发现卖烧烤收入更可观,便支了个烧烤摊开始卖鹅腿。为了方便学生预订鹅腿,她把自己的微信名字改为“鹅腿阿姨”。 提到制作“鹅腿”的过程,陈秀凤称,每天早上7点,供应商将新鲜的鹅腿送到她的手上,她先把鹅腿全部清洗,然后改刀。因为洗鹅腿用的是冷水,她的手经过长期浸泡,关节都变形了。改刀也常常花费三四个小时,才能切出大小基本一致的鹅腿。 然而,在微信群里和学生们沟通时,陈秀凤又称“鹅腿”是冷冻的。 另据观察者网,陈秀凤也在北大讲台上向学生们分享自己的“生意经”。她说,一是讲规则,和同学们建立信任关系。二是保证做良心活,就是要有高品质,不能让顾客遇到食品安全的问题,这也是特别重要的。 北大还曾在官方微信号推文《“鹅腿阿姨”来北大啦!》,记录陈秀凤的故事,不过目前相关文章已被删除。但她的分享内容在网络流传至今,这些看似朴实真诚的话语,现在读来更显讽刺。 据悉,陈秀凤的儿子还曾晒出微信聊天截图,指有中共中央党校的顾客希望订购“鹅腿”,他回应称“级别太高,暂时不送”。对此有网民调侃:“他们也知道谁不能骗。” 月入数万元 注册多个商标 网民愤怒的另一个原因,则是“鹅腿”的售价。对于货真价实的熟食鹅腿来说,16元(人民币,下同,约3新元)一个是闻所未闻的低价;但对于冷冻鸭腿而言,这个价格远不算便宜。 界面新闻星期三(6月10日)走访北京新发地市场发现,鸭腿与鹅腿的批发价天差地别。一只鸭腿的批发价约为2.5元,电商平台冻鸭腿单价不到2元。相比之下,电商平台冷冻鹅腿的单价在14元至15元左右,相差超过五倍。 以此计算,陈秀凤一只售价16元的鸭腿,利润约13元;一天卖出300多只,利润就达到4000元。全年无休且不算房租、代理商分成的情况下,利润高达146万元。 不过,陈秀凤的儿子否认了“年收入数百万”的说法,称一家人一个月收入在5万元左右。陈秀凤丈夫则说,他们用的鸭腿进价四五元,“品质好”,加上一年20万元店面租金、酱料及水电等成本,“16元一个的定价并不高”。 媒体还发现,陈秀凤的“鹅腿”生意早已悄然做大。 界面新闻报道,陈秀凤的“鹅腿”业务已覆盖北京几十所高校,团购成员超10万人次,跟团人次达20万,配送范围从北京的海淀区延伸至38公里外的房山区,拥有注册商标、正式后厨、雇佣员工及第三方配送代理,规模已堪比一家公司。 另据天眼查及中国商标网信息显示,2024年至2026年,陈秀凤申请过“鹅腿阿姨”等多枚商标,部分商标已经注册成功,国际分类涉及方便食品、广告销售、食品、医疗园艺等。 网传“鹅腿阿姨”后厨照片显示,有多名男子在厨房烤“鹅腿”,并非像陈秀凤此前所说,均由她亲自烤制。(互联网) 捧得越高 摔得越狠? 随着舆情持续发酵,中国消费者协会工作人员星期四(11日)回应中国新闻周刊称,中消协已关注到此事,将搜集相关线索,统一汇总成相关情况说明。目前,相关行政部门已介入调查。 同日,北京市海淀区市场监督管理局通报,已组织相关市场监管所,就“鹅腿阿姨”事件开展调查、问询当事人。目前当局正对其涉嫌误导消费者等行为进一步核查,下一步将依法依规处置。 北京安剑律师事务所周兆成律师撰文分析,陈秀凤明知原料是鸭腿,却十余年未主动公示,仅模糊规避标注,属于隐瞒关键商品信息、引人误解的虚假宣传,其行为已构成民事欺诈。对此,消费者可主张退一赔三,单笔赔偿不足500元按500元赔付。 周兆成补充,陈秀凤还面临多项行政处罚,包括市场监管处罚(可被处以20万至200万元罚款,以及责令停业、没收违法所得),以及无证经营风险等。 他同时研判,陈秀凤或处于刑事追责边界。若她长期累计销售金额超5万元,以鸭充鹅属于以假充真,涉嫌生产、销售伪劣产品罪,将被追究刑事责任。 还有网民翻出2019年的案例,指北京两名餐馆经营者以鸭肉冒充鹅肉制作成“烧鹅”销售,分别被判处有期徒刑二年六个月、缓刑三年,并罚款15万元,呼吁以此标准严惩陈秀凤。 一场以鸭充鹅的路边摊骗局,虽未导致严重食安事故,却引发舆情层层升温。央视网星期四就此评论:“这些套路并非惊天骗局,却处处透着‘险恶’。它的伤害性可能不大,但恶心人,也寒人心。套路千万条,真诚第一条。” 网民们从中总结的教训是:“别相信大学生推荐的美食,只要给的东西多,放料足,大学生啥都觉得好吃。” 对于购买“鹅腿”的学生们来说,除了满足口腹之欲,某种程度上也是为了共享校园生活的氛围,表达对靠双手讨生活的小商贩的支持与认同。因此,当他们发现善良勤恳的“鹅腿阿姨”,实则是弄虚作假的奸商,难免感到被欺骗。 在这个造神快、塌房也快的流量时代,人们支持的究竟是真实的劳动价值,还是精心包装的人设故事,或许是这场风波留给公众的最大疑问。 zaobao.com.sg 下午察:游走高校圈多年 “鹅腿阿姨”进城后翻车了 叱咤北京高校圈的明星摊贩“鹅腿阿姨”,刚进军市中心的国贸商圈没几天,就被上班族们识破,她十几年来都在“挂鹅腿卖鸭腿”。 17 个帖子 - 14 位参与者 阅读完整话题

v2ex · 2026-06-11 16:43:42+08:00 · tech

做了 10 多年, 发现那些搞 .Net / Ruby / Delphi 的人好像都不见了 还有 iOS / Android 开发工程师,现在也少 近几年,Go / Rust / Python 岗位也不多 AI 出来后,特殊工种也没有以前那么吃香 很多公司,还是后端加前端的模式,有大量 java 工程师和前端工程师 有时候在想🤔,如果没有前端,就转后端或者全栈,感觉后端似乎更容易? 到现在为止,我还在写前端。 除非哪天,公司要求写全栈,否则我应该不会想碰后端。 Ref 为什么总是“前端已死”? 前端死八百回了,我还在做前端 - V2EX

v2ex · 2026-06-11 16:14:32+08:00 · tech

做了 10 多年, 发现那些搞 .Net / Ruby / Delphi 的人好像都不见了 还有 iOS / Android 开发工程师,现在也少 近几年,Go / Rust / Python 岗位也不多 AI 出来后,特殊工种也没有以前那么吃香 很多公司,还是后端加前端的模式,有大量 java 工程师和前端工程师 有时候在想🤔,如果没有前端,就转后端或者全栈,感觉后端似乎更容易? 到现在为止,我还在写前端。 除非哪天,公司要求写全栈,否则我应该不会想碰后端。 Ref 为什么总是“前端已死”? 前端死八百回了,我还在做前端 - V2EX

v2ex · 2026-06-11 16:03:18+08:00 · tech

做了 10 多年, 发现那些搞 .Net / Ruby / Delphi 的人好像都不见了 还有 iOS / Android 开发工程师,现在也少 近几年,Go / Rust / Python 岗位也不多 AI 出来后,特殊工种也没有以前那么吃香 很多公司,还是后端加前端的模式,有大量 java 工程师和前端工程师 有时候在想🤔,如果没有前端,就转后端或者全栈,感觉后端似乎更容易? 到现在为止,我还在写前端。 除非哪天,公司要求写全栈,否则我应该不会想碰后端。 Ref 为什么总是“前端已死”? 前端死八百回了,我还在做前端 - V2EX

v2ex · 2026-06-11 16:01:14+08:00 · tech

做了 10 多年, 发现那些搞 .Net / Ruby / Delphi 的人好像都不见了 还有 iOS / Android 开发工程师,现在也少 近几年,Go / Rust / Python 岗位也不多 AI 出来后,特殊工种也没有以前那么吃香 很多公司,还是后端加前端的模式,有大量 java 工程师和前端工程师 有时候在想🤔,如果没有前端,就转后端或者全栈,感觉后端似乎更容易? 到现在为止,我还在写前端。 除非哪天,公司要求写全栈,否则我应该不会想碰后端。 Ref 为什么总是“前端已死”? 前端死八百回了,我还在做前端 - V2EX

v2ex · 2026-06-11 14:56:08+08:00 · tech

做了 10 多年, 发现那些搞 .Net / Ruby / Delphi 的人好像都不见了 还有 iOS / Android 开发工程师,现在也少 近几年,Go / Rust / Python 岗位也不多 AI 出来后,特殊工种也没有以前那么吃香 很多公司,还是后端加前端的模式,有大量 java 工程师和前端工程师 有时候在想🤔,如果没有前端,就转后端或者全栈,感觉后端似乎更容易? 到现在为止,我还在写前端。 除非哪天,公司要求写全栈,否则我应该不会想碰后端。 Ref 为什么总是“前端已死”? 前端死八百回了,我还在做前端 - V2EX

v2ex · 2026-06-11 14:36:11+08:00 · tech

做了 10 多年, 发现那些搞 .Net / Ruby / Delphi 的人好像都不见了 还有 iOS / Android 开发工程师,现在也少 近几年,Go / Rust / Python 岗位也不多 AI 出来后,特殊工种也没有以前那么吃香 很多公司,还是后端加前端的模式,有大量 java 工程师和前端工程师 有时候在想🤔,如果没有前端,就转后端或者全栈,感觉后端似乎更容易? 到现在为止,我还在写前端。 除非哪天,公司要求写全栈,否则我应该不会想碰后端。 Ref 为什么总是“前端已死”? 前端死八百回了,我还在做前端 - V2EX

v2ex · 2026-06-11 14:27:42+08:00 · tech

做了 10 多年, 发现那些搞 .Net / Ruby / Delphi 的人好像都不见了 还有 iOS / Android 开发工程师,现在也少 近几年,Go / Rust / Python 岗位也不多 AI 出来后,特殊工种也没有以前那么吃香 很多公司,还是后端加前端的模式,有大量 java 工程师和前端工程师 有时候在想🤔,如果没有前端,就转后端或者全栈,感觉后端似乎更容易? 到现在为止,我还在写前端。 除非哪天,公司要求写全栈,否则我应该不会想碰后端。 Ref 为什么总是“前端已死”? 前端死八百回了,我还在做前端 - V2EX

v2ex · 2026-06-11 14:22:25+08:00 · tech

做了 10 多年, 发现那些搞 .Net / Ruby / Delphi 的人好像都不见了 还有 iOS / Android 开发工程师,现在也少 近几年,Go / Rust / Python 岗位也不多 AI 出来后,特殊工种也没有以前那么吃香 很多公司,还是后端加前端的模式,有大量 java 工程师和前端工程师 有时候在想🤔,如果没有前端,就转后端或者全栈,感觉后端似乎更容易? 到现在为止,我还在写前端。 除非哪天,公司要求写全栈,否则我应该不会想碰后端。 Ref 为什么总是“前端已死”? 前端死八百回了,我还在做前端 - V2EX

LinuxDo 最新话题 · 2026-06-10 17:07:09+08:00 · tech

https://www.nature.com/articles/d41586-026-01780-6 [!quote]+ 今年世界上两场最大癌症会议上,这个问题引起了广泛关注,假设层出不穷。超加工食品、肥胖、微生物毒素和农用化学品都被纳入考量。但答案依然难以捉摸。 “全球范围内,50岁以下人群中多种癌症的发病率正在上升,”肿瘤学家吴金美上周在伊利诺伊州芝加哥举行的美国临床肿瘤学会会议上对听众表示。“绝大多数被认为是零星的,原因不明。” 流行病学家成贤雅在加利福尼亚圣地亚哥举行的美国癌症研究协会(AACR)年会上表示,全球每天50岁以下成年人诊断出超过9000例癌症病例。但她提醒说,将这些诊断混为一谈可能会掩盖其原因的线索。“年轻成人癌症发病率上升并非单一故事的体现,”在佐治亚州亚特兰大美国癌症协会工作的宋说。 即便如此,50岁以下人群的癌症死亡仍占整体癌症死亡率的一小部分。但这一代癌症的风险可能比前一代癌症更高,这种风险可能会持续到老年,届时整体癌症风险会大幅提高。宋说:“年轻人癌症发病率上升的趋势,真正预示着20年和30年后他们进入中年和老年时的未来。” 9 个帖子 - 7 位参与者 阅读完整话题

v2ex · 2026-06-10 16:43:25+08:00 · tech

书接上回: https://www.v2ex.com/t/1218755#reply0 首先跟兄弟们道个歉,因为发现还是感情贴热度高,没法,蹭蹭热度.感谢,祝大家早日财务自由! 前两天闲来无事做了一个项目,初衷和目的上一章都有,可能就是觉得不甘心吧.期间也认识了一些新的人接触一些新的知识. 还是觉得 ai 是用来更好的服务人民的,我这个如果开源了,旅游业会发展跟快一点.起码不是跟我左右到处碰壁.万一有人真成了,街头店家都可以用,收外国的钱.我感觉这个意义更好.希望如果有人做起来也挺好的.也不知道行不行. 以下是代码的一些内容,有用的自取,感谢. 架构 Vercel Fluid Compute 单函数入口 │ ▼ api/ index.py → app/ init .py (Flask app factory) │ ├── Session: Flask session cookie, HTTPOnly, SameSite=Lax ├── 存储: Upstash Redis REST API → 内存 dict fallback ├── AI: DeepSeek API (deepseek-chat) ├── 前端: Jinja2 模板 + Tailwind CDN + Vanilla JS │ └── 8 个 Blueprint: translate /api/translate, /api/export-* auth /api/auth/ , /login, /logout merchant /api/merchant/ gmb /api/gmb/* (Google OAuth) payment /api/payment/* (支付诊断) psb /api/psb/* (MRZ + 机构查询) beta /api/health, /api/admin/* guide /api/guide/checklist 源代码 api/ index.py — Vercel 入口 from app import create_app app = create_app() app/ init.py — Flask 工厂 import os from flask import Flask from dotenv import load_dotenv load_dotenv(".env.local", override=False) load_dotenv(".env", override=False) def create_app(): app = Flask( name , template_folder="templates") app.secret_key = os.getenv("SESSION_SECRET", os.urandom(24).hex()) app.config["SESSION_COOKIE_HTTPONLY"] = True app.config["SESSION_COOKIE_SAMESITE"] = "Lax" from app.translate import translate_bp from app.auth import auth_bp from app.merchant import merchant_bp from app.gmb import gmb_bp from app.payment import payment_bp from app.psb import psb_bp from app.beta import beta_bp from app.guide import guide_bp app.register_blueprint(translate_bp) app.register_blueprint(auth_bp) app.register_blueprint(merchant_bp) app.register_blueprint(gmb_bp) app.register_blueprint(payment_bp) app.register_blueprint(psb_bp) app.register_blueprint(beta_bp) app.register_blueprint(guide_bp) @app.route("/") def index(): from flask import render_template return render_template("index.html") @app.route("/dashboard") def dashboard(): from flask import render_template return render_template("dashboard.html") @app.route("/tripadvisor") def tripadvisor_guide(): from flask import render_template return render_template("tripadvisor_guide.html") @app.route("/psb") def psb_guide(): from flask import render_template return render_template("psb_guide.html") @app.route("/gmb/guide") def gmb_guide(): from flask import render_template return render_template("gmb_guide.html") @app.route("/health") def health(): from flask import redirect return redirect("/api/health") return app app/ kv_client.py — 存储抽象层 import os, json, time, threading from urllib.request import Request, urlopen def _strip_env(val): v = val.strip() if v and ord(v[0]) == 0xFEFF: # 去除 Upstash URL 的 BOM 前缀 v = v[1:] return v _REST_URL = _strip_env(os.getenv("UPSTASH_REDIS_REST_URL", "")) _REST_TOKEN = _strip_env(os.getenv("UPSTASH_REDIS_REST_TOKEN", "")) _REDIS_OK = None _MEMORY_STORE = {} _MEMORY_LOCK = threading.Lock() def _redis_cmd(*args): if not (_REST_URL and _REST_TOKEN): return None try: body = json.dumps(args).encode("utf-8") req = Request(_REST_URL, data=body, headers={ "Content-Type": "application/json", "Authorization": f"Bearer {_REST_TOKEN}", }) with urlopen(req, timeout=5) as r: resp = json.loads(r.read().decode("utf-8")) _REDIS_OK = True # FIXME: global mutable return resp.get("result") except Exception: _REDIS_OK = False return None 公开 API — Redis 优先,内存 fallback def redis_get(key): if _REST_URL and _REST_TOKEN: result = _redis_cmd("GET", key) if result is not None or _REDIS_OK: return result with _MEMORY_LOCK: entry = _MEMORY_STORE.get(key) if entry and entry.get("exp") and time.time() > ent del _MEMORY_STORE[key] return None return entry.get("val") if entry else None def redis_set(key, value, ex=None): if _REST_URL and _REST_TOKEN: if ex: result = _redis_cmd("SET", key, str(value), "EX", str(ex)) else: result = _redis_cmd("SET", key, str(value)) if result is not None or _REDIS_OK: return result with _MEMORY_LOCK: entry = {"val": str(value)} if ex: entry["exp"] = time.time() + int(ex) _MEMORY_STORE[key] = entry return True def redis_incr(key): if _REST_URL and _REST_TOKEN: result = _redis_cmd("INCR", key) if result is not None: return result with _MEMORY_LOCK: val = redis_get(key) new_val = (int(val) + 1) if val is not None else 1 _MEMORY_STORE[key] = {"val": str(new_val)} return new_val def redis_del(key): if _REST_URL and _REST_TOKEN: _redis_cmd("DEL", key) with _MEMORY_LOCK: _MEMORY_STORE.pop(key, None) def redis_keys(pattern): if _REST_URL and _REST_TOKEN: keys, cursor = [], "0" while True: result = _redis_cmd("SCAN", cursor, "MATCH", pattern, "COUNT", "200") if not isinstance(result, list) or len(result) < 2: return [] cursor = str(result[0]) if result[0] is not None else "0" keys.extend(result[1] if isinstance(result[1], list) else []) if cursor == "0": break return keys import re escaped = re.escape(pattern).replace(r"*", ".*") compiled = re.compile("^" + escaped + "$") with _MEMORY_LOCK: return [k for k in _MEMORY_STORE if compiled.match(k)] def is_redis_available(): if _REST_URL and _REST_TOKEN: return _redis_cmd("PING") == "PONG" return False app/ translate.py — AI 翻译(核心) import os, json, sys from urllib.request import Request, urlopen from urllib.error import URLError from flask import Blueprint, request, jsonify, session from app.rate_limit import rate_limit from app.auth import login_required from app.constants import HISTORY_MAX_ENTRIES, HISTORY_TTL translate_bp = Blueprint("translate", name ) PROMPTS = { "menu": { "en": "You are a professional restaurant menu translator. Translate Chinese menu items into natural, appetizing English...", "ja": "あなたはプロの料理メニュー翻訳者です...", "ko": "당신은 전문 레스토랑 메뉴 번역가입니다...", "ru": "Вы профессиональный переводчик меню ресторанов...", }, "checkin_guide": { ... }, "room_card": { ... }, "reg_card": { ... }, "emergency_card": { ... }, } LANGUAGES = [ {"code": "en", "label": "English", "flag": "🇬🇧"}, {"code": "ja", "label": "日本語", "flag": "🇯🇵"}, {"code": "ko", "label": "한국어", "flag": "🇰🇷"}, {"code": "ru", "label": "Русский", "flag": "🇷🇺"}, ] @ translate_bp .route("/api/translate", methods=["POST"]) @ rate_limit ("translate", identifier_fn=lambda: session.get("user_id", "anon")) def translate(): data = request.get_json() source_text = data.get("sourceText", "") material_type = data.get("materialType", "") target_lang = data.get("targetLang", "") api_key = os.getenv("DEEPSEEK_API_KEY", "").strip() system_prompt = PROMPTS.get(material_type, {}).get(target_lang, "") req_body = json.dumps({ "model": "deepseek-chat", "messages": [ {"role": "system", "content": system_prompt}, {"role": "user", "content": source_text}, ], "temperature": 0.3, "max_tokens": 4096, }).encode("utf-8") req = Request("https://api.deepseek.com/v1/chat/completions", data=req_body, headers={"Content-Type": "application/json", "Authorization": f"Bearer {api_key}"}) with urlopen(req, timeout=30) as r: body = json.loads(r.read().decode("utf-8")) translated = body["choices"][0]["message"]["content"]

v2ex · 2026-06-10 16:30:50+08:00 · tech

书接上回: https://www.v2ex.com/t/1218755#reply0 首先跟兄弟们道个歉,因为发现还是感情贴热度高,没法,蹭蹭热度.感谢,祝大家早日财务自由! 前两天闲来无事做了一个项目,初衷和目的上一章都有,可能就是觉得不甘心吧.期间也认识了一些新的人接触一些新的知识. 还是觉得 ai 是用来更好的服务人民的,我这个如果开源了,旅游业会发展跟快一点.起码不是跟我左右到处碰壁.万一有人真成了,街头店家都可以用,收外国的钱.我感觉这个意义更好.希望如果有人做起来也挺好的.也不知道行不行. 以下是代码的一些内容,有用的自取,感谢. 架构 Vercel Fluid Compute 单函数入口 │ ▼ api/ index.py → app/ init .py (Flask app factory) │ ├── Session: Flask session cookie, HTTPOnly, SameSite=Lax ├── 存储: Upstash Redis REST API → 内存 dict fallback ├── AI: DeepSeek API (deepseek-chat) ├── 前端: Jinja2 模板 + Tailwind CDN + Vanilla JS │ └── 8 个 Blueprint: translate /api/translate, /api/export-* auth /api/auth/ , /login, /logout merchant /api/merchant/ gmb /api/gmb/* (Google OAuth) payment /api/payment/* (支付诊断) psb /api/psb/* (MRZ + 机构查询) beta /api/health, /api/admin/* guide /api/guide/checklist 源代码 api/ index.py — Vercel 入口 from app import create_app app = create_app() app/ init.py — Flask 工厂 import os from flask import Flask from dotenv import load_dotenv load_dotenv(".env.local", override=False) load_dotenv(".env", override=False) def create_app(): app = Flask( name , template_folder="templates") app.secret_key = os.getenv("SESSION_SECRET", os.urandom(24).hex()) app.config["SESSION_COOKIE_HTTPONLY"] = True app.config["SESSION_COOKIE_SAMESITE"] = "Lax" from app.translate import translate_bp from app.auth import auth_bp from app.merchant import merchant_bp from app.gmb import gmb_bp from app.payment import payment_bp from app.psb import psb_bp from app.beta import beta_bp from app.guide import guide_bp app.register_blueprint(translate_bp) app.register_blueprint(auth_bp) app.register_blueprint(merchant_bp) app.register_blueprint(gmb_bp) app.register_blueprint(payment_bp) app.register_blueprint(psb_bp) app.register_blueprint(beta_bp) app.register_blueprint(guide_bp) @app.route("/") def index(): from flask import render_template return render_template("index.html") @app.route("/dashboard") def dashboard(): from flask import render_template return render_template("dashboard.html") @app.route("/tripadvisor") def tripadvisor_guide(): from flask import render_template return render_template("tripadvisor_guide.html") @app.route("/psb") def psb_guide(): from flask import render_template return render_template("psb_guide.html") @app.route("/gmb/guide") def gmb_guide(): from flask import render_template return render_template("gmb_guide.html") @app.route("/health") def health(): from flask import redirect return redirect("/api/health") return app app/ kv_client.py — 存储抽象层 import os, json, time, threading from urllib.request import Request, urlopen def _strip_env(val): v = val.strip() if v and ord(v[0]) == 0xFEFF: # 去除 Upstash URL 的 BOM 前缀 v = v[1:] return v _REST_URL = _strip_env(os.getenv("UPSTASH_REDIS_REST_URL", "")) _REST_TOKEN = _strip_env(os.getenv("UPSTASH_REDIS_REST_TOKEN", "")) _REDIS_OK = None _MEMORY_STORE = {} _MEMORY_LOCK = threading.Lock() def _redis_cmd(*args): if not (_REST_URL and _REST_TOKEN): return None try: body = json.dumps(args).encode("utf-8") req = Request(_REST_URL, data=body, headers={ "Content-Type": "application/json", "Authorization": f"Bearer {_REST_TOKEN}", }) with urlopen(req, timeout=5) as r: resp = json.loads(r.read().decode("utf-8")) _REDIS_OK = True # FIXME: global mutable return resp.get("result") except Exception: _REDIS_OK = False return None 公开 API — Redis 优先,内存 fallback def redis_get(key): if _REST_URL and _REST_TOKEN: result = _redis_cmd("GET", key) if result is not None or _REDIS_OK: return result with _MEMORY_LOCK: entry = _MEMORY_STORE.get(key) if entry and entry.get("exp") and time.time() > ent del _MEMORY_STORE[key] return None return entry.get("val") if entry else None def redis_set(key, value, ex=None): if _REST_URL and _REST_TOKEN: if ex: result = _redis_cmd("SET", key, str(value), "EX", str(ex)) else: result = _redis_cmd("SET", key, str(value)) if result is not None or _REDIS_OK: return result with _MEMORY_LOCK: entry = {"val": str(value)} if ex: entry["exp"] = time.time() + int(ex) _MEMORY_STORE[key] = entry return True def redis_incr(key): if _REST_URL and _REST_TOKEN: result = _redis_cmd("INCR", key) if result is not None: return result with _MEMORY_LOCK: val = redis_get(key) new_val = (int(val) + 1) if val is not None else 1 _MEMORY_STORE[key] = {"val": str(new_val)} return new_val def redis_del(key): if _REST_URL and _REST_TOKEN: _redis_cmd("DEL", key) with _MEMORY_LOCK: _MEMORY_STORE.pop(key, None) def redis_keys(pattern): if _REST_URL and _REST_TOKEN: keys, cursor = [], "0" while True: result = _redis_cmd("SCAN", cursor, "MATCH", pattern, "COUNT", "200") if not isinstance(result, list) or len(result) < 2: return [] cursor = str(result[0]) if result[0] is not None else "0" keys.extend(result[1] if isinstance(result[1], list) else []) if cursor == "0": break return keys import re escaped = re.escape(pattern).replace(r"*", ".*") compiled = re.compile("^" + escaped + "$") with _MEMORY_LOCK: return [k for k in _MEMORY_STORE if compiled.match(k)] def is_redis_available(): if _REST_URL and _REST_TOKEN: return _redis_cmd("PING") == "PONG" return False app/ translate.py — AI 翻译(核心) import os, json, sys from urllib.request import Request, urlopen from urllib.error import URLError from flask import Blueprint, request, jsonify, session from app.rate_limit import rate_limit from app.auth import login_required from app.constants import HISTORY_MAX_ENTRIES, HISTORY_TTL translate_bp = Blueprint("translate", name ) PROMPTS = { "menu": { "en": "You are a professional restaurant menu translator. Translate Chinese menu items into natural, appetizing English...", "ja": "あなたはプロの料理メニュー翻訳者です...", "ko": "당신은 전문 레스토랑 메뉴 번역가입니다...", "ru": "Вы профессиональный переводчик меню ресторанов...", }, "checkin_guide": { ... }, "room_card": { ... }, "reg_card": { ... }, "emergency_card": { ... }, } LANGUAGES = [ {"code": "en", "label": "English", "flag": "🇬🇧"}, {"code": "ja", "label": "日本語", "flag": "🇯🇵"}, {"code": "ko", "label": "한국어", "flag": "🇰🇷"}, {"code": "ru", "label": "Русский", "flag": "🇷🇺"}, ] @ translate_bp .route("/api/translate", methods=["POST"]) @ rate_limit ("translate", identifier_fn=lambda: session.get("user_id", "anon")) def translate(): data = request.get_json() source_text = data.get("sourceText", "") material_type = data.get("materialType", "") target_lang = data.get("targetLang", "") api_key = os.getenv("DEEPSEEK_API_KEY", "").strip() system_prompt = PROMPTS.get(material_type, {}).get(target_lang, "") req_body = json.dumps({ "model": "deepseek-chat", "messages": [ {"role": "system", "content": system_prompt}, {"role": "user", "content": source_text}, ], "temperature": 0.3, "max_tokens": 4096, }).encode("utf-8") req = Request("https://api.deepseek.com/v1/chat/completions", data=req_body, headers={"Content-Type": "application/json", "Authorization": f"Bearer {api_key}"}) with urlopen(req, timeout=30) as r: body = json.loads(r.read().decode("utf-8")) translated = body["choices"][0]["message"]["content"]

V2EX - 技术 · 2026-06-10 15:34:26+08:00 · tech

之前有 3 个 Voice 号通过 web 版每月手动互发不同语种歌词。 三月底互发时,一个近十年的号和一个十多年的号在各发送一条信息后 voice 账号被禁用了。 多次去 Google 申诉都是同样封禁不给用。去 FCC 投诉,Google 拖到最后一天回复让通过链接地址去申诉,结果还是不给解封。 为了暂时保住最后一个注册时间最长的 Voice 号,在刷了 xiaomi.eu 的 Note 12 Tubro 上安装了 Voice 应用,24 小时开启 SS 配置绕过大陆地址。 Voice 应用没有开启自启动,省电策略是后台运行超过 10 分钟后关闭。现状是不论停止运行多久只要收到信息都会第一时间推送通知。 本机上另外一个能抽风式推送通知的是智能省电策略的淘宝。其他 play 版应用即使点击打开都不会用推送通知。

V2EX - 技术 · 2026-06-10 14:34:26+08:00 · tech

之前有 3 个 Voice 号通过 web 版每月手动互发不同语种歌词。 三月底互发时,一个近十年的号和一个十多年的号在各发送一条信息后 voice 账号被禁用了。 多次去 Google 申诉都是同样封禁不给用。去 FCC 投诉,Google 拖到最后一天回复让通过链接地址去申诉,结果还是不给解封。 为了暂时保住最后一个注册时间最长的 Voice 号,在刷了 xiaomi.eu 的 Note 12 Tubro 上安装了 Voice 应用,24 小时开启 SS 配置绕过大陆地址。 Voice 应用没有开启自启动,省电策略是后台运行超过 10 分钟后关闭。现状是不论停止运行多久只要收到信息都会第一时间推送通知。 本机上另外一个能抽风式推送通知的是智能省电策略的淘宝。其他 play 版应用即使点击打开都不会用推送通知。