wwt-certificate-tool 1.2.32 → 1.2.33
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app.html +106 -10
- package/dist/version.json +6 -6
- package/package.json +1 -1
package/dist/app.html
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
6
|
-
<title>WWT 金蝶凭证工具 · 纯前端版 P1.2.
|
|
6
|
+
<title>WWT 金蝶凭证工具 · 纯前端版 P1.2.33</title>
|
|
7
7
|
<style>*{box-sizing:border-box;margin:0;padding:0}
|
|
8
8
|
body{font-family:"Microsoft YaHei","PingFang SC",-apple-system,Segoe UI,sans-serif;font-size:13px;color:#1f2328;background:#f4f6f9;line-height:1.6}
|
|
9
9
|
h1{font-size:17px;font-weight:600}
|
|
@@ -305,7 +305,7 @@ tr.bad:hover td{background:#fbe9e9}
|
|
|
305
305
|
<div class="brand">
|
|
306
306
|
<span class="logo">WWT</span>
|
|
307
307
|
<div>
|
|
308
|
-
<h1>金蝶凭证工具 <span class="ver">P1.2.
|
|
308
|
+
<h1>金蝶凭证工具 <span class="ver">P1.2.33</span></h1>
|
|
309
309
|
<div class="sub">纯前端离线版 · 双击即用 · 数据只存在本机,不上传任何服务器</div>
|
|
310
310
|
</div>
|
|
311
311
|
</div>
|
|
@@ -2263,10 +2263,15 @@ window.WWT_ENGINE = (function () {
|
|
|
2263
2263
|
|
|
2264
2264
|
/* ---------------- 金额表达式 ---------------- */
|
|
2265
2265
|
function isAutoDiff(line) { return clean(line && line.amountField) === "__AUTO_DIFF__"; }
|
|
2266
|
+
|
|
2267
|
+
// 兼容旧接口:返回 { parts: [{fld, sign}], auto? }。新逻辑统一走 evalAmtExpr,
|
|
2268
|
+
// 这里只为了不让外部旧调用点(如果有)报错。
|
|
2266
2269
|
function parseAmtExpr(expr) {
|
|
2267
2270
|
const e = clean(expr);
|
|
2268
2271
|
if (!e || e === "-") return null;
|
|
2269
2272
|
if (e === "__AUTO_DIFF__") return { auto: true };
|
|
2273
|
+
// 含 * / ( ) 时视为新语法(按 evalAmtExpr 处理),parts 留空
|
|
2274
|
+
if (/[*\/()]/.test(e)) return { parts: [], v2: true };
|
|
2270
2275
|
const parts = [];
|
|
2271
2276
|
for (let p of e.split("+")) {
|
|
2272
2277
|
p = p.trim();
|
|
@@ -2277,12 +2282,103 @@ window.WWT_ENGINE = (function () {
|
|
|
2277
2282
|
}
|
|
2278
2283
|
return parts.length ? { parts } : null;
|
|
2279
2284
|
}
|
|
2285
|
+
|
|
2286
|
+
// ============== 表达式解析器(支持 + - * / 括号 与 字段名/数字常量) ==============
|
|
2287
|
+
// 语法:
|
|
2288
|
+
// expr := term ( ('+'|'-') term )*
|
|
2289
|
+
// term := atom ( ('*'|'/') atom )*
|
|
2290
|
+
// atom := '-' atom | number | identifier | '(' expr ')'
|
|
2291
|
+
// identifier := 除空白与运算符之外的连续字符(即字段名)
|
|
2292
|
+
//
|
|
2293
|
+
// 设计目标:会计场景常见公式——`实收金额+折扣费` / `-折扣费` / `实收金额*0.13` / `金额/数量` / `(金额+税额)*0.13`
|
|
2294
|
+
// tokenize 时跳过空白;遇到运算符边界时,前一段连续字符要么是字段名,要么是数字。
|
|
2295
|
+
function tokenizeExpr(s) {
|
|
2296
|
+
const toks = [];
|
|
2297
|
+
let i = 0;
|
|
2298
|
+
while (i < s.length) {
|
|
2299
|
+
const c = s.charAt(i);
|
|
2300
|
+
if (c === ' ' || c === '\t') { i++; continue; }
|
|
2301
|
+
if (c === '+' || c === '*' || c === '/' || c === '(' || c === ')') { toks.push({ t: c }); i++; continue; }
|
|
2302
|
+
if (c === '-') {
|
|
2303
|
+
// 单目 vs 二元判断:若前一个 token 是操作符/左括号/开头,则是单目
|
|
2304
|
+
const prev = toks[toks.length - 1];
|
|
2305
|
+
const isUnary = !prev || (prev.t !== ')' && !/^\d/.test(prev.v || '') && prev.t !== 'num' && prev.t !== 'id');
|
|
2306
|
+
toks.push({ t: isUnary ? 'unary-' : '-' });
|
|
2307
|
+
i++; continue;
|
|
2308
|
+
}
|
|
2309
|
+
// 读一段连续字符
|
|
2310
|
+
let j = i;
|
|
2311
|
+
while (j < s.length) {
|
|
2312
|
+
const cj = s.charAt(j);
|
|
2313
|
+
if (cj === ' ' || cj === '\t') break;
|
|
2314
|
+
if ('+*-/()'.indexOf(cj) >= 0) break;
|
|
2315
|
+
j++;
|
|
2316
|
+
}
|
|
2317
|
+
const seg = s.slice(i, j);
|
|
2318
|
+
i = j;
|
|
2319
|
+
if (seg) {
|
|
2320
|
+
// 判断是数字(允许可选前导 0/小数点)
|
|
2321
|
+
if (/^-?\d+(\.\d+)?$/.test(seg) || /^\.\d+$/.test(seg)) toks.push({ t: 'num', v: parseFloat(seg) });
|
|
2322
|
+
else toks.push({ t: 'id', v: seg });
|
|
2323
|
+
}
|
|
2324
|
+
}
|
|
2325
|
+
return toks;
|
|
2326
|
+
}
|
|
2327
|
+
|
|
2328
|
+
function evalAmtExpr(row, expr) {
|
|
2329
|
+
const e = clean(expr);
|
|
2330
|
+
if (!e || e === "-") return 0;
|
|
2331
|
+
const toks = tokenizeExpr(e);
|
|
2332
|
+
let pos = 0;
|
|
2333
|
+
function peek() { return toks[pos]; }
|
|
2334
|
+
function eat(t) { if (toks[pos] && toks[pos].t === t) { pos++; return true; } return false; }
|
|
2335
|
+
function err(m) { throw new Error('金额表达式错误: ' + m + ' (pos=' + pos + ', expr=' + e + ')'); }
|
|
2336
|
+
|
|
2337
|
+
function parseExpr() {
|
|
2338
|
+
let v = parseTerm();
|
|
2339
|
+
while (true) {
|
|
2340
|
+
const p = peek();
|
|
2341
|
+
if (!p) break;
|
|
2342
|
+
if (p.t === '+') { pos++; v = v + parseTerm(); }
|
|
2343
|
+
else if (p.t === '-') { pos++; v = v - parseTerm(); }
|
|
2344
|
+
else break;
|
|
2345
|
+
}
|
|
2346
|
+
return v;
|
|
2347
|
+
}
|
|
2348
|
+
function parseTerm() {
|
|
2349
|
+
let v = parseAtom();
|
|
2350
|
+
while (true) {
|
|
2351
|
+
const p = peek();
|
|
2352
|
+
if (!p) break;
|
|
2353
|
+
if (p.t === '*') { pos++; v = v * parseAtom(); }
|
|
2354
|
+
else if (p.t === '/') {
|
|
2355
|
+
pos++;
|
|
2356
|
+
const d = parseAtom();
|
|
2357
|
+
if (d === 0) throw new Error('金额表达式除零 (expr=' + e + ')');
|
|
2358
|
+
v = v / d;
|
|
2359
|
+
}
|
|
2360
|
+
else break;
|
|
2361
|
+
}
|
|
2362
|
+
return v;
|
|
2363
|
+
}
|
|
2364
|
+
function parseAtom() {
|
|
2365
|
+
const p = peek();
|
|
2366
|
+
if (!p) err('缺少操作数');
|
|
2367
|
+
if (p.t === 'unary-') { pos++; return -parseAtom(); }
|
|
2368
|
+
if (p.t === '(') { pos++; const v = parseExpr(); if (!eat(')')) err('缺少右括号'); return v; }
|
|
2369
|
+
if (p.t === 'num') { pos++; return p.v; }
|
|
2370
|
+
if (p.t === 'id') { pos++; return num(row[p.v]); }
|
|
2371
|
+
err('非法 token: ' + JSON.stringify(p));
|
|
2372
|
+
}
|
|
2373
|
+
const v = parseExpr();
|
|
2374
|
+
if (pos !== toks.length) err('未消费完: ' + toks.slice(pos).map(t => t.v || t.t).join(' '));
|
|
2375
|
+
return v;
|
|
2376
|
+
}
|
|
2377
|
+
|
|
2280
2378
|
function sumAmtExpr(row, expr) {
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
for (const it of pe.parts) s += num(row[it.fld]) * it.sign;
|
|
2285
|
-
return s;
|
|
2379
|
+
if (isAutoDiff({ amountField: expr })) return 0;
|
|
2380
|
+
try { return round2(evalAmtExpr(row, expr)); }
|
|
2381
|
+
catch (e) { console.warn(e.message); return 0; }
|
|
2286
2382
|
}
|
|
2287
2383
|
|
|
2288
2384
|
/* ---------------- 映射查表 ---------------- */
|
|
@@ -3296,7 +3392,7 @@ window.WWT_ENGINE = (function () {
|
|
|
3296
3392
|
return {
|
|
3297
3393
|
clean, num, round2, normPay, pad3,
|
|
3298
3394
|
buildIndex, getField, compare, evalConditions, applyTransform,
|
|
3299
|
-
parseAmtExpr, sumAmtExpr, isAutoDiff, splitFieldsOf,
|
|
3395
|
+
parseAmtExpr, sumAmtExpr, evalAmtExpr, isAutoDiff, splitFieldsOf,
|
|
3300
3396
|
calcDimValues, leafSubject, resolveEffectiveLines, lookupTypeDim,
|
|
3301
3397
|
generate, balanceCheck, buildKingdee, detect, auditRule,
|
|
3302
3398
|
lookupMap, lookupTypeMap,
|
|
@@ -3322,7 +3418,7 @@ const S = window.__STATE__ = {
|
|
|
3322
3418
|
};
|
|
3323
3419
|
|
|
3324
3420
|
/* ---------------- 版本 & 框架自动更新(只更新程序本身,本地数据/规则不动) ---------------- */
|
|
3325
|
-
const WWT_VER=(function(){const raw='P1.2.
|
|
3421
|
+
const WWT_VER=(function(){const raw='P1.2.33';return raw.indexOf('__WVER__')>=0?'P1.2.10':raw;})();
|
|
3326
3422
|
const UPD_URL_KEY='wwt_fe_updurl';
|
|
3327
3423
|
// 默认更新源:Gitee 上本项目的 version.json(API 接口,浏览器可直接跨域读)
|
|
3328
3424
|
const DEFAULT_UPD_URL='https://gitee.com/api/v5/repos/wwtmrhu/certificate-generation/contents/dist/version.json';
|
|
@@ -4913,7 +5009,7 @@ function lineHTML(bi,li,l){
|
|
|
4913
5009
|
return '<div class="sec linerow" data-bi="'+bi+'" data-li="'+li+'" style="background:#fff;margin:5px 0">'+
|
|
4914
5010
|
'<div class="row"><select class="w60" data-lf="side">'+sideOpts+'</select>'+
|
|
4915
5011
|
'<span class="w60">科目</span><input class="w140" data-lf="subject" value="'+esc(l.subject||'')+'" placeholder="如 1122 / 6002" list="dlSubjects" title="可下拉选会计科目表里的编码;也可手动输入">'+
|
|
4916
|
-
'<span class="w60">金额</span><input class="w180" data-lf="amountField" value="'+esc(l.amountField||'')+'" placeholder="实收金额+折扣费 / -折扣费 /
|
|
5012
|
+
'<span class="w60">金额</span><input class="w180" data-lf="amountField" value="'+esc(l.amountField||'')+'" placeholder="实收金额+折扣费 / -折扣费 / 金额*0.13 / 金额/数量" list="dlBizFields" title="支持四则运算与括号:字段名/数字常量;例:实收金额+折扣费、-折扣费、金额*0.13、金额/数量、(金额+税额)*0.13。特殊值:__AUTO_DIFF__ 自动补差额">'+
|
|
4917
5013
|
'<button class="mini del" onclick="UI.delRow(this,\'linerow\')">删除分录</button></div>'+
|
|
4918
5014
|
'<div class="row"><span class="w60">摘要</span><input class="grow" data-lf="summary" value="'+esc(l.summary||'')+'" placeholder="{单位名称}{收入板块}对帐S{原单号}"></div>'+
|
|
4919
5015
|
'<div style="font-size:11.5px;color:#57606a;margin:3px 0">辅助核算维度:</div>'+
|
package/dist/version.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
|
-
"ver": "P1.2.
|
|
3
|
-
"npm": "1.2.
|
|
4
|
-
"url": "https://cdn.jsdelivr.net/npm/wwt-certificate-tool@1.2.
|
|
5
|
-
"url_unpkg": "https://unpkg.com/wwt-certificate-tool@1.2.
|
|
6
|
-
"url_gh": "https://api.github.com/repos/huweipei745839/certificate-generation/contents/dist/WWT%E5%87%AD%E8%AF%81%E5%B7%A5%E5%85%B7_P1.2.
|
|
7
|
-
"note": "
|
|
2
|
+
"ver": "P1.2.33",
|
|
3
|
+
"npm": "1.2.33",
|
|
4
|
+
"url": "https://cdn.jsdelivr.net/npm/wwt-certificate-tool@1.2.33/dist/app.html",
|
|
5
|
+
"url_unpkg": "https://unpkg.com/wwt-certificate-tool@1.2.33/dist/app.html",
|
|
6
|
+
"url_gh": "https://api.github.com/repos/huweipei745839/certificate-generation/contents/dist/WWT%E5%87%AD%E8%AF%81%E5%B7%A5%E5%85%B7_P1.2.33.html",
|
|
7
|
+
"note": "默认分录金额表达式支持四则运算与括号:① 字段名/数字常量,③ 运算符 + - * /,④ 括号 () 优先级,⑤ 单目负号(-字段 仍可用)。例:实收金额+折扣费、-折扣费、金额*0.13(税额)、金额/数量(单价)、(金额+税额)*0.13 嵌套。placeholder 文案与 tooltip 已同步更新。"
|
|
8
8
|
}
|