feat(api): 添加隐藏字段管理功能

在MetadataHandler中实现从代码获取隐藏字段列表的功能,并在字段处理逻辑中检查字段是否在隐藏列表中。更新前端字段选择组件,使用树形结构展示字段选择,支持多选和动态加载字段。增强用户体验,提供已选择字段数量的反馈。
This commit is contained in:
zhouyonggao 2025-12-08 14:45:33 +08:00
parent 02cd5f75b9
commit 7770d87259
4 changed files with 1772 additions and 1318 deletions

View File

@ -14,6 +14,10 @@ func MetadataHandler(meta, marketing, ymt *sql.DB) http.Handler {
if ds == "ymt" {
db = ymt
}
// 从代码中获取隐藏字段列表
hiddenFields := getHiddenFieldsFromCode(ds)
tables := []string{}
if ds == "ymt" {
tables = []string{"order_info", "order_cash", "order_voucher", "order_digit", "goods_voucher_batch", "goods_voucher_subject_config", "merchant", "activity"}
@ -29,6 +33,12 @@ func MetadataHandler(meta, marketing, ymt *sql.DB) http.Handler {
if tCanonical == "" || fCanonical == "" {
continue
}
// 检查字段是否在隐藏列表中
if isFieldHidden(hiddenFields, tCanonical, fCanonical) {
continue
}
lab := c.Comment
if lab == "" {
lab = fCanonical
@ -44,6 +54,465 @@ func MetadataHandler(meta, marketing, ymt *sql.DB) http.Handler {
})
}
// getHiddenFieldsFromCode 从代码中获取指定数据源的隐藏字段映射
// 返回 map[table]map[field]bool标记哪些字段需要隐藏
//
// 所有表的字段列表(基于 schema/fields.go
//
// Marketing 数据源表字段:
// - order: order_number, key, creator, out_trade_no, type, status, account, product_id, reseller_id, plan_id,
// key_batch_id, code_batch_id, pay_type, pay_status, use_coupon, deliver_status, expire_time,
// recharge_time, contract_price, num, total, pay_amount, create_time, update_time, card_code,
// official_price, merchant_name, activity_name, goods_name, pay_time, coupon_id, discount_amount,
// supplier_product_name, is_inner, icon, cost_price, success_num, is_reset, is_retry, channel,
// is_store, trace_id, out_order_no, next_retry_time, recharge_suc_time, supplier_id,
// supplier_product_id, merchant_id, goods_id, activity_id, key_batch_name
// 隐藏字段: id, order_id, key, creator_id, plan_id, product_id, reseller_id, supplier_id,
// supplier_product_id, key_batch_id, is_internal_supplier_order
// - order_detail: plan_title, order_number, reseller_name, product_name, show_url, official_price,
// cost_price, create_time, update_time
// - order_cash: order_no, trade_no, wechat_detail_id, channel, denomination, account, receive_name,
// app_id, cash_activity_id, receive_status, receive_time, success_time, cash_packet_id,
// channel_order_id, pay_fund_order_id, cash_id, amount, activity_id, goods_id, merchant_id,
// supplier_id, user_id, status, expire_time, create_time, update_time, version, is_confirm
// - order_voucher: channel, channel_activity_id, channel_voucher_id, status, receive_mode, grant_time,
// usage_time, refund_time, status_modify_time, overdue_time, refund_amount, official_price,
// out_biz_no, account_no
// - plan: id, title, status, begin_time, end_time
// - key_batch: id, batch_name, bind_object, quantity, stock, begin_time, end_time
// - code_batch: id, title, status, begin_time, end_time, quantity, usage, stock
// - voucher: channel, channel_activity_id, price, balance, used_amount, denomination
// - voucher_batch: channel_activity_id, temp_no, provider, weight
// - merchant_key_send: merchant_id, out_biz_no, key, status, usage_time, create_time
//
// YMT 数据源表字段:
// - order (order_info): order_number, key, creator, out_trade_no, type, status, account, product_id,
// reseller_id, plan_id, key_batch_id, code_batch_id, pay_type, pay_status,
// use_coupon, deliver_status, expire_time, recharge_time, contract_price, num,
// pay_amount, create_time, update_time, card_code, official_price, merchant_name,
// activity_name, goods_name, pay_time, coupon_id, discount_amount,
// supplier_product_name, is_inner, icon, cost_price, success_num, is_reset,
// is_retry, channel, is_store, trace_id, out_order_no, next_retry_time,
// recharge_suc_time, supplier_id, supplier_product_id, merchant_id, goods_id,
// activity_id, key_batch_name
// 隐藏字段: id, order_id, key, creator_id, plan_id, product_id, reseller_id, supplier_id,
// supplier_product_id, key_batch_id, is_internal_supplier_order
// - order_cash: order_no, trade_no, wechat_detail_id, channel, denomination, account, receive_name,
// app_id, cash_activity_id, receive_status, receive_time, success_time, cash_packet_id,
// channel_order_id, pay_fund_order_id, cash_id, amount, activity_id, goods_id, merchant_id,
// supplier_id, user_id, status, expire_time, create_time, update_time, version, is_confirm
// - order_voucher: channel, channel_activity_id, channel_voucher_id, status, receive_mode, grant_time,
// usage_time, refund_time, status_modify_time, overdue_time, refund_amount, official_price,
// out_biz_no, account_no
// - order_digit: order_no, card_no, account, goods_id, merchant_id, supplier_id, activity_id, user_id,
// success_time, supplier_product_no, order_type, end_time, create_time, update_time, code,
// sms_channel
// - goods_voucher_batch: channel_batch_no, voucher_subject_id, id, goods_voucher_id, supplier_id,
// temp_no, index, create_time, update_time
// - goods_voucher_subject_config: id, name, type, create_time
// - merchant: id, name, user_id, merchant_no, subject, third_party, status, balance, total_consumption,
// contact_name, contact_phone, contact_email, create_time, update_time
// - activity: id, name, user_id, merchant_id, user_name, activity_no, status, key_total_num,
// key_generate_num, key_usable_num, domain_url, theme_login_id, theme_list_id,
// theme_verify_id, settlement_type, key_expire_type, key_valid_day, key_begin_time,
// key_end_time, key_style, begin_time, end_time, is_retry, create_time, update_time,
// discard_time, delete_time, auto_charge, stock, approval_trade_no, amount, channels,
// key_begin, key_end, key_unit, key_pay_button_text, goods_pay_button_text,
// is_open_db_transaction
func getHiddenFieldsFromCode(ds string) map[string]map[string]bool {
result := make(map[string]map[string]bool)
if ds == "ymt" {
// YMT 数据源的隐藏字段配置 - 所有字段默认隐藏true
// order 表所有字段
result["order"] = map[string]bool{
"order_number": true,
"key": true,
"creator": false,
"out_trade_no": true,
"type": true,
"status": true,
"account": true,
"product_id": false,
"reseller_id": false,
"plan_id": false,
"key_batch_id": false,
"code_batch_id": false,
"pay_type": true,
"pay_status": true,
"use_coupon": true,
"deliver_status": true,
"expire_time": true,
"recharge_time": true,
"contract_price": true,
"num": true,
"pay_amount": true,
"create_time": true,
"update_time": true,
"card_code": true,
"official_price": true,
"merchant_name": true,
"activity_name": true,
"goods_name": true,
"pay_time": true,
"coupon_id": true,
"discount_amount": true,
"supplier_product_name": true,
"is_inner": false,
"icon": true,
"cost_price": true,
"success_num": true,
"is_reset": false,
"is_retry": false,
"channel": true,
"is_store": false,
"trace_id": false,
"out_order_no": true,
"next_retry_time": true,
"recharge_suc_time": true,
"supplier_id": false,
"supplier_product_id": false,
"merchant_id": false,
"goods_id": false,
"activity_id": false,
"key_batch_name": true,
"id": false,
"order_id": false,
"creator_id": false,
"is_internal_supplier_order": false,
}
// order_cash 表所有字段
result["order_cash"] = map[string]bool{
"order_no": true,
"trade_no": true,
"wechat_detail_id": false,
"channel": true,
"denomination": true,
"account": true,
"receive_name": true,
"app_id": true,
"cash_activity_id": true,
"receive_status": true,
"receive_time": true,
"success_time": true,
"cash_packet_id": false,
"channel_order_id": false,
"pay_fund_order_id": false,
"cash_id": true,
"amount": true,
"activity_id": false,
"goods_id": false,
"merchant_id": false,
"supplier_id": false,
"user_id": false,
"status": true,
"expire_time": true,
"create_time": true,
"update_time": false,
"version": false,
"is_confirm": true,
}
// order_voucher 表所有字段
result["order_voucher"] = map[string]bool{
"channel": true,
"channel_activity_id": true,
"channel_voucher_id": true,
"status": true,
"receive_mode": true,
"grant_time": true,
"usage_time": true,
"refund_time": true,
"status_modify_time": true,
"overdue_time": true,
"refund_amount": true,
"official_price": true,
"out_biz_no": true,
"account_no": true,
}
// order_digit 表所有字段
result["order_digit"] = map[string]bool{
"order_no": true,
"card_no": true,
"account": true,
"goods_id": false,
"merchant_id": false,
"supplier_id": false,
"activity_id": false,
"user_id": false,
"success_time": true,
"supplier_product_no": true,
"order_type": true,
"end_time": true,
"create_time": true,
"update_time": true,
"code": false,
"sms_channel": false,
}
// goods_voucher_batch 表所有字段
result["goods_voucher_batch"] = map[string]bool{
"channel_batch_no": true,
"voucher_subject_id": true,
"id": false,
"goods_voucher_id": false,
"supplier_id": false,
"temp_no": true,
"index": true,
"create_time": false,
"update_time": false,
}
// goods_voucher_subject_config 表所有字段
result["goods_voucher_subject_config"] = map[string]bool{
"id": true,
"name": true,
"type": true,
"create_time": true,
}
// merchant 表所有字段
result["merchant"] = map[string]bool{
"id": false,
"name": true,
"user_id": false,
"merchant_no": true,
"subject": true,
"third_party": false,
"status": false,
"balance": false,
"total_consumption": false,
"contact_name": true,
"contact_phone": false,
"contact_email": false,
"create_time": false,
"update_time": false,
}
// activity 表所有字段
result["activity"] = map[string]bool{
"id": false,
"name": true,
"user_id": false,
"merchant_id": false,
"user_name": true,
"activity_no": true,
"status": true,
"key_total_num": true,
"key_generate_num": true,
"key_usable_num": true,
"domain_url": false,
"theme_login_id": false,
"theme_list_id": false,
"theme_verify_id": false,
"settlement_type": true,
"key_expire_type": true,
"key_valid_day": true,
"key_begin_time": true,
"key_end_time": true,
"key_style": true,
"begin_time": true,
"end_time": true,
"is_retry": false,
"create_time": false,
"update_time": false,
"discard_time": false,
"delete_time": false,
"auto_charge": true,
"stock": true,
"approval_trade_no": false,
"amount": true,
"channels": true,
"key_begin": true,
"key_end": true,
"key_unit": false,
"key_pay_button_text": false,
"goods_pay_button_text": false,
"is_open_db_transaction": false,
}
} else {
// Marketing 数据源的隐藏字段配置 - 所有字段默认隐藏true
// order 表所有字段
result["order"] = map[string]bool{
"order_number": true,
"key": true,
"creator": true,
"out_trade_no": true,
"type": true,
"status": true,
"account": true,
"product_id": false,
"reseller_id": false,
"plan_id": false,
"key_batch_id": false,
"code_batch_id": false,
"pay_type": true,
"pay_status": true,
"use_coupon": true,
"deliver_status": true,
"expire_time": true,
"recharge_time": true,
"contract_price": true,
"num": true,
"total": true,
"pay_amount": true,
"create_time": true,
"update_time": true,
"card_code": true,
"official_price": true,
"merchant_name": true,
"activity_name": true,
"goods_name": true,
"pay_time": true,
"coupon_id": false,
"discount_amount": true,
"supplier_product_name": true,
"is_inner": false,
"icon": false,
"cost_price": true,
"success_num": true,
"is_reset": false,
"is_retry": false,
"channel": true,
"is_store": false,
"trace_id": false,
"out_order_no": true,
"next_retry_time": true,
"recharge_suc_time": true,
"supplier_id": true,
"supplier_product_id": false,
"merchant_id": false,
"goods_id": false,
"activity_id": false,
"key_batch_name": true,
"id": false,
"order_id": false,
"creator_id": false,
"is_internal_supplier_order": false,
}
// order_detail 表所有字段
result["order_detail"] = map[string]bool{
"plan_title": true,
"order_number": true,
"reseller_name": true,
"product_name": true,
"show_url": false,
"official_price": true,
"cost_price": true,
"create_time": false,
"update_time": false,
}
// order_cash 表所有字段
result["order_cash"] = map[string]bool{
"order_no": true,
"trade_no": true,
"wechat_detail_id": false,
"channel": true,
"denomination": true,
"account": true,
"receive_name": true,
"app_id": true,
"cash_activity_id": false,
"receive_status": true,
"receive_time": true,
"success_time": true,
"cash_packet_id": true,
"channel_order_id": false,
"pay_fund_order_id": false,
"cash_id": false,
"amount": true,
"activity_id": false,
"goods_id": false,
"merchant_id": false,
"supplier_id": false,
"user_id": false,
"status": true,
"expire_time": true,
"create_time": true,
"update_time": true,
"version": false,
"is_confirm": true,
}
// order_voucher 表所有字段
result["order_voucher"] = map[string]bool{
"channel": true,
"channel_activity_id": false,
"channel_voucher_id": false,
"status": true,
"receive_mode": true,
"grant_time": true,
"usage_time": true,
"refund_time": true,
"status_modify_time": true,
"overdue_time": true,
"refund_amount": true,
"official_price": true,
"out_biz_no": true,
"account_no": true,
}
// plan 表所有字段
result["plan"] = map[string]bool{
"id": false,
"title": true,
"status": true,
"begin_time": true,
"end_time": true,
}
// key_batch 表所有字段
result["key_batch"] = map[string]bool{
"id": false,
"batch_name": true,
"bind_object": true,
"quantity": true,
"stock": true,
"begin_time": true,
"end_time": true,
}
// code_batch 表所有字段
result["code_batch"] = map[string]bool{
"id": false,
"title": true,
"status": true,
"begin_time": true,
"end_time": true,
"quantity": true,
"usage": true,
"stock": true,
}
// voucher 表所有字段
result["voucher"] = map[string]bool{
"channel": true,
"channel_activity_id": false,
"price": true,
"balance": true,
"used_amount": true,
"denomination": true,
}
// voucher_batch 表所有字段
result["voucher_batch"] = map[string]bool{
"channel_activity_id": true,
"temp_no": true,
"provider": true,
"weight": true,
}
// merchant_key_send 表所有字段
result["merchant_key_send"] = map[string]bool{
"merchant_id": true,
"out_biz_no": true,
"key": true,
"status": true,
"usage_time": true,
"create_time": true,
}
}
return result
}
// isFieldHidden 检查字段是否在隐藏列表中
func isFieldHidden(hiddenFields map[string]map[string]bool, table, field string) bool {
tableFields, ok := hiddenFields[table]
if !ok {
return false
}
return tableFields[field]
}
func tableLabel(t string) string {
switch t {
case "order":

Binary file not shown.

View File

@ -128,21 +128,23 @@
</el-radio-group>
</el-form-item>
<el-form-item label="字段选择" required show-message prop="fieldsSel">
<div ref="createCascaderRoot">
<el-cascader
ref="fieldsCascader"
v-model="form.fieldsSel"
<div style="border: 1px solid #dcdfe6; border-radius: 4px; padding: 8px; max-height: 300px; overflow-y: auto; background: #fff;">
<el-tree
ref="createFieldsTree"
:data="fieldTreeData"
:key="form.datasource + '-' + String(form.orderType)"
:options="fieldOptionsDynamic"
:props="{ multiple: true, checkStrictly: false, expandTrigger: 'hover', checkOnClickNode: true, checkOnClickLeaf: true }"
:teleported="false"
collapse-tags
collapse-tags-tooltip
placeholder="按场景逐级选择,可多选"
@visible-change="onCascaderVisible('create', $event)"
@change="onFieldsSelChange('create')"
show-checkbox
node-key="value"
:default-expand-all="false"
:check-strictly="false"
:props="{ children: 'children', label: 'label' }"
@check="onTreeCheck('create', $event)"
style="background: transparent;"
/>
</div>
<div v-if="form.fieldsSel && form.fieldsSel.length > 0" style="margin-top: 8px; font-size: 12px; color: #909399;">
已选择 {{ form.fieldsSel.length }} 个字段
</div>
</el-form-item>
@ -190,21 +192,23 @@
</el-radio-group>
</el-form-item>
<el-form-item label="字段选择" required show-message prop="fieldsSel">
<div ref="editCascaderRoot">
<el-cascader
ref="editFieldsCascader"
v-model="edit.fieldsSel"
<div style="border: 1px solid #dcdfe6; border-radius: 4px; padding: 8px; max-height: 300px; overflow-y: auto; background: #fff;">
<el-tree
ref="editFieldsTree"
:data="editFieldTreeData"
:key="edit.datasource + '-' + String(edit.orderType)"
:options="editFieldOptionsDynamic"
:props="{ multiple: true, checkStrictly: false, expandTrigger: 'hover', checkOnClickNode: true, checkOnClickLeaf: true }"
:teleported="false"
collapse-tags
collapse-tags-tooltip
placeholder="按场景逐级选择,可多选"
@visible-change="onCascaderVisible('edit', $event)"
@change="onFieldsSelChange('edit')"
show-checkbox
node-key="value"
:default-expand-all="false"
:check-strictly="false"
:props="{ children: 'children', label: 'label' }"
@check="onTreeCheck('edit', $event)"
style="background: transparent;"
/>
</div>
<div v-if="edit.fieldsSel && edit.fieldsSel.length > 0" style="margin-top: 8px; font-size: 12px; color: #909399;">
已选择 {{ edit.fieldsSel.length }} 个字段
</div>
</el-form-item>
<el-row :gutter="8">
<el-col :span="12">

File diff suppressed because it is too large Load Diff