重构租户管理城市数据处理逻辑,支持直辖市特殊处理
This commit is contained in:
3
src/types/file-saver.d.ts
vendored
Normal file
3
src/types/file-saver.d.ts
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
declare module 'file-saver' {
|
||||||
|
export function saveAs(data: Blob | string, filename?: string, options?: object): void;
|
||||||
|
}
|
||||||
@@ -11,9 +11,7 @@
|
|||||||
ref="uploadRef"
|
ref="uploadRef"
|
||||||
class="upload-demo"
|
class="upload-demo"
|
||||||
drag
|
drag
|
||||||
:action="uploadAction"
|
action="#"
|
||||||
:headers="uploadHeaders"
|
|
||||||
:data="uploadData"
|
|
||||||
:accept="acceptFileTypes"
|
:accept="acceptFileTypes"
|
||||||
:limit="1"
|
:limit="1"
|
||||||
:on-success="handleUploadSuccess"
|
:on-success="handleUploadSuccess"
|
||||||
@@ -84,7 +82,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref, reactive, nextTick, watch, computed } from 'vue';
|
import { ref, reactive, nextTick, computed } from 'vue';
|
||||||
import { ElMessage, ElMessageBox, type UploadInstance, type UploadFile, type UploadFiles } from 'element-plus';
|
import { ElMessage, ElMessageBox, type UploadInstance, type UploadFile, type UploadFiles } from 'element-plus';
|
||||||
import { UploadFilled, Download } from '@element-plus/icons-vue';
|
import { UploadFilled, Download } from '@element-plus/icons-vue';
|
||||||
import JSZip from 'jszip';
|
import JSZip from 'jszip';
|
||||||
@@ -107,11 +105,6 @@ const currentFile = ref<File | null>(null);
|
|||||||
const fileList = ref<UploadFile[]>([]);
|
const fileList = ref<UploadFile[]>([]);
|
||||||
|
|
||||||
// 上传配置
|
// 上传配置
|
||||||
const uploadAction = '/customerService/product/import';
|
|
||||||
const uploadHeaders = reactive({
|
|
||||||
Authorization: `Bearer ${localStorage.getItem('token') || ''}`,
|
|
||||||
});
|
|
||||||
const uploadData = reactive({});
|
|
||||||
const acceptFileTypes = '.zip,.ZIP';
|
const acceptFileTypes = '.zip,.ZIP';
|
||||||
const fileSizeLimit = 50;
|
const fileSizeLimit = 50;
|
||||||
|
|
||||||
@@ -126,13 +119,15 @@ const hasFile = computed(() => fileList.value.length > 0);
|
|||||||
* 处理文件变化事件 - 修复版本
|
* 处理文件变化事件 - 修复版本
|
||||||
*/
|
*/
|
||||||
const handleFileChange = (file: UploadFile, files: UploadFile[]) => {
|
const handleFileChange = (file: UploadFile, files: UploadFile[]) => {
|
||||||
console.log('文件变化事件:', file.status, files.length);
|
// 更新文件列表,保持单选
|
||||||
|
if (files.length > 1) {
|
||||||
// 更新文件列表
|
fileList.value = [files[files.length - 1]];
|
||||||
fileList.value = files;
|
} else {
|
||||||
|
fileList.value = files;
|
||||||
|
}
|
||||||
|
|
||||||
if (file.status === 'ready') {
|
if (file.status === 'ready') {
|
||||||
currentFile.value = file.raw;
|
currentFile.value = file.raw!;
|
||||||
ElMessage.success('文件已选择,可以开始导入');
|
ElMessage.success('文件已选择,可以开始导入');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -144,7 +139,6 @@ const handleRemove = (file: UploadFile, files: UploadFile[]) => {
|
|||||||
fileList.value = files;
|
fileList.value = files;
|
||||||
currentFile.value = null;
|
currentFile.value = null;
|
||||||
importResult.value = null;
|
importResult.value = null;
|
||||||
ElMessage.info('文件已移除');
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ import { addScript, updateScript } from '/@/api/customerService/script';
|
|||||||
|
|
||||||
// 定义类型接口
|
// 定义类型接口
|
||||||
interface DialogRow {
|
interface DialogRow {
|
||||||
id: number;
|
id?: number | string;
|
||||||
tag: string;
|
tag: string;
|
||||||
creator: string;
|
creator: string;
|
||||||
content: string;
|
content: string;
|
||||||
|
|||||||
@@ -216,7 +216,7 @@ const handleAdd = () => {
|
|||||||
* 编辑话术
|
* 编辑话术
|
||||||
*/
|
*/
|
||||||
const handleEdit = (row: ScriptItem) => {
|
const handleEdit = (row: ScriptItem) => {
|
||||||
editRoleRef.value?.openDialog(row);
|
editRoleRef.value?.openDialog(row as any);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ import { reactive, ref, unref, computed, toRefs } from 'vue';
|
|||||||
import { ElMessage, UploadProps } from 'element-plus';
|
import { ElMessage, UploadProps } from 'element-plus';
|
||||||
import { Plus } from '@element-plus/icons-vue';
|
import { Plus } from '@element-plus/icons-vue';
|
||||||
import { addTenant, editTenant } from '/@/api/system/tenant';
|
import { addTenant, editTenant } from '/@/api/system/tenant';
|
||||||
import { pcTextArr } from 'element-china-area-data';
|
import { pcTextArr,provinceAndCityData } from 'element-china-area-data';
|
||||||
|
|
||||||
// 定义父组件传递的事件
|
// 定义父组件传递的事件
|
||||||
const emit = defineEmits(['getTenantList']);
|
const emit = defineEmits(['getTenantList']);
|
||||||
@@ -115,7 +115,19 @@ const emit = defineEmits(['getTenantList']);
|
|||||||
const formRef = ref<HTMLElement | null>(null);
|
const formRef = ref<HTMLElement | null>(null);
|
||||||
|
|
||||||
// 省市数据(使用 element-china-area-data)
|
// 省市数据(使用 element-china-area-data)
|
||||||
const cityOptions = pcTextArr;
|
const cityOptions = ref<any[]>([]);
|
||||||
|
|
||||||
|
const initCityData = () => {
|
||||||
|
const data = JSON.parse(JSON.stringify(provinceAndCityData));
|
||||||
|
cityOptions.value = data.map((item: any) => {
|
||||||
|
// 处理直辖市:北京(110000), 天津(120000), 上海(310000), 重庆(500000)
|
||||||
|
if (['110000', '120000', '310000', '500000'].includes(item.value) || ['北京市', '天津市', '上海市', '重庆市'].includes(item.label)) {
|
||||||
|
delete item.children;
|
||||||
|
}
|
||||||
|
return item;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
initCityData();
|
||||||
|
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
isShowDialog: false,
|
isShowDialog: false,
|
||||||
@@ -196,13 +208,39 @@ const passwordStrengthClass = computed(() => {
|
|||||||
const openDialog = (row?: any) => {
|
const openDialog = (row?: any) => {
|
||||||
resetForm();
|
resetForm();
|
||||||
if (row) {
|
if (row) {
|
||||||
|
// 处理城市回显:如果是字符串且以00结尾,去掉00并转为数组(这里简化处理,实际可能需要根据code反查路径)
|
||||||
|
// 假设 row.city 是 "110100",element-china-area-data 的 provinceAndCityData 对应的是 "110000", "110100"
|
||||||
|
// 注意:provinceAndCityData 的二级(市)code 通常不带后缀 00,或者需要具体看数据源
|
||||||
|
// 这里假设后端存的是 "110100",前端组件需要 ["110000", "110100"] 形式的路径数组
|
||||||
|
// 由于没有反查函数,这里如果 row.city 是字符串,我们暂时将其直接放入数组,或者需要调用专门的工具函数
|
||||||
|
// 简单处理:如果 row.city 是字符串,尝试回显
|
||||||
|
let cityArray: string[] = [];
|
||||||
|
if (row.city && typeof row.city === 'string') {
|
||||||
|
const storedCode = row.city;
|
||||||
|
// 判断是否为直辖市代码 (11xxxx, 12xxxx, 31xxxx, 50xxxx)
|
||||||
|
if (/^(11|12|31|50)/.test(storedCode)) {
|
||||||
|
// 直辖市,回显为 [2位代码] (如 '11')
|
||||||
|
cityArray = [storedCode.substring(0, 2)];
|
||||||
|
} else {
|
||||||
|
// 普通省市,回显为 [2位省代码, 4位市代码] (如 '13', '1301')
|
||||||
|
// 假设 storedCode 是 6 位,如 130100
|
||||||
|
if (storedCode.length >= 4) {
|
||||||
|
const provinceCode = storedCode.substring(0, 2);
|
||||||
|
const cityCode = storedCode.substring(0, 4);
|
||||||
|
cityArray = [provinceCode, cityCode];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (Array.isArray(row.city)) {
|
||||||
|
cityArray = row.city;
|
||||||
|
}
|
||||||
|
|
||||||
state.ruleForm = {
|
state.ruleForm = {
|
||||||
id: row.id,
|
id: row.id,
|
||||||
tenantName: row.tenantName,
|
tenantName: row.tenantName,
|
||||||
tenantType: row.tenantType,
|
tenantType: row.tenantType,
|
||||||
contactPerson: row.contactPerson,
|
contactPerson: row.contactPerson,
|
||||||
phone: row.phone,
|
phone: row.phone,
|
||||||
city: row.city || [],
|
city: cityArray,
|
||||||
tenantAccount: row.tenantAccount,
|
tenantAccount: row.tenantAccount,
|
||||||
password: '', // 修改时不显示密码
|
password: '', // 修改时不显示密码
|
||||||
confirmPassword: '',
|
confirmPassword: '',
|
||||||
@@ -225,8 +263,30 @@ const onSubmit = () => {
|
|||||||
if (!formWrap) return;
|
if (!formWrap) return;
|
||||||
formWrap.validate((valid: boolean) => {
|
formWrap.validate((valid: boolean) => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
|
// 处理城市数据提交:取数组最后一位
|
||||||
|
const submitForm: any = { ...state.ruleForm };
|
||||||
|
if (Array.isArray(submitForm.city) && submitForm.city.length > 0) {
|
||||||
|
let lastCode = String(submitForm.city[submitForm.city.length - 1]);
|
||||||
|
// 特殊处理直辖市:如果选中的是省级代码,转换为市级代码 (市辖区)
|
||||||
|
const municipalityMap: Record<string, string> = {
|
||||||
|
'11': '110100', '110000': '110100', // 北京
|
||||||
|
'12': '120100', '120000': '120100', // 天津
|
||||||
|
'31': '310100', '310000': '310100', // 上海
|
||||||
|
'50': '500100', '500000': '500100', // 重庆
|
||||||
|
};
|
||||||
|
if (municipalityMap[lastCode]) {
|
||||||
|
lastCode = municipalityMap[lastCode];
|
||||||
|
} else if (lastCode.length === 4) {
|
||||||
|
// 普通省市,如果是4位代码,补齐为6位
|
||||||
|
lastCode = lastCode + '00';
|
||||||
|
}
|
||||||
|
submitForm.city = lastCode;
|
||||||
|
} else {
|
||||||
|
submitForm.city = '';
|
||||||
|
}
|
||||||
|
|
||||||
if (state.ruleForm.id === 0) {
|
if (state.ruleForm.id === 0) {
|
||||||
addTenant(state.ruleForm).then(() => {
|
addTenant(submitForm).then(() => {
|
||||||
ElMessage.success('添加成功');
|
ElMessage.success('添加成功');
|
||||||
closeDialog();
|
closeDialog();
|
||||||
emit('getTenantList');
|
emit('getTenantList');
|
||||||
@@ -234,7 +294,7 @@ const onSubmit = () => {
|
|||||||
} else {
|
} else {
|
||||||
// 过滤掉密码字段,或者后端接口决定是否更新密码
|
// 过滤掉密码字段,或者后端接口决定是否更新密码
|
||||||
// 根据需求,修改时不能修改密码
|
// 根据需求,修改时不能修改密码
|
||||||
const { password, confirmPassword, tenantAccount, ...rest } = state.ruleForm;
|
const { password, confirmPassword, tenantAccount, ...rest } = submitForm;
|
||||||
editTenant({ ...rest, id: state.ruleForm.id }).then(() => {
|
editTenant({ ...rest, id: state.ruleForm.id }).then(() => {
|
||||||
ElMessage.success('修改成功');
|
ElMessage.success('修改成功');
|
||||||
closeDialog();
|
closeDialog();
|
||||||
|
|||||||
@@ -55,13 +55,13 @@
|
|||||||
<el-tag v-else type="info">未知</el-tag>
|
<el-tag v-else type="info">未知</el-tag>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="city" label="所属城市" show-overflow-tooltip>
|
<el-table-column prop="cityName" label="所属城市" show-overflow-tooltip>
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
{{ getCityName(scope.row.city) }}
|
{{ getCityName(scope.row.cityName) }}
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="contactPerson" label="联系人" show-overflow-tooltip></el-table-column>
|
<el-table-column prop="userNickname" label="联系人" show-overflow-tooltip></el-table-column>
|
||||||
<el-table-column prop="phone" label="电话" show-overflow-tooltip></el-table-column>
|
<el-table-column prop="mobile" label="电话" show-overflow-tooltip></el-table-column>
|
||||||
<el-table-column prop="businessLicense" label="营业执照" align="center">
|
<el-table-column prop="businessLicense" label="营业执照" align="center">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-image
|
<el-image
|
||||||
@@ -106,7 +106,7 @@ import { toRefs, reactive, onMounted, ref } from 'vue';
|
|||||||
import { ElMessageBox, ElMessage, FormInstance } from 'element-plus';
|
import { ElMessageBox, ElMessage, FormInstance } from 'element-plus';
|
||||||
import EditTenant from './component/editTenant.vue';
|
import EditTenant from './component/editTenant.vue';
|
||||||
import { getTenantList, deleteTenant } from '/@/api/system/tenant';
|
import { getTenantList, deleteTenant } from '/@/api/system/tenant';
|
||||||
import { pcTextArr } from 'element-china-area-data';
|
import { pcTextArr,provinceAndCityData } from 'element-china-area-data';
|
||||||
|
|
||||||
const editTenantRef = ref();
|
const editTenantRef = ref();
|
||||||
const queryRef = ref();
|
const queryRef = ref();
|
||||||
@@ -120,7 +120,7 @@ const state = reactive({
|
|||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
tenantName: '',
|
tenantName: '',
|
||||||
tenantType: '',
|
tenantType: '',
|
||||||
city: [],
|
city: '',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -128,12 +128,49 @@ const state = reactive({
|
|||||||
const { tableData } = toRefs(state);
|
const { tableData } = toRefs(state);
|
||||||
|
|
||||||
// 省市数据
|
// 省市数据
|
||||||
const cityOptions = pcTextArr;
|
const cityOptions = ref<any[]>([]);
|
||||||
|
|
||||||
|
// 初始化城市数据
|
||||||
|
const initCityData = () => {
|
||||||
|
const data = JSON.parse(JSON.stringify(provinceAndCityData));
|
||||||
|
cityOptions.value = data.map((item: any) => {
|
||||||
|
// 处理直辖市:北京(110000), 天津(120000), 上海(310000), 重庆(500000)
|
||||||
|
if (['110000', '120000', '310000', '500000'].includes(item.value) || ['北京市', '天津市', '上海市', '重庆市'].includes(item.label)) {
|
||||||
|
// 移除 children 属性,使其成为叶子节点
|
||||||
|
delete item.children;
|
||||||
|
}
|
||||||
|
return item;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
initCityData();
|
||||||
|
|
||||||
|
|
||||||
// 初始化表格数据
|
// 初始化表格数据
|
||||||
const tenantList = () => {
|
const tenantList = () => {
|
||||||
state.tableData.loading = true;
|
state.tableData.loading = true;
|
||||||
getTenantList(state.tableData.param)
|
const params = { ...state.tableData.param };
|
||||||
|
// 处理城市数据:如果是数组(级联选择器返回),取最后一个值
|
||||||
|
if (Array.isArray(params.city) && params.city.length > 0) {
|
||||||
|
let lastCode = String(params.city[params.city.length - 1]);
|
||||||
|
// 特殊处理直辖市:如果选中的是省级代码,转换为市级代码 (市辖区)
|
||||||
|
const municipalityMap: Record<string, string> = {
|
||||||
|
'11': '110100', '110000': '110100', // 北京
|
||||||
|
'12': '120100', '120000': '120100', // 天津
|
||||||
|
'31': '310100', '310000': '310100', // 上海
|
||||||
|
'50': '500100', '500000': '500100', // 重庆
|
||||||
|
};
|
||||||
|
if (municipalityMap[lastCode]) {
|
||||||
|
lastCode = municipalityMap[lastCode];
|
||||||
|
} else if (lastCode.length === 4) {
|
||||||
|
// 普通省市,如果是4位代码,补齐为6位
|
||||||
|
lastCode = lastCode + '00';
|
||||||
|
}
|
||||||
|
params.city = lastCode;
|
||||||
|
} else {
|
||||||
|
params.city = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
getTenantList(params)
|
||||||
.then((res: any) => {
|
.then((res: any) => {
|
||||||
state.tableData.data = res.data.list ?? [];
|
state.tableData.data = res.data.list ?? [];
|
||||||
state.tableData.total = res.data.total;
|
state.tableData.total = res.data.total;
|
||||||
|
|||||||
Reference in New Issue
Block a user