update 1400-10-09

This commit is contained in:
sedmedgh
2021-12-30 16:13:42 +03:30
parent e510b6ab98
commit 6b6b9a3652
79 changed files with 3323 additions and 395 deletions
+1 -1
View File
@@ -51,7 +51,7 @@
"vue-i18n": "^8.11.2", "vue-i18n": "^8.11.2",
"vue-instantsearch": "^2.2.1", "vue-instantsearch": "^2.2.1",
"vue-perfect-scrollbar": "^0.1.0", "vue-perfect-scrollbar": "^0.1.0",
"vue-persian-datetime-picker": "^2.4.0", "vue-persian-datetime-picker": "^2.10.2",
"vue-prism-component": "^1.1.1", "vue-prism-component": "^1.1.1",
"vue-property-decorator": "^8.1.1", "vue-property-decorator": "^8.1.1",
"vue-quill-editor": "^3.0.6", "vue-quill-editor": "^3.0.6",
+9 -2
View File
@@ -21,7 +21,7 @@
<script> <script>
import themeConfig from '@/../themeConfig.js' import themeConfig from '@/../themeConfig.js'
import jwt from '@/http/requests/auth/jwt/index.js' import jwt from '@/http/requests/auth/jwt/index.js'
import axios from "@/axios"
export default { export default {
data () { data () {
return { return {
@@ -72,7 +72,14 @@ export default {
}, },
async created() { async created() {
try{
let {data:{permission}} = await axios.get('/permission/user')
await this.$store.dispatch("access/setPermissions", permission)
// console.log("user data",this.$store.state.access.permissions)
}
catch (e) {
console.log("eeeee: ",e)
}
//console.log("this ==> ", this); //console.log("this ==> ", this);
const dict = { const dict = {
attributes: { attributes: {
+27
View File
@@ -57,3 +57,30 @@
* @import "utilities/background-patterns"; * @import "utilities/background-patterns";
* @import "utilities/skew-transforms"; * @import "utilities/skew-transforms";
*/ */
@media (min-width: 1201px) {
.main-vertical .vx-navbar-wrapper {
width: calc(100% - 16%);
}
}
.ant-input-wrapper.ant-input-group{
direction: ltr;
}
.ant-select-selection-selected-value{
float: right;
}
.ant-tree li span.ant-tree-switcher.ant-tree-switcher_close .ant-tree-switcher-icon, .ant-tree li span.ant-tree-switcher.ant-tree-switcher_close .ant-select-switcher-icon {
transform: scale(0.83333333) rotate(
180deg);
}
.ant-tree li ul {
margin: 0;
padding: 0 18px 0 0;
}
.ant-modal-close {
left: 0;
right: unset;
}
.ant-modal-footer button + button {
margin-right: 8px;
margin-left: unset;
}
+54 -14
View File
@@ -1,22 +1,55 @@
import axios from 'axios' import axios from 'axios'
import router from '@/router'
const domain = "" const domain = ""
// import themeConfig from '@/../themeConfig.js' // import themeConfig from '@/../themeConfig.js'
const noAthUrl =["/register/form",
"/auth/login",
"/auth/register",
"/pages/error-404",
"/pages/error-403",
"/auth/forgot-password"]
const token = sessionStorage.getItem("accessToken") || sessionStorage.accessToken || null const token = sessionStorage.getItem("accessToken") || sessionStorage.accessToken || null
const headers = { const headers = {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
//'Authorization': 'Bearer ' + localStorage.getItem("accessToken") || localStorage.accessToken 'accept':'application/json',
'Authorization': 'Bearer ' + token 'Authorization': 'Bearer ' + token
} }
var myax= new axios.create({ var myax= new axios.create({
baseURL: 'http://hr.asco-intl.com/back/public/api/', baseURL: 'http://hr.asco-intl.com:2020/back/public/api/',
headers, headers,
domain // domain
}) })
myax.interceptors.request.use( myax.interceptors.request.use(
function (config) {
// Do something before request is sent
if (process.browser) {
if (!sessionStorage.getItem("accessToken") && !noAthUrl.includes(router.currentRoute.fullPath)) {
console.log("router req::::",router.currentRoute)
router.push('/auth/login');
}
}
config.headers = {
'Content-Type': 'application/json',
'accept':'application/json'
};
if (sessionStorage.getItem("accessToken")) {
config.headers['Authorization'] = 'Bearer ' + sessionStorage.getItem("accessToken");
}
return config;
},
function (error) {
return Promise.reject(error);
}
);
/*myax.interceptors.request.use(
config => { config => {
config.headers["Authorization"] = "Bearer " + sessionStorage.getItem("accessToken") || sessionStorage.accessToken || null; config.headers["Authorization"] = "Bearer " + sessionStorage.getItem("accessToken") || sessionStorage.accessToken || null;
return config; return config;
@@ -24,17 +57,24 @@ myax.interceptors.request.use(
error => { error => {
Promise.reject(error); Promise.reject(error);
} }
);
/*myax.interceptors.request.use(
config => {
config.headers["Authorization"] = "Bearer " + sessionStorage.getItem("accessToken");
return config;
},
error => {
Promise.reject(error);
}
);*/ );*/
myax.interceptors.response.use(
function (res) {
return res;
},
function ({response}) {
if (response.status === 401 && !noAthUrl.includes(router.currentRoute.fullPath)) {
console.log("router response::::",router.currentRoute)
router.push({path:'/auth/login'});
}
if(response.status === 403 && router.currentRoute.fullPath !== '/error-403'){
console.log('403333333333333')
router.push({path:'/error-403'});
}
return Promise.reject(response);
}
);
export default myax; export default myax;
+7 -1
View File
@@ -1,6 +1,7 @@
<template> <template>
<div class="clearfix"> <div class="clearfix">
<AUpload <AUpload
:disabled="disabled"
:action="url" :action="url"
:headers="headers" :headers="headers"
:accept="accept" :accept="accept"
@@ -50,6 +51,11 @@ export default {
size: { size: {
default: 2 default: 2
}, },
disabled: {
required:false,
type:Boolean,
default: false
},
accept: {default: "image/jpeg"}, accept: {default: "image/jpeg"},
serverType: { serverType: {
types: { types: {
@@ -63,7 +69,7 @@ export default {
}, },
data() { data() {
return { return {
url: 'http://hr.asco-intl.com/back/public/api/register/upload', url: 'http://hr.asco-intl.com:2020/back/public/api/register/upload',
previewVisible: false, previewVisible: false,
previewImage: '', previewImage: '',
fileList: [], fileList: [],
+6
View File
@@ -1,6 +1,7 @@
<template> <template>
<div class="clearfix"> <div class="clearfix">
<AUpload <AUpload
:disabled="disabled"
:action="url" :action="url"
:headers="headers" :headers="headers"
accept="image/jpeg" accept="image/jpeg"
@@ -48,6 +49,11 @@ export default {
size: { size: {
default: 2 default: 2
}, },
disabled: {
required:false,
type:Boolean,
default: false
},
label: {}, label: {},
serverType: { serverType: {
types: { types: {
+69
View File
@@ -0,0 +1,69 @@
`Version 0.95`
# Table Engine for Vue 2 Projects
# Requirements
- ant design ^1.3
- fullscreen plugin
- vue-persian-datetime-picker ^2.4
# Example
To define the model layer, we do the following
```js
import XTbl, {Xtc} from './index' // import from x-table directory;
const tbl = new XTbl('http://some-url', 'foo-bar-title');
tbl.add(new Xtc('id', 'آیدی').filterNumber());
tbl.add(new Xtc('title', 'عنوان').filterText())
tbl.add(new Xtc('fname', 'نام کوچک').filterText())
tbl.add(new Xtc('lname', 'نام بزرگ').filterText())
tbl.add(new Xtc('ncode', 'کد ملی').filterText().hidden().noSort())
tbl.add(new Xtc('birth_date', 'تاریخ تولد').filterDate().hidden().noSort())
tbl.add(new Xtc('sts_str', 'وضعیت').renderSlot('sts_str').filterSelect({1: 'گزینه اول'}).noSort())
tbl.add(new Xtc('active', 'فعال').filterSwitch().hidden().noSort())
tbl.add(new Xtc('wow', 'فعال').filterSwitch().renderSlot('wow').noSort())
tbl.addOpt()
export default tbl;
```
And to use the model layer in the view layer, we will do the following in vue file
```vue
<template>
....
<XTable :model="model"/>
....
</template>
<script>
import XTable from "@/components/x-table/XTable";
import model from './some-model';
export default {
components: {XTable},
data(){
return {model:undefined}
},
created(){
this.model = model;
}
}
</script>
```
Feature road map
- [x] Date filter
- [x] Select filter
- [x] Multiple filter
- [x] Switch filter
- [x] Numeric filter
- [x] JSON export
- [x] Print export
- [x] Excel export
- [x] Auto translate columns in export mode
- [x] Auto set title for print report
- [ ] Sort in joined table
- [ ] Exception Handlers for server and client
- [ ] Reset Table Engine feature
- [ ] Store current view in localstorage
- [ ] Add scope to filter
+448
View File
@@ -0,0 +1,448 @@
<template>
<div>
<ACard ref="tblCard" class="overflow-auto">
<template #cover>
<ASpin :spinning="loading">
<div class="flex justify-between p-4">
<div class="flex items-center">
<a-input-search class="md:ml-4" placeholder="عبارت مورد نظر برای جستجو را وارد کنید"
enter-button="جستجو"
@search="onSearch" v-if="!model._noSearch"/>
<AButton @click="toggleVisibleFilter" :type="getFilterType">
<div class="flex items-center">
<feather-icon icon="FilterIcon" svg-classes="h-4 w-4 color-grey cursor-pointer"
class="ml-4"/>
<div v-if="query && query.filters.length > 0">
{{ query.filters.length }}
فیلتر
</div>
<div v-else>
فیلتر ها
</div>
</div>
</AButton>
</div>
<div class="filter-backdrop p-4" v-if="visibleDownload">
<feather-icon icon="XIcon" @click="toggleVisibleDownload"
svg-classes="h-4 w-4 color-grey cursor-pointer"
class="ml-4"/>
<AAlert >
<template #message>
لیست فعلی را می توانید در یکی از قالب های زیر دریافت کنید.
</template>
</AAlert>
<div class="grid grid-cols-3 p-8">
<div class="flex items-center justify-center flex-col cursor-pointer" @click="fetch('json')">
<img :src="jsonIcon" style="max-height: 45px" class="mb-4"/>
خروجی json
</div>
<div class="flex items-center justify-center flex-col cursor-pointer" @click="fetch('excel')">
<img :src="excelIcon" style="max-height: 45px" class="mb-4"/>
خروجی اکسل
</div>
<div class="flex items-center justify-center flex-col cursor-pointer" @click="fetch('print')">
<img :src="printIcon" style="max-height: 45px" class="mb-4"/>
خروجی پرینت
</div>
</div>
</div>
<div class="filter-backdrop p-4" v-if="activeFilter">
<div>
<div class="flex items-center mb-4">
<feather-icon icon="XIcon" @click="toggleVisibleFilter"
svg-classes="h-4 w-4 color-grey cursor-pointer"
class="ml-4"/>
<div class="font-bold">
فیلتر ها
</div>
</div>
<div v-if="query">
<div v-for="(item,index) in query.filters" :key="item.id" class="mb-4">
<XFilterRow :value="item"
@remove="removeFilter"
@input="filterChange"
:index="index"
:id="item.id"
:col-filters="getColsFilter"
:is-first="index < 1"
/>
</div>
</div>
<div class="flex items-center justify-center">
<AButton @click="addFilterRow">
افزودن ردیف جدید
</AButton>
<div class="flex-1"></div>
<AButton @click="doFilter" type="primary" v-if="query" :disabled="query.filters.length == 0">
انجام فیلتر
</AButton>
</div>
<ADivider orientation="left">مرتب سازی</ADivider>
<div class="md:flex gap-4">
<ARadioGroup v-model="sortDirection" class="ml-4" dir="ltr">
<ARadioButton value="asc">صعودی</ARadioButton>
<ARadioButton value="desc">نزولی</ARadioButton>
</ARadioGroup>
<ASelect style="min-width: 250px" placeholder="مرتب سازی" allow-clear v-model="sort">
<ASelectOption :key="index" :value="item.key" v-for="(item, index) in model.getSortFields()">
{{ item.title }}
</ASelectOption>
</ASelect>
<div class="flex-1">
</div>
<AButton @click="doFilter" type="primary">
بروزرسانی
</AButton>
</div>
</div>
</div>
<div class="flex justify-end gap-4 items-center" v-if="!model._noSettings">
<feather-icon :icon="getFullIcon" svg-classes="w-5 h-5 cursor-pointer text-primary" @click="fullScreen"/>
<ADropdown :trigger="['hover']">
<div slot="overlay" class="p-2" style="min-width: 250px">
<ACard @click.stop="noThings" :body-style="{padding:'8px'}">
ستون های جدول
<ADivider class="my-2"/>
<div class="flex flex-col items-start" style="max-height:150px;overflow:auto">
<Draggable v-model="cols">
<div v-for="item,index in cols" :key="index" class="flex items-start">
<feather-icon icon="MoreVerticalIcon" svg-classes="h-4 w-4 color-grey cursor-pointer"
class="mr-0"/>
<feather-icon icon="MoreVerticalIcon" svg-classes="h-4 w-4 color-grey cursor-pointer"
style="position: relative;left: 9px;"/>
<ACheckbox v-model="item.show">
{{ item.title }}
</ACheckbox>
</div>
</Draggable>
</div>
</ACard>
</div>
<feather-icon icon="SettingsIcon" svg-classes="w-5 h-5 cursor-pointer refresh-btn text-primary"/>
</ADropdown>
<feather-icon icon="RotateCwIcon" svg-classes="w-5 h-5 refresh-btn cursor-pointer text-primary"
@click="fetch"/>
<!-- <feather-icon icon="DownloadIcon" svg-classes="w-5 h-5 cursor-pointer text-primary"
@click="showDownload"/>-->
</div>
</div>
<a-table
@change="change"
:indentSize="5"
:pagination="false"
ref="tbl"
:locale="locale"
:columns="visibleCols"
:data-source="data"
>
<template :slot="item" slot-scope="name, record, index" v-for="item,ind in customRender">
<slot :name="item" :text="name" :record="record" :index="index"/>
</template>
<div slot="footer" slot-scope="{item}">
<div class="flex items-center">
<div class="flex-1">
<div v-if="query.total">
<span>{{ query.total }}</span>
رکورد یافت شد.
</div>
</div>
<APagination dir="ltr"
show-size-changer
:pageSizeOptions="['5','10','20']"
:page-size.sync="query.limit"
@change="changePage"
@showSizeChange="changePage"
:default-current="1" :total="query.total" v-model.sync="query.page">
<template slot="buildOptionText" slot-scope="props">
<div dir="rtl">
<span> {{ props.value }} </span>
<span>رکورد</span>
</div>
</template>
</APagination>
</div>
</div>
</a-table>
</ASpin>
</template>
</ACard>
</div>
</template>
<script>
import XTbl from "./model/XTbl";
import Draggable from 'vuedraggable'
import axios from "../../axios";
import {closeFullscreen, openFullscreen} from "@/plugins/fullscreen";
import printIcon from './assets/print.svg'
import excelIcon from './assets/excel.svg'
import jsonIcon from './assets/json.svg'
import FeatherIcon from '@/components/FeatherIcon.vue'
import XFilterRow from "./components/XFilterRow";
export default {
name: 'XTable',
components: {
XFilterRow,
FeatherIcon,
Draggable,
// DatePickerBetweenXTableFilter
},
props: {
model: {
type: XTbl.default
}
},
data() {
return {
data: [],
jsonIcon,
excelIcon,
printIcon,
lastHashStringFilter: undefined,
query: {
search: undefined,
filters: [],
total: 0,
limit: 10,
page: 1,
},
locale: {
emptyText: 'هیج رکوردی یافت نشد.'
},
loading: false,
activeFilter: false,
full: false,
sort: undefined,
sortDirection: 'asc',
colSelector: false,
visibleDownload: false
}
},
methods: {
getFilters() {
return this.query.filters
},
showDownload() {
this.visibleDownload = true;
},
doFilter() {
this.activeFilter = false;
this.fetch();
},
removeFilter(index) {
console.log("index ==> ", index);
this.$delete(this.query.filters, index)
this.$forceUpdate();
},
filterChange(value) {
console.log("value ==> " , value);
this.query.filters[value.index] = value;
},
calcHash() {
},
addFilterRow() {
if (!this.query) this.query = {};
if (!this.query.filters) this.query.filters = []
let rand = parseFloat(`${this.query.filters.length}.${Math.floor(Math.random() * 1000)}`);
this.query.filters.push({id: rand});
this.$forceUpdate();
},
toggleVisibleFilter() {
this.activeFilter = !this.activeFilter;
},
toggleVisibleDownload() {
this.visibleDownload = !this.visibleDownload;
},
// submitFilter({model, column}) {
// if (!this.query.filters) {
// this.query.filters = new Map()
// }
// const e = this.query.filters.values().filter((i) => i.field == (column.__fkey || column.dataIndex));
// if (e) {
// e.forEach((i) => {
// this.$delete(this.query.filters, this.query.filters.indexOf(i));
// });
// }
//
// const vModel = model.filter((i) => i.value)
// this.query.filters = this.query.filters.concat(vModel);
// console.log("this.query.filters ==> ", this.query.filters);
// this.fetch()
// },
hasFiltered(item) {
for (const i of this.query) {
if (item.startsWith(i.field)) {
return true;
}
}
return false;
},
change(item, filter, sorter) {
if (sorter) {
const {columnKey, order} = sorter;
this.query.order = [`${order == 'ascend' ? '-' : '+'}${columnKey}`];
}
this.fetch();
},
changePage(item) {
this.query.page = item;
this.fetch();
},
fullScreen() {
if (this.full) {
closeFullscreen()
this.full = false;
return;
}
openFullscreen(this.$refs.tblCard.$el);
this.full = true;
},
requestData(op) {
this.query.order = this.order;
this.query.filters = this.query.filters.filter((item) => item.value || ['null', 'nn'].includes(item.op) || item.value == 0);
const select = this.visibleCols.map((i) => i.key);
const titles = {};
let hash = JSON.stringify(this.query.filters);
if (this.query.search) {
hash += this.query.search;
}
if (hash != this.lastHashStringFilter) {
this.query.page = 1;
}
this.lastHashStringFilter = hash;
this.visibleCols.forEach((i) => titles[i.key] = i.title);
if (op) {
return {...this.query, op, select, titles, report_title: this.model.title};
}
return {...this.query, select, titles, report_title: this.model.title};
},
async fetch(op) {
try {
this.loading = true;
const {data} = await axios.post(this.model.url, this.requestData(op));
if (op == 'excel' || op == 'json' || op == 'print') {
window.open(data.url);
return;
}
this.data = data.rows;
this.query = data.query
console.log("this.query ==> ", this.query);
this.$emit('fetch', data)
} catch (e) {
this.$message.error('خطا در دریافت اطلاعات');
throw e
} finally {
this.loading = false;
this.visibleDownload = false;
}
},
noThings() {
},
getFilterData() {
},
onSearch(value) {
this.query.search = value;
this.fetch();
// if (value) {
// }
},
showColSelector() {
this.colSelector = !this.colSelector;
}
},
computed: {
order: {
set() {
},
get() {
if (this.sort) {
const direc = (this.sortDirection == 'asc') ? '+' : '-';
return `${direc}${this.sort}`
}
}
},
getFilterType() {
return (this.query && this.query.filters && this.query.filters.length > 0) ? 'primary' : '';
},
getFullIcon() {
return !this.full ? 'Maximize2Icon' : 'Minimize2Icon';
},
customRender() {
return this.model.cols.filter((item) => item.scopedSlots && item.scopedSlots.customRender).map((i) => i.scopedSlots.customRender)
},
filterIcons() {
return this.model.cols.filter((item) => item.scopedSlots && item.scopedSlots.filterIcon).map((i) => i.scopedSlots.filterIcon)
},
cols: {
get() {
return this.model.cols || [];
},
set(value) {
this.model.cols = value;
}
},
getColsFilter() {
return this.cols.filter(item => item.filtered)
},
visibleCols() {
console.log(" ==> " , this.cols.filter(item => item.show));
return this.cols.filter(item => item.show)
}
},
mounted() {
this.fetch();
}
}
</script>
<style scoped>
.fade-enter {
opacity: 0;
}
.fade-enter-active {
opacity: 0.5;
transition: 0.5s ease;
}
.fade-leave {
opacity: 1;
}
.fade-leave-active {
opacity: 0;
transition: 0.5s ease;
}
.refresh-btn {
transition: all 0.15s ease;
}
.refresh-btn:hover {
transform: rotate(90deg);
}
.filter-backdrop {
position: absolute;
z-index: 1000;
top: 0;
left: 0;
bottom: 0;
right: 0;
background-color: white;
}
</style>
@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
<!ENTITY ns_extend "http://ns.adobe.com/Extensibility/1.0/">
<!ENTITY ns_ai "http://ns.adobe.com/AdobeIllustrator/10.0/">
<!ENTITY ns_graphs "http://ns.adobe.com/Graphs/1.0/">
<!ENTITY ns_vars "http://ns.adobe.com/Variables/1.0/">
<!ENTITY ns_imrep "http://ns.adobe.com/ImageReplacement/1.0/">
<!ENTITY ns_sfw "http://ns.adobe.com/SaveForWeb/1.0/">
<!ENTITY ns_custom "http://ns.adobe.com/GenericCustomNamespace/1.0/">
<!ENTITY ns_adobe_xpath "http://ns.adobe.com/XPath/1.0/">
]>
<svg version="1.1" id="Livello_1" xmlns:x="&ns_extend;" xmlns:i="&ns_ai;" xmlns:graph="&ns_graphs;"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 2289.75 2130"
enable-background="new 0 0 2289.75 2130" xml:space="preserve">
<metadata>
<sfw xmlns="&ns_sfw;">
<slices></slices>
<sliceSourceBounds bottomLeftOrigin="true" height="2130" width="2289.75" x="-1147.5" y="-1041"></sliceSourceBounds>
</sfw>
</metadata>
<path fill="#185C37" d="M1437.75,1011.75L532.5,852v1180.393c0,53.907,43.7,97.607,97.607,97.607l0,0h1562.036
c53.907,0,97.607-43.7,97.607-97.607l0,0V1597.5L1437.75,1011.75z"/>
<path fill="#21A366" d="M1437.75,0H630.107C576.2,0,532.5,43.7,532.5,97.607c0,0,0,0,0,0V532.5l905.25,532.5L1917,1224.75
L2289.75,1065V532.5L1437.75,0z"/>
<path fill="#107C41" d="M532.5,532.5h905.25V1065H532.5V532.5z"/>
<path opacity="0.1" enable-background="new " d="M1180.393,426H532.5v1331.25h647.893c53.834-0.175,97.432-43.773,97.607-97.607
V523.607C1277.825,469.773,1234.227,426.175,1180.393,426z"/>
<path opacity="0.2" enable-background="new " d="M1127.143,479.25H532.5V1810.5h594.643
c53.834-0.175,97.432-43.773,97.607-97.607V576.857C1224.575,523.023,1180.977,479.425,1127.143,479.25z"/>
<path opacity="0.2" enable-background="new " d="M1127.143,479.25H532.5V1704h594.643c53.834-0.175,97.432-43.773,97.607-97.607
V576.857C1224.575,523.023,1180.977,479.425,1127.143,479.25z"/>
<path opacity="0.2" enable-background="new " d="M1073.893,479.25H532.5V1704h541.393c53.834-0.175,97.432-43.773,97.607-97.607
V576.857C1171.325,523.023,1127.727,479.425,1073.893,479.25z"/>
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="203.5132" y1="1729.0183" x2="967.9868" y2="404.9817" gradientTransform="matrix(1 0 0 -1 0 2132)">
<stop offset="0" style="stop-color:#18884F"/>
<stop offset="0.5" style="stop-color:#117E43"/>
<stop offset="1" style="stop-color:#0B6631"/>
</linearGradient>
<path fill="url(#SVGID_1_)" d="M97.607,479.25h976.285c53.907,0,97.607,43.7,97.607,97.607v976.285
c0,53.907-43.7,97.607-97.607,97.607H97.607C43.7,1650.75,0,1607.05,0,1553.143V576.857C0,522.95,43.7,479.25,97.607,479.25z"/>
<path fill="#FFFFFF" d="M302.3,1382.264l205.332-318.169L319.5,747.683h151.336l102.666,202.35
c9.479,19.223,15.975,33.494,19.49,42.919h1.331c6.745-15.336,13.845-30.228,21.3-44.677L725.371,747.79h138.929l-192.925,314.548
L869.2,1382.263H721.378L602.79,1160.158c-5.586-9.45-10.326-19.376-14.164-29.66h-1.757c-3.474,10.075-8.083,19.722-13.739,28.755
l-122.102,223.011H302.3z"/>
<path fill="#33C481" d="M2192.143,0H1437.75v532.5h852V97.607C2289.75,43.7,2246.05,0,2192.143,0L2192.143,0z"/>
<path fill="#107C41" d="M1437.75,1065h852v532.5h-852V1065z"/>
</svg>

After

Width:  |  Height:  |  Size: 3.4 KiB

@@ -0,0 +1,79 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 56 56" style="enable-background:new 0 0 56 56;" xml:space="preserve">
<g>
<path style="fill:#E9E9E0;" d="M36.985,0H7.963C7.155,0,6.5,0.655,6.5,1.926V55c0,0.345,0.655,1,1.463,1h40.074
c0.808,0,1.463-0.655,1.463-1V12.978c0-0.696-0.093-0.92-0.257-1.085L37.607,0.257C37.442,0.093,37.218,0,36.985,0z"/>
<polygon style="fill:#D9D7CA;" points="37.5,0.151 37.5,12 49.349,12 "/>
<path style="fill:#9777A8;" d="M48.037,56H7.963C7.155,56,6.5,55.345,6.5,54.537V39h43v15.537C49.5,55.345,48.845,56,48.037,56z"/>
<g>
<path style="fill:#FFFFFF;" d="M17.021,42.719v7.848c0,0.474-0.087,0.873-0.26,1.196s-0.405,0.583-0.697,0.779
s-0.627,0.333-1.005,0.41c-0.378,0.077-0.768,0.116-1.169,0.116c-0.2,0-0.436-0.021-0.704-0.062s-0.547-0.104-0.834-0.191
s-0.563-0.185-0.827-0.294s-0.487-0.232-0.67-0.369l0.697-1.107c0.091,0.063,0.221,0.13,0.39,0.198s0.354,0.132,0.554,0.191
s0.41,0.111,0.629,0.157s0.424,0.068,0.615,0.068c0.483,0,0.868-0.094,1.155-0.28s0.439-0.504,0.458-0.95v-7.711H17.021z"/>
<path style="fill:#FFFFFF;" d="M25.184,50.238c0,0.364-0.075,0.718-0.226,1.06s-0.362,0.643-0.636,0.902s-0.61,0.467-1.012,0.622
s-0.856,0.232-1.367,0.232c-0.219,0-0.444-0.012-0.677-0.034s-0.467-0.062-0.704-0.116c-0.237-0.055-0.463-0.13-0.677-0.226
s-0.398-0.212-0.554-0.349l0.287-1.176c0.128,0.073,0.289,0.144,0.485,0.212s0.398,0.132,0.608,0.191s0.419,0.107,0.629,0.144
s0.405,0.055,0.588,0.055c0.556,0,0.982-0.13,1.278-0.39s0.444-0.645,0.444-1.155c0-0.31-0.104-0.574-0.314-0.793
s-0.472-0.417-0.786-0.595s-0.654-0.355-1.019-0.533s-0.706-0.388-1.025-0.629s-0.583-0.526-0.793-0.854s-0.314-0.738-0.314-1.23
c0-0.446,0.082-0.843,0.246-1.189s0.385-0.641,0.663-0.882s0.602-0.426,0.971-0.554s0.759-0.191,1.169-0.191
c0.419,0,0.843,0.039,1.271,0.116s0.774,0.203,1.039,0.376c-0.055,0.118-0.118,0.248-0.191,0.39s-0.142,0.273-0.205,0.396
s-0.118,0.226-0.164,0.308s-0.073,0.128-0.082,0.137c-0.055-0.027-0.116-0.063-0.185-0.109s-0.166-0.091-0.294-0.137
s-0.296-0.077-0.506-0.096s-0.479-0.014-0.807,0.014c-0.183,0.019-0.355,0.07-0.52,0.157s-0.31,0.193-0.438,0.321
s-0.228,0.271-0.301,0.431s-0.109,0.313-0.109,0.458c0,0.364,0.104,0.658,0.314,0.882s0.47,0.419,0.779,0.588
s0.647,0.333,1.012,0.492s0.704,0.354,1.019,0.581s0.576,0.513,0.786,0.854S25.184,49.7,25.184,50.238z"/>
<path style="fill:#FFFFFF;" d="M35.082,47.914c0,0.848-0.107,1.595-0.321,2.242s-0.511,1.185-0.889,1.613s-0.82,0.752-1.326,0.971
s-1.06,0.328-1.661,0.328s-1.155-0.109-1.661-0.328s-0.948-0.542-1.326-0.971s-0.675-0.966-0.889-1.613s-0.321-1.395-0.321-2.242
s0.107-1.593,0.321-2.235s0.511-1.178,0.889-1.606s0.82-0.754,1.326-0.978s1.06-0.335,1.661-0.335s1.155,0.111,1.661,0.335
s0.948,0.549,1.326,0.978s0.675,0.964,0.889,1.606S35.082,47.066,35.082,47.914z M30.844,51.729c0.337,0,0.658-0.066,0.964-0.198
s0.579-0.349,0.82-0.649s0.431-0.695,0.567-1.183s0.21-1.082,0.219-1.784c-0.009-0.684-0.08-1.265-0.212-1.743
s-0.314-0.873-0.547-1.183s-0.497-0.533-0.793-0.67s-0.608-0.205-0.937-0.205c-0.337,0-0.658,0.063-0.964,0.191
s-0.579,0.344-0.82,0.649s-0.431,0.699-0.567,1.183c-0.137,0.483-0.21,1.075-0.219,1.777c0.009,0.684,0.08,1.267,0.212,1.75
s0.314,0.877,0.547,1.183s0.497,0.528,0.793,0.67S30.516,51.729,30.844,51.729z"/>
<path style="fill:#FFFFFF;" d="M44.68,42.924V53h-1.668l-3.951-6.945V53h-1.668V42.924h1.668l3.951,6.945v-6.945H44.68z"/>
</g>
<g>
<path style="fill:#9777A8;" d="M19.5,19v-4c0-0.551,0.448-1,1-1c0.553,0,1-0.448,1-1s-0.447-1-1-1c-1.654,0-3,1.346-3,3v4
c0,1.103-0.897,2-2,2c-0.553,0-1,0.448-1,1s0.447,1,1,1c1.103,0,2,0.897,2,2v4c0,1.654,1.346,3,3,3c0.553,0,1-0.448,1-1
s-0.447-1-1-1c-0.552,0-1-0.449-1-1v-4c0-1.2-0.542-2.266-1.382-3C18.958,21.266,19.5,20.2,19.5,19z"/>
<circle style="fill:#9777A8;" cx="27.5" cy="18.5" r="1.5"/>
<path style="fill:#9777A8;" d="M39.5,21c-1.103,0-2-0.897-2-2v-4c0-1.654-1.346-3-3-3c-0.553,0-1,0.448-1,1s0.447,1,1,1
c0.552,0,1,0.449,1,1v4c0,1.2,0.542,2.266,1.382,3c-0.84,0.734-1.382,1.8-1.382,3v4c0,0.551-0.448,1-1,1c-0.553,0-1,0.448-1,1
s0.447,1,1,1c1.654,0,3-1.346,3-3v-4c0-1.103,0.897-2,2-2c0.553,0,1-0.448,1-1S40.053,21,39.5,21z"/>
<path style="fill:#9777A8;" d="M27.5,24c-0.553,0-1,0.448-1,1v3c0,0.552,0.447,1,1,1s1-0.448,1-1v-3
C28.5,24.448,28.053,24,27.5,24z"/>
</g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.7 KiB

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <svg version="1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" enable-background="new 0 0 48 48">
<rect x="9" y="11" fill="#424242" width="30" height="3"/>
<path fill="#616161" d="M4,25h40v-7c0-2.2-1.8-4-4-4H8c-2.2,0-4,1.8-4,4V25z"/>
<path fill="#424242" d="M8,36h32c2.2,0,4-1.8,4-4v-8H4v8C4,34.2,5.8,36,8,36z"/>
<circle fill="#00E676" cx="40" cy="18" r="1"/>
<rect x="11" y="4" fill="#90CAF9" width="26" height="10"/>
<path fill="#242424" d="M37.5,31h-27C9.7,31,9,30.3,9,29.5v0c0-0.8,0.7-1.5,1.5-1.5h27c0.8,0,1.5,0.7,1.5,1.5v0 C39,30.3,38.3,31,37.5,31z"/>
<rect x="11" y="31" fill="#90CAF9" width="26" height="11"/>
<rect x="11" y="29" fill="#42A5F5" width="26" height="2"/>
<g fill="#1976D2">
<rect x="16" y="33" width="17" height="2"/>
<rect x="16" y="37" width="13" height="2"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 915 B

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-search"><circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line></svg>

After

Width:  |  Height:  |  Size: 308 B

@@ -0,0 +1,30 @@
<template>
<div>
<date-picker auto-submit accepted="bottom-left" @change="search" v-model="input" input-class="ant-input"/>
</div>
</template>
<script>
export default {
name: 'DateXTableFilter',
props: ['value'],
data() {
return {
input: undefined
}
},
methods: {
search() {
this.$emit('input', this.input)
},
},
mounted() {
this.input = this.value
}
}
</script>
<style>
.vpd-input-group label{
border-radius: 0 4px 4px 0;
}
</style>
@@ -0,0 +1,27 @@
<template>
<div>
<AInputNumber placehoder="مقدار"
@change="search"
v-model="input"/>
</div>
</template>
<script>
export default {
name: 'NumberXTableFilter',
props: ['value'],
data() {
return {
input: undefined
}
},
methods: {
search() {
this.$emit('input', this.input)
},
},
mounted() {
this.input = this.value
}
}
</script>
@@ -0,0 +1,62 @@
<template>
<div>
<ASelect
:show-search="true"
v-model="input"
placeholder="مقدار"
style="width: 200px"
:default-active-first-option="false"
:show-arrow="true"
:filter-option="false"
:not-found-content="null"
class="w-full"
@search="fetch"
@change="search"
>
<template #notFoundContent>
<div>
هیچ موردی یافت نشد
</div>
</template>
<ASelectOption v-for="item in data" :key="item.id" :value="item.id">
{{ item.title }}
</ASelectOption>
</ASelect>
</div>
</template>
<script>
import axios from "@/axios";
export default {
name: 'QuerySelectTableFilter',
props: ['value', 'action'],
data() {
return {
input: undefined,
data: [],
}
},
methods: {
search() {
this.$emit('input', this.input)
},
async fetch(value) {
try {
if (!value || value.length < 2) return;
const {data} = await axios.get('/te/query', {params: {action: this.action , query:value}});
this.data = data;
} catch (e) {
this.$message.error('خطا در دریافت اطلاعات');
}
}
},
mounted() {
this.input = this.value
}
}
</script>
@@ -0,0 +1,34 @@
<template>
<div>
<ASelect
v-model="input"
class="w-full"
@change="search"
placehoder="مقدار"
>
<ASelectOption v-for="(i,k) in items" :key="k">
{{ i }}
</ASelectOption>
</ASelect>
</div>
</template>
<script>
export default {
name: 'SelectXTableFilter',
props: ['value', 'items'],
data() {
return {
input: undefined
}
},
methods: {
search() {
this.$emit('input', this.input)
},
},
mounted() {
this.input = this.value
}
}
</script>
@@ -0,0 +1,25 @@
<template>
<div>
<ASwitch v-model="input" @change="search"/>
</div>
</template>
<script>
export default {
name: 'SwitchXTableFilter',
props: ['value'],
data() {
return {
input: undefined
}
},
methods: {
search() {
this.$emit('input', this.input)
},
},
mounted() {
this.input = this.value
}
}
</script>
@@ -0,0 +1,30 @@
<template>
<div>
<AInput v-model="input"
placehoder="مقدار"
@change="search"
@pressEnter="() => search()"
/>
</div>
</template>
<script>
export default {
name: 'TextXTableFilter',
props: ['value'],
data() {
return {
input: undefined
}
},
methods: {
search() {
this.$emit('input', this.input)
this.$emit('search', this.input)
},
},
mounted() {
this.input = this.value
}
}
</script>
@@ -0,0 +1,164 @@
<template>
<div class="grid md:grid-cols-4 gap-4">
<div class="flex">
<ARadioGroup :value="cr" v-model="cr" class="ml-4" v-if="!isFirst" @change="change">
<ARadioButton value="and">و</ARadioButton>
<ARadioButton value="or">یا</ARadioButton>
</ARadioGroup>
<ASelect class="flex-1" @change="change" v-model="col" placeholder="عنوان ستون">
<ASelectOption :value="item.key" :key="index" v-for="(item, index) in colFilters">
{{
item.title
}}
</ASelectOption>
</ASelect>
</div>
<ASelect :disabled="!col" placeholder="عملگر" v-model="op" @change="change">
<ASelectOption :value="index" :key="index" v-for="(item, index) in colTypes">
{{
item
}}
</ASelectOption>
</ASelect>
<div v-if="type && hasInput">
<component
@input="change"
:is="getModifierComponent"
:items="filterObject.filterItems"
:action="filterObject.filterAction"
v-model="input"
/>
</div>
<div>
<feather-icon icon="XIcon" class="cursor-pointer" svg-classes="text-danger" @click="$emit('remove', index)"/>
</div>
</div>
</template>
<script>
import NumberXTableFilter from "./NumberXTableFilter";
import SwitchXTableFilter from './SwitchXTableFilter'
import SelectOptionXTableFilter from './SelectOptionXTableFilter'
import DateXTableFilter from './DateXTableFilter'
import TextXTableFilter from './TextXTableFilter'
import QuerySelectTableFilter from './QuerySelectTableFilter'
export default {
name: "XFilterRow",
components: {
NumberXTableFilter,
SwitchXTableFilter,
SelectOptionXTableFilter,
QuerySelectTableFilter,
DateXTableFilter,
TextXTableFilter,
},
props: {
value: {default: {}},
isFirst: {default: false},
id: {},
index: {},
colFilters: {default: []}
},
data() {
return {
col: undefined,
op: undefined,
master: undefined,
cr: 'and',
input: undefined,
}
},
computed: {
hasInput() {
if (this.op) {
return !['null', 'nn'].includes(this.op);
}
},
getModifierComponent() {
const comp = {
'text': 'TextXTableFilter',
'default': 'TextXTableFilter',
'number': 'NumberXTableFilter',
'date': 'DateXTableFilter',
'switch': 'SwitchXTableFilter',
'select': 'SelectOptionXTableFilter',
'query': 'QuerySelectTableFilter',
};
return comp[this.type];
},
getModel() {
return {
cr: this.cr,
index: this.index,
field: this.col,
master: this.master,
type: this.type,
id: this.id,
op: this.op,
value: this.input
}
},
filterObject() {
return this.colFilters.find((item) => item.key == this.col);
},
type() {
if (this.filterObject) {
return this.filterObject.filterType;
}
},
colTypes() {
const exp = {};
if (!this.col) return [];
const filter = this.colFilters.find((item) => item.key == this.col);
if (!filter) return [];
switch (filter.filterType) {
case 'number':
case 'date':
exp.gt = 'بزرگتر';
exp.lt = 'کوچکتر';
exp.gte = 'بزرگتر مساوی';
exp.lte = 'کوچکتر مساوی';
// exp.bet = 'بین';
break;
case 'text':
exp.sw = 'شروع شود';
exp.ew = 'تمام شود';
break;
}
exp.eq = 'برابر';
exp.has = 'شامل';
exp.not = 'نباشد';
exp.null = 'تهی';
exp.nn = 'تهی نباشد';
return exp;
}
},
methods: {
change() {
const filter = this.colFilters.find((item) => item.key == this.col);
this.master = filter.master;
this.$emit('input', this.getModel);
}
},
mounted() {
this.cr = this.value.cr || 'and';
// this.index = this.value.index;
console.log("this.value.field ==> ", this.value);
this.col = this.value.field;
// this.type = this.value.type;
this.op = this.value.op;
this.input = this.value.value;
}
}
</script>
<style scoped>
</style>
+6
View File
@@ -0,0 +1,6 @@
import Xtc from "./model/Xtc";
import XTbl from "./model/XTbl";
export {Xtc};
export default XTbl;
+30
View File
@@ -0,0 +1,30 @@
export interface Xtc {
title: string;
key: string;
filter(): Xtc;
filterSwitch(): Xtc;
filterSelect(items: {}[]): Xtc;
filterDate(): Xtc;
filterNumber(): Xtc;
renderSlot(slotName: string): Xtc;
export(): {};
}
export interface XTbl {
title: string;
url: string;
cols: Xtc[];
addCol(col: Xtc): void;
addAll(cols: Xtc[]): void;
}
+62
View File
@@ -0,0 +1,62 @@
import Xtc from './Xtc'
export default class XTbl {
title;
url;
cols;
opt;
constructor(url, title) {
this.url = url;
this.title = title;
}
add(col) {
if (!this.cols) {
this.cols = [];
}
this.cols.push(col);
}
addOpt(col, slotEdit, slotDelete, ridEdit, ridDelete) {
this.opt = new Xtc('opt', 'عملیات').noSort();
this.opt.opt = true;
this.opt.slotEdit = slotEdit;
this.opt.slotDelete = slotDelete;
this.cols.push(this.opt)
return this;
}
hidePagination() {
this._hidePageination = true;
return this;
}
getSortFields() {
return this.cols.filter((item) => item.__sorter)
}
hideSearch() {
this._hidePageination = true;
return this;
}
addExtraBtn(btn) {
this._hidePageination = true;
return this;
}
noSearch() {
this._noSearch = true;
return this;
}
noSettings() {
this._noSettings = true;
return this;
}
}
+106
View File
@@ -0,0 +1,106 @@
export default class Xtc {
constructor(key, title) {
this.key = key;
this.title = title;
this.dataIndex = key;
this.show = true;
this.__sorter = true;
}
export() {
let exp = {};
exp['key'] = this.key;
exp['__key'] = this.__fkey;
exp['dataIndex'] = this.key;
exp['title'] = this.title;
if (this._slots) {
if(!this._slots.filterIcon){
this._slots.filterIcon = 'filterIcon';
}
exp['scopedSlots'] = this._slots;
}
if (this.filter) {
this.filter = this.filterType;
this.filtered = true;
}
return exp;
}
filterKey(key){
this.__fkey = key;
this.master = key;
return this;
}
renderSlot(name) {
this._slots = {
customRender: name
};
if (!this.scopedSlots) {
this.scopedSlots = {}
}
this.scopedSlots.customRender = name;
return this;
}
__filter() {
this.filtered = true;
if (!this._slots) {
this.scopedSlots = {};
}
this.scopedSlots.filterDropdown = `${this.key}_filterDropdown`;
this.scopedSlots.filterIcon = `${this.key}_filterIcon`;
}
filterText() {
this.__filter();
this.filterType = 'default';
return this;
}
filterSwitch() {
this.__filter();
this.filterType = 'switch';
return this;
}
filterQuery(action) {
this.__filter();
this.filterType = 'query';
this.filterAction = action;
return this;
}
filterDate() {
this.__filter();
this.filterType = 'date';
return this;
}
filterSelect(items) {
this.__filter();
this.filterType = 'select';
this.filterItems = items;
return this;
}
filterNumber() {
this.__filter();
this.filterType = 'number';
return this;
}
noSort() {
this.__sorter = false;
return this;
}
hidden() {
this.show = false;
return this;
}
}
+1
View File
@@ -0,0 +1 @@
git add . && git commit -m "Auto" && git push
+15
View File
@@ -0,0 +1,15 @@
import XTbl, {Xtc} from './index';
const tbl = new XTbl('http://kheyr.flut.ir/api/get-person', 'جدول مشتریان');
tbl.add(new Xtc('id', 'آیدی').filterNumber());
tbl.add(new Xtc('title', 'عنوان').filterText())
tbl.add(new Xtc('fname', 'نام کوچک').filterText())
tbl.add(new Xtc('lname', 'نام بزرگ').filterText())
tbl.add(new Xtc('ncode', 'کد ملی').filterText().hidden().noSort())
tbl.add(new Xtc('birth_date', 'تاریخ تولد').filterDate().hidden().noSort())
tbl.add(new Xtc('sts_str', 'وضعیت').renderSlot('sts_str').filterSelect({1: 'گزینه اول'}).noSort())
tbl.add(new Xtc('active', 'فعال').filterSwitch().hidden().noSort())
tbl.add(new Xtc('wow', 'فعال').filterSwitch().renderSlot('wow').noSort())
tbl.addOpt()
export default tbl;
+1 -1
View File
@@ -238,7 +238,7 @@
}, },
mounted() { mounted() {
this.fetch(); this.fetch();
console.log("this.model ==> ", this.model); // console.log("this.model ==> ", this.model);
} }
} }
</script> </script>
+1 -1
View File
@@ -37,7 +37,7 @@ mock.onGet('/api/apps/calendar/events').reply(() => {
return [200, data.events] return [200, data.events]
}) })
// POST : Add new events // POST : Add new-x-table events
mock.onPost('/api/apps/calendar/events/').reply((request) => { mock.onPost('/api/apps/calendar/events/').reply((request) => {
// Get event from post data // Get event from post data
+4 -4
View File
@@ -677,13 +677,13 @@ mock.onPost('/api/apps/email/set-starred').reply((request) => {
// let event = data.events.find((event) => event.id == eventId) // let event = data.events.find((event) => event.id == eventId)
// const payload = JSON.parse(request.data).payload // const payload = JSON.parse(request.data).payload
// const draggedDateStart = new Date(payload.date) // const draggedDateStart = new-x-table Date(payload.date)
// const eventStartDate = new Date(event.startDate).getTime() // const eventStartDate = new-x-table Date(event.startDate).getTime()
// const eventEndDate = new Date(event.endDate).getTime() // const eventEndDate = new-x-table Date(event.endDate).getTime()
// const diff = draggedDateStart - eventStartDate // const diff = draggedDateStart - eventStartDate
// const newEndDate = new Date(eventEndDate + diff) // const newEndDate = new-x-table Date(eventEndDate + diff)
// event.startDate = draggedDateStart // event.startDate = draggedDateStart
// event.endDate = newEndDate // event.endDate = newEndDate
+1 -1
View File
@@ -132,7 +132,7 @@ const data = {
] ]
} }
// POST : Add new Tasks // POST : Add new-x-table Tasks
mock.onPost('/api/apps/todo/tasks/').reply((request) => { mock.onPost('/api/apps/todo/tasks/').reply((request) => {
// Get task from post data // Get task from post data
+1 -1
View File
@@ -910,7 +910,7 @@ mock.onGet('/api/data-list/products').reply(() => {
return [200, JSON.parse(JSON.stringify(data.products)).reverse()] return [200, JSON.parse(JSON.stringify(data.products)).reverse()]
}) })
// POST : Add new Item // POST : Add new-x-table Item
mock.onPost('/api/data-list/products/').reply((request) => { mock.onPost('/api/data-list/products/').reply((request) => {
// Get event from post data // Get event from post data
+1 -1
View File
@@ -666,7 +666,7 @@ mock.onGet(/\/api\/user-management\/users\/\d+/).reply((request) => {
return user ? [200, JSON.parse(JSON.stringify(user))] : [404] return user ? [200, JSON.parse(JSON.stringify(user))] : [404]
}) })
// // POST : Add new Item // // POST : Add new-x-table Item
// mock.onPost("/api/data-list/products/").reply((request) => { // mock.onPost("/api/data-list/products/").reply((request) => {
// // Get event from post data // // Get event from post data
@@ -167,7 +167,32 @@ export default {
} }
}, },
menuItemsUpdated () { menuItemsUpdated () {
const clone = this.navMenuItems.slice() let new_item = []
// const clone = th
// .filter(item=> item.items)
const per = this.$store.state.access.permissions
// console.log(per,'perererererer')
if(per != undefined){
this.navMenuItems.map( menus=> {
// item=>item.items.map(menus=>{
if (menus.submenu) {
let submenu = menus.submenu.filter(menu => (menu.permissionId && per.includes(menu.permissionId)))
menus.submenu = submenu
if (submenu.length) new_item.push(menus)
} else {
if ((menus.permissionId && per.includes(menus.permissionId))) {
new_item.push(menus)
}
}
// })
})
return new_item
}
// console.log(new_item,'new_item')
/*const clone = this.navMenuItems.slice()
for (const [index, item] of this.navMenuItems.entries()) { for (const [index, item] of this.navMenuItems.entries()) {
if (item.header && item.items.length && (index || 1)) { if (item.header && item.items.length && (index || 1)) {
@@ -181,7 +206,7 @@ export default {
console.log(clone console.log(clone
) )
return clone return clone*/
}, },
isVerticalNavMenuActive: { isVerticalNavMenuActive: {
get () { return this.$store.state.isVerticalNavMenuActive }, get () { return this.$store.state.isVerticalNavMenuActive },
@@ -6,12 +6,14 @@ export default [
icon: 'HomeIcon', icon: 'HomeIcon',
i18n: 'داشبورد', i18n: 'داشبورد',
slug: "config", slug: "config",
permissionId:'home'
}, },
{ {
url: '/config', url: '/config',
icon: 'LayersIcon', icon: 'LayersIcon',
i18n: 'پیکربندی', i18n: 'پیکربندی',
slug: 'config', slug: 'config',
permissionId:'config'
}, },
{ {
url: "/proposal", url: "/proposal",
@@ -19,6 +21,7 @@ export default [
slug: "proposal", slug: "proposal",
icon: "AlignJustifyIcon", icon: "AlignJustifyIcon",
i18n: "درخواست ها", i18n: "درخواست ها",
permissionId:'request'
}, },
{ {
url: "/personel", url: "/personel",
@@ -26,6 +29,7 @@ export default [
slug: "personel", slug: "personel",
icon: "AlignJustifyIcon", icon: "AlignJustifyIcon",
i18n: "اطلاعات پرسنلی", i18n: "اطلاعات پرسنلی",
permissionId:'personnel'
}, },
{ {
url: "/permission", url: "/permission",
@@ -33,6 +37,15 @@ export default [
slug: "permission", slug: "permission",
icon: "AlignJustifyIcon", icon: "AlignJustifyIcon",
i18n: "سطح دسترسی", i18n: "سطح دسترسی",
permissionId:'permission.show'
},
{
url: "/users",
name: "users",
slug: "users",
icon: "UserIcon",
i18n: "کاربران",
permissionId:'user'
} }
] ]
+21
View File
@@ -132,6 +132,27 @@ require('./assets/css/iconfont.css')
// Note: In latest version you have to add it separately // Note: In latest version you have to add it separately
// import 'vue-select/dist/vue-select.css'; // import 'vue-select/dist/vue-select.css';
//permission functions
Vue.prototype.$getAccess = (rid)=>{
const roles = store.state.access.permissions
if(roles){
return roles.includes(rid)
}
}
import VuePersianDatetimePicker from 'vue-persian-datetime-picker';
Vue.use(VuePersianDatetimePicker, {
name: 'date-picker',
props: {
format: 'YYYY-MM-DD HH:mm',
displayFormat: 'jYYYY-jMM-jDD HH:mm',
editable: false,
inputClass: '',
placeholder: 'انتخاب کنید',
altFormat: 'YYYY-MM-DD HH:mm',
color: '#1DA57A',
autoSubmit: true,
}
});
Vue.config.productionTip = false Vue.config.productionTip = false
+42 -5
View File
@@ -49,7 +49,10 @@ const router = new Router({
{ {
path: '/', path: '/',
name: 'dashboard', name: 'dashboard',
redirect: '/dashboard' redirect: '/dashboard',
meta: {
rule: 'editor'
}
}, },
{ {
path: '/dashboard', path: '/dashboard',
@@ -86,6 +89,24 @@ const router = new Router({
parent: 'main' parent: 'main'
} }
}, },
{
path: '/users',
name: 'users',
component: () => import('./views/users/users.vue'),
meta: {
rule: 'editor',
parent: 'main'
}
},
{
path: '/register/users',
name: 'register-users',
component: () => import('./views/users/create.vue'),
meta: {
rule: 'editor',
parent: 'main'
}
},
{ {
path: '/register/personnel', path: '/register/personnel',
name: 'register-personnel', name: 'register-personnel',
@@ -106,6 +127,23 @@ const router = new Router({
}, },
] ]
}, },
{
path: '/pages/error-404',
name: 'error-404',
component: () => import('./views/pages/Error404'),
meta: {
rule: 'editor'
}
},
{
path: '/pages/error-403',
name: 'error-403',
component: () => import('./views/pages/NotAuthorized'),
meta: {
rule: 'editor'
}
},
{ {
path: '*', path: '*',
redirect: '/pages/error-404' redirect: '/pages/error-404'
@@ -125,21 +163,20 @@ router.beforeEach((to, from, next) => {
let isLogin = sessionStorage.getItem('accessToken'); let isLogin = sessionStorage.getItem('accessToken');
//console.log("to.path ==> ", to.path); //console.log("to.path ==> ", to.path);
if ( if (
(
to.path === "/register/form" || to.path === "/register/form" ||
to.path === "/auth/login" || to.path === "/auth/login" ||
to.path === "/auth/register" || to.path === "/auth/register" ||
to.path === "/pages/error-404" || to.path === "/pages/error-404" ||
to.path === "/pages/error-403" ||
to.path === "/auth/forgot-password" to.path === "/auth/forgot-password"
) ) {
) {
/* if (isLogin) { /* if (isLogin) {
router.push({path: '/'}); router.push({path: '/'});
}*/ }*/
return next(); return next();
} }
if (!isLogin) { else if (!isLogin) {
router.push({path: '/auth/login'}); router.push({path: '/auth/login'});
return; return;
} else { } else {
+26 -2
View File
@@ -1,13 +1,34 @@
import axios from '@/axios' import axios from '@/axios'
function getParents(keys) {
let parents = []
while (keys.length > 1) {
keys.pop()
parents.push(keys.join('.'))
}
return parents
}
const state = { const state = {
loading: false, loading: false,
access_id:undefined access_id:undefined,
permissions:undefined
}; };
const actions = { const actions = {
setPermissions({commit}, payload){
let rid = payload
payload.map(x => {
const keys = x.split('.')
if (keys.length > 1) {
const set1 = new Set([...rid, ...getParents(keys)])
rid = [...set1]
}
})
console.log("rid",rid)
commit('SetPermissions', rid);
},
async save({commit}, payload) { async save({commit}, payload) {
try { try {
commit('LOADING', true); commit('LOADING', true);
@@ -33,6 +54,9 @@ const actions = {
} }
const mutations = { const mutations = {
SetPermissions(state, payload) {
state.permissions = payload;
},
LOADING(state, payload) { LOADING(state, payload) {
state.loading = payload; state.loading = payload;
}, },
+1 -1
View File
@@ -174,7 +174,7 @@ export default {
// if username update is not required // if username update is not required
// just reload the page to get fresh data // just reload the page to get fresh data
// set new user data in localstorage // set new-x-table user data in localstorage
if (!isUsernameUpdateRequired) { if (!isUsernameUpdateRequired) {
router.push(router.currentRoute.query.to || '/') router.push(router.currentRoute.query.to || '/')
commit('UPDATE_USER_INFO', result.user.providerData[0], {root: true}) commit('UPDATE_USER_INFO', result.user.providerData[0], {root: true})
+4 -4
View File
@@ -31,7 +31,7 @@ export default {
}) })
}, },
// fetchEventLabels({ commit }) { // fetchEventLabels({ commit }) {
// return new Promise((resolve, reject) => { // return new-x-table Promise((resolve, reject) => {
// axios.get("/api/apps/calendar/labels") // axios.get("/api/apps/calendar/labels")
// .then((response) => { // .then((response) => {
// commit('SET_LABELS', response.data) // commit('SET_LABELS', response.data)
@@ -61,14 +61,14 @@ export default {
}) })
} }
// eventDragged({ commit }, payload) { // eventDragged({ commit }, payload) {
// return new Promise((resolve, reject) => { // return new-x-table Promise((resolve, reject) => {
// axios.post(`/api/apps/calendar/event/dragged/${payload.event.id}`, {payload: payload}) // axios.post(`/api/apps/calendar/event/dragged/${payload.event.id}`, {payload: payload})
// .then((response) => { // .then((response) => {
// // Convert Date String to Date Object // // Convert Date String to Date Object
// let event = response.data // let event = response.data
// event.startDate = new Date(event.startDate) // event.startDate = new-x-table Date(event.startDate)
// event.endDate = new Date(event.endDate) // event.endDate = new-x-table Date(event.endDate)
// commit('UPDATE_EVENT', event) // commit('UPDATE_EVENT', event)
// resolve(response) // resolve(response)
+1 -1
View File
@@ -15,7 +15,7 @@ export default {
{ "name": "Beats by Dr. Dre - Geek Squad Certified Refurbished Beats Studio Wireless On-Ear Headphones - Red", "description": "Rock out to your favorite songs with these Beats by Dr. Dre Beats Studio Wireless GS-MH8K2AM/A headphones that feature a Beats Acoustic Engine and DSP software for enhanced clarity. ANC (Adaptive Noise Cancellation) allows you to focus on your tunes.", "brand": "Beats by Dr. Dre", "categories": ["Audio", "Headphones", "All Headphones"], "hierarchicalCategories": { "lvl0": "Audio", "lvl1": "Audio > Headphones", "lvl2": "Audio > Headphones > All Headphones" }, "type": "Refurbished beats", "price": 379.99, "price_range": "200 - 500", "image": "https://cdn-demo.algolia.com/bestbuy-0118/4784058_sb.jpg", "url": "https://api.bestbuy.com/click/-/4784058/pdp", "free_shipping": false, "rating": 4, "popularity": 15883, "objectID": "4784058", "_highlightResult": { "name": { "value": "<mark>Beats</mark> <mark>by</mark> <mark>Dr.</mark> Dre - Geek Squad Certified Refurbished <mark>Beats</mark> Studio Wireless On-Ear Headphones - Red", "matchLevel": "full", "fullyHighlighted": false, "matchedWords": ["beats", "by", "dr"] }, "description": { "value": "Rock out to your favorite songs with these <mark>Beats</mark> <mark>by</mark> <mark>Dr.</mark> Dre <mark>Beats</mark> Studio Wireless GS-MH8K2AM/A headphones that feature a <mark>Beats</mark> Acoustic Engine and DSP software for enhanced clarity. ANC (Adaptive Noise Cancellation) allows you to focus on your tunes.", "matchLevel": "full", "fullyHighlighted": false, "matchedWords": ["beats", "by", "dr"] }, "brand": { "value": "<mark>Beats</mark> <mark>by</mark> <mark>Dr.</mark> Dre", "matchLevel": "full", "fullyHighlighted": false, "matchedWords": ["beats", "by", "dr"] }, "categories": [{ "value": "Audio", "matchLevel": "none", "matchedWords": [] }, { "value": "Headphones", "matchLevel": "none", "matchedWords": [] }, { "value": "All Headphones", "matchLevel": "none", "matchedWords": [] }] }, "quantity": 1, "discount_in_percentage": 12, "offers_count": 3, "delivery_date": "Wed Apr 9" }, { "name": "Beats by Dr. Dre - Geek Squad Certified Refurbished Beats Studio Wireless On-Ear Headphones - Red", "description": "Rock out to your favorite songs with these Beats by Dr. Dre Beats Studio Wireless GS-MH8K2AM/A headphones that feature a Beats Acoustic Engine and DSP software for enhanced clarity. ANC (Adaptive Noise Cancellation) allows you to focus on your tunes.", "brand": "Beats by Dr. Dre", "categories": ["Audio", "Headphones", "All Headphones"], "hierarchicalCategories": { "lvl0": "Audio", "lvl1": "Audio > Headphones", "lvl2": "Audio > Headphones > All Headphones" }, "type": "Refurbished beats", "price": 379.99, "price_range": "200 - 500", "image": "https://cdn-demo.algolia.com/bestbuy-0118/4784058_sb.jpg", "url": "https://api.bestbuy.com/click/-/4784058/pdp", "free_shipping": false, "rating": 4, "popularity": 15883, "objectID": "4784058", "_highlightResult": { "name": { "value": "<mark>Beats</mark> <mark>by</mark> <mark>Dr.</mark> Dre - Geek Squad Certified Refurbished <mark>Beats</mark> Studio Wireless On-Ear Headphones - Red", "matchLevel": "full", "fullyHighlighted": false, "matchedWords": ["beats", "by", "dr"] }, "description": { "value": "Rock out to your favorite songs with these <mark>Beats</mark> <mark>by</mark> <mark>Dr.</mark> Dre <mark>Beats</mark> Studio Wireless GS-MH8K2AM/A headphones that feature a <mark>Beats</mark> Acoustic Engine and DSP software for enhanced clarity. ANC (Adaptive Noise Cancellation) allows you to focus on your tunes.", "matchLevel": "full", "fullyHighlighted": false, "matchedWords": ["beats", "by", "dr"] }, "brand": { "value": "<mark>Beats</mark> <mark>by</mark> <mark>Dr.</mark> Dre", "matchLevel": "full", "fullyHighlighted": false, "matchedWords": ["beats", "by", "dr"] }, "categories": [{ "value": "Audio", "matchLevel": "none", "matchedWords": [] }, { "value": "Headphones", "matchLevel": "none", "matchedWords": [] }, { "value": "All Headphones", "matchLevel": "none", "matchedWords": [] }] }, "quantity": 1, "discount_in_percentage": 12, "offers_count": 3, "delivery_date": "Wed Apr 9" },
{ "name": "Sony - PlayStation 4 Pro Console", "description": "PS4 Pro Dynamic 4K Gaming & 4K Entertainment* PS4 Pro gets you closer to your game. Heighten your experiences. Enrich your adventures. Let the super-charged PS4 Pro lead the way.** GREATNESS AWAITS", "brand": "Sony", "categories": ["Video Games", "PlayStation 4", "PS4 Consoles"], "hierarchicalCategories": { "lvl0": "Video Games", "lvl1": "Video Games > PlayStation 4", "lvl2": "Video Games > PlayStation 4 > PS4 Consoles" }, "type": "Playstation 4 hw", "price": 399.99, "price_range": "200 - 500", "image": "https://cdn-demo.algolia.com/bestbuy-0118/5388900_sb.jpg", "url": "https://api.bestbuy.com/click/-/5388900/pdp", "free_shipping": true, "rating": 4, "popularity": 21402, "objectID": "5388900", "_highlightResult": { "name": { "value": "<mark>Sony</mark> - <mark>Pla</mark>yStation 4 Pro Console", "matchLevel": "full", "fullyHighlighted": false, "matchedWords": ["sony", "pla"] }, "description": { "value": "PS4 Pro Dynamic 4K Gaming &amp; 4K Entertainment* PS4 Pro gets you closer to your game. Heighten your experiences. Enrich your adventures. Let the super-charged PS4 Pro lead the way.** GREATNESS AWAITS", "matchLevel": "none", "matchedWords": [] }, "brand": { "value": "<mark>Sony</mark>", "matchLevel": "partial", "fullyHighlighted": true, "matchedWords": ["sony"] }, "categories": [{ "value": "Video Games", "matchLevel": "none", "matchedWords": [] }, { "value": "<mark>Pla</mark>yStation 4", "matchLevel": "partial", "fullyHighlighted": false, "matchedWords": ["pla"] }, { "value": "PS4 Consoles", "matchLevel": "none", "matchedWords": [] }] }, "quantity": 1, "discount_in_percentage": 3, "offers_count": 1, "delivery_date": "Wed Apr 12" }, { "name": "Sony - PlayStation 4 Pro Console", "description": "PS4 Pro Dynamic 4K Gaming & 4K Entertainment* PS4 Pro gets you closer to your game. Heighten your experiences. Enrich your adventures. Let the super-charged PS4 Pro lead the way.** GREATNESS AWAITS", "brand": "Sony", "categories": ["Video Games", "PlayStation 4", "PS4 Consoles"], "hierarchicalCategories": { "lvl0": "Video Games", "lvl1": "Video Games > PlayStation 4", "lvl2": "Video Games > PlayStation 4 > PS4 Consoles" }, "type": "Playstation 4 hw", "price": 399.99, "price_range": "200 - 500", "image": "https://cdn-demo.algolia.com/bestbuy-0118/5388900_sb.jpg", "url": "https://api.bestbuy.com/click/-/5388900/pdp", "free_shipping": true, "rating": 4, "popularity": 21402, "objectID": "5388900", "_highlightResult": { "name": { "value": "<mark>Sony</mark> - <mark>Pla</mark>yStation 4 Pro Console", "matchLevel": "full", "fullyHighlighted": false, "matchedWords": ["sony", "pla"] }, "description": { "value": "PS4 Pro Dynamic 4K Gaming &amp; 4K Entertainment* PS4 Pro gets you closer to your game. Heighten your experiences. Enrich your adventures. Let the super-charged PS4 Pro lead the way.** GREATNESS AWAITS", "matchLevel": "none", "matchedWords": [] }, "brand": { "value": "<mark>Sony</mark>", "matchLevel": "partial", "fullyHighlighted": true, "matchedWords": ["sony"] }, "categories": [{ "value": "Video Games", "matchLevel": "none", "matchedWords": [] }, { "value": "<mark>Pla</mark>yStation 4", "matchLevel": "partial", "fullyHighlighted": false, "matchedWords": ["pla"] }, { "value": "PS4 Consoles", "matchLevel": "none", "matchedWords": [] }] }, "quantity": 1, "discount_in_percentage": 3, "offers_count": 1, "delivery_date": "Wed Apr 12" },
{ "name": "Apple - Macbook® (Latest Model) - 12\" Display - Intel Core M5 - 8GB Memory - 512GB Flash Storage - Space Gray", "description": "MacBook delivers a full-size experience in the lightest and most compact Mac notebook ever. With a full-size keyboard, force-sensing trackpad, 12-inch Retina display,1 sixth-generation Intel Core M processor, multifunctional USB-C port, and now up to 10 hours of battery life,2 MacBook features big thinking in an impossibly compact form.", "brand": "Apple", "categories": ["Computers & Tablets", "Laptops", "All Laptops", "MacBooks"], "hierarchicalCategories": { "lvl0": "Computers & Tablets", "lvl1": "Computers & Tablets > Laptops", "lvl2": "Computers & Tablets > Laptops > All Laptops", "lvl3": "Computers & Tablets > Laptops > All Laptops > MacBooks" }, "type": "Apple", "price": 1599.99, "price_range": "500 - 2000", "image": "https://cdn-demo.algolia.com/bestbuy-0118/5229600_sb.jpg", "url": "https://api.bestbuy.com/click/-/5229600/pdp", "free_shipping": true, "rating": 4, "popularity": 19609, "objectID": "5229600", "_highlightResult": { "name": { "value": "<mark>Apple</mark> - Macbook® (Latest Model) - 12&quot; Display - Intel Core M5 - 8GB Memory - 512GB Flash Storage - Space Gray", "matchLevel": "partial", "fullyHighlighted": false, "matchedWords": ["apple"] }, "description": { "value": "MacBook delivers a full-size experience in the lightest and most compact Mac notebook ever. With a full-size keyboard, force-sensing trackpad, 12-inch Retina display,1 sixth-generation Intel Core M processor, multifunctional USB-C port, and now up to 10 hours of battery life,2 MacBook features big thinking in an impossibly compact form.", "matchLevel": "none", "matchedWords": [] }, "brand": { "value": "<mark>Apple</mark>", "matchLevel": "partial", "fullyHighlighted": true, "matchedWords": ["apple"] }, "categories": [{ "value": "Computers &amp; Tablets", "matchLevel": "none", "matchedWords": [] }, { "value": "<mark>Laptops</mark>", "matchLevel": "partial", "fullyHighlighted": true, "matchedWords": ["laptop"] }, { "value": "All <mark>Laptops</mark>", "matchLevel": "partial", "fullyHighlighted": false, "matchedWords": ["laptop"] }, { "value": "MacBooks", "matchLevel": "none", "matchedWords": [] }] }, "quantity": 1, "discount_in_percentage": 7, "offers_count": 1, "delivery_date": "Wed Apr 14" }, { "name": "Apple - Macbook® (Latest Model) - 12\" Display - Intel Core M5 - 8GB Memory - 512GB Flash Storage - Space Gray", "description": "MacBook delivers a full-size experience in the lightest and most compact Mac notebook ever. With a full-size keyboard, force-sensing trackpad, 12-inch Retina display,1 sixth-generation Intel Core M processor, multifunctional USB-C port, and now up to 10 hours of battery life,2 MacBook features big thinking in an impossibly compact form.", "brand": "Apple", "categories": ["Computers & Tablets", "Laptops", "All Laptops", "MacBooks"], "hierarchicalCategories": { "lvl0": "Computers & Tablets", "lvl1": "Computers & Tablets > Laptops", "lvl2": "Computers & Tablets > Laptops > All Laptops", "lvl3": "Computers & Tablets > Laptops > All Laptops > MacBooks" }, "type": "Apple", "price": 1599.99, "price_range": "500 - 2000", "image": "https://cdn-demo.algolia.com/bestbuy-0118/5229600_sb.jpg", "url": "https://api.bestbuy.com/click/-/5229600/pdp", "free_shipping": true, "rating": 4, "popularity": 19609, "objectID": "5229600", "_highlightResult": { "name": { "value": "<mark>Apple</mark> - Macbook® (Latest Model) - 12&quot; Display - Intel Core M5 - 8GB Memory - 512GB Flash Storage - Space Gray", "matchLevel": "partial", "fullyHighlighted": false, "matchedWords": ["apple"] }, "description": { "value": "MacBook delivers a full-size experience in the lightest and most compact Mac notebook ever. With a full-size keyboard, force-sensing trackpad, 12-inch Retina display,1 sixth-generation Intel Core M processor, multifunctional USB-C port, and now up to 10 hours of battery life,2 MacBook features big thinking in an impossibly compact form.", "matchLevel": "none", "matchedWords": [] }, "brand": { "value": "<mark>Apple</mark>", "matchLevel": "partial", "fullyHighlighted": true, "matchedWords": ["apple"] }, "categories": [{ "value": "Computers &amp; Tablets", "matchLevel": "none", "matchedWords": [] }, { "value": "<mark>Laptops</mark>", "matchLevel": "partial", "fullyHighlighted": true, "matchedWords": ["laptop"] }, { "value": "All <mark>Laptops</mark>", "matchLevel": "partial", "fullyHighlighted": false, "matchedWords": ["laptop"] }, { "value": "MacBooks", "matchLevel": "none", "matchedWords": [] }] }, "quantity": 1, "discount_in_percentage": 7, "offers_count": 1, "delivery_date": "Wed Apr 14" },
{ "name": "Apple - Apple Watch Series 1 42mm Space Gray Aluminum Case Black Sport Band - Space Gray Aluminum", "description": "Durable, lightweight aluminum cases in silver, space gray, gold, and rose gold. Sport Band in a variety of colors. All the features of the original Apple Watch, plus a new dual-core processor for faster performance. All models run watchOS 3. Requires an iPhone 5 or later.", "brand": "Apple", "categories": ["Wearable Technology", "Apple Watch", "Apple Watch Series 1"], "hierarchicalCategories": { "lvl0": "Wearable Technology", "lvl1": "Wearable Technology > Apple Watch", "lvl2": "Wearable Technology > Apple Watch > Apple Watch Series 1" }, "type": "Standard apple watch", "price": 299, "price_range": "200 - 500", "image": "https://cdn-demo.algolia.com/bestbuy-0118/5546604_sb.jpg", "url": "https://api.bestbuy.com/click/-/5546604/pdp", "free_shipping": true, "rating": 4, "popularity": 21419, "objectID": "5546604", "_highlightResult": { "name": { "value": "<mark>Apple</mark> - <mark>Apple</mark> Watch Series 1 42mm Space Gray Aluminum Case Black Sport Band - Space Gray Aluminum", "matchLevel": "full", "fullyHighlighted": false, "matchedWords": ["apple"] }, "description": { "value": "Durable, lightweight aluminum cases in silver, space gray, gold, and rose gold. Sport Band in a variety of colors. All the features of the original <mark>Apple</mark> Watch, plus a new dual-core processor for faster performance. All models run watchOS 3. Requires an iPhone 5 or later.", "matchLevel": "full", "fullyHighlighted": false, "matchedWords": ["apple"] }, "brand": { "value": "<mark>Apple</mark>", "matchLevel": "full", "fullyHighlighted": true, "matchedWords": ["apple"] }, "categories": [{ "value": "Wearable Technology", "matchLevel": "none", "matchedWords": [] }, { "value": "<mark>Apple</mark> Watch", "matchLevel": "full", "fullyHighlighted": false, "matchedWords": ["apple"] }, { "value": "<mark>Apple</mark> Watch Series 1", "matchLevel": "full", "fullyHighlighted": false, "matchedWords": ["apple"] }], "type": { "value": "Standard <mark>apple</mark> watch", "matchLevel": "full", "fullyHighlighted": false, "matchedWords": ["apple"] } }, "quantity": 1, "discount_in_percentage": 17, "offers_count": 4, "delivery_date": "Wed Apr 15" }, { "name": "Apple - Apple Watch Series 1 42mm Space Gray Aluminum Case Black Sport Band - Space Gray Aluminum", "description": "Durable, lightweight aluminum cases in silver, space gray, gold, and rose gold. Sport Band in a variety of colors. All the features of the original Apple Watch, plus a new-x-table dual-core processor for faster performance. All models run watchOS 3. Requires an iPhone 5 or later.", "brand": "Apple", "categories": ["Wearable Technology", "Apple Watch", "Apple Watch Series 1"], "hierarchicalCategories": { "lvl0": "Wearable Technology", "lvl1": "Wearable Technology > Apple Watch", "lvl2": "Wearable Technology > Apple Watch > Apple Watch Series 1" }, "type": "Standard apple watch", "price": 299, "price_range": "200 - 500", "image": "https://cdn-demo.algolia.com/bestbuy-0118/5546604_sb.jpg", "url": "https://api.bestbuy.com/click/-/5546604/pdp", "free_shipping": true, "rating": 4, "popularity": 21419, "objectID": "5546604", "_highlightResult": { "name": { "value": "<mark>Apple</mark> - <mark>Apple</mark> Watch Series 1 42mm Space Gray Aluminum Case Black Sport Band - Space Gray Aluminum", "matchLevel": "full", "fullyHighlighted": false, "matchedWords": ["apple"] }, "description": { "value": "Durable, lightweight aluminum cases in silver, space gray, gold, and rose gold. Sport Band in a variety of colors. All the features of the original <mark>Apple</mark> Watch, plus a new-x-table dual-core processor for faster performance. All models run watchOS 3. Requires an iPhone 5 or later.", "matchLevel": "full", "fullyHighlighted": false, "matchedWords": ["apple"] }, "brand": { "value": "<mark>Apple</mark>", "matchLevel": "full", "fullyHighlighted": true, "matchedWords": ["apple"] }, "categories": [{ "value": "Wearable Technology", "matchLevel": "none", "matchedWords": [] }, { "value": "<mark>Apple</mark> Watch", "matchLevel": "full", "fullyHighlighted": false, "matchedWords": ["apple"] }, { "value": "<mark>Apple</mark> Watch Series 1", "matchLevel": "full", "fullyHighlighted": false, "matchedWords": ["apple"] }], "type": { "value": "Standard <mark>apple</mark> watch", "matchLevel": "full", "fullyHighlighted": false, "matchedWords": ["apple"] } }, "quantity": 1, "discount_in_percentage": 17, "offers_count": 4, "delivery_date": "Wed Apr 15" },
], ],
wishList: [ wishList: [
{ "name": "Bowers & Wilkins - CM10 S2 Triple 6-1/2\" 3-Way Floorstanding Speaker (Each) - Gloss Black", "description": "Featuring triple 6-1/2\" bass cones, a 6\" midrange cone and a 1\" tweeter, this Bowers & Wilkins CM10 S2 floorstanding speaker fills a large room with stunning, true-to-life audio. The tweeter-on-top design ensures studio-grade sound is emitted.", "brand": "Bowers & Wilkins", "categories": ["Audio", "Home Audio", "Speakers", "Floor Speakers"], "hierarchicalCategories": { "lvl0": "Audio", "lvl1": "Audio > Home Audio", "lvl2": "Audio > Home Audio > Speakers", "lvl3": "Audio > Home Audio > Speakers > Floor Speakers" }, "type": "Mht floor speakers", "price": 1999.98, "price_range": "500 - 2000", "image": "https://cdn-demo.algolia.com/bestbuy-0118/8434275_sb.jpg", "url": "https://api.bestbuy.com/click/-/8434275/pdp", "free_shipping": false, "rating": 5, "popularity": 17253, "objectID": "8434275", "_highlightResult": { "name": { "value": "Bowers &amp; Wilkins - CM10 S2 Triple 6-1/2&quot; 3-Way Floorstanding Speaker (Each) - Gloss Black", "matchLevel": "none", "matchedWords": [] }, "description": { "value": "Featuring triple 6-1/2&quot; bass cones, a 6&quot; midrange cone and a 1&quot; tweeter, this Bowers &amp; Wilkins CM10 S2 floorstanding speaker fills a large room with stunning, true-to-life audio. The tweeter-on-top design ensures studio-grade sound is emitted.", "matchLevel": "none", "matchedWords": [] }, "brand": { "value": "Bowers &amp; Wilkins", "matchLevel": "none", "matchedWords": [] }, "categories": [{ "value": "Audio", "matchLevel": "none", "matchedWords": [] }, { "value": "Home Audio", "matchLevel": "none", "matchedWords": [] }, { "value": "Speakers", "matchLevel": "none", "matchedWords": [] }, { "value": "Floor Speakers", "matchLevel": "none", "matchedWords": [] }] } }, { "name": "Bowers & Wilkins - CM10 S2 Triple 6-1/2\" 3-Way Floorstanding Speaker (Each) - Gloss Black", "description": "Featuring triple 6-1/2\" bass cones, a 6\" midrange cone and a 1\" tweeter, this Bowers & Wilkins CM10 S2 floorstanding speaker fills a large room with stunning, true-to-life audio. The tweeter-on-top design ensures studio-grade sound is emitted.", "brand": "Bowers & Wilkins", "categories": ["Audio", "Home Audio", "Speakers", "Floor Speakers"], "hierarchicalCategories": { "lvl0": "Audio", "lvl1": "Audio > Home Audio", "lvl2": "Audio > Home Audio > Speakers", "lvl3": "Audio > Home Audio > Speakers > Floor Speakers" }, "type": "Mht floor speakers", "price": 1999.98, "price_range": "500 - 2000", "image": "https://cdn-demo.algolia.com/bestbuy-0118/8434275_sb.jpg", "url": "https://api.bestbuy.com/click/-/8434275/pdp", "free_shipping": false, "rating": 5, "popularity": 17253, "objectID": "8434275", "_highlightResult": { "name": { "value": "Bowers &amp; Wilkins - CM10 S2 Triple 6-1/2&quot; 3-Way Floorstanding Speaker (Each) - Gloss Black", "matchLevel": "none", "matchedWords": [] }, "description": { "value": "Featuring triple 6-1/2&quot; bass cones, a 6&quot; midrange cone and a 1&quot; tweeter, this Bowers &amp; Wilkins CM10 S2 floorstanding speaker fills a large room with stunning, true-to-life audio. The tweeter-on-top design ensures studio-grade sound is emitted.", "matchLevel": "none", "matchedWords": [] }, "brand": { "value": "Bowers &amp; Wilkins", "matchLevel": "none", "matchedWords": [] }, "categories": [{ "value": "Audio", "matchLevel": "none", "matchedWords": [] }, { "value": "Home Audio", "matchLevel": "none", "matchedWords": [] }, { "value": "Speakers", "matchLevel": "none", "matchedWords": [] }, { "value": "Floor Speakers", "matchLevel": "none", "matchedWords": [] }] } },
@@ -11,7 +11,7 @@ import axios from '@/axios.js'
export default { export default {
// addItem({ commit }, item) { // addItem({ commit }, item) {
// return new Promise((resolve, reject) => { // return new-x-table Promise((resolve, reject) => {
// axios.post("/api/data-list/products/", {item: item}) // axios.post("/api/data-list/products/", {item: item})
// .then((response) => { // .then((response) => {
// commit('ADD_ITEM', Object.assign(item, {id: response.data.id})) // commit('ADD_ITEM', Object.assign(item, {id: response.data.id}))
+1 -1
View File
@@ -1,4 +1,4 @@
import XTbl,{Xtc} from '../../components/x-table/index'; import XTbl,{Xtc} from '../../components/new-x-table/index';
const tbl = new XTbl('/admin/ipc/table', 'لسیت بسته ها'); const tbl = new XTbl('/admin/ipc/table', 'لسیت بسته ها');
tbl.add(new Xtc('title', 'نام بسته').filterText()) tbl.add(new Xtc('title', 'نام بسته').filterText())
+2 -2
View File
@@ -271,13 +271,13 @@
const {data} = await axios.get('site/city'); const {data} = await axios.get('site/city');
console.log(data,'city') console.log(data,'city')
this.cities = data; this.cities = data;
// this.provinces = new Set(Object.values(data).map((item) => item[0])); // this.provinces = new-x-table Set(Object.values(data).map((item) => item[0]));
}, },
// async getCity() { // async getCity() {
// const {data} = await axios.get('site/city'); // const {data} = await axios.get('site/city');
// this.provinceCities = data; // this.provinceCities = data;
// this.provinces = new Set(Object.values(data).map((item) => item[0])); // this.provinces = new-x-table Set(Object.values(data).map((item) => item[0]));
// }, // },
// //
// changeProvinces(value) { // changeProvinces(value) {
+2 -2
View File
@@ -25,8 +25,8 @@
<script> <script>
// function getBase64(file) { // function getBase64(file) {
// return new Promise((resolve, reject) => { // return new-x-table Promise((resolve, reject) => {
// const reader = new FileReader(); // const reader = new-x-table FileReader();
// reader.readAsDataURL(file); // reader.readAsDataURL(file);
// reader.onload = () => resolve(reader.result); // reader.onload = () => resolve(reader.result);
// reader.onerror = error => reject(error); // reader.onerror = error => reject(error);
+1 -1
View File
@@ -21,7 +21,7 @@
<!-- Month Name --> <!-- Month Name -->
<div class="vx-col w-1/3 items-center sm:flex hidden"> <div class="vx-col w-1/3 items-center sm:flex hidden">
<!-- Add new event button --> <!-- Add new-x-table event button -->
<vs-button icon-pack="feather" icon="icon-plus" @click="promptAddNewEvent(new Date())">Add</vs-button> <vs-button icon-pack="feather" icon="icon-plus" @click="promptAddNewEvent(new Date())">Add</vs-button>
</div> </div>
+1 -1
View File
@@ -10,7 +10,7 @@ tbl.add(new Xtc('email', 'ایمیل').filterText())
tbl.add(new Xtc('active', 'وضعیت اکانت').filterSelect().renderSlot('active')) tbl.add(new Xtc('active', 'وضعیت اکانت').filterSelect().renderSlot('active'))
tbl.add(new Xtc('total_adv', 'تعداد آگهی').filterNumber()) tbl.add(new Xtc('total_adv', 'تعداد آگهی').filterNumber())
tbl.add(new Xtc('caj', 'تاریخ عضویت').hidden().filterDate()) tbl.add(new Xtc('caj', 'تاریخ عضویت').hidden().filterDate())
// tbl.add(new Xtc('adv', 'دسته های ثبت آگهی').renderSlot('title_collection')) // tbl.add(new-x-table Xtc('adv', 'دسته های ثبت آگهی').renderSlot('title_collection'))
tbl.add(new Xtc('opt', 'عملیات').noSort().renderSlot('names')) tbl.add(new Xtc('opt', 'عملیات').noSort().renderSlot('names'))
export default tbl; export default tbl;
@@ -134,7 +134,7 @@
label="Full Name:" label="Full Name:"
v-model="fullName" v-model="fullName"
class="w-full mt-5" /> class="w-full mt-5" />
<span v-show="errors.has('add-new-address.fullName')" class="text-danger">{{ errors.first('add-new-address.fullName') }}</span> <span v-show="errors.has('add-new-x-table-address.fullName')" class="text-danger">{{ errors.first('add-new-x-table-address.fullName') }}</span>
</div> </div>
@@ -146,7 +146,7 @@
label="Mobile Number:" label="Mobile Number:"
v-model="mobileNum" v-model="mobileNum"
class="w-full mt-5" /> class="w-full mt-5" />
<span v-show="errors.has('add-new-address.mobileNum')" class="text-danger">{{ errors.first('add-new-address.mobileNum') }}</span> <span v-show="errors.has('add-new-x-table-address.mobileNum')" class="text-danger">{{ errors.first('add-new-x-table-address.mobileNum') }}</span>
</div> </div>
</div> </div>
@@ -162,7 +162,7 @@
label="Flat, House No:" label="Flat, House No:"
v-model="houseNum" v-model="houseNum"
class="w-full mt-5" /> class="w-full mt-5" />
<span v-show="errors.has('add-new-address.houseNum')" class="text-danger">{{ errors.first('add-new-address.houseNum') }}</span> <span v-show="errors.has('add-new-x-table-address.houseNum')" class="text-danger">{{ errors.first('add-new-x-table-address.houseNum') }}</span>
</div> </div>
<div class="vx-col sm:w-1/2 w-full"> <div class="vx-col sm:w-1/2 w-full">
@@ -186,7 +186,7 @@
label="Town/City:" label="Town/City:"
v-model="city" v-model="city"
class="w-full mt-5" /> class="w-full mt-5" />
<span v-show="errors.has('add-new-address.city')" class="text-danger">{{ errors.first('add-new-address.city') }}</span> <span v-show="errors.has('add-new-x-table-address.city')" class="text-danger">{{ errors.first('add-new-x-table-address.city') }}</span>
</div> </div>
<div class="vx-col sm:w-1/2 w-full"> <div class="vx-col sm:w-1/2 w-full">
@@ -196,7 +196,7 @@
label="Pincode:" label="Pincode:"
v-model="pincode" v-model="pincode"
class="w-full mt-5" /> class="w-full mt-5" />
<span v-show="errors.has('add-new-address.pincode')" class="text-danger">{{ errors.first('add-new-address.pincode') }}</span> <span v-show="errors.has('add-new-x-table-address.pincode')" class="text-danger">{{ errors.first('add-new-x-table-address.pincode') }}</span>
</div> </div>
</div> </div>
@@ -211,7 +211,7 @@
label="State:" label="State:"
v-model="state" v-model="state"
class="w-full mt-5" /> class="w-full mt-5" />
<span v-show="errors.has('add-new-address.state')" class="text-danger">{{ errors.first('add-new-address.state') }}</span> <span v-show="errors.has('add-new-x-table-address.state')" class="text-danger">{{ errors.first('add-new-x-table-address.state') }}</span>
</div> </div>
<div class="vx-col sm:w-1/2 w-full"> <div class="vx-col sm:w-1/2 w-full">
@@ -410,7 +410,7 @@ export default {
// TAB 2 // TAB 2
submitNewAddressForm () { submitNewAddressForm () {
return new Promise(() => { return new Promise(() => {
this.$validator.validateAll('add-new-address').then(result => { this.$validator.validateAll('add-new-x-table-address').then(result => {
if (result) { if (result) {
// if form have no errors // if form have no errors
this.$refs.checkoutWizard.nextTab() this.$refs.checkoutWizard.nextTab()
+1 -1
View File
@@ -1,6 +1,6 @@
<!-- ========================================================================================= <!-- =========================================================================================
File Name: TodoAddNew.vue File Name: TodoAddNew.vue
Description: Add new todo component Description: Add new-x-table todo component
---------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------
Item Name: Vuexy - Vuejs, HTML & Laravel Admin Dashboard Template Item Name: Vuexy - Vuejs, HTML & Laravel Admin Dashboard Template
Author: Pixinvent Author: Pixinvent
+1 -1
View File
@@ -1,6 +1,6 @@
<!-- ========================================================================================= <!-- =========================================================================================
File Name: TodoAddNew.vue File Name: TodoAddNew.vue
Description: Add new todo component Description: Add new-x-table todo component
---------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------
Item Name: Vuexy - Vuejs, HTML & Laravel Admin Dashboard Template Item Name: Vuexy - Vuejs, HTML & Laravel Admin Dashboard Template
Author: Pixinvent Author: Pixinvent
+11 -2
View File
@@ -70,6 +70,8 @@
</template> </template>
<script> <script>
import axios from "../../http/axios";
export default { export default {
data() { data() {
return { return {
@@ -100,7 +102,7 @@
} }
return true return true
}, },
loginJWT() { async loginJWT() {
if (!this.checkLogin()) return if (!this.checkLogin()) return
if (!this.validateForm) return if (!this.validateForm) return
@@ -112,7 +114,7 @@
password: this.password password: this.password
} }
}; };
this.$store.dispatch('auth/loginJWT', payload) await this.$store.dispatch('auth/loginJWT', payload)
.then(() => { this.$vs.loading.close() }) .then(() => { this.$vs.loading.close() })
.catch(({code , response}) => { .catch(({code , response}) => {
let msg = 'نام کاربری یا رمز عبور اشتباه است';//this.$t('Error Login '); let msg = 'نام کاربری یا رمز عبور اشتباه است';//this.$t('Error Login ');
@@ -122,6 +124,13 @@
this.$vs.loading.close() this.$vs.loading.close()
this.$message.error(msg); this.$message.error(msg);
}) })
try{
let {data:{permission}} = await axios.get('/permission/user')
await this.$store.dispatch("access/setPermissions", permission)
}
catch (e) {
console.log("eeeee: ",e)
}
}, },
registerUser() { registerUser() {
if (!this.checkLogin()) return if (!this.checkLogin()) return
+13 -13
View File
@@ -4,7 +4,7 @@
<a-card> <a-card>
<a-tabs default-active-key="1" style="direction: ltr" > <a-tabs default-active-key="1" style="direction: ltr" >
<a-tab-pane key="3" tab="شهرهای محل همکاری"> <a-tab-pane key="3" tab="شهرهای محل همکاری" v-if="$getAccess('config.city')">
<input <input
v-if="inputCityVisible" v-if="inputCityVisible"
@@ -18,21 +18,21 @@
@blur="handleInputConfirmCity" @blur="handleInputConfirmCity"
@keyup.enter="handleInputConfirmCity" @keyup.enter="handleInputConfirmCity"
/> />
<a-tag v-else style="background: #fff; borderStyle: dashed;" @click="showInputCity"> <a-tag v-else style="background: #fff; borderStyle: dashed;" @click="showInputCity" v-if="$getAccess('config.city.create')">
<a-icon type="plus" />افزودن <a-icon type="plus" />افزودن
</a-tag> </a-tag>
<template v-for="(city, index) in configCities"> <template v-for="(city, index) in configCities">
<a-tag :key="city.id" :closable="true" @close="() => handleCloseCity(city.id)"> <a-tag :key="city.id" :closable="$getAccess('config.city.delete')" @close="() => handleCloseCity(city.id)">
{{ city.title }} {{ city.title }}
</a-tag> </a-tag>
</template> </template>
<br> <br>
<a-button type="primary" class="mt-10" @click="saveCity()"> <a-button type="primary" class="mt-10" @click="saveCity()" v-if="$getAccess('config.city')">
ذخیره اطلاعات ذخیره اطلاعات
</a-button> </a-button>
</a-tab-pane> </a-tab-pane>
<a-tab-pane key="2" tab="دسته های آموزشی"> <a-tab-pane key="2" tab="دسته های آموزشی" v-if="$getAccess('config.category')">
<input <input
v-if="inputVisible" v-if="inputVisible"
class="ant-input" class="ant-input"
@@ -45,22 +45,22 @@
@blur="handleInputConfirm" @blur="handleInputConfirm"
@keyup.enter="handleInputConfirm" @keyup.enter="handleInputConfirm"
/> />
<a-tag v-else style="background: #fff; borderStyle: dashed;" @click="showInput"> <a-tag v-else style="background: #fff; borderStyle: dashed;" @click="showInput" v-if="$getAccess('config.category.create')">
<a-icon type="plus" /> افزودن دسته جدید آموزشی <a-icon type="plus" /> افزودن دسته جدید آموزشی
</a-tag> </a-tag>
<template v-for="(tag, index) in tags"> <template v-for="(tag, index) in tags">
<a-tag :key="tag" :closable="true" @close="() => handleClose(tag)"> <a-tag :key="tag" :closable="$getAccess('config.category.delete')" @close="() => handleClose(tag)">
{{ tag }} {{ tag }}
</a-tag> </a-tag>
</template> </template>
<br> <br>
<a-button type="primary" class="mt-10" @click="saveCategory()"> <a-button type="primary" class="mt-10" @click="saveCategory()" v-if="$getAccess('config.category')">
ذخیره اطلاعات ذخیره اطلاعات
</a-button> </a-button>
</a-tab-pane> </a-tab-pane>
<a-tab-pane key="1" tab="شغل ها"> <a-tab-pane key="1" tab="شغل ها" v-if="$getAccess('config.job')">
<div> <div>
<!-- <a-card title="شهرهای محل همکاری" :bordered="true" > <!-- <a-card title="شهرهای محل همکاری" :bordered="true" >
<a-form :form="formCities" @submit="handleSubmitCities"> <a-form :form="formCities" @submit="handleSubmitCities">
@@ -143,7 +143,7 @@
</div> </div>
<a-button @click="showAddJob =true" type="primary" class="mt-5"> <a-button @click="showAddJob =true" type="primary" class="mt-5" v-if="$getAccess('config.job.create')">
افزودن شغل افزودن شغل
</a-button > </a-button >
<br/> <br/>
@@ -174,7 +174,7 @@
<template slot="operator" slot-scope="{text,record}"> <template slot="operator" slot-scope="{text,record}">
<a-tooltip placement="bottomLeft"> <a-tooltip placement="bottomLeft" v-if="$getAccess('config.job.delete')">
<template slot="title"> <template slot="title">
<span>حذف</span> <span>حذف</span>
</template> </template>
@@ -190,7 +190,7 @@
</a-popconfirm> </a-popconfirm>
</a-tooltip> </a-tooltip>
<a-button type="primary" @click="showEditModal(record)" > <a-button type="primary" @click="showEditModal(record)" v-if="$getAccess('config.job.update')">
ویرایش ویرایش
</a-button> </a-button>
</template> </template>
@@ -252,7 +252,7 @@
<script> <script>
import * as TableCol from './jobTbl'; import * as TableCol from './jobTbl';
import XTable from "@/components/x-table/XTable"; import XTable from "@/components/new-x-table/XTable";
import axios from "@/axios"; import axios from "@/axios";
+6 -6
View File
@@ -1,8 +1,8 @@
import XTbl, {Xtc} from '../../components/x-table/index'; import XTbl, {Xtc} from '../../components/new-x-table/index';
const tbl = new XTbl('/jobsList', ''); const tbl = new XTbl('/job/table', '');
tbl.add(new Xtc('title', 'عنوان شغل').noSort()); tbl.add(new Xtc('title', 'عنوان شغل').filterText());
tbl.add(new Xtc('cities_str_slot', 'شهر های فعال در شغل').renderSlot('cities_str_slot').noSort()); tbl.add(new Xtc('cities_str_slot', 'شهر های فعال در شغل').renderSlot('cities_str_slot').filterText());
tbl.add(new Xtc('is_visible', 'نمایش در ثبت نام').renderSlot('visible').noSort()); tbl.add(new Xtc('is_visible', 'نمایش در ثبت نام').renderSlot('visible').filterSwitch());
tbl.add(new Xtc('id', 'عملیات').renderSlot('operator').noSort()) tbl.add(new Xtc('id', 'عملیات').renderSlot('operator'))
export default tbl; export default tbl;
+138 -78
View File
@@ -6,96 +6,141 @@
Author: Pixinvent Author: Pixinvent
Author URL: http://www.themeforest.net/user/pixinvent Author URL: http://www.themeforest.net/user/pixinvent
========================================================================================== --> ========================================================================================== -->
<template> <template>
<div> <a-spin type="loading" :spinning="loading">
<!-- <div class="grid grid-cols-4 gap-4"> <a-card title="نرخ خروج" class="mb-10">
<div> <div class="grid grid-cols-3 gap-10">
<a-card > <a-card class="flex flex-col items-center bg-custom">
<span>تعداد کل پرسنل</span> <h5 class="text-center">ماه گذشته</h5>
<h1>{{ model.total_personnel }}</h1> <div class="text-center">{{exit.past}}</div>
<a-divider /> </a-card>
<span>ثبت نام شده در 30 روز گذشته {{ model.last_month_personnel }}</span> <a-card class="flex flex-col items-center bg-custom">
<h5 class="text-center">ماه جاری</h5>
<div class="text-center">{{exit.current}}</div>
</a-card>
<a-card class="flex flex-col items-center bg-custom">
<h5 class="text-center">ماه آینده</h5>
<div class="text-center">{{exit.next}}</div>
</a-card> </a-card>
</div> </div>
<div> </a-card>
<a-card > <a-card title="منابع انسانی" class="mb-10">
<span>تعداد کل درخواست ها</span> <h4>جنسیت</h4>
<h1>{{ model.total_proposal }}</h1> <div class="grid grid-cols-3 gap-10 mb-10">
<a-divider /> <a-card class="flex flex-col items-center bg-custom">
<span>ثبت شده در 30 روز گذشته {{ model.last_month_proposal }}</span> <h5 class="text-center">کل</h5>
<div class="text-center" v-if="chart.index">{{chart.index.count_personnel}}</div>
</a-card>
<a-card class="flex flex-col items-center bg-custom">
<h5 class="text-center">زن</h5>
<div class="text-center" v-if="chart.index">{{chart.index.count_woman}}</div>
</a-card>
<a-card class="flex flex-col items-center bg-custom">
<h5 class="text-center">مرد</h5>
<div class="text-center" v-if="chart.index">{{chart.index.count_man}}</div>
</a-card> </a-card>
</div> </div>
<div> <a-card class="mb-10">
<a-card > <h4>تحصیلات</h4>
<span>تعداد کل قراداد ها</span> <a-table v-if="chart.index" class="mb-10" :data-source="chart.index.ed" :columns="[
<h1>{{ model.total_contract }}</h1> {title: 'تعداد',dataIndex: 'count'},
<a-divider /> {title: 'تحصیلات',dataIndex: 'level_str'},
<span>ثبت شده در 30 روز گذشته {{ model.last_month_contract }}</span> {title: 'وضعیت مدرک',dataIndex: 'has_certificate_str'},]"/>
</a-card> </a-card>
<a-card>
<h4>سن</h4>
<a-table v-if="chart.index" class="mb-10" :data-source="chart.index.list_age" :columns="[
{title: 'تعداد',dataIndex: 'count'},
{title: 'سن',dataIndex: 'age'},]"/>
</a-card>
</a-card>
<a-card title="فرایند جذب و نگهداشت" class="mb-10">
<div class="flex justify-between mb-10">
<h5>نسبت دعوت به مصاحبه به تعداد رزومه دریافتی</h5>
<div v-if="chart.proposal">
{{chart.proposal.ratio_employ_interview}}
</div>
</div> </div>
<div> <a-card class="mb-10">
</div> <h5>نسبت استخدام به مصاحبه</h5>
</div>--> <a-table v-if="chart.proposal" :data-source="chart.proposal.ratio_intrview_proposal" :columns="[
<br/> {title: 'تعداد',dataIndex: 'count'},
{title: 'شغل',dataIndex: 'title'},]"/>
<div class="grid grid-cols-2 gap-4"> </a-card>
<a-card>
<h5>تعداد پرسنل در هر شغل</h5>
<a-table v-if="chart.proposal" :data-source="chart.proposal.count_job" :columns="[
{title: 'تعداد',dataIndex: 'count'},
{title: 'شغل',dataIndex: 'job_title'},]"/>
</a-card>
</a-card>
<div class="grid grid-cols-1 gap-10">
<div> <div>
<a-card title="لیست پرسنل اتمام قرارداد در ماه گذشته"> <a-card title="لیست پرسنل اتمام قرارداد در ماه گذشته">
<x-table style="height: 400px;overflow: auto" class="mt-4" :model="contractEndPastMonth"></x-table> <x-table @fetch="setExitPast" class="mt-4" :model="contractEndPastMonth"></x-table>
</a-card> </a-card>
</div> </div>
<div> <div>
<a-card title="لیست پرسنل اتمام قرارداد در ماه جاری"> <a-card title="لیست پرسنل اتمام قرارداد در ماه جاری">
<x-table style="height: 400px;overflow: auto" class="mt-4" :model="contractEndCurrentMonth"></x-table> <x-table @fetch="setExitCurrent" :model="contractEndCurrentMonth"></x-table>
</a-card> </a-card>
</div> </div>
<div> <div>
<a-card title="لیست پرسنل اتمام قرارداد در ماه آینده"> <a-card title="لیست پرسنل اتمام قرارداد در ماه آینده">
<x-table style="height: 400px;overflow: auto" class="mt-4" :model="contractEndNextMonth"></x-table> <x-table @fetch="setExitNext" :model="contractEndNextMonth"></x-table>
</a-card> </a-card>
</div> </div>
<div> <div>
<a-card title="لیست پرسنل استخدام شده در ماه گذشته"> <a-card title="لیست پرسنل استخدام شده در ماه گذشته">
<x-table style="height: 400px;overflow: auto" class="mt-4" :model="PersonelPastMonth"></x-table> <x-table :model="PersonelPastMonth"></x-table>
</a-card> </a-card>
</div> </div>
<div> <div>
<a-card title="لیست پرسنل استخدام شده در ماه جاری"> <a-card title="لیست پرسنل استخدام شده در ماه جاری">
<x-table style="height: 400px;overflow: auto" class="mt-4" :model="PersonelCurrentMonth"></x-table> <x-table :model="PersonelCurrentMonth"></x-table>
</a-card> </a-card>
</div> </div>
<div> <div>
<a-card title="لیست پرسنل فسخ قرارداد در ماه گذشته"> <a-card title="لیست پرسنل فسخ قرارداد در ماه گذشته">
<x-table style="height: 400px;overflow: auto" class="mt-4" :model="contractTerminationPastMonth"></x-table> <x-table :model="contractTerminationPastMonth"></x-table>
</a-card> </a-card>
</div> </div>
<div> <div>
<a-card title="لیست پرسنل فسخ قرارداد در ماه جاری"> <a-card title="لیست پرسنل فسخ قرارداد در ماه جاری">
<x-table style="height: 400px;overflow: auto" class="mt-4" :model="contractTerminationCurrentMonth"></x-table> <x-table :model="contractTerminationCurrentMonth"></x-table>
</a-card>
</div>
<div>
<a-card title="سوابق کاری">
<x-table :model="workChart">
<template slot="history" slot-scope="{text, record}">
{{record.history?record.history+' سال':'-'}}
</template>
<template slot="end" slot-scope="{text, record}">
{{record.end_at?record.end_at:'-'}}
</template>
</x-table>
</a-card> </a-card>
</div> </div>
</div> </div>
</div> </a-spin>
</template> </template>
<script> <script>
//import * as TableCol from "@/table/personelPerMonth"; import contractEndPastMonth from './personelEndContractPastmonthTbl';
import * as TableColcontractEndPastMonth from './personelEndContractPastmonthTbl'; import contractEndNextMonth from './personelEndContractNextmonthTbl';
import * as TableColcontractEndNextMonth from './personelEndContractNextmonthTbl'; import contractEndCurrentMonth from './personelEndContractCurrentmonthTbl';
import * as TableColcontractCurrentMonth from './personelEndContractCurrentmonthTbl'; import PersonelPastMonth from './personelPastmonthTbl';
import * as TableColPersonelPastMonth from './personelPastmonthTbl'; import PersonelCurrentMonth from './personelCurrentmonthTbl';
import * as TableColPersonelCurrentMonth from './personelCurrentmonthTbl'; import contractTerminationCurrentMonth from './contractTerminationCurrentMonthTbl';
import * as TableColcontractTerminationCurrentMonth from './contractTerminationCurrentMonthTbl'; import contractTerminationPastMonth from './contractTerminationPastMonthTbl';
import * as TableColcontractTerminationPastMonth from './contractTerminationPastMonthTbl'; import workChart from './workChart';
import XTable from "@/components/x-table/XTable"; import XTable from "@/components/new-x-table/XTable";
//import {ax} from "@/axios";
import axios from "@/axios" import axios from "@/axios"
export default { export default {
data() { data() {
return { return {
@@ -105,47 +150,62 @@
PersonelCurrentMonth, PersonelCurrentMonth,
PersonelPastMonth, PersonelPastMonth,
contractTerminationPastMonth, contractTerminationPastMonth,
contractTerminationCurrentMonth contractTerminationCurrentMonth,
//col:null, exit: {
//model:{}, past: undefined,
//personelPerMonth:[], current: undefined,
next: undefined,
},
loading: true,
loadingCounter: 0,
chart: {
index:undefined,
proposal:undefined,
},
workChart,
} }
}, },
components: { components: {
XTable, XTable,
}, },
computed: { methods: {
setExitPast(val) {
this.exit.past = val.query.exit
this.loadingCounter++
},
setExitCurrent(val) {
this.exit.current = val.query.exit
this.loadingCounter++
},
setExitNext(val) {
this.exit.next = val.query.exit
this.loadingCounter++
},
},
watch: {
loadingCounter(val) {
if(val === 3) this.loading = false
},
}, },
async created() { async created() {
this.contractEndPastMonth = TableColcontractEndPastMonth.default; try {
this.contractEndNextMonth = TableColcontractEndNextMonth.default; this.loading = true
this.contractEndCurrentMonth = TableColcontractCurrentMonth.default; let {data} = await axios.get('chart')
this.PersonelCurrentMonth=TableColPersonelCurrentMonth.default; this.chart.index = data
this.PersonelPastMonth= TableColPersonelPastMonth.default; data = await axios.get('chart/proposal')
this.contractTerminationPastMonth=TableColcontractTerminationPastMonth.default; this.chart.proposal = data.data
this.contractTerminationCurrentMonth=TableColcontractTerminationCurrentMonth.default; this.loading = false
//console.log('111111111',axios.defaults.headers); } catch (e) {
// try { console.log(e,'eeeeeeeeeeeee')
// await axios.get('dashboard') }
// .then((res)=>{
// //console.log('dsfsdfsdfds');
// this.model=res.data;
// this.personelPerMonth=res.data.personnel;
// }).catch((error)=>{
// //console.log('dsafsdfsdfsdf');
// console.log(error);
// });
// }
// catch (error)
// {
// // console.log('gggggggg');
// }
}, },
} }
</script> </script>
<style lang="scss" > <style lang="scss" >
.bg-custom{
background: #f5f5f542;
}
.ant-pagination .ant-pagination
{ {
direction: ltr !important; direction: ltr !important;
@@ -1,8 +1,9 @@
import XTbl, {Xtc} from '../../components/x-table/index'; import XTbl, {Xtc} from '../../components/new-x-table/index';
const tbl = new XTbl('contractTerminationCurrentMonth', 'لیست پرسنل'); const tbl = new XTbl('contractTerminationCurrentMonth/table', 'لیست پرسنل');
tbl.add(new Xtc('personnel.personel_id', 'کد پرسنلی').noSort()); tbl.add(new Xtc('personnel.personel_id', 'کد پرسنلی').hidden().filterText());
tbl.add(new Xtc('personnel.name', 'نام و نام خانوادگی').noSort()) tbl.add(new Xtc('personnel.name', 'نام و نام خانوادگی').filterText())
tbl.add(new Xtc('start_atj', 'تاریخ شروع قرارداد').noSort()) tbl.add(new Xtc('start_atj', 'تاریخ شروع قرارداد').filterDate().filterKey('start_at'))
tbl.add(new Xtc('end_atj', 'تاریخ اتمام قرارداد').noSort()) tbl.add(new Xtc('end_atj', 'تاریخ اتمام قرارداد').filterDate().filterKey('end_at'))
tbl.add(new Xtc('reason_termination', 'علت فسخ قرارداد').filterText())
export default tbl; export default tbl;
@@ -1,8 +1,9 @@
import XTbl, {Xtc} from '../../components/x-table/index'; import XTbl, {Xtc} from '../../components/new-x-table/index';
const tbl = new XTbl('contractTerminationPastMonth', 'لیست پرسنل'); const tbl = new XTbl('contractTerminationPastMonth/table', 'لیست پرسنل');
tbl.add(new Xtc('personnel.personel_id', 'کد پرسنلی').noSort()); tbl.add(new Xtc('personnel.personel_id', 'کد پرسنلی').hidden().filterText());
tbl.add(new Xtc('personnel.name', 'نام و نام خانوادگی').noSort()) tbl.add(new Xtc('personnel.name', 'نام و نام خانوادگی').filterText())
tbl.add(new Xtc('start_atj', 'تاریخ شروع قرارداد').noSort()) tbl.add(new Xtc('start_atj', 'تاریخ شروع قرارداد').filterDate().filterKey('start_at'))
tbl.add(new Xtc('end_atj', 'تاریخ اتمام قرارداد').noSort()) tbl.add(new Xtc('end_atj', 'تاریخ اتمام قرارداد').filterDate().filterKey('end_at'))
tbl.add(new Xtc('reason_termination', 'علت فسخ قرارداد').filterText())
export default tbl; export default tbl;
@@ -1,7 +1,7 @@
import XTbl, {Xtc} from '../../components/x-table/index'; import XTbl, {Xtc} from '../../components/new-x-table/index';
const tbl = new XTbl('personelCurrentMonth', 'لیست پرسنل'); const tbl = new XTbl('personelCurrentMonth/table', 'لیست پرسنل');
tbl.add(new Xtc('personel_id', 'کد پرسنلی').noSort()); tbl.add(new Xtc('personel_id', 'کد پرسنلی').filterText());
tbl.add(new Xtc('name', 'نام و نام خانوادگی').noSort()) tbl.add(new Xtc('name', 'نام و نام خانوادگی').filterText())
tbl.add(new Xtc('caj', 'تاریخ استخدام').noSort()) tbl.add(new Xtc('caj', 'تاریخ استخدام').filterDate().filterKey('created_at'))
export default tbl; export default tbl;
@@ -1,8 +1,9 @@
import XTbl, {Xtc} from '../../components/x-table/index'; import XTbl, {Xtc} from '../../components/new-x-table/index';
const tbl = new XTbl('personelContactEndCurrentMonth', 'لیست پرسنل'); const tbl = new XTbl('personelContactEndCurrentMonth/table', 'لیست پرسنل');
tbl.add(new Xtc('personnel.personel_id', 'کد پرسنلی').noSort()); tbl.add(new Xtc('personnel.personel_id', 'کد پرسنلی').filterText());
tbl.add(new Xtc('personnel.name', 'نام و نام خانوادگی').noSort()) tbl.add(new Xtc('personnel.name', 'نام و نام خانوادگی').filterText())
tbl.add(new Xtc('start_atj', 'تاریخ شروع قرارداد').noSort()) tbl.add(new Xtc('start_atj', 'تاریخ شروع قرارداد').filterDate().filterKey('start_at'))
tbl.add(new Xtc('end_atj', 'تاریخ اتمام قرارداد').noSort()) tbl.add(new Xtc('end_atj', 'تاریخ اتمام قرارداد').filterDate().filterKey('end_at'))
tbl.add(new Xtc('date_work', 'مدت تصدی (روز)'))
export default tbl; export default tbl;
@@ -1,8 +1,9 @@
import XTbl, {Xtc} from '../../components/x-table/index'; import XTbl, {Xtc} from '../../components/new-x-table/index';
const tbl = new XTbl('personelContactEndNextMonth', 'لیست پرسنل'); const tbl = new XTbl('personelContactEndNextMonth/table', 'لیست پرسنل');
tbl.add(new Xtc('personnel.personel_id', 'کد پرسنلی').noSort()); tbl.add(new Xtc('personnel.personel_id', 'کد پرسنلی').noSort());
tbl.add(new Xtc('personnel.name', 'نام و نام خانوادگی').noSort()) tbl.add(new Xtc('personnel.name', 'نام و نام خانوادگی').noSort())
tbl.add(new Xtc('start_atj', 'تاریخ شروع قرارداد').noSort()) tbl.add(new Xtc('start_atj', 'تاریخ شروع قرارداد').noSort())
tbl.add(new Xtc('end_atj', 'تاریخ اتمام قرارداد').noSort()) tbl.add(new Xtc('end_atj', 'تاریخ اتمام قرارداد').noSort())
tbl.add(new Xtc('date_work', 'مدت تصدی (روز)'))
export default tbl; export default tbl;
@@ -1,8 +1,9 @@
import XTbl, {Xtc} from '../../components/x-table/index'; import XTbl, {Xtc} from '../../components/new-x-table/index';
const tbl = new XTbl('personelContactEndPastMonth', 'لیست پرسنل'); const tbl = new XTbl('personelContactEndPastMonth/table', 'لیست پرسنل اتمام قرارداد در ماه گذشته');
tbl.add(new Xtc('personnel.personel_id', 'کد پرسنلی').noSort()); tbl.add(new Xtc('personnel.personel_id', 'کد پرسنلی').filterText());
tbl.add(new Xtc('personnel.name', 'نام و نام خانوادگی').noSort()) tbl.add(new Xtc('personnel.name', 'نام و نام خانوادگی').filterText())
tbl.add(new Xtc('start_atj', 'تاریخ شروع قرارداد').noSort()) tbl.add(new Xtc('start_atj', 'تاریخ شروع قرارداد').filterDate().filterKey('start_at'))
tbl.add(new Xtc('end_atj', 'تاریخ اتمام قرارداد').noSort()) tbl.add(new Xtc('end_atj', 'تاریخ اتمام قرارداد').filterDate().filterKey('end_at'))
tbl.add(new Xtc('date_work', 'مدت تصدی (روز)'))
export default tbl; export default tbl;
+5 -5
View File
@@ -1,7 +1,7 @@
import XTbl, {Xtc} from '../../components/x-table/index'; import XTbl, {Xtc} from '../../components/new-x-table/index';
const tbl = new XTbl('personelPastMonth', 'لیست پرسنل'); const tbl = new XTbl('personelPastMonth/table', 'لیست پرسنل');
tbl.add(new Xtc('personel_id', 'کد پرسنلی').noSort()); tbl.add(new Xtc('personel_id', 'کد پرسنلی').filterText());
tbl.add(new Xtc('name', 'نام و نام خانوادگی').noSort()) tbl.add(new Xtc('name', 'نام و نام خانوادگی').filterText())
tbl.add(new Xtc('caj', 'تاریخ استخدام').noSort()) tbl.add(new Xtc('caj', 'تاریخ استخدام').filterDate().filterKey('created_at'))
export default tbl; export default tbl;
+11
View File
@@ -0,0 +1,11 @@
import XTbl, {Xtc} from '@/components/new-x-table/index';
const tbl = new XTbl('/work', 'لیست پرسنل');
tbl.add(new Xtc('proposal.name', 'نام و نام خانوادگی').filterText())
tbl.add(new Xtc('history', 'سابقه کار').renderSlot('history').filterText());
tbl.add(new Xtc('title', 'نام شغل').filterText())
tbl.add(new Xtc('university', 'مکان').filterText())
tbl.add(new Xtc('has_certificate_str', 'وضعیت مدرک').filterText())
tbl.add(new Xtc('start_at', 'تاریخ شروع سابقه').filterDate().filterKey('start_at'))
tbl.add(new Xtc('end_at', 'تاریخ اتمام سابقه').renderSlot('end').filterDate().filterKey('end_at'))
export default tbl;
@@ -182,7 +182,7 @@ export default {
firstName: '', firstName: '',
lastName: '', lastName: '',
email: '', email: '',
city: 'new-york', city: 'new-x-table-york',
proposalTitle: '', proposalTitle: '',
jobTitle: '', jobTitle: '',
textarea: '', textarea: '',
@@ -190,7 +190,7 @@ export default {
eventLocation: 'san-francisco', eventLocation: 'san-francisco',
status: 'plannning', status: 'plannning',
cityOptions: [ cityOptions: [
{text: 'New York', value:'new-york'}, {text: 'New York', value:'new-x-table-york'},
{text: 'Chicago', value:'chicago'}, {text: 'Chicago', value:'chicago'},
{text: 'San Francisco', value:'san-francisco'}, {text: 'San Francisco', value:'san-francisco'},
{text: 'Boston', value:'boston'} {text: 'Boston', value:'boston'}
@@ -201,7 +201,7 @@ export default {
{text: 'Finished', value:'finished'} {text: 'Finished', value:'finished'}
], ],
LocationOptions: [ LocationOptions: [
{text: 'New York', value:'new-york'}, {text: 'New York', value:'new-x-table-york'},
{text: 'Chicago', value:'chicago'}, {text: 'Chicago', value:'chicago'},
{text: 'San Francisco', value:'san-francisco'}, {text: 'San Francisco', value:'san-francisco'},
{text: 'Boston', value:'boston'} {text: 'Boston', value:'boston'}
@@ -207,7 +207,7 @@ export default {
firstName: '', firstName: '',
lastName: '', lastName: '',
email: '', email: '',
city: 'new-york', city: 'new-x-table-york',
proposalTitle: '', proposalTitle: '',
jobTitle: '', jobTitle: '',
textarea: '', textarea: '',
@@ -215,7 +215,7 @@ export default {
eventLocation: 'san-francisco', eventLocation: 'san-francisco',
status: 'plannning', status: 'plannning',
cityOptions: [ cityOptions: [
{text: 'New York', value:'new-york'}, {text: 'New York', value:'new-x-table-york'},
{text: 'Chicago', value:'chicago'}, {text: 'Chicago', value:'chicago'},
{text: 'San Francisco', value:'san-francisco'}, {text: 'San Francisco', value:'san-francisco'},
{text: 'Boston', value:'boston'} {text: 'Boston', value:'boston'}
@@ -226,7 +226,7 @@ export default {
{text: 'Finished', value:'finished'} {text: 'Finished', value:'finished'}
], ],
LocationOptions: [ LocationOptions: [
{text: 'New York', value:'new-york'}, {text: 'New York', value:'new-x-table-york'},
{text: 'Chicago', value:'chicago'}, {text: 'Chicago', value:'chicago'},
{text: 'San Francisco', value:'san-francisco'}, {text: 'San Francisco', value:'san-francisco'},
{text: 'Boston', value:'boston'} {text: 'Boston', value:'boston'}
@@ -332,7 +332,7 @@ export default {
firstName: '', firstName: '',
lastName: '', lastName: '',
email: '', email: '',
city: 'new-york', city: 'new-x-table-york',
proposalTitle: '', proposalTitle: '',
jobTitle: '', jobTitle: '',
textarea: '', textarea: '',
@@ -340,7 +340,7 @@ export default {
eventLocation: 'san-francisco', eventLocation: 'san-francisco',
status: 'plannning', status: 'plannning',
cityOptions: [ cityOptions: [
{ text: 'New York', value: 'new-york' }, { text: 'New York', value: 'new-x-table-york' },
{ text: 'Chicago', value: 'chicago' }, { text: 'Chicago', value: 'chicago' },
{ text: 'San Francisco', value: 'san-francisco' }, { text: 'San Francisco', value: 'san-francisco' },
{ text: 'Boston', value: 'boston' } { text: 'Boston', value: 'boston' }
@@ -351,7 +351,7 @@ export default {
{ text: 'Finished', value: 'finished' } { text: 'Finished', value: 'finished' }
], ],
LocationOptions: [ LocationOptions: [
{ text: 'New York', value: 'new-york' }, { text: 'New York', value: 'new-x-table-york' },
{ text: 'Chicago', value: 'chicago' }, { text: 'Chicago', value: 'chicago' },
{ text: 'San Francisco', value: 'san-francisco' }, { text: 'San Francisco', value: 'san-francisco' },
{ text: 'Boston', value: 'boston' } { text: 'Boston', value: 'boston' }
+74 -51
View File
@@ -6,21 +6,27 @@
<a-form-item label="سطح کاربر"> <a-form-item label="سطح کاربر">
<a-select <a-select
v-decorator="['user_type', { initialValue:null,rules: [{ required: true, message: 'لطفاسطح دسترسی را انتخاب کنید' }] }]" @change="selectChange"> v-decorator="['user_type', { initialValue:null,rules: [{ required: true, message: 'لطفاسطح دسترسی را انتخاب کنید' }] }]" @change="selectChange">
<a-select-option v-for="(item,key) in userTypes" :value="key"> <a-select-option v-for="item in userTypes" :value="item.id">
{{ item }} {{ item.value }}
</a-select-option> </a-select-option>
</a-select> </a-select>
</a-form-item> </a-form-item>
<a-form-item label="نام" has-feedback v-if="showName">
<input class="ant-input"
v-decorator="['name', { rules: [{ required: true, message: 'لطفا مقدار را وارد کنید' }] }]"
autocomplete="off"
/>
</a-form-item>
<a-form-item label="نقش ها"> <a-form-item label="نقش ها">
<a-tree <a-tree style="direction: rtl"
v-model="rid" v-model="rid"
checkable checkable
default-expand-all default-expand-all
style="width: 100%"
:tree-data="treeData" :tree-data="treeData"
:replace-fields="replaceFields"
:auto-expand-parent="autoExpandParent"
/> />
<!-- :replace-fields="replaceFields"-->
<!-- :auto-expand-parent="autoExpandParent"-->
</a-form-item> </a-form-item>
</div> </div>
<a-button type="primary" html-type="submit"> <a-button type="primary" html-type="submit">
@@ -40,30 +46,49 @@
data() { data() {
return { return {
form: this.$form.createForm(this, {name: 'coordinated'}), form: this.$form.createForm(this, {name: 'coordinated'}),
expandedKeys:[],
value: ['0-0-0'],
treeData:undefined, treeData:undefined,
userTypes: undefined, userTypes: undefined,
autoExpandParent: false, // autoExpandParent: false,
rid: [], rid: [],
replaceFields: { /*replaceFields: {
children: 'child', children: 'child',
title: 'title' title: 'title'
}, },*/
keyId: null, // keyId: null,
getDataUserType:null getDataUserType:null,
showName:false,
loading:false
} }
}, },
methods: { methods: {
async getUserTypes(){
try{
this.loading = true
const {data} = await axios.get('/permission/type')
if(this.$getAccess("permission.create")){
data.push
({
id: "new",
value: "افزودن کاربر جدید"
})
}
this.userTypes = Object.values(data)
}catch (e) {
console.log("errr:",e)
}finally {
this.loading = false
}
},
async getPermission() { async getPermission() {
try{ try{
const {data} = await axios.get('admin/permission/rid') this.loading = true
const {data} = await axios.get('/permission')
this.treeData = Object.values(data) this.treeData = Object.values(data)
}catch (e) { }catch (e) {
console.log("errr:",e)
}finally { }finally {
this.loading = false
} }
}, },
handleSubmit(e) { handleSubmit(e) {
@@ -71,65 +96,63 @@
this.form.validateFields(async (err, values) => { this.form.validateFields(async (err, values) => {
if (!err) { if (!err) {
try { try {
this.loading = true
values.rid = this.rid values.rid = this.rid
await this.$store.dispatch('access/save', values); if(values.user_type == "new"){
values.user_type = values.name
}
await axios.post('/permission',values)
if (values.user_type == JSON.parse(localStorage.getItem('userInfo')).user_type)
await this.$store.dispatch("access/setPermissions", values.rid)
this.$ntSet() this.$ntSet()
setTimeout(()=>{ setTimeout(()=>{
window.location.reload() window.location.reload()
},500) },500)
} catch (e) { } catch (e) {
this.$ntSetError() this.$ntSetError(e)
} finally { } finally {
this.loading =false
} }
} }
}); });
}, },
async getUserType() { async selectChange(id){
const {data} = await axios.get('admin/user/type') try{
this.userTypes = data this.loading = true
console.log(this.userTypes,'user_type') if (id !== "new") {
}, this.showName = false
loadSyncOptionChange(){ let {data: {rid}} = await axios.get(`/permission/show/${id}`)
let storageId = localStorage.getItem("contestId"); this.rid = Object.values(rid)
storageId = this.keyId; }
localStorage.setItem("contestId", storageId); else{
let test = localStorage.getItem("contestId"); this.showName = true
test = JSON.parse(localStorage.getItem("contestId")); }
localStorage.setItem("contestId", test); }catch (e) {
if(test != null){ console.log("errr:",e)
this.$store.dispatch('access/getOneId',test).then(()=>{ }finally {
this.rid = this.data.rid this.loading = false
this.form.setFieldsValue(this.data)
})
}else{
return false
} }
},
selectChange(id){
this.keyId = id
this.loadSyncOptionChange()
} }
}, },
computed: { computed: {
loading() {
return this.$store.state.access.loading;
},
data(){ data(){
console.log(this.$store.state.access.access_id,'hgghgh') console.log(this.$store.state.access.access_id,'hgghgh')
return this.$store.state.access.access_id return this.$store.state.access.access_id
} }
}, },
mounted() { async mounted() {
this.getUserType() this.form.setFieldsValue({user_type:1})
this.getPermission() await this.selectChange(1)
this.keyId = 1 },
this.loadSyncOptionChange() async created(){
await this.getPermission()
await this.getUserTypes()
} }
} }
</script> </script>
<style> <!--<style>
[dir=rtl] .ant-tree-checkbox-inner::after{ [dir=rtl] .ant-tree-checkbox-inner::after{
right: 55%; right: 55%;
top: 35%; top: 35%;
@@ -147,4 +170,4 @@
-webkit-transform: rotate(-45deg) scale(1) translate(50%, -50%); -webkit-transform: rotate(-45deg) scale(1) translate(50%, -50%);
transform: rotate(25deg) scale(1) translate(50%, -50%); transform: rotate(25deg) scale(1) translate(50%, -50%);
} }
</style> </style>-->
+435 -115
View File
@@ -4,7 +4,7 @@
<a-spin :spinning="showLoading" tip="در حال دریافت اطلاعات"> <a-spin :spinning="showLoading" tip="در حال دریافت اطلاعات">
<div class="spin-content"> <div class="spin-content">
<a-card> <a-card>
<a-button @click="$router.push('/register/personnel')" > <a-button @click="$router.push('/register/personnel')" :disabled="!$getAccess('personnel.create')">
ثبت پرسنل جدید ثبت پرسنل جدید
</a-button> </a-button>
<x-table ref="personelTbl" class="mt-4" <x-table ref="personelTbl" class="mt-4"
@@ -15,16 +15,27 @@
</a-button> </a-button>
</template> </template>
</x-table> </x-table>
<a-modal @ok="savefromPersonel" :maskClosable="false" :forceRender="true" okText="ویرایش" cancelText="بستن" width="90%" v-model="showPersonalModal" title="ویرایش اطلاعات پرسنلی"> <a-modal :maskClosable="false" :forceRender="true" width="90%" v-model="showPersonalModal" title="ویرایش اطلاعات پرسنلی">
<template slot="footer">
<a-button @click="showPersonalModal=false">بستن</a-button>
</template>
<a-form :form="fromPersonel"> <a-form :form="fromPersonel">
<a-tabs type="card"> <a-tabs type="card" :default-active-key="
<a-tab-pane :forceRender="true" key="1" tab="اطلاعات پایه"> $getAccess('personnel.basic')?1:
$getAccess('personnel.train')?3:
$getAccess('personnel.contract')?4:
$getAccess('personnel.intro')?5:
$getAccess('personnel.delivery')?6:
$getAccess('personnel.function')?7:
$getAccess('personnel.rule')?8:undefined
">
<a-tab-pane :disabled="!$getAccess('personnel.basic')" :forceRender="true" key="1" tab="اطلاعات پایه">
<a-card title="اطلاعات فردی"> <a-card title="اطلاعات فردی">
<div class="grid grid-cols-2 gap-4"> <div class="grid grid-cols-2 gap-4">
<div> <div>
<a-form-item label="تصویر پرسنلی" > <a-form-item label="تصویر پرسنلی" >
<single-upload-input ref="fileUpload" :field="'profile_file'" ></single-upload-input> <single-upload-input ref="fileUpload" :field="'profile_file'" :disabled="!$getAccess('personnel.basic.update')"></single-upload-input>
<a-modal :visible="previewVisible" :footer="null" @cancel="previewVisible = false;"> <a-modal :visible="previewVisible" :footer="null" @cancel="previewVisible = false;">
<img alt="example" style="width: 100%" :src="previewImage" /> <img alt="example" style="width: 100%" :src="previewImage" />
</a-modal> </a-modal>
@@ -37,7 +48,8 @@
<!----> <!---->
<div class="dropbox"> <div class="dropbox">
<a-upload-dragger <a-upload-dragger
action="http://hr.asco-intl.com/back/public/api/register/upload" :disabled="!$getAccess('personnel.basic.update')"
action="http://hr.asco-intl.com:2020/back/public/api/register/upload"
:file-list="documentFileList" :file-list="documentFileList"
:default-file-list="documentFileList" :default-file-list="documentFileList"
@change="changeDocumentUpload" @change="changeDocumentUpload"
@@ -194,7 +206,7 @@
<div> <div>
<a-form-item label="شماره بیمه"> <a-form-item label="شماره بیمه">
<input class="ant-input" style="" <input class="ant-input"
v-decorator="['insurance_no']"/> v-decorator="['insurance_no']"/>
</a-form-item> </a-form-item>
</div> </div>
@@ -212,12 +224,27 @@
</a-form-item> </a-form-item>
</div> </div>
<div>
<a-form-item label="تعداد فرزند">
<input class="ant-input" v-decorator="['proposal.count_child',{rules: [{ required: true, message: 'لطفا مقدار را وارد کنید' },{ pattern: /^[0-9]+$/, message: 'فقط عدد مجاز است' }] }]"/>
</a-form-item>
</div>
<div>
<a-form-item label="وضعیت نظام وظیفه">
<a-select style="width: 100%" v-decorator="['proposal.military_sts',{rules: [{ required: true, message: 'لطفا مقدار را وارد کنید' }] }]">
<a-select-option v-for="(item,index) in {1:'معاف',2:'مشمول',3:'پایان خدمت',}" :value="index">
{{ item }}
</a-select-option>
</a-select>
</a-form-item>
</div>
</div> </div>
</a-card> </a-card>
<a-card title="اطلاعات خانوادگی" class="mt-5"> <a-card title="اطلاعات خانوادگی" class="mt-5">
<a slot="extra" @click.prevent="AddFamily()">افزودن اطلاعات خانوادگی</a> <a slot="extra" @click.prevent="AddFamily()" :disabled="!$getAccess('personnel.basic.family.create')">افزودن اطلاعات خانوادگی</a>
<template v-for="(item,index) in personalDetails['family']" > <template v-for="(item,index) in personalDetails['family']" >
<a-button type="danger" @click="handleRemoveFamily(item,index)">حذف</a-button> <a-button :disabled="!$getAccess('personnel.basic.family.delete')" type="danger" @click="handleRemoveFamily(item,index)">حذف</a-button>
<div class="grid sm:grid-cols-1 md:grid-cols-3 md:gap-3 lg:grid-cols-3 lg:gap-3"> <div class="grid sm:grid-cols-1 md:grid-cols-3 md:gap-3 lg:grid-cols-3 lg:gap-3">
<a-form-item style="display: none"> <a-form-item style="display: none">
<input type="hidden" class="ant-input" autocomplete="off" v-decorator="[`personal_details.family[${index}].id`]"/> <input type="hidden" class="ant-input" autocomplete="off" v-decorator="[`personal_details.family[${index}].id`]"/>
@@ -260,9 +287,9 @@
</a-card> </a-card>
<a-card title="اطلاعات تحصیلی" class="mt-5"> <a-card title="اطلاعات تحصیلی" class="mt-5">
<a slot="extra" @click.prevent="AddEducation()">افزودن سابقه تحصیلی</a> <a :disabled="!$getAccess('personnel.basic.education.create')" slot="extra" @click.prevent="AddEducation()">افزودن سابقه تحصیلی</a>
<template v-for="(item,index) in personalDetails['education']"> <template v-for="(item,index) in personalDetails['education']">
<a-button type="danger" @click="handleRemoveEducation(item,index)">حذف</a-button> <a-button :disabled="!$getAccess('personnel.basic.education.delete')" type="danger" @click="handleRemoveEducation(item,index)">حذف</a-button>
<div class="grid sm:grid-cols-1 md:grid-cols-3 md:gap-3 lg:grid-cols-3 lg:gap-3"> <div class="grid sm:grid-cols-1 md:grid-cols-3 md:gap-3 lg:grid-cols-3 lg:gap-3">
<a-form-item style="display: none"> <a-form-item style="display: none">
<input type="hidden" class="ant-input" autocomplete="off" v-decorator="[`personal_details.education[${index}].id`]"/> <input type="hidden" class="ant-input" autocomplete="off" v-decorator="[`personal_details.education[${index}].id`]"/>
@@ -305,9 +332,9 @@
</a-card> </a-card>
<a-card title="سوابق آموزشی" class="mt-5"> <a-card title="سوابق آموزشی" class="mt-5">
<a slot="extra" @click.prevent="AddTraning()">افزودن سابقه آموزشی </a> <a :disabled="!$getAccess('personnel.basic.train.create')" slot="extra" @click.prevent="AddTraning()">افزودن سابقه آموزشی </a>
<template v-for="(item,index) in personalDetails['traning']"> <template v-for="(item,index) in personalDetails['traning']">
<a-button type="danger" @click="handleRemoveTraning(item,index)">حذف</a-button> <a-button :disabled="!$getAccess('personnel.basic.train.delete')" type="danger" @click="handleRemoveTraning(item,index)">حذف</a-button>
<div class="grid sm:grid-cols-1 md:grid-cols-3 md:gap-3 lg:grid-cols-3 lg:gap-3"> <div class="grid sm:grid-cols-1 md:grid-cols-3 md:gap-3 lg:grid-cols-3 lg:gap-3">
<a-form-item style="display: none"> <a-form-item style="display: none">
<input type="hidden" class="ant-input" autocomplete="off" v-decorator="[`personal_details.traning[${index}].id`]"/> <input type="hidden" class="ant-input" autocomplete="off" v-decorator="[`personal_details.traning[${index}].id`]"/>
@@ -330,9 +357,9 @@
</a-card> </a-card>
<a-card title="سوابق کاری" class="mt-5"> <a-card title="سوابق کاری" class="mt-5">
<a slot="extra" @click.prevent="AddJobsHistory()">افزودن سابقه کاری</a> <a :disabled="!$getAccess('personnel.basic.job.create')" slot="extra" @click.prevent="AddJobsHistory()">افزودن سابقه کاری</a>
<template v-for="(item,index) in personalDetails['jobs_history']"> <template v-for="(item,index) in personalDetails['jobs_history']">
<a-button type="danger" @click="handleRemoveJobsHistory(item,index)">حذف</a-button> <a-button :disabled="!$getAccess('personnel.basic.job.delete')" type="danger" @click="handleRemoveJobsHistory(item,index)">حذف</a-button>
<div class="grid sm:grid-cols-1 md:grid-cols-3 md:gap-3 lg:grid-cols-3 lg:gap-3"> <div class="grid sm:grid-cols-1 md:grid-cols-3 md:gap-3 lg:grid-cols-3 lg:gap-3">
<a-form-item style="display: none"> <a-form-item style="display: none">
<input type="hidden" class="ant-input" autocomplete="off" v-decorator="[`personal_details.jobs_history[${index}].id`]"/> <input type="hidden" class="ant-input" autocomplete="off" v-decorator="[`personal_details.jobs_history[${index}].id`]"/>
@@ -360,8 +387,35 @@
<a-divider /> <a-divider />
</template> </template>
</a-card> </a-card>
<a-card title="سوابق شخصی" class="mt-5">
<div class="dropbox">
<a-upload-dragger
:disabled="!$getAccess('personnel.basic.update')"
:multiple="false"
action="http://hr.asco-intl.com:2020/back/public/api/register/upload"
:file-list="prsonalFileList"
:default-file-list="prsonalFileList"
@change="fileUpload"
:remove="fileRemove"
>
<p class="ant-upload-drag-icon">
<a-icon type="inbox" />
</p>
<p class="ant-upload-text">
فایل را درگ کنید یا اینکه کاوش کنید.
</p>
<p class="ant-upload-hint">
فایلی که بارگذاری می کنید باید زیر ۵ مگابایت باشد.
</p>
</a-upload-dragger>
</div>
</a-card>
<a-button type="primary" @click="savefromPersonel" class="mt-5" :disabled="checkPermission('1')">ویرایش</a-button>
</a-tab-pane> </a-tab-pane>
<a-tab-pane :forceRender="true" key="3" tab="اطلاعات آموزشی"> <a-tab-pane :disabled="!$getAccess('personnel.train')" :forceRender="true" key="3" tab="اطلاعات آموزشی">
<a-list :locale="{emptyText:'رکوردی وجود ندارد.'}" bordered item-layout="horizontal" > <a-list :locale="{emptyText:'رکوردی وجود ندارد.'}" bordered item-layout="horizontal" >
<a-list-item class="grid grid-cols-3" v-for="(item,index) in training" :key="index" > <a-list-item class="grid grid-cols-3" v-for="(item,index) in training" :key="index" >
<div> <div>
@@ -371,6 +425,7 @@
<span>حذف</span> <span>حذف</span>
</template> </template>
<a-popconfirm <a-popconfirm
:disabled="!$getAccess('personnel.train.delete')"
placement="right" placement="right"
style="z-index: 999999999999" style="z-index: 999999999999"
title="آیا می خواهید حذف کنید؟" title="آیا می خواهید حذف کنید؟"
@@ -386,35 +441,70 @@
<div style="direction: rtl">عنوان گواهینامه : {{ item.title }}</div> <div style="direction: rtl">عنوان گواهینامه : {{ item.title }}</div>
</a-list-item> </a-list-item>
</a-list> </a-list>
<a-button class="mt-4" @click="showAddEducationalInformation=true;isAlertUpload = false">افزودن ردیف</a-button> <a-button :disabled="!$getAccess('personnel.train.create')" class="mt-4" @click="showAddEducationalInformation=true;isAlertUpload = false">افزودن ردیف</a-button>
<a-button type="primary" @click="savefromPersonel" class="mt-5" :disabled="checkPermission('3')">ویرایش</a-button>
</a-tab-pane> </a-tab-pane>
<a-tab-pane :forceRender="true" key="4" tab="قراردادها"> <a-tab-pane :disabled="!$getAccess('personnel.contract')" :forceRender="true" key="4" tab="قراردادها">
<a-list :locale="{emptyText:'رکوردی وجود ندارد.'}" bordered item-layout="horizontal" > <a-list :locale="{emptyText:'رکوردی وجود ندارد.'}" bordered item-layout="horizontal" >
<a-list-item class="grid grid-cols-4" v-for="(item,index) in contract" :key="index" > <a-list-item class="grid grid-cols-4" style="direction: rtl" v-for="(item,index) in contract" :key="index">
<div> <div class="col-span-3 grid grid-cols-3">
<a-button v-if="!item.date_termination" class="mt-3 mr-3" @click="showTerminationModal(index)">فسخ قرارداد</a-button> <div class="mt-5">حقوق پایه :
<a-button v-if="item.file" target="_blank" :href="item.file.storage" >دانلود پیوست</a-button> {{ item.salary }}</div>
<div class="mt-5">تاریخ خاتمه :
{{ item.end_atj }}</div>
<div class="mt-5">تاریخ شروع :
{{ item.start_atj }}</div>
<div class="mt-5">بن کارگری :
{{ item.worker_coupon }}</div>
<div class="mt-5">کمک هزینه مسکن :
{{ item.housing_allowance }}</div>
<div class="mt-5">حق جذب : {{ item.right_attraction }}</div>
<div class="mt-5"> شماره سفته :
{{ item.promissory_number }}</div>
<div class="mt-5"> مبلغ سفته :
{{ item.promissory }}</div>
<div class="mt-5"> حق سرپرستی :
{{ item.right_guardianship }}</div>
<div class="mt-5"><span>شماره قرارداد :</span>&nbsp;<span>{{ item.contract_number }}</span></div>
<div class="mt-5">دلیل فسخ قرارداد :
{{ item.reason_termination }}</div>
<div class="mt-5">تاریخ فسخ قرارداد :
{{ item.datej_termination }}</div>
<div class="mt-5">نوع قرارداد :
{{ item.type_str }}</div>
<div class="mt-5">محل خدمت :
{{ item.cnt.value }}</div>
</div> </div>
<div>{{ item.salary }} : حقوق پایه</div> <div class="grid grid-cols-1" style="direction: ltr">
<div>{{ item.end_atj }} : تاریخ خاتمه</div> <div class="mt-5">
<div>{{ item.start_atj }} : تاریخ شروع</div> <a-button :disabled="!$getAccess('personnel.contract.termination')" v-if="!item.date_termination" class="ml-3" @click="showTerminationModal(index)">فسخ قرارداد</a-button>
<div> <a-button :disabled="!$getAccess('personnel.contract.no.termination')" v-else class="ml-3" @click="removetermination(index)">لغو فسخ قرارداد</a-button>
<a-tooltip placement="bottomRight" > <a-button :disabled="!$getAccess('personnel.contract')" v-if="item.file" class="ml-3" target="_blank" :href="item.file.storage" >دانلود پیوست</a-button>
<template slot="title"> </div>
<span>حذف</span> <div class="mt-5">
</template> <a-tooltip :disabled="!$getAccess('personnel.contract.delete')" placement="bottomRight" class="ml-3">
<a-popconfirm <template slot="title">
placement="right" <span>حذف</span>
style="z-index: 999999999999" </template>
title="آیا می خواهید حذف کنید؟" <a-popconfirm
ok-text="بله" placement="right"
cancel-text="خیر" style="z-index: 999999999999"
@confirm="removeContract(item)" > title="آیا می خواهید حذف کنید؟"
<a-button type="danger" class="mt-3 mr-3">حذف</a-button> ok-text="بله"
</a-popconfirm> cancel-text="خیر"
</a-tooltip> @confirm="removeContract(item)" >
<a-button style="width:20%" class="mr-3" @click="contractId=item.id;showContractPrint=true">چاپ</a-button> <a-button type="danger" class="mt-3 mr-3">حذف</a-button>
<!-- <a-dropdown class="mt-3" v-if="item.id"> </a-popconfirm>
</a-tooltip>
<a-button :disabled="!$getAccess('personnel.contract.print')" class="ml-3" :href="`http://hr.asco-intl.com:2020/back/public/api/personnel/print?id=${item.id}&type=${item.type?item.type:1}`" target="_blank">چاپ قرداد</a-button>
<!-- <a-button :disabled="!$getAccess('personnel.contract.print')" style="width:20%" class="mr-3" @click="contractId=item.id;showContractPrint=true">چاپ</a-button>-->
<a-button class="ml-3" :disabled="!$getAccess('personnel.contract.update')" @click="openEditingContractModal(item,index)" >ویرایش</a-button>
</div>
</div>
<!-- <div>
&lt;!&ndash; <a-dropdown class="mt-3" v-if="item.id">
<a-menu slot="overlay" > <a-menu slot="overlay" >
<a-menu-item key="1"> <a-menu-item key="1">
<a @click="showContractId=true">نوع 1</a> <a @click="showContractId=true">نوع 1</a>
@@ -451,31 +541,25 @@
</a-menu-item>&ndash;&gt; </a-menu-item>&ndash;&gt;
</a-menu> </a-menu>
<a-button style="width: 33%" > چاپ <a-icon type="down" /> </a-button> <a-button style="width: 33%" > چاپ <a-icon type="down" /> </a-button>
</a-dropdown>--> </a-dropdown>&ndash;&gt;
</div> </div>
<div>{{ item.worker_coupon }} : بن کارگری</div>
<div>{{ item.housing_allowance }} : کمک هزینه مسکن</div>
<div>{{ item.right_attraction }} : حق جذب</div>
<div> <div>
<!--<a-button v-if="item.id" :href="`http://hr.asco-intl.com/back/public/api/personnel/print?id=${item.id}`" target="_blank" class="mt-3">چاپ</a-button>--> &lt;!&ndash;<a-button v-if="item.id" :href="`http://hr.asco-intl.com/back/public/api/personnel/print?id=${item.id}`" target="_blank" class="mt-3">چاپ</a-button>&ndash;&gt;
</div> </div>
<div>{{ item.promissory_number }} : شماره سفته</div>
<div>{{ item.promissory }} : مبلغ سفته</div>
<div>{{ item.right_guardianship }} : حق سرپرستی</div>
<div class="mt-5"></div> <div class="mt-5"></div>
<!-- <div> شماره قرارداد : <span>{{ item. }}</span> </div>--> &lt;!&ndash; <div> شماره قرارداد : <span>{{ item. }}</span> </div>&ndash;&gt;
<!-- <div > : <span>{{ item.reason_termination }}</span> </div>--> &lt;!&ndash; <div > : <span>{{ item.reason_termination }}</span> </div>&ndash;&gt;
<!----> &lt;!&ndash;&ndash;&gt;-->
<div class="mt-5" style="direction: rtl"><span>شماره قرارداد :</span>&nbsp;<span>{{ item.contract_number }}</span></div>
<div class="mt-5">{{ item.reason_termination }} : دلیل فسخ قرارداد</div>
<div class="mt-5">{{ item.datej_termination }} : تاریخ فسخ قرارداد</div>
<!--<div style="direction: rtl">عنوان گواهینامه : {{ item.title }}</div>-->
</a-list-item> </a-list-item>
</a-list> </a-list>
<a-button class="mt-3" @click="showAddContract = true">افزودن ردیف</a-button> <a-button class="mt-3" @click="showAddContract = true">افزودن ردیف</a-button>
<a-button type="primary" @click="savefromPersonel" class="mt-5" :disabled="checkPermission('4')">ویرایش</a-button>
</a-tab-pane> </a-tab-pane>
<a-tab-pane :forceRender="true" key="5" tab="آشناسازی"> <a-tab-pane :disabled="!$getAccess('personnel.intro')" :forceRender="true" key="5" tab="آشناسازی">
<div class="grid sm:grid-cols-1 md:grid-cols-2 md:gap-4 lg:grid-cols-3 lg:gap-4" style="direction: rtl"> <div class="grid sm:grid-cols-1 md:grid-cols-2 md:gap-4 lg:grid-cols-3 lg:gap-4" style="direction: rtl">
<div> <div>
<a-form-item> <a-form-item>
@@ -496,8 +580,9 @@
</div> </div>
</div> </div>
<a-button type="primary" @click="savefromPersonel" class="mt-5" :disabled="checkPermission('5')">ویرایش</a-button>
</a-tab-pane> </a-tab-pane>
<a-tab-pane :forceRender="true" key="6" tab="تحویل تجهیزات"> <a-tab-pane :disabled="!$getAccess('personnel.delivery')" :forceRender="true" key="6" tab="تحویل تجهیزات">
<div class="grid sm:grid-cols-1 md:grid-cols-2 md:gap-4 lg:grid-cols-10 lg:gap-4" style="direction: rtl"> <div class="grid sm:grid-cols-1 md:grid-cols-2 md:gap-4 lg:grid-cols-10 lg:gap-4" style="direction: rtl">
<div> <div>
<!--<a-form-item> <!--<a-form-item>
@@ -555,8 +640,9 @@
</div> </div>
</div> </div>
<a-button type="primary" @click="savefromPersonel" class="mt-5" :disabled="checkPermission('6')">ویرایش</a-button>
</a-tab-pane> </a-tab-pane>
<a-tab-pane :forceRender="true" key="7" tab="ارزیابی عملکرد"> <a-tab-pane :disabled="!$getAccess('personnel.function')" :forceRender="true" key="7" tab="ارزیابی عملکرد">
<a-list :locale="{emptyText:'رکوردی وجود ندارد.'}" bordered item-layout="horizontal" > <a-list :locale="{emptyText:'رکوردی وجود ندارد.'}" bordered item-layout="horizontal" >
<a-list-item class="grid grid-cols-3" v-for="(item,index) in estimate" :key="index" > <a-list-item class="grid grid-cols-3" v-for="(item,index) in estimate" :key="index" >
<div> <div>
@@ -564,7 +650,7 @@
<template slot="title"> <template slot="title">
<span>حذف</span> <span>حذف</span>
</template> </template>
<a-popconfirm <a-popconfirm :disabled="!$getAccess('personnel.function.delete')"
placement="right" placement="right"
style="z-index: 999999999999" style="z-index: 999999999999"
title="آیا می خواهید حذف کنید؟" title="آیا می خواهید حذف کنید؟"
@@ -581,9 +667,10 @@
</a-list-item> </a-list-item>
</a-list> </a-list>
<br/> <br/>
<a-button @click="showAddPerformance=true">افزودن ردیف</a-button> <a-button :disabled="!$getAccess('personnel.function.create')" @click="showAddPerformance=true">افزودن ردیف</a-button>
<a-button type="primary" @click="savefromPersonel" class="mt-5" :disabled="checkPermission('7')">ویرایش</a-button>
</a-tab-pane> </a-tab-pane>
<a-tab-pane :forceRender="true" key="8" tab="احکام / اخطار / پاداش"> <a-tab-pane :disabled="!$getAccess('personnel.rule')" :forceRender="true" key="8" tab="احکام / اخطار / پاداش">
<a-list :locale="{emptyText:'رکوردی وجود ندارد.'}" bordered item-layout="horizontal" > <a-list :locale="{emptyText:'رکوردی وجود ندارد.'}" bordered item-layout="horizontal" >
<a-list-item class="grid grid-cols-3" v-for="(item,index) in writ" :key="index" > <a-list-item class="grid grid-cols-3" v-for="(item,index) in writ" :key="index" >
<div> <div>
@@ -592,7 +679,7 @@
<template slot="title"> <template slot="title">
<span>حذف</span> <span>حذف</span>
</template> </template>
<a-popconfirm <a-popconfirm :disabled="!$getAccess('personnel.rule.delete')"
placement="right" placement="right"
style="z-index: 999999999999" style="z-index: 999999999999"
title="آیا می خواهید حذف کنید؟" title="آیا می خواهید حذف کنید؟"
@@ -610,7 +697,8 @@
<div style="direction: rtl">عنوان : {{ item.note }}</div> <div style="direction: rtl">عنوان : {{ item.note }}</div>
</a-list-item> </a-list-item>
</a-list> </a-list>
<a-button class="mt-4" @click="showAddDocument=true;isAlertUpload = false">افزودن ردیف</a-button> <a-button :disabled="!$getAccess('personnel.rule.create')" class="mt-4" @click="showAddDocument=true;isAlertUpload = false">افزودن ردیف</a-button>
<a-button type="primary" @click="savefromPersonel" class="mt-5" :disabled="checkPermission('8')">ویرایش</a-button>
</a-tab-pane> </a-tab-pane>
</a-tabs> </a-tabs>
</a-form> </a-form>
@@ -665,7 +753,7 @@
</a-form> </a-form>
</a-modal> </a-modal>
<a-modal @ok="addContract" okText="ایجاد" forceRender cancelText="بستن" v-model="showAddContract" title="افزودن قرارداد" > <a-modal @ok="detectEditMode" :okText="editContractFlag?'ویرایش':'ایجاد'" forceRender cancelText="بستن" v-model="showAddContract" :title="editContractFlag?'ویرایش قرارداد':'افزودن قرارداد'" :forceRender="true">
<a-form :form="fromContract" > <a-form :form="fromContract" >
<div class="grid grid-cols-2 gap-4"> <div class="grid grid-cols-2 gap-4">
<div> <div>
@@ -737,33 +825,71 @@
<div> <div>
<a-form-item label="حق فرزند"> <a-form-item label="حق فرزند">
<input class="ant-input" v-decorator="['test1']" /> <input class="ant-input" v-decorator="['right_child']" />
</a-form-item> </a-form-item>
</div> </div>
<div> <div>
<a-form-item label="پایه سنوات"> <a-form-item label="پایه سنوات">
<input class="ant-input" v-decorator="['test2']" /> <input class="ant-input" v-decorator="['basic_years']" />
</a-form-item> </a-form-item>
</div> </div>
<div> <div>
<a-form-item label="حق ماموریت"> <a-form-item label="حق ماموریت">
<input class="ant-input" v-decorator="['test3']" /> <input class="ant-input" v-decorator="['right_mission']" />
</a-form-item> </a-form-item>
</div> </div>
<div> <div>
<a-form-item label="حق شیفت"> <a-form-item label="حق شیفت">
<input class="ant-input" v-decorator="['test4']" /> <input class="ant-input" v-decorator="['right_shift']" />
</a-form-item> </a-form-item>
</div> </div>
<div> <div>
<a-form-item label="پاداش مستمر"> <a-form-item label="پاداش مستمر">
<input class="ant-input" v-decorator="['test5']" /> <input class="ant-input" v-decorator="['reward']" />
</a-form-item> </a-form-item>
</div> </div>
<a-form-item label="نوع قرارداد">
<a-select v-model="contractType" style="width: 100%" v-decorator="['type']">
<a-select-option v-for="(item,index) in contractTypes" :value="`${index}`">
{{ item }}
</a-select-option>
</a-select>
</a-form-item>
<div>
<a-form-item label="حق السعی">
<input class="ant-input" v-decorator="['right_try']" />
</a-form-item>
</div>
<div>
<a-form-item label="محل خدمت">
<input class="ant-input" v-decorator="['city_workplace']" />
</a-form-item>
</div>
<div>
<a-form-item label="واحد کار">
<a-select
v-decorator="['work_unit', { initialValue:null,rules: [{ required: true, message: 'لطفاسطح مقدار را انتخاب کنید' }] }]" @change="selectChange">
<a-select-option v-for="item in work_units" :value="item.id">
{{ item.value }}
</a-select-option>
</a-select>
</a-form-item>
</div>
<div>
<a-form-item label="نام واحد" has-feedback v-if="showName">
<input class="ant-input"
v-decorator="['work_unit_name', { rules: [{ required: true, message: 'لطفا مقدار را وارد کنید' }] }]"
autocomplete="off"
/>
</a-form-item>
</div>
</div> </div>
<!--<a-form-item label="دلیل فسخ قرارداد"> <!--<a-form-item label="دلیل فسخ قرارداد">
<input class="ant-input" style="width: 100%" v-decorator="['reason_termination']" /> <input class="ant-input" style="width: 100%" v-decorator="['reason_termination']" />
@@ -771,9 +897,28 @@
<a-form-item label="فایل"> <a-form-item label="فایل">
<div class="dropbox"> <div class="dropbox">
<a-upload-dragger <a-upload-dragger
v-if="!isAlertUpload" :disabled="!$getAccess('personnel.basic.update')"
:multiple="false"
action="http://hr.asco-intl.com:2020/back/public/api/register/upload"
:file-list="contractFileList"
:default-file-list="contractFileList"
@change="contractFileUpload"
:remove="contractFileRemove"
>
<p class="ant-upload-drag-icon">
<a-icon type="inbox" />
</p>
<p class="ant-upload-text">
فایل را درگ کنید یا اینکه کاوش کنید.
</p>
<p class="ant-upload-hint">
فایلی که بارگذاری می کنید باید زیر ۵ مگابایت باشد.
</p>
</a-upload-dragger>
<!-- <a-upload-dragger
:customRequest="uploadImage" :customRequest="uploadImage"
:show-upload-list="false" :file-list="contractFileList"
:before-upload="beforeUpload" :before-upload="beforeUpload"
> >
<p class="ant-upload-drag-icon"> <p class="ant-upload-drag-icon">
@@ -785,10 +930,10 @@
<p class="ant-upload-hint"> <p class="ant-upload-hint">
تصویر که بارگذاری می کنید باید زیر ۵ مگابایت باشد. تصویر که بارگذاری می کنید باید زیر ۵ مگابایت باشد.
</p> </p>
</a-upload-dragger> </a-upload-dragger>-->
<div v-else> <!-- <div v-else>
<a-alert message="آپلود سند با موفقیت انجام شد." type="success" /> <a-alert message="آپلود سند با موفقیت انجام شد." type="success" />
</div> </div>-->
</div> </div>
</a-form-item> </a-form-item>
</a-form> </a-form>
@@ -882,19 +1027,19 @@
</a-form> </a-form>
</a-modal> </a-modal>
<a-modal okText="چاپ" :footer="null" cancelText="بستن" forceRender v-model="showContractPrint" title="شماره قرارداد" > <!-- <a-modal okText="چاپ" :footer="null" cancelText="بستن" forceRender v-model="showContractPrint" title="شماره قرارداد" >
<!-- <a-form-item label="شماره قرارداد"> &lt;!&ndash; <a-form-item label="شماره قرارداد">
<input class="ant-input" autocomplete="off" v-model="contractNumber" /> <input class="ant-input" autocomplete="off" v-model="contractNumber" />
</a-form-item>--> </a-form-item>&ndash;&gt;
<a-form-item label="نوع قرارداد"> <a-form-item label="نوع قرارداد">
<a-select v-model="contractType" style="width: 120px" > <a-select v-model="contractType" style="width: 120px" >
<a-select-option v-for="i in 10" :value="i"> <a-select-option v-for="(item,index) in contractTypes" :value="index">
{{ i }} نوع {{ item }}
</a-select-option> </a-select-option>
</a-select> </a-select>
</a-form-item> </a-form-item>
<a-button :href="`/back/public/api/personnel/print?id=${contractId}&type=${contractType}`" target="_blank">چاپ قرداد</a-button> <a-button :href="`http://hr.asco-intl.com/back/public/api/personnel/print?id=${contractId}&type=${contractType}`" target="_blank">چاپ قرداد</a-button>
</a-modal> </a-modal>-->
</a-card> </a-card>
</div> </div>
</a-spin> </a-spin>
@@ -904,8 +1049,8 @@
<script> <script>
import * as TableCol from './personelTbl'; import tbl from './personelTbl';
import XTable from "@/components/x-table/XTable"; import XTable from "@/components/new-x-table/XTable";
import axios from "@/axios"; import axios from "@/axios";
import moment from 'moment-jalaali' import moment from 'moment-jalaali'
//import Button from "@/views/components/vuesax/button/Button"; //import Button from "@/views/components/vuesax/button/Button";
@@ -934,6 +1079,8 @@
}, },
data() { data() {
return { return {
prsonalFileList:[],
file_id:undefined,
fileList: [], fileList: [],
documentFileList: [], documentFileList: [],
documents:[], documents:[],
@@ -983,12 +1130,113 @@
activeContract:null, activeContract:null,
contractId:'', contractId:'',
contractNumber:'', contractNumber:'',
contractType:1, contractType:"1",
showContractPrint:false, showContractPrint:false,
//profile_file:null, //profile_file:null,
// editing mode add
editContractFlag : false,
// editingContractIndex : undefined,
contractTypes:undefined,
work_units:[],
showName:false,
contractFileList:[]
} }
}, },
methods:{ methods:{
getTime(date){
return moment(date,'YYYY-MM-DD HH:mm:ss').format('jYYYY/jM/jD-HH:mm')
},
contractFileUpload({fileList, event, file}){
if (file.response && file.response.id) {
this.image_data = file.response
}
this.contractFileList = fileList;
},
contractFileRemove(){
this.image_data = null
},
fileUpload({fileList, event, file}){
if (file.response && file.response.id) {
this.file_id = file.response;
}
this.prsonalFileList = fileList;
},
fileRemove(){
this.file_id = null
},
checkPermission(index){
const steps = {
1:'personnel.basic.update',
3:'personnel.train',
4:'personnel.contract',
5:'personnel.intro',
6:'personnel.delivery',
7:'personnel.function',
8:'personnel.rule'
}
return !this.$getAccess(steps[index])
},
async detectEditMode(e){
await this.addContract(e)
if(this.editContractFlag)
this.editContractFlag = false
},
openEditingContractModal(item,index){
console.log(this.contractTypes)
console.log(item)
console.log(item)
item.type = item.type?item.type.toString():undefined
if(item.file){
this.contractFileList = [{ uid:item.file.id, name: item.file.filename, status: 'done', url:item.file.storage }]
}
this.activeContract = index
this.editContractFlag = true
this.showAddContract = true
this.contractModel.end_at = moment(item.end_at,'YYYY-MM-DD HH:mm:ss').format('jYYYY/jM/jD');
this.contractModel.start_at = moment(item.start_at,'YYYY-MM-DD HH:mm:ss').format('jYYYY/jM/jD');
// console.log("item:::::::::::::",item)
this.fromContract.setFieldsValue(item)
},
addContract(e){
e.preventDefault();
this.fromContract.validateFields((err, values) => {
if (!err) {
if(this.image_data){
values.contract_file_id = this.image_data.id
//values.file = this.image_data.storage
}
//values.start_at=this.contractModel.start_at,
//values.end_at=this.contractModel.end_at;
if(values.work_unit=="new"){
values.work_unit = values.work_unit_name
}
if(this.editContractFlag){
// console.log("editing")
values.start_at=moment(this.contractModel.start_at,'jYYYY/jM/jD').format('YYYY-M-D');
values.end_at=moment(this.contractModel.end_at,'jYYYY/jM/jD').format('YYYY-M-D');
this.contract[this.activeContract] = Object.assign(this.contract[this.activeContract], values)
console.log("model",this.contractModel)
this.contractModel = {start_at:'', end_at:'', salary:0, worker_coupon:0, housing_allowance:0, right_attraction:0, right_guardianship:0, reason_termination:''}
}
else {
// console.log("adding")
values.start_at=moment(this.contractModel.start_at,'jYYYY/jM/jD').format('YYYY-M-D');
values.end_at=moment(this.contractModel.end_at,'jYYYY/jM/jD').format('YYYY-M-D');
this.contract.push(values);
}
console.log("data",this.contract[this.editingContractIndex])
this.saveData();
this.showAddContract = false;
this.$message.success('اطلاعات با موفقیت ثبت شد');
this.fromContract.resetFields();
this.image_data=null;
// console.log('contract',this.contract);
}
});
},
AddJobsHistory(){ AddJobsHistory(){
const obj={ const obj={
"title": null, "title": null,
@@ -1168,10 +1416,26 @@
} }
}); });
}, },
removetermination(index){
try{
this.contract[index].date_termination=null
this.contract[index].datej_termination=null
this.contract[index].reason_termination=null
this.saveData();
}catch (e) {
this.$ntSetError()
throw e
}finally {
this.$refs.personelTbl.fetch();
}
},
async saveData(){ async saveData(){
this.fromPersonel.validateFields(async(err, values) => { this.fromPersonel.validateFields(async(err, values) => {
if (!err) { if (!err) {
try{ try{
this.$vs.loading()
values.proposal.count_child = parseInt(values.proposal.count_child)
values.proposal.file_id = this.file_id
//console.log(values); //console.log(values);
values.id=this.personel.id; values.id=this.personel.id;
//values.profile_file=this.profile_file; //values.profile_file=this.profile_file;
@@ -1183,7 +1447,37 @@
return item.uid; return item.uid;
});*/ });*/
values.documents=this.documents; values.documents=this.documents;
await axios.post('personnel/update',values); if (!this.$getAccess('personnel.basic.update')) {
values.proposal = this.personel.proposal
values.bank_card_number = this.personel.bank_card_number
values.bank_account = this.personel.bank_account
values.name = this.personel.name
values.insurance_no = this.personel.insurance_sts
values.insurance_sts = this.personel.insurance_sts
values.ncode = this.personel.ncode
values.documents = this.personel.documents
values.personel_id = this.personel.personel_id
values.profile_file = this.personel.profile_file
}
if (!this.$getAccess('personnel.train')) {
values.training = this.personel.training
}
if (!this.$getAccess('personnel.contract')) {
values.contract = this.personel.contract
}
if (!this.$getAccess('personnel.intro')) {
values.intro_checklist = this.personel.intro_checklist
}
if (!this.$getAccess('personnel.delivery')) {
values.equip_checklist = this.personel.equip_checklist
}
if (!this.$getAccess('personnel.function')) {
values.estimate = this.personel.estimate
}
if (!this.$getAccess('personnel.rule')) {
values.writ = this.personel.writ
}
await axios.post('personnel/update',values);
this.getdata(this.personel.id); this.getdata(this.personel.id);
this.$ntSet() this.$ntSet()
}catch (e) { }catch (e) {
@@ -1191,6 +1485,14 @@
throw e throw e
}finally { }finally {
this.$refs.personelTbl.fetch(); this.$refs.personelTbl.fetch();
this.$vs.loading.close()
this.showAddPerformance = false
this.showAddDocument = false
this.showPersonalModal = false
this.showAddEducationalInformation = false
this.showAddContract = false
this.showTermination = false
this.showTermination = false
} }
} }
}); });
@@ -1285,28 +1587,6 @@
} }
}); });
}, },
addContract(e){
e.preventDefault();
this.fromContract.validateFields((err, values) => {
if (!err) {
if(this.image_data){
values.contract_file_id = this.image_data.id
//values.file = this.image_data.storage
}
//values.start_at=this.contractModel.start_at,
//values.end_at=this.contractModel.end_at;
values.start_at=moment(this.contractModel.start_at,'jYYYY/jM/jD').format('YYYY-M-D');
values.end_at=moment(this.contractModel.end_at,'jYYYY/jM/jD').format('YYYY-M-D');
this.contract.push(values);
this.showAddContract = false;
this.$message.success('اطلاعات با موفقیت ثبت شد');
this.fromContract.resetFields();
this.image_data=null;
this.saveData();
// console.log('contract',this.contract);
}
});
},
savefromPersonel(e) { savefromPersonel(e) {
e.preventDefault(); e.preventDefault();
this.fromPersonel.validateFields(async(err, values) => { this.fromPersonel.validateFields(async(err, values) => {
@@ -1333,6 +1613,11 @@
this.writ=personelData.data.writ; this.writ=personelData.data.writ;
this.estimate=personelData.data.estimate; this.estimate=personelData.data.estimate;
this.training=personelData.data.training; this.training=personelData.data.training;
//for per
this.personel.contract = this.contract
this.personel.writ = this.writ
this.personel.estimate = this.estimate
this.personel.training = this.training
}catch (error) }catch (error)
{ {
console.log(error); console.log(error);
@@ -1397,7 +1682,7 @@
//console.log(data,'dataaaa') //console.log(data,'dataaaa')
this.image_data = data this.image_data = data
this.$message.success('آپلود سند با موفقیت انجام شد.'); this.$message.success('آپلود سند با موفقیت انجام شد.');
this.isAlertUpload = true // this.isAlertUpload = true
} catch (e) { } catch (e) {
this.$message.error('خطا در بارگذاری اطلاعات'); this.$message.error('خطا در بارگذاری اطلاعات');
} finally { } finally {
@@ -1406,7 +1691,7 @@
}, },
/*async uploadDocument(input) { /*async uploadDocument(input) {
try { try {
let formData = new FormData(); let formData = new-x-table FormData();
formData.append("file", input.file); formData.append("file", input.file);
const { data } = await axios.post("register/upload",formData, {'Content-Type': 'multipart/form-data'}); const { data } = await axios.post("register/upload",formData, {'Content-Type': 'multipart/form-data'});
//console.log(data,'dataaaa') //console.log(data,'dataaaa')
@@ -1421,7 +1706,7 @@
},*/ },*/
/* async uploadImageProfile(input) { /* async uploadImageProfile(input) {
try { try {
let formData = new FormData(); let formData = new-x-table FormData();
formData.append("file", input.file); formData.append("file", input.file);
const { data } = await axios.post("register/upload",formData, {'Content-Type': 'multipart/form-data'}); const { data } = await axios.post("register/upload",formData, {'Content-Type': 'multipart/form-data'});
//console.log(data,'dataaaa') //console.log(data,'dataaaa')
@@ -1453,8 +1738,12 @@
}, },
async showPersonal(record) { async showPersonal(record) {
try { try {
if(record.proposal.file){
this.file_id = record.proposal.file.id
this.prsonalFileList= [{ uid:record.proposal.file.id, name: record.proposal.file.filename, status: 'done', url:record.proposal.file.storage }]
}
record.proposal.military_sts = record.proposal.military_sts?`${record.proposal.military_sts}`:undefined
this.showLoading=true; this.showLoading=true;
this.personel = record;
const {data} = await axios.post('/proposal/details', {id:record.proposal_id}) const {data} = await axios.post('/proposal/details', {id:record.proposal_id})
record.personal_details = data; record.personal_details = data;
this.$refs.fileUpload.fileList=[]; this.$refs.fileUpload.fileList=[];
@@ -1473,8 +1762,8 @@
this.personalDetails=data; this.personalDetails=data;
this.getdata(record.id); this.getdata(record.id);
this.showPersonalModal=true; this.showPersonalModal=true;
this.personel = record;
this.$nextTick(()=>{ this.$nextTick(()=>{
// console.log('fdsfgdf',record);
this.fromPersonel.setFieldsValue(record); this.fromPersonel.setFieldsValue(record);
}); });
this.showLoading=false; this.showLoading=false;
@@ -1483,7 +1772,35 @@
}finally { }finally {
} }
},
//get contract types
async getTypes(){
try {
const {data} = await axios.get('/personnel/type')
this.contractTypes = data
}catch (e) {
throw e
} }
},
async getUnits(){
try {
let {data} = await axios.get('/personnel/unit')
data.push
({
id: "new",
value: "افزودن واحد جدید"
})
this.work_units = data
}catch (e) {
throw e
}
},
async selectChange(id){
if (id == "new") {
this.showName = true
}
}
}, },
beforeCreate() { beforeCreate() {
}, },
@@ -1504,7 +1821,10 @@
}).catch((error) => { }).catch((error) => {
this.$message.error('خطا در دریافت اطلاعات'); this.$message.error('خطا در دریافت اطلاعات');
}); });
this.cols = TableCol.default; this.cols = tbl;
this.getTypes()
this.getUnits()
} }
} }
</script> </script>
+5 -5
View File
@@ -1,12 +1,12 @@
import XTbl, {Xtc} from '../../components/x-table/index'; import XTbl, {Xtc} from '../../components/new-x-table/index';
const tbl = new XTbl('http://hr.asco-intl.com/back/public/api/personnel', 'لیست پرسنل'); const tbl = new XTbl('http://hr.asco-intl.com:2020/back/public/api/personnel/table', 'لیست پرسنل');
tbl.add(new Xtc('name', 'نام و نام خانوادگی').filterText()); tbl.add(new Xtc('name', 'نام و نام خانوادگی').filterText());
tbl.add(new Xtc('personel_id', 'کد پرسنلی').filterText()) tbl.add(new Xtc('personel_id', 'کد پرسنلی').filterText())
tbl.add(new Xtc('insurance_no', 'شماره بیمه').filterText()) tbl.add(new Xtc('insurance_no', 'شماره بیمه').filterText())
tbl.add(new Xtc('ncode', 'کد ملی').filterText()) tbl.add(new Xtc('ncode', 'کد ملی').filterText())
tbl.add(new Xtc('caj', 'ثبت نام').filterDate().noSort()) tbl.add(new Xtc('caj', 'ثبت نام').filterDate().filterKey('created_at'))
tbl.add(new Xtc('uaj', 'به روز رسانی').filterText().noSort()) tbl.add(new Xtc('uaj', 'به روز رسانی').filterDate().filterKey('updated_at'))
tbl.add(new Xtc('operator', 'عملیات').filterSwitch().renderSlot('operator').noSort()) tbl.add(new Xtc('operator', 'عملیات').renderSlot('operator').noSort())
export default tbl; export default tbl;
+1 -1
View File
@@ -119,7 +119,7 @@
const {data} = await axios.get('site/city'); const {data} = await axios.get('site/city');
console.log(data,'city') console.log(data,'city')
this.cities = data; this.cities = data;
// this.provinces = new Set(Object.values(data).map((item) => item[0])); // this.provinces = new-x-table Set(Object.values(data).map((item) => item[0]));
}, },
async getCollection() { async getCollection() {
+1 -1
View File
@@ -1,4 +1,4 @@
import XTbl, {Xtc} from '../../components/x-table/index'; import XTbl, {Xtc} from '../../components/new-x-table/index';
const tbl = new XTbl('/admin/transaction/table', 'لیست اسناد واریزی'); const tbl = new XTbl('/admin/transaction/table', 'لیست اسناد واریزی');
tbl.add(new Xtc('amount', 'مبلغ پرداختی').filterNumber()); tbl.add(new Xtc('amount', 'مبلغ پرداختی').filterNumber());
+1 -1
View File
@@ -150,7 +150,7 @@
async getIpc() { async getIpc() {
const {data} = await axios.get('admin/price/list/ipc'); const {data} = await axios.get('admin/price/list/ipc');
this.ipc = data this.ipc = data
// let mySet = new Set(Object.values(data).map(item=>item.title)); // let mySet = new-x-table Set(Object.values(data).map(item=>item.title));
// let array = Array.from(mySet); // let array = Array.from(mySet);
}, },
+1 -1
View File
@@ -122,7 +122,7 @@
const {data} = await axios.get('site/city'); const {data} = await axios.get('site/city');
console.log(data,'city') console.log(data,'city')
this.cities = data; this.cities = data;
// this.provinces = new Set(Object.values(data).map((item) => item[0])); // this.provinces = new-x-table Set(Object.values(data).map((item) => item[0]));
}, },
// changeProvinces(value) { // changeProvinces(value) {
+547 -9
View File
@@ -14,26 +14,25 @@
عملیات <a-icon type="down" /> عملیات <a-icon type="down" />
</a> </a>
<a-menu slot="overlay"> <a-menu slot="overlay">
<a-menu-item> <a-menu-item v-if="$getAccess('request.interview')">
<a href="javascript:;" @click="showMosahebe(text.record.id)">مشاهده مصاحبه</a> <a href="javascript:;" @click="showMosahebe(text.record.id)">مشاهده مصاحبه</a>
</a-menu-item> </a-menu-item>
<a-menu-item> <a-menu-item v-if="$getAccess('request.detail')">
<a href="javascript:;" @click="showDetails(text.record)">مشاهده اطلاعات</a> <a href="javascript:;" @click="showDetails(text.record)">مشاهده اطلاعات</a>
</a-menu-item> </a-menu-item>
<a-menu-item> <a-menu-item v-if="$getAccess('request.create')">
<a href="javascript:;" @click="showAddMosahebe(text.record.id)">ثبت مصاحبه</a> <a href="javascript:;" @click="showAddMosahebe(text.record.id)">ثبت مصاحبه</a>
</a-menu-item> </a-menu-item>
<a-menu-item> <a-menu-item v-if="$getAccess('request.employment')">
<a href="javascript:;" @click="showConfirme(text.record.id)">استخدام</a> <a href="javascript:;" @click="showConfirme(text.record.id)">استخدام</a>
</a-menu-item> </a-menu-item>
</a-menu> </a-menu>
</a-dropdown> </a-dropdown>
</template> </template>
</x-table> </x-table>
<a-modal :width="1000" v-model="showMosahebeModal" title="مشاهده مصاحبه ها" > <a-modal :width="1000" v-model="showMosahebeModal" title="مشاهده مصاحبه ها" >
<div v-if="is_skeleton"> <div v-if="is_skeleton">
<ASkeleton/> <ASkeleton/>
@@ -57,6 +56,9 @@
<a-descriptions-item label="وضعیت"> <a-descriptions-item label="وضعیت">
{{ item.sts_str }} {{ item.sts_str }}
</a-descriptions-item> </a-descriptions-item>
<a-descriptions-item lable="" v-if="$getAccess('request.update.interview')">
<a-button icon="edit" @click="openEditInterviewModal(item)"/>
</a-descriptions-item>
</a-descriptions> </a-descriptions>
<a-card title="جزییات" > <a-card title="جزییات" >
<a-list > <a-list >
@@ -92,7 +94,6 @@
</template> </template>
</a-modal> </a-modal>
<a-modal force-render :width="990" v-model="showAddMosahebeModal" title="ثبت مصاحبه"> <a-modal force-render :width="990" v-model="showAddMosahebeModal" title="ثبت مصاحبه">
<template slot="footer"> <template slot="footer">
<a-button v-if="current < 2" type="primary" @click="savefromMosahebe"> <a-button v-if="current < 2" type="primary" @click="savefromMosahebe">
@@ -322,7 +323,6 @@
</div> </div>
</a-modal> </a-modal>
<a-modal :width="800" v-model="showInformationModal" title="جزییات درخواست" > <a-modal :width="800" v-model="showInformationModal" title="جزییات درخواست" >
<template slot="footer"> <template slot="footer">
<a-button key="back" @click="showInformationModal=false"> <a-button key="back" @click="showInformationModal=false">
@@ -414,14 +414,496 @@
<a-divider /> <a-divider />
</template> </template>
</a-card> </a-card>
<br/>
<a-card title="سوابق شخصی" :bordered="true">
<div class="dropbox">
<a-upload-dragger
:disabled="!requestEditMode"
:multiple="false"
action="http://hr.asco-intl.com:2020/back/public/api/register/upload"
:file-list="prsonalFileList"
:default-file-list="prsonalFileList"
@change="fileUpload"
:remove="fileRemove"
>
<p class="ant-upload-drag-icon">
<a-icon type="inbox" />
</p>
<p class="ant-upload-text">
فایل را درگ کنید یا اینکه کاوش کنید.
</p>
<p class="ant-upload-hint">
فایلی که بارگذاری می کنید باید زیر ۵ مگابایت باشد.
</p>
</a-upload-dragger>
</div>
</a-card>
</a-modal> </a-modal>
<a-modal force-render :width="990" v-model="editInterviewModel" title="ویرایش مصاحبه">
<template slot="footer">
<a-button type="primary" @click="editInterview">
ثبت اطلاعات
</a-button>
</template>
<div>
<div class="steps-content">
<a-form :form="fromMosahebe">
<p style="font-weight: bold">موضوع بررسی</p>
<a-card title="مشاغل" :bordered="true" class="mt-3">
<div class="grid sm:grid-cols-1 md:grid-cols-2 md:gap-3 lg:grid-cols-2 lg:gap-3">
<div>
<a-form-item label="تاریخ مصاحبه">
<a-input
v-model="interview_at"
id="interview_at"
autocomplete="off"
/>
</a-form-item>
<date-picker
:auto-submit="true"
color="#1DA57A"
v-model="interview_at"
element="interview_at"
/>
</div>
<a-form-item label="نام مصاحبه کننده">
<input class="ant-input" autocomplete="off" v-decorator="['interviewer',{rules: [{ required: true, message: 'نام مصاحبه کننده را وارد نمایید' }]}]"/>
</a-form-item>
</div>
</a-card>
<br/>
<a-card title="دانش تخصصی" :bordered="true" >
<a-form-item label="نمره">
<a-input-number v-decorator="['result_1.score',{initialValue: 0}]" :min="0" :max="20" />
</a-form-item>
<a-form-item label="توضیحات">
<textarea class="ant-input"
placeholder=""
v-decorator="['result_1.desc']"
:auto-size="{ minRows: 2, maxRows: 6 }"
/>
</a-form-item>
</a-card>
<br/>
<a-card title="تحصیلات مرتبط" :bordered="true" >
<a-form-item label="نمره">
<a-input-number v-decorator="['result_2.score',{initialValue: 0}]" :min="0" :max="20" />
</a-form-item>
<a-form-item label="توضیحات">
<textarea class="ant-input"
placeholder=""
v-decorator="['result_2.desc']"
:auto-size="{ minRows: 2, maxRows: 6 }"
/>
</a-form-item>
</a-card>
<br/>
<a-card title="تجربه کاری مرتبط" :bordered="true" >
<a-form-item label="نمره">
<a-input-number v-decorator="['result_3.score',{initialValue: 0}]" :min="0" :max="20" />
</a-form-item>
<a-form-item label="توضیحات">
<textarea
class="ant-input"
placeholder=""
v-decorator="['result_3.desc']"
:auto-size="{ minRows: 2, maxRows: 6 }"
/>
</a-form-item>
<!-- <a-form-item label="نتیجه">
<a-radio-group v-decorator="['result_3.sts']">
<a-radio :value="-1">
رد شده
</a-radio>
<a-radio :value="1">
قبول
</a-radio>
</a-radio-group>
</a-form-item>-->
</a-card>
<br/>
<a-card title="رفتار و شخصیت عمومی" :bordered="true" >
<a-form-item label="نمره">
<a-input-number v-decorator="['result_4.score',{initialValue: 0}]" :min="0" :max="20" />
</a-form-item>
<a-form-item label="توضیحات">
<textarea class="ant-input"
placeholder=""
v-decorator="['result_4.desc']"
:auto-size="{ minRows: 2, maxRows: 6 }"
/>
</a-form-item>
<!--
<a-form-item label="نتیجه">
<a-radio-group v-decorator="['result_4.sts']">
<a-radio :value="-1">
رد شده
</a-radio>
<a-radio :value="1">
قبول
</a-radio>
</a-radio-group>
</a-form-item>-->
</a-card>
<br/>
<a-card title="ویژگی های اختصاصی شغل" :bordered="true" >
<a-form-item label="نمره">
<a-input-number v-decorator="['result_5.score',{initialValue: 0}]" :min="0" :max="20" />
</a-form-item>
<a-form-item label="توضیحات">
<textarea class="ant-input"
placeholder=""
v-decorator="['result_5.desc']"
:auto-size="{ minRows: 2, maxRows: 6 }"
/>
</a-form-item>
</a-card>
<a-form-item label="نتیجه کلی مصاحبه">
<a-radio-group v-decorator="['sts',{rules: [{ required: true, message: 'نتیجه مصاحبه را انتخاب نمایید' }]}]">
<a-radio :value="-1">
رد شده
</a-radio>
<a-radio :value="1">
قبول
</a-radio>
<a-radio :value="2">
الویت دوم
</a-radio>
</a-radio-group>
</a-form-item>
</a-form>
</div>
</div>
</a-modal>
<!-- <a-modal :width="800" v-model="editInformationModal" title="ویرایش درخواست" :forceRender="true">
<template slot="footer">
<a-button key="back" @click="editInformationModal=false">
بستن
</a-button>
</template>
<a-card title="اطلاعات فردی">
<div class="grid sm:grid-cols-1 md:grid-cols-3 md:gap-3 lg:grid-cols-3 lg:gap-3">
<a-form-item label="نام و نام خانوادگی">
<input class="ant-input" autocomplete="off" v-decorator="['name']"/>
</a-form-item>
<a-form-item label="شهر متقاضی شغل">
<input class="ant-input" autocomplete="off" v-decorator="['for_cities']"/>
</a-form-item>
<a-form-item label="شغل متقاضی">
<input class="ant-input" autocomplete="off" v-decorator="['job_title']"/>
</a-form-item>
<a-form-item label="نام پدر">
<input class="ant-input" autocomplete="off" v-decorator="['father_name']"/>
</a-form-item>
<a-form-item label="تاریخ تولد">
<input class="ant-input" autocomplete="off" v-decorator="['birth_date']"/>
</a-form-item>
<a-form-item label="کدملی">
<input class="ant-input" autocomplete="off" v-decorator="['ncode']"/>
</a-form-item>
<a-form-item label="جنسیت">
<a-radio-group v-decorator="['gender']">
<a-radio :value="1">
مرد
</a-radio>
<a-radio :value="2">
زن
</a-radio>
</a-radio-group>
</a-form-item>
<a-form-item label="وضعیت تاهل">
<a-radio-group v-decorator="['marriage_sts']">
<a-radio :value="2">
متاهل
</a-radio>
<a-radio :value="1">
مجرد
</a-radio>
</a-radio-group>
</a-form-item>
<a-form-item label="شماره حساب بانک پاسارگاد">
<input class="ant-input"
v-decorator="['pasargad_bank_number']"/>
</a-form-item>
<a-form-item label="حقوق درخواستی">
<input class="ant-input" autocomplete="off" v-decorator="['requested_salary']"/>
</a-form-item>
<a-form-item label="شماره شناسنامه">
<input class="ant-input" autocomplete="off" v-decorator="['iden_id']"/>
</a-form-item>
<a-form-item label="سریال شناسنامه">
<input class="ant-input" autocomplete="off" v-decorator="['iden_serial']"/>
</a-form-item>
<a-form-item label="محل صدور">
<input class="ant-input" autocomplete="off" v-decorator="['iden_place']"/>
</a-form-item>
<a-form-item label="محل تولد">
<input class="ant-input" autocomplete="off" v-decorator="['birth_place']"/>
</a-form-item>
<a-form-item label="وضعیت مسکن">
<a-radio-group v-decorator="['house_sts']">
<a-radio :value="1">
مالک
</a-radio>
<a-radio :value="2">
مستاجر
</a-radio>
</a-radio-group>
</a-form-item>
<a-form-item label="آدرس" class="col-span-3" >
<input class="ant-input" autocomplete="off" v-decorator="['address',{initialValue: null,rules: [{ required: false, message: 'آدرس را وارد نمایید' }]}]" />
</a-form-item>
<a-form-item label="ایمیل">
<input class="ant-input" autocomplete="off" v-decorator="['email']"/>
</a-form-item>
<a-form-item label="موبایل">
<input class="ant-input" autocomplete="off" v-decorator="['mobile']"/>
</a-form-item>
<a-form-item label="تلفن ثابت">
<input class="ant-input" autocomplete="off" v-decorator="['phone']"/>
</a-form-item>
<a-form-item label="تلفن ضروری">
<input class="ant-input" style="direction: rtl !important;" v-decorator="['phone_emergency',{initialValue: null,rules: [{ required:false, message: 'تلفن ضروری را وارد نمایید' }]}]">
</a-form-item>
<a-form-item label="نام فرد">
<input class="ant-input" autocomplete="off" v-decorator="['phone_emergency_name',{initialValue: null}]" >
</a-form-item>
<a-form-item label="نسبت">
<input class="ant-input" autocomplete="off" v-decorator="['phone_emergency_related',{initialValue: null}]" >
</a-form-item>
<a-form-item label="وضعیت بیمه">
<a-radio-group v-decorator="['has_insurance']">
<a-radio :value="-1">
ندارد
</a-radio>
<a-radio :value="1">
دارد
</a-radio>
</a-radio-group>
</a-form-item>
<a-form-item label="شماره بیمه">
<input class="ant-input"
v-decorator="['insurance_no']"/>
</a-form-item>
<a-form-item label="تعداد فرزند">
<input class="ant-input" v-decorator="['count_child',{rules: [{ required: true, message: 'لطفا مقدار را وارد کنید' },{ pattern: /^[0-9]+$/, message: 'فقط عدد مجاز است' }] }]"/>
</a-form-item>
<a-form-item label="وضعیت نظام وظیفه">
<a-select style="width: 100%" v-decorator="['military_sts',{rules: [{ required: true, message: 'لطفا مقدار را وارد کنید' }] }]">
<a-select-option v-for="(item,index) in {1:'معاف',2:'مشمول',3:'پایان خدمت',}" :value="index">
{{ item }}
</a-select-option>
</a-select>
</a-form-item>
</div>
</a-card>
<a-card title="اطلاعات خانوادگی" class="mt-5">
<a slot="extra" @click.prevent="AddFamily()" :disabled="!$getAccess('personnel.basic.family.create')">افزودن اطلاعات خانوادگی</a>
<template v-for="(item,index) in personalDetails['family']" >
<a-button :disabled="!$getAccess('personnel.basic.family.delete')" type="danger" @click="handleRemoveFamily(item,index)">حذف</a-button>
<div class="grid sm:grid-cols-1 md:grid-cols-3 md:gap-3 lg:grid-cols-3 lg:gap-3">
<a-form-item style="display: none">
<input type="hidden" class="ant-input" autocomplete="off" v-decorator="[`personal_details.family[${index}].id`]"/>
</a-form-item>
<a-form-item label="نام">
<input class="ant-input" autocomplete="off" v-decorator="[`personal_details.family[${index}].name`]"/>
</a-form-item>
<a-form-item label="نسبت">
<input class="ant-input" autocomplete="off" v-decorator="[`personal_details.family[${index}].relation`]"/>
</a-form-item>
<a-form-item label="مقطع">
&lt;!&ndash; <a-input autocomplete="off" v-decorator="['personal_details[0].university',{rules: [{ required: true, message: 'وارد کردن شغل الزامی است' }]}]"/>&ndash;&gt;
<a-select v-decorator="[`personal_details.family[${index}].edu_level`]" >
<a-select-option :value="1">
کاردانی
</a-select-option>
<a-select-option :value="2">
کارشناسی
</a-select-option>
<a-select-option :value="3" >
کارشناسی ارشد
</a-select-option>
<a-select-option :value="4">
دکترا
</a-select-option>
</a-select>
</a-form-item>
&lt;!&ndash; <a-form-item label="دانشگاه">
<input class="ant-input" autocomplete="off" v-decorator="[`personal_details.family[${index}].university`]"/>
</a-form-item>&ndash;&gt;
<a-form-item label="رشته تحصیلی">
<input class="ant-input" autocomplete="off" v-decorator="[`personal_details.family[${index}].edu_title`]"/>
</a-form-item>
<a-form-item label="شغل">
<input class="ant-input" autocomplete="off" v-decorator="[`personal_details.family[${index}].job`]"/>
</a-form-item>
</div>
<a-divider />
</template>
</a-card>
<a-card title="اطلاعات تحصیلی" class="mt-5">
<a :disabled="!$getAccess('personnel.basic.education.create')" slot="extra" @click.prevent="AddEducation()">افزودن سابقه تحصیلی</a>
<template v-for="(item,index) in personalDetails['education']">
<a-button :disabled="!$getAccess('personnel.basic.education.delete')" type="danger" @click="handleRemoveEducation(item,index)">حذف</a-button>
<div class="grid sm:grid-cols-1 md:grid-cols-3 md:gap-3 lg:grid-cols-3 lg:gap-3">
<a-form-item style="display: none">
<input type="hidden" class="ant-input" autocomplete="off" v-decorator="[`personal_details.education[${index}].id`]"/>
</a-form-item>
<a-form-item label="مقطع">
&lt;!&ndash; <a-input autocomplete="off" v-decorator="['personal_details[0].university',{rules: [{ required: true, message: 'وارد کردن شغل الزامی است' }]}]"/>&ndash;&gt;
<a-select v-decorator="[`personal_details.education[${index}].level`]" >
<a-select-option :value="1">
کاردانی
</a-select-option>
<a-select-option :value="2">
کارشناسی
</a-select-option>
<a-select-option :value="3" >
کارشناسی ارشد
</a-select-option>
<a-select-option :value="4">
دکترا
</a-select-option>
</a-select>
</a-form-item>
<a-form-item label="دانشگاه">
<input class="ant-input" autocomplete="off" v-decorator="[`personal_details.education[${index}].university`]"/>
</a-form-item>
<a-form-item label="رشته تحصیلی">
<input class="ant-input" autocomplete="off" v-decorator="[`personal_details.education[${index}].title`]"/>
</a-form-item>
<a-form-item label="گرایش">
<input class="ant-input" autocomplete="off" v-decorator="[`personal_details.education[${index}].trend`]"/>
</a-form-item>
<a-form-item label="سال شروع">
<input class="ant-input" autocomplete="off" v-decorator="[`personal_details.education[${index}].start_at`]"/>
</a-form-item>
<a-form-item label="سال خاتمه">
<input class="ant-input" autocomplete="off" v-decorator="[`personal_details.education[${index}].end_at`]"/>
</a-form-item>
</div>
<a-divider />
</template>
</a-card>
<a-card title="سوابق آموزشی" class="mt-5">
<a :disabled="!$getAccess('personnel.basic.train.create')" slot="extra" @click.prevent="AddTraning()">افزودن سابقه آموزشی </a>
<template v-for="(item,index) in personalDetails['traning']">
<a-button :disabled="!$getAccess('personnel.basic.train.delete')" type="danger" @click="handleRemoveTraning(item,index)">حذف</a-button>
<div class="grid sm:grid-cols-1 md:grid-cols-3 md:gap-3 lg:grid-cols-3 lg:gap-3">
<a-form-item style="display: none">
<input type="hidden" class="ant-input" autocomplete="off" v-decorator="[`personal_details.traning[${index}].id`]"/>
</a-form-item>
<a-form-item label="مرکز برگزاری">
<input class="ant-input" autocomplete="off" v-decorator="[`personal_details.traning[${index}].university`]"/>
</a-form-item>
<a-form-item label="عنوان دوره ">
<input class="ant-input" autocomplete="off" v-decorator="[`personal_details.traning[${index}].title`]"/>
</a-form-item>
<a-form-item label="سال">
<input class="ant-input" autocomplete="off" v-decorator="[`personal_details.traning[${index}].start_at`]"/>
</a-form-item>
<a-form-item label="امکان ارائه گواهینامه دارم">
<a-checkbox v-decorator="[`personal_details.traning[${index}].has_certificate`,{initialValue:false,valuePropName: 'checked'}]"/>
</a-form-item>
</div>
<a-divider />
</template>
</a-card>
<a-card title="سوابق کاری" class="mt-5">
<a :disabled="!$getAccess('personnel.basic.job.create')" slot="extra" @click.prevent="AddJobsHistory()">افزودن سابقه کاری</a>
<template v-for="(item,index) in personalDetails['jobs_history']">
<a-button :disabled="!$getAccess('personnel.basic.job.delete')" type="danger" @click="handleRemoveJobsHistory(item,index)">حذف</a-button>
<div class="grid sm:grid-cols-1 md:grid-cols-3 md:gap-3 lg:grid-cols-3 lg:gap-3">
<a-form-item style="display: none">
<input type="hidden" class="ant-input" autocomplete="off" v-decorator="[`personal_details.jobs_history[${index}].id`]"/>
</a-form-item>
<a-form-item label="نام سازمان ">
<input class="ant-input" autocomplete="off" v-decorator="[`personal_details.jobs_history[${index}].university`]"/>
</a-form-item>
<a-form-item label="عنوان شغل">
<input class="ant-input" autocomplete="off" v-decorator="[`personal_details.jobs_history[${index}].title`]"/>
</a-form-item>
<a-form-item label="دلیل خاتمه">
<input class="ant-input" autocomplete="off" v-decorator="[`personal_details.jobs_history[${index}].note`]"/>
</a-form-item>
<a-form-item label="سال شروع">
<input class="ant-input" autocomplete="off" v-decorator="[`personal_details.jobs_history[${index}].start_at`]"/>
</a-form-item>
<a-form-item label="سال خاتمه">
<input class="ant-input" autocomplete="off" v-decorator="[`personal_details.jobs_history[${index}].end_at`]"/>
</a-form-item>
&lt;!&ndash;<a-form-item label="تاکنون">
<a-checkbox v-decorator="['end_now',{initialValue:false,valuePropName: 'checked'}]" />
</a-form-item>&ndash;&gt;
</div>
<a-divider />
</template>
</a-card>
<a-card title="سوابق شخصی" class="mt-5">
<div class="dropbox">
<a-upload-dragger
:multiple="false"
action="http://hr.asco-intl.com/back/public/api/register/upload"
:file-list="prsonalFileList"
:default-file-list="prsonalFileList"
@change="fileUpload"
:remove="fileRemove"
>
<p class="ant-upload-drag-icon">
<a-icon type="inbox" />
</p>
<p class="ant-upload-text">
فایل را درگ کنید یا اینکه کاوش کنید.
</p>
<p class="ant-upload-hint">
فایلی که بارگذاری می کنید باید زیر ۵ مگابایت باشد.
</p>
</a-upload-dragger>
</div>
</a-card>
</a-modal>-->
</a-card> </a-card>
</div> </div>
</template> </template>
<script> <script>
import * as TableCol from './proposalTbl'; import * as TableCol from './proposalTbl';
import XTable from "@/components/x-table/XTable"; import XTable from "@/components/new-x-table/XTable";
import axios from "@/axios"; import axios from "@/axios";
import VuePersianDatetimePicker from "vue-persian-datetime-picker"; import VuePersianDatetimePicker from "vue-persian-datetime-picker";
@@ -432,6 +914,8 @@
}, },
data() { data() {
return { return {
prsonalFileList:[],
file_id:undefined,
showMosahebeModal:false, showMosahebeModal:false,
showInformationModal:false, showInformationModal:false,
showAddMosahebeModal:false, showAddMosahebeModal:false,
@@ -445,10 +929,57 @@
row_id:null, row_id:null,
interview:[], interview:[],
title_interview:['دانش تخصصی','تحصیلات مرتبط','تجربه کاری مرتبط','رفتار و شخصیت عمومی','ویژگی های اختصاصی شغل'], title_interview:['دانش تخصصی','تحصیلات مرتبط','تجربه کاری مرتبط','رفتار و شخصیت عمومی','ویژگی های اختصاصی شغل'],
is_skeleton:false is_skeleton:false,
// requestEditMode:false,
editInterviewModel:false,
editingInterviewIndex:undefined
} }
}, },
methods:{ methods:{
editInterview(e){
e.preventDefault();
this.fromMosahebe.validateFields(async(err, values) => {
try{
if (!err) {
this.$vs.loading()
console.log(values,'values')
values.interview_at = this.interview_at
await axios.put(`/proposal/interview/update/${this.editingInterviewIndex}`,values)
this.editInterviewModel = false
this.$ntSet('اطلاعات با موفقیت کامل شد')
this.fromMosahebe.resetFields();
}
}catch (e) {
this.$ntSetError()
throw e
}finally {
this.$vs.loading.close()
}
});
},
openEditInterviewModal(item){
item.result.map((i,index)=>{
item[`result_${index+1}`] = {
desc: i.desc,
score: i.score
}
})
this.editingInterviewIndex = item.id
this.showMosahebeModal = false
this.editInterviewModel = true
this.interview_at = item.interview_at
this.fromMosahebe.setFieldsValue(item)
},
fileUpload({fileList, event, file}){
if (file.response && file.response.id) {
this.file_id = file.response.id;
}
this.prsonalFileList = fileList;
},
fileRemove(){
this.file_id = null
},
showAddMosahebe(id) showAddMosahebe(id)
{ {
this.showAddMosahebeModal=true; this.showAddMosahebeModal=true;
@@ -526,6 +1057,13 @@
}, },
showDetails(record) { showDetails(record) {
console.log('aaaaa',record); console.log('aaaaa',record);
if(record.file){
console.log("%c yess","color:blue")
this.file_id = record.file.id
this.prsonalFileList.push(
{ uid:record.file.id, name: record.file.filename, status: 'done', url:record.file.storage }
)
}
axios.post('/proposal/details', {id:record.id}) axios.post('/proposal/details', {id:record.id})
.then((res)=>{ .then((res)=>{
this.personalInformation=record; this.personalInformation=record;
+6 -6
View File
@@ -1,14 +1,14 @@
import XTbl, {Xtc} from '../../components/x-table/index'; import XTbl, {Xtc} from '../../components/new-x-table/index';
const tbl = new XTbl('http://hr.asco-intl.com/back/public/api/proposal', 'لیست درخواست ها'); const tbl = new XTbl('http://hr.asco-intl.com:2020/back/public/api/proposal/table', 'لیست درخواست ها');
tbl.add(new Xtc('name', 'نام و نام خانوادگی').filterText()); tbl.add(new Xtc('name', 'نام و نام خانوادگی').filterText());
tbl.add(new Xtc('ncode', 'کد ملی').filterText()) tbl.add(new Xtc('ncode', 'کد ملی').filterText())
tbl.add(new Xtc('mobile', 'موبایل').filterText()) tbl.add(new Xtc('mobile', 'موبایل').filterText())
tbl.add(new Xtc('job_title', 'شغل').filterText()) tbl.add(new Xtc('job_title', 'شغل').filterText())
tbl.add(new Xtc('for_cities', 'شهر').filterText().noSort()) tbl.add(new Xtc('for_cities', 'شهر').filterText())
tbl.add(new Xtc('caj', 'ثبت نام').filterDate().noSort()) tbl.add(new Xtc('caj', 'ثبت نام').filterDate())
tbl.add(new Xtc('uaj', 'به روز رسانی').filterText().noSort()) tbl.add(new Xtc('uaj', 'به روز رسانی').filterDate().filterKey('updated_at'))
tbl.add(new Xtc('id', 'عملیات').filterSwitch().renderSlot('operator').noSort()) tbl.add(new Xtc('id', 'عملیات').renderSlot('operator'))
/*tbl.addOpt()*/ /*tbl.addOpt()*/
export default tbl; export default tbl;
+49
View File
@@ -145,6 +145,17 @@
<a-form-item label="حقوق درخواستی"> <a-form-item label="حقوق درخواستی">
<input class="ant-input" autocomplete="off" v-decorator="['requested_salary',{initialValue: null,rules: [{ required: true, message: 'حقوق درخواستی را وارد نمایید' }]}]" /> <input class="ant-input" autocomplete="off" v-decorator="['requested_salary',{initialValue: null,rules: [{ required: true, message: 'حقوق درخواستی را وارد نمایید' }]}]" />
</a-form-item> </a-form-item>
<a-form-item label="تعداد فرزند">
<input class="ant-input" v-decorator="['count_child',{rules: [{ required: true, message: 'لطفا مقدار را وارد کنید' },{ pattern: /^[0-9]+$/,type: 'string', message: 'فقط عدد مجاز است' }] }]"/>
</a-form-item>
<a-form-item label="وضعیت نظام وظیفه">
<a-select style="width: 100%" v-decorator="['military_sts',{rules: [{ required: true, message: 'لطفا مقدار را وارد کنید' }] }]">
<a-select-option v-for="(item,index) in {1:'معاف',2:'مشمول',3:'پایان خدمت',}" :value="index">
{{ item }}
</a-select-option>
</a-select>
</a-form-item>
</div> </div>
@@ -468,6 +479,31 @@
افزودن سابقه کاری افزودن سابقه کاری
</a-button> </a-button>
</a-card>
<br/>
<a-card title="سوابق شخصی" :bordered="true" >
<div class="dropbox">
<a-upload-dragger
:multiple="false"
action="http://hr.asco-intl.com:2020/back/public/api/register/upload"
:file-list="fileList"
:default-file-list="fileList"
@change="changeDocumentUpload"
:remove="handleRemoveDocument"
>
<p class="ant-upload-drag-icon">
<a-icon type="inbox" />
</p>
<p class="ant-upload-text">
فایل را درگ کنید یا اینکه کاوش کنید.
</p>
<p class="ant-upload-hint">
فایلی که بارگذاری می کنید باید زیر ۵ مگابایت باشد.
</p>
</a-upload-dragger>
</div>
</a-card> </a-card>
<br/> <br/>
@@ -708,6 +744,8 @@
}, },
data(){ data(){
return{ return{
fileList: [],
file_id:undefined,
current: 0, current: 0,
from: this.$form.createForm(this, {name: 'coordinated'}), from: this.$form.createForm(this, {name: 'coordinated'}),
formEdu: this.$form.createForm(this, {name: 'coordinated'}), formEdu: this.$form.createForm(this, {name: 'coordinated'}),
@@ -750,6 +788,16 @@
} }
}, },
methods:{ methods:{
changeDocumentUpload({fileList, event, file}){
if (file.response && file.response.id) {
this.file_id = file.response.id;
}
this.fileList = fileList;
},
handleRemoveDocument(){
this.file_id = null
},
deleteCity(index){ deleteCity(index){
this.jobsList.splice(index,1); this.jobsList.splice(index,1);
//console.log(index); //console.log(index);
@@ -792,6 +840,7 @@
values.model = this.formFirst.getFieldsValue(); values.model = this.formFirst.getFieldsValue();
values.birth_date = this.birth_day; values.birth_date = this.birth_day;
values.work = this.work; values.work = this.work;
values.file_id = this.file_id;
values.training = this.educational; values.training = this.educational;
values.academic = this.edu; values.academic = this.edu;
values.family= this.family; values.family= this.family;
+48
View File
@@ -155,6 +155,16 @@
<a-form-item label="حقوق درخواستی"> <a-form-item label="حقوق درخواستی">
<input class="ant-input" autocomplete="off" v-decorator="['requested_salary',{initialValue: null,rules: [{ required: true, message: 'حقوق درخواستی را وارد نمایید' }]}]" /> <input class="ant-input" autocomplete="off" v-decorator="['requested_salary',{initialValue: null,rules: [{ required: true, message: 'حقوق درخواستی را وارد نمایید' }]}]" />
</a-form-item> </a-form-item>
<a-form-item label="تعداد فرزند">
<input class="ant-input" v-decorator="['count_child',{rules: [{ required: true, message: 'لطفا مقدار را وارد کنید' },{ pattern: /^[0-9]+$/,type: 'string', message: 'فقط عدد مجاز است' }] }]"/>
</a-form-item>
<a-form-item label="وضعیت نظام وظیفه">
<a-select style="width: 100%" v-decorator="['military_sts',{rules: [{ required: true, message: 'لطفا مقدار را وارد کنید' }] }]">
<a-select-option v-for="(item,index) in {1:'معاف',2:'مشمول',3:'پایان خدمت',}" :value="index">
{{ item }}
</a-select-option>
</a-select>
</a-form-item>
</div> </div>
@@ -475,6 +485,31 @@
افزودن سابقه کاری افزودن سابقه کاری
</a-button> </a-button>
</a-card>
<br/>
<a-card title="سوابق شخصی" :bordered="true" >
<div class="dropbox">
<a-upload-dragger
:multiple="false"
action="http://hr.asco-intl.com:2020/back/public/api/register/upload"
:file-list="fileList"
:default-file-list="fileList"
@change="changeDocumentUpload"
:remove="handleRemoveDocument"
>
<p class="ant-upload-drag-icon">
<a-icon type="inbox" />
</p>
<p class="ant-upload-text">
فایل را درگ کنید یا اینکه کاوش کنید.
</p>
<p class="ant-upload-hint">
فایلی که بارگذاری می کنید باید زیر ۵ مگابایت باشد.
</p>
</a-upload-dragger>
</div>
</a-card> </a-card>
<br/> <br/>
@@ -713,6 +748,8 @@
}, },
data(){ data(){
return{ return{
fileList:[],
file_id:undefined,
current: 0, current: 0,
from: this.$form.createForm(this, {name: 'coordinated'}), from: this.$form.createForm(this, {name: 'coordinated'}),
formEdu: this.$form.createForm(this, {name: 'coordinated'}), formEdu: this.$form.createForm(this, {name: 'coordinated'}),
@@ -755,6 +792,15 @@
} }
}, },
methods:{ methods:{
changeDocumentUpload({fileList, event, file}){
if (file.response && file.response.id) {
this.file_id = file.response.id;
}
this.fileList = fileList;
},
handleRemoveDocument(){
this.file_id = null
},
deleteCity(index){ deleteCity(index){
this.jobsList.splice(index,1); this.jobsList.splice(index,1);
//console.log(index); //console.log(index);
@@ -799,6 +845,8 @@
values.training = this.educational; values.training = this.educational;
values.academic = this.edu; values.academic = this.edu;
values.family= this.family; values.family= this.family;
values.file_id = this.file_id;
// values.count_child = parseInt(values.count_child);
await axios.post('register/personnel', values) await axios.post('register/personnel', values)
this.$ntSet(); this.$ntSet();
// this.from.resetFields() // this.from.resetFields()
@@ -25,7 +25,7 @@ export default {
'Establish a set of column in the horizontal space defined by row (abbreviated col)', 'Establish a set of column in the horizontal space defined by row (abbreviated col)',
'Your content elements should be placed directly in the col, and only col should be placed directly in row', 'Your content elements should be placed directly in the col, and only col should be placed directly in row',
'The column grid system is a value from 1-12 to represent its range spans. For example, three columns of equal width can be created by .col-4 (33.3%)', 'The column grid system is a value from 1-12 to represent its range spans. For example, three columns of equal width can be created by .col-4 (33.3%)',
'If the sum of col spans in a row are more than 12, then the overflowing col as a whole will start a new line arrangement' 'If the sum of col spans in a row are more than 12, then the overflowing col as a whole will start a new-x-table line arrangement'
] ]
} }
} }
+131
View File
@@ -0,0 +1,131 @@
<template>
<div id="page-user-view" style="width: 100%">
<a-form :form="form" @submit="handleSubmit">
<ASpin type="loading" :spinning="loading">
<vx-card title="افزودن کاربر">
<div class="grid grid-col-1 sm:grid-cols-1 md:grid-cols-2 md:gap-2 lg:gap-4 xl:gap-4">
<a-form-item label="نام" has-feedback>
<a-input
v-decorator="['fname', { rules: [{ required: true, message: 'لطفا مقدار را وارد کنید' },{ pattern:/^([\u0600-\u06FF\uFB8A\u067E\u0686\u06AF\u200C ])+$/,type:'string',message:'فیلد نام باید شامل حروف فارسی باشد.' }] }]"
autocomplete="off"
/>
</a-form-item>
<a-form-item label="نام خانوادگی" has-feedback>
<a-input
v-decorator="['lname', { rules: [{ required: true, message: 'لطفا مقدار را وارد کنید' },{ pattern:/^([\u0600-\u06FF\uFB8A\u067E\u0686\u06AF\u200C ])+$/,type:'string',message:'فیلد نام باید شامل حروف فارسی باشد.' }] }]"
autocomplete="off"
/>
</a-form-item>
<a-form-item label="شماره موبایل" has-feedback>
<a-input
v-decorator="['mobile', { rules: [{ required: true, message: 'لطفا مقدار را وارد کنید' },{pattern:/(\+98|0|98|0098)?([ ]|-|[()]){0,2}9[0-9]([ ]|-|[()]){0,2}(?:[0-9]([ ]|-|[()]){0,2}){8}/,type:'string',message:'فرمت شماره موبایل نادرست است.'},{ min:11,required: true, message: 'شماره موبایل باید 11 رقم باشد '}] }]"
placeholder="09XXXXXXXXX"
/>
</a-form-item>
<a-form-item label="نوع کاربری" has-feedback>
<a-select
show-search
allowClear
placeholder="انتخاب کنید"
v-decorator="['user_type',{ rules: [{ required: true, message: 'وارد کردن مقدار الزامی است' }] }]"
>
<a-select-option v-for="item in userTypes" :value="item.id">
{{item.value}}
</a-select-option>
</a-select>
</a-form-item>
<a-form-item label="رمز عبور" has-feedback>
<a-input-password placeholder="رمز عبور خود را وارد کنید"
:autocomplete="false"
v-decorator="['password', { rules: [
{ required: true, message: 'لطفا مقدار را وارد کنید' },
{min: 6, message: 'رمز عبور نباید کمتر از 6 کارکتر باشد' },
{max: 24, message: 'رمز عبور نباید بیشتر از 24 کارکتر باشد' },
]}]"
/>
</a-form-item>
<a-form-item label="وضعیت">
<a-switch checked-children="فعال" un-checked-children="غیر فعال" default-checked
v-decorator="['active', { valuePropName: 'checked' }]"/>
</a-form-item>
</div>
<a-button @click="handleSubmit" type="primary" html-type="submit" class="mt-4">
ثبت کاربر
</a-button>
</vx-card>
</ASpin>
</a-form>
</div>
</template>
<script>
import axios from '@/axios'
export default {
name: "create",
components:{
},
data() {
return {
form: this.$form.createForm(this, { name: 'coordinated' }),
loading: false,
userTypes:{}
}
},
methods: {
async handleSubmit(e) {
e.preventDefault();
this.form.validateFields(async(err, values) => {
if (!err) {
try{
this.loading = true
await axios.post('/user',values)
this.$ntSet()
setTimeout(()=>{
this.$router.push('/users')
},500)
}catch (e) {
if(e.response.data.errors){
let str_error = ''
for (let x of Object.values(e.response.data.errors)){
x.map(xx=>{
str_error += xx + "<br/>"
})
}
this.$ntSetError(str_error)
}
}finally {
this.loading = false
}
}
});
},
},
async created(){
try{
this.loading = true
const { data } = await axios.get(`/permission/type`)
this.userTypes = data
}catch (e) {
this.$ntSetError('خطا در دریافت اطلاعات')
}finally {
this.loading = false
}
}
}
</script>
<style>
.has-success.has-feedback .ant-form-item-children-icon{
color: var(--vs-primary) !important;
}
</style>
+267
View File
@@ -0,0 +1,267 @@
<template>
<div>
<a-spin :spinning="loading" tip="در حال دریافت اطلاعات">
<div class="spin-content">
<a-card>
<a-button @click="$router.push('/register/users')" :disabled="!$getAccess('user.create')">
ثبت کاربر جدید
</a-button>
<x-table ref="users" class="mt-4"
:model="cols">
<template slot="operator" slot-scope="text,record">
<a-button type="primary" class="ml-2" @click="showUser(text.record)" :disabled="!$getAccess('user.update')">ویرایش</a-button>
<a-popconfirm
title="از حذف کاربر مطمعن هستید؟"
ok-text="بله"
cancel-text="خیر"
@confirm= "removeUsre(text.record)"
@cancel=""
>
<a-button type="danger" :disabled="!$getAccess('user.delete')">حذف</a-button>
</a-popconfirm>
</template>
</x-table>
<a-modal @ok="handleSubmit" :forceRender="false" okText="ویرایش" cancelText="بستن" width="90%" v-model="model" title="ویرایش اطلاعات کاربر">
<a-form :form="form" @submit="handleSubmit">
<a-spin :spinning="loading" tip="در حال دریافت اطلاعات">
<div class="grid grid-col-1 sm:grid-cols-1 md:grid-cols-2 md:gap-2 lg:gap-4 xl:gap-4">
<a-form-item label="نام" has-feedback>
<a-input
v-decorator="['fname', { rules: [{ required: true, message: 'لطفا مقدار را وارد کنید' },{ pattern:/^([\u0600-\u06FF\uFB8A\u067E\u0686\u06AF\u200C ])+$/,type:'string',message:'فیلد نام باید شامل حروف فارسی باشد.' }] }]"
autocomplete="off"
/>
</a-form-item>
<a-form-item label="نام خانوادگی" has-feedback>
<a-input
v-decorator="['lname', { rules: [{ required: true, message: 'لطفا مقدار را وارد کنید' },{ pattern:/^([\u0600-\u06FF\uFB8A\u067E\u0686\u06AF\u200C ])+$/,type:'string',message:'فیلد نام باید شامل حروف فارسی باشد.' }] }]"
autocomplete="off"
/>
</a-form-item>
<a-form-item label="شماره موبایل" has-feedback>
<a-input
v-decorator="['mobile', { rules: [{ required: true, message: 'لطفا مقدار را وارد کنید' },{pattern:/(\+98|0|98|0098)?([ ]|-|[()]){0,2}9[0-9]([ ]|-|[()]){0,2}(?:[0-9]([ ]|-|[()]){0,2}){8}/,type:'string',message:'فرمت شماره موبایل نادرست است.'},{ min:11,required: true, message: 'شماره موبایل باید 11 رقم باشد '}] }]"
placeholder="09XXXXXXXXX"
/>
</a-form-item>
<a-form-item label="نوع کاربری" has-feedback>
<a-select
show-search
allowClear
placeholder="انتخاب کنید"
v-decorator="['user_type',{ rules: [{ required: true, message: 'وارد کردن مقدار الزامی است' }] }]"
>
<a-select-option v-for="item in userTypes" :value="item.id">
{{item.value}}
</a-select-option>
</a-select>
</a-form-item>
<a-form-item label="رمز عبور" has-feedback>
<a-input-password placeholder="رمز عبور خود را وارد کنید"
:autocomplete="false"
v-decorator="['password', { rules: [
{ required: false, message: 'لطفا مقدار را وارد کنید' },
{min: 6, message: 'رمز عبور نباید کمتر از 6 کارکتر باشد' },
{max: 24, message: 'رمز عبور نباید بیشتر از 24 کارکتر باشد' },
]}]"
/>
</a-form-item>
<a-form-item label="وضعیت">
<a-switch checked-children="فعال" un-checked-children="غیر فعال" default-checked
v-decorator="['active', { valuePropName: 'checked' }]"/>
</a-form-item>
</div>
</a-spin>
</a-form>
</a-modal>
</a-card>
</div>
</a-spin>
</div>
</template>
<script>
import tbl from './usersTbl';
import XTable from "@/components/new-x-table/XTable";
import axios from "@/axios";
export default {
components:{
XTable,
},
data() {
return {
cols : null,
form: this.$form.createForm(this, { name: 'coordinated' }),
loading: false,
userTypes:{},
record : undefined,
id : undefined,
model : false
}
},
methods:{
async handleSubmit(e) {
e.preventDefault();
this.form.validateFields(async(err, values) => {
if (!err) {
try{
this.$vs.loading()
this.loading = true
values.op = "update"
await axios.put(`/user/${this.id}`,values)
this.model = false
this.$ntSet()
this.$refs.users.fetch()
}catch (e) {
if(e.response.data.errors){
let str_error = ''
for (let x of Object.values(e.response.data.errors)){
x.map(xx=>{
str_error += xx + "<br/>"
})
}
this.$ntSetError(str_error)
}
}finally {
this.loading = false
this.$vs.loading.close()
}
}
});
},
async showUser(record) {
try {
this.loading =true
this.model = true
console.log(record)
let {data} = await axios.get(`/user/${record.id}`)
if(data.user_type && data.user_type.id)
data.user_type = data.user_type.id
else
data.user_type = undefined
if(!data.fname && !data.lname && data.name){
let splited = data.name.split(" ")
data.fname =splited[0]
data.lname =splited.slice(1).join(" ")
}
this.record = data
this.id = record.id
this.form.setFieldsValue(data)
}catch (e) {
throw e
}
finally {
this.loading = false
}
},
async removeUsre(record) {
try {
this.loading = true
console.log(record)
// await axios.delete(`/user/${record.id}`)
this.$refs.users.fetch()
}catch (e) {
if(e.response.data.errors){
let str_error = ''
for (let x of Object.values(e.response.data.errors)){
x.map(xx=>{
str_error += xx + "<br/>"
})
}
this.$ntSetError(str_error)
}
}finally {
this.loading = false
}
},
},
async created() {
try{
this.cols = tbl;
this.loading = true
const { data } = await axios.get(`/permission/type`)
this.userTypes = data
}catch (e) {
this.$ntSetError('خطا در دریافت اطلاعات')
}finally {
this.loading = false
}
}
}
</script>
<!--
<style>
.ant-pagination
{
direction: ltr !important;
}
td,th{
text-align: right !important;
}
.ant-tabs-nav-wrap
{
float: right !important;
}
.ant-tabs-content
{
text-align: right !important;
}
.ant-modal-mask
{
z-index: 9999999 !important;
}
.ant-modal-wrap
{
z-index: 999999999 !important;
}
.ant-select-dropdown{
z-index: 999999999!important;
}
.ant-modal-content
{
direction: ltr !important;
}
.ant-modal-body
{
direction: rtl !important;
}
.ant-modal-header
{
direction: rtl;
margin-right: 25px;
}
.ant-dropdown,.ant-popover.ant-popover-placement-right{
z-index: 99999999999;
}
/*.ant-dropdown
{
z-index: 9999999999 !important;
}*/
.ant-form-item-label
{
direction: rtl !important;
}
.ant-list-item
{
direction: ltr;
}
.ant-upload.ant-upload-select-picture-card,.ant-upload-list-picture-card-container{
float: right !important;
}
.ant-upload-list-item-card-actions {
right:80% !important;
}
/* .ant-dropdown,.ant-popover.ant-popover-placement-right{
z-index: 999999999;
}*/
</style>-->
+10
View File
@@ -0,0 +1,10 @@
import XTbl, {Xtc} from '../../components/new-x-table/index';
const tbl = new XTbl('http://hr.asco-intl.com:2020/back/public/api/user/table', 'لیست کاربران');
tbl.add(new Xtc('id', 'id').filterNumber());
tbl.add(new Xtc('name', 'نام و نام خانوادگی').filterText());
tbl.add(new Xtc('user_type.value', 'نوع کاربر').filterText());
tbl.add(new Xtc('mobile', 'شماره تلفن').filterText());
tbl.add(new Xtc('operator', 'عملیات').renderSlot('operator').noSort());
export default tbl;
+1 -1
View File
@@ -39,7 +39,7 @@ module.exports = {
chunks: 'all' chunks: 'all'
}, },
} },
} }
// devServer: { // devServer: {
// overlay: { // overlay: {