refactor(web): 重构前端资源引用和API请求路径
将CDN资源改为本地引用,并统一API请求基础路径 修复导出表单变量名冲突问题 添加错误处理逻辑增强稳定性
This commit is contained in:
parent
d0e1488815
commit
26e8685ac4
|
|
@ -0,0 +1,13 @@
|
||||||
|
PORT=8080
|
||||||
|
# Marketing MySQL
|
||||||
|
MARKETING_DB_HOST=127.0.0.1
|
||||||
|
MARKETING_DB_PORT=3306
|
||||||
|
MARKETING_DB_USER=root
|
||||||
|
MARKETING_DB_PASSWORD=
|
||||||
|
MARKETING_DB_NAME=market
|
||||||
|
# YMT MySQL
|
||||||
|
YMT_DB_HOST=127.0.0.1
|
||||||
|
YMT_DB_PORT=3306
|
||||||
|
YMT_DB_USER=root
|
||||||
|
YMT_DB_PASSWORD=
|
||||||
|
YMT_DB_NAME=market
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
PORT=8077
|
||||||
|
MARKETING_DB_HOST=192.168.6.92
|
||||||
|
MARKETING_DB_PORT=3306
|
||||||
|
MARKETING_DB_USER=root
|
||||||
|
MARKETING_DB_PASSWORD=lansexiongdi
|
||||||
|
MARKETING_DB_NAME=market
|
||||||
|
YMT_DB_HOST=47.97.27.195
|
||||||
|
YMT_DB_PORT=3306
|
||||||
|
YMT_DB_USER=root
|
||||||
|
YMT_DB_PASSWORD=lansexiongdi6,
|
||||||
|
YMT_DB_NAME=merketing
|
||||||
|
MARKETING_REDIS_HOST=192.168.6.75
|
||||||
|
MARKETING_REDIS_PORT=6379
|
||||||
|
MARKETING_REDIS_PASSWORD=lansexiongdi
|
||||||
|
MARKETING_REDIS_DB=0
|
||||||
|
|
@ -41,7 +41,7 @@ func main() {
|
||||||
log.Println("skip migrations: YMT DSN missing")
|
log.Println("skip migrations: YMT DSN missing")
|
||||||
}
|
}
|
||||||
r := api.NewRouter(ymt, marketing)
|
r := api.NewRouter(ymt, marketing)
|
||||||
addr := ":" + func() string { s := os.Getenv("PORT"); if s == "" { return "8080" }; return s }()
|
addr := ":" + func() string { s := os.Getenv("PORT"); if s == "" { return "8077" }; return s }()
|
||||||
srv := &http.Server{Addr: addr, Handler: r, ReadTimeout: 15 * time.Second, WriteTimeout: 60 * time.Second}
|
srv := &http.Server{Addr: addr, Handler: r, ReadTimeout: 15 * time.Second, WriteTimeout: 60 * time.Second}
|
||||||
log.Println("server listening on ", addr)
|
log.Println("server listening on ", addr)
|
||||||
log.Fatal(srv.ListenAndServe())
|
log.Fatal(srv.ListenAndServe())
|
||||||
|
|
|
||||||
BIN
server/server
BIN
server/server
Binary file not shown.
|
|
@ -4,8 +4,8 @@
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<title>MarketingSystemDataTool</title>
|
<title>MarketingSystemDataTool</title>
|
||||||
<link rel="stylesheet" href="https://unpkg.com/element-plus/dist/index.css">
|
<link rel="stylesheet" href="./vendor/element-plus.min.css">
|
||||||
<link rel="stylesheet" href="/styles.css">
|
<link rel="stylesheet" href="./styles.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="app">
|
<div id="app">
|
||||||
|
|
@ -143,26 +143,26 @@
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
<el-dialog v-model="exportVisible" title="执行导出" width="700px">
|
<el-dialog v-model="exportVisible" title="执行导出" width="700px">
|
||||||
<el-form :model="export" label-width="110px">
|
<el-form :model="exportForm" label-width="110px">
|
||||||
<el-form-item label="订单类型">
|
<el-form-item label="订单类型">
|
||||||
<el-radio-group v-model="export.orderType">
|
<el-radio-group v-model="exportForm.orderType">
|
||||||
<el-radio :label="1">直充卡密</el-radio>
|
<el-radio :label="1">直充卡密</el-radio>
|
||||||
<el-radio :label="2">立减金</el-radio>
|
<el-radio :label="2">立减金</el-radio>
|
||||||
<el-radio :label="3">红包</el-radio>
|
<el-radio :label="3">红包</el-radio>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="数据权限">
|
<el-form-item label="数据权限">
|
||||||
<el-select v-model="export.permissionMode" style="width:160px">
|
<el-select v-model="exportForm.permissionMode" style="width:160px">
|
||||||
<el-option label="所有" value="all" />
|
<el-option label="所有" value="all" />
|
||||||
<el-option label="按创建者" value="creator" />
|
<el-option label="按创建者" value="creator" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item v-if="export.permissionMode==='creator'" label="创建者列表"><el-input v-model="export.creatorRaw" placeholder="如:1,2,3" /></el-form-item>
|
<el-form-item v-if="exportForm.permissionMode==='creator'" label="创建者列表"><el-input v-model="exportForm.creatorRaw" placeholder="如:1,2,3" /></el-form-item>
|
||||||
<el-form-item label="时间范围">
|
<el-form-item label="时间范围">
|
||||||
<el-date-picker v-model="export.timeRange" type="datetimerange" range-separator="至" start-placeholder="开始" end-placeholder="结束" />
|
<el-date-picker v-model="exportForm.timeRange" type="datetimerange" range-separator="至" start-placeholder="开始" end-placeholder="结束" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="输出格式">
|
<el-form-item label="输出格式">
|
||||||
<el-select v-model="export.file_format" :teleported="false" placeholder="请选择" style="width:160px">
|
<el-select v-model="exportForm.file_format" :teleported="false" placeholder="请选择" style="width:160px">
|
||||||
<el-option v-for="opt in formatOptions" :key="opt.value" :label="opt.label" :value="opt.value" />
|
<el-option v-for="opt in formatOptions" :key="opt.value" :label="opt.label" :value="opt.value" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
@ -173,8 +173,8 @@
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
</div>
|
</div>
|
||||||
<script src="https://unpkg.com/vue@3/dist/vue.global.prod.js"></script>
|
<script src="./vendor/vue.global.prod.js"></script>
|
||||||
<script src="https://unpkg.com/element-plus/dist/index.full.min.js"></script>
|
<script src="./vendor/element-plus.full.min.js"></script>
|
||||||
<script src="/main.js"></script>
|
<script src="./main.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
60
web/main.js
60
web/main.js
|
|
@ -24,8 +24,9 @@ const app = createApp({
|
||||||
createWidth: (localStorage.getItem('tplDialogWidth') || '900px'),
|
createWidth: (localStorage.getItem('tplDialogWidth') || '900px'),
|
||||||
editWidth: (localStorage.getItem('tplEditDialogWidth') || '600px'),
|
editWidth: (localStorage.getItem('tplEditDialogWidth') || '600px'),
|
||||||
edit: { id: null, name: '', visibility: 'private', file_format: 'csv' },
|
edit: { id: null, name: '', visibility: 'private', file_format: 'csv' },
|
||||||
export: { tplId: null, orderType: 1, permissionMode: 'all', creatorRaw: '', timeRange: [], file_format: 'xlsx' }
|
exportForm: { tplId: null, orderType: 1, permissionMode: 'all', creatorRaw: '', timeRange: [], file_format: 'xlsx' }
|
||||||
})
|
})
|
||||||
|
const API_BASE = 'http://localhost:8077'
|
||||||
const FIELDS_MAP = {
|
const FIELDS_MAP = {
|
||||||
marketing: {
|
marketing: {
|
||||||
order: [
|
order: [
|
||||||
|
|
@ -207,8 +208,19 @@ const app = createApp({
|
||||||
return `${d.getFullYear()}-${pad(d.getMonth()+1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`;
|
return `${d.getFullYear()}-${pad(d.getMonth()+1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`;
|
||||||
}
|
}
|
||||||
const loadTemplates = async ()=>{
|
const loadTemplates = async ()=>{
|
||||||
const res = await fetch('/api/templates');
|
try{
|
||||||
state.templates = await res.json();
|
const res = await fetch(API_BASE + '/api/templates');
|
||||||
|
if(!res.ok){
|
||||||
|
msg('加载模板失败','error');
|
||||||
|
state.templates = []
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const data = await res.json();
|
||||||
|
state.templates = Array.isArray(data)?data:[]
|
||||||
|
}catch(e){
|
||||||
|
msg('加载模板异常','error');
|
||||||
|
state.templates = []
|
||||||
|
}
|
||||||
}
|
}
|
||||||
const createTemplate = async ()=>{
|
const createTemplate = async ()=>{
|
||||||
let fields = []
|
let fields = []
|
||||||
|
|
@ -233,26 +245,26 @@ const app = createApp({
|
||||||
owner_id: Number(state.form.owner_id),
|
owner_id: Number(state.form.owner_id),
|
||||||
visibility: state.form.visibility
|
visibility: state.form.visibility
|
||||||
}
|
}
|
||||||
const res = await fetch('/api/templates',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify(payload)});
|
const res = await fetch(API_BASE + '/api/templates',{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') }
|
if(res.ok){ msg('创建成功'); state.createVisible=false; loadTemplates() } else { msg(await res.text(),'error') }
|
||||||
}
|
}
|
||||||
const openExport = (row)=>{
|
const openExport = (row)=>{
|
||||||
state.export.tplId = row.id
|
state.exportForm.tplId = row.id
|
||||||
state.export.file_format = row.file_format || 'xlsx'
|
state.exportForm.file_format = row.file_format || 'xlsx'
|
||||||
state.exportVisible = true
|
state.exportVisible = true
|
||||||
}
|
}
|
||||||
const submitExport = async ()=>{
|
const submitExport = async ()=>{
|
||||||
const id = state.export.tplId
|
const id = state.exportForm.tplId
|
||||||
const filters = {}
|
const filters = {}
|
||||||
if(state.export.permissionMode==='creator' && state.export.creatorRaw){
|
if(state.exportForm.permissionMode==='creator' && state.exportForm.creatorRaw){
|
||||||
filters.creator_in = state.export.creatorRaw.split(',').map(s=>Number(s.trim())).filter(x=>!isNaN(x))
|
filters.creator_in = state.exportForm.creatorRaw.split(',').map(s=>Number(s.trim())).filter(x=>!isNaN(x))
|
||||||
}
|
}
|
||||||
if(state.export.orderType){ filters.type_eq = Number(state.export.orderType) }
|
if(state.exportForm.orderType){ filters.type_eq = Number(state.exportForm.orderType) }
|
||||||
if(state.export.timeRange && state.export.timeRange.length===2){
|
if(state.exportForm.timeRange && state.exportForm.timeRange.length===2){
|
||||||
filters.create_time_between = [fmtDT(new Date(state.export.timeRange[0])), fmtDT(new Date(state.export.timeRange[1]))]
|
filters.create_time_between = [fmtDT(new Date(state.exportForm.timeRange[0])), fmtDT(new Date(state.exportForm.timeRange[1]))]
|
||||||
}
|
}
|
||||||
const payload={template_id:Number(id),requested_by:1,permission:{},options:{},filters, file_format: state.export.file_format};
|
const payload={template_id:Number(id),requested_by:1,permission:{},options:{},filters, file_format: state.exportForm.file_format};
|
||||||
const r=await fetch('/api/exports',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify(payload)});
|
const r=await fetch(API_BASE + '/api/exports',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify(payload)});
|
||||||
const j=await r.json();
|
const j=await r.json();
|
||||||
state.exportVisible=false
|
state.exportVisible=false
|
||||||
loadJob(j.id);
|
loadJob(j.id);
|
||||||
|
|
@ -284,18 +296,28 @@ const app = createApp({
|
||||||
const saveEdit = async ()=>{
|
const saveEdit = async ()=>{
|
||||||
const id = state.edit.id
|
const id = state.edit.id
|
||||||
const payload = { name: state.edit.name, visibility: state.edit.visibility, file_format: state.edit.file_format }
|
const payload = { name: state.edit.name, visibility: state.edit.visibility, file_format: state.edit.file_format }
|
||||||
const res = await fetch('/api/templates/'+id,{method:'PATCH',headers:{'Content-Type':'application/json'},body:JSON.stringify(payload)})
|
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') }
|
if(res.ok){ msg('保存成功'); state.editVisible=false; loadTemplates() } else { msg(await res.text(),'error') }
|
||||||
}
|
}
|
||||||
const removeTemplate = async (id)=>{
|
const removeTemplate = async (id)=>{
|
||||||
const r = await fetch('/api/templates/'+id,{method:'DELETE'})
|
const r = await fetch(API_BASE + '/api/templates/'+id,{method:'DELETE'})
|
||||||
if(r.ok){ msg('删除成功'); loadTemplates() } else { msg(await r.text(),'error') }
|
if(r.ok){ msg('删除成功'); loadTemplates() } else { msg(await r.text(),'error') }
|
||||||
}
|
}
|
||||||
const loadJob = async (id)=>{
|
const loadJob = async (id)=>{
|
||||||
const res=await fetch('/api/exports/'+id);
|
try{
|
||||||
state.job = await res.json();
|
const res=await fetch(API_BASE + '/api/exports/'+id);
|
||||||
|
if(!res.ok){
|
||||||
|
msg('加载任务失败','error');
|
||||||
|
state.job = {}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
state.job = await res.json();
|
||||||
|
}catch(e){
|
||||||
|
msg('加载任务异常','error');
|
||||||
|
state.job = {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
const download = (id)=>{ window.open('/api/exports/'+id+'/download','_blank') }
|
const download = (id)=>{ window.open(API_BASE + '/api/exports/'+id+'/download','_blank') }
|
||||||
loadTemplates()
|
loadTemplates()
|
||||||
return { ...Vue.toRefs(state), visibilityOptions, formatOptions, fieldOptions, loadTemplates, createTemplate, openExport, submitExport, loadJob, download, openEdit, saveEdit, removeTemplate, resizeDialog }
|
return { ...Vue.toRefs(state), visibilityOptions, formatOptions, fieldOptions, loadTemplates, createTemplate, openExport, submitExport, loadJob, download, openEdit, saveEdit, removeTemplate, resizeDialog }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue