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-instantsearch": "^2.2.1",
"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-property-decorator": "^8.1.1",
"vue-quill-editor": "^3.0.6",
+9 -2
View File
@@ -21,7 +21,7 @@
<script>
import themeConfig from '@/../themeConfig.js'
import jwt from '@/http/requests/auth/jwt/index.js'
import axios from "@/axios"
export default {
data () {
return {
@@ -72,7 +72,14 @@ export default {
},
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);
const dict = {
attributes: {
+27
View File
@@ -57,3 +57,30 @@
* @import "utilities/background-patterns";
* @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 router from '@/router'
const domain = ""
// 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 headers = {
'Content-Type': 'application/json',
//'Authorization': 'Bearer ' + localStorage.getItem("accessToken") || localStorage.accessToken
'accept':'application/json',
'Authorization': 'Bearer ' + token
}
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,
domain
// domain
})
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.headers["Authorization"] = "Bearer " + sessionStorage.getItem("accessToken") || sessionStorage.accessToken || null;
return config;
@@ -24,17 +57,24 @@ myax.interceptors.request.use(
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;
+7 -1
View File
@@ -1,6 +1,7 @@
<template>
<div class="clearfix">
<AUpload
:disabled="disabled"
:action="url"
:headers="headers"
:accept="accept"
@@ -50,6 +51,11 @@ export default {
size: {
default: 2
},
disabled: {
required:false,
type:Boolean,
default: false
},
accept: {default: "image/jpeg"},
serverType: {
types: {
@@ -63,7 +69,7 @@ export default {
},
data() {
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,
previewImage: '',
fileList: [],
+6
View File
@@ -1,6 +1,7 @@
<template>
<div class="clearfix">
<AUpload
:disabled="disabled"
:action="url"
:headers="headers"
accept="image/jpeg"
@@ -48,6 +49,11 @@ export default {
size: {
default: 2
},
disabled: {
required:false,
type:Boolean,
default: false
},
label: {},
serverType: {
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() {
this.fetch();
console.log("this.model ==> ", this.model);
// console.log("this.model ==> ", this.model);
}
}
</script>
+1 -1
View File
@@ -37,7 +37,7 @@ mock.onGet('/api/apps/calendar/events').reply(() => {
return [200, data.events]
})
// POST : Add new events
// POST : Add new-x-table events
mock.onPost('/api/apps/calendar/events/').reply((request) => {
// 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)
// 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 eventEndDate = new Date(event.endDate).getTime()
// const eventStartDate = new-x-table Date(event.startDate).getTime()
// const eventEndDate = new-x-table Date(event.endDate).getTime()
// const diff = draggedDateStart - eventStartDate
// const newEndDate = new Date(eventEndDate + diff)
// const newEndDate = new-x-table Date(eventEndDate + diff)
// event.startDate = draggedDateStart
// 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) => {
// 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()]
})
// POST : Add new Item
// POST : Add new-x-table Item
mock.onPost('/api/data-list/products/').reply((request) => {
// 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]
})
// // POST : Add new Item
// // POST : Add new-x-table Item
// mock.onPost("/api/data-list/products/").reply((request) => {
// // Get event from post data
@@ -167,7 +167,32 @@ export default {
}
},
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()) {
if (item.header && item.items.length && (index || 1)) {
@@ -181,7 +206,7 @@ export default {
console.log(clone
)
return clone
return clone*/
},
isVerticalNavMenuActive: {
get () { return this.$store.state.isVerticalNavMenuActive },
@@ -6,12 +6,14 @@ export default [
icon: 'HomeIcon',
i18n: 'داشبورد',
slug: "config",
permissionId:'home'
},
{
url: '/config',
icon: 'LayersIcon',
i18n: 'پیکربندی',
slug: 'config',
permissionId:'config'
},
{
url: "/proposal",
@@ -19,6 +21,7 @@ export default [
slug: "proposal",
icon: "AlignJustifyIcon",
i18n: "درخواست ها",
permissionId:'request'
},
{
url: "/personel",
@@ -26,6 +29,7 @@ export default [
slug: "personel",
icon: "AlignJustifyIcon",
i18n: "اطلاعات پرسنلی",
permissionId:'personnel'
},
{
url: "/permission",
@@ -33,6 +37,15 @@ export default [
slug: "permission",
icon: "AlignJustifyIcon",
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
// 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
+42 -5
View File
@@ -49,7 +49,10 @@ const router = new Router({
{
path: '/',
name: 'dashboard',
redirect: '/dashboard'
redirect: '/dashboard',
meta: {
rule: 'editor'
}
},
{
path: '/dashboard',
@@ -86,6 +89,24 @@ const router = new Router({
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',
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: '*',
redirect: '/pages/error-404'
@@ -125,21 +163,20 @@ router.beforeEach((to, from, next) => {
let isLogin = sessionStorage.getItem('accessToken');
//console.log("to.path ==> ", to.path);
if (
(
to.path === "/register/form" ||
to.path === "/auth/login" ||
to.path === "/auth/register" ||
to.path === "/pages/error-404" ||
to.path === "/pages/error-403" ||
to.path === "/auth/forgot-password"
)
) {
) {
/* if (isLogin) {
router.push({path: '/'});
}*/
return next();
}
if (!isLogin) {
else if (!isLogin) {
router.push({path: '/auth/login'});
return;
} else {
+26 -2
View File
@@ -1,13 +1,34 @@
import axios from '@/axios'
function getParents(keys) {
let parents = []
while (keys.length > 1) {
keys.pop()
parents.push(keys.join('.'))
}
return parents
}
const state = {
loading: false,
access_id:undefined
access_id:undefined,
permissions:undefined
};
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) {
try {
commit('LOADING', true);
@@ -33,6 +54,9 @@ const actions = {
}
const mutations = {
SetPermissions(state, payload) {
state.permissions = payload;
},
LOADING(state, payload) {
state.loading = payload;
},
+1 -1
View File
@@ -174,7 +174,7 @@ export default {
// if username update is not required
// just reload the page to get fresh data
// set new user data in localstorage
// set new-x-table user data in localstorage
if (!isUsernameUpdateRequired) {
router.push(router.currentRoute.query.to || '/')
commit('UPDATE_USER_INFO', result.user.providerData[0], {root: true})
+4 -4
View File
@@ -31,7 +31,7 @@ export default {
})
},
// fetchEventLabels({ commit }) {
// return new Promise((resolve, reject) => {
// return new-x-table Promise((resolve, reject) => {
// axios.get("/api/apps/calendar/labels")
// .then((response) => {
// commit('SET_LABELS', response.data)
@@ -61,14 +61,14 @@ export default {
})
}
// 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})
// .then((response) => {
// // Convert Date String to Date Object
// let event = response.data
// event.startDate = new Date(event.startDate)
// event.endDate = new Date(event.endDate)
// event.startDate = new-x-table Date(event.startDate)
// event.endDate = new-x-table Date(event.endDate)
// commit('UPDATE_EVENT', event)
// 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": "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 - 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: [
{ "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 {
// addItem({ commit }, item) {
// return new Promise((resolve, reject) => {
// return new-x-table Promise((resolve, reject) => {
// axios.post("/api/data-list/products/", {item: item})
// .then((response) => {
// 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', 'لسیت بسته ها');
tbl.add(new Xtc('title', 'نام بسته').filterText())
+2 -2
View File
@@ -271,13 +271,13 @@
const {data} = await axios.get('site/city');
console.log(data,'city')
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() {
// const {data} = await axios.get('site/city');
// 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) {
+2 -2
View File
@@ -25,8 +25,8 @@
<script>
// function getBase64(file) {
// return new Promise((resolve, reject) => {
// const reader = new FileReader();
// return new-x-table Promise((resolve, reject) => {
// const reader = new-x-table FileReader();
// reader.readAsDataURL(file);
// reader.onload = () => resolve(reader.result);
// reader.onerror = error => reject(error);
+1 -1
View File
@@ -21,7 +21,7 @@
<!-- Month Name -->
<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>
</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('total_adv', 'تعداد آگهی').filterNumber())
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'))
export default tbl;
@@ -134,7 +134,7 @@
label="Full Name:"
v-model="fullName"
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>
@@ -146,7 +146,7 @@
label="Mobile Number:"
v-model="mobileNum"
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>
@@ -162,7 +162,7 @@
label="Flat, House No:"
v-model="houseNum"
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 class="vx-col sm:w-1/2 w-full">
@@ -186,7 +186,7 @@
label="Town/City:"
v-model="city"
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 class="vx-col sm:w-1/2 w-full">
@@ -196,7 +196,7 @@
label="Pincode:"
v-model="pincode"
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>
@@ -211,7 +211,7 @@
label="State:"
v-model="state"
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 class="vx-col sm:w-1/2 w-full">
@@ -410,7 +410,7 @@ export default {
// TAB 2
submitNewAddressForm () {
return new Promise(() => {
this.$validator.validateAll('add-new-address').then(result => {
this.$validator.validateAll('add-new-x-table-address').then(result => {
if (result) {
// if form have no errors
this.$refs.checkoutWizard.nextTab()
+1 -1
View File
@@ -1,6 +1,6 @@
<!-- =========================================================================================
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
Author: Pixinvent
+1 -1
View File
@@ -1,6 +1,6 @@
<!-- =========================================================================================
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
Author: Pixinvent
+11 -2
View File
@@ -70,6 +70,8 @@
</template>
<script>
import axios from "../../http/axios";
export default {
data() {
return {
@@ -100,7 +102,7 @@
}
return true
},
loginJWT() {
async loginJWT() {
if (!this.checkLogin()) return
if (!this.validateForm) return
@@ -112,7 +114,7 @@
password: this.password
}
};
this.$store.dispatch('auth/loginJWT', payload)
await this.$store.dispatch('auth/loginJWT', payload)
.then(() => { this.$vs.loading.close() })
.catch(({code , response}) => {
let msg = 'نام کاربری یا رمز عبور اشتباه است';//this.$t('Error Login ');
@@ -122,6 +124,13 @@
this.$vs.loading.close()
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() {
if (!this.checkLogin()) return
+13 -13
View File
@@ -4,7 +4,7 @@
<a-card>
<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
v-if="inputCityVisible"
@@ -18,21 +18,21 @@
@blur="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-tag>
<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 }}
</a-tag>
</template>
<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-tab-pane>
<a-tab-pane key="2" tab="دسته های آموزشی">
<a-tab-pane key="2" tab="دسته های آموزشی" v-if="$getAccess('config.category')">
<input
v-if="inputVisible"
class="ant-input"
@@ -45,22 +45,22 @@
@blur="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-tag>
<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 }}
</a-tag>
</template>
<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-tab-pane>
<a-tab-pane key="1" tab="شغل ها">
<a-tab-pane key="1" tab="شغل ها" v-if="$getAccess('config.job')">
<div>
<!-- <a-card title="شهرهای محل همکاری" :bordered="true" >
<a-form :form="formCities" @submit="handleSubmitCities">
@@ -143,7 +143,7 @@
</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 >
<br/>
@@ -174,7 +174,7 @@
<template slot="operator" slot-scope="{text,record}">
<a-tooltip placement="bottomLeft">
<a-tooltip placement="bottomLeft" v-if="$getAccess('config.job.delete')">
<template slot="title">
<span>حذف</span>
</template>
@@ -190,7 +190,7 @@
</a-popconfirm>
</a-tooltip>
<a-button type="primary" @click="showEditModal(record)" >
<a-button type="primary" @click="showEditModal(record)" v-if="$getAccess('config.job.update')">
ویرایش
</a-button>
</template>
@@ -252,7 +252,7 @@
<script>
import * as TableCol from './jobTbl';
import XTable from "@/components/x-table/XTable";
import XTable from "@/components/new-x-table/XTable";
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', '');
tbl.add(new Xtc('title', 'عنوان شغل').noSort());
tbl.add(new Xtc('cities_str_slot', 'شهر های فعال در شغل').renderSlot('cities_str_slot').noSort());
tbl.add(new Xtc('is_visible', 'نمایش در ثبت نام').renderSlot('visible').noSort());
tbl.add(new Xtc('id', 'عملیات').renderSlot('operator').noSort())
const tbl = new XTbl('/job/table', '');
tbl.add(new Xtc('title', 'عنوان شغل').filterText());
tbl.add(new Xtc('cities_str_slot', 'شهر های فعال در شغل').renderSlot('cities_str_slot').filterText());
tbl.add(new Xtc('is_visible', 'نمایش در ثبت نام').renderSlot('visible').filterSwitch());
tbl.add(new Xtc('id', 'عملیات').renderSlot('operator'))
export default tbl;
+138 -78
View File
@@ -6,96 +6,141 @@
Author: Pixinvent
Author URL: http://www.themeforest.net/user/pixinvent
========================================================================================== -->
<template>
<div>
<!-- <div class="grid grid-cols-4 gap-4">
<div>
<a-card >
<span>تعداد کل پرسنل</span>
<h1>{{ model.total_personnel }}</h1>
<a-divider />
<span>ثبت نام شده در 30 روز گذشته {{ model.last_month_personnel }}</span>
<a-spin type="loading" :spinning="loading">
<a-card title="نرخ خروج" class="mb-10">
<div class="grid grid-cols-3 gap-10">
<a-card class="flex flex-col items-center bg-custom">
<h5 class="text-center">ماه گذشته</h5>
<div class="text-center">{{exit.past}}</div>
</a-card>
<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>
</div>
<div>
<a-card >
<span>تعداد کل درخواست ها</span>
<h1>{{ model.total_proposal }}</h1>
<a-divider />
<span>ثبت شده در 30 روز گذشته {{ model.last_month_proposal }}</span>
</a-card>
<a-card title="منابع انسانی" class="mb-10">
<h4>جنسیت</h4>
<div class="grid grid-cols-3 gap-10 mb-10">
<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_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>
</div>
<div>
<a-card >
<span>تعداد کل قراداد ها</span>
<h1>{{ model.total_contract }}</h1>
<a-divider />
<span>ثبت شده در 30 روز گذشته {{ model.last_month_contract }}</span>
</a-card>
<a-card class="mb-10">
<h4>تحصیلات</h4>
<a-table v-if="chart.index" class="mb-10" :data-source="chart.index.ed" :columns="[
{title: 'تعداد',dataIndex: 'count'},
{title: 'تحصیلات',dataIndex: 'level_str'},
{title: 'وضعیت مدرک',dataIndex: 'has_certificate_str'},]"/>
</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>
</div>-->
<br/>
<div class="grid grid-cols-2 gap-4">
<a-card class="mb-10">
<h5>نسبت استخدام به مصاحبه</h5>
<a-table v-if="chart.proposal" :data-source="chart.proposal.ratio_intrview_proposal" :columns="[
{title: 'تعداد',dataIndex: 'count'},
{title: 'شغل',dataIndex: 'title'},]"/>
</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>
<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>
</div>
<div>
<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>
</div>
<div>
<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>
</div>
<div>
<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>
</div>
<div>
<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>
</div>
<div>
<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>
</div>
<div>
<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>
</div>
</div>
</div>
</a-spin>
</template>
<script>
//import * as TableCol from "@/table/personelPerMonth";
import * as TableColcontractEndPastMonth from './personelEndContractPastmonthTbl';
import * as TableColcontractEndNextMonth from './personelEndContractNextmonthTbl';
import * as TableColcontractCurrentMonth from './personelEndContractCurrentmonthTbl';
import * as TableColPersonelPastMonth from './personelPastmonthTbl';
import * as TableColPersonelCurrentMonth from './personelCurrentmonthTbl';
import * as TableColcontractTerminationCurrentMonth from './contractTerminationCurrentMonthTbl';
import * as TableColcontractTerminationPastMonth from './contractTerminationPastMonthTbl';
import XTable from "@/components/x-table/XTable";
//import {ax} from "@/axios";
import contractEndPastMonth from './personelEndContractPastmonthTbl';
import contractEndNextMonth from './personelEndContractNextmonthTbl';
import contractEndCurrentMonth from './personelEndContractCurrentmonthTbl';
import PersonelPastMonth from './personelPastmonthTbl';
import PersonelCurrentMonth from './personelCurrentmonthTbl';
import contractTerminationCurrentMonth from './contractTerminationCurrentMonthTbl';
import contractTerminationPastMonth from './contractTerminationPastMonthTbl';
import workChart from './workChart';
import XTable from "@/components/new-x-table/XTable";
import axios from "@/axios"
export default {
data() {
return {
@@ -105,47 +150,62 @@
PersonelCurrentMonth,
PersonelPastMonth,
contractTerminationPastMonth,
contractTerminationCurrentMonth
//col:null,
//model:{},
//personelPerMonth:[],
contractTerminationCurrentMonth,
exit: {
past: undefined,
current: undefined,
next: undefined,
},
loading: true,
loadingCounter: 0,
chart: {
index:undefined,
proposal:undefined,
},
workChart,
}
},
components: {
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() {
this.contractEndPastMonth = TableColcontractEndPastMonth.default;
this.contractEndNextMonth = TableColcontractEndNextMonth.default;
this.contractEndCurrentMonth = TableColcontractCurrentMonth.default;
this.PersonelCurrentMonth=TableColPersonelCurrentMonth.default;
this.PersonelPastMonth= TableColPersonelPastMonth.default;
this.contractTerminationPastMonth=TableColcontractTerminationPastMonth.default;
this.contractTerminationCurrentMonth=TableColcontractTerminationCurrentMonth.default;
//console.log('111111111',axios.defaults.headers);
// try {
// 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');
// }
try {
this.loading = true
let {data} = await axios.get('chart')
this.chart.index = data
data = await axios.get('chart/proposal')
this.chart.proposal = data.data
this.loading = false
} catch (e) {
console.log(e,'eeeeeeeeeeeee')
}
},
}
</script>
<style lang="scss" >
.bg-custom{
background: #f5f5f542;
}
.ant-pagination
{
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', 'لیست پرسنل');
tbl.add(new Xtc('personnel.personel_id', 'کد پرسنلی').noSort());
tbl.add(new Xtc('personnel.name', 'نام و نام خانوادگی').noSort())
tbl.add(new Xtc('start_atj', 'تاریخ شروع قرارداد').noSort())
tbl.add(new Xtc('end_atj', 'تاریخ اتمام قرارداد').noSort())
const tbl = new XTbl('contractTerminationCurrentMonth/table', 'لیست پرسنل');
tbl.add(new Xtc('personnel.personel_id', 'کد پرسنلی').hidden().filterText());
tbl.add(new Xtc('personnel.name', 'نام و نام خانوادگی').filterText())
tbl.add(new Xtc('start_atj', 'تاریخ شروع قرارداد').filterDate().filterKey('start_at'))
tbl.add(new Xtc('end_atj', 'تاریخ اتمام قرارداد').filterDate().filterKey('end_at'))
tbl.add(new Xtc('reason_termination', 'علت فسخ قرارداد').filterText())
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', 'لیست پرسنل');
tbl.add(new Xtc('personnel.personel_id', 'کد پرسنلی').noSort());
tbl.add(new Xtc('personnel.name', 'نام و نام خانوادگی').noSort())
tbl.add(new Xtc('start_atj', 'تاریخ شروع قرارداد').noSort())
tbl.add(new Xtc('end_atj', 'تاریخ اتمام قرارداد').noSort())
const tbl = new XTbl('contractTerminationPastMonth/table', 'لیست پرسنل');
tbl.add(new Xtc('personnel.personel_id', 'کد پرسنلی').hidden().filterText());
tbl.add(new Xtc('personnel.name', 'نام و نام خانوادگی').filterText())
tbl.add(new Xtc('start_atj', 'تاریخ شروع قرارداد').filterDate().filterKey('start_at'))
tbl.add(new Xtc('end_atj', 'تاریخ اتمام قرارداد').filterDate().filterKey('end_at'))
tbl.add(new Xtc('reason_termination', 'علت فسخ قرارداد').filterText())
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', 'لیست پرسنل');
tbl.add(new Xtc('personel_id', 'کد پرسنلی').noSort());
tbl.add(new Xtc('name', 'نام و نام خانوادگی').noSort())
tbl.add(new Xtc('caj', 'تاریخ استخدام').noSort())
const tbl = new XTbl('personelCurrentMonth/table', 'لیست پرسنل');
tbl.add(new Xtc('personel_id', 'کد پرسنلی').filterText());
tbl.add(new Xtc('name', 'نام و نام خانوادگی').filterText())
tbl.add(new Xtc('caj', 'تاریخ استخدام').filterDate().filterKey('created_at'))
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', 'لیست پرسنل');
tbl.add(new Xtc('personnel.personel_id', 'کد پرسنلی').noSort());
tbl.add(new Xtc('personnel.name', 'نام و نام خانوادگی').noSort())
tbl.add(new Xtc('start_atj', 'تاریخ شروع قرارداد').noSort())
tbl.add(new Xtc('end_atj', 'تاریخ اتمام قرارداد').noSort())
const tbl = new XTbl('personelContactEndCurrentMonth/table', 'لیست پرسنل');
tbl.add(new Xtc('personnel.personel_id', 'کد پرسنلی').filterText());
tbl.add(new Xtc('personnel.name', 'نام و نام خانوادگی').filterText())
tbl.add(new Xtc('start_atj', 'تاریخ شروع قرارداد').filterDate().filterKey('start_at'))
tbl.add(new Xtc('end_atj', 'تاریخ اتمام قرارداد').filterDate().filterKey('end_at'))
tbl.add(new Xtc('date_work', 'مدت تصدی (روز)'))
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.name', 'نام و نام خانوادگی').noSort())
tbl.add(new Xtc('start_atj', 'تاریخ شروع قرارداد').noSort())
tbl.add(new Xtc('end_atj', 'تاریخ اتمام قرارداد').noSort())
tbl.add(new Xtc('date_work', 'مدت تصدی (روز)'))
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', 'لیست پرسنل');
tbl.add(new Xtc('personnel.personel_id', 'کد پرسنلی').noSort());
tbl.add(new Xtc('personnel.name', 'نام و نام خانوادگی').noSort())
tbl.add(new Xtc('start_atj', 'تاریخ شروع قرارداد').noSort())
tbl.add(new Xtc('end_atj', 'تاریخ اتمام قرارداد').noSort())
const tbl = new XTbl('personelContactEndPastMonth/table', 'لیست پرسنل اتمام قرارداد در ماه گذشته');
tbl.add(new Xtc('personnel.personel_id', 'کد پرسنلی').filterText());
tbl.add(new Xtc('personnel.name', 'نام و نام خانوادگی').filterText())
tbl.add(new Xtc('start_atj', 'تاریخ شروع قرارداد').filterDate().filterKey('start_at'))
tbl.add(new Xtc('end_atj', 'تاریخ اتمام قرارداد').filterDate().filterKey('end_at'))
tbl.add(new Xtc('date_work', 'مدت تصدی (روز)'))
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', 'لیست پرسنل');
tbl.add(new Xtc('personel_id', 'کد پرسنلی').noSort());
tbl.add(new Xtc('name', 'نام و نام خانوادگی').noSort())
tbl.add(new Xtc('caj', 'تاریخ استخدام').noSort())
const tbl = new XTbl('personelPastMonth/table', 'لیست پرسنل');
tbl.add(new Xtc('personel_id', 'کد پرسنلی').filterText());
tbl.add(new Xtc('name', 'نام و نام خانوادگی').filterText())
tbl.add(new Xtc('caj', 'تاریخ استخدام').filterDate().filterKey('created_at'))
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: '',
lastName: '',
email: '',
city: 'new-york',
city: 'new-x-table-york',
proposalTitle: '',
jobTitle: '',
textarea: '',
@@ -190,7 +190,7 @@ export default {
eventLocation: 'san-francisco',
status: 'plannning',
cityOptions: [
{text: 'New York', value:'new-york'},
{text: 'New York', value:'new-x-table-york'},
{text: 'Chicago', value:'chicago'},
{text: 'San Francisco', value:'san-francisco'},
{text: 'Boston', value:'boston'}
@@ -201,7 +201,7 @@ export default {
{text: 'Finished', value:'finished'}
],
LocationOptions: [
{text: 'New York', value:'new-york'},
{text: 'New York', value:'new-x-table-york'},
{text: 'Chicago', value:'chicago'},
{text: 'San Francisco', value:'san-francisco'},
{text: 'Boston', value:'boston'}
@@ -207,7 +207,7 @@ export default {
firstName: '',
lastName: '',
email: '',
city: 'new-york',
city: 'new-x-table-york',
proposalTitle: '',
jobTitle: '',
textarea: '',
@@ -215,7 +215,7 @@ export default {
eventLocation: 'san-francisco',
status: 'plannning',
cityOptions: [
{text: 'New York', value:'new-york'},
{text: 'New York', value:'new-x-table-york'},
{text: 'Chicago', value:'chicago'},
{text: 'San Francisco', value:'san-francisco'},
{text: 'Boston', value:'boston'}
@@ -226,7 +226,7 @@ export default {
{text: 'Finished', value:'finished'}
],
LocationOptions: [
{text: 'New York', value:'new-york'},
{text: 'New York', value:'new-x-table-york'},
{text: 'Chicago', value:'chicago'},
{text: 'San Francisco', value:'san-francisco'},
{text: 'Boston', value:'boston'}
@@ -332,7 +332,7 @@ export default {
firstName: '',
lastName: '',
email: '',
city: 'new-york',
city: 'new-x-table-york',
proposalTitle: '',
jobTitle: '',
textarea: '',
@@ -340,7 +340,7 @@ export default {
eventLocation: 'san-francisco',
status: 'plannning',
cityOptions: [
{ text: 'New York', value: 'new-york' },
{ text: 'New York', value: 'new-x-table-york' },
{ text: 'Chicago', value: 'chicago' },
{ text: 'San Francisco', value: 'san-francisco' },
{ text: 'Boston', value: 'boston' }
@@ -351,7 +351,7 @@ export default {
{ text: 'Finished', value: 'finished' }
],
LocationOptions: [
{ text: 'New York', value: 'new-york' },
{ text: 'New York', value: 'new-x-table-york' },
{ text: 'Chicago', value: 'chicago' },
{ text: 'San Francisco', value: 'san-francisco' },
{ text: 'Boston', value: 'boston' }
+74 -51
View File
@@ -6,21 +6,27 @@
<a-form-item label="سطح کاربر">
<a-select
v-decorator="['user_type', { initialValue:null,rules: [{ required: true, message: 'لطفاسطح دسترسی را انتخاب کنید' }] }]" @change="selectChange">
<a-select-option v-for="(item,key) in userTypes" :value="key">
{{ item }}
<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 v-if="showName">
<input class="ant-input"
v-decorator="['name', { rules: [{ required: true, message: 'لطفا مقدار را وارد کنید' }] }]"
autocomplete="off"
/>
</a-form-item>
<a-form-item label="نقش ها">
<a-tree
<a-tree style="direction: rtl"
v-model="rid"
checkable
default-expand-all
style="width: 100%"
:tree-data="treeData"
:replace-fields="replaceFields"
:auto-expand-parent="autoExpandParent"
/>
<!-- :replace-fields="replaceFields"-->
<!-- :auto-expand-parent="autoExpandParent"-->
</a-form-item>
</div>
<a-button type="primary" html-type="submit">
@@ -40,30 +46,49 @@
data() {
return {
form: this.$form.createForm(this, {name: 'coordinated'}),
expandedKeys:[],
value: ['0-0-0'],
treeData:undefined,
userTypes: undefined,
autoExpandParent: false,
// autoExpandParent: false,
rid: [],
replaceFields: {
/*replaceFields: {
children: 'child',
title: 'title'
},
keyId: null,
getDataUserType:null
},*/
// keyId: null,
getDataUserType:null,
showName:false,
loading:false
}
},
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() {
try{
const {data} = await axios.get('admin/permission/rid')
this.loading = true
const {data} = await axios.get('/permission')
this.treeData = Object.values(data)
}catch (e) {
console.log("errr:",e)
}finally {
this.loading = false
}
},
handleSubmit(e) {
@@ -71,65 +96,63 @@
this.form.validateFields(async (err, values) => {
if (!err) {
try {
this.loading = true
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()
setTimeout(()=>{
window.location.reload()
},500)
} catch (e) {
this.$ntSetError()
this.$ntSetError(e)
} finally {
this.loading =false
}
}
});
},
async getUserType() {
const {data} = await axios.get('admin/user/type')
this.userTypes = data
console.log(this.userTypes,'user_type')
},
loadSyncOptionChange(){
let storageId = localStorage.getItem("contestId");
storageId = this.keyId;
localStorage.setItem("contestId", storageId);
let test = localStorage.getItem("contestId");
test = JSON.parse(localStorage.getItem("contestId"));
localStorage.setItem("contestId", test);
if(test != null){
this.$store.dispatch('access/getOneId',test).then(()=>{
this.rid = this.data.rid
this.form.setFieldsValue(this.data)
})
}else{
return false
async selectChange(id){
try{
this.loading = true
if (id !== "new") {
this.showName = false
let {data: {rid}} = await axios.get(`/permission/show/${id}`)
this.rid = Object.values(rid)
}
else{
this.showName = true
}
}catch (e) {
console.log("errr:",e)
}finally {
this.loading = false
}
},
selectChange(id){
this.keyId = id
this.loadSyncOptionChange()
}
},
computed: {
loading() {
return this.$store.state.access.loading;
},
data(){
console.log(this.$store.state.access.access_id,'hgghgh')
return this.$store.state.access.access_id
}
},
mounted() {
this.getUserType()
this.getPermission()
this.keyId = 1
this.loadSyncOptionChange()
async mounted() {
this.form.setFieldsValue({user_type:1})
await this.selectChange(1)
},
async created(){
await this.getPermission()
await this.getUserTypes()
}
}
</script>
<style>
<!--<style>
[dir=rtl] .ant-tree-checkbox-inner::after{
right: 55%;
top: 35%;
@@ -147,4 +170,4 @@
-webkit-transform: rotate(-45deg) 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="در حال دریافت اطلاعات">
<div class="spin-content">
<a-card>
<a-button @click="$router.push('/register/personnel')" >
<a-button @click="$router.push('/register/personnel')" :disabled="!$getAccess('personnel.create')">
ثبت پرسنل جدید
</a-button>
<x-table ref="personelTbl" class="mt-4"
@@ -15,16 +15,27 @@
</a-button>
</template>
</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-tabs type="card">
<a-tab-pane :forceRender="true" key="1" tab="اطلاعات پایه">
<a-tabs type="card" :default-active-key="
$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="اطلاعات فردی">
<div class="grid grid-cols-2 gap-4">
<div>
<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;">
<img alt="example" style="width: 100%" :src="previewImage" />
</a-modal>
@@ -37,7 +48,8 @@
<!---->
<div class="dropbox">
<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"
:default-file-list="documentFileList"
@change="changeDocumentUpload"
@@ -194,7 +206,7 @@
<div>
<a-form-item label="شماره بیمه">
<input class="ant-input" style=""
<input class="ant-input"
v-decorator="['insurance_no']"/>
</a-form-item>
</div>
@@ -212,12 +224,27 @@
</a-form-item>
</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>
</a-card>
<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']" >
<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">
<a-form-item style="display: none">
<input type="hidden" class="ant-input" autocomplete="off" v-decorator="[`personal_details.family[${index}].id`]"/>
@@ -260,9 +287,9 @@
</a-card>
<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']">
<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">
<a-form-item style="display: none">
<input type="hidden" class="ant-input" autocomplete="off" v-decorator="[`personal_details.education[${index}].id`]"/>
@@ -305,9 +332,9 @@
</a-card>
<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']">
<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">
<a-form-item style="display: none">
<input type="hidden" class="ant-input" autocomplete="off" v-decorator="[`personal_details.traning[${index}].id`]"/>
@@ -330,9 +357,9 @@
</a-card>
<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']">
<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">
<a-form-item style="display: none">
<input type="hidden" class="ant-input" autocomplete="off" v-decorator="[`personal_details.jobs_history[${index}].id`]"/>
@@ -360,8 +387,35 @@
<a-divider />
</template>
</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 :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-item class="grid grid-cols-3" v-for="(item,index) in training" :key="index" >
<div>
@@ -371,6 +425,7 @@
<span>حذف</span>
</template>
<a-popconfirm
:disabled="!$getAccess('personnel.train.delete')"
placement="right"
style="z-index: 999999999999"
title="آیا می خواهید حذف کنید؟"
@@ -386,35 +441,70 @@
<div style="direction: rtl">عنوان گواهینامه : {{ item.title }}</div>
</a-list-item>
</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 :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-item class="grid grid-cols-4" v-for="(item,index) in contract" :key="index" >
<div>
<a-button v-if="!item.date_termination" class="mt-3 mr-3" @click="showTerminationModal(index)">فسخ قرارداد</a-button>
<a-button v-if="item.file" target="_blank" :href="item.file.storage" >دانلود پیوست</a-button>
<a-list-item class="grid grid-cols-4" style="direction: rtl" v-for="(item,index) in contract" :key="index">
<div class="col-span-3 grid grid-cols-3">
<div class="mt-5">حقوق پایه :
{{ 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>{{ item.salary }} : حقوق پایه</div>
<div>{{ item.end_atj }} : تاریخ خاتمه</div>
<div>{{ item.start_atj }} : تاریخ شروع</div>
<div>
<a-tooltip placement="bottomRight" >
<template slot="title">
<span>حذف</span>
</template>
<a-popconfirm
placement="right"
style="z-index: 999999999999"
title="آیا می خواهید حذف کنید؟"
ok-text="بله"
cancel-text="خیر"
@confirm="removeContract(item)" >
<a-button type="danger" class="mt-3 mr-3">حذف</a-button>
</a-popconfirm>
</a-tooltip>
<a-button style="width:20%" class="mr-3" @click="contractId=item.id;showContractPrint=true">چاپ</a-button>
<!-- <a-dropdown class="mt-3" v-if="item.id">
<div class="grid grid-cols-1" style="direction: ltr">
<div class="mt-5">
<a-button :disabled="!$getAccess('personnel.contract.termination')" v-if="!item.date_termination" class="ml-3" @click="showTerminationModal(index)">فسخ قرارداد</a-button>
<a-button :disabled="!$getAccess('personnel.contract.no.termination')" v-else class="ml-3" @click="removetermination(index)">لغو فسخ قرارداد</a-button>
<a-button :disabled="!$getAccess('personnel.contract')" v-if="item.file" class="ml-3" target="_blank" :href="item.file.storage" >دانلود پیوست</a-button>
</div>
<div class="mt-5">
<a-tooltip :disabled="!$getAccess('personnel.contract.delete')" placement="bottomRight" class="ml-3">
<template slot="title">
<span>حذف</span>
</template>
<a-popconfirm
placement="right"
style="z-index: 999999999999"
title="آیا می خواهید حذف کنید؟"
ok-text="بله"
cancel-text="خیر"
@confirm="removeContract(item)" >
<a-button type="danger" class="mt-3 mr-3">حذف</a-button>
</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-item key="1">
<a @click="showContractId=true">نوع 1</a>
@@ -451,31 +541,25 @@
</a-menu-item>&ndash;&gt;
</a-menu>
<a-button style="width: 33%" > چاپ <a-icon type="down" /> </a-button>
</a-dropdown>-->
</a-dropdown>&ndash;&gt;
</div>
<div>{{ item.worker_coupon }} : بن کارگری</div>
<div>{{ item.housing_allowance }} : کمک هزینه مسکن</div>
<div>{{ item.right_attraction }} : حق جذب</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>{{ item.promissory_number }} : شماره سفته</div>
<div>{{ item.promissory }} : مبلغ سفته</div>
<div>{{ item.right_guardianship }} : حق سرپرستی</div>
<div class="mt-5"></div>
<!-- <div> شماره قرارداد : <span>{{ item. }}</span> </div>-->
<!-- <div > : <span>{{ item.reason_termination }}</span> </div>-->
<!---->
<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>-->
&lt;!&ndash; <div> شماره قرارداد : <span>{{ item. }}</span> </div>&ndash;&gt;
&lt;!&ndash; <div > : <span>{{ item.reason_termination }}</span> </div>&ndash;&gt;
&lt;!&ndash;&ndash;&gt;-->
</a-list-item>
</a-list>
<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 :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>
<a-form-item>
@@ -496,8 +580,9 @@
</div>
</div>
<a-button type="primary" @click="savefromPersonel" class="mt-5" :disabled="checkPermission('5')">ویرایش</a-button>
</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>
<!--<a-form-item>
@@ -555,8 +640,9 @@
</div>
</div>
<a-button type="primary" @click="savefromPersonel" class="mt-5" :disabled="checkPermission('6')">ویرایش</a-button>
</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-item class="grid grid-cols-3" v-for="(item,index) in estimate" :key="index" >
<div>
@@ -564,7 +650,7 @@
<template slot="title">
<span>حذف</span>
</template>
<a-popconfirm
<a-popconfirm :disabled="!$getAccess('personnel.function.delete')"
placement="right"
style="z-index: 999999999999"
title="آیا می خواهید حذف کنید؟"
@@ -581,9 +667,10 @@
</a-list-item>
</a-list>
<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 :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-item class="grid grid-cols-3" v-for="(item,index) in writ" :key="index" >
<div>
@@ -592,7 +679,7 @@
<template slot="title">
<span>حذف</span>
</template>
<a-popconfirm
<a-popconfirm :disabled="!$getAccess('personnel.rule.delete')"
placement="right"
style="z-index: 999999999999"
title="آیا می خواهید حذف کنید؟"
@@ -610,7 +697,8 @@
<div style="direction: rtl">عنوان : {{ item.note }}</div>
</a-list-item>
</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-tabs>
</a-form>
@@ -665,7 +753,7 @@
</a-form>
</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" >
<div class="grid grid-cols-2 gap-4">
<div>
@@ -737,33 +825,71 @@
<div>
<a-form-item label="حق فرزند">
<input class="ant-input" v-decorator="['test1']" />
<input class="ant-input" v-decorator="['right_child']" />
</a-form-item>
</div>
<div>
<a-form-item label="پایه سنوات">
<input class="ant-input" v-decorator="['test2']" />
<input class="ant-input" v-decorator="['basic_years']" />
</a-form-item>
</div>
<div>
<a-form-item label="حق ماموریت">
<input class="ant-input" v-decorator="['test3']" />
<input class="ant-input" v-decorator="['right_mission']" />
</a-form-item>
</div>
<div>
<a-form-item label="حق شیفت">
<input class="ant-input" v-decorator="['test4']" />
<input class="ant-input" v-decorator="['right_shift']" />
</a-form-item>
</div>
<div>
<a-form-item label="پاداش مستمر">
<input class="ant-input" v-decorator="['test5']" />
<input class="ant-input" v-decorator="['reward']" />
</a-form-item>
</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>
<!--<a-form-item label="دلیل فسخ قرارداد">
<input class="ant-input" style="width: 100%" v-decorator="['reason_termination']" />
@@ -771,9 +897,28 @@
<a-form-item label="فایل">
<div class="dropbox">
<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"
:show-upload-list="false"
:file-list="contractFileList"
:before-upload="beforeUpload"
>
<p class="ant-upload-drag-icon">
@@ -785,10 +930,10 @@
<p class="ant-upload-hint">
تصویر که بارگذاری می کنید باید زیر ۵ مگابایت باشد.
</p>
</a-upload-dragger>
<div v-else>
</a-upload-dragger>-->
<!-- <div v-else>
<a-alert message="آپلود سند با موفقیت انجام شد." type="success" />
</div>
</div>-->
</div>
</a-form-item>
</a-form>
@@ -882,19 +1027,19 @@
</a-form>
</a-modal>
<a-modal okText="چاپ" :footer="null" cancelText="بستن" forceRender v-model="showContractPrint" title="شماره قرارداد" >
<!-- <a-form-item label="شماره قرارداد">
<!-- <a-modal okText="چاپ" :footer="null" cancelText="بستن" forceRender v-model="showContractPrint" title="شماره قرارداد" >
&lt;!&ndash; <a-form-item label="شماره قرارداد">
<input class="ant-input" autocomplete="off" v-model="contractNumber" />
</a-form-item>-->
</a-form-item>&ndash;&gt;
<a-form-item label="نوع قرارداد">
<a-select v-model="contractType" style="width: 120px" >
<a-select-option v-for="i in 10" :value="i">
{{ i }} نوع
<a-select-option v-for="(item,index) in contractTypes" :value="index">
{{ item }}
</a-select-option>
</a-select>
</a-form-item>
<a-button :href="`/back/public/api/personnel/print?id=${contractId}&type=${contractType}`" target="_blank">چاپ قرداد</a-button>
</a-modal>
<a-button :href="`http://hr.asco-intl.com/back/public/api/personnel/print?id=${contractId}&type=${contractType}`" target="_blank">چاپ قرداد</a-button>
</a-modal>-->
</a-card>
</div>
</a-spin>
@@ -904,8 +1049,8 @@
<script>
import * as TableCol from './personelTbl';
import XTable from "@/components/x-table/XTable";
import tbl from './personelTbl';
import XTable from "@/components/new-x-table/XTable";
import axios from "@/axios";
import moment from 'moment-jalaali'
//import Button from "@/views/components/vuesax/button/Button";
@@ -934,6 +1079,8 @@
},
data() {
return {
prsonalFileList:[],
file_id:undefined,
fileList: [],
documentFileList: [],
documents:[],
@@ -983,12 +1130,113 @@
activeContract:null,
contractId:'',
contractNumber:'',
contractType:1,
contractType:"1",
showContractPrint:false,
//profile_file:null,
// editing mode add
editContractFlag : false,
// editingContractIndex : undefined,
contractTypes:undefined,
work_units:[],
showName:false,
contractFileList:[]
}
},
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(){
const obj={
"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(){
this.fromPersonel.validateFields(async(err, values) => {
if (!err) {
try{
this.$vs.loading()
values.proposal.count_child = parseInt(values.proposal.count_child)
values.proposal.file_id = this.file_id
//console.log(values);
values.id=this.personel.id;
//values.profile_file=this.profile_file;
@@ -1183,7 +1447,37 @@
return item.uid;
});*/
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.$ntSet()
}catch (e) {
@@ -1191,6 +1485,14 @@
throw e
}finally {
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) {
e.preventDefault();
this.fromPersonel.validateFields(async(err, values) => {
@@ -1333,6 +1613,11 @@
this.writ=personelData.data.writ;
this.estimate=personelData.data.estimate;
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)
{
console.log(error);
@@ -1397,7 +1682,7 @@
//console.log(data,'dataaaa')
this.image_data = data
this.$message.success('آپلود سند با موفقیت انجام شد.');
this.isAlertUpload = true
// this.isAlertUpload = true
} catch (e) {
this.$message.error('خطا در بارگذاری اطلاعات');
} finally {
@@ -1406,7 +1691,7 @@
},
/*async uploadDocument(input) {
try {
let formData = new FormData();
let formData = new-x-table FormData();
formData.append("file", input.file);
const { data } = await axios.post("register/upload",formData, {'Content-Type': 'multipart/form-data'});
//console.log(data,'dataaaa')
@@ -1421,7 +1706,7 @@
},*/
/* async uploadImageProfile(input) {
try {
let formData = new FormData();
let formData = new-x-table FormData();
formData.append("file", input.file);
const { data } = await axios.post("register/upload",formData, {'Content-Type': 'multipart/form-data'});
//console.log(data,'dataaaa')
@@ -1453,8 +1738,12 @@
},
async showPersonal(record) {
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.personel = record;
const {data} = await axios.post('/proposal/details', {id:record.proposal_id})
record.personal_details = data;
this.$refs.fileUpload.fileList=[];
@@ -1473,8 +1762,8 @@
this.personalDetails=data;
this.getdata(record.id);
this.showPersonalModal=true;
this.personel = record;
this.$nextTick(()=>{
// console.log('fdsfgdf',record);
this.fromPersonel.setFieldsValue(record);
});
this.showLoading=false;
@@ -1483,7 +1772,35 @@
}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() {
},
@@ -1504,7 +1821,10 @@
}).catch((error) => {
this.$message.error('خطا در دریافت اطلاعات');
});
this.cols = TableCol.default;
this.cols = tbl;
this.getTypes()
this.getUnits()
}
}
</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('personel_id', 'کد پرسنلی').filterText())
tbl.add(new Xtc('insurance_no', 'شماره بیمه').filterText())
tbl.add(new Xtc('ncode', 'کد ملی').filterText())
tbl.add(new Xtc('caj', 'ثبت نام').filterDate().noSort())
tbl.add(new Xtc('uaj', 'به روز رسانی').filterText().noSort())
tbl.add(new Xtc('operator', 'عملیات').filterSwitch().renderSlot('operator').noSort())
tbl.add(new Xtc('caj', 'ثبت نام').filterDate().filterKey('created_at'))
tbl.add(new Xtc('uaj', 'به روز رسانی').filterDate().filterKey('updated_at'))
tbl.add(new Xtc('operator', 'عملیات').renderSlot('operator').noSort())
export default tbl;
+1 -1
View File
@@ -119,7 +119,7 @@
const {data} = await axios.get('site/city');
console.log(data,'city')
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() {
+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', 'لیست اسناد واریزی');
tbl.add(new Xtc('amount', 'مبلغ پرداختی').filterNumber());
+1 -1
View File
@@ -150,7 +150,7 @@
async getIpc() {
const {data} = await axios.get('admin/price/list/ipc');
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);
},
+1 -1
View File
@@ -122,7 +122,7 @@
const {data} = await axios.get('site/city');
console.log(data,'city')
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) {
+547 -9
View File
@@ -14,26 +14,25 @@
عملیات <a-icon type="down" />
</a>
<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-menu-item>
<a-menu-item>
<a-menu-item v-if="$getAccess('request.detail')">
<a href="javascript:;" @click="showDetails(text.record)">مشاهده اطلاعات</a>
</a-menu-item>
<a-menu-item>
<a-menu-item v-if="$getAccess('request.create')">
<a href="javascript:;" @click="showAddMosahebe(text.record.id)">ثبت مصاحبه</a>
</a-menu-item>
<a-menu-item>
<a-menu-item v-if="$getAccess('request.employment')">
<a href="javascript:;" @click="showConfirme(text.record.id)">استخدام</a>
</a-menu-item>
</a-menu>
</a-dropdown>
</template>
</x-table>
<a-modal :width="1000" v-model="showMosahebeModal" title="مشاهده مصاحبه ها" >
<div v-if="is_skeleton">
<ASkeleton/>
@@ -57,6 +56,9 @@
<a-descriptions-item label="وضعیت">
{{ item.sts_str }}
</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-card title="جزییات" >
<a-list >
@@ -92,7 +94,6 @@
</template>
</a-modal>
<a-modal force-render :width="990" v-model="showAddMosahebeModal" title="ثبت مصاحبه">
<template slot="footer">
<a-button v-if="current < 2" type="primary" @click="savefromMosahebe">
@@ -322,7 +323,6 @@
</div>
</a-modal>
<a-modal :width="800" v-model="showInformationModal" title="جزییات درخواست" >
<template slot="footer">
<a-button key="back" @click="showInformationModal=false">
@@ -414,14 +414,496 @@
<a-divider />
</template>
</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 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>
</div>
</template>
<script>
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 VuePersianDatetimePicker from "vue-persian-datetime-picker";
@@ -432,6 +914,8 @@
},
data() {
return {
prsonalFileList:[],
file_id:undefined,
showMosahebeModal:false,
showInformationModal:false,
showAddMosahebeModal:false,
@@ -445,10 +929,57 @@
row_id:null,
interview:[],
title_interview:['دانش تخصصی','تحصیلات مرتبط','تجربه کاری مرتبط','رفتار و شخصیت عمومی','ویژگی های اختصاصی شغل'],
is_skeleton:false
is_skeleton:false,
// requestEditMode:false,
editInterviewModel:false,
editingInterviewIndex:undefined
}
},
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)
{
this.showAddMosahebeModal=true;
@@ -526,6 +1057,13 @@
},
showDetails(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})
.then((res)=>{
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('ncode', 'کد ملی').filterText())
tbl.add(new Xtc('mobile', 'موبایل').filterText())
tbl.add(new Xtc('job_title', 'شغل').filterText())
tbl.add(new Xtc('for_cities', 'شهر').filterText().noSort())
tbl.add(new Xtc('caj', 'ثبت نام').filterDate().noSort())
tbl.add(new Xtc('uaj', 'به روز رسانی').filterText().noSort())
tbl.add(new Xtc('id', 'عملیات').filterSwitch().renderSlot('operator').noSort())
tbl.add(new Xtc('for_cities', 'شهر').filterText())
tbl.add(new Xtc('caj', 'ثبت نام').filterDate())
tbl.add(new Xtc('uaj', 'به روز رسانی').filterDate().filterKey('updated_at'))
tbl.add(new Xtc('id', 'عملیات').renderSlot('operator'))
/*tbl.addOpt()*/
export default tbl;
+49
View File
@@ -145,6 +145,17 @@
<a-form-item label="حقوق درخواستی">
<input class="ant-input" autocomplete="off" v-decorator="['requested_salary',{initialValue: null,rules: [{ required: true, message: 'حقوق درخواستی را وارد نمایید' }]}]" />
</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>
@@ -468,6 +479,31 @@
افزودن سابقه کاری
</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>
<br/>
@@ -708,6 +744,8 @@
},
data(){
return{
fileList: [],
file_id:undefined,
current: 0,
from: this.$form.createForm(this, {name: 'coordinated'}),
formEdu: this.$form.createForm(this, {name: 'coordinated'}),
@@ -750,6 +788,16 @@
}
},
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){
this.jobsList.splice(index,1);
//console.log(index);
@@ -792,6 +840,7 @@
values.model = this.formFirst.getFieldsValue();
values.birth_date = this.birth_day;
values.work = this.work;
values.file_id = this.file_id;
values.training = this.educational;
values.academic = this.edu;
values.family= this.family;
+48
View File
@@ -155,6 +155,16 @@
<a-form-item label="حقوق درخواستی">
<input class="ant-input" autocomplete="off" v-decorator="['requested_salary',{initialValue: null,rules: [{ required: true, message: 'حقوق درخواستی را وارد نمایید' }]}]" />
</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>
@@ -475,6 +485,31 @@
افزودن سابقه کاری
</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>
<br/>
@@ -713,6 +748,8 @@
},
data(){
return{
fileList:[],
file_id:undefined,
current: 0,
from: this.$form.createForm(this, {name: 'coordinated'}),
formEdu: this.$form.createForm(this, {name: 'coordinated'}),
@@ -755,6 +792,15 @@
}
},
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){
this.jobsList.splice(index,1);
//console.log(index);
@@ -799,6 +845,8 @@
values.training = this.educational;
values.academic = this.edu;
values.family= this.family;
values.file_id = this.file_id;
// values.count_child = parseInt(values.count_child);
await axios.post('register/personnel', values)
this.$ntSet();
// this.from.resetFields()
@@ -25,7 +25,7 @@ export default {
'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',
'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'
},
}
},
}
// devServer: {
// overlay: {