Commit daff13a5 by yuzhenWang

客户资料模块发布测试

parent 04757222
...@@ -4,5 +4,7 @@ VITE_APP_TITLE = CSF-CORE ...@@ -4,5 +4,7 @@ VITE_APP_TITLE = CSF-CORE
# 开发环境配置 # 开发环境配置
VITE_APP_ENV = 'development' VITE_APP_ENV = 'development'
# 若依管理系统/开发环境 # 测试前缀 接口前缀 暂时是这个
VITE_APP_BASE_API = 'http://10.0.10.26:9002' VITE_APP_BASE_API = 'http://139.224.145.34:9002'
# 测试环境地址前缀 暂时是这个
VITE_APP_BASE_API1 = 'http://139.224.145.34:6699'
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
"@vueuse/core": "13.3.0", "@vueuse/core": "13.3.0",
"axios": "1.9.0", "axios": "1.9.0",
"clipboard": "2.0.11", "clipboard": "2.0.11",
"dayjs": "^1.11.18",
"echarts": "5.6.0", "echarts": "5.6.0",
"element-plus": "2.9.9", "element-plus": "2.9.9",
"file-saver": "2.0.5", "file-saver": "2.0.5",
......
import request from '@/utils/request'
// 修改上传图片方法,添加正确的请求配置
export function uploadImage(data) {
console.log('data', data)
return request({
url: '/oss/api/oss/upload',
data: data,
method: 'post',
// 添加以下配置
headers: {
'Content-Type': 'multipart/form-data' // 明确指定为multipart类型
},
// 如果使用axios,需要设置这个参数
transformRequest: [
function (data) {
return data
}
]
})
}
// 获取系统左侧菜单
export function getMenuLists(projectBizId, tenantBizId) {
return request({
url: `/user/api/sysUser/login/permission/project/getMenuRouters?projectBizId=${projectBizId}&tenantBizId=${tenantBizId}`,
method: 'get'
})
}
// 用token获取用户详细信息
export function getUserInfo(token) {
return request({
url: `/user/api/sysUser/getUserInfoByToken?token=${token}`,
method: 'get'
})
}
// 获取国家地区信息
export function getCountryInfo() {
return request({
url: `/user/api/mdCountry/group`,
method: 'get'
})
}
// 搜索国家地区信息
export function getSearchCountry(name) {
return request({
url: `/user/api/mdCountry/search?name=${name}`,
method: 'get'
})
}
import request from '@/utils/request'
// 查询fna列表
export function getFnaList(data) {
return request({
url: '/csf/api/Fna/list/page',
method: 'post',
data: data
})
}
/*
流程接口开始
*/
// 删除流程
export function deleteFna(data) {
return request({
url: '/csf/api/Fna/delete',
method: 'post',
data: data
})
}
// 新建流程
export function addFna(data) {
return request({
url: '/csf/api/Fna/add',
method: 'post',
data: data
})
}
// 查询流程详情
export function getProcessDetail(fnaBizId) {
return request({
url: `/csf/api/Fna/get/vo?fnaBizId=${fnaBizId}`,
method: 'get'
})
}
// 更新流程
export function updateProcess(data) {
return request({
url: '/csf/api/Fna/update',
method: 'post',
data: data
})
}
/*
流程接口结束
*/
/*
客户模块接口开始
*/
// 新增客户信息
export function addCustomer(data) {
return request({
url: '/csf/api/Customer/add',
method: 'post',
data: data
})
}
// 获取客户详情
export function getCustomerDetail(customerBizId) {
return request({
url: `/csf/api/Customer/get/vo?customerBizId=${customerBizId}`,
method: 'get'
})
}
// 修改客户信息
export function editCustomer(data) {
return request({
url: '/csf/api/Customer/update',
method: 'post',
data: data
})
}
// 修改客户信息
export function getCustomerList(data) {
return request({
url: '/csf/api/Customer/list/page/vo',
method: 'post',
data: data
})
}
/*
客户模块接口结束
*/
// 修改角色
export function roleUpdate(data) {
return request({
url: '/user/api/sysRole/edit',
method: 'put',
data: data
})
}
// 删除角色
export function delRole(roleId) {
return request({
url: '/system/role/' + roleId,
method: 'delete'
})
}
// 编辑角色状态
export function roleStatusChange(roleBizId, status) {
return request({
url: `/user/api/sysRole/edit/status?roleBizId=${roleBizId}&status=${status}`,
method: 'patch'
})
}
// 查询角色详情
export function getRoleDetail(roleBizId) {
return request({
url: `/user/api/sysRole/detail?roleBizId=${roleBizId}`,
method: 'get'
})
}
//作用域切换搜索
export function searchScopeList(data) {
return request({
url: '/user/api/sysUser/scope/page',
method: 'post',
data: data
})
}
/* Logo 字体 */
@font-face {
font-family: "iconfont logo";
src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834');
src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834#iefix') format('embedded-opentype'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.woff?t=1545807318834') format('woff'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.ttf?t=1545807318834') format('truetype'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.svg?t=1545807318834#iconfont') format('svg');
}
.logo {
font-family: "iconfont logo";
font-size: 160px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
/* tabs */
.nav-tabs {
position: relative;
}
.nav-tabs .nav-more {
position: absolute;
right: 0;
bottom: 0;
height: 42px;
line-height: 42px;
color: #666;
}
#tabs {
border-bottom: 1px solid #eee;
}
#tabs li {
cursor: pointer;
width: 100px;
height: 40px;
line-height: 40px;
text-align: center;
font-size: 16px;
border-bottom: 2px solid transparent;
position: relative;
z-index: 1;
margin-bottom: -1px;
color: #666;
}
#tabs .active {
border-bottom-color: #f00;
color: #222;
}
.tab-container .content {
display: none;
}
/* 页面布局 */
.main {
padding: 30px 100px;
width: 960px;
margin: 0 auto;
}
.main .logo {
color: #333;
text-align: left;
margin-bottom: 30px;
line-height: 1;
height: 110px;
margin-top: -50px;
overflow: hidden;
*zoom: 1;
}
.main .logo a {
font-size: 160px;
color: #333;
}
.helps {
margin-top: 40px;
}
.helps pre {
padding: 20px;
margin: 10px 0;
border: solid 1px #e7e1cd;
background-color: #fffdef;
overflow: auto;
}
.icon_lists {
width: 100% !important;
overflow: hidden;
*zoom: 1;
}
.icon_lists li {
width: 100px;
margin-bottom: 10px;
margin-right: 20px;
text-align: center;
list-style: none !important;
cursor: default;
}
.icon_lists li .code-name {
line-height: 1.2;
}
.icon_lists .icon {
display: block;
height: 100px;
line-height: 100px;
font-size: 42px;
margin: 10px auto;
color: #333;
-webkit-transition: font-size 0.25s linear, width 0.25s linear;
-moz-transition: font-size 0.25s linear, width 0.25s linear;
transition: font-size 0.25s linear, width 0.25s linear;
}
.icon_lists .icon:hover {
font-size: 100px;
}
.icon_lists .svg-icon {
/* 通过设置 font-size 来改变图标大小 */
width: 1em;
/* 图标和文字相邻时,垂直对齐 */
vertical-align: -0.15em;
/* 通过设置 color 来改变 SVG 的颜色/fill */
fill: currentColor;
/* path 和 stroke 溢出 viewBox 部分在 IE 下会显示
normalize.css 中也包含这行 */
overflow: hidden;
}
.icon_lists li .name,
.icon_lists li .code-name {
color: #666;
}
/* markdown 样式 */
.markdown {
color: #666;
font-size: 14px;
line-height: 1.8;
}
.highlight {
line-height: 1.5;
}
.markdown img {
vertical-align: middle;
max-width: 100%;
}
.markdown h1 {
color: #404040;
font-weight: 500;
line-height: 40px;
margin-bottom: 24px;
}
.markdown h2,
.markdown h3,
.markdown h4,
.markdown h5,
.markdown h6 {
color: #404040;
margin: 1.6em 0 0.6em 0;
font-weight: 500;
clear: both;
}
.markdown h1 {
font-size: 28px;
}
.markdown h2 {
font-size: 22px;
}
.markdown h3 {
font-size: 16px;
}
.markdown h4 {
font-size: 14px;
}
.markdown h5 {
font-size: 12px;
}
.markdown h6 {
font-size: 12px;
}
.markdown hr {
height: 1px;
border: 0;
background: #e9e9e9;
margin: 16px 0;
clear: both;
}
.markdown p {
margin: 1em 0;
}
.markdown>p,
.markdown>blockquote,
.markdown>.highlight,
.markdown>ol,
.markdown>ul {
width: 80%;
}
.markdown ul>li {
list-style: circle;
}
.markdown>ul li,
.markdown blockquote ul>li {
margin-left: 20px;
padding-left: 4px;
}
.markdown>ul li p,
.markdown>ol li p {
margin: 0.6em 0;
}
.markdown ol>li {
list-style: decimal;
}
.markdown>ol li,
.markdown blockquote ol>li {
margin-left: 20px;
padding-left: 4px;
}
.markdown code {
margin: 0 3px;
padding: 0 5px;
background: #eee;
border-radius: 3px;
}
.markdown strong,
.markdown b {
font-weight: 600;
}
.markdown>table {
border-collapse: collapse;
border-spacing: 0px;
empty-cells: show;
border: 1px solid #e9e9e9;
width: 95%;
margin-bottom: 24px;
}
.markdown>table th {
white-space: nowrap;
color: #333;
font-weight: 600;
}
.markdown>table th,
.markdown>table td {
border: 1px solid #e9e9e9;
padding: 8px 16px;
text-align: left;
}
.markdown>table th {
background: #F7F7F7;
}
.markdown blockquote {
font-size: 90%;
color: #999;
border-left: 4px solid #e9e9e9;
padding-left: 0.8em;
margin: 1em 0;
}
.markdown blockquote p {
margin: 0;
}
.markdown .anchor {
opacity: 0;
transition: opacity 0.3s ease;
margin-left: 8px;
}
.markdown .waiting {
color: #ccc;
}
.markdown h1:hover .anchor,
.markdown h2:hover .anchor,
.markdown h3:hover .anchor,
.markdown h4:hover .anchor,
.markdown h5:hover .anchor,
.markdown h6:hover .anchor {
opacity: 1;
display: inline-block;
}
.markdown>br,
.markdown>p>br {
clear: both;
}
.hljs {
display: block;
background: white;
padding: 0.5em;
color: #333333;
overflow-x: auto;
}
.hljs-comment,
.hljs-meta {
color: #969896;
}
.hljs-string,
.hljs-variable,
.hljs-template-variable,
.hljs-strong,
.hljs-emphasis,
.hljs-quote {
color: #df5000;
}
.hljs-keyword,
.hljs-selector-tag,
.hljs-type {
color: #a71d5d;
}
.hljs-literal,
.hljs-symbol,
.hljs-bullet,
.hljs-attribute {
color: #0086b3;
}
.hljs-section,
.hljs-name {
color: #63a35c;
}
.hljs-tag {
color: #333333;
}
.hljs-title,
.hljs-attr,
.hljs-selector-id,
.hljs-selector-class,
.hljs-selector-attr,
.hljs-selector-pseudo {
color: #795da3;
}
.hljs-addition {
color: #55a532;
background-color: #eaffea;
}
.hljs-deletion {
color: #bd2c00;
background-color: #ffecec;
}
.hljs-link {
text-decoration: underline;
}
/* 代码高亮 */
/* PrismJS 1.15.0
https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript */
/**
* prism.js default theme for JavaScript, CSS and HTML
* Based on dabblet (http://dabblet.com)
* @author Lea Verou
*/
code[class*="language-"],
pre[class*="language-"] {
color: black;
background: none;
text-shadow: 0 1px white;
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
text-align: left;
white-space: pre;
word-spacing: normal;
word-break: normal;
word-wrap: normal;
line-height: 1.5;
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
-webkit-hyphens: none;
-moz-hyphens: none;
-ms-hyphens: none;
hyphens: none;
}
pre[class*="language-"]::-moz-selection,
pre[class*="language-"] ::-moz-selection,
code[class*="language-"]::-moz-selection,
code[class*="language-"] ::-moz-selection {
text-shadow: none;
background: #b3d4fc;
}
pre[class*="language-"]::selection,
pre[class*="language-"] ::selection,
code[class*="language-"]::selection,
code[class*="language-"] ::selection {
text-shadow: none;
background: #b3d4fc;
}
@media print {
code[class*="language-"],
pre[class*="language-"] {
text-shadow: none;
}
}
/* Code blocks */
pre[class*="language-"] {
padding: 1em;
margin: .5em 0;
overflow: auto;
}
:not(pre)>code[class*="language-"],
pre[class*="language-"] {
background: #f5f2f0;
}
/* Inline code */
:not(pre)>code[class*="language-"] {
padding: .1em;
border-radius: .3em;
white-space: normal;
}
.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
color: slategray;
}
.token.punctuation {
color: #999;
}
.namespace {
opacity: .7;
}
.token.property,
.token.tag,
.token.boolean,
.token.number,
.token.constant,
.token.symbol,
.token.deleted {
color: #905;
}
.token.selector,
.token.attr-name,
.token.string,
.token.char,
.token.builtin,
.token.inserted {
color: #690;
}
.token.operator,
.token.entity,
.token.url,
.language-css .token.string,
.style .token.string {
color: #9a6e3a;
background: hsla(0, 0%, 100%, .5);
}
.token.atrule,
.token.attr-value,
.token.keyword {
color: #07a;
}
.token.function,
.token.class-name {
color: #DD4A68;
}
.token.regex,
.token.important,
.token.variable {
color: #e90;
}
.token.important,
.token.bold {
font-weight: bold;
}
.token.italic {
font-style: italic;
}
.token.entity {
cursor: help;
}
@font-face {
font-family: "iconfont"; /* Project id 5015061 */
src: url('iconfont.woff2?t=1757311484908') format('woff2'),
url('iconfont.woff?t=1757311484908') format('woff'),
url('iconfont.ttf?t=1757311484908') format('truetype');
}
.iconfont {
font-family: "iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon-yiwancheng:before {
content: "\e114";
}
.icon-yanqiweiwancheng:before {
content: "\e113";
}
.icon-daoru:before {
content: "\e112";
}
.icon-xuqi:before {
content: "\e001";
}
.icon-genjinjilu:before {
content: "\e002";
}
.icon-yuyue:before {
content: "\e003";
}
.icon-huabi:before {
content: "\e004";
}
.icon-Homehomepagemenu:before {
content: "\e005";
}
.icon-daijiesuan:before {
content: "\e006";
}
.icon-jianchafudao:before {
content: "\e007";
}
.icon-youxiaobaodan:before {
content: "\e008";
}
.icon-anquan:before {
content: "\e009";
}
.icon-zongbaofei:before {
content: "\e010";
}
.icon-xiexian:before {
content: "\e011";
}
{
"id": "5015061",
"name": "csf",
"font_family": "iconfont",
"css_prefix_text": "icon-",
"description": "csf核心系统",
"glyphs": [
{
"icon_id": "8300842",
"name": "已完成",
"font_class": "yiwancheng",
"unicode": "e114",
"unicode_decimal": 57620
},
{
"icon_id": "16725409",
"name": "延期未完成",
"font_class": "yanqiweiwancheng",
"unicode": "e113",
"unicode_decimal": 57619
},
{
"icon_id": "23191146",
"name": "导入",
"font_class": "daoru",
"unicode": "e112",
"unicode_decimal": 57618
},
{
"icon_id": "6079882",
"name": "续期",
"font_class": "xuqi",
"unicode": "e001",
"unicode_decimal": 57345
},
{
"icon_id": "8387742",
"name": "跟进记录",
"font_class": "genjinjilu",
"unicode": "e002",
"unicode_decimal": 57346
},
{
"icon_id": "9550464",
"name": "预约",
"font_class": "yuyue",
"unicode": "e003",
"unicode_decimal": 57347
},
{
"icon_id": "10048834",
"name": "画笔",
"font_class": "huabi",
"unicode": "e004",
"unicode_decimal": 57348
},
{
"icon_id": "11982657",
"name": "Home, homepage, menu",
"font_class": "Homehomepagemenu",
"unicode": "e005",
"unicode_decimal": 57349
},
{
"icon_id": "20438891",
"name": "待结算",
"font_class": "daijiesuan",
"unicode": "e006",
"unicode_decimal": 57350
},
{
"icon_id": "27966554",
"name": "检查辅导",
"font_class": "jianchafudao",
"unicode": "e007",
"unicode_decimal": 57351
},
{
"icon_id": "31367111",
"name": "有效保单",
"font_class": "youxiaobaodan",
"unicode": "e008",
"unicode_decimal": 57352
},
{
"icon_id": "34180715",
"name": "安全",
"font_class": "anquan",
"unicode": "e009",
"unicode_decimal": 57353
},
{
"icon_id": "38352588",
"name": "总保费",
"font_class": "zongbaofei",
"unicode": "e010",
"unicode_decimal": 57360
},
{
"icon_id": "42202603",
"name": "斜线",
"font_class": "xiexian",
"unicode": "e011",
"unicode_decimal": 57361
}
]
}
const customer = [
{
fatherTitle: '客户',
type: 'object',
key: 'personInfo',
data: [
{
label: '姓氏',
key: 'lastName',
type: 'Input',
inputType: 'text',
required: false,
maxLength: 5,
disabled: false,
placeholder: '请输入',
show: true
},
{
label: '名字',
key: 'firstName',
type: 'Input',
inputType: 'text',
required: false,
maxLength: 10,
disabled: false,
placeholder: '请输入',
show: true
},
{
label: '姓名',
key: 'name',
type: 'Input',
inputType: 'text',
required: false,
maxLength: 15,
disabled: false,
placeholder: '请输入',
show: true
},
{
label: '姓氏拼音',
key: 'lastNamePinyin',
type: 'Input',
inputType: 'text',
required: false,
maxLength: 30,
disabled: false,
placeholder: '请输入',
show: true
},
{
label: '姓名拼音',
key: 'pinyin',
type: 'Input',
inputType: 'text',
required: false,
maxLength: 30,
disabled: false,
placeholder: '请输入',
show: true
},
{
label: '名字-英文',
key: 'firstNamePinyin',
type: 'Input',
inputType: 'text',
required: true,
maxLength: 30,
disabled: false,
placeholder: '请输入',
show: true
},
{
label: '称谓',
key: 'title',
type: 'Select',
required: true,
disabled: false,
placeholder: '请选择',
dictType: 'csf_customer_title',
show: true
},
{
label: '性别',
key: 'gender',
type: 'Select',
required: false,
disabled: false,
placeholder: '请选择',
dictType: 'sys_gender',
show: true
},
{
label: '生日',
key: 'birthdate',
type: 'DatePicker',
required: false,
disabled: false,
placeholder: '请选择',
show: true
},
{
label: '年龄',
key: 'age',
type: 'Input',
inputType: 'number',
maxLength: 30,
required: true,
disabled: false,
placeholder: '请输入',
show: true
},
{
label: '移动电话',
key: 'phone',
type: 'arrowRight',
required: true,
disabled: false,
placeholder: '请填写',
show: true,
drawerType: 'phone',
phone: {},
code: 'areaCode',
value: ''
},
{
label: '邮箱',
key: 'email',
type: 'Input',
inputType: 'text',
maxLength: 30,
required: true,
disabled: false,
placeholder: '请输入',
show: true
},
{
label: '是否吸烟',
key: 'smoke',
type: 'Select',
required: false,
disabled: false,
placeholder: '请选择',
dictType: 'sys_no_yes',
show: true
},
{
label: '吸烟数量(支/天)',
key: 'smokeQuantity',
type: 'Input',
inputType: 'number',
maxLength: 30,
required: false,
disabled: false,
placeholder: '请输入',
show: false
},
// {
// label: '公司类型',
// key: 'companyType',
// type: 'Select',
// required: false,
// disabled: false,
// placeholder: '请选择',
// dictType: 'sys_status',
// show: true
// },
{
label: '客户类型',
key: 'customerType',
type: 'Select',
required: false,
disabled: false,
placeholder: '请选择',
dictType: 'csf_customer_type',
show: true
},
// {
// label: '客户来源',
// key: 'source',
// type: 'Select',
// required: false,
// disabled: false,
// placeholder: '请选择',
// dictType: 'sys_status',
// show: true
// },
{
label: '行业',
key: 'companyType',
type: 'Input',
inputType: 'text',
maxLength: 300,
required: true,
disabled: false,
placeholder: '请输入',
show: true
}
]
},
{
fatherTitle: '基本情况',
type: 'object',
key: 'basic',
// description: '证件信息至少填写一项',
data: [
{
label: '婚姻状况',
key: 'marriage',
type: 'Select',
required: true,
disabled: false,
placeholder: '请选择',
dictType: 'csf_marriage',
show: true
},
{
label: '国籍(国家/地区)',
key: 'country',
type: 'arrowRight',
required: true,
disabled: false,
placeholder: '请填写',
show: true,
drawerType: 'country'
},
{
label: '出生地',
key: 'birthplace',
type: 'Input',
inputType: 'text',
required: false,
maxLength: 300,
disabled: false,
placeholder: '请输入出生地(省市)',
show: true
},
{
label: '教育程度',
key: 'education',
type: 'Select',
required: true,
disabled: false,
placeholder: '请选择',
dictType: 'csf_education',
show: true
},
{
label: '住宅电话',
key: 'residenceTelephone',
type: 'arrowRight',
required: false,
disabled: false,
placeholder: '请填写',
show: true,
drawerType: 'phone',
residenceTelephone: {},
code: 'residenceAreaCode',
maxLength: 20
},
{
label: '固定电话',
key: 'fixedPhone',
type: 'Input',
inputType: 'number',
required: false,
disabled: false,
placeholder: '请填写',
show: true,
maxLength: 20
},
{
label: '是否长期出国',
key: 'longtimeAbroad',
type: 'Select',
required: false,
disabled: false,
placeholder: '请选择',
dictType: 'sys_no_yes',
show: true
},
{
label: '通讯地址',
key: 'residenceAddress',
type: 'arrowRight',
required: false,
disabled: false,
placeholder: '请填写',
show: true,
drawerType: 'address',
residenceAddress: {}
},
{
label: '住宅地址',
key: 'residentialAddress',
type: 'arrowRight',
required: false,
disabled: false,
placeholder: '请填写',
show: true,
drawerType: 'address',
residentialAddress: {}
},
{
label: '邮寄地址',
key: 'mailingAddress',
type: 'arrowRight',
required: false,
disabled: false,
placeholder: '请填写',
show: true,
drawerType: 'address',
mailingAddress: {}
}
]
},
{
fatherTitle: '证件信息',
type: 'object',
key: 'pid',
description: '证件信息至少填写一项',
data: [
{
label: '证件类型',
key: 'idType',
type: 'Select',
required: true,
disabled: false,
placeholder: '请选择',
dictType: 'csf_id_type',
show: true
},
{
label: '证件号码',
key: 'idCard',
type: 'Input',
inputType: 'text',
required: false,
maxLength: 20,
disabled: false,
placeholder: '请输入',
show: true
}
]
},
{
fatherTitle: '公司信息',
type: 'object',
key: 'companyInfo',
data: [
{
label: '公司名称',
key: 'companyName',
type: 'Input',
inputType: 'text',
required: false,
maxLength: 300,
disabled: false,
placeholder: '请输入',
show: true
},
{
label: '公司电话',
key: 'companyTelephone',
type: 'arrowRight',
required: false,
disabled: false,
placeholder: '请填写',
show: true,
drawerType: 'phone',
companyTelephone: {},
code: 'companyAreaCode',
maxLength: 20
},
{
label: '职位',
key: 'position',
type: 'Input',
inputType: 'text',
required: false,
maxLength: 300,
disabled: false,
placeholder: '请输入',
show: true
},
{
label: '总工作年期',
key: 'workYear',
type: 'Input',
inputType: 'number',
required: false,
maxLength: 300,
disabled: false,
placeholder: '请输入',
show: true
},
{
label: '现时每月收入',
key: 'salary',
type: 'Input',
inputType: 'number',
required: false,
maxLength: 300,
disabled: false,
placeholder: '请输入',
show: true
},
{
label: '公司地址',
key: 'companyAddress',
type: 'arrowRight',
required: false,
disabled: false,
placeholder: '请填写',
show: true,
drawerType: 'address',
companyAddress: {}
}
]
}
]
export default customer
...@@ -2,9 +2,10 @@ ...@@ -2,9 +2,10 @@
<section class="app-main"> <section class="app-main">
<router-view v-slot="{ Component, route }"> <router-view v-slot="{ Component, route }">
<transition name="fade-transform" mode="out-in"> <transition name="fade-transform" mode="out-in">
<keep-alive :include="tagsViewStore.cachedViews"> <!-- <keep-alive :include="tagsViewStore.cachedViews">
<component v-if="!route.meta.link" :is="Component" :key="route.path"/>
</keep-alive> </keep-alive> -->
<component v-if="!route.meta.link" :is="Component" :key="route.path" />
</transition> </transition>
</router-view> </router-view>
<iframe-toggle /> <iframe-toggle />
...@@ -13,8 +14,8 @@ ...@@ -13,8 +14,8 @@
</template> </template>
<script setup> <script setup>
import copyright from "./Copyright/index" import copyright from './Copyright/index'
import iframeToggle from "./IframeToggle/index" import iframeToggle from './IframeToggle/index'
import useTagsViewStore from '@/store/modules/tagsView' import useTagsViewStore from '@/store/modules/tagsView'
const route = useRoute() const route = useRoute()
...@@ -86,4 +87,3 @@ function addIframe() { ...@@ -86,4 +87,3 @@ function addIframe() {
border-radius: 3px; border-radius: 3px;
} }
</style> </style>
...@@ -45,12 +45,12 @@ ...@@ -45,12 +45,12 @@
<screenfull id="screenfull" class="right-menu-item hover-effect" /> <screenfull id="screenfull" class="right-menu-item hover-effect" />
<el-tooltip content="主题模式" effect="dark" placement="bottom"> <!-- <el-tooltip content="主题模式" effect="dark" placement="bottom">
<div class="right-menu-item hover-effect theme-switch-wrapper" @click="toggleTheme"> <div class="right-menu-item hover-effect theme-switch-wrapper" @click="toggleTheme">
<svg-icon v-if="settingsStore.isDark" icon-class="sunny" /> <svg-icon v-if="settingsStore.isDark" icon-class="sunny" />
<svg-icon v-if="!settingsStore.isDark" icon-class="moon" /> <svg-icon v-if="!settingsStore.isDark" icon-class="moon" />
</div> </div>
</el-tooltip> </el-tooltip> -->
<el-tooltip content="布局大小" effect="dark" placement="bottom"> <el-tooltip content="布局大小" effect="dark" placement="bottom">
<size-select id="size-select" class="right-menu-item hover-effect" /> <size-select id="size-select" class="right-menu-item hover-effect" />
...@@ -162,7 +162,11 @@ function logout() { ...@@ -162,7 +162,11 @@ function logout() {
}) })
.then(() => { .then(() => {
userStore.logOut().then(() => { userStore.logOut().then(() => {
location.href = '/index' // location.href = '/workbench'
//退回到中台登录页
window.open(`${import.meta.env.VITE_APP_BASE_API1}/login?redirect=/workbench`)
// 然后立刻关闭自己
window.close()
}) })
}) })
.catch(() => {}) .catch(() => {})
......
...@@ -8,6 +8,8 @@ import 'element-plus/theme-chalk/dark/css-vars.css' ...@@ -8,6 +8,8 @@ import 'element-plus/theme-chalk/dark/css-vars.css'
import locale from 'element-plus/es/locale/lang/zh-cn' import locale from 'element-plus/es/locale/lang/zh-cn'
import '@/assets/styles/index.scss' // global css import '@/assets/styles/index.scss' // global css
// 引入 Iconfont 样式文件
import '@/assets/iconfont/iconfont.css'
import App from './App' import App from './App'
import store from './store' import store from './store'
...@@ -26,21 +28,28 @@ import elementIcons from '@/components/SvgIcon/svgicon' ...@@ -26,21 +28,28 @@ import elementIcons from '@/components/SvgIcon/svgicon'
import './permission' // permission control import './permission' // permission control
import { useDict } from '@/utils/dict' import { useDict } from '@/utils/dict'
import { getConfigKey } from "@/api/system/config" import { getConfigKey } from '@/api/system/config'
import { parseTime, resetForm, addDateRange, handleTree, selectDictLabel, selectDictLabels } from '@/utils/ruoyi' import {
parseTime,
resetForm,
addDateRange,
handleTree,
selectDictLabel,
selectDictLabels
} from '@/utils/ruoyi'
import { getNowTime, formatToDate, formatToDateTime } from '@/utils/date'
// 分页组件 // 分页组件
import Pagination from '@/components/Pagination' import Pagination from '@/components/Pagination'
// 自定义表格工具组件 // 自定义表格工具组件
import RightToolbar from '@/components/RightToolbar' import RightToolbar from '@/components/RightToolbar'
// 富文本组件 // 富文本组件
import Editor from "@/components/Editor" import Editor from '@/components/Editor'
// 文件上传组件 // 文件上传组件
import FileUpload from "@/components/FileUpload" import FileUpload from '@/components/FileUpload'
// 图片上传组件 // 图片上传组件
import ImageUpload from "@/components/ImageUpload" import ImageUpload from '@/components/ImageUpload'
// 图片预览组件 // 图片预览组件
import ImagePreview from "@/components/ImagePreview" import ImagePreview from '@/components/ImagePreview'
// 字典标签组件 // 字典标签组件
import DictTag from '@/components/DictTag' import DictTag from '@/components/DictTag'
...@@ -50,6 +59,9 @@ const app = createApp(App) ...@@ -50,6 +59,9 @@ const app = createApp(App)
app.config.globalProperties.useDict = useDict app.config.globalProperties.useDict = useDict
app.config.globalProperties.download = download app.config.globalProperties.download = download
app.config.globalProperties.parseTime = parseTime app.config.globalProperties.parseTime = parseTime
app.config.globalProperties.getNowTime = getNowTime
app.config.globalProperties.formatToDate = formatToDate
app.config.globalProperties.formatToDateTime = formatToDateTime
app.config.globalProperties.resetForm = resetForm app.config.globalProperties.resetForm = resetForm
app.config.globalProperties.handleTree = handleTree app.config.globalProperties.handleTree = handleTree
app.config.globalProperties.addDateRange = addDateRange app.config.globalProperties.addDateRange = addDateRange
......
...@@ -8,26 +8,36 @@ import useUserStore from '@/store/modules/user' // 使用命名导入 ...@@ -8,26 +8,36 @@ import useUserStore from '@/store/modules/user' // 使用命名导入
import useSettingsStore from '@/store/modules/settings' // 使用命名导入 import useSettingsStore from '@/store/modules/settings' // 使用命名导入
import usePermissionStore from '@/store/modules/permission' // 使用命名导入 import usePermissionStore from '@/store/modules/permission' // 使用命名导入
import { getToken, setToken, removeToken } from '@/utils/auth' import { getToken, setToken, removeToken } from '@/utils/auth'
import { de } from 'element-plus/es/locales.mjs'
NProgress.configure({ showSpinner: false }) NProgress.configure({ showSpinner: false })
const whiteList = ['/login', '/register'] const whiteList = ['/login', '/register', '/workbench']
const isWhiteList = path => { const isWhiteList = path => {
return whiteList.some(pattern => isPathMatch(pattern, path)) return whiteList.some(pattern => isPathMatch(pattern, path))
} }
router.beforeEach((to, from, next) => { router.beforeEach((to, from, next) => {
console.log('跳转进来了', to)
// 带token是从外部跳转进系统的 // 带token是从外部跳转进系统的
if (to.query.token) { if (to.query.token) {
removeToken()
setToken(to.query.token) setToken(to.query.token)
useUserStore().setProjectInfo({ useUserStore().setProjectInfo({
tenantBizId: to.query.tenantBizId, tenantBizId: to.query.tenantBizId,
projectBizId: to.query.projectBizId projectBizId: to.query.projectBizId
}) })
localStorage.setItem(
'projectInfo',
JSON.stringify({
tenantBizId: to.query.tenantBizId,
projectBizId: to.query.projectBizId
})
)
}
if (localStorage.getItem('projectInfo')) {
useUserStore().setProjectInfo(JSON.parse(localStorage.getItem('projectInfo')))
} }
NProgress.start() NProgress.start()
if (getToken()) { if (getToken()) {
to.meta.title && useSettingsStore().setTitle(to.meta.title) to.meta.title && useSettingsStore().setTitle(to.meta.title)
...@@ -36,10 +46,38 @@ router.beforeEach((to, from, next) => { ...@@ -36,10 +46,38 @@ router.beforeEach((to, from, next) => {
next({ path: '/' }) next({ path: '/' })
NProgress.done() NProgress.done()
} else if (isWhiteList(to.path)) { } else if (isWhiteList(to.path)) {
if (useUserStore().roles.length === 0) {
isRelogin.show = true
// 判断当前用户是否已拉取完user_info信息
useUserStore()
.getInfo()
.then(() => {
isRelogin.show = false
usePermissionStore()
.generateRoutes()
.then(accessRoutes => {
// 根据roles权限生成可访问的路由表
accessRoutes.forEach(route => {
if (!isHttp(route.path)) {
router.addRoute(route) // 动态添加可访问路由表
}
})
next() // hack方法 确保addRoutes已完成
})
})
.catch(err => {
useUserStore()
.logOut()
.then(() => {
ElMessage.error(err)
next({ path: '/' })
})
})
} else {
next() next()
}
} else { } else {
console.log('roles', useUserStore().roles.length)
if (useUserStore().roles.length === 0) { if (useUserStore().roles.length === 0) {
isRelogin.show = true isRelogin.show = true
...@@ -57,6 +95,7 @@ router.beforeEach((to, from, next) => { ...@@ -57,6 +95,7 @@ router.beforeEach((to, from, next) => {
router.addRoute(route) // 动态添加可访问路由表 router.addRoute(route) // 动态添加可访问路由表
} }
}) })
// next({ path: '/' })
next({ ...to, replace: true }) // hack方法 确保addRoutes已完成 next({ ...to, replace: true }) // hack方法 确保addRoutes已完成
}) })
}) })
...@@ -75,10 +114,16 @@ router.beforeEach((to, from, next) => { ...@@ -75,10 +114,16 @@ router.beforeEach((to, from, next) => {
} else { } else {
// 没有token // 没有token
if (isWhiteList(to.path)) { if (isWhiteList(to.path)) {
// 在免登录白名单,直接进入 // 在免登录白名单,现在先跳回中台,后续根据具体需求在改动
next() // next()
window.open(`${import.meta.env.VITE_APP_BASE_API1}/login?redirect=/workbench`)
// 然后立刻关闭自己
window.close()
} else { } else {
next(`/login?redirect=${to.fullPath}`) // 否则全部重定向到登录页 // next(`/login?redirect=${to.fullPath}`) // 否则全部重定向到登录页
window.open(`${import.meta.env.VITE_APP_BASE_API1}/login?redirect=/workbench`)
// 然后立刻关闭自己
window.close()
NProgress.done() NProgress.done()
} }
} }
......
...@@ -21,19 +21,19 @@ export default { ...@@ -21,19 +21,19 @@ export default {
}, },
// 弹出提示 // 弹出提示
alert(content) { alert(content) {
ElMessageBox.alert(content, "系统提示") ElMessageBox.alert(content, '系统提示')
}, },
// 错误提示 // 错误提示
alertError(content) { alertError(content) {
ElMessageBox.alert(content, "系统提示", { type: 'error' }) ElMessageBox.alert(content, '系统提示', { type: 'error' })
}, },
// 成功提示 // 成功提示
alertSuccess(content) { alertSuccess(content) {
ElMessageBox.alert(content, "系统提示", { type: 'success' }) ElMessageBox.alert(content, '系统提示', { type: 'success' })
}, },
// 警告提示 // 警告提示
alertWarning(content) { alertWarning(content) {
ElMessageBox.alert(content, "系统提示", { type: 'warning' }) ElMessageBox.alert(content, '系统提示', { type: 'warning' })
}, },
// 通知提示 // 通知提示
notify(content) { notify(content) {
...@@ -52,19 +52,28 @@ export default { ...@@ -52,19 +52,28 @@ export default {
ElNotification.warning(content) ElNotification.warning(content)
}, },
// 确认窗体 // 确认窗体
confirm(content) { confirm(content, info) {
return ElMessageBox.confirm(content, "系统提示", { console.log('confirm', info)
confirmButtonText: '确定', let newInfo = {
cancelButtonText: '取消', confirmButtonText: info?.confirmButtonText || '确定',
type: "warning", cancelButtonText: info?.cancelButtonText || '取消',
showCancel: info?.showCancel == '0' ? false : true,
title: info?.title || '系统提示'
}
console.log('confirm', newInfo)
return ElMessageBox.confirm(content, newInfo.title, {
confirmButtonText: newInfo.confirmButtonText,
cancelButtonText: newInfo.cancelButtonText,
showCancelButton: newInfo.showCancel,
type: 'warning'
}) })
}, },
// 提交内容 // 提交内容
prompt(content) { prompt(content) {
return ElMessageBox.prompt(content, "系统提示", { return ElMessageBox.prompt(content, '系统提示', {
confirmButtonText: '确定', confirmButtonText: '确定',
cancelButtonText: '取消', cancelButtonText: '取消',
type: "warning", type: 'warning'
}) })
}, },
// 打开遮罩层 // 打开遮罩层
...@@ -72,7 +81,7 @@ export default { ...@@ -72,7 +81,7 @@ export default {
loadingInstance = ElLoading.service({ loadingInstance = ElLoading.service({
lock: true, lock: true,
text: content, text: content,
background: "rgba(0, 0, 0, 0.7)", background: 'rgba(0, 0, 0, 0.7)'
}) })
}, },
// 关闭遮罩层 // 关闭遮罩层
......
...@@ -48,7 +48,7 @@ export const constantRoutes = [ ...@@ -48,7 +48,7 @@ export const constantRoutes = [
hidden: true hidden: true
}, },
{ {
path: "/:pathMatch(.*)*", path: '/:pathMatch(.*)*',
component: () => import('@/views/error/404'), component: () => import('@/views/error/404'),
hidden: true hidden: true
}, },
...@@ -70,7 +70,7 @@ export const constantRoutes = [ ...@@ -70,7 +70,7 @@ export const constantRoutes = [
meta: { title: '工作台', icon: 'dashboard', affix: true } meta: { title: '工作台', icon: 'dashboard', affix: true }
} }
] ]
}, }
// { // {
// path: '', // path: '',
// component: Layout, // component: Layout,
...@@ -198,7 +198,7 @@ const router = createRouter({ ...@@ -198,7 +198,7 @@ const router = createRouter({
return savedPosition return savedPosition
} }
return { top: 0 } return { top: 0 }
}, }
}) })
// 重置路由函数 // 重置路由函数
......
import auth from '@/plugins/auth' import auth from '@/plugins/auth'
import router, { constantRoutes, dynamicRoutes } from '@/router' import router, { constantRoutes, dynamicRoutes } from '@/router'
import { getRouters } from '@/api/menu' import { getRouters } from '@/api/menu'
import { getMenuLists } from '@/api/common'
import Layout from '@/layout/index' import Layout from '@/layout/index'
import ParentView from '@/components/ParentView' import ParentView from '@/components/ParentView'
import InnerLink from '@/layout/components/InnerLink' import InnerLink from '@/layout/components/InnerLink'
...@@ -21,9 +22,6 @@ const usePermissionStore = defineStore('permission', { ...@@ -21,9 +22,6 @@ const usePermissionStore = defineStore('permission', {
setRoutes(routes) { setRoutes(routes) {
this.addRoutes = routes this.addRoutes = routes
this.routes = constantRoutes.concat(routes) this.routes = constantRoutes.concat(routes)
console.log('====================================')
console.log('this.routes', this.routes)
console.log('====================================')
}, },
setDefaultRoutes(routes) { setDefaultRoutes(routes) {
this.defaultRoutes = constantRoutes.concat(routes) this.defaultRoutes = constantRoutes.concat(routes)
...@@ -37,10 +35,8 @@ const usePermissionStore = defineStore('permission', { ...@@ -37,10 +35,8 @@ const usePermissionStore = defineStore('permission', {
generateRoutes() { generateRoutes() {
return new Promise(resolve => { return new Promise(resolve => {
const userStore = useUserStore() const userStore = useUserStore()
const tenantBizId = getMenuLists(userStore.projectInfo.projectBizId, userStore.projectInfo.tenantBizId).then(
userStore.currentTenant.apiLoginTenantInfoResponse.tenantBizId || 'tenant_1001' res => {
getRouters(tenantBizId).then(res => {
const sdata = JSON.parse(JSON.stringify(res.data)) const sdata = JSON.parse(JSON.stringify(res.data))
const rdata = JSON.parse(JSON.stringify(res.data)) const rdata = JSON.parse(JSON.stringify(res.data))
const defaultData = JSON.parse(JSON.stringify(res.data)) const defaultData = JSON.parse(JSON.stringify(res.data))
...@@ -53,9 +49,13 @@ const usePermissionStore = defineStore('permission', { ...@@ -53,9 +49,13 @@ const usePermissionStore = defineStore('permission', {
this.setSidebarRouters(constantRoutes.concat(sidebarRoutes)) this.setSidebarRouters(constantRoutes.concat(sidebarRoutes))
this.setDefaultRoutes(sidebarRoutes) this.setDefaultRoutes(sidebarRoutes)
this.setTopbarRoutes(defaultRoutes) this.setTopbarRoutes(defaultRoutes)
console.log('====================================')
console.log('rewriteRoutes', rewriteRoutes)
console.log('====================================')
resolve(rewriteRoutes) resolve(rewriteRoutes)
}) }
)
}) })
} }
} }
...@@ -86,7 +86,7 @@ function filterAsyncRouter(asyncRouterMap, lastRouter = false, type = false) { ...@@ -86,7 +86,7 @@ function filterAsyncRouter(asyncRouterMap, lastRouter = false, type = false) {
route.meta.title = route.menuName route.meta.title = route.menuName
route.meta.icon = route.icon route.meta.icon = route.icon
route.meta.isCache = route.isCache === 1 route.meta.isCache = route.isCache === 1
route.name = route.routeName
//确保单子菜单的父菜单也显示 //确保单子菜单的父菜单也显示
if (route.menuType === 1) { if (route.menuType === 1) {
route.alwaysShow = true // 强制显示父菜单 route.alwaysShow = true // 强制显示父菜单
......
import router from '@/router' import router from '@/router'
import { ElMessageBox } from 'element-plus' import { ElMessageBox } from 'element-plus'
import { login, logout, getInfo } from '@/api/login' import { login, logout, getInfo } from '@/api/login'
import { getUserInfo } from '@/api/common'
import { getToken, setToken, removeToken } from '@/utils/auth' import { getToken, setToken, removeToken } from '@/utils/auth'
import { isHttp, isEmpty } from '@/utils/validate' import { isHttp, isEmpty } from '@/utils/validate'
import defAva from '@/assets/images/profile.jpg' import defAva from '@/assets/images/profile.jpg'
...@@ -18,7 +19,8 @@ const useUserStore = defineStore('user', { ...@@ -18,7 +19,8 @@ const useUserStore = defineStore('user', {
permissions: [], permissions: [],
tenants: [], // 新增租户列表 tenants: [], // 新增租户列表
currentTenant: null, // 新增当前租户 currentTenant: null, // 新增当前租户
projectInfo:null //保存从中台跳转过来的项目信息 projectInfo: null, //保存从中台跳转过来的项目信息
userDetail: null //保存从中台跳转过来的用户信息
}), }),
actions: { actions: {
// 登录 // 登录
...@@ -75,7 +77,7 @@ const useUserStore = defineStore('user', { ...@@ -75,7 +77,7 @@ const useUserStore = defineStore('user', {
this.nickName = user.nickName this.nickName = user.nickName
this.avatar = avatar this.avatar = avatar
this.isSuperAdmin = user.isSuperAdmin this.isSuperAdmin = user.isSuperAdmin
this.userDetail = user //新增的中台用户信息
/* 初始密码提示 */ /* 初始密码提示 */
if (res.data.isDefaultModifyPwd) { if (res.data.isDefaultModifyPwd) {
ElMessageBox.confirm('您的密码还是初始密码,请修改密码!', '安全提示', { ElMessageBox.confirm('您的密码还是初始密码,请修改密码!', '安全提示', {
......
{
"id": 12,
"customerBizId": "customer_XQH9OmZsSNafYMhc",
"customCode": null,
"lastName": "11",
"firstName": "11",
"name": "11",
"lastNamePinyin": "11",
"firstNamePinyin": "11",
"pinyin": "11",
"title": "Dr",
"gender": "2",
"birthdate": null,
"abnormal": null,
"age": "12",
"areaCode": "+86",
"phone": "11111",
"email": "11111",
"smoke": "1",
"smokeQuantity": "10",
"companyType": "11111",
"source": null,
"idType": "passport",
"idCard": "555",
"passport": null,
"eepCode": null,
"marriage": "MARRIED",
"birthplace": "11111111",
"education": "UNIVERSITY",
"customerExpandBizId": "customer_expand_l3eOcWeqGd1IFDJg",
"country": "CHINESE",
"countryName": "中国",
"createTime": "2025-09-16T11:40:58.000+08:00",
"customerType": null,
"residenceAreaCode": "+44",
"residenceTelephone": "22222",
"longtimeAbroad": "1",
"addressList": [
{
"type": "residenceAddress",
"region": "111",
"city": "222",
"street": "333",
"location": "444"
},
{
"type": "residentialAddress",
"region": "111",
"city": "222",
"street": "333",
"location": "444"
},
{
"type": "mailingAddress",
"region": "333",
"city": "333",
"street": "444",
"location": "555"
},
{
"type": "companyAddress",
"region": "666",
"city": "777",
"street": "888",
"location": "999"
}
],
"companyName": "444",
"companyAreaCode": "+65",
"companyTelephone": "5555",
"position": "555",
"workYear": "55",
"salary": 55555
}
// 深拷贝函数,避免对象引用问题
export default function deepClone(obj) {
if (obj === null || typeof obj !== 'object') return obj
if (obj instanceof Date) return new Date(obj.getTime())
if (obj instanceof Array) return obj.map(item => deepClone(item))
if (typeof obj === 'object') {
const clonedObj = {}
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
clonedObj[key] = deepClone(obj[key])
}
}
return clonedObj
}
}
import dayjs from 'dayjs'
export function formatIsoToDateTime(isoStr) { export function formatIsoToDateTime(isoStr) {
// 处理 null/undefined 情况,避免报错 // 处理 null/undefined 情况,避免报错
if (!isoStr) return undefined; if (!isoStr) return undefined
// 替换 T 为空格,返回 "YYYY-MM-DD HH:mm:ss" // 替换 T 为空格,返回 "YYYY-MM-DD HH:mm:ss"
return isoStr.replace('T', ' '); return isoStr.replace('T', ' ')
}
console.log(dayjs)
const DATE_TIME_FORMAT = 'YYYY-MM-DD HH:mm:ss'
const DATE_FORMAT = 'YYYY-MM-DD'
export function formatToDateTime(date, format = DATE_TIME_FORMAT) {
return dayjs(date).format(format)
}
export function formatToDate(date, format = DATE_FORMAT) {
if (!date) return ''
return dayjs(date).format(format)
}
export const getNowTime = (format = DATE_TIME_FORMAT) => {
return dayjs().format(format)
} }
import useDictStore from '@/store/modules/dict' import useDictStore from '@/store/modules/dict'
import { getDicts } from '@/api/system/dict/data' import { getDicts } from '@/api/system/dict/data'
/** /**
* 获取字典数据 * 获取字典数据
*/ */
...@@ -24,7 +23,6 @@ export function useDict(...args) { ...@@ -24,7 +23,6 @@ export function useDict(...args) {
})() })()
} }
// /** // /**
// * 获取字典数据 // * 获取字典数据
// */ // */
......
...@@ -40,7 +40,9 @@ function buildFormTemplate(conf, child, type) { ...@@ -40,7 +40,9 @@ function buildFormTemplate(conf, child, type) {
labelPosition = `label-position="${conf.labelPosition}"` labelPosition = `label-position="${conf.labelPosition}"`
} }
const disabled = conf.disabled ? `:disabled="${conf.disabled}"` : '' const disabled = conf.disabled ? `:disabled="${conf.disabled}"` : ''
let str = `<el-form ref="${conf.formRef}" :model="${conf.formModel}" :rules="${conf.formRules}" size="${conf.size}" ${disabled} label-width="${conf.labelWidth}px" ${labelPosition}> let str = `<el-form ref="${conf.formRef}" :model="${conf.formModel}" :rules="${
conf.formRules
}" size="${conf.size}" ${disabled} label-width="${conf.labelWidth}px" ${labelPosition}>
${child} ${child}
${buildFromBtns(conf, type)} ${buildFromBtns(conf, type)}
</el-form>` </el-form>`
...@@ -108,9 +110,7 @@ const layouts = { ...@@ -108,9 +110,7 @@ const layouts = {
const tags = { const tags = {
'el-button': el => { 'el-button': el => {
const { const { tag, disabled } = attrBuilder(el)
tag, disabled
} = attrBuilder(el)
const type = el.type ? `type="${el.type}"` : '' const type = el.type ? `type="${el.type}"` : ''
const icon = el.icon ? `icon="${el.icon}"` : '' const icon = el.icon ? `icon="${el.icon}"` : ''
const size = el.size ? `size="${el.size}"` : '' const size = el.size ? `size="${el.size}"` : ''
...@@ -120,9 +120,7 @@ const tags = { ...@@ -120,9 +120,7 @@ const tags = {
return `<${el.tag} ${type} ${icon} ${size} ${disabled}>${child}</${el.tag}>` return `<${el.tag} ${type} ${icon} ${size} ${disabled}>${child}</${el.tag}>`
}, },
'el-input': el => { 'el-input': el => {
const { const { disabled, vModel, clearable, placeholder, width } = attrBuilder(el)
disabled, vModel, clearable, placeholder, width
} = attrBuilder(el)
const maxlength = el.maxlength ? `:maxlength="${el.maxlength}"` : '' const maxlength = el.maxlength ? `:maxlength="${el.maxlength}"` : ''
const showWordLimit = el['show-word-limit'] ? 'show-word-limit' : '' const showWordLimit = el['show-word-limit'] ? 'show-word-limit' : ''
const readonly = el.readonly ? 'readonly' : '' const readonly = el.readonly ? 'readonly' : ''
...@@ -130,7 +128,8 @@ const tags = { ...@@ -130,7 +128,8 @@ const tags = {
const suffixIcon = el['suffix-icon'] ? `suffix-icon='${el['suffix-icon']}'` : '' const suffixIcon = el['suffix-icon'] ? `suffix-icon='${el['suffix-icon']}'` : ''
const showPassword = el['show-password'] ? 'show-password' : '' const showPassword = el['show-password'] ? 'show-password' : ''
const type = el.type ? `type="${el.type}"` : '' const type = el.type ? `type="${el.type}"` : ''
const autosize = el.autosize && el.autosize.minRows const autosize =
el.autosize && el.autosize.minRows
? `:autosize="{minRows: ${el.autosize.minRows}, maxRows: ${el.autosize.maxRows}}"` ? `:autosize="{minRows: ${el.autosize.minRows}, maxRows: ${el.autosize.maxRows}}"`
: '' : ''
let child = buildElInputChild(el) let child = buildElInputChild(el)
...@@ -140,7 +139,9 @@ const tags = { ...@@ -140,7 +139,9 @@ const tags = {
}, },
'el-input-number': el => { 'el-input-number': el => {
const { disabled, vModel, placeholder } = attrBuilder(el) const { disabled, vModel, placeholder } = attrBuilder(el)
const controlsPosition = el['controls-position'] ? `controls-position=${el['controls-position']}` : '' const controlsPosition = el['controls-position']
? `controls-position=${el['controls-position']}`
: ''
const min = el.min ? `:min='${el.min}'` : '' const min = el.min ? `:min='${el.min}'` : ''
const max = el.max ? `:max='${el.max}'` : '' const max = el.max ? `:max='${el.max}'` : ''
const step = el.step ? `:step='${el.step}'` : '' const step = el.step ? `:step='${el.step}'` : ''
...@@ -150,9 +151,7 @@ const tags = { ...@@ -150,9 +151,7 @@ const tags = {
return `<${el.tag} ${vModel} ${placeholder} ${step} ${stepStrictly} ${precision} ${controlsPosition} ${min} ${max} ${disabled}></${el.tag}>` return `<${el.tag} ${vModel} ${placeholder} ${step} ${stepStrictly} ${precision} ${controlsPosition} ${min} ${max} ${disabled}></${el.tag}>`
}, },
'el-select': el => { 'el-select': el => {
const { const { disabled, vModel, clearable, placeholder, width } = attrBuilder(el)
disabled, vModel, clearable, placeholder, width
} = attrBuilder(el)
const filterable = el.filterable ? 'filterable' : '' const filterable = el.filterable ? 'filterable' : ''
const multiple = el.multiple ? 'multiple' : '' const multiple = el.multiple ? 'multiple' : ''
let child = buildElSelectChild(el) let child = buildElSelectChild(el)
...@@ -184,15 +183,17 @@ const tags = { ...@@ -184,15 +183,17 @@ const tags = {
const inactiveText = el['inactive-text'] ? `inactive-text="${el['inactive-text']}"` : '' const inactiveText = el['inactive-text'] ? `inactive-text="${el['inactive-text']}"` : ''
const activeColor = el['active-color'] ? `active-color="${el['active-color']}"` : '' const activeColor = el['active-color'] ? `active-color="${el['active-color']}"` : ''
const inactiveColor = el['inactive-color'] ? `inactive-color="${el['inactive-color']}"` : '' const inactiveColor = el['inactive-color'] ? `inactive-color="${el['inactive-color']}"` : ''
const activeValue = el['active-value'] !== true ? `:active-value='${JSON.stringify(el['active-value'])}'` : '' const activeValue =
const inactiveValue = el['inactive-value'] !== false ? `:inactive-value='${JSON.stringify(el['inactive-value'])}'` : '' el['active-value'] !== true ? `:active-value='${JSON.stringify(el['active-value'])}'` : ''
const inactiveValue =
el['inactive-value'] !== false
? `:inactive-value='${JSON.stringify(el['inactive-value'])}'`
: ''
return `<${el.tag} ${vModel} ${activeText} ${inactiveText} ${activeColor} ${inactiveColor} ${activeValue} ${inactiveValue} ${disabled}></${el.tag}>` return `<${el.tag} ${vModel} ${activeText} ${inactiveText} ${activeColor} ${inactiveColor} ${activeValue} ${inactiveValue} ${disabled}></${el.tag}>`
}, },
'el-cascader': el => { 'el-cascader': el => {
const { const { disabled, vModel, clearable, placeholder, width } = attrBuilder(el)
disabled, vModel, clearable, placeholder, width
} = attrBuilder(el)
const options = el.options ? `:options="${el.vModel}Options"` : '' const options = el.options ? `:options="${el.vModel}Options"` : ''
const props = el.props ? `:props="${el.vModel}Props"` : '' const props = el.props ? `:props="${el.vModel}Props"` : ''
const showAllLevels = el['show-all-levels'] ? '' : ':show-all-levels="false"' const showAllLevels = el['show-all-levels'] ? '' : ':show-all-levels="false"'
...@@ -212,24 +213,26 @@ const tags = { ...@@ -212,24 +213,26 @@ const tags = {
return `<${el.tag} ${min} ${max} ${step} ${vModel} ${range} ${showStops} ${disabled}></${el.tag}>` return `<${el.tag} ${min} ${max} ${step} ${vModel} ${range} ${showStops} ${disabled}></${el.tag}>`
}, },
'el-time-picker': el => { 'el-time-picker': el => {
const { const { disabled, vModel, clearable, placeholder, width } = attrBuilder(el)
disabled, vModel, clearable, placeholder, width const startPlaceholder = el['start-placeholder']
} = attrBuilder(el) ? `start-placeholder="${el['start-placeholder']}"`
const startPlaceholder = el['start-placeholder'] ? `start-placeholder="${el['start-placeholder']}"` : '' : ''
const endPlaceholder = el['end-placeholder'] ? `end-placeholder="${el['end-placeholder']}"` : '' const endPlaceholder = el['end-placeholder'] ? `end-placeholder="${el['end-placeholder']}"` : ''
const rangeSeparator = el['range-separator'] ? `range-separator="${el['range-separator']}"` : '' const rangeSeparator = el['range-separator'] ? `range-separator="${el['range-separator']}"` : ''
const isRange = el['is-range'] ? 'is-range' : '' const isRange = el['is-range'] ? 'is-range' : ''
const format = el.format ? `format="${el.format}"` : '' const format = el.format ? `format="${el.format}"` : ''
const valueFormat = el['value-format'] ? `value-format="${el['value-format']}"` : '' const valueFormat = el['value-format'] ? `value-format="${el['value-format']}"` : ''
const pickerOptions = el['picker-options'] ? `:picker-options='${JSON.stringify(el['picker-options'])}'` : '' const pickerOptions = el['picker-options']
? `:picker-options='${JSON.stringify(el['picker-options'])}'`
: ''
return `<${el.tag} ${vModel} ${isRange} ${format} ${valueFormat} ${pickerOptions} ${width} ${placeholder} ${startPlaceholder} ${endPlaceholder} ${rangeSeparator} ${clearable} ${disabled}></${el.tag}>` return `<${el.tag} ${vModel} ${isRange} ${format} ${valueFormat} ${pickerOptions} ${width} ${placeholder} ${startPlaceholder} ${endPlaceholder} ${rangeSeparator} ${clearable} ${disabled}></${el.tag}>`
}, },
'el-date-picker': el => { 'el-date-picker': el => {
const { const { disabled, vModel, clearable, placeholder, width } = attrBuilder(el)
disabled, vModel, clearable, placeholder, width const startPlaceholder = el['start-placeholder']
} = attrBuilder(el) ? `start-placeholder="${el['start-placeholder']}"`
const startPlaceholder = el['start-placeholder'] ? `start-placeholder="${el['start-placeholder']}"` : '' : ''
const endPlaceholder = el['end-placeholder'] ? `end-placeholder="${el['end-placeholder']}"` : '' const endPlaceholder = el['end-placeholder'] ? `end-placeholder="${el['end-placeholder']}"` : ''
const rangeSeparator = el['range-separator'] ? `range-separator="${el['range-separator']}"` : '' const rangeSeparator = el['range-separator'] ? `range-separator="${el['range-separator']}"` : ''
const format = el.format ? `format="${el.format}"` : '' const format = el.format ? `format="${el.format}"` : ''
...@@ -257,7 +260,7 @@ const tags = { ...@@ -257,7 +260,7 @@ const tags = {
return `<${el.tag} ${vModel} ${size} ${showAlpha} ${colorFormat} ${disabled}></${el.tag}>` return `<${el.tag} ${vModel} ${size} ${showAlpha} ${colorFormat} ${disabled}></${el.tag}>`
}, },
'el-upload': el => { 'el-upload': el => {
const disabled = el.disabled ? ':disabled=\'true\'' : '' const disabled = el.disabled ? ":disabled='true'" : ''
const action = el.action ? `:action="${el.vModel}Action"` : '' const action = el.action ? `:action="${el.vModel}Action"` : ''
const multiple = el.multiple ? 'multiple' : '' const multiple = el.multiple ? 'multiple' : ''
const listType = el['list-type'] !== 'text' ? `list-type="${el['list-type']}"` : '' const listType = el['list-type'] !== 'text' ? `list-type="${el['list-type']}"` : ''
...@@ -280,7 +283,7 @@ function attrBuilder(el) { ...@@ -280,7 +283,7 @@ function attrBuilder(el) {
clearable: el.clearable ? 'clearable' : '', clearable: el.clearable ? 'clearable' : '',
placeholder: el.placeholder ? `placeholder="${el.placeholder}"` : '', placeholder: el.placeholder ? `placeholder="${el.placeholder}"` : '',
width: el.style && el.style.width ? ':style="{width: \'100%\'}"' : '', width: el.style && el.style.width ? ':style="{width: \'100%\'}"' : '',
disabled: el.disabled ? ':disabled=\'true\'' : '' disabled: el.disabled ? ":disabled='true'" : ''
} }
} }
...@@ -308,7 +311,9 @@ function buildElInputChild(conf) { ...@@ -308,7 +311,9 @@ function buildElInputChild(conf) {
function buildElSelectChild(conf) { function buildElSelectChild(conf) {
const children = [] const children = []
if (conf.options && conf.options.length) { if (conf.options && conf.options.length) {
children.push(`<el-option v-for="(item, index) in ${conf.vModel}Options" :key="index" :label="item.label" :value="item.value" :disabled="item.disabled"></el-option>`) children.push(
`<el-option v-for="(item, index) in ${conf.vModel}Options" :key="index" :label="item.label" :value="item.value" :disabled="item.disabled"></el-option>`
)
} }
return children.join('\n') return children.join('\n')
} }
...@@ -318,7 +323,9 @@ function buildElRadioGroupChild(conf) { ...@@ -318,7 +323,9 @@ function buildElRadioGroupChild(conf) {
if (conf.options && conf.options.length) { if (conf.options && conf.options.length) {
const tag = conf.optionType === 'button' ? 'el-radio-button' : 'el-radio' const tag = conf.optionType === 'button' ? 'el-radio-button' : 'el-radio'
const border = conf.border ? 'border' : '' const border = conf.border ? 'border' : ''
children.push(`<${tag} v-for="(item, index) in ${conf.vModel}Options" :key="index" :value="item.value" :disabled="item.disabled" ${border}>{{item.label}}</${tag}>`) children.push(
`<${tag} v-for="(item, index) in ${conf.vModel}Options" :key="index" :value="item.value" :disabled="item.disabled" ${border}>{{item.label}}</${tag}>`
)
} }
return children.join('\n') return children.join('\n')
} }
...@@ -328,7 +335,9 @@ function buildElCheckboxGroupChild(conf) { ...@@ -328,7 +335,9 @@ function buildElCheckboxGroupChild(conf) {
if (conf.options && conf.options.length) { if (conf.options && conf.options.length) {
const tag = conf.optionType === 'button' ? 'el-checkbox-button' : 'el-checkbox' const tag = conf.optionType === 'button' ? 'el-checkbox-button' : 'el-checkbox'
const border = conf.border ? 'border' : '' const border = conf.border ? 'border' : ''
children.push(`<${tag} v-for="(item, index) in ${conf.vModel}Options" :key="index" :label="item.value" :value="item.label" :disabled="item.disabled" ${border} />`) children.push(
`<${tag} v-for="(item, index) in ${conf.vModel}Options" :key="index" :label="item.value" :value="item.label" :disabled="item.disabled" ${border} />`
)
} }
return children.join('\n') return children.join('\n')
} }
...@@ -336,8 +345,14 @@ function buildElCheckboxGroupChild(conf) { ...@@ -336,8 +345,14 @@ function buildElCheckboxGroupChild(conf) {
function buildElUploadChild(conf) { function buildElUploadChild(conf) {
const list = [] const list = []
if (conf['list-type'] === 'picture-card') list.push('<i class="el-icon-plus"></i>') if (conf['list-type'] === 'picture-card') list.push('<i class="el-icon-plus"></i>')
else list.push(`<el-button size="small" type="primary" icon="el-icon-upload">${conf.buttonText}</el-button>`) else
if (conf.showTip) list.push(`<div slot="tip" class="el-upload__tip">只能上传不超过 ${conf.fileSize}${conf.sizeUnit}${conf.accept}文件</div>`) list.push(
`<el-button size="small" type="primary" icon="el-icon-upload">${conf.buttonText}</el-button>`
)
if (conf.showTip)
list.push(
`<div slot="tip" class="el-upload__tip">只能上传不超过 ${conf.fileSize}${conf.sizeUnit}${conf.accept}文件</div>`
)
return list.join('\n') return list.join('\n')
} }
......
import axios from 'axios' import axios from 'axios'
import { ElNotification , ElMessageBox, ElMessage, ElLoading } from 'element-plus' import { ElNotification, ElMessageBox, ElMessage, ElLoading } from 'element-plus'
import { getToken } from '@/utils/auth' import { getToken } from '@/utils/auth'
import errorCode from '@/utils/errorCode' import errorCode from '@/utils/errorCode'
import { tansParams, blobValidate } from '@/utils/ruoyi' import { tansParams, blobValidate } from '@/utils/ruoyi'
...@@ -21,14 +21,14 @@ const service = axios.create({ ...@@ -21,14 +21,14 @@ const service = axios.create({
}) })
// request拦截器 // request拦截器
service.interceptors.request.use(config => { service.interceptors.request.use(
config => {
// 添加租户ID到请求头 // 添加租户ID到请求头
const userStore = useUserStore() const userStore = useUserStore()
if (userStore.currentTenant) { // if (userStore.currentTenant) {
const tenantBizId = userStore.currentTenant.apiLoginTenantInfoResponse.tenantBizId // const tenantBizId = userStore.currentTenant.apiLoginTenantInfoResponse.tenantBizId
config.headers['X-Tenant-ID'] = tenantBizId // config.headers['X-Tenant-ID'] = tenantBizId
} // }
// 是否需要设置 token // 是否需要设置 token
const isToken = (config.headers || {}).isToken === false const isToken = (config.headers || {}).isToken === false
...@@ -64,23 +64,26 @@ service.interceptors.request.use(config => { ...@@ -64,23 +64,26 @@ service.interceptors.request.use(config => {
const s_data = sessionObj.data // 请求数据 const s_data = sessionObj.data // 请求数据
const s_time = sessionObj.time // 请求时间 const s_time = sessionObj.time // 请求时间
const interval = 1000 // 间隔时间(ms),小于此时间视为重复提交 const interval = 1000 // 间隔时间(ms),小于此时间视为重复提交
if (s_data === requestObj.data && requestObj.time - s_time < interval && s_url === requestObj.url) { // if (s_data === requestObj.data && requestObj.time - s_time < interval && s_url === requestObj.url) {
const message = '数据正在处理,请勿重复提交' // const message = '数据正在处理,请勿重复提交'
console.warn(`[${s_url}]: ` + message) // console.warn(`[${s_url}]: ` + message)
return Promise.reject(new Error(message)) // return Promise.reject(new Error(message))
} else { // } else {
cache.session.setJSON('sessionObj', requestObj) // cache.session.setJSON('sessionObj', requestObj)
} // }
} }
} }
return config return config
}, error => { },
error => {
console.log(error) console.log(error)
Promise.reject(error) Promise.reject(error)
}) }
)
// 响应拦截器 // 响应拦截器
service.interceptors.response.use(res => { service.interceptors.response.use(
res => {
// 未设置状态码则默认成功状态 // 未设置状态码则默认成功状态
const code = res.data.code || 200 const code = res.data.code || 200
// 获取错误信息 // 获取错误信息
...@@ -92,18 +95,32 @@ service.interceptors.response.use(res => { ...@@ -92,18 +95,32 @@ service.interceptors.response.use(res => {
if (code === 401) { if (code === 401) {
if (!isRelogin.show) { if (!isRelogin.show) {
isRelogin.show = true isRelogin.show = true
ElMessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', { confirmButtonText: '重新登录', cancelButtonText: '取消', type: 'warning' }).then(() => { ElMessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', {
confirmButtonText: '重新登录',
cancelButtonText: '取消',
type: 'warning'
})
.then(() => {
isRelogin.show = false isRelogin.show = false
useUserStore().logOut().then(() => { useUserStore()
location.href = '/index' .logOut()
.then(() => {
// location.href = '/index'
//token过期,跳转回中台的登录页
window.open(`${import.meta.env.VITE_APP_BASE_API1}/login?redirect=/workbench`)
// 然后立刻关闭自己
window.close()
}) })
}).catch(() => { })
.catch(() => {
isRelogin.show = false isRelogin.show = false
}) })
} }
return Promise.reject('无效的会话,或者会话已过期,请重新登录。') return Promise.reject('无效的会话,或者会话已过期,请重新登录。')
} else if (code === 500) { } else if (code === 500) {
ElMessage({ message: msg, type: 'error' }) ElMessage({ message: msg, type: 'error' })
console.log('msg', Promise.reject(new Error(msg)))
return Promise.reject(new Error(msg)) return Promise.reject(new Error(msg))
} else if (code === 601) { } else if (code === 601) {
ElMessage({ message: msg, type: 'warning' }) ElMessage({ message: msg, type: 'warning' })
...@@ -118,12 +135,12 @@ service.interceptors.response.use(res => { ...@@ -118,12 +135,12 @@ service.interceptors.response.use(res => {
error => { error => {
console.log('err' + error) console.log('err' + error)
let { message } = error let { message } = error
if (message == "Network Error") { if (message == 'Network Error') {
message = "后端接口连接异常" message = '后端接口连接异常'
} else if (message.includes("timeout")) { } else if (message.includes('timeout')) {
message = "系统接口请求超时" message = '系统接口请求超时'
} else if (message.includes("Request failed with status code")) { } else if (message.includes('Request failed with status code')) {
message = "系统接口" + message.substr(message.length - 3) + "异常" message = '系统接口' + message.substr(message.length - 3) + '异常'
} }
ElMessage({ message: message, type: 'error', duration: 5 * 1000 }) ElMessage({ message: message, type: 'error', duration: 5 * 1000 })
return Promise.reject(error) return Promise.reject(error)
...@@ -132,13 +149,22 @@ service.interceptors.response.use(res => { ...@@ -132,13 +149,22 @@ service.interceptors.response.use(res => {
// 通用下载方法 // 通用下载方法
export function download(url, params, filename, config) { export function download(url, params, filename, config) {
downloadLoadingInstance = ElLoading.service({ text: "正在下载数据,请稍候", background: "rgba(0, 0, 0, 0.7)", }) downloadLoadingInstance = ElLoading.service({
return service.post(url, params, { text: '正在下载数据,请稍候',
transformRequest: [(params) => { return tansParams(params) }], background: 'rgba(0, 0, 0, 0.7)'
})
return service
.post(url, params, {
transformRequest: [
params => {
return tansParams(params)
}
],
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
responseType: 'blob', responseType: 'blob',
...config ...config
}).then(async (data) => { })
.then(async data => {
const isBlob = blobValidate(data) const isBlob = blobValidate(data)
if (isBlob) { if (isBlob) {
const blob = new Blob([data]) const blob = new Blob([data])
...@@ -150,7 +176,8 @@ export function download(url, params, filename, config) { ...@@ -150,7 +176,8 @@ export function download(url, params, filename, config) {
ElMessage.error(errMsg) ElMessage.error(errMsg)
} }
downloadLoadingInstance.close() downloadLoadingInstance.close()
}).catch((r) => { })
.catch(r => {
console.error(r) console.error(r)
ElMessage.error('下载文件出现错误,请联系管理员!') ElMessage.error('下载文件出现错误,请联系管理员!')
downloadLoadingInstance.close() downloadLoadingInstance.close()
......
<template>
<div class="drawerBox">
<!-- direction="btt" -->
<el-drawer v-model="drawer" :before-close="handleBeforeClose" size="50%">
<template #header>
<h2>{{ drawerInfo.name }}</h2>
</template>
<template #default>
<div class="drawerContent">
<div class="item" v-for="e in menuList" :key="e.name">
<div class="left">{{ e.name }}</div>
<div class="right">
<el-input class="addressInput" v-model="e.value" :placeholder="e.placeholder" />
<el-icon v-if="e.icon" class="rightArrow"> <ArrowRight /></el-icon>
</div>
</div>
<div class="quickBox" v-if="addressList.length > 0">
<span class="title">快捷地址</span>
<div
class="quickItem"
v-for="(quick, index) in addressList"
:key="index"
@click="setAddress(quick)"
>
<el-icon class="locationIcon"><Location /></el-icon>
<span>{{ quick.region }}{{ quick.city }}{{ quick.street }}{{ quick.location }}</span>
</div>
</div>
</div>
</template>
<template #footer>
<div class="buttonBox">
<div class="left" @click.stop="resetClick">
<el-icon class="buttonIcon"><RefreshRight /></el-icon>
<span>重置</span>
</div>
<div class="right" @click.stop="confirmClick">
<el-icon><Check /></el-icon>
<span>保存</span>
</div>
</div>
</template>
</el-drawer>
</div>
</template>
<script setup name="AddressDrawer">
import deepClone from '@/utils/common'
import { watch, ref } from 'vue'
const props = defineProps({
showAddressDrawer: {
type: Boolean,
default: null
},
drawerInfo: {
type: Object,
default: () => {
return {}
}
},
addressMenuList: {
type: Array,
default: () => {
return []
}
},
addressQuickList: {
type: Array,
default: () => {
return []
}
}
})
const emit = defineEmits(['close', 'confirmDrawer'])
const { proxy } = getCurrentInstance()
const drawer = ref(false)
const menuList = ref([])
const addressList = ref([
{
region: '中国',
city: '北京',
street: '朝阳区',
location: '三里屯'
}
])
// 处理抽屉关闭前的事件
const handleBeforeClose = done => {
menuList.value = props.addressMenuList
emit('close')
drawer.value = false
done()
}
const resetClick = () => {
menuList.value.forEach(e => {
e.value = ''
})
}
const confirmClick = () => {
let info = JSON.parse(JSON.stringify(props.drawerInfo))
//收集填写的地址传给父组件
let location = {}
menuList.value.forEach(e => {
location[e.key] = e.value
})
for (const key in props.drawerInfo) {
if (key === info.key) {
info[key] = location
}
}
emit('confirmDrawer', info)
drawer.value = false
}
//通过快捷电话设置区号和电话号码
const setAddress = item => {
menuList.value.forEach(e => {
for (const key in item) {
if (e.key === key) {
e.value = item[e.key]
}
}
})
}
// 初始化menuList数据
const initMenuList = () => {
// 使用深拷贝创建新的数组,避免修改props
menuList.value = deepClone(props.addressMenuList)
}
// 监听父组件传递的showAddressDrawer变化
watch(
() => props.showAddressDrawer,
val => {
drawer.value = val
if (val) {
// 每次打开抽屉时初始化数据
nextTick(() => {
initMenuList()
})
}
}
)
watch(
() => props.addressQuickList,
val => {
addressList.value = val
},
{ immediate: true }
)
watch(drawer, val => {
if (!val) {
proxy.$emit('close', false)
}
})
</script>
<style lang="scss" scoped>
::v-deep .el-drawer__header {
margin-bottom: 0 !important;
}
::v-deep .el-drawer__footer {
padding: 0;
}
.addressInput ::v-deep .el-input__wrapper {
box-shadow: none !important;
}
.addressInput ::v-deep .el-input__inner::placeholder {
text-align: right;
}
.addressInput ::v-deep .el-input__inner {
text-align: right;
}
.addressInput ::v-deep .el-input__wrapper {
padding: 0 !important;
}
.drawerContent {
.item {
display: flex;
align-items: center;
justify-content: space-between;
border-bottom: 1px solid #e5e6e8;
margin-bottom: 20px;
padding: 10px;
color: #4e5969;
font-size: 14px;
.right {
display: flex;
align-items: center;
}
.rightArrow {
color: #4e5969;
font-size: 14px;
}
}
.quickBox {
.title {
font-size: 18px;
border-left: 4px solid #165dff;
padding-left: 5px;
}
.quickItem {
display: flex;
align-items: center;
justify-content: flex-start;
margin-top: 10px;
color: #1d2129;
font-size: 14px;
border: 1px solid #e5e6e8;
border-radius: 3px;
padding: 10px;
.locationIcon {
color: #1d2129;
font-size: 16px;
margin-right: 5px;
}
}
}
}
.buttonBox {
box-shadow: 0 -1px 14px #00000014;
width: 100%;
display: flex;
align-items: center;
justify-content: space-between;
.left,
.right {
display: flex;
align-items: center;
justify-content: center;
width: 50%;
font-size: 16px;
height: 60px;
}
.left {
background-color: #fff;
color: #165dff;
.buttonIcon {
font-size: 16px;
color: #165dff;
}
}
.right {
background-color: #165dff;
color: #fff;
.buttonIcon {
font-size: 16px;
color: #fff;
}
}
}
</style>
<template>
<div class="countryDrawerBox">
<!-- direction="btt" -->
<el-drawer
v-model="countryDrawer"
:before-close="handleBeforeClose"
class="countryBox"
size="50%"
>
<template #header>
<h2>国家/地区</h2>
</template>
<template #default>
<div class="countryContent">
<el-row>
<!-- 左侧 -->
<el-col :sm="20" :lg="21" class="content-col">
<el-row>
<el-col :span="24">
<div class="searchBox">
<el-input
class="searchInput"
v-model="searchValue"
placeholder="请输入国家/地区名称"
@change="searchCountry"
/>
<el-icon class="searchIcon"><Search /></el-icon>
</div>
</el-col>
</el-row>
<div class="hotCountryBox" ref="containerRef">
<div v-if="!searchValue">
<div class="title">热门国家/地区</div>
<div class="hotCountryList">
<el-row :gutter="20">
<template v-for="(item, index1) in hotCountriesList" :key="item.name">
<el-col :sm="12" :lg="8" @click="handleCountryClick(item)">
<div class="hotCountryItem">
<span>{{ item.name }}</span>
<span>{{ item.areaCode }}</span>
</div>
</el-col>
</template>
</el-row>
</div>
<div class="hotCountryList">
<template v-for="item in countryList" :key="item.areaCode">
<el-row>
<el-col :sm="24" :lg="24" style="margin: 5px 0">{{ item.title }}</el-col>
</el-row>
<el-row :gutter="20" :id="`${item.title}`">
<template v-for="(data, index2) in item.data" :key="item.name">
<el-col :span="24" @click="handleCountryClick(data)">
<div class="hotCountryItem">
<span>{{ data.name }}</span>
<span>{{ data.areaCode }}</span>
</div>
</el-col>
</template>
</el-row>
</template>
</div>
</div>
<div v-if="searchValue">
<div class="hotCountryList">
<el-row :gutter="20">
<template v-for="item in searchList" :key="item.name">
<el-col :sm="24" :lg="24" @click="handleCountryClick(item)">
<div class="hotCountryItem">
<span>{{ item.name }}</span>
<span>{{ item.areaCode }}</span>
</div>
</el-col>
</template>
</el-row>
</div>
</div>
</div>
</el-col>
<!-- 右侧锚点 -->
<el-col :sm="4" :lg="3">
<div class="anchor-wrapper">
<el-anchor
:container="containerRef"
direction="vertical"
type="default"
:offset="30"
@click="handleAnchorClick"
>
<el-anchor-link
v-for="item in anchorList"
:href="'#' + item.title"
:title="item.title"
/>
</el-anchor>
</div>
</el-col>
</el-row>
</div>
</template>
</el-drawer>
</div>
</template>
<script setup>
import { watch, ref } from 'vue'
import { getCountryInfo, getSearchCountry } from '@/api/common'
const props = defineProps({
showCountryDrawer: {
type: Boolean,
default: null
},
drawerInfo: {
type: Object,
default: () => {
return {}
}
}
})
const emit = defineEmits(['close', 'confirmCountry'])
const countryDrawer = ref(false)
const countryList = ref([])
const originalData = ref([])
const hotCountriesList = ref([])
const containerRef = ref(null)
const anchorList = ref([])
const searchValue = ref('')
const searchList = ref([])
const isSearchLoading = ref(false)
const searchCountry = () => {
isSearchLoading.value = true
if (searchValue.value.trim()) {
getSearchCountry(searchValue.value.trim()).then(res => {
if (res.code === 200) {
res.data.countryList.forEach(d => {
d.areaCode = `+${d.areaCode}`
})
searchList.value = res.data.countryList
isSearchLoading.value = false
}
})
}
}
const handleCountryClick = item => {
emit('confirmCountry', item)
countryDrawer.value = false
resetSearch()
}
// 锚点事件
const handleAnchorClick = e => {
e.preventDefault()
}
// 处理抽屉关闭前的事件
const handleBeforeClose = done => {
emit('close')
countryDrawer.value = false
resetSearch()
done()
}
// 生成A-Z的分组结构
const generateGroups = () => {
const groups = []
// 生成26个字母的分组
for (let i = 0; i < 26; i++) {
const letter = String.fromCharCode(65 + i)
groups.push({
title: letter,
data: []
})
}
// 将国家数据分配到对应分组
originalData.value.forEach(country => {
const firstLetter = country.group.toUpperCase()
const group = groups.find(g => g.title === firstLetter)
if (group) {
group.data.push(country)
}
})
// 按国家名称排序每个分组内的数据
groups.forEach(group => {
group.data.sort((a, b) => a.name.localeCompare(b.name, 'zh-CN'))
})
return groups.filter(group => group.data.length > 0)
}
// 获取国家信息
const getCountry = () => {
getCountryInfo().then(res => {
if (res.code === 200) {
originalData.value = res.data.groupCountries
const result = generateGroups()
result.forEach(item => {
anchorList.value.push({ title: item.title })
item.data.forEach(d => {
d.areaCode = `+${d.areaCode}`
})
})
res.data.hotCountries.forEach(item => {
item.areaCode = `+${item.areaCode}`
})
hotCountriesList.value = res.data.hotCountries
countryList.value = result
}
})
}
const resetSearch = () => {
searchValue.value = ''
searchList.value = []
isSearchLoading.value = false
}
watch(searchValue, val => {
if (!val) {
searchList.value = []
isSearchLoading.value = false
}
})
watch(
() => props.showCountryDrawer,
val => {
countryDrawer.value = val
if (countryDrawer.value) {
getCountry()
}
}
)
watch(countryDrawer, val => {
if (!val) {
resetSearch()
emit('close', false)
}
})
</script>
<style lang="scss" scoped>
::v-deep .el-drawer__header {
margin-bottom: 0 !important;
}
.searchInput ::v-deep .el-input__wrapper {
box-shadow: none !important;
background-color: #fafbfd !important;
}
.searchInput ::v-deep .el-input__inner::placeholder {
text-align: left !important;
}
.searchInput ::v-deep .el-input__inner {
text-align: left !important;
}
.countryContent {
box-sizing: border-box;
.searchBox {
box-sizing: border-box;
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 20px;
background-color: #fafbfd;
width: 100%;
border-radius: 10px;
padding: 4px 10px;
.el-input {
width: 80%;
}
.searchIcon {
font-size: 20px;
color: #1d2129;
}
}
.hotCountryBox {
overflow: hidden;
height: calc(100vh - 100px);
overflow-y: auto;
box-sizing: border-box;
width: 100%;
scrollbar-width: none;
-ms-overflow-style: none;
.title {
box-sizing: border-box;
font-size: 18px;
border-left: 4px solid #165dff;
padding-left: 5px;
margin-bottom: 10px;
}
.hotCountryList {
box-sizing: border-box;
width: 100%;
.hotCountryItem {
box-sizing: border-box;
height: 40px;
padding: 5px;
border: 1px solid #e5e6e8;
border-radius: 7px;
margin-bottom: 10px;
display: flex;
align-items: center;
justify-content: space-between;
font-size: 13px;
color: #595959;
}
.loading-container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 40px 0;
}
.loading-text {
margin-top: 10px;
color: #909399;
}
.empty-state {
text-align: center;
padding: 40px 0;
color: #909399;
}
}
}
.hotCountryBox::-webkit-scrollbar {
display: none;
}
.anchor-wrapper {
box-sizing: border-box;
margin-left: 20px;
border-left: 2px solid #d8ebff;
::v-deep(.el-anchor) {
.el-anchor__link {
padding: 4px 0;
.el-anchor__link-title {
font-size: 16px;
color: #1d2129;
&.is-active {
color: #165dff;
font-weight: 500;
}
}
}
}
::v-deep(.el-anchor__marker) {
height: 10px !important;
left: -6px !important;
border-radius: 50% !important;
width: 10px !important;
border: 1px solid #409eff !important;
background-color: transparent !important;
}
}
}
</style>
<template>
<div class="stepBox">
<div class="stepItem" v-for="step in stepList" :key="step.id">
<div
class="circle"
:class="{
finfish: step.finish,
todo: step.todo,
unFinish: step.unFinish
}"
>
<el-icon v-if="step.finish"><Check /></el-icon>
<span v-else>{{ step.id }}</span>
</div>
<div class="stepTitle">{{ step.title }}</div>
</div>
</div>
</template>
<script setup>
const props = defineProps({
stepList: {
type: Array,
default: () => []
}
})
</script>
<style lang="scss" scoped>
.stepBox {
width: 100%;
display: flex;
justify-content: center;
align-items: center;
.stepItem {
display: flex;
justify-content: center;
align-items: center;
margin-right: 100px;
box-sizing: border-box;
.circle {
width: 35px;
height: 35px;
box-sizing: border-box;
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
.el-icon {
font-size: 16px;
font-weight: 600;
}
}
.finfish {
background-color: #e8f3ff;
color: #165dff;
}
.todo {
background-color: #165dff;
color: #fff;
}
.unFinish {
background-color: #f2f3f5;
color: #4e5969;
}
.stepTitle {
font-size: 14px;
margin-left: 10px;
}
}
.stepItem:last-child {
margin-right: 0;
}
}
</style>
<template>
<div class="drawerBox">
<!-- direction="btt" -->
<el-drawer v-model="drawer" :before-close="handleBeforeClose" size="50%">
<template #header>
<h2>{{ drawerInfo.label }}</h2>
</template>
<template #default>
<div class="drawerContent">
<div class="item" v-for="e in menuList" :key="e.name">
<div class="left">{{ e.name }}</div>
<div class="right" @click="openCountryDrawer(e)">
<el-input
class="phoneInput"
v-model="e.value"
:placeholder="e.placeholder"
:type="e.type"
/>
<el-icon v-if="e.icon" class="rightArrow"> <ArrowRight /></el-icon>
</div>
</div>
<div class="quickBox" v-if="quickList.length > 0">
<span class="title">快捷电话</span>
<div
class="quickItem"
v-for="(quick, index) in quickList"
:key="index"
@click="setPhone(quick)"
>
<span>{{ quick.code }}</span>
<span style="margin-left: 5px">{{ quick.mobile }}</span>
</div>
</div>
</div>
</template>
<template #footer>
<div class="buttonBox">
<div class="left" @click.stop="resetClick">
<el-icon class="buttonIcon"><RefreshRight /></el-icon>
<span>重置</span>
</div>
<div class="right" @click.stop="confirmClick">
<el-icon><Check /></el-icon>
<span>保存</span>
</div>
</div>
</template>
</el-drawer>
<Country
:showCountryDrawer="showCountryDrawer"
@close="hanleCountryClose"
@confirmCountry="confirmCountry"
/>
</div>
</template>
<script setup name="PhoneDrawer">
import { watch, ref } from 'vue'
import Country from '@/views/components/country'
import deepClone from '@/utils/common'
const props = defineProps({
showDrawer: {
type: Boolean,
default: null
},
drawerInfo: {
type: Object,
default: () => {
return {}
}
},
phoneMenuList: {
type: Array,
default: () => {
return []
}
},
phoneQuickList: {
type: Array,
default: () => {
return []
}
}
})
const emit = defineEmits(['close', 'confirmDrawer'])
const { proxy } = getCurrentInstance()
const drawer = ref(false)
const showCountryDrawer = ref(false) //国家地区抽屉开关
const menuList = ref([])
const quickList = ref([])
const confirmCountry = item => {
menuList.value[0].value = item.areaCode
console.log('====================================')
console.log('menuList.value', menuList.value)
console.log('====================================')
hanleCountryClose()
}
const openCountryDrawer = item => {
if (item.arrow) {
showCountryDrawer.value = true
}
}
// 处理抽屉关闭前的事件
const handleBeforeClose = done => {
menuList.value = props.phoneMenuList
emit('close')
drawer.value = false
done()
}
const resetClick = () => {
menuList.value.forEach(e => {
e.value = ''
})
}
const confirmClick = () => {
let info = JSON.parse(JSON.stringify(props.drawerInfo))
//收集填写的电话传给父组件
let phone = {}
menuList.value.forEach(e => {
phone[e.key] = e.value
})
for (const key in props.drawerInfo) {
if (key === info.key) {
info[key] = phone
}
}
emit('confirmDrawer', info)
drawer.value = false
}
//通过快捷电话设置区号和电话号码
const setPhone = item => {
console.log('menuList', menuList.value)
console.log('item', item)
menuList.value[0].value = item.code
menuList.value[1].value = item.mobile
// menuList.value.forEach(e => {
// for (const key in item) {
// if (e.key === key) {
// e.value = item[e.key]
// }
// }
// })
}
// 关闭国家地区的抽屉
const hanleCountryClose = () => {
showCountryDrawer.value = false
}
// 初始化menuList数据
const initMenuList = () => {
// 使用深拷贝创建新的数组,避免修改props
menuList.value = deepClone(props.phoneMenuList)
}
watch(
() => props.showDrawer,
val => {
drawer.value = val
if (val) {
// 每次打开抽屉时初始化数据
nextTick(() => {
initMenuList()
})
}
}
)
watch(drawer, val => {
if (!val) {
proxy.$emit('close', false)
}
})
watch(
() => props.phoneQuickList,
val => {
quickList.value = val
},
{ immediate: true }
)
</script>
<style lang="scss" scoped>
::v-deep .el-drawer__header {
margin-bottom: 0 !important;
}
::v-deep .el-drawer__footer {
padding: 0;
}
.phoneInput ::v-deep .el-input__wrapper {
box-shadow: none !important;
}
.phoneInput ::v-deep .el-input__inner::placeholder {
text-align: right;
}
.phoneInput ::v-deep .el-input__inner {
text-align: right;
}
.phoneInput ::v-deep .el-input__wrapper {
padding: 0 !important;
}
.drawerContent {
.item {
display: flex;
align-items: center;
justify-content: space-between;
border-bottom: 1px solid #e5e6e8;
margin-bottom: 20px;
padding: 10px;
color: #4e5969;
font-size: 14px;
.right {
display: flex;
align-items: center;
}
.rightArrow {
color: #4e5969;
font-size: 14px;
}
}
.quickBox {
.title {
font-size: 18px;
border-left: 4px solid #165dff;
padding-left: 5px;
}
.quickItem {
display: flex;
align-items: center;
justify-content: flex-start;
margin-top: 10px;
color: #1d2129;
font-size: 14px;
border: 1px solid #e5e6e8;
border-radius: 3px;
padding: 10px;
}
}
}
.buttonBox {
box-shadow: 0 -1px 14px #00000014;
width: 100%;
display: flex;
align-items: center;
justify-content: space-between;
.left,
.right {
display: flex;
align-items: center;
justify-content: center;
width: 50%;
font-size: 16px;
height: 60px;
}
.left {
background-color: #fff;
color: #165dff;
.buttonIcon {
font-size: 16px;
color: #165dff;
}
}
.right {
background-color: #165dff;
color: #fff;
.buttonIcon {
font-size: 16px;
color: #fff;
}
}
}
</style>
<template>
<div class="app-container">
<!-- 步骤条 -->
<el-row style="margin-bottom: 30px">
<el-col :span="24">
<Step :stepList="stepList"></Step>
</el-col>
</el-row>
<!-- 条件查询 -->
<el-row>
<el-col :span="24">
<el-form
:model="queryParams"
ref="queryRef"
:inline="true"
v-show="showSearch"
label-width="70px"
>
<el-form-item
><el-button type="primary" icon="Plus" @click="handleAdd"
>新建流程</el-button
></el-form-item
>
<el-form-item label="创建时间" style="width: 300px">
<el-date-picker
v-model="dateRange"
value-format="YYYY-MM-DD"
type="daterange"
range-separator="-"
start-placeholder="开始日期"
end-placeholder="结束日期"
></el-date-picker>
</el-form-item>
<el-form-item label="流程编号" prop="fnaNo">
<el-input
v-model="queryParams.fnaNo"
placeholder="请输入流程编号"
clearable
style="width: 150px"
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label="客户姓名" prop="customerName">
<el-input
v-model="queryParams.customerName"
placeholder="请输入姓名"
clearable
style="width: 140px"
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select
v-model="queryParams.status"
placeholder="请选择"
clearable
style="width: 110px"
>
<el-option
v-for="dict in csf_fna_status"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">查询</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
</el-col>
</el-row>
<el-table
v-loading="loading"
:data="tenantList"
@selection-change="tableSelect"
:default-sort="{ prop: 'createTime', order: 'descending' }"
>
<el-table-column type="selection" width="55" />
<el-table-column label="流程编号" align="center" prop="fnaNo" width="200" />
<el-table-column label="预约编号" align="center" prop="appointmentNo" width="150" />
<el-table-column label="新单编号" align="center" prop="policyId" />
<el-table-column label="保单号" align="center" prop="policyNo" />
<el-table-column label="客户姓名" align="center" prop="customerName" />
<el-table-column label="状态" align="center" width="150">
<template #default="scope">
<span v-if="scope.row.status == 'UNCOMPLETED'">
<span style="color: #ff7d00" class="iconfont icon-yanqiweiwancheng"></span> 未完成
</span>
<span v-if="scope.row.status == 'COMPLETED'"
><span style="color: #43cf7c" class="iconfont icon-yiwancheng"></span> 已完成
</span>
</template>
</el-table-column>
<!-- sortable 后端未做 -->
<el-table-column label="创建时间" align="center" prop="createTime">
<template #default="scope">
<span>{{ parseTime(scope.row.createTime) }}</span>
</template>
</el-table-column>
<el-table-column
label="操作"
align="center"
width="200"
class-name="small-padding fixed-width"
>
<template #default="scope">
<el-button link type="primary" @click="handleUpdate(scope.row)">修改</el-button>
<!-- v-if="scope.row.status == 'COMPLETED'" -->
<el-button link type="primary" @click="handleDelete(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total >= 0"
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
<!-- 下一步到预约 -->
<div class="bottomBtn">
<el-button type="primary" @click="goToAppointment">下一步</el-button>
</div>
</div>
</template>
<script setup name="FnaList">
import Step from '@/views/components/moduleStep'
import useAppStore from '@/store/modules/app'
import {
changeUserStatus,
listTenant,
resetUserPwd,
delUser,
getTenant,
updateTenant,
addTenant,
changeTenantStatus
} from '@/api/system/tenant'
import { getFnaList, deleteFna } from '@/api/sign/fna'
import useUserStore from '@/store/modules/user'
const stepList = ref([
{ title: 'FNA', id: 1, finish: false, todo: true, unFinish: false },
{ title: '预约', id: 2, todo: false, finish: false, unFinish: true },
{ title: '新单跟进', id: 3, finish: false, todo: false, unFinish: true }
])
const userStore = useUserStore()
const router = useRouter()
const { proxy } = getCurrentInstance()
const { sys_status, csf_fna_status, sys_no_yes } = proxy.useDict(
'sys_status',
'csf_fna_status',
'sys_no_yes'
)
const tenantList = ref([])
const open = ref(false)
const loading = ref(true)
const showSearch = ref(true)
const ids = ref([])
const single = ref(true)
const multiple = ref(true)
const total = ref(0)
const dateRange = ref([])
const selectIdsList = ref([])
const data = reactive({
form: {},
queryParams: {
pageNo: 1,
pageSize: 8,
startTime: '',
endTime: ''
}
})
const { queryParams, form, rules } = toRefs(data)
/** 多选框选中数据 */
function tableSelect(selection) {
selectIdsList.value = selection.map(item => item.projectBizId)
}
const goToAppointment = () => {
router.push({ path: '/sign/appointment' })
}
/** 查询租户列表 */
function getList() {
if (dateRange.value.length > 0) {
queryParams.value.startTime = `${dateRange.value[0]} 00:00:00`
queryParams.value.endTime = `${dateRange.value[1]} 23:59:59`
}
loading.value = true
try {
getFnaList(queryParams.value).then(response => {
tenantList.value = response.data.records
total.value = response.data.total
loading.value = false
})
} catch (error) {
tenantList.value = []
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
function handleQuery() {
queryParams.value.pageNo = 1
getList()
}
/** 重置按钮操作 */
function resetQuery() {
dateRange.value = []
proxy.resetForm('queryRef')
queryParams.value = {
pageNo: 1,
pageSize: 8,
startTime: '',
endTime: ''
}
handleQuery()
}
/** 删除按钮操作 */
function handleDelete(row) {
proxy.$modal
.confirm('是否确认删除' + row.customerName + '的FNA流程?')
.then(function () {
return deleteFna({ fnaBizId: row.fnaBizId })
})
.then(() => {
getList()
proxy.$modal.msgSuccess('删除成功')
})
.catch(() => {})
}
/** 租户状态修改 */
function handleStatusChange(row, event) {
let text = row.status === 0 ? '停用' : '启用'
const tenantName = row.tenantName
proxy.$modal
.confirm(`确认要${text}"${tenantName}"租户吗?`)
.then(() => changeTenantStatus({ tenantBizId: row.tenantBizId, status: row.status }))
.then(() => proxy.$modal.msgSuccess(`${text}成功`))
.catch(() => {
// 操作取消时恢复原状态
row.status = row.status === 0 ? 1 : 0
})
}
/** 重置操作表单 */
function reset() {
form.value = {
pageNo: 1,
pageSize: 8
}
proxy.resetForm('tenantRef')
}
/** 新增按钮操作 */
function handleAdd() {
router.push('/sign/FnaList/edit?type=add')
}
/** 修改按钮操作 */
function handleUpdate(row) {
router.push({ path: '/sign/FnaList/edit', query: { fnaBizId: row.fnaBizId, type: 'edit' } })
}
getList()
</script>
<style lang="scss" scoped>
/* ::v-deep .el-step__head.is-success {
color: none !important;
background-color: #e8f3ff !important;
border: none !important;
} */
/* ::v-deep .el-step__icon {
background-color: #e8f3ff !important;
} */
.bottomBtn {
width: 100%;
text-align: right;
margin-top: 20px;
}
</style>
...@@ -94,7 +94,7 @@ ...@@ -94,7 +94,7 @@
v-if="(userStore.isSuperAdmin === 0 && scope.row.scope !== 1) || userStore.isSuperAdmin === 1">分配权限</el-button> v-if="(userStore.isSuperAdmin === 0 && scope.row.scope !== 1) || userStore.isSuperAdmin === 1">分配权限</el-button>
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)"
v-if="(userStore.isSuperAdmin === 0 && scope.row.scope !== 1) || userStore.isSuperAdmin === 1">修改</el-button> v-if="(userStore.isSuperAdmin === 0 && scope.row.scope !== 1) || userStore.isSuperAdmin === 1">修改</el-button>
<!-- <el-button link type="primary" icon="View" @click="handleUpdate(scope.row)" >详情</el-button>-->
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)"
v-if="(userStore.isSuperAdmin === 0 && scope.row.scope !== 1) || userStore.isSuperAdmin === 1">删除</el-button> v-if="(userStore.isSuperAdmin === 0 && scope.row.scope !== 1) || userStore.isSuperAdmin === 1">删除</el-button>
</template> </template>
......
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