Commit e4e06e22 authored by 李苏's avatar 李苏 💬

ERP

parent 7113755c
...@@ -56,6 +56,11 @@ export const constantRoutes = [ ...@@ -56,6 +56,11 @@ export const constantRoutes = [
component: () => import('@/views/register'), component: () => import('@/views/register'),
hidden: true hidden: true
}, },
{
path: '/getfs',
component: () => import('@/views/tool/getfs'),
hidden: true
},
{ {
path: '/404', path: '/404',
component: () => import('@/views/error/404'), component: () => import('@/views/error/404'),
......
...@@ -184,7 +184,10 @@ const permission = { ...@@ -184,7 +184,10 @@ const permission = {
} else if (homePage[0].erpComponent) { } else if (homePage[0].erpComponent) {
homePage[0].component = loadErpView(homePage[0].component) homePage[0].component = loadErpView(homePage[0].component)
} else { } else if (homePage[0].iotComponent) {
homePage[0].component = loadIotView(homePage[0].component)
}
else {
homePage[0].component = loadView(homePage[0].component) homePage[0].component = loadView(homePage[0].component)
} }
......
<template> <template>
<div class="app-container home"> <div class="app-container home">
<!-- <AuxMulSelect :options='options' v-model="test" /> -->
<el-skeleton animated style="width: 100%"> <el-skeleton animated style="width: 100%">
<template slot="template"> <template slot="template">
...@@ -19,53 +19,21 @@ ...@@ -19,53 +19,21 @@
export default { export default {
name: "Index", name: "Index",
mounted() { mounted() {
/* 递归设置*/
function dgCrateRoutes(arr,pid){
let oldarr = JSON.parse(JSON.stringify(arr))
let outarr = []
oldarr.forEach((e,index)=>{
if(e.fmkid==pid){
let routes=routing(e.mkid)
let news={...e,...routes}
outarr.push(news)
e.children=dgCrateRoutes(oldarr,e.mkid)
}
})
return outarr
}
function routing(mkid){
let componentInfo={}
if(mkid=="101001300"){
componentInfo={
component: "system/user/index",
hidden:false,
mata:{
"title": "用户管理",
"icon": "user",
"noCache": false,
"link": null
},
name:'User',
path:"user"
}
}else if(mkid=='101000000'){
componentInfo={
component: "Layout",
alwaysShow: true,
hidden: false,
name: "System",
path: "/system",
redirect: "noRedirect"
}
}
return componentInfo
}
console.log('系统管理',dgCrateRoutes(menus,0))
}, },
data() { data() {
return { return {
test:'1,2',
options:[
{
id:1,
name:'1n'
},
{
id:2,
name:'2n'
}
],
// 版本号 // 版本号
version: "3.8.3", version: "3.8.3",
}; };
......
<template>
<div class="config-generator">
<!-- 顶部导航栏 -->
<div class="header">
<h1>CRUD 配置生成工具</h1>
<p class="header-desc">可视化配置表格标题、查询参数与编辑表单,支持全部类型快速示例</p>
</div>
<!-- 1. 表格标题配置区 -->
<div class="config-section">
<div class="config-card">
<div class="config-card-header">
<div class="config-card-icon">
<i class="el-icon-table"></i>
</div>
<h2 class="config-card-title">表格标题配置 (tableTitle)</h2>
<p class="config-card-desc">配置列表页表格的列信息</p>
</div>
<div class="config-content">
<!-- 左侧规则说明 -->
<div class="config-left">
<div class="rule-section">
<h3>配置规则</h3>
<ul class="rule-list">
<li><strong>title</strong>:表格列显示的中文名称(必填)</li>
<li><strong>field</strong>:对应后端返回的字段名(必填)</li>
<li><strong>fieldType</strong>:字段格式化类型(可选,如upper/tybz/ftDate/ftDateTime等)</li>
<li><strong>width</strong>:列宽度(可选,数字类型)</li>
<li><strong>url</strong>:字段格式化的数据源URL(可选,用于下拉字典映射)</li>
</ul>
</div>
<div class="example-section">
<h3>完整示例</h3>
<pre class="example-code"><code>{{ tableTitleExample }}</code></pre>
</div>
</div>
<!-- 右侧代码预览 -->
<div class="config-right">
<div class="preview-header">
<h3>tableTitle 代码</h3>
<el-button @click="copyTableTitleCode" type="primary" size="mini" class="copy-btn">
<i class="el-icon-document-copy"></i> 复制
</el-button>
</div>
<div class="code-container">
<pre><code class="language-javascript">{{ tableTitleCode }}</code></pre>
</div>
</div>
</div>
</div>
</div>
<!-- 2. 查询参数配置区 -->
<div class="config-section">
<div class="config-card">
<div class="config-card-header">
<div class="config-card-icon">
<i class="el-icon-search"></i>
</div>
<h2 class="config-card-title">查询参数配置 (queryParams)</h2>
<p class="config-card-desc">配置列表页的搜索条件字段(一行span总和=24)</p>
</div>
<div class="config-content">
<!-- 左侧配置区 -->
<div class="config-left">
<el-button type="primary" @click="addQueryRow" class="add-btn">
<i class="el-icon-plus"></i> 添加查询行
</el-button>
<!-- 全部类型示例(分两行展示) -->
<div class="example-types">
<h3>快速添加示例 <span class="tip-text">(点击添加对应类型)</span></h3>
<el-row :gutter="12" class="example-row first-row">
<el-col :span="4">
<el-button @click="addExample('input')" type="text" class="example-btn">输入框</el-button>
</el-col>
<el-col :span="4">
<el-button @click="addExample('RelSelect')" type="text" class="example-btn">单选下拉</el-button>
</el-col>
<el-col :span="4">
<el-button @click="addExample('RelMulSelect')" type="text" class="example-btn">多选下拉</el-button>
</el-col>
<el-col :span="4">
<el-button @click="addExample('date')" type="text" class="example-btn">日期选择</el-button>
</el-col>
<el-col :span="4">
<el-button @click="addExample('datetime')" type="text" class="example-btn">日期时间选择</el-button>
</el-col>
<el-col :span="4">
<el-button @click="addExample('year')" type="text" class="example-btn">年度选择</el-button>
</el-col>
</el-row>
<el-row :gutter="12" class="example-row">
<el-col :span="4">
<el-button @click="addExample('month')" type="text" class="example-btn">月份选择</el-button>
</el-col>
<el-col :span="6">
<el-button @click="addExample('RelDaterangeV2')" type="text" class="example-btn">日期范围选择</el-button>
</el-col>
<el-col :span="6">
<el-button @click="addExample('RelDatetimerangeV2')" type="text" class="example-btn">日期时间范围选择</el-button>
</el-col>
<el-col :span="4">
<el-button @click="addExample('AuxInput')" type="text" class="example-btn">辅助输入</el-button>
</el-col>
</el-row>
</div>
<!-- 配置表单 -->
<div v-for="(row, rowIndex) in queryRows" :key="rowIndex" class="query-row">
<div class="row-header">
<span class="row-number">查询行 {{ rowIndex + 1 }}</span>
<el-button
@click="removeQueryRow(rowIndex)"
size="mini"
type="text"
class="remove-btn"
:disabled="queryRows.length <= 1"
>
<i class="el-icon-delete"></i> 删除行
</el-button>
</div>
<div v-for="(item, itemIndex) in row" :key="itemIndex" class="field-item">
<div class="field-item-header">
<span class="field-number">字段 {{ itemIndex + 1 }}</span>
<el-button
@click="removeQueryItem(rowIndex, itemIndex)"
size="mini"
type="text"
class="remove-btn"
:disabled="row.length <= 1"
>
<i class="el-icon-circle-close"></i> 删除
</el-button>
</div>
<el-form :model="item" label-width="120px" size="small" class="field-form">
<el-row :gutter="15">
<el-col :span="12">
<el-form-item label="字段标签">
<el-input v-model="item.label" @input="updateQueryCode" placeholder="请输入显示名称"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="字段属性名">
<el-input v-model="item.prop" @input="updateQueryCode" placeholder="请输入后端参数名"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="栅格宽度">
<el-input-number
v-model="item.span"
:min="1"
:max="24"
@change="updateQueryCode"
placeholder="24为满宽"
></el-input-number>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="字段类型">
<el-select v-model="item.type" @change="handleQueryTypeChange(rowIndex, itemIndex)" clearable>
<el-option label="输入框" value="input"></el-option>
<el-option label="单选下拉" value="RelSelect"></el-option>
<el-option label="多选下拉" value="RelMulSelect"></el-option>
<el-option label="日期" value="date"></el-option>
<el-option label="日期时间" value="datetime"></el-option>
<el-option label="日期范围" value="RelDaterangeV2"></el-option>
<el-option label="日期时间范围" value="RelDatetimerangeV2"></el-option>
<el-option label="年度" value="year"></el-option>
<el-option label="月份" value="month"></el-option>
<el-option label="辅助输入" value="AuxInput"></el-option>
</el-select>
</el-form-item>
</el-col>
<!-- 类型专属配置 -->
<template v-if="item.type === 'RelSelect' || item.type === 'RelMulSelect'">
<el-col :span="24">
<el-form-item label="数据源URL">
<el-input v-model="item.typeConfig.src" @input="updateQueryCode" placeholder="如: jcsj/common/kjdw"></el-input>
</el-form-item>
</el-col>
</template>
<template v-if="item.type === 'RelDaterangeV2' || item.type === 'RelDatetimerangeV2'">
<el-col :span="12">
<el-form-item label="开始字段名">
<el-input v-model="item.startProp" @input="updateQueryCode" placeholder="如: ywrqb"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="结束字段名">
<el-input v-model="item.endProp" @input="updateQueryCode" placeholder="如: ywrqe"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="开始值(JS表达式)">
<el-input v-model="item.startValueExpr" @input="updateQueryCode" placeholder="如: new Date().getTime() - 1000*60*60*24*30"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="结束值(JS表达式)">
<el-input v-model="item.endValueExpr" @input="updateQueryCode" placeholder="如: new Date().getTime()"></el-input>
</el-form-item>
</el-col>
</template>
<template v-if="item.type === 'AuxInput'">
<el-col :span="12">
<el-form-item label="编码">
<el-input v-model="item.typeConfig.code" @input="updateQueryCode" placeholder="后端识别编码(如true/CUSTOM)"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="显示字段">
<el-input v-model="item.typeConfig.label" @input="updateQueryCode" placeholder="如: name"></el-input>
</el-form-item>
</el-col>
</template>
<!-- 普通字段配置(含动态JS表达式) -->
<template v-if="!['RelDaterangeV2', 'RelDatetimerangeV2'].includes(item.type)">
<el-col :span="12">
<el-form-item label="是否必填">
<el-switch v-model="item.required" @change="updateQueryCode" active-color="#1890ff"></el-switch>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="默认值(JS表达式)">
<el-input v-model="item.valueExpr" @input="updateQueryCode" placeholder="如: new Date().getFullYear()"></el-input>
</el-form-item>
</el-col>
</template>
</el-row>
</el-form>
</div>
<el-button
@click="addQueryItem(rowIndex)"
size="mini"
type="primary"
plain
class="add-field-btn"
>
<i class="el-icon-plus"></i> 添加字段
</el-button>
</div>
</div>
<!-- 右侧代码预览 -->
<div class="config-right">
<div class="preview-header">
<h3>queryParams 代码</h3>
<el-button @click="copyQueryCode" type="primary" size="mini" class="copy-btn">
<i class="el-icon-document-copy"></i> 复制
</el-button>
</div>
<div class="code-container">
<pre><code class="language-javascript">{{ queryParamsCode }}</code></pre>
</div>
</div>
</div>
</div>
</div>
<!-- 3. 编辑表单配置区 -->
<div class="config-section">
<div class="config-card">
<div class="config-card-header">
<div class="config-card-icon">
<i class="el-icon-edit"></i>
</div>
<h2 class="config-card-title">编辑表单配置 (editColItemList)</h2>
<p class="config-card-desc">配置新增/编辑页的表单字段(一行span总和=24)</p>
</div>
<div class="config-content">
<!-- 左侧配置区 -->
<div class="config-left">
<el-button type="primary" @click="addEditItem" class="add-btn">
<i class="el-icon-plus"></i> 添加表单字段
</el-button>
<!-- 全部类型示例(分两行展示) -->
<div class="example-types">
<h3>快速添加示例 <span class="tip-text">(点击添加对应类型)</span></h3>
<el-row :gutter="12" class="example-row first-row">
<el-col :span="4">
<el-button @click="addEditExample('input')" type="text" class="example-btn">输入框</el-button>
</el-col>
<el-col :span="4">
<el-button @click="addEditExample('inputNumber')" type="text" class="example-btn">数字输入</el-button>
</el-col>
<el-col :span="4">
<el-button @click="addEditExample('inputInt')" type="text" class="example-btn">整数输入</el-button>
</el-col>
<el-col :span="4">
<el-button @click="addEditExample('textarea')" type="text" class="example-btn">文本域</el-button>
</el-col>
<el-col :span="4">
<el-button @click="addEditExample('RelSelect')" type="text" class="example-btn">单选下拉</el-button>
</el-col>
<el-col :span="4">
<el-button @click="addEditExample('RelMulSelect')" type="text" class="example-btn">多选下拉</el-button>
</el-col>
</el-row>
<el-row :gutter="12" class="example-row">
<el-col :span="4">
<el-button @click="addEditExample('checkbox')" type="text" class="example-btn">复选框</el-button>
</el-col>
<el-col :span="4">
<el-button @click="addEditExample('date')" type="text" class="example-btn">日期选择</el-button>
</el-col>
<el-col :span="4">
<el-button @click="addEditExample('datetime')" type="text" class="example-btn">日期时间选择</el-button>
</el-col>
<el-col :span="4">
<el-button @click="addEditExample('year')" type="text" class="example-btn">年度选择</el-button>
</el-col>
<el-col :span="4">
<el-button @click="addEditExample('AuxInput')" type="text" class="example-btn">辅助输入</el-button>
</el-col>
</el-row>
</div>
<!-- 配置表单 -->
<div v-for="(item, index) in editItems" :key="index" class="field-item">
<div class="field-item-header">
<span class="field-number">表单字段 {{ index + 1 }}</span>
<el-button
@click="removeEditItem(index)"
size="mini"
type="text"
class="remove-btn"
:disabled="editItems.length <= 1"
>
<i class="el-icon-circle-close"></i> 删除
</el-button>
</div>
<el-form :model="item" label-width="120px" size="small" class="field-form">
<el-row :gutter="15">
<el-col :span="12">
<el-form-item label="字段标签">
<el-input v-model="item.label" @input="updateEditCode" placeholder="请输入显示名称"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="字段属性名">
<el-input v-model="item.prop" @input="updateEditCode" placeholder="请输入后端参数名"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="栅格宽度">
<el-input-number
v-model="item.span"
:min="1"
:max="24"
@change="updateEditCode"
placeholder="24为满宽"
></el-input-number>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="字段类型">
<el-select v-model="item.type" @change="handleEditTypeChange(index)" clearable>
<el-option label="输入框" value="input"></el-option>
<el-option label="数字输入" value="inputNumber"></el-option>
<el-option label="整数输入" value="inputInt"></el-option>
<el-option label="文本域" value="textarea"></el-option>
<el-option label="单选下拉" value="RelSelect"></el-option>
<el-option label="多选下拉" value="RelMulSelect"></el-option>
<el-option label="复选框" value="checkbox"></el-option>
<el-option label="日期" value="date"></el-option>
<el-option label="日期时间" value="datetime"></el-option>
<el-option label="年度" value="year"></el-option>
<el-option label="辅助输入" value="AuxInput"></el-option>
</el-select>
</el-form-item>
</el-col>
<!-- 类型专属配置 -->
<template v-if="item.type === 'RelSelect' || item.type === 'RelMulSelect'">
<el-col :span="24">
<el-form-item label="数据源URL">
<el-input v-model="item.typeConfig.src" @input="updateEditCode" placeholder="如: jcsj/jldw/query"></el-input>
</el-form-item>
</el-col>
</template>
<template v-if="item.type === 'AuxInput'">
<el-col :span="12">
<el-form-item label="编码">
<el-input v-model="item.typeConfig.code" @input="updateEditCode" placeholder="后端识别编码(如CUSTOM)"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="显示字段">
<el-input v-model="item.typeConfig.label" @input="updateEditCode" placeholder="如: name"></el-input>
</el-form-item>
</el-col>
</template>
<el-col :span="8">
<el-form-item label="是否必填">
<el-switch v-model="item.required" @change="updateEditCode" active-color="#1890ff"></el-switch>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="是否只读">
<el-switch v-model="item.readonly" @change="updateEditCode" active-color="#1890ff"></el-switch>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="默认值(JS表达式)">
<el-input v-model="item.valueExpr" @input="updateEditCode" placeholder="如: new Date().getTime()"></el-input>
</el-form-item>
</el-col>
</el-row>
</el-form>
</div>
</div>
<!-- 右侧代码预览 -->
<div class="config-right">
<div class="preview-header">
<h3>editColItemList 代码</h3>
<el-button @click="copyEditCode" type="primary" size="mini" class="copy-btn">
<i class="el-icon-document-copy"></i> 复制
</el-button>
</div>
<div class="code-container">
<pre><code class="language-javascript">{{ editColItemListCode }}</code></pre>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'ConfigGenerator',
data() {
return {
// 表格标题配置(固定示例)
tableTitleExample: `[
{
title: "编码",
field: "code",
fieldType: "upper", // 大写格式化
width: 140,
url: "jcsj/gysfl/init/zt" // 字典映射URL
},
{
title: "名称",
field: "name",
width: 140
},
{
title: "停用",
field: "tybz",
fieldType: "tybz" // 停用标识格式化
},
{
title: "停用日期",
field: "tyrq",
fieldType: "ftDate" // 日期格式化
},
{
title: "维护人",
field: "whr"
},
{
title: "维护时间",
field: "whsj",
fieldType: "ftDateTime" // 日期时间格式化
}
]`,
tableTitleCode: `tableTitle: [
{
title: "编码",
field: "code",
fieldType: "upper",
width: 140,
url: "jcsj/gysfl/init/zt"
},
{
title: "名称",
field: "name",
width: 140
},
{
title: "停用",
field: "tybz",
fieldType: "tybz"
},
{
title: "停用日期",
field: "tyrq",
fieldType: "ftDate"
},
{
title: "维护人",
field: "whr"
},
{
title: "维护时间",
field: "whsj",
fieldType: "ftDateTime"
}
],`,
// 查询参数配置(新增Expr字段存储JS表达式字符串)
queryRows: [
[
{
label: '',
prop: '',
span: 6,
type: 'input',
required: false,
valueExpr: '', // 存储JS表达式字符串(如"new Date().getFullYear()")
startProp: '',
endProp: '',
startValueExpr: '', // 范围类型开始值表达式
endValueExpr: '', // 范围类型结束值表达式
typeConfig: {}
}
]
],
queryParamsCode: '',
// 编辑表单配置(新增Expr字段存储JS表达式字符串)
editItems: [
{
label: '',
prop: '',
span: 12,
type: 'input',
required: false,
readonly: false,
valueExpr: '', // 存储JS表达式字符串
typeConfig: {}
}
],
editColItemListCode: ''
}
},
methods: {
// 表格标题代码复制
copyTableTitleCode() {
this.copyToClipboard(this.tableTitleCode);
},
// 查询参数相关方法
addQueryRow() {
this.queryRows.push([this.createDefaultQueryItem()]);
this.updateQueryCode();
},
addQueryItem(rowIndex) {
this.queryRows[rowIndex].push(this.createDefaultQueryItem());
this.updateQueryCode();
},
createDefaultQueryItem() {
return {
label: '',
prop: '',
span: 6,
type: 'input',
required: false,
valueExpr: '',
startProp: '',
endProp: '',
startValueExpr: '',
endValueExpr: '',
typeConfig: {}
};
},
removeQueryRow(index) {
if (this.queryRows.length > 1) {
this.queryRows.splice(index, 1);
this.updateQueryCode();
} else {
this.$message.warning('至少保留一行查询条件');
}
},
removeQueryItem(rowIndex, itemIndex) {
if (this.queryRows[rowIndex].length > 1) {
this.queryRows[rowIndex].splice(itemIndex, 1);
this.updateQueryCode();
} else {
this.$message.warning('每行至少保留一个字段');
}
},
handleQueryTypeChange(rowIndex, itemIndex) {
const item = this.queryRows[rowIndex][itemIndex];
// 重置表达式字段
item.valueExpr = '';
item.startProp = '';
item.endProp = '';
item.startValueExpr = '';
item.endValueExpr = '';
item.typeConfig = {};
// 按类型设置默认JS表达式
switch(item.type) {
case 'year':
item.label = '年度';
item.prop = 'year';
item.span = 4;
item.valueExpr = 'new Date().getFullYear()'; // 保留JS表达式
break;
case 'month':
item.type = 'RelSelect'; // 强制转为RelSelect
item.label = '月份';
item.prop = 'month';
item.span = 4;
item.valueExpr = 'new Date().getMonth() + 1'; // 保留JS表达式
// 保留月份IIFE原始代码
item.typeConfig.optionsDataExpr = `(() => {
const months = []
for (let i = 0; i <= 11; i++) {
months.push({
id: i + 1,
name: i + 1 + '月'
})
}
return months
})()`;
break;
case 'RelDatetimerangeV2':
item.label = '时间';
item.startProp = 'start';
item.endProp = 'end';
item.span = 8;
// 保留时间戳计算表达式
item.startValueExpr = 'new Date().getTime() - 1000 * 60 * 60 * 24 * 30';
item.endValueExpr = 'new Date().getTime()';
break;
case 'RelDaterangeV2':
item.label = '订单日期';
item.startProp = 'ywrqb';
item.endProp = 'ywrqe';
item.span = 8;
item.startValueExpr = '';
item.endValueExpr = '';
break;
case 'RelSelect':
item.label = '会计单位';
item.prop = 'kjdwid';
item.span = 8;
item.typeConfig.src = 'jcsj/common/kjdw';
item.valueExpr = '';
break;
case 'RelMulSelect':
item.label = '会计单位';
item.prop = 'kjdwid';
item.span = 8;
item.typeConfig.src = 'jcsj/common/kjdw';
item.valueExpr = '';
break;
case 'AuxInput':
item.label = '供应商';
item.prop = 'gysid';
item.span = 6;
item.typeConfig = {
isRequest: true,
dynamic: false,
code: 'true',
label: 'name',
transform: { value: 'id', label: 'name' }
};
break;
case 'date':
item.label = '日期';
item.prop = 'rq';
item.span = 6;
item.valueExpr = '';
break;
case 'datetime':
item.label = '日期';
item.prop = 'rq';
item.span = 6;
item.valueExpr = '';
break;
}
this.updateQueryCode();
},
// 手动构建配置字符串,保留JS表达式
updateQueryCode() {
let queryParamsStr = 'queryParams: [';
this.queryRows.forEach((row, rowIdx) => {
const filteredItems = row.filter(item => item.prop);
if (filteredItems.length === 0) return;
queryParamsStr += rowIdx > 0 ? ', [' : '[';
filteredItems.forEach((item, itemIdx) => {
if (itemIdx > 0) queryParamsStr += ',';
queryParamsStr += '\n {';
// 基础属性
queryParamsStr += `\n label: '${item.label || ''}',`;
queryParamsStr += `\n prop: '${item.prop}',`;
queryParamsStr += `\n span: ${item.span},`;
queryParamsStr += `\n type: '${item.type}',`;
// 处理动态值(保留JS表达式)
if (item.type === 'month') {
// 月份特殊处理:保留IIFE代码
queryParamsStr += `\n value: ${item.valueExpr},`;
queryParamsStr += `\n typeConfig: {`;
queryParamsStr += `\n optionsData: ${item.typeConfig.optionsDataExpr}`;
queryParamsStr += `\n }`;
} else if (item.type === 'RelDaterangeV2' || item.type === 'RelDatetimerangeV2') {
// 范围类型:startProp/endProp/startValue/endValue
queryParamsStr += `\n startProp: '${item.startProp || ''}',`;
queryParamsStr += `\n endProp: '${item.endProp || ''}',`;
if (item.startValueExpr) queryParamsStr += `\n startValue: ${item.startValueExpr},`;
if (item.endValueExpr) queryParamsStr += `\n endValue: ${item.endValueExpr},`;
} else {
// 普通类型:value/required
if (item.valueExpr) queryParamsStr += `\n value: ${item.valueExpr},`;
else queryParamsStr += `\n value: '',`;
if (item.required) queryParamsStr += `\n required: true,`;
// 其他typeConfig
if (Object.keys(item.typeConfig).length > 0) {
queryParamsStr += `\n typeConfig: {`;
if (item.typeConfig.src) queryParamsStr += `\n src: '${item.typeConfig.src}'`;
if (item.typeConfig.code) {
queryParamsStr += `\n isRequest: ${item.typeConfig.isRequest},`;
queryParamsStr += `\n dynamic: ${item.typeConfig.dynamic},`;
queryParamsStr += `\n code: ${item.typeConfig.code},`;
queryParamsStr += `\n label: '${item.typeConfig.label}',`;
queryParamsStr += `\n transform: {`;
queryParamsStr += `\n value: '${item.typeConfig.transform.value}',`;
queryParamsStr += `\n label: '${item.typeConfig.transform.label}'`;
queryParamsStr += `\n }`;
}
queryParamsStr += `\n }`;
}
}
queryParamsStr += '\n }';
});
queryParamsStr += '\n]';
});
queryParamsStr += '\n],';
this.queryParamsCode = queryParamsStr;
},
copyQueryCode() {
this.copyToClipboard(this.queryParamsCode);
},
// 查询参数全部示例添加(带正确JS表达式)
addExample(type) {
const examples = {
input: {
label: '编码',
prop: 'code',
span: 6,
type: 'input',
required: false,
valueExpr: ''
},
RelSelect: {
label: '会计单位',
prop: 'kjdwid',
span: 8,
type: 'RelSelect',
typeConfig: { src: 'jcsj/common/kjdw' },
valueExpr: ''
},
RelMulSelect: {
label: '会计单位',
prop: 'kjdwid',
span: 8,
type: 'RelMulSelect',
typeConfig: { src: 'jcsj/common/kjdw' },
valueExpr: ''
},
date: {
label: '日期',
prop: 'rq',
span: 6,
type: 'date',
valueExpr: ''
},
datetime: {
label: '日期',
prop: 'rq',
span: 6,
type: 'datetime',
valueExpr: ''
},
year: {
label: '年度',
prop: 'year',
span: 4,
type: 'year',
valueExpr: 'new Date().getFullYear()'
},
month: {
label: '月份',
prop: 'month',
span: 4,
type: 'month',
valueExpr: 'new Date().getMonth() + 1',
typeConfig: {
optionsDataExpr: `(() => {
const months = []
for (let i = 0; i <= 11; i++) {
months.push({
id: i + 1,
name: i + 1 + '月'
})
}
return months
})()`
}
},
RelDaterangeV2: {
label: '订单日期',
startProp: 'ywrqb',
endProp: 'ywrqe',
span: 8,
type: 'RelDaterangeV2',
startValueExpr: '',
endValueExpr: ''
},
RelDatetimerangeV2: {
label: '时间',
startProp: 'start',
endProp: 'end',
span: 8,
type: 'RelDatetimerangeV2',
startValueExpr: 'new Date().getTime() - 1000 * 60 * 60 * 24 * 30',
endValueExpr: 'new Date().getTime()'
},
AuxInput: {
label: '供应商',
prop: 'gysid',
span: 6,
type: 'AuxInput',
required: false,
typeConfig: {
isRequest: true,
dynamic: false,
code: 'true',
label: 'name',
transform: { value: 'id', label: 'name' }
},
valueExpr: ''
}
};
if (examples[type]) {
// 找到第一个非空行添加示例
const targetRow = this.queryRows.find(row => row.length > 0) || this.queryRows[0];
targetRow.push({...examples[type]});
this.updateQueryCode();
}
},
// 编辑表单相关方法(同查询参数逻辑,保留JS表达式)
addEditItem() {
this.editItems.push({
label: '',
prop: '',
span: 12,
type: 'input',
required: false,
readonly: false,
valueExpr: '',
typeConfig: {}
});
this.updateEditCode();
},
removeEditItem(index) {
if (this.editItems.length > 1) {
this.editItems.splice(index, 1);
this.updateEditCode();
} else {
this.$message.warning('至少保留一个表单字段');
}
},
handleEditTypeChange(index) {
const item = this.editItems[index];
item.typeConfig = {};
item.valueExpr = '';
switch(item.type) {
case 'textarea':
item.span = 24;
item.label = '备注';
item.prop = 'bz';
break;
case 'checkbox':
item.label = '批号管理';
item.prop = 'phgl';
item.span = 12;
item.valueExpr = "'N'"; // 字符串类型JS表达式
break;
case 'date':
item.label = '维护时间';
item.prop = 'whsj';
item.span = 8;
item.readonly = true;
item.valueExpr = 'new Date().getTime()';
break;
case 'datetime':
item.label = '维护时间';
item.prop = 'whsj';
item.span = 8;
item.readonly = true;
item.valueExpr = 'new Date().getTime()';
break;
case 'year':
item.label = '年度';
item.prop = 'year';
item.span = 8;
item.readonly = true;
item.valueExpr = 'new Date().getFullYear()';
break;
case 'RelSelect':
item.label = '计量单位';
item.prop = 'jldw';
item.span = 12;
item.required = true;
item.typeConfig.src = 'jcsj/jldw/query';
break;
case 'RelMulSelect':
item.label = '计量单位';
item.prop = 'jldw';
item.span = 12;
item.required = true;
item.typeConfig.src = 'jcsj/jldw/query';
break;
case 'inputNumber':
item.label = '数量';
item.prop = 'sl';
item.span = 12;
item.valueExpr = '0';
break;
case 'inputInt':
item.label = '排序号';
item.prop = 'pxh';
item.span = 12;
item.valueExpr = '1';
break;
case 'AuxInput':
item.label = '客户信息';
item.prop = 'khid';
item.span = 8;
item.required = true;
item.typeConfig = {
isRequest: true,
code: '"CUSTOM"', // 字符串类型JS表达式
label: 'name',
transform: { value: 'id', label: 'name' }
};
break;
}
this.updateEditCode();
},
// 编辑表单手动构建字符串,保留JS表达式
updateEditCode() {
let editCodeStr = 'editColItemList: [';
const filteredItems = this.editItems.filter(item => item.prop);
filteredItems.forEach((item, idx) => {
if (idx > 0) editCodeStr += ',';
editCodeStr += '\n {';
// 基础属性
editCodeStr += `\n label: '${item.label || ''}',`;
editCodeStr += `\n prop: '${item.prop}',`;
editCodeStr += `\n span: ${item.span},`;
editCodeStr += `\n type: '${item.type}',`;
// 动态值与配置
if (item.required) editCodeStr += `\n required: true,`;
if (item.readonly) editCodeStr += `\n readonly: true,`;
if (item.valueExpr) editCodeStr += `\n value: ${item.valueExpr},`;
else editCodeStr += `\n value: '',`;
// typeConfig
if (Object.keys(item.typeConfig).length > 0) {
editCodeStr += `\n typeConfig: {`;
if (item.typeConfig.src) editCodeStr += `\n src: '${item.typeConfig.src}',`;
if (item.typeConfig.code) {
editCodeStr += `\n isRequest: ${item.typeConfig.isRequest},`;
editCodeStr += `\n code: ${item.typeConfig.code},`;
editCodeStr += `\n label: '${item.typeConfig.label}',`;
editCodeStr += `\n transform: {`;
editCodeStr += `\n value: '${item.typeConfig.transform.value}',`;
editCodeStr += `\n label: '${item.typeConfig.transform.label}'`;
editCodeStr += `\n }`;
}
editCodeStr += `\n }`;
}
editCodeStr += '\n }';
});
editCodeStr += '\n],';
this.editColItemListCode = editCodeStr;
},
copyEditCode() {
this.copyToClipboard(this.editColItemListCode);
},
// 编辑表单全部示例添加(带正确JS表达式)
addEditExample(type) {
const examples = {
input: {
label: '编码',
prop: 'code',
span: 12,
type: 'input',
required: true,
valueExpr: ''
},
inputNumber: {
label: '数量',
prop: 'sl',
span: 12,
type: 'inputNumber',
required: true,
valueExpr: '0'
},
inputInt: {
label: '排序号',
prop: 'pxh',
span: 12,
type: 'inputInt',
required: true,
valueExpr: '1'
},
textarea: {
label: '备注',
prop: 'bz',
span: 24,
type: 'textarea',
valueExpr: ''
},
RelSelect: {
label: '计量单位',
prop: 'jldw',
span: 12,
type: 'RelSelect',
typeConfig: { src: 'jcsj/jldw/query' },
required: true,
valueExpr: ''
},
RelMulSelect: {
label: '计量单位',
prop: 'jldw',
span: 12,
type: 'RelMulSelect',
typeConfig: { src: 'jcsj/jldw/query' },
required: true,
valueExpr: ''
},
checkbox: {
label: '批号管理',
prop: 'phgl',
span: 12,
type: 'checkbox',
valueExpr: "'N'"
},
date: {
label: '维护时间',
prop: 'whsj',
span: 8,
type: 'date',
readonly: true,
valueExpr: 'new Date().getTime()'
},
datetime: {
label: '维护时间',
prop: 'whsj',
span: 8,
type: 'datetime',
readonly: true,
valueExpr: 'new Date().getTime()'
},
year: {
label: '年度',
prop: 'year',
span: 8,
type: 'year',
readonly: true,
valueExpr: 'new Date().getFullYear()'
},
AuxInput: {
label: '客户信息',
prop: 'khid',
span: 8,
type: 'AuxInput',
required: true,
typeConfig: {
isRequest: true,
code: '"CUSTOM"',
label: 'name',
transform: { value: 'id', label: 'name' }
},
valueExpr: ''
}
};
if (examples[type]) {
this.editItems.push({...examples[type]});
this.updateEditCode();
}
},
// 通用复制方法
copyToClipboard(text) {
const textarea = document.createElement('textarea');
textarea.value = text;
document.body.appendChild(textarea);
textarea.select();
document.execCommand('copy');
document.body.removeChild(textarea);
this.$message.success('代码已复制到剪贴板');
}
},
mounted() {
this.updateQueryCode();
this.updateEditCode();
}
}
</script>
<style scoped>
/* 基础样式 */
.config-generator {
padding: 0 20px 40px;
background-color: #f5f7fa;
min-height: 100vh;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
}
/* 顶部导航 */
.header {
padding: 30px 0;
text-align: center;
border-bottom: 1px solid #e5e7eb;
margin-bottom: 30px;
}
.header h1 {
font-size: 28px;
font-weight: 600;
color: #1f2329;
margin: 0 0 10px;
letter-spacing: 0.5px;
}
.header-desc {
color: #6b7280;
font-size: 14px;
margin: 0;
opacity: 0.9;
}
/* 配置区域 */
.config-section {
margin-bottom: 30px;
}
.config-card {
background: #fff;
border-radius: 12px;
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.03);
overflow: hidden;
transition: all 0.3s ease;
border: 1px solid #f0f2f5;
}
.config-card:hover {
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.05);
border-color: #e6f7ff;
}
.config-card-header {
padding: 20px 24px;
border-bottom: 1px solid #f0f2f5;
display: flex;
align-items: center;
gap: 12px;
background-color: #fafbfc;
}
.config-card-icon {
width: 36px;
height: 36px;
border-radius: 8px;
background-color: #e6f7ff;
display: flex;
align-items: center;
justify-content: center;
color: #1890ff;
font-size: 18px;
transition: all 0.2s ease;
}
.config-card:hover .config-card-icon {
background-color: #1890ff;
color: #fff;
}
.config-card-title {
font-size: 18px;
font-weight: 600;
color: #1f2329;
margin: 0;
}
.config-card-desc {
font-size: 14px;
color: #6b7280;
margin: 0;
flex: 1;
opacity: 0.9;
}
/* 配置内容区(左右布局) */
.config-content {
display: flex;
gap: 20px;
padding: 24px;
}
.config-left {
flex: 1.3;
padding-right: 10px;
max-height: 750px;
overflow-y: auto;
scrollbar-width: thin;
scrollbar-color: #e6f7ff #f5f7fa;
}
.config-left::-webkit-scrollbar {
width: 6px;
}
.config-left::-webkit-scrollbar-track {
background: #f5f7fa;
border-radius: 3px;
}
.config-left::-webkit-scrollbar-thumb {
background: #e6f7ff;
border-radius: 3px;
}
.config-left::-webkit-scrollbar-thumb:hover {
background: #b3d8ff;
}
.config-right {
flex: 1;
display: flex;
flex-direction: column;
}
/* 规则与示例区 */
.rule-section {
margin-bottom: 24px;
padding: 18px;
background-color: #f9fafb;
border-radius: 8px;
border: 1px solid #f0f2f5;
}
.rule-section h3, .example-section h3, .example-types h3 {
font-size: 16px;
color: #1f2329;
margin: 0 0 12px;
display: flex;
align-items: center;
gap: 8px;
font-weight: 500;
}
.rule-section h3::before, .example-section h3::before, .example-types h3::before {
content: '';
width: 4px;
height: 16px;
background-color: #1890ff;
border-radius: 2px;
}
.rule-list {
margin: 0;
padding-left: 20px;
font-size: 14px;
color: #4b5563;
line-height: 1.8;
}
.rule-list strong {
color: #1f2329;
font-weight: 500;
}
.example-section {
margin-bottom: 24px;
}
.example-code {
/* background-color: #f8fafc; */
border-radius: 6px;
padding: 14px;
font-size: 13px;
color: #334155;
overflow-x: auto;
margin: 0;
border: 1px solid #f0f2f5;
font-family: 'Fira Code', monospace;
}
/* 示例按钮区域 */
.example-types {
margin-bottom: 24px;
padding: 16px;
background-color: #f0f9ff;
border-radius: 8px;
border: 1px solid #e6f7ff;
}
.tip-text {
font-size: 12px;
color: #6b7280;
font-weight: normal;
margin-left: 8px;
}
.example-row {
margin-bottom: 12px;
}
.example-row.first-row {
margin-bottom: 8px;
}
.example-btn {
display: block;
width: 100%;
padding: 8px 0;
text-align: center;
color: #1890ff;
border-radius: 4px;
transition: all 0.2s ease;
font-size: 13px;
}
.example-btn:hover {
background-color: #e6f7ff;
color: #096dd9;
}
/* 查询行与字段项样式 */
.query-row {
margin-bottom: 24px;
padding: 18px;
border: 1px dashed #e5e7eb;
border-radius: 8px;
transition: all 0.2s ease;
background-color: #fff;
}
.query-row:hover {
border-color: #c9cdD4;
background-color: #fafafa;
}
.row-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 16px;
padding-bottom: 8px;
border-bottom: 1px solid #f0f2f5;
}
.row-number {
font-size: 14px;
font-weight: 500;
color: #4b5563;
}
.field-item {
margin-bottom: 18px;
padding: 18px;
background-color: #f9fafb;
border-radius: 8px;
border: 1px solid #f0f2f5;
transition: all 0.2s ease;
}
.field-item:hover {
border-color: #e6f7ff;
background-color: #f0f9ff;
}
.field-item-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 14px;
}
.field-number {
font-size: 13px;
color: #6b7280;
font-weight: 500;
}
/* 表单样式 */
.field-form {
margin-bottom: 0;
}
.el-form-item {
margin-bottom: 14px;
}
.el-input, .el-select, .el-input-number {
border-radius: 6px;
border-color: #e5e7eb;
transition: all 0.2s ease;
}
.el-input:focus-within, .el-select:focus-within, .el-input-number:focus-within {
border-color: #1890ff;
box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.1);
}
.el-input__inner, .el-select__inner {
border-radius: 6px;
padding: 8px 12px;
font-size: 13px;
}
/* 按钮样式 */
.add-btn {
margin-bottom: 20px;
background-color: #1890ff;
border-color: #1890ff;
border-radius: 6px;
padding: 8px 16px;
font-size: 14px;
transition: all 0.2s ease;
}
.add-btn:hover {
background-color: #096dd9;
border-color: #096dd9;
box-shadow: 0 2px 8px rgba(24, 144, 255, 0.2);
}
.add-field-btn {
margin-top: 10px;
color: #1890ff;
border-color: #1890ff;
border-radius: 6px;
padding: 4px 12px;
font-size: 12px;
transition: all 0.2s ease;
}
.add-field-btn:hover {
background-color: #e6f7ff;
color: #096dd9;
}
.remove-btn {
color: #ff4d4f;
padding: 0 6px;
font-size: 12px;
transition: all 0.2s ease;
}
.remove-btn:hover {
color: #d93025;
background-color: #fff2f0;
border-radius: 4px;
}
/* 预览区样式 */
.preview-header {
padding: 14px 18px;
background-color: #f5f7fa;
border-radius: 8px 8px 0 0;
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 1px solid #e5e7eb;
border-top: 1px solid #f0f2f5;
border-left: 1px solid #f0f2f5;
border-right: 1px solid #f0f2f5;
}
.preview-header h3 {
font-size: 14px;
font-weight: 600;
color: #1f2329;
margin: 0;
}
.copy-btn {
background-color: #1890ff;
border-color: #1890ff;
border-radius: 4px;
padding: 4px 12px;
font-size: 12px;
transition: all 0.2s ease;
}
.copy-btn:hover {
background-color: #096dd9;
border-color: #096dd9;
box-shadow: 0 2px 6px rgba(24, 144, 255, 0.2);
}
.code-container {
flex: 1;
padding: 0;
overflow: hidden;
border-radius: 0 0 8px 8px;
height: 100%;
min-height: 320px;
border: 1px solid #f0f2f5;
border-top: none;
}
pre {
margin: 0;
padding: 18px;
background-color: #1e293b;
color: #e2e8f0;
font-family: 'Fira Code', monospace;
font-size: 13px;
line-height: 1.6;
overflow: auto;
height: 100%;
min-height: 320px;
border-radius: 0 0 8px 8px;
}
code {
color: #cbd5e1;
}
/* 响应式调整 */
@media (max-width: 1200px) {
.config-content {
flex-direction: column;
}
.config-left, .config-right {
width: 100%;
max-height: none;
}
.code-container {
min-height: 250px;
}
.example-row {
margin-bottom: 8px;
}
.example-btn {
font-size: 12px;
padding: 6px 0;
}
}
@media (max-width: 768px) {
.config-content {
padding: 16px;
}
.el-row {
flex-direction: column;
}
.el-col {
width: 100% !important;
margin-bottom: 8px;
}
.example-row {
flex-direction: column;
}
.example-row .el-col {
margin-bottom: 8px;
}
}
</style>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment