changes
This commit is contained in:
36
components/menu/MarkData.vue
Normal file
36
components/menu/MarkData.vue
Normal file
@@ -0,0 +1,36 @@
|
||||
<template>
|
||||
<div>{{maskLoanAndAmountByKeyword(row.content)}}</div>
|
||||
</template>
|
||||
<script setup>
|
||||
const props = defineProps({
|
||||
row: Object
|
||||
})
|
||||
function maskLoanAndAmountByKeyword(str) {
|
||||
// Che mã đơn vay sau từ "đơn vay"
|
||||
let result = str.replace(/(đơn vay\s+)([A-Z]{2})(\d+)(\d{3})/gi, (m, prefix, letters, middle, last3) => {
|
||||
return prefix + letters + '*'.repeat(middle.length) + last3;
|
||||
});
|
||||
|
||||
// Che mã đơn vay sau từ "khoản vay"
|
||||
result = result.replace(/(khoản vay\s+)([A-Z]{2})(\d+)(\d{3})/gi, (m, prefix, letters, middle, last3) => {
|
||||
return prefix + letters + '*'.repeat(middle.length) + last3;
|
||||
});
|
||||
|
||||
// Che số tiền sau từ "số tiền"
|
||||
result = result.replace(/(số tiền\s+)(\d{1,3}(?:,\d{3})*)/gi, (m, prefix, amount) => {
|
||||
const digits = amount.replace(/,/g, '');
|
||||
if (digits.length <= 3) return prefix + amount;
|
||||
const masked = '*'.repeat(digits.length - 3) + digits.slice(-3);
|
||||
|
||||
// thêm lại dấu phẩy từ phải sang
|
||||
const parts = [];
|
||||
for (let i = masked.length; i > 0; i -= 3) {
|
||||
const start = Math.max(0, i - 3);
|
||||
parts.unshift(masked.slice(start, i));
|
||||
}
|
||||
return prefix + parts.join(',');
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
</script>
|
||||
14
components/menu/MenuAction.vue
Normal file
14
components/menu/MenuAction.vue
Normal file
@@ -0,0 +1,14 @@
|
||||
<template>
|
||||
<a class="mr-3" @click="$emit('edit')">
|
||||
<SvgIcon v-bind="{name: 'pen1.svg', type: 'dark', size: 16}"></SvgIcon>
|
||||
</a>
|
||||
<a @click="remove()">
|
||||
<SvgIcon v-bind="{name: 'bin1.svg', type: 'dark', size: 16}"></SvgIcon>
|
||||
</a>
|
||||
</template>
|
||||
<script setup>
|
||||
const emit = defineEmits(['edit', 'remove'])
|
||||
const remove = function() {
|
||||
emit('remove')
|
||||
}
|
||||
</script>
|
||||
11
components/menu/MenuAdd.vue
Normal file
11
components/menu/MenuAdd.vue
Normal file
@@ -0,0 +1,11 @@
|
||||
<template>
|
||||
<span class="tooltip">
|
||||
<span class="dot-twitter">+</span>
|
||||
<span class="tooltiptext to-left" style="min-width: max-content;">{{ label }}</span>
|
||||
</span>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
props: ['label']
|
||||
}
|
||||
</script>
|
||||
15
components/menu/MenuCV.vue
Normal file
15
components/menu/MenuCV.vue
Normal file
@@ -0,0 +1,15 @@
|
||||
<template>
|
||||
<a class="has-text-link" @click="open">{{row['code']}}</a>
|
||||
</template>
|
||||
<script setup>
|
||||
import { useStore } from "~/stores/index";
|
||||
const store = useStore();
|
||||
const emit = defineEmits(["clickevent"])
|
||||
const props = defineProps({
|
||||
row: Object
|
||||
})
|
||||
function open() {
|
||||
emit('clickevent', {name: 'dataevent', data: {modal: {title: store.lang==='en'? 'Candidate' : 'Hồ sơ ứng viên',
|
||||
height: '400px', width: '65%', component: 'common/JobView', vbind:{row: props.row}}}})
|
||||
}
|
||||
</script>
|
||||
43
components/menu/MenuCheck.vue
Normal file
43
components/menu/MenuCheck.vue
Normal file
@@ -0,0 +1,43 @@
|
||||
<template>
|
||||
<div class="mx-2">
|
||||
<a @click="change()">
|
||||
<SvgIcon v-bind="{name: check? 'checked.svg' : 'uncheck.svg', type: check? 'blue' : 'gray', size: 22}"></SvgIcon>
|
||||
</a>
|
||||
<a class="ml-5" @click="userRights" v-if="api && check">
|
||||
<SvgIcon v-bind="{name: 'list.svg', type: check? 'blue' : 'gray', size: 20}"></SvgIcon>
|
||||
</a>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
const { $insertapi, $deleteapi, $store } = useNuxtApp()
|
||||
const emit = defineEmits(["clickevent"])
|
||||
var props = defineProps({
|
||||
appid: Number,
|
||||
row: Object,
|
||||
api: String,
|
||||
setting: String
|
||||
})
|
||||
var check = ref(false)
|
||||
var current
|
||||
if(props.row) {
|
||||
props.row.apps.map(v=>{
|
||||
if(v.userapps__apps==props.appid) {
|
||||
check.value = true
|
||||
current = v
|
||||
}
|
||||
})
|
||||
}
|
||||
async function change() {
|
||||
if(check.value) {
|
||||
await $deleteapi('userapps', current.userapps__id)
|
||||
} else {
|
||||
let obj = {user: props.row.id, apps: props.appid}
|
||||
await $insertapi('userapps', obj)
|
||||
}
|
||||
check.value = !check.value
|
||||
}
|
||||
function userRights() {
|
||||
emit('clickevent', {name: 'dataevent', data: {modal: {title: $store.lang==='en'? 'User rights' : 'Phân quyền',
|
||||
height: '500px', width: '500px', component: 'menu/MenuRights', vbind: {row: props.row, api: props.api, setting: props.setting}}}})
|
||||
}
|
||||
</script>
|
||||
15
components/menu/MenuCollab.vue
Normal file
15
components/menu/MenuCollab.vue
Normal file
@@ -0,0 +1,15 @@
|
||||
<template>
|
||||
<a class="has-text-link" @click="open">{{row['code']}}</a>
|
||||
</template>
|
||||
<script setup>
|
||||
import { useStore } from "~/stores/index";
|
||||
const store = useStore();
|
||||
const emit = defineEmits(["clickevent"])
|
||||
const props = defineProps({
|
||||
row: Object
|
||||
})
|
||||
function open() {
|
||||
emit('clickevent', {name: 'dataevent', data: {modal: {title: store.lang==='en'? 'Collaborator' : 'Cộng tác viên',
|
||||
height: '500px', width: '65%', component: 'collaborator/Collaborator', vbind:{row: props.row}}}})
|
||||
}
|
||||
</script>
|
||||
23
components/menu/MenuDocker.vue
Normal file
23
components/menu/MenuDocker.vue
Normal file
@@ -0,0 +1,23 @@
|
||||
<template>
|
||||
<div>
|
||||
<a @click="stop()">
|
||||
<SvgIcon v-bind="{name: 'stop.svg', type: 'gray', size: 20}"></SvgIcon>
|
||||
</a>
|
||||
<a class="ml-3" @click="start()">
|
||||
<SvgIcon v-bind="{name: 'play.svg', type: 'gray', size: 20}"></SvgIcon>
|
||||
</a>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
props: ['row'],
|
||||
methods: {
|
||||
stop() {
|
||||
this.$emit('clickevent', {name: 'dataevent', data: 'stop'})
|
||||
},
|
||||
start() {
|
||||
this.$emit('clickevent', {name: 'dataevent', data: 'start'})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
17
components/menu/MenuParam.vue
Normal file
17
components/menu/MenuParam.vue
Normal file
@@ -0,0 +1,17 @@
|
||||
<template>
|
||||
<span :style="style">{{row[column]}}</span>
|
||||
</template>
|
||||
<script setup>
|
||||
import { useStore } from '~/stores/index'
|
||||
const store = useStore()
|
||||
const emit = defineEmits(["clickevent"])
|
||||
const props = defineProps({
|
||||
row: Object,
|
||||
field: String,
|
||||
column: String,
|
||||
param: String
|
||||
})
|
||||
const params = store[props.param]
|
||||
const found = params.find(v=>props.row[props.field]===v.id)
|
||||
const style = found? `color:${found.color}` : undefined
|
||||
</script>
|
||||
13
components/menu/MenuPhone.vue
Normal file
13
components/menu/MenuPhone.vue
Normal file
@@ -0,0 +1,13 @@
|
||||
<template>
|
||||
<a class="has-text-link" @click="open">{{row['phone']}}</a>
|
||||
</template>
|
||||
<script setup>
|
||||
const emit = defineEmits(["clickevent"])
|
||||
const props = defineProps({
|
||||
row: Object
|
||||
})
|
||||
function open() {
|
||||
emit('clickevent', {name: 'dataevent', data:
|
||||
{modal: {title: 'Phone', height: '180px', width: '400px', component: 'common/Phone'}}})
|
||||
}
|
||||
</script>
|
||||
118
components/menu/MenuRights.vue
Normal file
118
components/menu/MenuRights.vue
Normal file
@@ -0,0 +1,118 @@
|
||||
<template>
|
||||
<div class="has-text-black">
|
||||
<div>{{ row.username }} / {{ row.fullname }} {{$lang('access-right')}}:</div>
|
||||
<div class="mt-2">
|
||||
<span class="icon-text mr-6" v-for="v in options">
|
||||
<a @click="changeOption(v)">
|
||||
<SvgIcon v-bind="{name: option===v.code? 'radio-checked.svg' : 'radio-unchecked.svg', type: option===v.code? 'blue' : 'gray', size: 25}" />
|
||||
</a>
|
||||
<b class="fs-18">{{v[$store.lang==='en'? 'en' : 'name']}}</b>
|
||||
</span>
|
||||
</div>
|
||||
<aside class="menu">
|
||||
<ul class="menu-list" v-for="v in topmenu">
|
||||
<li>
|
||||
<div class="field is-grouped has-background-light has-text-black py-2 px-3">
|
||||
<div class="control is-expanded"><b>{{ v[$store.lang] }}</b></div>
|
||||
<div class="control" v-if="v.submenu.length===0 && option==='limit'">
|
||||
<span class="ml-6 is-clickable" @click="changeTick(v)">
|
||||
<SvgIcon v-bind="{name: v.checked? 'checked.svg' : 'uncheck.svg', type: v.checked? 'blue' : 'gray', size: 25}"></SvgIcon>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<ul>
|
||||
<li class="border-bottom" v-for="x in v.submenu">
|
||||
<div class="field is-grouped py-1">
|
||||
<div class="control is-expanded">
|
||||
<span class="icon-text">
|
||||
<span>{{ x[$store.lang] }}</span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="control" v-if="option==='limit'">
|
||||
<span class="ml-6 is-clickable" @click="changeTick(x, v)">
|
||||
<SvgIcon v-bind="{name: x.checked? 'checked.svg' : 'uncheck.svg', type: x.checked? 'blue' : 'gray', size: 25}"></SvgIcon>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</aside>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
const { $copy, $getdata, $filter, $find, $insertapi, $deleteapi } = useNuxtApp()
|
||||
const props = defineProps({
|
||||
row: Object,
|
||||
api: String,
|
||||
setting: String
|
||||
})
|
||||
const options = [{code: 'all', name: 'Tất cả tính năng', en: 'All functions'}, {code: 'limit', name: 'Bị giới hạn', en: 'Limited functions'}]
|
||||
var option = ref('limit')
|
||||
const rows = await $getdata(props.setting, {category__in: ['topmenu', 'submenu']})
|
||||
var topmenu = ref([])
|
||||
var loanRights = []
|
||||
async function getRights(first) {
|
||||
loanRights = await $getdata(props.api, {user: props.row.id})
|
||||
if(loanRights.length==0 && first) option.value = 'all'
|
||||
var rights = $filter(rows, {category: 'topmenu'})
|
||||
rights.map(v=>{
|
||||
let arr = $filter(rows, {category: 'submenu', classify: v.code})
|
||||
arr.map(x=>{
|
||||
let found = $find(loanRights, {setting: x.id})
|
||||
if(found) {
|
||||
x.rightId = found.id
|
||||
x.checked = true
|
||||
}
|
||||
})
|
||||
let found = $find(loanRights, {setting: v.id})
|
||||
if(found) v.rightId = found.id
|
||||
if(arr.length===0) {
|
||||
v.checked = found? true : false
|
||||
} else v.checked = true
|
||||
v.submenu = arr
|
||||
})
|
||||
topmenu.value = rights
|
||||
}
|
||||
async function changeTick(x, v) {
|
||||
if(x.checked) {
|
||||
if(x.rightId) {
|
||||
await $deleteapi(props.api, x.rightId)
|
||||
x.rightId = null
|
||||
}
|
||||
x.checked = false
|
||||
if(v? v.rightId>0 : false) {
|
||||
let idx = v.submenu.findIndex(h=>h.checked)
|
||||
if(idx<0) {
|
||||
await $deleteapi(props.api, v.rightId)
|
||||
v.checked = false
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let obj = await $insertapi(props.api, {setting: x.id, user: props.row.id}, undefined, false)
|
||||
if(obj) {
|
||||
x.checked = true
|
||||
x.rightId = obj.id
|
||||
}
|
||||
x.checked = true
|
||||
if(v? !v.rightId : false) {
|
||||
let obj = await $insertapi(props.api, {setting: v.id, user: props.row.id}, undefined, false)
|
||||
if(obj) {
|
||||
v.rightId = obj.rightId
|
||||
v.checked = true
|
||||
}
|
||||
}
|
||||
}
|
||||
topmenu.value = $copy(topmenu.value)
|
||||
}
|
||||
async function changeOption(v) {
|
||||
option.value = v.code
|
||||
if(v.code==='all') {
|
||||
if(loanRights.length>0) await $deleteapi(props.api, loanRights)
|
||||
} else {
|
||||
await getRights()
|
||||
}
|
||||
}
|
||||
await getRights(true)
|
||||
</script>
|
||||
15
components/menu/MenuStaff.vue
Normal file
15
components/menu/MenuStaff.vue
Normal file
@@ -0,0 +1,15 @@
|
||||
<template>
|
||||
<a class="has-text-link" @click="open">{{row['code']}}</a>
|
||||
</template>
|
||||
<script setup>
|
||||
import { useStore } from "~/stores/index";
|
||||
const store = useStore();
|
||||
const emit = defineEmits(["clickevent"])
|
||||
const props = defineProps({
|
||||
row: Object
|
||||
})
|
||||
function open() {
|
||||
emit('clickevent', {name: 'dataevent', data: {modal: {title: store.lang==='en'? 'Staff' : 'Hồ sơ nhân viên',
|
||||
height: '400px', width: '70%', component: 'staff/Staff', vbind:{row: props.row}}}})
|
||||
}
|
||||
</script>
|
||||
13
components/menu/MenuUser.vue
Normal file
13
components/menu/MenuUser.vue
Normal file
@@ -0,0 +1,13 @@
|
||||
<template>
|
||||
<a v-if="row.user__username">{{row.user__username.toUpperCase()}}</a>
|
||||
<a v-else-if="row.status__code==='yes'"
|
||||
@click="$emit('clickevent', {name: 'dataevent', data: {modal: {title: 'Tạo tài khoản', height: '400px', width: '800px',
|
||||
component: 'user/NewUser', vbind:{row:row, isadd: 1, type: 3}}}})">
|
||||
<MenuAdd v-bind="{label: 'Tạo tài khoản đăng nhập'}"/>
|
||||
</a>
|
||||
</template>
|
||||
<script setup>
|
||||
var props = defineProps({
|
||||
row: Object
|
||||
})
|
||||
</script>
|
||||
Reference in New Issue
Block a user