refactor: 折扣设置改用Jinja2直建HBox列表+Form/UiFloat+changed事件, 废弃Tabular和inline_edit.js
This commit is contained in:
parent
1bf3528b6d
commit
2259b68789
@ -730,3 +730,44 @@ def load_discount():
|
||||
env.bind_customer = bind_customer
|
||||
env.get_customer_bind = get_customer_bind
|
||||
env.assign_customer_to_sale = assign_customer_to_sale
|
||||
# Discount setting products list
|
||||
env.get_discount_setting_products = get_discount_setting_products
|
||||
|
||||
|
||||
async def get_discount_setting_products(request):
|
||||
"""Get products with their discount details for discount_setting page.
|
||||
Used in Jinja2 template: {% set products = get_discount_setting_products(request) %}
|
||||
"""
|
||||
env = request._run_ns
|
||||
discountid = (getattr(request, '_params_kw', {}) or {}).get('discountid', '')
|
||||
user_orgid = await env.get_userorgid()
|
||||
|
||||
if not discountid or not user_orgid:
|
||||
return []
|
||||
|
||||
dbname = env.get_module_dbname('discount')
|
||||
db = DBPools()
|
||||
config = getConfig()
|
||||
db.databases = config.databases
|
||||
|
||||
sql = """
|
||||
SELECT
|
||||
p.id as productid,
|
||||
p.product_code,
|
||||
p.product_name,
|
||||
p.category_id,
|
||||
pc.name as category_name,
|
||||
dd.id as detail_id,
|
||||
dd.discount,
|
||||
dd.discountid
|
||||
FROM product p
|
||||
LEFT JOIN product_category pc ON p.category_id = pc.id
|
||||
LEFT JOIN discount_detail dd ON dd.productid = p.id
|
||||
AND dd.discountid = ${discountid}$
|
||||
WHERE p.org_id = ${org_id}$ AND p.status = '1'
|
||||
ORDER BY pc.name, p.product_name
|
||||
"""
|
||||
|
||||
async with db.sqlorContext(dbname) as sor:
|
||||
recs = await sor.sqlExe(sql, {'discountid': discountid, 'org_id': user_orgid})
|
||||
return recs if recs else []
|
||||
|
||||
@ -95,7 +95,6 @@ for d in crud_defs:
|
||||
PATHS_ANY = [
|
||||
f"/{MOD}/menu.ui",
|
||||
f"/{MOD}/discount_setting",
|
||||
f"/{MOD}/discount_inline_edit.js",
|
||||
]
|
||||
|
||||
# 每个 CRUD 定义 → any 别名目录 + logined 页面和脚本
|
||||
|
||||
@ -1,116 +0,0 @@
|
||||
/**
|
||||
* Discount inline editor for discount_setting Tabular.
|
||||
* Scans discount cells after render and enables click-to-edit.
|
||||
*/
|
||||
(function() {
|
||||
var PROCESSED_CELLS = new WeakSet();
|
||||
var SETUP_INTERVAL = 300;
|
||||
|
||||
function findTabular() {
|
||||
if (typeof bricks === 'undefined') return null;
|
||||
try {
|
||||
return bricks.getWidgetById('product_discount_tbl', bricks.app.root);
|
||||
} catch(e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function setupCell(cell) {
|
||||
if (PROCESSED_CELLS.has(cell)) return;
|
||||
var text = cell.textContent.trim();
|
||||
if (text === '' || isNaN(parseFloat(text))) return;
|
||||
PROCESSED_CELLS.add(cell);
|
||||
|
||||
cell.style.cursor = 'pointer';
|
||||
cell.title = '点击编辑折扣';
|
||||
|
||||
cell.addEventListener('click', function(e) {
|
||||
e.stopPropagation();
|
||||
if (cell.querySelector('input')) return;
|
||||
|
||||
var oldVal = cell.textContent.trim();
|
||||
var inp = document.createElement('input');
|
||||
inp.type = 'number';
|
||||
inp.step = '0.01';
|
||||
inp.min = '0';
|
||||
inp.max = '1';
|
||||
inp.value = oldVal;
|
||||
inp.style.cssText = 'width:100%;box-sizing:border-box;text-align:center;background:#1E293B;color:#F1F5F9;border:1px solid #3B82F6;border-radius:4px;padding:2px 4px;font-size:12px;';
|
||||
|
||||
cell.textContent = '';
|
||||
cell.appendChild(inp);
|
||||
inp.focus();
|
||||
inp.select();
|
||||
|
||||
var saved = false;
|
||||
var saveFn = async function() {
|
||||
if (saved) return;
|
||||
saved = true;
|
||||
var newVal = inp.value.trim();
|
||||
inp.disabled = true;
|
||||
|
||||
if (newVal === oldVal) {
|
||||
cell.textContent = oldVal;
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
var url = new URL(window.location.href);
|
||||
var discountid = url.searchParams.get('discountid') || '';
|
||||
var rowEl = cell.closest('.tabular-row');
|
||||
var productId = '';
|
||||
var detailId = '';
|
||||
var dv = findTabular();
|
||||
if (dv && dv.scrollpanel) {
|
||||
for (var i = 0; i < dv.scrollpanel.children.length; i++) {
|
||||
var r = dv.scrollpanel.children[i];
|
||||
if (r.dom_element === rowEl && r.user_data) {
|
||||
productId = r.user_data.productid || '';
|
||||
detailId = r.user_data.detail_id || '';
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var resp = await fetch(
|
||||
url.origin + url.pathname.replace(/\/[^\/]*$/, '/save_discount.dspy'),
|
||||
{
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: JSON.stringify({
|
||||
discountid: discountid,
|
||||
productid: productId,
|
||||
detail_id: detailId,
|
||||
discount: newVal
|
||||
})
|
||||
}
|
||||
);
|
||||
|
||||
if (resp.ok) {
|
||||
cell.textContent = parseFloat(newVal).toString();
|
||||
} else {
|
||||
cell.textContent = oldVal;
|
||||
}
|
||||
} catch(ex) {
|
||||
cell.textContent = oldVal;
|
||||
}
|
||||
};
|
||||
|
||||
inp.addEventListener('blur', saveFn);
|
||||
inp.addEventListener('keydown', function(ev) {
|
||||
if (ev.key === 'Enter') { ev.preventDefault(); inp.blur(); }
|
||||
if (ev.key === 'Escape') { cell.textContent = oldVal; }
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function scan() {
|
||||
var dv = findTabular();
|
||||
if (!dv || !dv.scrollpanel || !dv.scrollpanel.dom_element) return;
|
||||
var cells = dv.scrollpanel.dom_element.querySelectorAll('.tabular-cell');
|
||||
cells.forEach(setupCell);
|
||||
}
|
||||
|
||||
// Keep scanning for new cells after each render
|
||||
setInterval(scan, SETUP_INTERVAL);
|
||||
})();
|
||||
@ -1,67 +1,88 @@
|
||||
{% set products = get_discount_setting_products(request) %}
|
||||
{
|
||||
"id": "product_discount_tbl",
|
||||
"widgettype": "Tabular",
|
||||
"widgettype": "VBox",
|
||||
"options": {
|
||||
"width": "100%",
|
||||
"height": "100%",
|
||||
"title": "产品折扣设置",
|
||||
"description": "选中行后点击「设置折扣」编辑,折扣值留空或填0可清除折扣",
|
||||
"css": "card",
|
||||
"toolbar": {
|
||||
"tools": [
|
||||
{
|
||||
"name": "set_discount",
|
||||
"label": "设置折扣",
|
||||
"selected_row": true,
|
||||
"icon": "{{entire_url('/bricks/imgs/edit.svg')}}"
|
||||
}
|
||||
]
|
||||
},
|
||||
"data_url": "{{entire_url('./get_products_with_discount.dspy')}}",
|
||||
"data_params": {
|
||||
"discountid": "{{params_kw.discountid}}"
|
||||
},
|
||||
"data_method": "GET",
|
||||
"row_options": {
|
||||
"idField": "productid",
|
||||
"checkField": "checked",
|
||||
"fields": [
|
||||
{
|
||||
"name": "category_name",
|
||||
"title": "产品分类",
|
||||
"type": "str",
|
||||
"cwidth": 3
|
||||
},
|
||||
{
|
||||
"name": "product_name",
|
||||
"title": "产品名称",
|
||||
"type": "str",
|
||||
"cwidth": 5
|
||||
},
|
||||
{
|
||||
"name": "product_code",
|
||||
"title": "产品编码",
|
||||
"type": "str",
|
||||
"cwidth": 3
|
||||
},
|
||||
{
|
||||
"name": "discount",
|
||||
"title": "当前折扣",
|
||||
"type": "float",
|
||||
"cwidth": 3
|
||||
}
|
||||
]
|
||||
},
|
||||
"page_rows": 100,
|
||||
"cache_limit": 5
|
||||
"css": "filler"
|
||||
},
|
||||
"binds": [
|
||||
"subwidgets": [
|
||||
{
|
||||
"wid": "set_discount",
|
||||
"event": "click",
|
||||
"actiontype": "script",
|
||||
"target": "self",
|
||||
"script": "var dv = bricks.getWidgetById('product_discount_tbl', bricks.app.root); if (!dv || !dv.select_row || !dv.select_row.user_data) { alert('请先选中一个产品'); return; } var row = dv.select_row.user_data; var discountid = new URLSearchParams(window.location.search).get('discountid') || ''; var mf = new bricks.ModalForm({title: '设置折扣 - ' + row.product_name, width: '400px', auto_open: true, fields: [{name: 'discountid', uitype: 'hide', value: discountid}, {name: 'productid', uitype: 'hide', value: row.productid}, {name: 'category_id', uitype: 'hide', value: row.category_id}, {name: 'detail_id', uitype: 'hide', value: row.detail_id || ''}, {name: 'product_name', label: '产品', uitype: 'text', value: row.product_name}, {name: 'category_name', label: '分类', uitype: 'text', value: row.category_name}, {name: 'discount', label: '折扣(0-1)', uitype: 'float', value: row.discount || '', tip: '0到1之间,如0.8表示8折,留空或0表示清除折扣'}], submit_url: '{{entire_url('./save_discount.dspy')}}'}); mf.bind('submited', async function(params) { await bricks.show_resp_message_or_error(params); await dv.render({}); });"
|
||||
"widgettype": "Text",
|
||||
"options": {
|
||||
"text": "产品折扣设置",
|
||||
"fontSize": "16px",
|
||||
"fontWeight": "600",
|
||||
"color": "#F1F5F9",
|
||||
"padding": "8px 12px"
|
||||
}
|
||||
},
|
||||
{
|
||||
"widgettype": "HBox",
|
||||
"options": {
|
||||
"bgcolor": "#0F172A",
|
||||
"padding": "8px 12px",
|
||||
"borderRadius": "6px 6px 0 0",
|
||||
"alignItems": "center"
|
||||
},
|
||||
"subwidgets": [
|
||||
{"widgettype": "Text", "options": {"text": "产品分类", "cwidth": 3, "fontSize": "12px", "fontWeight": "600", "color": "#94A3B8"}},
|
||||
{"widgettype": "Text", "options": {"text": "产品名称", "cwidth": 5, "fontSize": "12px", "fontWeight": "600", "color": "#94A3B8"}},
|
||||
{"widgettype": "Text", "options": {"text": "产品编码", "cwidth": 3, "fontSize": "12px", "fontWeight": "600", "color": "#94A3B8"}},
|
||||
{"widgettype": "Text", "options": {"text": "折扣(可编辑)", "cwidth": 3, "fontSize": "12px", "fontWeight": "600", "color": "#94A3B8"}}
|
||||
]
|
||||
},
|
||||
{
|
||||
"widgettype": "VBox",
|
||||
"id": "discount_rows",
|
||||
"options": {
|
||||
"width": "100%",
|
||||
"css": "childrensize"
|
||||
},
|
||||
"subwidgets": [
|
||||
{% for p in products %}
|
||||
{
|
||||
"widgettype": "HBox",
|
||||
"options": {
|
||||
"padding": "6px 12px",
|
||||
"border": "0 0 1px 0",
|
||||
"borderColor": "#334155",
|
||||
"alignItems": "center",
|
||||
"width": "100%"
|
||||
},
|
||||
"subwidgets": [
|
||||
{"widgettype": "Text", "options": {"text": "{{p.category_name or ''}}", "cwidth": 3, "fontSize": "12px", "color": "#E2E8F0"}},
|
||||
{"widgettype": "Text", "options": {"text": "{{p.product_name or ''}}", "cwidth": 5, "fontSize": "12px", "color": "#F1F5F9"}},
|
||||
{"widgettype": "Text", "options": {"text": "{{p.product_code or ''}}", "cwidth": 3, "fontSize": "12px", "color": "#E2E8F0"}},
|
||||
{
|
||||
"widgettype": "Form",
|
||||
"id": "discount_form_{{loop.index}}",
|
||||
"options": {
|
||||
"cwidth": 3,
|
||||
"show_label": false,
|
||||
"css": "childrensize",
|
||||
"submit_url": "{{entire_url('./save_discount.dspy')}}",
|
||||
"fields": [
|
||||
{"name": "discountid", "uitype": "hide", "value": "{{params_kw.discountid}}"},
|
||||
{"name": "productid", "uitype": "hide", "value": "{{p.productid}}"},
|
||||
{"name": "detail_id", "uitype": "hide", "value": "{{p.detail_id or ''}}"},
|
||||
{"name": "discount", "uitype": "float", "value": "{{p.discount or ''}}", "placeholder": "0~1", "dec_len": 2}
|
||||
]
|
||||
},
|
||||
"binds": [
|
||||
{
|
||||
"wid": "self",
|
||||
"event": "changed",
|
||||
"actiontype": "script",
|
||||
"target": "self",
|
||||
"script": "var form = this.target; var d = form.getValue(); var old = form._last_val; if (d.discount === old) return; form._last_val = d.discount; fetch(form.options.submit_url, {method:'POST', headers:{'Content-Type':'application/json'}, body:JSON.stringify(d)}).then(function(r){ return r.json(); }).then(function(resp){ if (resp.widgettype === 'Error') bricks.show_error(resp.options); else console.log('discount saved'); }).catch(function(e){ console.error(e); });"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}{% if not loop.last %},{% endif %}
|
||||
{% endfor %}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user