敏感数据加密和查看密文
This commit is contained in:
parent
461eba8f93
commit
dda013c4a9
|
|
@ -274,3 +274,18 @@ export function crmContactsExitTeamAPI(data) {
|
|||
method: 'post'
|
||||
})
|
||||
}
|
||||
/**
|
||||
* 获取明文
|
||||
* @param data
|
||||
* @returns {*}
|
||||
*/
|
||||
export function filedGetPlaintextAPI(data) {
|
||||
return request({
|
||||
url: 'crmContacts/getPlaintext',
|
||||
method: 'post',
|
||||
data: data,
|
||||
headers: {
|
||||
'Content-Type': 'application/json;charset=UTF-8'
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -711,3 +711,35 @@ export function crmCustomerInvoiceInfoAPI(data) {
|
|||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取明文
|
||||
* @param data
|
||||
* @returns {*}
|
||||
*/
|
||||
export function filedGetPlaintextAPI(data) {
|
||||
return request({
|
||||
url: 'crmCustomer/getPlaintext',
|
||||
method: 'post',
|
||||
data: data,
|
||||
headers: {
|
||||
'Content-Type': 'application/json;charset=UTF-8'
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证企业画像的密码
|
||||
* @param data
|
||||
* @returns {*}
|
||||
*/
|
||||
export function verifyPasswordAPI(data) {
|
||||
return request({
|
||||
url: 'crmCustomer/verifyPassword',
|
||||
method: 'post',
|
||||
data: data,
|
||||
headers: {
|
||||
'Content-Type': 'application/json;charset=UTF-8'
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1757056872697" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1347" width="16" height="16" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M512.048 768a224 224 0 1 1 0-448 224 224 0 0 1 0 448z m0-64a160 160 0 1 0 0-320 160 160 0 0 0 0 320z" p-id="1348" fill="#8a8a8a"></path><path d="M674.992 706.944Q742.448 639.36 742.448 544q0-95.424-67.456-162.944Q607.408 313.6 512.048 313.6q-95.424 0-162.944 67.456Q281.648 448.64 281.648 544q0 95.424 67.456 162.944Q416.688 774.4 512.048 774.4q95.424 0 162.944-67.456z m-9.088-316.8q63.744 63.744 63.744 153.856t-63.744 153.856Q602.16 761.6 512.048 761.6t-153.856-63.744Q294.448 634.112 294.448 544t63.744-153.856Q421.936 326.4 512.048 326.4t153.856 63.744z m-271.488 36.16Q345.648 475.072 345.648 544t48.704 117.632Q443.184 710.4 512.048 710.4t117.632-48.768q48.768-48.704 48.768-117.632T629.68 426.24Q580.976 377.6 512.048 377.6t-117.632 48.704z m8.96 226.304Q358.448 607.616 358.448 544q0-63.616 44.992-108.608Q448.432 390.4 512.048 390.4q63.616 0 108.608 44.992 44.992 44.992 44.992 108.608 0 63.616-44.992 108.608Q575.664 697.6 512.048 697.6q-63.616 0-108.608-44.992z" p-id="1349" fill="#8a8a8a"></path><path d="M512.048 896C323.248 896 154.224 783.232 5.488 561.856a32 32 0 0 1 0-35.712C154.288 304.704 323.248 192 512.048 192s357.824 112.704 506.56 334.144a32 32 0 0 1 0 35.712c-148.736 221.44-317.76 334.08-506.56 334.08z m0-64c159.872 0 306.752-94.784 441.216-288C818.8 350.72 671.92 256 512.048 256 352.24 256 205.36 350.784 70.832 544 205.36 737.216 352.24 832 512.048 832z" p-id="1350" fill="#8a8a8a"></path><path d="M512.048 896C323.248 896 154.224 783.232 5.488 561.856a32 32 0 0 1 0-35.712C154.288 304.704 323.248 192 512.048 192s357.824 112.704 506.56 334.144a32 32 0 0 1 0 35.712c-148.736 221.44-317.76 334.08-506.56 334.08z m0-12.8q275.328 0 495.936-328.512 7.168-10.688 0-21.44Q787.376 204.8 512.048 204.8T16.112 533.312q-7.232 10.688 0 21.376Q236.72 883.2 512.048 883.2z m0-38.4q-247.424 0-451.776-293.504L55.152 544l5.12-7.296Q264.624 243.2 512.048 243.2t451.776 293.504l5.12 7.296-5.12 7.296Q759.472 844.8 512.048 844.8z m0-12.8c159.872 0 306.752-94.784 441.216-288C818.8 350.72 671.92 256 512.048 256 352.24 256 205.36 350.784 70.832 544 205.36 737.216 352.24 832 512.048 832z" p-id="1351" fill="#8a8a8a"></path></svg>
|
||||
|
After Width: | Height: | Size: 2.4 KiB |
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 427 KiB After Width: | Height: | Size: 426 KiB |
|
|
@ -28,7 +28,7 @@
|
|||
type="primary"
|
||||
icon="wk wk-transfer"
|
||||
@click.native="handleTypeClick('transfer')">转移</el-button>
|
||||
<el-button v-if="crmType === 'customer'" type="primary" icon="el-icon-s-opportunity" @click="showQyHx">企业画像</el-button>
|
||||
<el-button v-if="crmType === 'customer'" type="primary" icon="el-icon-s-opportunity" @click="popPasswordBox">企业画像</el-button>
|
||||
<el-button
|
||||
v-if="showEdit"
|
||||
class="head-handle-button xr-btn--green"
|
||||
|
|
@ -118,6 +118,28 @@
|
|||
:id="id"
|
||||
:pool-id="poolId"
|
||||
/>
|
||||
<!-- 密码验证对话框 -->
|
||||
<el-dialog
|
||||
:visible.sync="showPasswordDialog"
|
||||
title="验证密码"
|
||||
width="400px"
|
||||
append-to-body>
|
||||
<el-form>
|
||||
<el-form-item label="密码">
|
||||
<el-input
|
||||
v-model="passwordValue"
|
||||
type="password"
|
||||
placeholder="请输入验证密码"
|
||||
@keyup.enter.native="verifyPassword"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<p v-if="errorMessage" class="error-message">{{ errorMessage }}</p>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button @click="showPasswordDialog = false">取消</el-button>
|
||||
<el-button :loading="verifying" type="primary" @click="verifyPassword">验证</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
<script type="text/javascript">
|
||||
|
|
@ -150,7 +172,8 @@ import TransferHandle from './SelectionHandle/TransferHandle' // 转移
|
|||
import AllocHandle from './SelectionHandle/AllocHandle' // 公海分配操作
|
||||
import DealStatusHandle from './SelectionHandle/DealStatusHandle' // 客户状态修改操作
|
||||
import PutPoolHandle from './SelectionHandle/PutPoolHandle'
|
||||
import EnterpriseProfile from './EnterpriseProfile.vue' // 放入公海
|
||||
import EnterpriseProfile from './EnterpriseProfile.vue'
|
||||
import { verifyPasswordAPI } from '../../../api/crm/customer' // 放入公海
|
||||
|
||||
export default {
|
||||
name: 'CRMDetailHead',
|
||||
|
|
@ -205,7 +228,10 @@ export default {
|
|||
allocDialogShow: false, // 公海分配操作提示框
|
||||
dealStatusShow: false, // 成交状态修改框
|
||||
putPoolShow: false, // 客户放入公海
|
||||
EnterpriseProfileShow: false // 企业画像
|
||||
EnterpriseProfileShow: false, // 企业画像
|
||||
showPasswordDialog: false, // 控制密码对话框显示
|
||||
errorMessage: '', // 错误提示
|
||||
passwordValue: '' // 密码
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
|
@ -694,6 +720,32 @@ export default {
|
|||
|
||||
return true
|
||||
},
|
||||
/**
|
||||
* 弹出密码框
|
||||
*/
|
||||
popPasswordBox() {
|
||||
this.passwordValue = ''
|
||||
this.errorMessage = ''
|
||||
this.showPasswordDialog = true
|
||||
},
|
||||
/**
|
||||
* 验证密码
|
||||
*/
|
||||
verifyPassword() {
|
||||
const data = {
|
||||
password: this.passwordValue
|
||||
}
|
||||
verifyPasswordAPI(data)
|
||||
.then(res => {
|
||||
this.showPasswordDialog = false
|
||||
this.showQyHx()
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('验证请求失败:', error)
|
||||
this.errorMessage = error.msg
|
||||
this.passwordValue = ''
|
||||
})
|
||||
},
|
||||
showQyHx() {
|
||||
console.log(this.EnterpriseProfileShow)
|
||||
this.EnterpriseProfileShow = true
|
||||
|
|
@ -818,4 +870,10 @@ export default {
|
|||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.error-message {
|
||||
color: #f56c6c;
|
||||
font-size: 12px;
|
||||
margin-top: 8px;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -144,6 +144,13 @@
|
|||
</template>
|
||||
</wk-field-view>
|
||||
|
||||
<!-- 添加眼睛图标 -->
|
||||
<img
|
||||
v-if="triggerEyeField(item.fieldName)"
|
||||
:src="eyeClosedSrc"
|
||||
class="eye-icon"
|
||||
@click="changeEyeState(item)"
|
||||
>
|
||||
<i v-if="getEditAuth(item)" class="wk wk-edit form-item__edit" @click.stop="editClick(item, index)" />
|
||||
</flexbox>
|
||||
</template>
|
||||
|
|
@ -162,6 +169,47 @@
|
|||
:visible.sync="showFullDetail"
|
||||
:id="fullDetailId"
|
||||
:crm-type="fullDetailType"/>
|
||||
<!-- 密码验证对话框 -->
|
||||
<el-dialog
|
||||
:visible.sync="showPasswordDialog"
|
||||
title="验证密码"
|
||||
width="400px"
|
||||
append-to-body>
|
||||
<el-form>
|
||||
<el-form-item label="密码">
|
||||
<el-input
|
||||
v-model="passwordValue"
|
||||
type="password"
|
||||
placeholder="请输入验证密码"
|
||||
@keyup.enter.native="verifyPasswordAndGetPlaintext"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<p v-if="errorMessage" class="error-message">{{ errorMessage }}</p>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button @click="showPasswordDialog = false">取消</el-button>
|
||||
<el-button :loading="verifying" type="primary" @click="verifyPasswordAndGetPlaintext">验证</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
<!-- 明文弹框 -->
|
||||
<el-dialog
|
||||
:visible.sync="showPlaintext"
|
||||
title="明文"
|
||||
width="500px"
|
||||
append-to-body>
|
||||
<div class="plaintext-content">
|
||||
<el-input
|
||||
:autosize="{ minRows: 3, maxRows: 6 }"
|
||||
:value="plaintextValues"
|
||||
type="textarea"
|
||||
readonly
|
||||
class="plaintext-field"
|
||||
/>
|
||||
</div>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button @click="showPlaintext = false">确定</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
@ -185,6 +233,7 @@ import { isArray, isObject, isEmpty } from '@/utils/types'
|
|||
import { mapGetters } from 'vuex'
|
||||
import { getFormFieldShowName } from '@/components/NewCom/WkForm/utils'
|
||||
import CustomFieldsMixin from '@/mixins/CustomFields'
|
||||
import { filedGetPlaintextAPI } from '../../../api/crm/customer'
|
||||
|
||||
export default {
|
||||
// 客户管理 的 基本信息
|
||||
|
|
@ -268,7 +317,14 @@ export default {
|
|||
}, {
|
||||
name: '收据',
|
||||
value: 5
|
||||
}]
|
||||
}],
|
||||
eyeClosedSrc: require('@/assets/img/crm/eye-open.svg'), // 闭眼图标路径
|
||||
showPasswordDialog: false, // 控制密码对话框显示
|
||||
currentField: null, // 当前操作的字段
|
||||
plaintextValues: null, // 明文
|
||||
showPlaintext: false, // 明文弹框
|
||||
passwordValue: '', // 密码
|
||||
errorMessage: '' // 错误提示
|
||||
}
|
||||
},
|
||||
inject: ['rootTabs'],
|
||||
|
|
@ -728,6 +784,46 @@ export default {
|
|||
return dataValue ? dataValue.name : ''
|
||||
}
|
||||
return ''
|
||||
},
|
||||
/**
|
||||
* 触发眼睛的字段
|
||||
*/
|
||||
triggerEyeField(fieldName) {
|
||||
return ['mobile', 'email', 'fieldCbiasz', 'fliedKjhmgc', 'name', 'telephone', 'address'].includes(fieldName)
|
||||
},
|
||||
/**
|
||||
* 切换眼睛
|
||||
*/
|
||||
changeEyeState(item) {
|
||||
console.log(item)
|
||||
this.passwordValue = ''
|
||||
this.errorMessage = ''
|
||||
this.plaintextValues = null
|
||||
this.showPasswordDialog = true
|
||||
this.currentField = item.fieldName
|
||||
},
|
||||
/**
|
||||
* 验证密码并获取明文
|
||||
*/
|
||||
verifyPasswordAndGetPlaintext() {
|
||||
const data = {
|
||||
id: this.id,
|
||||
field: this.currentField,
|
||||
password: this.passwordValue,
|
||||
poolId: this.poolId,
|
||||
crmType: this.crmType
|
||||
}
|
||||
filedGetPlaintextAPI(data)
|
||||
.then(res => {
|
||||
this.plaintextValues = res.data
|
||||
this.showPasswordDialog = false
|
||||
this.showPlaintext = true
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('验证请求失败:', error)
|
||||
this.errorMessage = error.msg
|
||||
this.passwordValue = ''
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -795,6 +891,9 @@ export default {
|
|||
.form-item__edit{
|
||||
display: inline;
|
||||
}
|
||||
.eye-icon{
|
||||
display: inline;
|
||||
}
|
||||
}
|
||||
|
||||
&.is-desc_text {
|
||||
|
|
@ -859,4 +958,21 @@ export default {
|
|||
word-break: break-all;
|
||||
}
|
||||
}
|
||||
.eye-icon {
|
||||
cursor: pointer; /* 将鼠标光标变为手指形状 */
|
||||
transition: filter 0.3s ease; /* 添加颜色变化的过渡动画,使效果更柔和 */
|
||||
display: none;
|
||||
}
|
||||
.eye-icon:hover {
|
||||
filter: brightness(1.2) saturate(150%) hue-rotate(380deg);
|
||||
}
|
||||
.error-message {
|
||||
color: #f56c6c;
|
||||
font-size: 12px;
|
||||
margin-top: 8px;
|
||||
}
|
||||
.plaintext-field {
|
||||
border-radius: 12px; /* 更大的圆角 */
|
||||
overflow: hidden; /* 防止内容溢出圆角 */
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -70,18 +70,25 @@
|
|||
show-overflow-tooltip />
|
||||
<el-table-column
|
||||
label="操作"
|
||||
width="100">
|
||||
width="260">
|
||||
<template slot-scope="scope">
|
||||
<flexbox justify="center">
|
||||
<flexbox>
|
||||
<span
|
||||
v-if="contactsId == scope.row.contactsId"
|
||||
v-if="contactsId === scope.row.contactsId"
|
||||
class="chief">
|
||||
<i class="wk wk-success" />首要联系人</span>
|
||||
<i class="wk wk-success" />首要联系人
|
||||
</span>
|
||||
<el-button
|
||||
v-else-if="!isSeas"
|
||||
class="set-chief-btn"
|
||||
type="text"
|
||||
@click.native="setChieflyContacts(scope)">设为首要联系人</el-button>
|
||||
@click.native="setChieflyContacts(scope)">设为首要联系人
|
||||
</el-button>
|
||||
<el-button
|
||||
class="set-chief-btn"
|
||||
type="text"
|
||||
@click.native="viewPlaintext(scope.row.contactsId)">查看明文
|
||||
</el-button>
|
||||
</flexbox>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
|
@ -97,6 +104,48 @@
|
|||
crm-type="contacts"
|
||||
@save-success="createSaveSuccess"
|
||||
@close="isCreate=false" />
|
||||
|
||||
<!-- 密码验证对话框 -->
|
||||
<el-dialog
|
||||
:visible.sync="showPasswordDialog"
|
||||
title="验证密码"
|
||||
width="400px"
|
||||
append-to-body>
|
||||
<el-form>
|
||||
<el-form-item label="密码">
|
||||
<el-input
|
||||
v-model="passwordValue"
|
||||
type="password"
|
||||
placeholder="请输入验证密码"
|
||||
@keyup.enter.native="verifyPasswordAndGetPlaintext"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<p v-if="errorMessage" class="error-message">{{ errorMessage }}</p>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button @click="showPasswordDialog = false">取消</el-button>
|
||||
<el-button :loading="verifying" type="primary" @click="verifyPasswordAndGetPlaintext">验证</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
<!-- 明文弹框 -->
|
||||
<el-dialog
|
||||
:visible.sync="showPlaintext"
|
||||
title="明文"
|
||||
width="500px"
|
||||
append-to-body>
|
||||
<div class="plaintext-content">
|
||||
<el-input
|
||||
:autosize="{ minRows: 3, maxRows: 6 }"
|
||||
:value="plaintextValues"
|
||||
type="textarea"
|
||||
readonly
|
||||
class="plaintext-field"
|
||||
/>
|
||||
</div>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button @click="showPlaintext = false">确定</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
@ -114,6 +163,7 @@ import {
|
|||
} from '@/api/crm/business'
|
||||
import CrmRelative from '@/components/CreateCom/CrmRelative'
|
||||
import { getPermissionByKey } from '@/utils'
|
||||
import { filedGetPlaintextAPI } from '../../../api/crm/contacts'
|
||||
|
||||
export default {
|
||||
name: 'RelativeContacts', // 相关联系人列表 可能再很多地方展示 放到客户管理目录下
|
||||
|
|
@ -128,6 +178,8 @@ export default {
|
|||
id: [String, Number],
|
||||
// 首要联系人ID
|
||||
contactsId: [String, Number],
|
||||
// 联系人ID
|
||||
selectedContactsId: [String, Number],
|
||||
// 客户类型
|
||||
crmType: {
|
||||
type: String,
|
||||
|
|
@ -162,7 +214,12 @@ export default {
|
|||
createActionInfo: { type: 'relative', crmType: this.crmType, data: {}},
|
||||
// 关联的逻辑
|
||||
showRelativeView: false,
|
||||
selectionList: []
|
||||
selectionList: [],
|
||||
showPasswordDialog: false, // 控制密码对话框显示
|
||||
errorMessage: '', // 错误提示
|
||||
plaintextValues: null, // 明文
|
||||
showPlaintext: false, // 明文弹框
|
||||
passwordValue: '' // 密码
|
||||
}
|
||||
},
|
||||
inject: ['rootTabs'],
|
||||
|
|
@ -362,6 +419,37 @@ export default {
|
|||
this.$bus.emit('crm-tab-num-update')
|
||||
})
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 点击查看明文
|
||||
*/
|
||||
viewPlaintext(selectedContactsId) {
|
||||
this.passwordValue = ''
|
||||
this.errorMessage = ''
|
||||
this.plaintextValues = null
|
||||
this.showPasswordDialog = true
|
||||
this.selectedContactsId = selectedContactsId
|
||||
},
|
||||
/**
|
||||
* 验证密码并获取明文
|
||||
*/
|
||||
verifyPasswordAndGetPlaintext() {
|
||||
const data = {
|
||||
id: this.selectedContactsId,
|
||||
password: this.passwordValue
|
||||
}
|
||||
console.log(data)
|
||||
filedGetPlaintextAPI(data)
|
||||
.then(res => {
|
||||
this.plaintextValues = res.data
|
||||
this.showPasswordDialog = false
|
||||
this.showPlaintext = true
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('验证请求失败:', error)
|
||||
this.errorMessage = error.msg
|
||||
this.passwordValue = ''
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -371,16 +459,24 @@ export default {
|
|||
|
||||
.set-chief-btn {
|
||||
font-size: 12px;
|
||||
padding: 4px 12px;
|
||||
padding: 2px 10px;
|
||||
width: 150px;
|
||||
}
|
||||
|
||||
.chief {
|
||||
font-size: 12px;
|
||||
color: #333;
|
||||
padding: 2px 10px;
|
||||
i {
|
||||
font-size: 14px;
|
||||
color: #389e0b;
|
||||
margin-right: 3px;
|
||||
margin-right: 2px;
|
||||
}
|
||||
width: 150px;
|
||||
}
|
||||
.error-message {
|
||||
color: #f56c6c;
|
||||
font-size: 12px;
|
||||
margin-top: 8px;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
Loading…
Reference in New Issue