From 49f3e1a8a218c04400d1b84fa0efcce249938fcc Mon Sep 17 00:00:00 2001 From: Hermes Agent Date: Wed, 24 Jun 2026 09:47:36 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=BF=83=E9=94=80=E7=A0=81=E9=9A=90?= =?UTF-8?q?=E8=97=8Fid=E3=80=81=E8=87=AA=E5=8A=A8=E7=94=9F=E6=88=90?= =?UTF-8?q?=E3=80=81=E6=B7=BB=E5=8A=A0=E4=BA=8C=E7=BB=B4=E7=A0=81tool?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - json: id加入exclouded和editexclouded(不显示不输入) - 新增 api/promo_code_qr.dspy:为选中促销码生成二维码 - 修改 promote/index.dspy:支持code参数,未登录引导登录/注册 - toolbar添加'生成二维码'按钮,选中行后弹窗显示二维码 --- json/discount_promo_code_list.json | 31 ++++++++-- wwwroot/api/promo_code_qr.dspy | 76 +++++++++++++++++++++++ wwwroot/promote/index.dspy | 99 ++++++++++++++++++++++++++++-- 3 files changed, 196 insertions(+), 10 deletions(-) create mode 100644 wwwroot/api/promo_code_qr.dspy diff --git a/json/discount_promo_code_list.json b/json/discount_promo_code_list.json index db4f0fc..09d2e91 100644 --- a/json/discount_promo_code_list.json +++ b/json/discount_promo_code_list.json @@ -4,10 +4,7 @@ "title": "促销码", "params": { "browserfields": { - "id": { - "title": "促销码", - "width": 200 - }, + "exclouded": ["id"], "marketing_id": { "title": "营销方案", "width": 150 @@ -26,10 +23,36 @@ } }, "editexclouded": [ + "id", "resellerid", "sale_id", "created_at" ], + "toolbar": { + "tools": [ + { + "name": "generate_qr", + "label": "生成二维码", + "selected_row": true + } + ] + }, + "binds": [ + { + "wid": "self", + "event": "generate_qr", + "actiontype": "urlwidget", + "target": "PopupWindow", + "popup_options": { + "title": "促销码二维码", + "cwidth": 18, + "cheight": 22 + }, + "options": { + "url": "{{entire_url('../api/promo_code_qr.dspy')}}?id=${id}$" + } + } + ], "editable": { "new_data_url": "{{entire_url('../api/promo_code_create.dspy')}}", "update_data_url": "{{entire_url('../api/promo_code_update.dspy')}}", diff --git a/wwwroot/api/promo_code_qr.dspy b/wwwroot/api/promo_code_qr.dspy new file mode 100644 index 0000000..e6c5f2d --- /dev/null +++ b/wwwroot/api/promo_code_qr.dspy @@ -0,0 +1,76 @@ +# 为选中的促销码生成二维码 +from ahserver.serverenv import ServerEnv +from appPublic.qr import gen_qr_withlogo +from appPublic.jsonConfig import getConfig +from ahserver.filestorage import FileStorage +from sqlor.dbpools import DBPools +from appPublic.uniqueID import getID + +result = {'widgettype': 'Message', 'options': {'title': 'Error', 'message': 'Invalid', 'type': 'error'}} + +try: + env = ServerEnv() + dbname = env.get_module_dbname('discount') + promo_id = params_kw.get('id', '') + + if not promo_id: + raise Exception('Missing promo code id') + + async with DBPools().sqlorContext(dbname) as sor: + recs = await sor.R('discount_promo_code', {'id': promo_id}) + if not recs: + raise Exception(f'Promo code {promo_id} not found') + + # QR code URL: 扫码后进入促销绑定页面 + config = getConfig() + qr_url = env.entire_url('./promote') + f'?code={promo_id}' + fs = FileStorage() + p = fs._name2path(f'{getID()}.png') + gen_qr_withlogo(qr_url, p, logopath=config.logopath, logoloc='cc') + webp = fs.webpath(p) + qr_file_url = env.entire_url('/idfile') + f'?path={webp}' + + result = { + "widgettype": "VBox", + "options": {"width": "100%", "height": "100%", "spacing": 10}, + "subwidgets": [ + { + "widgettype": "Image", + "options": { + "width": "340px", + "height": "340px", + "url": qr_file_url + } + }, + { + "widgettype": "HBox", + "options": {"width": "100%", "cheight": 2}, + "subwidgets": [ + { + "widgettype": "Text", + "options": {"otext": "促销码:", "i18n": True, "cwidth": 5} + }, + { + "widgettype": "Text", + "options": {"text": promo_id} + } + ] + }, + { + "widgettype": "HBox", + "options": {"width": "100%", "cheight": 2}, + "subwidgets": [ + { + "widgettype": "Text", + "options": {"otext": "链接:", "i18n": True, "cwidth": 5} + }, + { + "widgettype": "Text", + "options": {"text": qr_url, "css": "text-muted"} + } + ] + } + ] + } +except Exception as e: + result = {'widgettype': 'Message', 'options': {'title': 'Error', 'message': str(e), 'type': 'error'}} diff --git a/wwwroot/promote/index.dspy b/wwwroot/promote/index.dspy index 83520ca..e92f860 100644 --- a/wwwroot/promote/index.dspy +++ b/wwwroot/promote/index.dspy @@ -1,6 +1,93 @@ -orgid = await get_userorgid() -if orgid is None: - return UiError(title='Error', message='You need login') - -ret = await set_promote_discount(request, params_kw) -return UiMessage(title="Succeeded", message=f'获得{ret}折扣') +# 促销码/折扣二维码 客户端入口 +# 参数: code=促销码id 或 id=discount_qr id +# 已登录: 直接绑定; 未登录: 提示登录/注册 + +from ahserver.serverenv import ServerEnv + +code = params_kw.get('code', '') +qr_id = params_kw.get('id', '') + +env = ServerEnv() +user = await env.get_user() + +if not user: + # 未登录 - 显示登录/注册引导 + back_url = '' + if code: + back_url = env.entire_url('./promote') + f'?code={code}' + elif qr_id: + back_url = env.entire_url('./promote') + f'?id={qr_id}' + + result = { + "widgettype": "VBox", + "options": {"width": "100%", "height": "100%", "spacing": 16, "padding": "20px"}, + "subwidgets": [ + { + "widgettype": "Title", + "options": {"text": "请先登录或注册", "level": 2, "i18n": True} + }, + { + "widgettype": "Text", + "options": {"otext": "使用促销码需要先登录,登录后将自动为您激活。", "i18n": True} + }, + { + "widgettype": "HBox", + "options": {"spacing": 10, "cheight": 3}, + "subwidgets": [ + { + "widgettype": "Button", + "options": { + "label": "登录", + "css": "primary", + "actiontype": "link", + "url": env.entire_url('/rbac/user/login') + f"?back={back_url}" if back_url else env.entire_url('/rbac/user/login') + } + }, + { + "widgettype": "Button", + "options": { + "label": "注册", + "css": "secondary", + "actiontype": "link", + "url": env.entire_url('/rbac/user/register') + f"?back={back_url}" if back_url else env.entire_url('/rbac/user/register') + } + } + ] + } + ] + } +elif code: + # 已登录 + 促销码参数 - 绑定促销码 + try: + # bind_customer expects promo_code_id + bind_params = params_kw.copy() + bind_params['promo_code_id'] = code + ret = await bind_customer(request, bind_params) + if ret.get('status') == 'success': + result = { + "widgettype": "VBox", + "options": {"width": "100%", "height": "100%", "spacing": 16, "padding": "20px"}, + "subwidgets": [ + { + "widgettype": "Message", + "options": {"title": "激活成功", "message": f"促销码 {code} 已成功激活,您已成为我们的客户!", "type": "success"} + } + ] + } + else: + result = { + "widgettype": "Message", + "options": {"title": "提示", "message": ret.get('message', '绑定失败'), "type": "warning"} + } + except Exception as e: + result = { + "widgettype": "Message", + "options": {"title": "激活失败", "message": str(e), "type": "error"} + } +else: + # 已登录 + 折扣二维码参数 - 走旧流程 + ret = await set_promote_discount(request, params_kw) + result = { + "widgettype": "Message", + "options": {"title": "成功", "message": f"获得{ret}折扣", "type": "success"} + }