994 lines
48 KiB
JavaScript
994 lines
48 KiB
JavaScript
const { createApp, reactive } = Vue;
|
|
const app = createApp({
|
|
setup(){
|
|
const state = reactive({
|
|
templates: [],
|
|
jobs: [],
|
|
jobsVisible: false,
|
|
jobsTplId: null,
|
|
jobsPage: 1,
|
|
jobsPageSize: 10,
|
|
jobsTotal: 0,
|
|
sqlVisible: false,
|
|
sqlText: '',
|
|
job: {},
|
|
form: {
|
|
name: '',
|
|
datasource: 'marketing',
|
|
main_table: 'order',
|
|
orderType: 1,
|
|
fieldsRaw: 'order_number,creator,out_trade_no,type,status,contract_price,num,total,pay_amount,create_time',
|
|
fieldsSel: [],
|
|
creatorRaw: '',
|
|
permissionMode: 'all',
|
|
file_format: 'xlsx',
|
|
visibility: 'private',
|
|
|
|
},
|
|
createVisible: false,
|
|
editVisible: false,
|
|
exportVisible: false,
|
|
createWidth: (localStorage.getItem('tplDialogWidth') || '900px'),
|
|
editWidth: (localStorage.getItem('tplEditDialogWidth') || '900px'),
|
|
edit: { id: null, name: '', datasource: 'marketing', main_table: 'order', orderType: 1, fieldsSel: [], visibility: 'private', file_format: 'xlsx' },
|
|
exportForm: { tplId: null, datasource: 'marketing', file_format: 'xlsx', dateRange: [], creatorIds: [], creatorIdsRaw: '', resellerId: null, planId: null, keyBatchId: null, codeBatchId: null, productId: null, outTradeNo: '', account: '', cashActivityId: '', voucherChannelActivityId: '', voucherBatchChannelActivityId: '', outBizNo: '' },
|
|
exportTpl: { id: null, filters: {}, main_table: '', fields: [], datasource: '', file_format: '' }
|
|
})
|
|
|
|
const API_BASE = 'http://localhost:8077'
|
|
const getUserId = ()=>{
|
|
const sp = new URLSearchParams(window.location.search||'')
|
|
const v = sp.get('userId') || sp.get('userid') || sp.get('user_id')
|
|
return v && String(v).trim() ? String(v).trim() : ''
|
|
}
|
|
const qsUser = ()=>{
|
|
const uid = getUserId()
|
|
return uid ? ('?userId=' + encodeURIComponent(uid)) : ''
|
|
}
|
|
const hasUserId = Vue.computed(()=> !!getUserId())
|
|
const currentUserId = Vue.computed(()=>{ const v = getUserId(); return v? Number(v): null })
|
|
const FIELDS_MAP = {
|
|
marketing: {
|
|
order: [
|
|
{ value: 'order_number', label: '订单编号' },
|
|
{ value: 'key', label: 'KEY' },
|
|
{ value: 'creator', label: '创建者ID' },
|
|
{ value: 'out_trade_no', label: '支付流水号' },
|
|
{ value: 'type', label: '订单类型' },
|
|
{ value: 'status', label: '订单状态' },
|
|
{ value: 'account', label: '账号' },
|
|
{ value: 'product_id', label: '商品ID' },
|
|
{ value: 'reseller_id', label: '分销商ID' },
|
|
{ value: 'plan_id', label: '计划' },
|
|
{ value: 'key_batch_id', label: 'key批次' },
|
|
{ value: 'code_batch_id', label: '兑换批次ID' },
|
|
{ value: 'contract_price', label: '合同单价' },
|
|
{ value: 'num', label: '数量' },
|
|
{ value: 'total', label: '总金额' },
|
|
{ value: 'pay_amount', label: '支付金额' },
|
|
{ value: 'pay_type', label: '支付方式' },
|
|
{ value: 'pay_status', label: '支付状态' },
|
|
{ value: 'use_coupon', label: '是否使用优惠券' },
|
|
{ value: 'deliver_status', label: '投递状态' },
|
|
{ value: 'expire_time', label: '过期处理时间' },
|
|
{ value: 'recharge_time', label: '充值时间' },
|
|
{ value: 'create_time', label: '创建时间' },
|
|
{ value: 'update_time', label: '更新时间' }
|
|
]
|
|
,
|
|
order_detail: [
|
|
{ value: 'plan_title', label: '计划标题' },
|
|
{ value: 'reseller_name', label: '分销商名称' },
|
|
{ value: 'product_name', label: '商品名称' },
|
|
{ value: 'show_url', label: '商品图片URL' },
|
|
{ value: 'official_price', label: '官方价' },
|
|
{ value: 'cost_price', label: '成本价' },
|
|
{ value: 'create_time', label: '创建时间' },
|
|
{ value: 'update_time', label: '更新时间' }
|
|
],
|
|
order_cash: [
|
|
{ value: 'channel', label: '渠道' },
|
|
{ value: 'activity_id', label: '红包批次号' },
|
|
{ value: 'receive_status', label: '领取状态' },
|
|
{ value: 'receive_time', label: '拆红包时间' },
|
|
{ value: 'cash_packet_id', label: '红包ID' },
|
|
{ value: 'cash_id', label: '红包规则ID' },
|
|
{ value: 'amount', label: '红包额度' },
|
|
{ value: 'status', label: '状态' },
|
|
{ value: 'expire_time', label: '过期时间' },
|
|
{ value: 'update_time', label: '更新时间' }
|
|
],
|
|
order_voucher: [
|
|
{ value: 'channel', label: '渠道' },
|
|
{ value: 'channel_batch_no', label: '渠道立减金批次' },
|
|
{ value: 'channel_voucher_id', label: '渠道立减金ID' },
|
|
{ value: 'status', label: '状态' },
|
|
{ value: 'receive_mode', label: '领取方式' },
|
|
{ value: 'grant_time', label: '领取时间' },
|
|
{ value: 'usage_time', label: '核销时间' },
|
|
{ value: 'refund_time', label: '退款时间' },
|
|
{ value: 'status_modify_time', label: '状态更新时间' },
|
|
{ value: 'overdue_time', label: '过期时间' },
|
|
{ value: 'refund_amount', label: '退款金额' },
|
|
{ value: 'official_price', label: '官方价' },
|
|
{ value: 'out_biz_no', label: '外部业务号' },
|
|
{ value: 'account_no', label: '账户号' }
|
|
],
|
|
plan: [
|
|
{ value: 'id', label: '计划ID' },
|
|
{ value: 'title', label: '计划标题' },
|
|
{ value: 'status', label: '状态' },
|
|
{ value: 'begin_time', label: '开始时间' },
|
|
{ value: 'end_time', label: '结束时间' }
|
|
],
|
|
key_batch: [
|
|
{ value: 'id', label: '批次ID' },
|
|
{ value: 'batch_name', label: '批次名称' },
|
|
{ value: 'bind_object', label: '绑定对象' },
|
|
{ value: 'quantity', label: '发放数量' },
|
|
{ value: 'stock', label: '剩余库存' },
|
|
{ value: 'begin_time', label: '开始时间' },
|
|
{ value: 'end_time', label: '结束时间' }
|
|
],
|
|
code_batch: [
|
|
{ value: 'id', label: '兑换批次ID' },
|
|
{ value: 'title', label: '标题' },
|
|
{ value: 'status', label: '状态' },
|
|
{ value: 'begin_time', label: '开始时间' },
|
|
{ value: 'end_time', label: '结束时间' },
|
|
{ value: 'quantity', label: '数量' },
|
|
{ value: 'usage', label: '使用数' },
|
|
{ value: 'stock', label: '库存' }
|
|
],
|
|
voucher: [
|
|
{ value: 'channel', label: '渠道' },
|
|
{ value: 'channel_activity_id', label: '渠道批次号' },
|
|
{ value: 'price', label: '合同单价' },
|
|
{ value: 'balance', label: '剩余额度' },
|
|
{ value: 'used_amount', label: '已用额度' },
|
|
{ value: 'denomination', label: '面额' }
|
|
],
|
|
voucher_batch: [
|
|
{ value: 'channel_activity_id', label: '渠道批次号' },
|
|
{ value: 'temp_no', label: '模板编号' },
|
|
{ value: 'provider', label: '服务商' },
|
|
{ value: 'weight', label: '权重' }
|
|
],
|
|
merchant_key_send: [
|
|
{ value: 'merchant_id', label: '商户ID' },
|
|
{ value: 'out_biz_no', label: '商户业务号' },
|
|
{ value: 'key', label: '券码' },
|
|
{ value: 'status', label: '状态' },
|
|
{ value: 'usage_time', label: '核销时间' },
|
|
{ value: 'create_time', label: '创建时间' }
|
|
]
|
|
},
|
|
ymt: {
|
|
order: [
|
|
{ value: 'order_number', label: '订单编号' },
|
|
{ value: 'key', label: 'KEY' },
|
|
{ value: 'creator', label: '创建者ID' },
|
|
{ value: 'out_trade_no', label: '支付流水号' },
|
|
{ value: 'type', label: '订单类型' },
|
|
{ value: 'status', label: '订单状态' },
|
|
{ value: 'product_id', label: '商品ID' },
|
|
{ value: 'reseller_id', label: '分销商ID' },
|
|
{ value: 'plan_id', label: '活动ID' },
|
|
{ value: 'key_batch_id', label: 'key批次' },
|
|
{ value: 'contract_price', label: '合同单价' },
|
|
{ value: 'num', label: '数量' },
|
|
{ value: 'pay_amount', label: '支付金额' },
|
|
{ value: 'pay_status', label: '支付状态' },
|
|
{ value: 'create_time', label: '创建时间' },
|
|
{ value: 'update_time', label: '更新时间' },
|
|
{ value: 'official_price', label: '官方价' },
|
|
{ value: 'merchant_name', label: '分销商名称' },
|
|
{ value: 'activity_name', label: '活动名称' },
|
|
{ value: 'goods_name', label: '商品名称' },
|
|
{ value: 'pay_time', label: '支付时间' },
|
|
{ value: 'coupon_id', label: '优惠券ID' },
|
|
{ value: 'discount_amount', label: '优惠金额' },
|
|
{ value: 'supplier_product_name', label: '供应商产品名称' },
|
|
{ value: 'is_inner', label: '内部供应商订单' },
|
|
{ value: 'icon', label: '订单图片' },
|
|
{ value: 'cost_price', label: '成本价' },
|
|
{ value: 'success_num', label: '到账数量' },
|
|
{ value: 'is_reset', label: '是否重置' },
|
|
{ value: 'is_retry', label: '是否重试' },
|
|
{ value: 'channel', label: '支付渠道' },
|
|
{ value: 'is_store', label: '是否退还库存' },
|
|
{ value: 'trace_id', label: 'TraceID' },
|
|
{ value: 'out_order_no', label: '外部订单号' },
|
|
{ value: 'next_retry_time', label: '下次重试时间' },
|
|
{ value: 'recharge_suc_time', label: '充值成功时间' },
|
|
{ value: 'supplier_id', label: '供应商ID' },
|
|
{ value: 'supplier_product_id', label: '供应商产品ID' },
|
|
{ value: 'merchant_id', label: '分销商ID(冗余)' },
|
|
{ value: 'goods_id', label: '商品ID(冗余)' },
|
|
{ value: 'activity_id', label: '活动ID(冗余)' },
|
|
{ value: 'key_batch_name', label: 'key批次名称' }
|
|
],
|
|
order_cash: [
|
|
{ value: 'order_no', label: '订单号' },
|
|
{ value: 'trade_no', label: '交易号' },
|
|
{ value: 'wechat_detail_id', label: '微信明细单号' },
|
|
{ value: 'channel', label: '渠道' },
|
|
{ value: 'denomination', label: '红包面额' },
|
|
{ value: 'account', label: '领取账号' },
|
|
{ value: 'receive_name', label: '真实姓名' },
|
|
{ value: 'app_id', label: '转账AppID' },
|
|
{ value: 'receive_status', label: '领取状态' },
|
|
{ value: 'merchant_id', label: '分销商ID' },
|
|
{ value: 'supplier_id', label: '供应商ID' },
|
|
{ value: 'activity_id', label: '活动ID' },
|
|
{ value: 'goods_id', label: '商品ID' },
|
|
{ value: 'user_id', label: '创建者ID' },
|
|
{ value: 'receive_time', label: '领取时间' },
|
|
{ value: 'success_time', label: '成功时间' },
|
|
{ value: 'expire_time', label: '过期时间' },
|
|
{ value: 'create_time', label: '创建时间' },
|
|
{ value: 'update_time', label: '更新时间' },
|
|
{ value: 'version', label: '版本' },
|
|
{ value: 'is_confirm', label: '是否确认' }
|
|
],
|
|
order_voucher: [
|
|
{ value: 'channel', label: '渠道' },
|
|
{ value: 'channel_activity_id', label: '渠道立减金批次' },
|
|
{ value: 'channel_voucher_id', label: '渠道立减金ID' },
|
|
{ value: 'status', label: '状态' },
|
|
{ value: 'receive_mode', label: '领取方式' },
|
|
{ value: 'grant_time', label: '领取时间' },
|
|
{ value: 'usage_time', label: '核销时间' },
|
|
{ value: 'refund_time', label: '退款时间' },
|
|
{ value: 'status_modify_time', label: '状态更新时间' },
|
|
{ value: 'overdue_time', label: '过期时间' },
|
|
{ value: 'refund_amount', label: '退款金额' },
|
|
{ value: 'official_price', label: '官方价' },
|
|
{ value: 'out_biz_no', label: '外部业务号' },
|
|
{ value: 'account_no', label: '账户号' }
|
|
]
|
|
}
|
|
}
|
|
// 扩展易码通数据源的关联表字段
|
|
FIELDS_MAP.ymt.order_digit = [
|
|
{ value: 'order_no', label: '订单号' },
|
|
{ value: 'card_no', label: '卡号' },
|
|
{ value: 'account', label: '充值账号' },
|
|
{ value: 'goods_id', label: '商品ID' },
|
|
{ value: 'merchant_id', label: '分销商ID' },
|
|
{ value: 'supplier_id', label: '供应商ID' },
|
|
{ value: 'activity_id', label: '活动ID' },
|
|
{ value: 'user_id', label: '创建者ID' },
|
|
{ value: 'success_time', label: '到账时间' },
|
|
{ value: 'supplier_product_no', label: '供应商产品编码' },
|
|
{ value: 'order_type', label: '订单类型' },
|
|
{ value: 'end_time', label: '卡密有效期' },
|
|
{ value: 'create_time', label: '创建时间' },
|
|
{ value: 'update_time', label: '更新时间' },
|
|
{ value: 'code', label: '验证码' },
|
|
{ value: 'sms_channel', label: '短信渠道' }
|
|
]
|
|
FIELDS_MAP.ymt.goods_voucher_batch = [
|
|
{ value: 'channel_batch_no', label: '渠道批次号' },
|
|
{ value: 'voucher_subject_id', label: '主体配置ID' },
|
|
{ value: 'id', label: 'ID' },
|
|
{ value: 'goods_voucher_id', label: '立减金ID' },
|
|
{ value: 'supplier_id', label: '供应商ID' },
|
|
{ value: 'temp_no', label: '模板编号' },
|
|
{ value: 'index', label: '权重' },
|
|
{ value: 'create_time', label: '创建时间' },
|
|
{ value: 'update_time', label: '更新时间' }
|
|
]
|
|
FIELDS_MAP.ymt.goods_voucher_subject_config = [
|
|
{ value: 'id', label: '主体配置ID' },
|
|
{ value: 'name', label: '主体名称' },
|
|
{ value: 'type', label: '主体类型' },
|
|
{ value: 'create_time', label: '创建时间' }
|
|
]
|
|
FIELDS_MAP.ymt.merchant = [
|
|
{ value: 'id', label: '客户ID' },
|
|
{ value: 'user_id', label: '用户中心ID' },
|
|
{ value: 'merchant_no', label: '商户编码' },
|
|
{ value: 'name', label: '客户名称' },
|
|
{ value: 'subject', label: '客户主体' },
|
|
{ value: 'third_party', label: '来源类型' },
|
|
{ value: 'status', label: '状态' },
|
|
{ value: 'balance', label: '客户余额' },
|
|
{ value: 'total_consumption', label: '累计消费' },
|
|
{ value: 'contact_name', label: '联系人名称' },
|
|
{ value: 'contact_phone', label: '联系人电话' },
|
|
{ value: 'contact_email', label: '联系人Email' },
|
|
{ value: 'create_time', label: '创建时间' },
|
|
{ value: 'update_time', label: '编辑时间' }
|
|
]
|
|
FIELDS_MAP.ymt.activity = [
|
|
{ value: 'id', label: '活动ID' },
|
|
{ value: 'user_id', label: '创建者ID' },
|
|
{ value: 'merchant_id', label: '客户ID' },
|
|
{ value: 'user_name', label: '创建者名称' },
|
|
{ value: 'name', label: '活动名称' },
|
|
{ value: 'activity_no', label: '活动编号' },
|
|
{ value: 'status', label: '状态' },
|
|
{ value: 'key_total_num', label: 'Key码总量' },
|
|
{ value: 'key_generate_num', label: 'Key码已生成数量' },
|
|
{ value: 'key_usable_num', label: 'Key可使用次数' },
|
|
{ value: 'domain_url', label: '域名' },
|
|
{ value: 'theme_login_id', label: '登录模版ID' },
|
|
{ value: 'theme_list_id', label: '列表模版ID' },
|
|
{ value: 'theme_verify_id', label: '验证模版ID' },
|
|
{ value: 'settlement_type', label: '结算方式' },
|
|
{ value: 'key_expire_type', label: 'Key有效期类型' },
|
|
{ value: 'key_valid_day', label: '有效天数' },
|
|
{ value: 'key_begin_time', label: 'Key有效开始时间' },
|
|
{ value: 'key_end_time', label: 'Key有效结束时间' },
|
|
{ value: 'key_style', label: 'Key样式' },
|
|
{ value: 'begin_time', label: '开始时间' },
|
|
{ value: 'end_time', label: '结束时间' },
|
|
{ value: 'is_retry', label: '是否自动重试' },
|
|
{ value: 'create_time', label: '创建时间' },
|
|
{ value: 'update_time', label: '修改时间' },
|
|
{ value: 'discard_time', label: '作废时间' },
|
|
{ value: 'delete_time', label: '删除时间' },
|
|
{ value: 'auto_charge', label: '是否充值到账' },
|
|
{ value: 'stock', label: '已使用库存' },
|
|
{ value: 'approval_trade_no', label: '审批交易号' },
|
|
{ value: 'amount', label: '支付金额' },
|
|
{ value: 'channels', label: '支付渠道' },
|
|
{ value: 'key_begin', label: '开始月份' },
|
|
{ value: 'key_end', label: '截止月份' },
|
|
{ value: 'key_unit', label: '时间单位' },
|
|
{ value: 'key_pay_button_text', label: 'Key支付按钮文本' },
|
|
{ value: 'goods_pay_button_text', label: '商品支付按钮文本' },
|
|
{ value: 'is_open_db_transaction', label: '是否开启事务' },
|
|
{ value: 'bank_tag', label: '银行标识' }
|
|
]
|
|
const TABLE_LABELS = {
|
|
order: '订单主表',
|
|
order_detail: '订单详情',
|
|
order_cash: '红包订单',
|
|
order_voucher: '立减金订单',
|
|
plan: '活动计划',
|
|
key_batch: 'key批次',
|
|
code_batch: '兑换码批次',
|
|
voucher: '立减金',
|
|
voucher_batch: '立减金批次',
|
|
merchant_key_send: '开放平台发放记录',
|
|
order_digit: '直充卡密订单',
|
|
merchant: '客户',
|
|
activity: '活动',
|
|
goods_voucher_batch: '立减金批次表',
|
|
goods_voucher_subject_config: '立减金主体配置'
|
|
}
|
|
const fieldOptions = Vue.computed(()=>{
|
|
const ds = state.form.datasource
|
|
const FM = FIELDS_MAP[ds] || {}
|
|
const node = (table, children=[])=>({ value: table, label: TABLE_LABELS[table]||table, children })
|
|
const fieldsNode = (table)=> (FM[table]||[])
|
|
const type = Number(state.form.orderType || 0)
|
|
if(ds === 'ymt'){
|
|
const orderChildrenBase = []
|
|
orderChildrenBase.push(...fieldsNode('order'))
|
|
const orderChildrenFor = (t)=>{
|
|
const ch = [...orderChildrenBase]
|
|
ch.push(node('merchant', fieldsNode('merchant')))
|
|
ch.push(node('activity', fieldsNode('activity')))
|
|
if(t===2){
|
|
ch.push(node('order_voucher', fieldsNode('order_voucher')))
|
|
ch.push(node('goods_voucher_batch', fieldsNode('goods_voucher_batch')))
|
|
ch.push(node('goods_voucher_subject_config', fieldsNode('goods_voucher_subject_config')))
|
|
} else if(t===3){
|
|
ch.push(node('order_cash', fieldsNode('order_cash')))
|
|
} else if(t===1){
|
|
ch.push(node('order_digit', fieldsNode('order_digit')))
|
|
} else if(!t){
|
|
ch.push(node('order_voucher', fieldsNode('order_voucher')))
|
|
ch.push(node('order_cash', fieldsNode('order_cash')))
|
|
ch.push(node('order_digit', fieldsNode('order_digit')))
|
|
ch.push(node('goods_voucher_batch', fieldsNode('goods_voucher_batch')))
|
|
ch.push(node('goods_voucher_subject_config', fieldsNode('goods_voucher_subject_config')))
|
|
}
|
|
return ch
|
|
}
|
|
const orderNode = node('order', orderChildrenFor(type))
|
|
if(type){ return [ orderNode ] }
|
|
return [ { value: 'scene_order', label: '订单数据', children: [ orderNode ] } ]
|
|
}
|
|
const orderChildrenBase = []
|
|
orderChildrenBase.push(...fieldsNode('order'))
|
|
orderChildrenBase.push(node('order_detail', fieldsNode('order_detail')))
|
|
const planChildren = []
|
|
planChildren.push(...fieldsNode('plan'))
|
|
planChildren.push(node('key_batch', [
|
|
...fieldsNode('key_batch'),
|
|
node('code_batch', fieldsNode('code_batch'))
|
|
]))
|
|
const voucherChildren = []
|
|
voucherChildren.push(...fieldsNode('order_voucher'))
|
|
voucherChildren.push(node('voucher', [
|
|
...fieldsNode('voucher'),
|
|
node('voucher_batch', fieldsNode('voucher_batch'))
|
|
]))
|
|
const orderChildrenFor = (t)=>{
|
|
const ch = [...orderChildrenBase]
|
|
if(t===1){
|
|
ch.push(node('plan', planChildren))
|
|
ch.push(node('merchant_key_send', fieldsNode('merchant_key_send')))
|
|
} else if(t===2){
|
|
ch.push(node('order_voucher', voucherChildren))
|
|
ch.push(node('plan', planChildren))
|
|
} else if(t===3){
|
|
ch.push(node('order_cash', fieldsNode('order_cash')))
|
|
ch.push(node('plan', planChildren))
|
|
} else {
|
|
ch.push(node('order_cash', fieldsNode('order_cash')))
|
|
ch.push(node('order_voucher', voucherChildren))
|
|
ch.push(node('plan', planChildren))
|
|
ch.push(node('merchant_key_send', fieldsNode('merchant_key_send')))
|
|
}
|
|
return ch
|
|
}
|
|
const orderNode = node('order', orderChildrenFor(type))
|
|
if(type){ return [ orderNode ] }
|
|
return [ { value: 'scene_order', label: '订单数据', children: [ orderNode ] } ]
|
|
})
|
|
const sceneOptions = Vue.computed(()=>{
|
|
const ds = state.form.datasource
|
|
return [{ label: '订单数据', value: ds==='ymt' ? 'order_info' : 'order' }]
|
|
})
|
|
const editSceneOptions = Vue.computed(()=>{
|
|
const ds = state.edit.datasource
|
|
return [{ label: '订单数据', value: ds==='ymt' ? 'order_info' : 'order' }]
|
|
})
|
|
const DEFAULT_FIELDS = {
|
|
marketing: 'order_number,creator,out_trade_no,type,status,contract_price,num,total,pay_amount,create_time',
|
|
ymt: 'order_number,creator,out_trade_no,type,status,contract_price,num,pay_amount,create_time'
|
|
}
|
|
Vue.watch(()=>state.form.datasource, (ds)=>{
|
|
state.form.fieldsSel = []
|
|
state.form.fieldsRaw = DEFAULT_FIELDS[ds] || ''
|
|
state.form.main_table = (ds==='ymt' ? 'order_info' : 'order')
|
|
state.form.orderType = 1
|
|
})
|
|
Vue.watch(()=>state.form.orderType, ()=>{
|
|
state.form.fieldsSel = []
|
|
})
|
|
Vue.watch(()=>state.edit.datasource, (ds)=>{
|
|
state.edit.fieldsSel = []
|
|
state.edit.main_table = (ds==='ymt' ? 'order_info' : 'order')
|
|
})
|
|
Vue.watch(()=>state.edit.orderType, ()=>{
|
|
state.edit.fieldsSel = []
|
|
})
|
|
const orderLeafPaths = (ds)=>{
|
|
const FM = FIELDS_MAP[ds] || {}
|
|
const arr = (FM.order || []).map(f=>['order', f.value])
|
|
return arr
|
|
}
|
|
|
|
const hasOrderPath = (arr)=> Array.isArray(arr) && arr.some(p=>Array.isArray(p) && p.length===1 && p[0]==='order')
|
|
const tableKeys = (ds)=> Object.keys(FIELDS_MAP[ds] || {})
|
|
const isGroupPath = (ds, path)=> Array.isArray(path) && path.length>=1 && tableKeys(ds).includes(path[path.length-1])
|
|
|
|
const msg = (t, type='success')=>ElementPlus.ElMessage({message:t,type});
|
|
const createFormRef = Vue.ref(null)
|
|
const exportFormRef = Vue.ref(null)
|
|
const editFormRef = Vue.ref(null)
|
|
const fieldsCascader = Vue.ref(null)
|
|
const editFieldsCascader = Vue.ref(null)
|
|
const createCascaderRoot = Vue.ref(null)
|
|
const editCascaderRoot = Vue.ref(null)
|
|
const cascaderScroll = { create: [], edit: [] }
|
|
const getWraps = (kind)=>{
|
|
const r = kind==='create' ? createCascaderRoot.value : editCascaderRoot.value
|
|
const el = r && r.$el ? r.$el : r
|
|
if(!el || typeof el.querySelectorAll !== 'function') return []
|
|
return Array.from(el.querySelectorAll('.el-cascader__panel .el-scrollbar__wrap'))
|
|
}
|
|
const onCascaderVisible = (kind, v)=>{
|
|
if(!v) return
|
|
Vue.nextTick(()=>{
|
|
const wraps = getWraps(kind)
|
|
cascaderScroll[kind] = wraps.map(w=>w.scrollTop)
|
|
wraps.forEach((wrap, idx)=>{
|
|
wrap.addEventListener('scroll', (e)=>{ cascaderScroll[kind][idx] = e.target.scrollTop }, { passive: true })
|
|
})
|
|
const r = kind==='create' ? createCascaderRoot.value : editCascaderRoot.value
|
|
const el = r && r.$el ? r.$el : r
|
|
if(el && typeof el.querySelectorAll === 'function'){
|
|
el.querySelectorAll('.el-cascader-node').forEach(node=>{
|
|
node.addEventListener('click', ()=>{
|
|
const ws = getWraps(kind)
|
|
cascaderScroll[kind] = ws.map(w=>w.scrollTop)
|
|
}, { passive: true })
|
|
})
|
|
}
|
|
})
|
|
}
|
|
const onFieldsSelChange = (kind)=>{
|
|
const tops = cascaderScroll[kind] || []
|
|
Vue.nextTick(()=>{
|
|
const wraps = getWraps(kind)
|
|
wraps.forEach((w, idx)=>{ w.scrollTop = tops[idx] || 0 })
|
|
})
|
|
}
|
|
const createRules = {
|
|
name: [{ required: true, message: '请输入模板名称', trigger: 'blur' }],
|
|
datasource: [{ required: true, message: '请选择数据源', trigger: 'change' }],
|
|
main_table: [{ required: true, message: '请选择导出场景', trigger: 'change' }],
|
|
orderType: [{ required: true, message: '请选择订单类型', trigger: 'change' }],
|
|
fieldsSel: [{ validator: (_rule, val, cb)=>{ if(Array.isArray(val) && val.length>0){ cb() } else { cb(new Error('请至少选择一个字段')) } }, trigger: 'change' }],
|
|
file_format: [{ required: true, message: '请选择输出格式', trigger: 'change' }],
|
|
visibility: [{ required: true, message: '请选择可见性', trigger: 'change' }]
|
|
}
|
|
const editRules = {
|
|
name: [{ required: true, message: '请输入模板名称', trigger: 'blur' }],
|
|
orderType: [{ required: true, message: '请选择订单类型', trigger: 'change' }],
|
|
fieldsSel: [{ validator: (_rule, val, cb)=>{ if(Array.isArray(val) && val.length>0){ cb() } else { cb(new Error('请至少选择一个字段')) } }, trigger: 'change' }]
|
|
}
|
|
const exportRules = {
|
|
tplId: [{ required: true, message: '请选择模板', trigger: 'change' }],
|
|
dateRange: [{ validator: (_r, v, cb)=>{ if(Array.isArray(v) && v.length===2){ cb() } else { cb(new Error('请选择时间范围')) } }, trigger: 'change' }]
|
|
}
|
|
const editFieldOptions = Vue.computed(()=>{
|
|
const ds = state.edit.datasource
|
|
const FM = FIELDS_MAP[ds] || {}
|
|
const node = (table, children=[])=>({ value: table, label: TABLE_LABELS[table]||table, children })
|
|
const fieldsNode = (table)=> (FM[table]||[])
|
|
const type = Number(state.edit.orderType || 0)
|
|
if(ds === 'ymt'){
|
|
const orderChildrenBase = []
|
|
orderChildrenBase.push(...fieldsNode('order'))
|
|
const orderChildrenFor = (t)=>{
|
|
const ch = [...orderChildrenBase]
|
|
ch.push(node('merchant', fieldsNode('merchant')))
|
|
ch.push(node('activity', fieldsNode('activity')))
|
|
if(t===2){
|
|
ch.push(node('order_voucher', fieldsNode('order_voucher')))
|
|
ch.push(node('goods_voucher_batch', fieldsNode('goods_voucher_batch')))
|
|
ch.push(node('goods_voucher_subject_config', fieldsNode('goods_voucher_subject_config')))
|
|
} else if(t===3){
|
|
ch.push(node('order_cash', fieldsNode('order_cash')))
|
|
} else if(t===1){
|
|
ch.push(node('order_digit', fieldsNode('order_digit')))
|
|
} else if(!t){
|
|
ch.push(node('order_voucher', fieldsNode('order_voucher')))
|
|
ch.push(node('order_cash', fieldsNode('order_cash')))
|
|
ch.push(node('order_digit', fieldsNode('order_digit')))
|
|
ch.push(node('goods_voucher_batch', fieldsNode('goods_voucher_batch')))
|
|
ch.push(node('goods_voucher_subject_config', fieldsNode('goods_voucher_subject_config')))
|
|
}
|
|
return ch
|
|
}
|
|
const orderNode = node('order', orderChildrenFor(type))
|
|
return [ orderNode ]
|
|
}
|
|
const orderChildrenBase = []
|
|
orderChildrenBase.push(...fieldsNode('order'))
|
|
orderChildrenBase.push(node('order_detail', fieldsNode('order_detail')))
|
|
const planChildren = []
|
|
planChildren.push(...fieldsNode('plan'))
|
|
planChildren.push(node('key_batch', [
|
|
...fieldsNode('key_batch'),
|
|
node('code_batch', fieldsNode('code_batch'))
|
|
]))
|
|
const voucherChildren = []
|
|
voucherChildren.push(...fieldsNode('order_voucher'))
|
|
voucherChildren.push(node('voucher', [
|
|
...fieldsNode('voucher'),
|
|
node('voucher_batch', fieldsNode('voucher_batch'))
|
|
]))
|
|
const orderChildrenFor = (t)=>{
|
|
const ch = [...orderChildrenBase]
|
|
if(t===1){
|
|
ch.push(node('plan', planChildren))
|
|
ch.push(node('merchant_key_send', fieldsNode('merchant_key_send')))
|
|
} else if(t===2){
|
|
ch.push(node('order_voucher', voucherChildren))
|
|
ch.push(node('plan', planChildren))
|
|
} else if(t===3){
|
|
ch.push(node('order_cash', fieldsNode('order_cash')))
|
|
ch.push(node('plan', planChildren))
|
|
} else {
|
|
ch.push(node('order_cash', fieldsNode('order_cash')))
|
|
ch.push(node('order_voucher', voucherChildren))
|
|
ch.push(node('plan', planChildren))
|
|
ch.push(node('merchant_key_send', fieldsNode('merchant_key_send')))
|
|
}
|
|
return ch
|
|
}
|
|
const orderNode = node('order', orderChildrenFor(type))
|
|
return [ orderNode ]
|
|
})
|
|
const visibilityOptions = [
|
|
{ label: '个人', value: 'private' },
|
|
{ label: '公共', value: 'public' }
|
|
]
|
|
const formatOptions = [
|
|
{ label: 'XLSX', value: 'xlsx' },
|
|
{ label: 'CSV', value: 'csv' }
|
|
]
|
|
const datasourceOptions = [
|
|
{ label: '营销系统', value: 'marketing' },
|
|
{ label: '易码通', value: 'ymt' }
|
|
]
|
|
const dsLabel = (v)=>{
|
|
if(v==='marketing') return '营销系统'
|
|
if(v==='ymt') return '易码通'
|
|
return v || ''
|
|
}
|
|
const creatorOptions = Vue.ref([])
|
|
const resellerOptions = Vue.ref([])
|
|
const planOptions = Vue.ref([])
|
|
const hasCreators = Vue.computed(()=> Array.isArray(state.exportForm.creatorIds) && state.exportForm.creatorIds.length>0 )
|
|
const hasReseller = Vue.computed(()=> !!state.exportForm.resellerId)
|
|
const hasPlan = Vue.computed(()=> !!state.exportForm.planId)
|
|
const hasKeyBatch = Vue.computed(()=> !!state.exportForm.keyBatchId)
|
|
const hasCodeBatch = Vue.computed(()=> !!state.exportForm.codeBatchId)
|
|
const loadCreators = async ()=>{
|
|
try{
|
|
const res = await fetch(API_BASE + '/api/creators')
|
|
const data = await res.json()
|
|
const arr = Array.isArray(data?.data) ? data.data : (Array.isArray(data) ? data : [])
|
|
creatorOptions.value = arr.map(it=>({label: it.name || String(it.id), value: Number(it.id)}))
|
|
}catch(_e){ creatorOptions.value = [] }
|
|
}
|
|
const loadResellers = async ()=>{
|
|
const ids = Array.isArray(state.exportForm.creatorIds) ? state.exportForm.creatorIds : []
|
|
if(!ids.length){ resellerOptions.value = []; return }
|
|
try{
|
|
const res = await fetch(API_BASE + '/api/resellers?creator=' + ids.join(','))
|
|
const data = await res.json()
|
|
const arr = Array.isArray(data?.data) ? data.data : (Array.isArray(data) ? data : [])
|
|
resellerOptions.value = arr.map(it=>({label: (it.name||'') + (it.name?'':'') , value: Number(it.id)}))
|
|
}catch(_e){ resellerOptions.value = [] }
|
|
}
|
|
const loadPlans = async ()=>{
|
|
const rid = state.exportForm.resellerId
|
|
if(!rid){ planOptions.value = []; return }
|
|
try{
|
|
const qs = new URLSearchParams()
|
|
qs.set('reseller', String(rid))
|
|
const res = await fetch(API_BASE + '/api/plans?' + qs.toString())
|
|
const data = await res.json()
|
|
const arr = Array.isArray(data?.data) ? data.data : (Array.isArray(data) ? data : [])
|
|
planOptions.value = arr.map(it=>({ label: `${it.id} - ${it.title||''}`, value: Number(it.id) }))
|
|
}catch(_e){ planOptions.value = [] }
|
|
}
|
|
const exportType = Vue.computed(()=>{
|
|
const f = state.exportTpl && state.exportTpl.filters
|
|
if(!f) return null
|
|
if(f.type_eq != null) return Number(f.type_eq)
|
|
if(Array.isArray(f.type_in) && f.type_in.length===1) return Number(f.type_in[0])
|
|
return null
|
|
})
|
|
const exportTypeList = Vue.computed(()=>{
|
|
const f = state.exportTpl && state.exportTpl.filters
|
|
if(!f) return []
|
|
if(Array.isArray(f.type_in) && f.type_in.length) return f.type_in.map(n=>Number(n))
|
|
if(f.type_eq != null) return [Number(f.type_eq)]
|
|
return []
|
|
})
|
|
const isOrder = Vue.computed(()=>{
|
|
return (state.exportTpl && state.exportTpl.main_table) === 'order'
|
|
})
|
|
const orderTypeLabel = (n)=>{
|
|
if(n===1) return '直充卡密'
|
|
if(n===2) return '立减金'
|
|
if(n===3) return '红包'
|
|
return ''
|
|
}
|
|
const sceneLabel = (s)=>{
|
|
if(s==='order') return '订单'
|
|
return s || ''
|
|
}
|
|
const exportTitle = Vue.computed(()=>{
|
|
let base = '执行导出'
|
|
const mt = state.exportTpl && state.exportTpl.main_table
|
|
if(mt){
|
|
base += ' - ' + sceneLabel(mt)
|
|
if(mt==='order'){
|
|
const list = exportTypeList.value
|
|
const labels = list.map(orderTypeLabel).filter(Boolean)
|
|
if(labels.length){
|
|
base += ' - 订单类型:' + labels.join('、')
|
|
}
|
|
}
|
|
}
|
|
return base
|
|
})
|
|
const fmtDT = (d)=>{
|
|
const pad=(n)=>String(n).padStart(2,'0');
|
|
return `${d.getFullYear()}-${pad(d.getMonth()+1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`;
|
|
}
|
|
const yearRange = ()=>{
|
|
const now = new Date()
|
|
const start = new Date(now.getFullYear(), 0, 1, 0, 0, 0)
|
|
const end = new Date(now.getFullYear(), 11, 31, 23, 59, 59)
|
|
return [ fmtDT(start), fmtDT(end) ]
|
|
}
|
|
const loadTemplates = async ()=>{
|
|
try{
|
|
const res = await fetch(API_BASE + '/api/templates' + qsUser());
|
|
if(!res.ok){
|
|
msg('加载模板失败','error');
|
|
state.templates = []
|
|
return
|
|
}
|
|
const data = await res.json();
|
|
const arr = Array.isArray(data?.data) ? data.data : (Array.isArray(data) ? data : [])
|
|
state.templates = arr
|
|
}catch(e){
|
|
msg('加载模板异常','error');
|
|
state.templates = []
|
|
}
|
|
}
|
|
const loadJobs = async (page)=>{
|
|
if(!page) page = state.jobsPage
|
|
try{
|
|
const qs = new URLSearchParams()
|
|
qs.set('page', String(page))
|
|
qs.set('page_size', String(state.jobsPageSize))
|
|
if(state.jobsTplId){ qs.set('template_id', String(state.jobsTplId)) }
|
|
const res = await fetch(API_BASE + '/api/exports?' + qs.toString() + (qsUser()?('&'+qsUser().slice(1)):'') );
|
|
if(!res.ok){ state.jobs = []; return }
|
|
const data = await res.json();
|
|
const payload = data?.data || data || {}
|
|
const arr = Array.isArray(payload.items) ? payload.items : (Array.isArray(payload) ? payload : [])
|
|
state.jobs = arr
|
|
state.jobsTotal = Number(payload.total || 0)
|
|
state.jobsPage = Number(payload.page || page)
|
|
}catch(_e){ state.jobs = [] }
|
|
}
|
|
let jobsPollTimer = null
|
|
const startJobsPolling = ()=>{
|
|
if(jobsPollTimer) return
|
|
jobsPollTimer = setInterval(()=>{ if(state.jobsVisible){ loadJobs(state.jobsPage) } }, 1000)
|
|
}
|
|
const stopJobsPolling = ()=>{ if(jobsPollTimer){ clearInterval(jobsPollTimer); jobsPollTimer=null } }
|
|
const openJobs = (row)=>{ state.jobsTplId = row.id; state.jobsVisible = true; loadJobs(1); startJobsPolling() }
|
|
const closeJobs = ()=>{ state.jobsVisible = false; stopJobsPolling() }
|
|
const jobPercent = (row)=>{
|
|
const est = Number(row.row_estimate || 0)
|
|
const done = Number(row.total_rows || 0)
|
|
if(row.status==='completed') return '100%'
|
|
if(row.status==='failed') return '失败'
|
|
if(row.status==='canceled') return '已取消'
|
|
if(row.status==='queued') return '0%'
|
|
if(row.status==='running'){
|
|
if(est>0){ const p = Math.max(0, Math.min(100, Math.floor(done*100/est))); return p + '%' }
|
|
return '0%'
|
|
}
|
|
if(est>0){ const p = Math.max(0, Math.min(100, Math.floor(done*100/est))); return p + '%' }
|
|
return '评估中'
|
|
}
|
|
const createTemplate = async ()=>{
|
|
const formRef = createFormRef.value
|
|
const ok = formRef ? await formRef.validate().catch(()=>false) : true
|
|
if(!ok){ msg('请完善必填项','error'); return }
|
|
let fields = []
|
|
if(state.form.fieldsSel && state.form.fieldsSel.length){
|
|
const ds = state.form.datasource
|
|
const hasOrderOnly = state.form.fieldsSel.some(p=>Array.isArray(p) && p.length===1 && p[0]==='order')
|
|
if(hasOrderOnly){
|
|
fields = orderLeafPaths(ds).map(p=>`${p[0]}.${p[1]}`)
|
|
} else {
|
|
fields = state.form.fieldsSel.flatMap(path=>{
|
|
if(!Array.isArray(path)) return []
|
|
if(isGroupPath(ds, path)) return []
|
|
if(path.length>=2){
|
|
const t = path[path.length-2]
|
|
const f = path[path.length-1]
|
|
return [`${t}.${f}`]
|
|
}
|
|
return []
|
|
})
|
|
}
|
|
} else {
|
|
fields = state.form.fieldsRaw.split(',').map(s=>s.trim()).filter(Boolean)
|
|
}
|
|
const payload = {
|
|
name: state.form.name,
|
|
datasource: state.form.datasource,
|
|
main_table: (state.form.datasource==='ymt' ? 'order_info' : 'order'),
|
|
fields,
|
|
filters: { type_eq: Number(state.form.orderType) },
|
|
file_format: state.form.file_format,
|
|
visibility: state.form.visibility,
|
|
owner_id: (getUserId()? Number(getUserId()) : (state.form.visibility==='public'? 0 : 0))
|
|
}
|
|
const res = await fetch(API_BASE + '/api/templates' + qsUser(),{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify(payload)});
|
|
if(res.ok){ msg('创建成功'); state.createVisible=false; loadTemplates() } else { msg(await res.text(),'error') }
|
|
}
|
|
const openExport = async (row)=>{
|
|
state.exportForm.tplId = row.id
|
|
await loadTemplateDetail(row.id)
|
|
state.exportForm.datasource = state.exportTpl.datasource || row.datasource || 'marketing'
|
|
state.exportForm.file_format = state.exportTpl.file_format || row.file_format || 'xlsx'
|
|
if(state.exportForm.datasource==='marketing'){ loadCreators() }
|
|
const uid = getUserId()
|
|
if(uid){ state.exportForm.creatorIds = [ Number(uid) ] }
|
|
if(!Array.isArray(state.exportForm.dateRange) || state.exportForm.dateRange.length!==2){ state.exportForm.dateRange = yearRange() }
|
|
state.exportVisible = true
|
|
}
|
|
const loadTemplateDetail = async (id)=>{
|
|
try{
|
|
const res = await fetch(API_BASE + '/api/templates/'+id)
|
|
if(!res.ok){ msg('加载模板详情失败','error'); state.exportTpl = { id: null, filters: {}, main_table: '', fields: [], datasource: '', file_format: '' }; return }
|
|
const data = await res.json()
|
|
const tpl = data?.data || {}
|
|
state.exportTpl = tpl
|
|
}catch(e){ msg('加载模板详情异常','error'); state.exportTpl = { id: null, filters: {}, main_table: '', fields: [], datasource: '', file_format: '' } }
|
|
}
|
|
const submitExport = async ()=>{
|
|
const formRef = exportFormRef.value
|
|
const ok = formRef ? await formRef.validate().catch(()=>false) : true
|
|
if(!ok){ msg('请完善必填项','error'); return }
|
|
const id = state.exportForm.tplId
|
|
const filters = {}
|
|
const tVal = exportType.value
|
|
if(tVal != null){ filters.type_eq = Number(tVal) }
|
|
if(Array.isArray(state.exportForm.dateRange) && state.exportForm.dateRange.length===2){ filters.create_time_between = [ state.exportForm.dateRange[0], state.exportForm.dateRange[1] ] }
|
|
|
|
if(state.exportForm.planId){ filters.plan_id_eq = Number(state.exportForm.planId) }
|
|
|
|
if(state.exportForm.resellerId){ filters.reseller_id_eq = Number(state.exportForm.resellerId) }
|
|
|
|
if(state.exportForm.cashActivityId){ filters.order_cash_cash_activity_id_eq = state.exportForm.cashActivityId }
|
|
if(state.exportForm.voucherChannelActivityId){ filters.order_voucher_channel_activity_id_eq = state.exportForm.voucherChannelActivityId }
|
|
if(state.exportForm.voucherBatchChannelActivityId){ filters.voucher_batch_channel_activity_id_eq = state.exportForm.voucherBatchChannelActivityId }
|
|
|
|
if(Array.isArray(state.exportForm.creatorIds) && state.exportForm.creatorIds.length){ filters.creator_in = state.exportForm.creatorIds.map(Number) }
|
|
else if(state.exportForm.creatorIdsRaw){ const arr = String(state.exportForm.creatorIdsRaw).split(',').map(s=>s.trim()).filter(Boolean); if(arr.length){ filters.creator_in = arr } }
|
|
|
|
const payload={template_id:Number(id),requested_by:1,permission:{},options:{},filters, file_format: state.exportForm.file_format, datasource: state.exportForm.datasource};
|
|
const r=await fetch(API_BASE + '/api/exports' + qsUser(),{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify(payload)});
|
|
const j=await r.json();
|
|
const jid = j?.data?.id ?? j?.id
|
|
state.exportVisible=false
|
|
if(jid){
|
|
state.jobsTplId = Number(id)
|
|
state.jobsVisible = true
|
|
loadJobs(1)
|
|
startJobsPolling()
|
|
} else { msg('任务创建返回异常','error') }
|
|
}
|
|
Vue.watch(()=>state.exportForm.creatorIds, ()=>{ state.exportForm.resellerId=null; state.exportForm.planId=null; state.exportForm.keyBatchId=null; state.exportForm.codeBatchId=null; state.exportForm.productId=null; loadResellers() })
|
|
Vue.watch(()=>state.exportForm.resellerId, ()=>{ state.exportForm.planId=null; state.exportForm.keyBatchId=null; state.exportForm.codeBatchId=null; state.exportForm.productId=null; loadPlans() })
|
|
Vue.watch(()=>state.exportForm.planId, ()=>{ state.exportForm.keyBatchId=null; state.exportForm.codeBatchId=null; state.exportForm.productId=null })
|
|
Vue.watch(()=>state.exportForm.keyBatchId, ()=>{ state.exportForm.codeBatchId=null; state.exportForm.productId=null })
|
|
Vue.watch(()=>state.exportForm.codeBatchId, ()=>{ state.exportForm.productId=null })
|
|
const clampWidth = (w)=>{
|
|
const n = Math.max(500, Math.min(1400, w))
|
|
return n + 'px'
|
|
}
|
|
const resizeDialog = (kind, delta)=>{
|
|
if(kind==='create'){
|
|
const cur = parseInt(String(state.createWidth).replace('px','')||'900',10)
|
|
const next = clampWidth(cur + delta)
|
|
state.createWidth = next
|
|
localStorage.setItem('tplDialogWidth', next)
|
|
} else if(kind==='edit'){
|
|
const cur = parseInt(String(state.editWidth).replace('px','')||'600',10)
|
|
const next = clampWidth(cur + delta)
|
|
state.editWidth = next
|
|
localStorage.setItem('tplEditDialogWidth', next)
|
|
}
|
|
}
|
|
const openEdit = async (row)=>{
|
|
state.edit.id = row.id
|
|
// 加载模板详情以便回填字段
|
|
try{
|
|
const res = await fetch(API_BASE + '/api/templates/'+row.id)
|
|
const data = await res.json()
|
|
const tpl = data?.data || {}
|
|
state.edit.name = tpl.name || row.name || ''
|
|
state.edit.datasource = tpl.datasource || row.datasource || 'marketing'
|
|
state.edit.main_table = tpl.main_table || row.main_table || 'order'
|
|
state.edit.file_format = tpl.file_format || row.file_format || 'xlsx'
|
|
state.edit.visibility = tpl.visibility || row.visibility || 'private'
|
|
const filters = tpl.filters || {}
|
|
if(filters && (filters.type_eq != null)){
|
|
state.edit.orderType = Number(filters.type_eq)
|
|
} else if(Array.isArray(filters?.type_in) && filters.type_in.length===1){
|
|
state.edit.orderType = Number(filters.type_in[0])
|
|
} else {
|
|
state.edit.orderType = 1
|
|
}
|
|
const fields = Array.isArray(tpl.fields) ? tpl.fields : []
|
|
const toPath = (tf)=>{
|
|
const parts = String(tf||'').split('.')
|
|
if(parts.length!==2) return null
|
|
const table = parts[0]
|
|
const field = parts[1]
|
|
if(table==='order') return ['order', field]
|
|
if(table==='order_detail') return ['order','order_detail',field]
|
|
if(table==='plan') return ['order','plan',field]
|
|
if(table==='key_batch') return ['order','plan','key_batch',field]
|
|
if(table==='code_batch') return ['order','plan','key_batch','code_batch',field]
|
|
if(table==='order_voucher') return ['order','order_voucher',field]
|
|
if(table==='voucher') return ['order','order_voucher','voucher',field]
|
|
if(table==='voucher_batch') return ['order','order_voucher','voucher','voucher_batch',field]
|
|
if(table==='merchant_key_send') return ['order','merchant_key_send',field]
|
|
if(table==='order_cash') return ['order','order_cash',field]
|
|
return null
|
|
}
|
|
state.edit.fieldsSel = fields.map(toPath).filter(p=>Array.isArray(p) && p.length>=2)
|
|
}catch(_e){
|
|
state.edit.name = row.name
|
|
state.edit.datasource = row.datasource || 'marketing'
|
|
state.edit.main_table = row.main_table || 'order'
|
|
state.edit.file_format = row.file_format || 'xlsx'
|
|
state.edit.visibility = row.visibility || 'private'
|
|
state.edit.orderType = 1
|
|
state.edit.fieldsSel = []
|
|
}
|
|
state.editVisible = true
|
|
}
|
|
const saveEdit = async ()=>{
|
|
const formRef = editFormRef.value
|
|
const ok = formRef ? await formRef.validate().catch(()=>false) : true
|
|
if(!ok){ msg('请完善必填项','error'); return }
|
|
const id = state.edit.id
|
|
// 构建字段与过滤
|
|
let fields = []
|
|
const ds = state.edit.datasource
|
|
if(state.edit.fieldsSel && state.edit.fieldsSel.length){
|
|
const hasOrderOnly = state.edit.fieldsSel.some(p=>Array.isArray(p) && p.length===1 && p[0]==='order')
|
|
if(hasOrderOnly){
|
|
fields = orderLeafPaths(ds).map(p=>`${p[0]}.${p[1]}`)
|
|
} else {
|
|
fields = state.edit.fieldsSel.flatMap(path=>{
|
|
if(!Array.isArray(path)) return []
|
|
if(isGroupPath(ds, path)) return []
|
|
if(path.length>=2){
|
|
const t = path[path.length-2]
|
|
const f = path[path.length-1]
|
|
return [`${t}.${f}`]
|
|
}
|
|
return []
|
|
})
|
|
}
|
|
}
|
|
const filters = { type_eq: Number(state.edit.orderType || 1) }
|
|
const payload = { name: state.edit.name, visibility: state.edit.visibility, file_format: state.edit.file_format, fields, filters, main_table: (state.edit.datasource==='ymt' ? 'order_info' : 'order') }
|
|
const res = await fetch(API_BASE + '/api/templates/'+id,{method:'PATCH',headers:{'Content-Type':'application/json'},body:JSON.stringify(payload)})
|
|
if(res.ok){ msg('保存成功'); state.editVisible=false; loadTemplates() } else { msg(await res.text(),'error') }
|
|
}
|
|
const removeTemplate = async (id)=>{
|
|
const r = await fetch(API_BASE + '/api/templates/'+id,{method:'DELETE'})
|
|
if(r.ok){ msg('删除成功'); loadTemplates() } else { msg(await r.text(),'error') }
|
|
}
|
|
const loadJob = async (id)=>{
|
|
try{
|
|
const res=await fetch(API_BASE + '/api/exports/'+id);
|
|
if(!res.ok){
|
|
msg('加载任务失败','error');
|
|
state.job = {}
|
|
return
|
|
}
|
|
const data = await res.json();
|
|
state.job = data?.data || {}
|
|
}catch(e){
|
|
msg('加载任务异常','error');
|
|
state.job = {}
|
|
}
|
|
}
|
|
const download = (id)=>{ window.open(API_BASE + '/api/exports/'+id+'/download','_blank') }
|
|
const openSQL = async (id)=>{
|
|
try{
|
|
const res = await fetch(API_BASE + '/api/exports/'+id+'/sql')
|
|
const data = await res.json()
|
|
const s = data?.data?.final_sql || data?.final_sql || data?.data?.sql || data?.sql || ''
|
|
state.sqlText = s
|
|
state.sqlVisible = true
|
|
}catch(_e){ state.sqlText=''; state.sqlVisible=false; msg('加载SQL失败','error') }
|
|
}
|
|
loadTemplates()
|
|
|
|
return { ...Vue.toRefs(state), visibilityOptions, formatOptions, datasourceOptions, fieldOptions, editFieldOptions, sceneOptions, editSceneOptions, loadTemplates, createTemplate, openExport, submitExport, loadJob, loadJobs, openJobs, closeJobs, download, openSQL, openEdit, saveEdit, removeTemplate, resizeDialog, createRules, exportRules, editRules, createFormRef, exportFormRef, editFormRef, dsLabel, exportType, isOrder, exportTitle, creatorOptions, resellerOptions, planOptions, hasCreators, hasReseller, hasPlan, hasKeyBatch, hasCodeBatch, jobPercent, fmtDT, fieldsCascader, editFieldsCascader, createCascaderRoot, editCascaderRoot, onCascaderVisible, onFieldsSelChange, hasUserId, currentUserId }
|
|
}
|
|
})
|
|
app.use(ElementPlus)
|
|
app.mount('#app')
|
|
|