增加辅助工具:数据字典,编号策略,地址选择,Excel导入导出

This commit is contained in:
zsvg
2022-06-04 05:12:03 +08:00
parent 3947290dba
commit 8e0a3a5b15
25 changed files with 1866 additions and 21 deletions
+2 -2
View File
@@ -5,5 +5,5 @@ VITE_PORT = 8888
VITE_OPEN = false
# public path 配置线上环境路径(打包)、本地通过 http-server 访问时,请置空即可
VITE_PUBLIC_PATH = /vue/
#VITE_PUBLIC_PATH = ''
#VITE_PUBLIC_PATH = /vue/
VITE_PUBLIC_PATH = ''
+1 -2
View File
@@ -2,7 +2,6 @@
ENV = 'development'
# 本地环境接口地址
VITE_API_URL = 'http://localhost:5000/'
#VITE_API_URL = 'http://localhost:5000/'
#VITE_API_URL = 'http://localhost:8088/'
#VITE_API_URL = 'http://222.92.228.219:5301/'
VITE_UI_URL = 'http://localhost:8888/'
+1 -1
View File
@@ -4,6 +4,6 @@ ENV = 'production'
# 线上环境接口地址
#VITE_API_URL = 'https://lyt-top.gitee.io/vue-next-admin-preview/'
#VITE_API_URL = 'http://222.92.228.219:5301/'
VITE_API_URL = 'http://localhost:5000/'
+11
View File
@@ -21,6 +21,7 @@
"echarts-gl": "^2.0.9",
"echarts-wordcloud": "^2.0.0",
"element-plus": "2.2.0",
"file-saver": "2.0.5",
"js-cookie": "^3.0.1",
"jsplumb": "^2.15.6",
"mitt": "^3.0.0",
@@ -3371,6 +3372,11 @@
"node": "^10.12.0 || >=12.0.0"
}
},
"node_modules/file-saver": {
"version": "2.0.5",
"resolved": "https://registry.npmmirror.com/file-saver/-/file-saver-2.0.5.tgz",
"integrity": "sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA=="
},
"node_modules/fill-range": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
@@ -7903,6 +7909,11 @@
"flat-cache": "^3.0.4"
}
},
"file-saver": {
"version": "2.0.5",
"resolved": "https://registry.npmmirror.com/file-saver/-/file-saver-2.0.5.tgz",
"integrity": "sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA=="
},
"fill-range": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+2 -1
View File
@@ -37,7 +37,8 @@
"codemirror": "^5.59.2",
"bpmn-js": "^8.1.0",
"bpmn-js-properties-panel": "^0.39.0",
"vform3-builds": "^3.0.8"
"vform3-builds": "^3.0.8",
"file-saver": "2.0.5"
},
"devDependencies": {
"@types/node": "^17.0.35",
+432
View File
@@ -0,0 +1,432 @@
html {
font-size: 12px;
}
.amap-copyright{
box-sizing: content-box
}
* {
box-sizing: border-box
}
.input-textarea{
color:grey;
height:8em;
overflow:auto;
border-radius:0.4rem;
border:1px solid #ced4da;
margin-bottom:1rem;
}
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
line-height: 1.5;
font-weight: 300;
color: #111213;
}
hr {
margin: 0.5rem 0;
box-sizing: content-box;
height: 0;
overflow: visible;
border: 0;
border-top: 1px solid rgba(0, 0, 0, .1)
}
p {
margin-top: 0;
margin-bottom: 0;
}
label {
display: inline-block;
margin-bottom: 0.4rem;
}
label, .btn {
margin-left: 0;
font-size: 1rem;
}
button, input, select {
margin: 0;
font-family: inherit;
font-size: inherit;
line-height: inherit;
overflow: visible;
text-transform: none
}
[type=button]::-moz-focus-inner, [type=reset]::-moz-focus-inner, [type=submit]::-moz-focus-inner, button::-moz-focus-inner {
padding: 0;
border-style: none;
}
input[type=checkbox], input[type=radio] {
box-sizing: border-box;
padding: 0;
-webkit-box-sizing: border-box;
box-sizing: border-box;
padding: 0;
margin: 0 0.5rem 0 0;
}
h4 {
font-family: inherit;
line-height: 1.8;
font-weight: 300;
color: inherit;
font-size: 1.1rem;
margin-top: 0;
margin-bottom: .5rem
}
.btn {
display: inline-block;
font-weight: 400;
text-align: center;
white-space: nowrap;
vertical-align: middle;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
border: 1px solid transparent;
transition: color .15s ease-in-out, background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out;
background-color: transparent;
background-image: none;
color: #25A5F7;
border-color: #25A5F7;
padding: .25rem .5rem;
line-height: 1.5;
border-radius: 1rem;
-webkit-appearance: button;
cursor:pointer;
}
.btn:hover {
color: #fff;
background-color: #25A5F7;
border-color: #25A5F7
}
.btn:hover {
text-decoration: none
}
.input-item {
position: relative;
display: -ms-flexbox;
display: flex;
-ms-flex-wrap: wrap;
flex-wrap: wrap;
-ms-flex-align: center;
align-items: center;
width: 100%;
height: 3rem;
}
.input-item:last-child {
margin-bottom: 0;
}
.input-item>select, .input-item>input[type=text], .input-item>input[type=date] {
position: relative;
-ms-flex: 1 1 auto;
flex: 1 1 auto;
width: 1%;
margin-bottom: 0;
}
.input-item>select:not(:last-child), .input-item>input[type=text]:not(:last-child), .input-item>input[type=date]:not(:last-child) {
border-top-right-radius: 0;
border-bottom-right-radius: 0
}
.input-item>select:not(:first-child), .input-item>input[type=text]:not(:first-child), .input-item>input[type=date]:not(:first-child) {
border-top-left-radius: 0;
border-bottom-left-radius: 0
}
.input-item-prepend {
margin-right: -1px;
}
.input-item-text, input[type=text],input[type=date], select {
height: calc(2.2rem + 2px);
}
.input-item-text {
width: 6rem;
text-align: justify;
padding: 0.4rem 0.7rem;
display: inline-block;
text-justify: distribute-all-lines;
/*ie6-8*/
text-align-last: justify;
/* ie9*/
-moz-text-align-last: justify;
/*ff*/
-webkit-text-align-last: justify;
/*chrome 20+*/
-ms-flex-align: center;
align-items: center;
margin-bottom: 0;
font-size: 1rem;
font-weight: 400;
line-height: 1.5;
color: #495057;
text-align: center;
white-space: nowrap;
background-color: #e9ecef;
border: 1px solid #ced4da;
border-radius: .25rem;
border-bottom-right-radius: 0;
border-top-right-radius: 0;
}
.input-item-text input[type=checkbox], .input-item-text input[type=radio] {
margin-top: 0
}
.input-card {
display: flex;
flex-direction: column;
min-width: 0;
word-wrap: break-word;
background-color: #fff;
background-clip: border-box;
border-radius: .25rem;
width: 28rem;
border-width: 0;
border-radius: 0.4rem;
box-shadow: 0 2px 6px 0 rgba(114, 124, 245, .5);
position: fixed;
top: 1rem;
right: 1rem;
-ms-flex: 1 1 auto;
flex: 1 1 auto;
padding: 0.75rem 1.25rem;
}
.input-text {
line-height: 2rem;
margin-right: 2rem;
}
.info hr {
margin-right: 0;
margin-left: 0;
border-top-color: grey;
}
.info {
padding: .75rem 1.25rem;
margin-bottom: 1rem;
border-radius: .25rem;
position: fixed;
top: 1rem;
background-color: white;
width: auto;
min-width: 22rem;
border-width: 0;
left: 1rem;
box-shadow: 0 2px 6px 0 rgba(114, 124, 245, .5);
}
.code {
left: 1.5rem;
right: 1.5rem;
top: 1.5rem;
bottom: 1.5rem;
overflow: auto;
margin-bottom: 0rem;
}
.code .btn {
top: 1rem;
position: absolute;
right: 1rem;
}
.code .result {
border: 1px solid rgba(0, 0, 0, 0.1);
border-radius: 0.5rem;
padding: 1rem;
bottom: 1rem;
position: absolute;
top: 5.5rem;
right: 1rem;
left: 1rem;
overflow: auto;
}
.code .status {
color: #80adff;
display: inline-block;
font-size: 14px;
}
.code h4 {
display: inline-block;
max-width: 20rem;
margin-right: 1rem;
margin-bottom: 1rem;
}
select, input[type=text], input[type=date] {
display: inline-block;
width: 100%;
padding: .375rem 1.75rem .375rem .75rem;
line-height: 1.5;
color: #495057;
vertical-align: middle;
background: #fff url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3E%3Cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E") no-repeat right .75rem center;
background-size: 8px 10px;
border: 1px solid #ced4da;
border-radius: .25rem;
-webkit-appearance: none;
-moz-appearance: none;
appearance: none
}
input[type=text],input[type=date] {
background: #fff;
padding: .375rem .75rem;
}
select:focus, input[type=text]:focus, input[type=date]:focus {
border-color: #80bdff;
outline: 0;
box-shadow: 0 0 0 .1rem rgba(128, 189, 255, .1)
}
.btn:focus {
outline: 0;
box-shadow: none;
}
select:focus::-ms-value, input[type=text]:focus::-ms-value,input[type=date]:focus::-ms-value {
color: #495057;
background-color: #fff
}
/* native toastr */
.native-toast {
position: fixed;
background-color: rgba(50, 50, 50, .8);
border-radius: 33px;
color: white;
left: 50%;
text-align: center;
padding: 6px 12px;
opacity: 0;
z-index: 99999;
transition: transform .25s, opacity .25s, top .25s;
box-sizing: border-box;
}
.native-toast-bottom {
bottom: 50px;
-ms-transform: translateX(-50%) translateY(50px);
transform: translateX(-50%) translateY(50px)
}
.native-toast-bottom.native-toast-shown {
opacity: 1;
-ms-transform: translateX(-50%) translateY(0);
transform: translateX(-50%) translateY(0);
}
.native-toast-bottom.native-toast-edge {
bottom: 0;
}
.native-toast-top {
top: 50px;
-ms-transform: translateX(-50%) translateY(-50px);
transform: translateX(-50%) translateY(-50px)
}
.native-toast-top.native-toast-shown {
opacity: 1;
-ms-transform: translateX(-50%) translateY(0);
transform: translateX(-50%) translateY(0);
}
.native-toast-top.native-toast-edge {
top: 0;
}
.native-toast-center {
top: 0;
-ms-transform: translateX(-50%) translateY(-50px);
transform: translateX(-50%) translateY(-50px)
}
.native-toast-center.native-toast-shown {
opacity: 1;
top: 50%;
-ms-transform: translateX(-50%) translateY(-50%);
transform: translateX(-50%) translateY(-50%);
}
.native-toast-edge {
border-radius: 0;
width: 100%;
text-align: left;
}
@media screen and (min-width: 40rem) {
.native-toast:not(.native-toast-edge) {
max-width: 18rem;
}
}
/*
max-width does not seem to work in small screen?
*/
/*@media screen and (max-width: 768px) {
.native-toast:not(.native-toast-edge) {
max-width: 400px;
}
}
@media screen and (max-width: 468px) {
.native-toast:not(.native-toast-edge) {
max-width: 300px;
}
}*/
/* types */
.native-toast-error {
background-color: #d92727;
color: white;
}
.native-toast-success {
background-color: #62a465;
color: white;
}
.native-toast-warning {
background-color: #fdaf17;
color: white;
}
.native-toast-info {
background-color: #5060ba;
color: white;
}
[class^="native-toast-icon-"] {
vertical-align: middle;
margin-right: 8px
}
[class^="native-toast-icon-"] svg {
width: 16px;
height: 16px;
}
+199
View File
@@ -0,0 +1,199 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="initial-scale=1.0, user-scalable=no, width=device-width">
<title>地址选择</title>
<link rel="stylesheet" href="amap.css?v=3"/>
<style type="text/css">
html, body, #container {
height: 100%;
}
html {
overflow-y: hidden;
}
.amap-logo {
display: none;
opacity: 0;
}
.amap-copyright {
opacity: 0;
}
.btn {
width: 10rem;
/*margin-left:6.8rem;*/
}
</style>
</head>
<body>
<div id="container"></div>
<div class="info">
<div class="input-item">
<div class="input-item-prepend">
<span class="input-item-text" style="width:8rem;">请输入关键字</span>
</div>
<input id='tipinput' type="text">
</div>
</div>
<div class="input-card">
<label style='color:grey'>点击地图选择地址,详细地址可手动修改</label>
<div class="input-item">
<div class="input-item-prepend"><span class="input-item-text">经纬度</span></div>
<input id='adcoo' type="text" value='116.39,39.9' disabled style="color: green" placeholder="点击地址自动带出">
</div>
<div class="input-item">
<div class="input-item-prepend"><span class="input-item-text">所在地区</span></div>
<input id='adreg' type="text" disabled style="color: green" placeholder="省市区,通过定位解析">
</div>
<div class="input-item">
<div class="input-item-prepend"><span class="input-item-text">详细地址</span></div>
<input id='addet' type="text" style="color: blue" placeholder="如道路、门牌号、小区、楼栋等">
</div>
<input id='adpro' type="hidden">
<input id='adcit' type="hidden">
<input id='addis' type="hidden">
<input id='adcco' type="hidden">
<input id='addco' type="hidden">
<div class="input-item">
<input id="yesBtn" type="button" class="btn" value="确定" style="border-radius: 0.1rem;margin-left:2rem;">
<input id="noBtn" type="button" class="btn" value="关闭" style="border-radius: 0.1rem;margin-left:2rem;">
</div>
</div>
<script type="text/javascript"
src="https://webapi.amap.com/maps?v=1.4.15&key=c2c9205ab3668d57d66084daf6f80eb2&plugin=AMap.Autocomplete,AMap.Geocoder,AMap.PlaceSearch"></script>
<script type="text/javascript">
// console.log(window.location.href);
// console.log(window.location.href.split("adzoo=")[1]);
// console.log(window.location.href.split("adzoo=")[1].split("&"));
document.getElementById('adcoo').value = window.location.href.split("adcoo=")[1].split("&")[0];
document.getElementById('adreg').value = decodeURIComponent(window.location.href.split("adreg=")[1].split("&")[0]);
document.getElementById('addet').value = decodeURIComponent(window.location.href.split("addet=")[1].split("&")[0]);
var map;
var marker = new AMap.Marker();
if (document.getElementById('adcoo').value) {
var cooArr = document.getElementById('adcoo').value.split(',');
var zoom = window.location.href.split("adzoo=")[1].split("&")[0];
map = new AMap.Map('container', {
resizeEnable: true,
center: cooArr,
zoom: zoom ? zoom : 11
});
marker.setPosition(cooArr);
marker.setMap(map);
} else {
map = new AMap.Map('container', {
resizeEnable: true,
zoom: 11
});
}
//输入提示
var autoOptions = {
input: "tipinput"
};
var auto = new AMap.Autocomplete(autoOptions);
var placeSearch = new AMap.PlaceSearch({
map: map
}); //构造地点查询类
AMap.event.addListener(auto, "select", select);//注册监听,当选中某条记录时会触发
function select(e) {
if (e.poi.location) {
document.getElementById('adcoo').value = e.poi.location.lng + ',' + e.poi.location.lat;
} else {
document.getElementById('adcoo').value = '';
}
placeSearch.setCity(e.poi.adcode);
placeSearch.search(e.poi.name);
regeoCode();
}
var geocoder = new AMap.Geocoder({
city: "010", //城市设为北京,默认:“全国”
radius: 500 //范围,默认:500
});
function regeoCode() {
var adcoo = document.getElementById('adcoo').value.split(',');
map.add(marker);
marker.setPosition(adcoo);
geocoder.getAddress(adcoo, function (status, result) {
if (status === 'complete' && result.regeocode) {
// var address = result.regeocode.formattedAddress;
var addrComp = result.regeocode.addressComponent;
var adreg = addrComp.province + addrComp.city + addrComp.district;
var addet = addrComp.township + addrComp.street + addrComp.streetNumber;
if (addet === '') {
var adarr = result.regeocode.formattedAddress.split(adreg);
if (adarr.length > 1) {
addet = adarr[1];
}
}
document.getElementById('adreg').value = adreg;
document.getElementById('addet').value = addet;
document.getElementById('adpro').value = addrComp.province;
document.getElementById('adcit').value = addrComp.city;
document.getElementById('addis').value = addrComp.district;
document.getElementById('adcco').value = addrComp.citycode;
document.getElementById('addco').value = addrComp.adcode;
// console.log(result);
} else {
log.error('根据经纬度查询地址失败')
}
});
}
map.on('click', function (e) {
document.getElementById('adcoo').value = e.lnglat;
regeoCode();
});
document.getElementById('adcoo').onkeydown = function (e) {
if (e.keyCode === 13) {
regeoCode();
return false;
}
return true;
};
function yesBtnClick() {
var back = {};
back.adcoo = document.getElementById('adcoo').value;
back.adreg = document.getElementById('adreg').value;
back.addet = document.getElementById('addet').value;
back.adpro = document.getElementById('adpro').value;
back.adcit = document.getElementById('adcit').value;
back.addis = document.getElementById('addis').value;
back.adcco = document.getElementById('adcco').value;
back.addco = document.getElementById('addco').value;
back.adzoo = map.getZoom();
if (back.adcoo === '') {
alert("请在地图上定位地址");
} else if (back.addet === '') {
alert("请填写详细地址");
} else {
window.parent.addressChooseBack(back);
}
}
document.getElementById("yesBtn").onclick = yesBtnClick;
function noBtnClick() {
window.parent.addressChooseBack();
}
document.getElementById("noBtn").onclick = noBtnClick;
</script>
</body>
</html>
+58
View File
@@ -0,0 +1,58 @@
<template>
<div class="amap-dialog">
<el-dialog v-model='dialogVisible' title='地址选择' draggable width='90%' >
<div style="height: 700px;overflow: hidden">
<iframe :src="state.amapSrc" frameborder="0" height="100%" width="100%"></iframe>
<!-- <iframe :src="http://localhost:8888/ass/amap.html?adcoo=&adreg=&addet=&adzoo=&v=" frameborder="0" height="100%" width="100%"></iframe>-->
</div>
<!-- <template #footer>-->
<!-- <span class='dialog-footer'>-->
<!-- <el-button type='primary' @click='handleConfirm'>确 认</el-button>-->
<!-- <el-button @click='dialogVisible = false'>取 消</el-button>-->
<!-- </span>-->
<!-- </template>-->
</el-dialog>
</div>
</template>
<script lang='ts' setup>
import {defineExpose, onMounted, reactive, ref} from 'vue';
const state = reactive({
data: [] as any,
amapSrc:'',
});
const dialogVisible = ref(false);
const openModal = async (data:any) => {
if(data&&data.adcoo){
state.amapSrc=import.meta.env.VITE_PUBLIC_PATH+'ass/amap.html?adcoo='
+data.adcoo+'&adreg='+data.adreg+'&addet='+data.addet+'&adzoo='+data.adzoo+'&v=';
}else{
state.amapSrc=import.meta.env.VITE_PUBLIC_PATH+'ass/amap.html?adcoo=&adreg=&addet=&adzoo=&v=';
}
dialogVisible.value = true;
};
defineExpose({openModal});
onMounted(() => {
});
const emits = defineEmits(['close']);
const handleConfirm = () => {
emits('close', {id: '333'});
dialogVisible.value = false;
};
window.addressChooseBack=function (data:any){
emits('close', data);
dialogVisible.value = false;
}
</script>
<style scoped>
</style>
+82
View File
@@ -0,0 +1,82 @@
<template>
<el-dialog v-model='dialogVisible' title='文件上传' draggable width='500px' :before-close='handleClose'>
<el-upload
class="upload-demo"
drag ref="upload"
:headers="state.headers"
:action="state.uploadUrl"
:auto-upload="false"
>
<el-icon class="el-icon--upload">
<upload-filled/>
</el-icon>
<div class="el-upload__text">
将文件拖到此处,或<em>点击上传</em>
</div>
<template #tip>
<div class="el-upload__tip">
请选择.xlsx的文件上传
</div>
</template>
</el-upload>
<template #footer>
<span class='dialog-footer'>
<el-button type='primary' @click='handleConfirm'>确 认</el-button>
<el-button @click='dialogVisible = false'>取 消</el-button>
</span>
</template>
</el-dialog>
</template>
<script lang='ts' setup>
import { defineExpose, onMounted, reactive, ref } from 'vue';
import { UploadFilled } from '@element-plus/icons-vue'
import {Session} from "/@/utils/storage";
import {ElMessage} from "element-plus";
const props = defineProps({
url: String,
});
const state = reactive({
data: [] as any,
uploadUrl:'',
headers:{} as any
});
const upload = ref()
const dialogVisible = ref(false);
const openModal = async () => {
state.uploadUrl=`${import.meta.env.VITE_API_URL}sa/agent/main/imp`
dialogVisible.value = true;
};
defineExpose({ openModal });
onMounted(() => {
state.headers={"Authorization": Session.get("token")}
});
const emits = defineEmits(['close']);
const handleConfirm = () => {
ElMessage.warning("演示模式不支持导入")
//upload.value!.submit();
emits('close', { id: '333' });
dialogVisible.value = false;
};
const clearAndcloseModal = () => {
emits('close', null);
dialogVisible.value = false;
};
</script>
<style scoped>
</style>
+46
View File
@@ -187,5 +187,51 @@ const checkSubmit = async (formRef: any) => {
return canSubmit;
}
interface ImodalSave {
state: any;
formRef:any;
iouField?: string;
}
export const modalSave = async (data:ImodalSave) => {
const loading = ElLoading.service({
lock: true,
fullscreen: true,
text:'',
background: 'rgba(0, 0, 0, 0.1)',
});
let isSuccess=true;
const canSubmit = await checkSubmit(data.formRef);
if (!canSubmit) {
loading.close();
return false;
}
if(!data.iouField){
data.iouField = "id";
}
if (!data.state.form[data.iouField]) {
await request({
url: data.state.url,
method: 'post',
data: data.state.form,
}).catch(() => {
isSuccess=false;
});
} else {
await request({
url: data.state.url,
method: 'put',
data: data.state.form,
}).catch(() => {
isSuccess=false;
});
}
loading.close();
if(isSuccess){
data.state.show = false;
}
};
+209
View File
@@ -0,0 +1,209 @@
<template>
<el-card class='box-card' :body-style="{padding:'2px 8px'}" shadow='never'>
<template #header>
<el-row>
<el-col :span='10'>
<div style='line-height: 32px'>代理商维护</div>
</el-col>
<el-col :span='14' style='text-align: right'>
<el-button type='success' @click='tabSave({formRef,state,proxy,route})' plain>保 存</el-button>
<el-button type='info' @click='tabClose({proxy,route})' plain>关 闭</el-button>
</el-col>
</el-row>
</template>
<div style='margin-top: 8px;margin-bottom: 8px'>
<el-form ref="formRef" class='zform' :model='form' label-width='140px'>
<el-tabs type='card' v-model='activeName'>
<el-tab-pane label='基本信息' name='tab1'>
<el-row style='border-top: 1px solid #d2d2d2;'>
<el-col :span='12'>
<el-form-item label='代理商名称:' prop='name' :rules="[{ required: true, message: '名称不能为空'}]">
<div class='zinput'>
<el-input v-model='form.name'></el-input>
</div>
</el-form-item>
</el-col>
<el-col :span='12'>
<el-form-item label='代理商编号:'>
<div class='zinput'>
<span v-show="form.id" style="margin-left: 5px;color: green">{{form.senum}}</span>
<span v-show="!form.id" style="margin-left: 5px;color: #b9abab">提交后自动生成</span>
</div>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span='12'>
<el-form-item label='代理商地址:'>
<div class='zinput'>
<el-input v-model='form.addre'></el-input>
</div>
</el-form-item>
</el-col>
<el-col :span='12'>
<el-form-item label='是否可用:'>
<div class='zinput'>
<el-switch v-model='form.avtag'>
</el-switch>
</div>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span='24'>
<el-form-item label='代理商经办人:'>
<div class='zinput'>
<el-input v-model='opmna' @click='openOrgModal' readonly></el-input>
</div>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span='24'>
<el-form-item label='可查看者:'>
<div class='zinput' style='height: auto'>
<el-input type='textarea' :rows='4' v-model='viewersName' readonly @click='openOrgsModal'>
</el-input>
</div>
</el-form-item>
</el-col>
</el-row>
</el-tab-pane>
<el-tab-pane label='其他信息' name='tab3'>
<el-row style='border-top: 1px solid #d2d2d2;'>
<el-col :span='24'>
<el-form-item label='备注:'>
<div class='zinput' style='height: auto'>
<el-input type='textarea' :rows='4' v-model='form.notes'>
</el-input>
</div>
</el-form-item>
</el-col>
</el-row>
<el-row v-show='form.crtim'>
<el-col :span='6'>
<el-form-item label='创建人:'>
<div class='zinput'>
{{ form.crman ? form.crman.name : '' }}
</div>
</el-form-item>
</el-col>
<el-col :span='6'>
<el-form-item label='创建时间:'>
<div class='zinput'>
{{ form.crtim }}
</div>
</el-form-item>
</el-col>
<el-col :span='6'>
<el-form-item label='更新人:'>
<div class='zinput'>
{{ form.upman ? form.upman.name : '' }}
</div>
</el-form-item>
</el-col>
<el-col :span='6'>
<el-form-item label='更新时间:'>
<div class='zinput'>
{{ form.uptim }}
</div>
</el-form-item>
</el-col>
</el-row>
</el-tab-pane>
</el-tabs>
</el-form>
</div>
<OrgModal ref='orgModal' @close='closeOrgModal'/>
</el-card>
</template>
<script lang='ts'>
export default {name: 'SaAgentMainEdit'};
</script>
<script lang='ts' setup>
import {computed, getCurrentInstance, onMounted, reactive, ref, toRaw, toRefs} from 'vue';
import {editInit, tabSave, tabClose} from '/@/comps/page/edit';
import {useRoute} from 'vue-router';
import OrgModal from '/@/comps/sys/OrgModal.vue';
import {FormInstance} from "element-plus";
const route = useRoute();
const formRef = ref<FormInstance>();
const {proxy} = getCurrentInstance() as any;
const activeName = ref('tab1');
const state = reactive({
url: '/sa/agent/main',
params: {path: '', query: ''}, checks: [] as any,
form: {avtag: true, items: [] as any} as any,
});
const {form} = toRefs(state);
onMounted(async () => {
await editInit({state, route});
});
//region 经办人与可查看者选择逻辑
const orgModal = ref();
const openOrgModal = () => {
orgModal.value.openModal({
opener: 'opman',
orgType: 8,
});
};
const openOrgsModal = () => {
orgModal.value.openModal({
opener: 'viewers',
orgType: 11,
selectMode: 2,
orgs: toRaw(form.value.viewers),
});
};
const closeOrgModal = (data: any) => {
if (data.opener == "opman") {
if (data.orgs && data.orgs.length > 0) {
form.value.opman = {id: data.orgs[0].id, name: data.orgs[0].name};
form.value.opmid = data.orgs[0].id;
} else {
form.value.opman = null;
form.value.opmid = null;
}
} else if (data.opener == "viewers") {
if (data.orgs && data.orgs.length > 0) {
form.value.viewers = data.orgs;
} else {
form.value.viewers = null;
}
}
};
const opmna = computed(() => {
let name = '';
if (form.value.opman) {
name = form.value.opman.name;
}
return name;
});
const viewersName = computed(() => {
let names = '';
if (form.value.viewers && form.value.viewers.length > 0) {
for (const user of form.value.viewers) {
names += user.name + ';';
}
}
return names;
});
//endregion
</script>
<style scoped>
</style>
+124
View File
@@ -0,0 +1,124 @@
<template>
<div>
<el-card class='box-card'>
<template #header>
<el-row>
<el-col :span='14'>
<el-input v-model='state.form.name' placeholder='输入名称回车查询' class='list-search' clearable @keyup.enter='listQuery(state)' />
<!-- <el-button type='primary' @click='chooseAddr()' plain>地图弹框</el-button>-->
<el-button type='primary' @click='listQuery(state)' plain v-waves='purple'>查 询</el-button>
<el-button class='more-button' :icon='state.moreParams?ArrowUp:ArrowDown' plain @click='state.moreParams=!state.moreParams' />
<span style='margin-left: 10px;color: red'>数据通过高德API拉取</span>
</el-col>
<el-col :span='10' style='text-align: right'>
<el-button type='success' :icon='Plus' @click='tabAdd(state.url)' plain>新增</el-button>
<el-button type='info' :icon='Upload' @click='listImp' plain>导入</el-button>
<el-button type='info' :icon='Download' plain @click='listExp' >导出</el-button>
<el-button type='warning' :icon='Lightning' @click='dataAsync()' plain>高德同步</el-button>
<el-button type='danger' :icon='Delete' :disabled='state.multiple' @click='listDelete(state)' plain>删除</el-button>
</el-col>
</el-row>
<div v-show='state.moreParams' class='more-params'>
<el-form :inline='true' label-width='100px'>
<el-form-item label='备注'>
<el-input v-model='state.form.notes' placeholder='输入备注' />
</el-form-item>
<el-form-item label='xxxxx'>
<el-input v-model='state.form.xx' />
</el-form-item>
<el-form-item />
</el-form>
</div>
</template>
<el-table height='400' :cell-style="{padding:'2px'}" :row-style="{height: '36px'}"
v-loading='state.loading' :data='state.list'
border stripe @selection-change='listSelect($event,state)'>
<el-table-column type='selection' width='55' align='center' />
<el-table-column label='序号' type='index' width='55' align='center' />
<el-table-column label='地址编码' width='162'>
<template #default='scope'>
<span style='cursor:pointer;color: #3e9ece' @click='chooseAddr2(scope.row.cecoo)'>
{{ scope.row.id }}
</span>
</template>
</el-table-column>
<el-table-column label='地址名称' prop='name' width='150' />
<el-table-column label='所属地区' prop='p2name' width='150' />
<el-table-column label='所属城市' prop='p3name' width='150' />
<el-table-column label='所属省份' prop='p4name' width='120' />
<el-table-column label='类型' prop='type' width='60' />
<el-table-column label='备注' prop='notes' />
<el-table-column label='创建时间' prop='crtim' width='160' />
<el-table-column label='更新时间' prop='uptim' width='160' />
</el-table>
<el-pagination
@size-change='listQuery(state)' @current-change='listQuery(state)'
class='mt8' :pager-count='5' :page-sizes='[10, 20, 30]' background
:total='state.total' v-model:current-page='state.form.page'
v-model:page-size='state.form.pageSize'
layout='total, sizes, prev, pager, next, jumper'
/>
</el-card>
<GenUpload ref='uploadModal' @close='closeOrgModal'/>
<Amap ref='amapRef' />
</div>
</template>
<script lang='ts' setup>
import { Plus, Delete, ArrowDown, ArrowUp,Upload,Download,Lightning } from '@element-plus/icons-vue';
import {onMounted, reactive, ref} from 'vue';
import { listQuery, listDelete, tabAdd, listSelect } from '/@/comps/page/index';
import request from "/@/utils/request";
import GenUpload from '/@/comps/gen/GenUpload.vue';
import Amap from '/@/comps/ass/amap.vue';
import {ElMessage} from "element-plus";
const state = reactive({
url: '/ass/addr/main', loading: true, ids: [], cates: [] as any,
form: {}, single: true, multiple: true, list: [], total: 0,
});
onMounted(() => {
listQuery(state);
});
const listExp=async ()=>{
await request({
url: state.url+"/exp",
method: 'get',
params: state.form,
responseType: "blob",
});
}
const uploadModal = ref();
const listImp = () => {
uploadModal.value.openModal();
};
const amapRef=ref();
const chooseAddr=()=>{
amapRef.value.openModal();
}
const chooseAddr2=(cecoo:string)=>{
amapRef.value.openModal({adcoo:cecoo,adreg:'',addet:'',adzoo:''});
}
const dataAsync=async ()=>{
ElMessage.warning("演示模式不支持同步操作")
// await request({
// url: state.url+"/addrupdate",
// method: 'put'
// });
}
</script>
<style scoped>
</style>
+77
View File
@@ -0,0 +1,77 @@
<template>
<el-dialog v-model='state.show' title='字典值编辑' draggable width='500px' :before-close='handleClose'>
<el-form ref='formRef' :model='form' label-width='120px'>
<el-form-item label='字典值编码:' prop='code' :rules="[{ required: true, message: '编码不能为空'}]">
<el-input v-model='form.code'></el-input>
</el-form-item>
<el-form-item label='字典值名称:' prop='name' :rules="[{ required: true, message: '名称不能为空'}]">
<el-input v-model='form.name'></el-input>
</el-form-item>
<el-form-item label='排序号:' prop='ornum'>
<el-input-number v-model='form.ornum' controls-position='right' style='width: 100%'/>
</el-form-item>
<el-form-item label='是否可用:' prop='avtag'>
<el-switch v-model='form.avtag'>
</el-switch>
</el-form-item>
<el-form-item label='备注:' prop='notes'>
<el-input type='textarea' :rows='4' v-model='form.notes'>
</el-input>
</el-form-item>
</el-form>
<template #footer>
<span class='dialog-footer'>
<el-button type='primary' @click='handleConfirm'>确 认</el-button>
<el-button @click='state.show = false'>取 消</el-button>
</span>
</template>
</el-dialog>
</template>
<script lang='ts' setup>
import {defineExpose,reactive, ref, toRefs} from 'vue';
import {modalSave} from '/@/comps/page/edit';
import request from "/@/utils/request";
import {ElMessage} from "element-plus";
const state = reactive({
url: '/ass/dict/data', show: false,
form: {avtag: true} as any,
});
const {form} = toRefs(state);
const formRef = ref();
const openModal = async (data: any) => {
if (data && data.id) {
state.form = await request({
url: state.url + '/one/' + data.id,
method: 'get',
});
} else if(data && data.maiid) {
state.form = {avtag: true,maiid:data.maiid};
if(formRef.value){
formRef.value.resetFields();
}
}else{
ElMessage.warning("请先选择字典后维护字典值");
return;
}
state.show = true;
};
defineExpose({openModal});
const emits = defineEmits(['close']);
const handleConfirm = async () => {
await modalSave({formRef: formRef.value, state});
emits('close');
};
</script>
<style scoped>
</style>
+91
View File
@@ -0,0 +1,91 @@
<template>
<div>
<el-card class='box-card'>
<template #header>
<el-row>
<el-col :span='14'>
<el-select v-model='state.form.maiid' @change="listQuery(state)" filterable clearable placeholder='字典名称' style='margin-right:10px;width: 180px'>
<el-option
v-for='item in state.dicts'
:key='item.id'
:label='item.name'
:value='item.id'
/>
</el-select>
<el-input v-model='state.form.name' placeholder='字典值编码/名称' class='list-search' style='width: 180px' clearable @keyup.enter='listQuery(state)' />
<el-button type='primary' @click='listQuery(state)' plain>查 询</el-button>
</el-col>
<el-col :span='10' style='text-align: right'>
<el-button type='success' :icon='Plus' @click='editRef.openModal({maiid:state.form.maiid})' plain>新增</el-button>
<el-button type='danger' :icon='Delete' :disabled='state.multiple' @click='listDelete(state)' plain>删除</el-button>
</el-col>
</el-row>
</template>
<el-table height='400' :cell-style="{padding:'2px'}" :row-style="{height: '36px'}"
v-loading='state.loading' :data='state.list'
border stripe @selection-change='listSelect($event,state)'>
<el-table-column type='selection' width='55' align='center' />
<el-table-column label='序号' type='index' width='55' align='center' />
<el-table-column label='字典值编码' width='180'>
<template #default='scope'>
<span style='cursor:pointer;color: #3e9ece' @click='editRef.openModal({id:scope.row.id})'>
{{ scope.row.code }}
</span>
</template>
</el-table-column>
<el-table-column label='字典值名称' prop='name' width='160' />
<el-table-column label='字典值排序' prop='ornum' width='160' />
<el-table-column label='创建时间' prop='crtim' width='160' />
<el-table-column label='更新时间' prop='uptim' width='160' />
<el-table-column label='备注' prop='notes' />
</el-table>
<el-pagination
@size-change='listQuery(state)' @current-change='listQuery(state)'
class='mt8' :pager-count='5' :page-sizes='[10, 20, 30]' background
:total='state.total' v-model:current-page='state.form.page'
v-model:page-size='state.form.pageSize'
layout='total, sizes, prev, pager, next, jumper'
/>
</el-card>
<Edit ref="editRef" @close="listQuery(state)"/>
</div>
</template>
<script lang='ts' setup>
import { Plus, Delete } from '@element-plus/icons-vue';
import {onMounted, reactive, ref} from 'vue';
import { listQuery, listDelete, listSelect } from '/@/comps/page/index';
import Edit from './edit.vue';
import request from "/@/utils/request";
import {useRoute} from "vue-router";
const route = useRoute();
const editRef = ref() as any;
const state = reactive({
url: '/ass/dict/data', loading: true, ids: [], dicts: [] as any,
form: {} as any, single: true, multiple: true, list: [], total: 0,
});
onMounted(() => {
state.form.maiid=route.query?.maiid;
listQuery(state);
dictsInit();
});
const dictsInit = async () => {
state.dicts = await request({
url: '/ass/dict/main/list',
method: 'get',
});
};
</script>
<style scoped>
</style>
+74
View File
@@ -0,0 +1,74 @@
<template>
<el-dialog v-model='state.show' title='字典编辑' draggable width='500px' :before-close='handleClose'>
<el-form ref='formRef' :model='form' label-width='120px'>
<el-form-item label='字典类型:' prop='id' :rules="[{ required: true, message: '类型不能为空'}]">
<el-input v-model='form.id' placeholder="字母编码" :disabled='form.crtim?true:false'></el-input>
</el-form-item>
<el-form-item label='字典名称:' prop='name' :rules="[{ required: true, message: '名称不能为空'}]">
<el-input v-model='form.name'></el-input>
</el-form-item>
<el-form-item label='排序号:' prop='ornum'>
<el-input-number v-model='form.ornum' controls-position='right' style='width: 100%'/>
</el-form-item>
<el-form-item label='是否可用:' prop='avtag'>
<el-switch v-model='form.avtag'>
</el-switch>
</el-form-item>
<el-form-item label='备注:' prop='notes'>
<el-input type='textarea' :rows='4' v-model='form.notes'>
</el-input>
</el-form-item>
</el-form>
<template #footer>
<span class='dialog-footer'>
<el-button type='primary' @click='handleConfirm'>确 认</el-button>
<el-button @click='state.show = false'>取 消</el-button>
</span>
</template>
</el-dialog>
</template>
<script lang='ts' setup>
import {defineExpose, reactive, ref, toRefs} from 'vue';
import {modalSave} from '/@/comps/page/edit';
import request from "/@/utils/request";
const state = reactive({
url: '/ass/dict/main', show: false,
form: {avtag: true} as any,
});
const {form} = toRefs(state);
const formRef = ref();
const openModal = async (data: any) => {
if (data && data.id) {
state.form = await request({
url: state.url + '/one/' + data.id,
method: 'get',
});
} else {
state.form = {avtag: true};
// formRef.value.clearValidate();
if(formRef.value){
formRef.value.resetFields();
}
}
state.show = true;
};
defineExpose({openModal});
const emits = defineEmits(['close']);
const handleConfirm = async () => {
await modalSave({formRef: formRef.value, state, iouField: "crtim"});
emits('close');
};
</script>
<style scoped>
</style>
+97
View File
@@ -0,0 +1,97 @@
<template>
<div>
<el-card class='box-card'>
<template #header>
<el-row>
<el-col :span='14'>
<el-input v-model='state.form.name' placeholder='字典编码/名称(回车可查询)' class='list-search' clearable @keyup.enter='listQuery(state)'/>
<el-button type='primary' @click='listQuery(state)' plain>查 询</el-button>
<el-button class='more-button' :icon='state.moreParams?ArrowUp:ArrowDown' plain @click='state.moreParams=!state.moreParams'/>
<span style='margin-left: 10px;color: red'>数据字典主要服务于业务表单下拉框</span>
</el-col>
<el-col :span='10' style='text-align: right'>
<el-button type='success' :icon='Plus' @click='editRef.openModal()' plain>新增</el-button>
<el-button type='danger' :icon='Delete' :disabled='state.multiple' @click='listDelete(state)' plain>删除</el-button>
</el-col>
</el-row>
<div v-show='state.moreParams' class='more-params'>
<el-form :inline='true' label-width='100px'>
<el-form-item label='更多参数1'>
<el-input v-model='state.form.notes' placeholder='更多参数1'/>
</el-form-item>
<el-form-item label='更多参数2'>
<el-input v-model='state.form.xx' placeholder='更多参数2'/>
</el-form-item>
<el-form-item/>
</el-form>
</div>
</template>
<el-table height='400' :cell-style="{padding:'2px'}" :row-style="{height: '36px'}"
v-loading='state.loading' :data='state.list'
border stripe @selection-change='listSelect($event,state)'>
<el-table-column type='selection' width='55' align='center'/>
<el-table-column label='序号' type='index' width='55' align='center'/>
<el-table-column label='字典编码' prop='id' width='160'>
<template #default='scope'>
<span style='cursor:pointer;color: #3e9ece' @click='configData(scope.row.id)'>
{{ scope.row.id }}
</span>
</template>
</el-table-column>
<el-table-column label='字典名称' prop='name' width='180'/>
<el-table-column label='创建时间' prop='crtim' width='160'/>
<el-table-column label='更新时间' prop='uptim' width='160'/>
<el-table-column label='备注' prop='notes'/>
<el-table-column label='操作' prop='notes' width='46' align='center'>
<template #default='scope'>
<el-icon :size='18' style='top:3px;color: #972fcb;cursor: pointer' @click='editRef.openModal({id:scope.row.id})' title="修改">
<Edit/>
</el-icon>
</template>
</el-table-column>
</el-table>
<el-pagination
@size-change='listQuery(state)' @current-change='listQuery(state)'
class='mt8' :pager-count='5' :page-sizes='[10, 20, 30]' background
:total='state.total' v-model:current-page='state.form.page'
v-model:page-size='state.form.pageSize'
layout='total, sizes, prev, pager, next, jumper'
/>
</el-card>
<DictEdit ref="editRef" @close="listQuery(state)"/>
</div>
</template>
<script lang='ts' setup>
import {Plus, Delete, ArrowDown, ArrowUp,Edit } from '@element-plus/icons-vue';
import {onMounted, reactive, ref} from 'vue';
import {listQuery, listDelete, listSelect} from '/@/comps/page/index';
import router from "/@/router";
import DictEdit from './edit.vue';
const editRef = ref() as any;
const state = reactive({
url: '/ass/dict/main', loading: true, ids: [], cates: [] as any,
form: {}, single: true, multiple: true, list: [], total: 0,
});
onMounted(() => {
listQuery(state);
});
const configData = async (rowid: string) => {
await router.push({
path: '/ass/dict/data',
query: {maiid: rowid},
});
}
</script>
<style scoped>
</style>
+92
View File
@@ -0,0 +1,92 @@
<template>
<el-dialog v-model='state.show' title='编号策略配置' draggable width='500px'>
<el-form ref='formRef' :model='form' label-width='120px'>
<el-form-item label='策略代码:' prop='id' :rules="[{ required: true, message: '策略代码不能为空'}]">
<el-input v-model='form.id' placeholder="字母编码" :disabled='form.crtim?true:false'></el-input>
</el-form-item>
<el-form-item label='策略名称:' prop='name' :rules="[{ required: true, message: '策略名称不能为空'}]">
<el-input v-model='form.name'></el-input>
</el-form-item>
<el-form-item label='编号生成模式:' prop='numod'>
<el-select v-model='form.numod' placeholder='请选择' style='width: 100%'>
<el-option :value="'nodate'" :label="'无日期,纯流水号'"></el-option>
<el-option :value="'yyyymmdd'" :label="'年月日YYYYMMDD+流水号'"></el-option>
<el-option :value="'yymmdd'" :label="'年月日YYMMDD+流水号'"></el-option>
<el-option :value="'yyyymm'" :label="'年月YYYYMM+流水号'"></el-option>
<el-option :value="'yymm'" :label="'年月YYMM+流水号'"></el-option>
<el-option :value="'yy'" :label="'年YY+流水号'"></el-option>
</el-select>
</el-form-item>
<el-form-item label='编号前缀:' prop='nupre'>
<el-input v-model='form.nupre'></el-input>
</el-form-item>
<el-form-item label='编号长度:' prop='nulen'>
<el-input-number v-model='form.nulen' controls-position='right' style='width: 100%'/>
</el-form-item>
<el-form-item label='下一个编号:' prop='nunex'>
<el-input v-model='form.nunex'></el-input>
</el-form-item>
<el-form-item label='是否可用:' prop='avtag'>
<el-switch v-model='form.avtag'>
</el-switch>
</el-form-item>
<el-form-item label='排序号:' prop='ornum'>
<el-input-number v-model='form.ornum' controls-position='right' style='width: 100%'/>
</el-form-item>
<el-form-item label='备注:' prop='notes'>
<el-input v-model='form.notes'></el-input>
</el-form-item>
</el-form>
<template #footer>
<span class='dialog-footer'>
<el-button type='primary' @click='handleConfirm'>确 认</el-button>
<el-button @click='state.show = false'>取 消</el-button>
</span>
</template>
</el-dialog>
</template>
<script lang='ts' setup>
import {defineExpose, reactive, ref, toRefs} from 'vue';
import {modalSave} from '/@/comps/page/edit';
import request from "/@/utils/request";
const state = reactive({
url: '/ass/num/main', show: false,
form: {avtag: true} as any,
});
const {form} = toRefs(state);
const formRef = ref();
const openModal = async (data: any) => {
if (data && data.id) {
state.form = await request({
url: state.url + '/one/' + data.id,
method: 'get',
});
} else {
state.form = {avtag: true};
// formRef.value.clearValidate();
if (formRef.value) {
formRef.value.resetFields();
}
}
state.show = true;
};
defineExpose({openModal});
const emits = defineEmits(['close']);
const handleConfirm = async () => {
await modalSave({formRef: formRef.value, state, iouField: "crtim"});
emits('close');
};
</script>
<style scoped>
</style>
+83
View File
@@ -0,0 +1,83 @@
<template>
<div>
<el-card class='box-card'>
<template #header>
<el-row>
<el-col :span='14'>
<el-input v-model='state.form.name' placeholder='输入名称回车查询' class='list-search' clearable @keyup.enter='listQuery(state)'/>
<el-button type='primary' @click='listQuery(state)' plain>查 询</el-button>
<el-button class='more-button' :icon='state.moreParams?ArrowUp:ArrowDown' plain @click='state.moreParams=!state.moreParams'/>
<span style='margin-left: 10px;color: red'>编号策略主要服务于业务模块主数据流水号</span>
</el-col>
<el-col :span='10' style='text-align: right'>
<el-button type='success' :icon='Plus' @click='editRef.openModal()' plain>新增</el-button>
<el-button type='danger' :icon='Delete' :disabled='state.multiple' @click='listDelete(state)' plain>删除</el-button>
</el-col>
</el-row>
<div v-show='state.moreParams' class='more-params'>
<el-form :inline='true' label-width='100px'>
<el-form-item label='更多参数1'>
<el-input v-model='state.form.notes' placeholder='更多参数1'/>
</el-form-item>
<el-form-item label='更多参数2'>
<el-input v-model='state.form.xx' placeholder='更多参数2'/>
</el-form-item>
<el-form-item/>
</el-form>
</div>
</template>
<el-table height='400' :cell-style="{padding:'2px'}" :row-style="{height: '36px'}"
v-loading='state.loading' :data='state.list'
border stripe @selection-change='listSelect($event,state)'>
<el-table-column type='selection' width='55' align='center'/>
<el-table-column label='序号' type='index' width='55' align='center'/>
<el-table-column label='编号策略代码' prop='id' width='160'>
<template #default='scope'>
<span style='cursor:pointer;color: #3e9ece' @click='editRef.openModal({id:scope.row.id})'>
{{ scope.row.id }}
</span>
</template>
</el-table-column>
<el-table-column label='编号策略名称' prop='name' width='180'/>
<el-table-column label='前缀' prop='nupre' width='160'/>
<el-table-column label='生成模式' prop='numod' width='160'/>
<el-table-column label='下一个编号' prop='nunex' width='160'/>
<el-table-column label='备注' prop='notes'/>
</el-table>
<el-pagination
@size-change='listQuery(state)' @current-change='listQuery(state)'
class='mt8' :pager-count='5' :page-sizes='[10, 20, 30]' background
:total='state.total' v-model:current-page='state.form.page'
v-model:page-size='state.form.pageSize'
layout='total, sizes, prev, pager, next, jumper'
/>
</el-card>
<Edit ref="editRef" @close="listQuery(state)"/>
</div>
</template>
<script lang='ts' setup>
import {Plus, Delete, ArrowDown, ArrowUp} from '@element-plus/icons-vue';
import {onMounted, reactive, ref} from 'vue';
import {listQuery, listDelete, listSelect} from '/@/comps/page/index';
import Edit from './edit.vue';
const editRef = ref() as any;
const state = reactive({
url: '/ass/num/main', loading: true, ids: [], cates: [] as any,
form: {}, single: true, multiple: true, list: [], total: 0,
});
onMounted(() => {
listQuery(state);
});
</script>
<style scoped>
</style>
+47 -6
View File
@@ -16,27 +16,36 @@
<el-tabs type='card' v-model='activeName'>
<el-tab-pane label='基本信息' name='tab1'>
<el-row style='border-top: 1px solid #d2d2d2;'>
<el-col :span='24'>
<el-col :span='12'>
<el-form-item label='代理商名称:' prop='name' :rules="[{ required: true, message: '名称不能为空'}]">
<div class='zinput'>
<el-input v-model='form.name'></el-input>
</div>
</el-form-item>
</el-col>
<el-col :span='12'>
<el-form-item label='代理商编号:'>
<div class='zinput'>
<span v-show="form.id" style="margin-left: 5px;color: green">{{form.senum}}</span>
<span v-show="!form.id" style="margin-left: 5px;color: #b9abab">提交后自动生成</span>
</div>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span='12'>
<el-form-item label='代理商地址:'>
<div class='zinput'>
<el-input v-model='form.addre'></el-input>
<el-input v-model='form.addre' readonly @click="chooseAddr"></el-input>
</div>
</el-form-item>
</el-col>
<el-col :span='12'>
<el-form-item label='是否可用:'>
<el-form-item label='代理商资质:'>
<div class='zinput'>
<el-switch v-model='form.avtag'>
</el-switch>
<el-select v-model='form.level' placeholder='请选择' style="width: 100%">
<el-option v-for='item in state.levels' :key='item.id' :value='item.id' :label="item.name"/>
</el-select>
</div>
</el-form-item>
</el-col>
@@ -107,6 +116,7 @@
</el-form>
</div>
<OrgModal ref='orgModal' @close='closeOrgModal'/>
<Amap ref='amapRef' @close='closeAmap'/>
</el-card>
</template>
<script lang='ts'>
@@ -117,7 +127,9 @@ import {computed, getCurrentInstance, onMounted, reactive, ref, toRaw, toRefs} f
import {editInit, tabSave, tabClose} from '/@/comps/page/edit';
import {useRoute} from 'vue-router';
import OrgModal from '/@/comps/sys/OrgModal.vue';
import Amap from '/@/comps/ass/amap.vue';
import {FormInstance} from "element-plus";
import request from "/@/utils/request";
const route = useRoute();
const formRef = ref<FormInstance>();
@@ -126,7 +138,7 @@ const activeName = ref('tab1');
const state = reactive({
url: '/sa/agent/main',
params: {path: '', query: ''}, checks: [] as any,
params: {path: '', query: ''}, levels:[] as any,
form: {avtag: true, items: [] as any} as any,
});
@@ -135,6 +147,7 @@ const {form} = toRefs(state);
onMounted(async () => {
await editInit({state, route});
await levelsInit();
});
@@ -194,6 +207,34 @@ const viewersName = computed(() => {
});
//endregion
//region 地址选择逻辑
const amapRef=ref();
const chooseAddr=()=>{
amapRef.value.openModal({adcoo:form.value.adcoo,adreg:form.value.adreg,addet:form.value.addet,adzoo:''});
}
const closeAmap=(data:any)=>{
if(data){
form.value.addre=data.adreg+data.addet;
form.value.adcoo=data.adcoo;
form.value.adreg=data.adreg;
form.value.addet=data.addet;
form.value.adpro=data.adpro;
form.value.adcit=data.adcit;
form.value.addis=data.addis;
}
}
//endregion
//region 业务字典逻辑
const levelsInit = async () => {
state.levels = await request({
url: '/ass/dict/data/list?maiid=AG_LEVEL',
method: 'get',
});
};
//endregion
</script>
<style scoped>
+31 -6
View File
@@ -10,6 +10,8 @@
</el-col>
<el-col :span='10' style='text-align: right'>
<el-button type='success' :icon='Plus' @click='tabAdd(state.url)' plain>新增</el-button>
<el-button type='info' :icon='Upload' @click='listImp' plain>导入</el-button>
<el-button type='info' :icon='Download' plain @click='listExp' >导出</el-button>
<el-button type='danger' :icon='Delete' :disabled='state.multiple' @click='listDelete(state)' plain>删除</el-button>
</el-col>
</el-row>
@@ -31,16 +33,19 @@
border stripe @selection-change='listSelect($event,state)'>
<el-table-column type='selection' width='55' align='center' />
<el-table-column label='序号' type='index' width='55' align='center' />
<el-table-column label='代理商名称' width='180'>
<el-table-column label='代理商编号' width='126'>
<template #default='scope'>
<span style='cursor:pointer;color: #3e9ece' @click='tabEdit(state.url,scope.row.id)'>
{{ scope.row.name }}
{{ scope.row.senum }}
</span>
</template>
</el-table-column>
<el-table-column label='代理商名称' prop='name' width='250' />
<el-table-column label='代理商地址' prop='addre' />
<el-table-column label='创建时间' prop='crtim' width='160' />
<el-table-column label='更新时间' prop='uptim' width='160' />
<el-table-column label='创建时间' prop='crtim' width='150' />
<el-table-column label='创建人' prop='crman' width='60' />
<el-table-column label='更新时间' prop='uptim' width='150' />
<el-table-column label='更新人' prop='crman' width='60' />
</el-table>
<el-pagination
@@ -51,13 +56,16 @@
layout='total, sizes, prev, pager, next, jumper'
/>
</el-card>
<GenUpload ref='uploadModal' @close='closeOrgModal'/>
</div>
</template>
<script lang='ts' setup>
import { Plus, Delete, ArrowDown, ArrowUp } from '@element-plus/icons-vue';
import { onMounted, reactive } from 'vue';
import { Plus, Delete, ArrowDown, ArrowUp,Upload,Download } from '@element-plus/icons-vue';
import {onMounted, reactive, ref} from 'vue';
import { listQuery, listDelete, tabAdd, tabEdit, listSelect } from '/@/comps/page/index';
import request from "/@/utils/request";
import GenUpload from '/@/comps/gen/GenUpload.vue';
const state = reactive({
url: '/sa/agent/main', loading: true, ids: [], cates: [] as any,
@@ -68,6 +76,23 @@ onMounted(() => {
listQuery(state);
});
const listExp=async ()=>{
await request({
url: state.url+"/exp",
method: 'get',
params: state.form,
responseType: "blob",
});
}
const uploadModal = ref();
const listImp = () => {
uploadModal.value.openModal();
};
</script>
<style scoped>
+1 -1
View File
@@ -6,7 +6,7 @@
</template>
<template #default>
<div style='padding: 20px;border-top: 1px solid #ccc'>
<el-form ref='ruleFormRef' :model='form' label-width='160px'>
<el-form ref='formRef' :model='form' label-width='160px'>
<el-row style='height: 48px'>
<el-col :span='12'>
<el-form-item label='任务名称:'>
+1 -1
View File
@@ -4,7 +4,7 @@
<template #header>
<el-row>
<el-col :span='14'>
<el-select v-model='state.form.porid' clearable placeholder='门户名称' @change="treeQuery(state)" style='margin-right:10px;width: 180px'>
<el-select v-model='state.form.porid' placeholder='门户名称' @change="treeQuery(state)" style='margin-right:10px;width: 180px'>
<el-option
v-for='item in state.portals'
:key='item.id'
+78
View File
@@ -496,6 +496,84 @@ export const dynamicRoutes: Array<RouteRecordRaw> = [
},
],
},
{
path: '/ass',
name: 'Ass',
component: () => import('/@/layout/routerView/parent.vue'),
redirect: '/ass/dict/main',
meta: {
title: '辅助工具',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
roles: ['admin'],
icon: 'ele-Help',
},
children: [
{
path: '/ass/dict/main',
name: 'AssDictMain',
component: () => import('/@/pages/ass/dict/main/index.vue'),
meta: {
title: '数据字典',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
roles: ['admin'],
icon: 'ele-Tickets',
},
},
{
path: '/ass/dict/data',
name: 'AssDictData',
component: () => import('/@/pages/ass/dict/data/index.vue'),
meta: {
title: '字典配置',
isLink: '',
isHide: true,
isKeepAlive: true,
isAffix: false,
isIframe: false,
roles: ['admin'],
icon: 'ele-Tickets',
},
},
{
path: '/ass/num/main',
name: 'AssNumMain',
component: () => import('/@/pages/ass/num/main/index.vue'),
meta: {
title: '编号策略',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
roles: ['admin'],
icon: 'ele-Tickets',
},
},
{
path: '/ass/addr/main',
name: 'AssAddrMain',
component: () => import('/@/pages/ass/addr/main/index.vue'),
meta: {
title: '省市区县',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
roles: ['admin'],
icon: 'ele-Tickets',
},
},
],
},
{
path: '/oa',
name: 'Oa',
+11
View File
@@ -142,3 +142,14 @@ color: red;border: 1px dashed red;margin-top: 10px;margin-bottom: 10px;padding:
//{
// background-color: #0960bd !important;
//}
.amap-dialog .el-overlay .el-overlay-dialog .el-dialog .el-dialog__body{
padding: 0 !important;
}
.amap-dialog .el-dialog__header {
margin: 10px;
padding: 0;
}
.amap-dialog .el-dialog__headerbtn{
top:0;
}
+16 -1
View File
@@ -1,6 +1,7 @@
import axios from 'axios';
import { ElMessage, ElMessageBox } from 'element-plus';
import { Session } from '/@/utils/storage';
import { saveAs } from 'file-saver';
// 配置新建一个 axios 实例
const service = axios.create({
@@ -46,7 +47,21 @@ service.interceptors.response.use(
}
return Promise.reject(service.interceptors.response);
} else {
return response.data.result;
// console.log(response);
if(response.data.size){
let blob = new Blob([res], { type: "application/xlsx" });
let filename=decodeURI(response.headers['download-filename']);
// let filename=decodeURI(response.headers['FileDownloadName']);
saveAs(blob, filename)
// let url = window.URL.createObjectURL(blob);
// const link = document.createElement("a"); // 创建a标签
// link.href = url;
// link.download = decodeURI(response.headers['download-filename']); // 重命名文件
// link.click();
// URL.revokeObjectURL(url);
}else{
return response.data.result;
}
}
},
(error) => {