Compare commits

...
10 Commits
Author SHA1 Message Date
MahdiandCursor e78b2865c5 Centralize API base URL in config and add missing ant-design icons.
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-15 11:30:51 +03:30
Mahdi 7ea97b922b export excel 14041207 2026-02-26 14:30:36 +03:30
sedmedgh 1c188b1494 add name_en to proposal 1401-05-05 2022-07-27 11:51:00 +04:30
sedmedgh d220d5932e added count child 2022-07-24 13:22:09 +04:30
sedmedgh 178fcc9229 add edu to p[ersonel list 1401-04-21 2022-07-12 16:14:08 +04:30
sedmedgh 2cd167a00d add eidi and years to contract 2022-07-07 16:39:37 +04:30
sedmedgh 3df2be1b6f change field 2022-06-30 17:54:34 +04:30
sedmedgh bf84c0c122 seperate personel components 1401-04-02 2022-06-23 17:15:17 +04:30
sedmedgh 14cec27f46 fixed multiple upload bug 1401-03-25 2022-06-15 16:12:39 +04:30
sedmedgh cc88bc287f multi file upload 1401-03-24 2022-06-14 20:40:57 +04:30
27 changed files with 2774 additions and 1024 deletions
+2 -1
View File
@@ -2,7 +2,8 @@
## Project setup
```
npm install -g npm@6
node -v 14.16.0 npm -v 6
npm install -g npm@6
npm install
```
+9 -8
View File
@@ -3,24 +3,24 @@
"version": "5.0.1",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
"serve": "node ./node_modules/@vue/cli-service/bin/vue-cli-service.js serve",
"build": "node ./node_modules/@vue/cli-service/bin/vue-cli-service.js build",
"lint": "node ./node_modules/@vue/cli-service/bin/vue-cli-service.js lint"
},
"dependencies": {
"@ant-design/icons": "^2.1.1",
"@chenfengyuan/vue-countdown": "^1.1.2",
"ag-grid-community": "^21.0.1",
"ag-grid-vue": "^21.0.1",
"algoliasearch": "^3.33.0",
"ant-design-vue": "^1.7.2",
"apexcharts": "^3.6.12",
"apexcharts": "^3.54.1",
"auth0-js": "^9.10.4",
"axios": "^0.19.2",
"axios-mock-adapter": "^1.19.0",
"chart.js": "^2.8.0",
"core-js": "2.6.5",
"echarts": "^4.2.1",
"eslint": "^7.14.0",
"eslint-loader": "^2.2.1",
"file-saver": "2.0.1",
"firebase": "^7.13.2",
@@ -36,7 +36,7 @@
"prismjs": "^1.16.0",
"vee-validate": "^2.2.15",
"vue": "^2.6.10",
"vue-acl": "4.0.7",
"vue-acl": "^4.1.10",
"vue-apexcharts": "^1.3.5",
"vue-awesome-swiper": "^3.1.3",
"vue-backtotop": "^1.6.1",
@@ -53,7 +53,6 @@
"vue-perfect-scrollbar": "^0.1.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",
"vue-router": "^3.0.6",
"vue-select": "^3.1.0",
@@ -77,11 +76,13 @@
"@vue/cli-plugin-babel": "^3.7.0",
"@vue/cli-plugin-eslint": "^3.9.1",
"@vue/cli-service": "^3.7.0",
"node-sass": "^4.12.0",
"eslint": "^6.8.0",
"node-sass": "^4.14.1",
"purgecss": "^1.3.0",
"sass-loader": "^7.1.0",
"script-loader": "0.7.2",
"tailwindcss": "^1.0.1",
"vue-property-decorator": "^7.2.0",
"vue-template-compiler": "^2.6.10"
},
"description": "## Project setup ``` npm install ```",
+2 -1
View File
@@ -1,6 +1,7 @@
import axios from 'axios'
import router from '@/router'
import store from '@/store/store'
import { API_BASE_URL } from '@/config'
const domain = ""
// import themeConfig from '@/../themeConfig.js'
@@ -20,7 +21,7 @@ const headers = {
var myax= new axios.create({
baseURL: 'http://hr.asco-intl.com:2020/kernel/api/',
baseURL: `${API_BASE_URL}/`,
headers,
// domain
})
+2 -2
View File
@@ -40,7 +40,7 @@ function getBase64(file) {
});
}
//import themeConfig from "../../../../themeConfig";
import { API_BASE_URL } from '@/config'
export default {
name: 'UploadInput',
@@ -69,7 +69,7 @@ export default {
},
data() {
return {
url: 'http://hr.asco-intl.com:2020/kernel/api/register/upload',
url: `${API_BASE_URL}/register/upload`,
previewVisible: false,
previewImage: '',
fileList: [],
+13
View File
@@ -0,0 +1,13 @@
<template>
</template>
<script>
export default {
name: "dragbleUpload"
}
</script>
<style scoped>
</style>
+11
View File
@@ -22,6 +22,9 @@
</div>
</div>
</AButton>
<AButton v-if="showExport" class="mr-2" type="primary" @click="$emit('export')">
{{ exportLabel }}
</AButton>
</div>
<div class="filter-backdrop p-4" v-if="visibleDownload">
<feather-icon icon="XIcon" @click="toggleVisibleDownload"
@@ -200,6 +203,14 @@ export default {
props: {
model: {
type: XTbl.default
},
showExport: {
type: Boolean,
default: false
},
exportLabel: {
type: String,
default: 'خروجی اکسل'
}
},
data() {
+3
View File
@@ -0,0 +1,3 @@
// آدرس API — برای تغییر دامنه یا پورت فقط همین فایل را ویرایش کنید
export const API_HOST = 'http://hr.asco-intl.com:2020'
export const API_BASE_URL = `${API_HOST}/kernel/api`
+2 -1
View File
@@ -16,5 +16,6 @@ Vue.use(VueI18n)
export default new VueI18n({
locale: 'en', // set default locale
messages: i18nData
messages: i18nData,
silentTranslationWarn: true
})
+2
View File
@@ -23,8 +23,10 @@ Vue.use(Antd)
// axios
import axios from './axios.js'
import { API_BASE_URL } from '@/config'
Vue.prototype.$http = axios
Vue.prototype.$apiBase = API_BASE_URL
// API Calls
/*import './http/requests'*/
+3 -3
View File
@@ -10,7 +10,7 @@ export const printWindow = (innerHTML = document.getElementById('printContent')
// Open the print window
const WinPrint = window.open('', '', 'left=0,top=0,width=800,height=900,toolbar=0,scrollbars=0,status=0')
WinPrint.document.write('<!DOCTYPE html><html><head>' +
WinPrint.document.write('<!DOCTYPE html><html dir="rtl"><head>' +
stylesHtml +
'<title>چاپ اطلاعات</title>' +
'</head><body>' +
@@ -20,8 +20,8 @@ export const printWindow = (innerHTML = document.getElementById('printContent')
WinPrint.document.close()
WinPrint.focus()
setTimeout(() => {
// WinPrint.print()
// WinPrint.close()
WinPrint.print()
WinPrint.close()
}, 600)
}
+6 -3
View File
@@ -1,12 +1,13 @@
import XTbl, {Xtc} from '../../components/new-x-table/index';
import store from '@/store/store'
import { API_BASE_URL } from '@/config'
let unitsFilter = {}
store.state.contract.units.map((x) => {
unitsFilter[x.id] = x.value
})
let contractTypes = store.state.contract.contractTypes
const tbl = new XTbl('http://hr.asco-intl.com:2020/kernel/api/personnel/contract/table', 'لیست قرارداد ها');
const tbl = new XTbl(`${API_BASE_URL}/personnel/contract/table`, 'لیست قرارداد ها');
tbl.add(new Xtc('personnel.proposal.name', 'نام پرسنل').filterText())
tbl.add(new Xtc('personnel.proposal.ncode', 'کد ملی').filterText())
tbl.add(new Xtc('personnel_id', 'کد پرسنلی').filterText())
@@ -29,11 +30,13 @@ tbl.add(new Xtc('contract_number', 'شماره قرارداد').filterText().hid
tbl.add(new Xtc('basic_years', 'پایه سنوات').filterText().hidden())
tbl.add(new Xtc('reward', 'پاداش مستمر').filterText().hidden())
tbl.add(new Xtc('city_workplace', 'محل خدمت').filterText().hidden())
tbl.add(new Xtc('eidi', 'عیدی').filterNumber().hidden())
tbl.add(new Xtc('years', 'علی الحساب سنوات').filterNumber().hidden())
tbl.add(new Xtc('personnel.gender', 'جنسیت').filterSelect({1: 'مرد', 2: 'زن'}).filterKey('personnel.gender').hidden().renderSlot('gender'))
tbl.add(new Xtc('type_str', 'نوع قرارداد').hidden().filterKey('type').filterSelect(contractTypes))
tbl.add(new Xtc('work_unit', 'واحد کار').hidden().renderSlot('work_unit').filterSelect(unitsFilter))
tbl.add(new Xtc('start_at', 'تاریخ شروع قراداد').filterDate().filterKey('start_at').hidden().renderSlot('start_at'))
tbl.add(new Xtc('end_at', 'تاریخ پایان قراداد').filterDate().filterKey('end_at').hidden().renderSlot('end_at'))
tbl.add(new Xtc('start_atj', 'تاریخ شروع قراداد').filterDate().filterKey('start_at').hidden())
tbl.add(new Xtc('end_atj', 'تاریخ پایان قراداد').filterDate().filterKey('end_at').hidden())
tbl.add(new Xtc('reason_termination', 'دلیل فسخ قرارداد').filterText().hidden())
tbl.add(new Xtc('date_termination', 'تاریخ فسخ قرارداد').filterDate().filterKey('date_termination').hidden())
+2 -2
View File
@@ -105,14 +105,14 @@
<div>
<a-card title="لیست پرسنل استخدام شده در ماه گذشته">
<x-table :model="PersonelPastMonth">
<template slot="created_at" slot-scope="text">{{text | jdate}}</template>
<!-- <template slot="created_at" slot-scope="text">{{text | jdate}}</template>-->
</x-table>
</a-card>
</div>
<div>
<a-card title="لیست پرسنل استخدام شده در ماه جاری">
<x-table :model="PersonelCurrentMonth">
<template slot="created_at" slot-scope="text">{{text | jdate}}</template>
<!-- <template slot="created_at" slot-scope="text">{{text | jdate}}</template>-->
</x-table>
</a-card>
</div>
@@ -3,5 +3,5 @@ import XTbl, {Xtc} from '../../components/new-x-table/index';
const tbl = new XTbl('personelCurrentMonth/table', 'لیست پرسنل');
tbl.add(new Xtc('id', 'کد پرسنلی').filterText());
tbl.add(new Xtc('name', 'نام و نام خانوادگی').filterText())
tbl.add(new Xtc('created_at', 'تاریخ استخدام').filterDate().filterKey('created_at').renderSlot('created_at'))
tbl.add(new Xtc('contract_first.start_atj', 'تاریخ استخدام').filterDate().filterKey('created_at'))
export default tbl;
+1 -1
View File
@@ -3,5 +3,5 @@ import XTbl, {Xtc} from '../../components/new-x-table/index';
const tbl = new XTbl('personelPastMonth/table', 'لیست پرسنل');
tbl.add(new Xtc('id', 'کد پرسنلی').filterText());
tbl.add(new Xtc('name', 'نام و نام خانوادگی').filterText())
tbl.add(new Xtc('created_at', 'تاریخ استخدام').filterDate().filterKey('created_at').renderSlot('created_at'))
tbl.add(new Xtc('contract_first.start_atj', 'تاریخ استخدام').filterDate().filterKey('created_at'))
export default tbl;
+105 -6
View File
@@ -1,7 +1,9 @@
<template>
<div>
<x-table ref="personelTbl" class="mt-4"
:model="cols">
:model="cols"
:show-export="true"
@export="exportExcel">
<template slot="operator" slot-scope="text,record">
<div class="flex">
<a-button class="ml-2" type="primary" @click="showPersonal(text.record)">
@@ -90,7 +92,7 @@
<div class="dropbox">
<a-upload-dragger
:disabled="!$getAccess('personnel.basic.update')"
action="http://hr.asco-intl.com:2020/kernel/api/register/upload"
:action="$apiBase + '/register/upload'"
:file-list="documentFileList"
:default-file-list="documentFileList"
@change="changeDocumentUpload"
@@ -488,7 +490,7 @@
<a-upload-dragger
:disabled="!$getAccess('personnel.basic.update')"
:multiple="false"
action="http://hr.asco-intl.com:2020/kernel/api/register/upload"
:action="$apiBase + '/register/upload'"
:file-list="prsonalFileList"
:default-file-list="prsonalFileList"
@change="fileUpload"
@@ -620,7 +622,7 @@
<a-button type="danger" class="mt-3 mr-3">حذف</a-button>
</a-popconfirm>
</a-tooltip>
&lt;!&ndash; <a-button :disabled="!$getAccess('personnel.contract.print')" class="ml-3" :href="`http://hr.asco-intl.com:2020/kernel/api/personnel/print?id=${item.id}&type=${item.type?item.type:1}`" target="_blank">چاپ قرداد</a-button>&ndash;&gt;
&lt;!&ndash; <a-button :disabled="!$getAccess('personnel.contract.print')" class="ml-3" :href="`${$apiBase}/personnel/print?id=${item.id}&type=${item.type?item.type:1}`" target="_blank">چاپ قرداد</a-button>&ndash;&gt;
<a-dropdown class="mb-4">
<a-menu slot="overlay" @click="printContract($event,item.id)">
<a-menu-item v-for="(subItem,subIndex) in contractTypes" :key="subIndex">{{ subItem }}
@@ -1088,7 +1090,7 @@
<a-upload-dragger
:disabled="!$getAccess('personnel.basic.update')"
:multiple="false"
action="http://hr.asco-intl.com:2020/kernel/api/register/upload"
:action="$apiBase + '/register/upload'"
:file-list="contractFileList"
:default-file-list="contractFileList"
@change="contractFileUpload"
@@ -1241,6 +1243,8 @@
import cols from './personelTbl';
import XTable from "@/components/new-x-table/XTable";
import axios from "@/axios";
import { export_json_to_excel } from "@/vendor/Export2Excel";
import moment from 'moment-jalaali';
/*import VuePersianDatetimePicker from 'vue-persian-datetime-picker';
import themeConfig from '@/../themeConfig.js'
import SingleUploadInput from '@/components/SingleUploadInput'*/
@@ -1334,7 +1338,102 @@ export default {
}
},
methods: {
formatJdate(val) {
if (val) {
return moment(val).format('jYYYY/jMM/jDD');
}
return '';
},
async exportExcel() {
const table = this.$refs.personelTbl;
if (!table || !table.model) {
this.$message && this.$message.warning('جدول در دسترس نیست.');
return;
}
const query = table.query || {};
const total = query.total || 0;
if (total === 0) {
this.$message && this.$message.warning('رکوردی برای خروجی اکسل وجود ندارد.');
return;
}
const visibleCols = table.visibleCols || [];
const filters = (query.filters || []).filter(
(item) => item.value || ['null', 'nn'].includes(item.op) || item.value === 0
);
const body = {
...query,
limit: total,
page: 1,
filters,
select: visibleCols.map((i) => i.key),
titles: visibleCols.reduce((acc, i) => {
acc[i.key] = i.title;
return acc;
}, {}),
report_title: table.model.title
};
let rows = [];
try {
const { data } = await axios.post(table.model.url, body);
rows = data.rows || [];
} catch (e) {
this.$message && this.$message.error('خطا در دریافت اطلاعات.');
return;
}
if (!rows.length) {
this.$message && this.$message.warning('رکوردی برای خروجی اکسل وجود ندارد.');
return;
}
const header = [
'نام و نام خانوادگی',
'نام پدر',
'شماره شناسنامه',
'کد ملی',
'تاریخ تولد',
'محل تولد',
'محل صدور',
'وضعیت تاهل',
'تعداد فرزندان',
'وضعیت نظام وظیفه',
'تحصیلات',
'تاریخ ثبت نام',
'شماره همراه',
'آدرس'
];
const data = rows.map((r) => {
const p = r.proposal || {};
const birthDate = p.birth_date || r.birth_date;
const createdAt = r.created_at;
return [
r.name || '',
p.father_name || '',
p.iden_id || '',
r.ncode || '',
this.formatJdate(birthDate),
p.birth_place || '',
p.iden_place || '',
p.marriage_sts_str || '',
(p.count_child !== undefined && p.count_child !== null ? p.count_child : ''),
p.military_sts_str || '',
r.last_education_str || '',
this.formatJdate(createdAt),
p.mobile || '',
p.address || ''
];
});
export_json_to_excel({
header,
data,
filename: 'personnel'
});
},
async deletePersonnel(id) {
try {
this.showLoading = true
@@ -1402,7 +1501,7 @@ export default {
this.flags.gender = event.target.value
},
printContract(event, id) {
window.open(`http://hr.asco-intl.com:2020/kernel/api/personnel/print?type=${event.key}&id=${id}`, '_blank').focus()
window.open(`${this.$apiBase}/personnel/print?type=${event.key}&id=${id}`, '_blank').focus()
},
contractFileUpload({fileList, event, file}) {
if (file.response && file.response.id) {
+570
View File
@@ -0,0 +1,570 @@
<template>
<a-spin :spinning="loading" tip="در حال ثبت اطلاعات">
<a-list :locale="{emptyText:'رکوردی وجود ندارد.'}" bordered item-layout="horizontal">
<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 | jtjdate }}
</div>
<div class="mt-5">تاریخ شروع :
{{ item.start_atj | jtjdate }}
</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"> علی الحساب سنوات :
{{ item.years }}
</div>
<div class="mt-5"> عیدی :
{{ item.eidi }}
</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 | jtjdate }}
</div>
<div class="mt-5">نوع قرارداد :
{{ item.type_str }}
</div>
<div class="mt-5">محل خدمت :
{{ item.cnt.value }}
</div>
</div>
<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" type="primary" :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"
title="آیا می خواهید حذف کنید؟"
ok-text="بله"
cancel-text="خیر"
@confirm="removeContract(item)">
<a-button type="danger" class="mt-3 mr-3">حذف</a-button>
</a-popconfirm>
</a-tooltip>
<a-dropdown class="mb-4">
<a-menu slot="overlay" @click="printContract($event,item.id)">
<a-menu-item v-for="(subItem,subIndex) in contractTypes" :key="subIndex">{{ subItem }}
</a-menu-item>
</a-menu>
<a-button style="margin-left: 8px"> چاپ قرارداد
<a-icon type="down"/>
</a-button>
</a-dropdown>
<a-button class="ml-3" :disabled="!$getAccess('personnel.contract.update')"
@click="openEditingContractModal(item,index)">ویرایش
</a-button>
</div>
</div>
</a-list-item>
</a-list>
<a-button class="mt-3 ml-2" @click="showAddContract = true">افزودن ردیف</a-button>
<!-- modal add edit -->
<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>
<a-form-item label="تاریخ شروع">
<input v-if="!contractModel.start_at" class="hidden" autocomplete="off"
v-decorator="['note',{ rules:[{ required: true, message: 'تاریخ را وارد نمایید' }] }]"/>
<date-picker v-model="contractModel.start_at"/>
</a-form-item>
</div>
<div>
<a-form-item label="تاریخ خاتمه">
<input v-if="!contractModel.end_at" class="hidden" autocomplete="off"
v-decorator="['note',{ rules:[{ required: true, message: 'تاریخ را وارد نمایید' }] }]"/>
<date-picker v-model="contractModel.end_at"/>
</a-form-item>
</div>
</div>
<div class="grid grid-cols-3 gap-4">
<div>
<a-form-item label="حقوق پایه">
<input class="ant-input"
v-decorator="['salary', { initialValue: 0 },{ rules: [{pattern:/^[0-9]+$/,message:'مقدار وارد شده باید عددی باشد.'},] }]"/>
</a-form-item>
</div>
<div>
<a-form-item label="بن کارگری">
<input class="ant-input"
v-decorator="['worker_coupon', { initialValue: 0 },{ rules: [{pattern:/^[0-9]+$/,message:'مقدار وارد شده باید عددی باشد.'},] }]"/>
</a-form-item>
</div>
<div>
<a-form-item label="کمک هزینه مسکن">
<input class="ant-input"
v-decorator="['housing_allowance', { initialValue: 0 },{ rules: [{pattern:/^[0-9]+$/,message:'مقدار وارد شده باید عددی باشد.'},] }]"/>
</a-form-item>
</div>
<div>
<a-form-item label="حق جذب">
<input class="ant-input"
v-decorator="['right_attraction', { initialValue: 0 },{ rules: [{pattern:/^[0-9]+$/,message:'مقدار وارد شده باید عددی باشد.'},] }]"/>
</a-form-item>
</div>
<div>
<a-form-item label="حق سرپرستی">
<input class="ant-input"
v-decorator="['right_guardianship', { initialValue: 0 },{ rules: [{pattern:/^[0-9]+$/,message:'مقدار وارد شده باید عددی باشد.'},] }]"/>
</a-form-item>
<a-form-item label="عیدی">
<input class="ant-input"
v-decorator="['eidi', { initialValue: 0 },{ rules: [{pattern:/^[0-9]+$/,message:'مقدار وارد شده باید عددی باشد.'},] }]"/>
</a-form-item>
<a-form-item label="علی الحساب سنوات">
<input class="ant-input"
v-decorator="['years', { initialValue: 0 },{ rules: [{pattern:/^[0-9]+$/,message:'مقدار وارد شده باید عددی باشد.'},] }]"/>
</a-form-item>
</div>
<div>
<a-form-item label="مبلغ سفته">
<input class="ant-input"
v-decorator="['promissory', { initialValue: 0 },{ rules: [{pattern:/^[0-9]+$/,message:'مقدار وارد شده باید عددی باشد.'},] }]"/>
</a-form-item>
</div>
<div>
<a-form-item label="شماره سفته">
<input class="ant-input"
v-decorator="['promissory_number',{ rules: [{pattern:/^[0-9]+$/,message:'مقدار وارد شده باید عددی باشد.'},] }]"/>
</a-form-item>
</div>
<div>
<a-form-item label="شماره قرارداد">
<input class="ant-input"
v-decorator="['contract_number']"/>
</a-form-item>
</div>
<div>
<a-form-item label="حق فرزند">
<input class="ant-input"
v-decorator="['right_child',{ rules: [{pattern:/^[0-9]+$/,message:'مقدار وارد شده باید عددی باشد.'},] }]"/>
</a-form-item>
</div>
<div>
<a-form-item label="پایه سنوات">
<input class="ant-input"
v-decorator="['basic_years',{ rules: [{pattern:/^[0-9]+$/,message:'مقدار وارد شده باید عددی باشد.'},] }]"/>
</a-form-item>
</div>
<div>
<a-form-item label="حق ماموریت">
<input class="ant-input"
v-decorator="['right_mission',{ rules: [{pattern:/^[0-9]+$/,message:'مقدار وارد شده باید عددی باشد.'},] }]"/>
</a-form-item>
</div>
<div>
<a-form-item label="حق شیفت">
<input class="ant-input"
v-decorator="['right_shift',{ rules: [{pattern:/^[0-9]+$/,message:'مقدار وارد شده باید عددی باشد.'},] }]"/>
</a-form-item>
</div>
<div>
<a-form-item label="پاداش مستمر">
<input class="ant-input"
v-decorator="['reward',{ rules: [{pattern:/^[0-9]+$/,message:'مقدار وارد شده باید عددی باشد.'},] }]"/>
</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',{ rules: [{pattern:/^[0-9]+$/,message:'مقدار وارد شده باید عددی باشد.'},] }]"/>
</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']" />
</a-form-item>-->
<a-form-item label="فایل">
<div class="dropbox">
<a-upload-dragger
:disabled="!$getAccess('personnel.basic.update')"
:multiple="false"
:action="$apiBase + '/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"
:file-list="contractFileList"
:before-upload="beforeUpload"
>
<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 v-else>
<a-alert message="آپلود سند با موفقیت انجام شد." type="success" />
</div>-->
</div>
</a-form-item>
</a-form>
</a-modal>
<!-- modal add edit -->
<!-- modal termision -->
<a-modal okText="ثبت" cancelText="بستن" forceRender v-model="showTermination" title="فسخ قرارداد"
@ok="addtermination">
<a-form :form="formTermination">
<a-form-item label="تاریخ فسخ قرارداد">
<input v-if="!date_termination" class="hidden" autocomplete="off"
v-decorator="['note',{ rules:[{ required: true, message: 'تاریخ را وارد نمایید' }] }]"/>
<date-picker v-model="date_termination"/>
</a-form-item>
<a-form-item label="دلیل فسخ قرارداد">
<input class="ant-input" autocomplete="off" v-decorator="['reason_termination']"/>
</a-form-item>
</a-form>
</a-modal>
<!-- modal termision -->
<!-- <a-button type="primary" @click="saveData" class="mt-5" :disabled="disabled"
v-if="contract && contract.length > 0">
ویرایش
</a-button>-->
</a-spin>
</template>
<script>
import axios from "@/axios";
export default {
name: "contracts",
props: {
contract:{
type: Array,
required: true
}
},
data() {
return{
showAddContract: false,
loading: false,
fromContract: this.$form.createForm(this, {name: 'fromContract'}),
formTermination: this.$form.createForm(this, {name: 'formTermination'}),
editContractFlag: false,
showTermination: false,
activeContract: null,
date_termination: null,
contractModel: {
start_at: '',
end_at: '',
salary: 0,
worker_coupon: 0,
housing_allowance: 0,
right_attraction: 0,
right_guardianship: 0,
reason_termination: ''
},
contractFileList: [],
work_units: [],
showName: false,
contractTypes: undefined,
contractType: "1",
}
},
methods: {
async getUnits() {
try {
let {data} = await axios.get('/personnel/unit/unit')
await this.$store.commit('personnel/setUnits', data)
data.push
({
id: "new",
value: "افزودن واحد جدید"
})
this.work_units = data
} catch (e) {
console.log(e)
}
},
selectChange(id) {
if (id == "new") {
this.showName = true
}
else if(this.showName == true) this.showName = false
},
async getTypes() {
try {
const {data} = await axios.get('/personnel/type/type')
this.contractTypes = data
await this.$store.commit('personnel/setContractTypes', data)
} catch (e) {
console.log(e)
}
},
showTerminationModal(index) {
this.activeContract = index;
this.showTermination = true;
},
async removetermination(index) {
try {
let contractList = this.contract
contractList[index].date_termination = null
contractList[index].datej_termination = null
contractList[index].reason_termination = null
await this.saveData(contractList);
} catch (e) {
this.$ntSetError()
console.log(e)
} finally {
await this.getPersonal()
}
},
async removeContract(item) {
if (item.id) {
try {
await axios.post('/personnel/remove-contract', {id: item.id});
await this.$emit('update')
} catch (e) {
console.log(e);
}
} else {
const index = this.contract.indexOf(item);
this.contract.splice(index, 1);
}
},
printContract(event, id) {
window.open(`${this.$apiBase}/personnel/print?type=${event.key}&id=${id}`, '_blank').focus()
},
openEditingContractModal(item, index) {
// console.log(this.contractTypes)
// 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 = item.end_at
this.contractModel.start_at = item.start_at
// console.log("item:::::::::::::",item)
// console.log(item)
this.fromContract.setFieldsValue(item)
},
async detectEditMode(e) {
await this.addContract(e)
if (this.editContractFlag) this.editContractFlag = false
},
addContract(e) {
e.preventDefault();
this.fromContract.validateFields((err, values) => {
if (!err) {
let contractList = this.contract
if (this.image_data) {
values.contract_file_id = this.image_data.id
}
if (values.work_unit == "new") {
values.work_unit = values.work_unit_name
}
if (this.editContractFlag) {
values.start_at = this.contractModel.start_at
values.end_at = this.contractModel.end_at
contractList[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 = this.contractModel.start_at
values.end_at = this.contractModel.end_at
contractList.push(values);
}
// console.log("data", this.contract[this.editingContractIndex])
this.saveData(contractList);
this.showAddContract = false;
this.fromContract.resetFields();
this.image_data = null;
// console.log('contract',this.contract);
} else {
this.$ntGetError('اطلاعات را به صورت کامل وارد کنید');
}
});
},
contractFileUpload({fileList, event, file}) {
if (file.response && file.response.id) {
this.image_data = file.response
}
this.contractFileList = fileList;
},
contractFileRemove() {
this.image_data = null
},
async addtermination(e) {
e.preventDefault();
this.formTermination.validateFields(async (err, values) => {
if (!err) {
try {
let contractList = this.contract
contractList[this.activeContract].date_termination = this.date_termination //values.date_termination;
contractList[this.activeContract].reason_termination = values.reason_termination;
this.showTermination = false;
this.formTermination.resetFields();
await this.saveData(contractList);
} catch (e) {
this.$ntSetError()
console.log(e)
} finally {
this.$refs.personelTbl.fetch();
}
} else {
this.$ntGetError('اطلاعات را به صورت کامل وارد کنید');
}
});
},
async saveData(contractList) {
if (contractList) {
try {
this.loading = true
console.log('contractList',contractList)
let values = {
contract: contractList,
id: this.id
}
if (!this.$getAccess('personnel.contract')) {
values.contract = this.contract
}
await axios.post(`/personnel/contract/update`, values)
this.$ntSet()
} catch (e) {
this.$ntSetError()
console.log(e)
} finally {
await this.$emit('update')
this.loading = false
this.showAddContract = false
}
}
else {
this.$ntGetError('اطلاعات را به صورت کامل وارد کنید');
}
},
},
computed: {
id() {
return this.$route.params.id
}
},
async created() {
await this.getTypes()
await this.getUnits()
},
}
</script>
<style scoped>
</style>
+129
View File
@@ -0,0 +1,129 @@
<template>
<a-spin :spinning="loading" tip="در حال ثبت اطلاعات">
<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>
<a-tooltip placement="bottomRight">
<template slot="title">
<span>حذف</span>
</template>
<a-popconfirm :disabled="!$getAccess('personnel.function.delete')"
placement="right"
title="آیا می خواهید حذف کنید؟"
ok-text="بله"
cancel-text="خیر"
@confirm="removeEstimate(item)">
<a-button type="danger" class="mr-3">حذف</a-button>
</a-popconfirm>
</a-tooltip>
</div>
<div>نمره : {{ item.score }}</div>
<div> برنامه توسعه دوره : <span>{{ item.note }} </span></div>
</a-list-item>
</a-list>
<br/>
<a-button class="ml-2" :disabled="!$getAccess('personnel.function.create')"
@click="showAddPerformance=true">افزودن ردیف
</a-button>
<a-modal @ok="savefromPerformance" okText="ایجاد" forceRender cancelText="بستن" v-model="showAddPerformance"
title="افزودن ارزیابی عملکرد">
<a-form :form="fromPerformance">
<a-form-item label="نمره">
<a-input-number autocomplete="off" :min="0" :max="20"
v-decorator="['score',{ rules:[{ required: true, message: 'وارد کردن الزامی است' }] }]"/>
</a-form-item>
<a-form-item label="برنامه توسعه دوره">
<input class="ant-input" autocomplete="off"
v-decorator="['note',{ rules:[{ required: false, message: 'وارد کردن الزامی است' }] }]"/>
</a-form-item>
</a-form>
</a-modal>
</a-spin>
</template>
<script>
import axios from "@/axios";
export default {
name: "estimate",
props: {
estimate: Array
},
data() {
return {
loading: false,
showAddPerformance: false,
fromPerformance: this.$form.createForm(this, {name: 'fromPerformance'}),
}
},
computed: {
id() {
return this.$route.params.id
}
},
methods: {
async removeEstimate(item) {
if (item.id) {
try {
await axios.post('/personnel/remove-estimate', {id: item.id});
this.$emit('update')
} catch (e) {
console.log(e);
}
} else {
const index = this.estimate.indexOf(item);
this.estimate.splice(index, 1);
}
},
savefromPerformance(e) {
e.preventDefault();
this.fromPerformance.validateFields(async (err, values) => {
if (!err) {
let estimate = this.estimate
estimate.push(values);
this.showAddPerformance = false;
this.$message.success('اطلاعات با موفقیت ثبت شد');
this.fromPerformance.resetFields();
await this.saveData(estimate);
} else {
this.$ntGetError('اطلاعات را به صورت کامل وارد کنید');
}
});
},
async saveData(estimate) {
if (estimate) {
try {
this.loading = true
let values = {
estimate: estimate,
id: this.id
}
values.documents = this.documents;
if (!this.$getAccess('personnel.train')) {
values.estimate = this.estimate
}
await axios.post('/personnel/estimate/update', values);
this.$emit('update')
this.$ntSet()
} catch (e) {
this.$ntSetError()
console.log(e)
} finally {
this.loading = false
this.showAddPerformance = false
}
} else {
this.$ntGetError('اطلاعات را به صورت کامل وارد کنید');
}
},
}
}
</script>
<style scoped>
</style>
@@ -0,0 +1,253 @@
<template>
<div id="printContent" class="hidden">
<a-card v-if="personel && personel.proposal" 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="نام و نام خانوادگی">
{{ personel.name }}
</a-form-item>
<a-form-item label="نام انگلیسی">
{{ personel.name_en }}
</a-form-item>
<a-form-item label="کدملی">
{{ personel.ncode }}
</a-form-item>
<a-form-item label="شماره پرسنلی">
{{ personel.personel_id }}
</a-form-item>
<a-form-item label="موبایل">
{{ personel.proposal.mobile }}
</a-form-item>
<a-form-item label="شهر متقاضی شغل">
{{ personel.proposal.for_cities.join(' , ') }}
</a-form-item>
<a-form-item label="شغل متقاضی">
{{ personel.proposal.job_title }}
</a-form-item>
<a-form-item label="واحد کار متقاضی">
{{ personel.unit }}
</a-form-item>
<a-form-item label="نام پدر">
{{ personel.proposal.father_name }}
</a-form-item>
<a-form-item label="تاریخ تولد">
{{ personelBirthDate | jdate }}
</a-form-item>
<a-form-item label="شماره شناسنامه">
{{ personel.proposal.iden_id }}
</a-form-item>
<a-form-item label="سریال شناسنامه">
{{ personel.proposal.iden_serial }}
</a-form-item>
<a-form-item label="محل صدور">
{{ personel.proposal.iden_place }}
</a-form-item>
<a-form-item label="محل تولد">
{{ personel.proposal.birth_place }}
</a-form-item>
<a-form-item label="ایمیل">
{{ personel.proposal.email }}
</a-form-item>
<a-form-item label="تلفن ثابت">
{{ personel.proposal.phone }}
</a-form-item>
<a-form-item label="حقوق درخواستی">
{{ personel.proposal.requested_salary }}
</a-form-item>
<a-form-item label="جنسیت">
<a-radio-group v-model="personel.proposal.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-model="personel.proposal.marriage_sts">
<a-radio :value="2">
متاهل
</a-radio>
<a-radio :value="1">
مجرد
</a-radio>
</a-radio-group>
</a-form-item>
<a-form-item label="وضعیت مسکن">
<a-radio-group v-model="personel.proposal.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">
{{ personel.proposal.address }}
</a-form-item>
<a-form-item label="تلفن ضروری">
{{ personel.proposal.phone_emergency }}
</a-form-item>
<a-form-item label="نام فرد">
{{ personel.proposal.phone_emergency_name }}
</a-form-item>
<a-form-item label="نسبت">
{{ personel.proposal.phone_emergency_related }}
</a-form-item>
<a-form-item label="شماره کارت">
{{ personel.bank_card_number }}
</a-form-item>
<a-form-item label="شماره حساب">
{{ personel.bank_account }}
</a-form-item>
<a-form-item label="شماره بیمه">
{{ personel.insurance_no }}
</a-form-item>
<a-form-item label="وضعیت بیمه">
<a-radio-group v-model="personel.insurance_sts">
<a-radio :value="-1">
ندارد
</a-radio>
<a-radio :value="1">
دارد
</a-radio>
</a-radio-group>
</a-form-item>
<a-form-item label="تعداد فرزند">
{{ personel.proposal.count_child }}
</a-form-item>
<a-form-item label="وضعیت نظام وظیفه">
{{
{1: 'معاف', 2: 'مشمول', 3: 'پایان خدمت'}[personel.proposal.military_sts]
}}
</a-form-item>
</div>
</a-card>
<a-card v-if="personalDetails && personalDetails.family" title="اطلاعات خانوادگی" class="mt-5">
<template v-for="(item,index) in personalDetails.family">
<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="شناسه">
{{ personalDetails.family[index].id }}
</a-form-item>
<a-form-item label="نام">
{{ personalDetails.family[index].name }}
</a-form-item>
<a-form-item label="نسبت">
{{ personalDetails.family[index].relation }}
</a-form-item>
<a-form-item label="مقطع">
{{
personalDetails.family[index].edu_level ?
grade[personalDetails.family[index].edu_level.toString()] :
null
}}
</a-form-item>
<a-form-item label="رشته تحصیلی">
{{ personalDetails.family[index].edu_title }}
</a-form-item>
<a-form-item label="شغل">
{{ personalDetails.family[index].job }}
</a-form-item>
</div>
<a-divider/>
</template>
</a-card>
<a-card v-if="personalDetails && personalDetails.education" title="اطلاعات تحصیلی" class="mt-5">
<template v-for="(item,index) in personalDetails.education">
<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="شناسه">
{{ personalDetails.education[index].id }}
</a-form-item>
<a-form-item label="مقطع">
{{
personalDetails.education[index].level ?
grade[personalDetails.education[index].level.toString()] :
null
}}
</a-form-item>
<a-form-item label="دانشگاه">
{{ personalDetails.education[index].university }}
</a-form-item>
<a-form-item label="رشته تحصیلی">
{{ personalDetails.education[index].title }}
</a-form-item>
<a-form-item label="گرایش">
{{ personalDetails.education[index].trend }}
</a-form-item>
<a-form-item label="سال شروع">
{{ personalDetails.education[index].start_at }}
</a-form-item>
<a-form-item label="سال خاتمه">
{{ personalDetails.education[index].end_at }}
</a-form-item>
</div>
<a-divider/>
</template>
</a-card>
<a-card v-if="personalDetails && personalDetails.traning" title="سوابق آموزشی" class="mt-5">
<template v-for="(item,index) in personalDetails.traning">
<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="شناسه">
{{ personalDetails.traning[index].id }}
</a-form-item>
<a-form-item label="مرکز برگزاری">
{{ personalDetails.traning[index].university }}
</a-form-item>
<a-form-item label="عنوان دوره ">
{{ personalDetails.traning[index].title }}
</a-form-item>
<a-form-item label="سال">
{{ personalDetails.traning[index].start_at }}
</a-form-item>
<a-form-item label="امکان ارائه گواهینامه دارم">
<a-checkbox v-model="personalDetails.traning[index].has_certificate"/>
</a-form-item>
</div>
<a-divider/>
</template>
</a-card>
<a-card v-if="personalDetails && personalDetails.jobs_history" title="سوابق کاری" class="mt-5">
<template v-for="(item,index) in personalDetails.jobs_history">
<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="شناسه">
{{ personalDetails.jobs_history[index].id }}
</a-form-item>
<a-form-item label="نام سازمان ">
{{ personalDetails.jobs_history[index].university }}
</a-form-item>
<a-form-item label="عنوان شغل">
{{ personalDetails.jobs_history[index].title }}
</a-form-item>
<a-form-item label="دلیل خاتمه">
{{ personalDetails.jobs_history[index].note }}
</a-form-item>
<a-form-item label="سال شروع">
{{ personalDetails.jobs_history[index].start_at }}
</a-form-item>
<a-form-item label="سال خاتمه">
{{ personalDetails.jobs_history[index].end_at }}
</a-form-item>
</div>
<a-divider/>
</template>
</a-card>
</div>
</template>
<script>
export default {
name: "printContent",
props: {
personel: Object,
personalDetails: Object,
grade: Object,
personelBirthDate: [String,null]
}
}
</script>
<style scoped>
</style>
+193
View File
@@ -0,0 +1,193 @@
<template>
<a-spin :spinning="loading" tip="در حال ثبت اطلاعات">
<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>
<a-button v-if="item.file" target="_blank" type="primary"
:disabled="!$getAccess('personnel.train.download')" :href="item.file.storage"
class="mr-3">دانلود پیوست
</a-button>
<a-tooltip placement="bottomRight">
<template slot="title">
<span>حذف</span>
</template>
<a-popconfirm
:disabled="!$getAccess('personnel.train.delete')"
placement="right"
title="آیا می خواهید حذف کنید؟"
ok-text="بله"
cancel-text="خیر"
@confirm="removeEdu(item)"
>
<a-button type="danger" class="mr-3">حذف</a-button>
</a-popconfirm>
</a-tooltip>
</div>
<div><span>دسته گواهینامه :</span> {{ item.type }}</div>
<div style="direction: rtl">عنوان گواهینامه : {{ item.title }}</div>
</a-list-item>
</a-list>
<a-button :disabled="!$getAccess('personnel.train.create')" class="mt-4 ml-2"
@click="showAddEducationalInformation=true;isAlertUpload = false">افزودن ردیف
</a-button>
<a-modal forceRender okText="ایجاد" cancelText="بستن" v-model="showAddEducationalInformation"
title="افزودن اطلاعات آموزشی" @ok="addEdu">
<a-form :form="fromEducationalInformation">
<div class="grid sm:grid-cols-1 md:grid-cols-2 md:gap-4 lg:grid-cols-2 lg:gap-4">
<a-form-item label="دسته گواهینامه">
<!--<input class="ant-input" autocomplete="off" v-decorator="['type',{rules: [{ required: true, message: 'وارد کردن شغل الزامی است' }]}]"/>-->
<a-select style="width: 100%"
v-decorator="['type',{rules: [{ required: true, message: 'وارد کردن شغل الزامی است' }]}]">
<a-select-option v-for="(item,index) in category" :value="item">
{{ item }}
</a-select-option>
<!--<a-select-option value="lucy">
Lucy
</a-select-option>
<a-select-option value="disabled" disabled>
Disabled
</a-select-option>
<a-select-option value="Yiminghe">
yiminghe
</a-select-option>-->
</a-select>
</a-form-item>
<a-form-item label="عنوان گواهینامه">
<input class="ant-input" autocomplete="off"
v-decorator="['title',{rules: [{ required: true, message: 'وارد کردن شغل الزامی است' }]}]"/>
</a-form-item>
</div>
<a-form-item label="فایل">
<div class="dropbox">
<a-upload-dragger
v-if="!isAlertUpload"
:customRequest="uploadImage"
:show-upload-list="false"
:before-upload="beforeUpload">
<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 v-else>
<a-alert message="آپلود سند با موفقیت انجام شد." type="success"/>
</div>
</div>
</a-form-item>
</a-form>
</a-modal>
</a-spin>
</template>
<script>
import axios from "@/axios";
export default {
name: "training",
props: {
training: Array,
uploadImage: Function,
beforeUpload: Function,
value: [Object,null]
},
data() {
return {
loading: false,
showAddEducationalInformation: false,
isAlertUpload: false,
fromEducationalInformation: this.$form.createForm(this, {name: 'cordinate'}),
category: [],
}
},
computed: {
id() {
return this.$route.params.id
}
},
methods: {
async removeEdu(item) {
if (item.id) {
try {
await axios.post('/personnel/remove-traning', {id: item.id});
this.$emit('update')
} catch (e) {
console.log(e);
}
} else {
const index = this.training.indexOf(item);
this.training.splice(index, 1);
}
},
addEdu(e) {
e.preventDefault();
this.fromEducationalInformation.validateFields(async(err, values) => {
if (!err) {
let training = this.training
if (this.value) {
values.file_id = this.value.id
values.file = this.value.storage
}
training.push(values);
this.showAddEducationalInformation = false;
this.$message.success('اطلاعات با موفقیت ثبت شد');
this.fromEducationalInformation.resetFields();
this.$emit('input',null)
await this.saveData(training);
} else {
this.$ntGetError('اطلاعات را به صورت کامل وارد کنید');
}
});
},
async saveData(training) {
if (training) {
try {
this.loading = true
let values = {
training: training,
id: this.id
}
values.documents = this.documents;
if (!this.$getAccess('personnel.train')) {
values.training = this.training
}
await axios.post('/personnel/training/update', values);
this.$emit('update')
this.$ntSet()
} catch (e) {
this.$ntSetError()
console.log(e)
} finally {
this.loading = false
this.showAddEducationalInformation = false
}
}
else {
this.$ntGetError('اطلاعات را به صورت کامل وارد کنید');
}
},
},
async created() {
try {
this.loading = true
const {data} = await axios.get('/get-category')
this.category = data
} catch (e) {
this.$message.error('خطا در دریافت اطلاعات');
} finally {
this.loading = false
}
}
}
</script>
<style scoped>
</style>
+185
View File
@@ -0,0 +1,185 @@
<template>
<a-spin :spinning="loading" tip="در حال ثبت اطلاعات">
<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>
<a-tooltip placement="bottomRight">
<a-button v-if="item.file" target="_blank" type="primary" :href="item.file.storage" class="mr-3">
دانلود
پیوست
</a-button>
<template slot="title">
<span>حذف</span>
</template>
<a-popconfirm :disabled="!$getAccess('personnel.rule.delete')"
placement="right"
title="آیا می خواهید حذف کنید؟"
ok-text="بله"
cancel-text="خیر"
@confirm="removeDocs(item)"
>
<a-button type="danger" class="mr-3">حذف</a-button>
</a-popconfirm>
</a-tooltip>
</div>
<div style="direction: rtl"><span>نوع :</span><span>{{ item.type_str }}</span></div>
<div style="direction: rtl">عنوان : {{ item.note }}</div>
</a-list-item>
</a-list>
<a-button :disabled="!$getAccess('personnel.rule.create')" class="mt-4 ml-2"
@click="showAddDocument=true;isAlertUpload = false">افزودن ردیف
</a-button>
<a-modal okText="ایجاد" cancelText="بستن" forceRender v-model="showAddDocument" title="افزودن سند"
@ok="addDocs">
<a-form :form="fromDocs">
<a-form-item label="نوع" has-feedback>
<a-select
v-decorator="['type']"
placeholder="انتخاب نوع"
>
<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>
</a-form-item>
<a-form-item label="شرح">
<input class="ant-input" style="width:100%"
autocomplete="off"
v-decorator="['note']"
/>
</a-form-item>
<a-form-item label="فایل">
<div class="dropbox">
<a-upload-dragger
v-if="!isAlertUpload"
:customRequest="uploadImage"
:show-upload-list="false"
:before-upload="beforeUpload"
>
<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 v-else>
<a-alert message="آپلود سند با موفقیت انجام شد." type="success"/>
</div>
</div>
</a-form-item>
</a-form>
</a-modal>
</a-spin>
</template>
<script>
import axios from "@/axios";
export default {
name: "writs",
props: {
writ: Array,
uploadImage: Function,
beforeUpload: Function,
value: [Object,null]
},
data() {
return {
loading: false,
showAddDocument: false,
isAlertUpload: false,
fromDocs: this.$form.createForm(this, {name: 'fromDocs'}),
}
},
computed: {
id() {
return this.$route.params.id
}
},
methods: {
async removeDocs(item) {
if (item.id) {
try {
await axios.post('/personnel/remove-writ', {id: item.id});
await this.$emit('update')
} catch (e) {
console.log(e);
}
} else {
const index = this.writ.indexOf(item);
this.writ.splice(index, 1);
}
},
addDocs(e) {
e.preventDefault();
this.fromDocs.validateFields(async(err, values) => {
if (!err) {
let writ = this.writ
if (this.value) {
values.file_id = this.value.id
values.file = this.value.storage
}
writ.push(values);
this.showAddDocument = false;
this.$message.success('اطلاعات با موفقیت ثبت شد');
this.fromDocs.resetFields();
this.$emit('input',null)
await this.saveData(writ);
} else {
this.$ntGetError('اطلاعات را به صورت کامل وارد کنید');
}
});
},
async saveData(writ) {
if (writ) {
try {
this.loading = true
let values = {
writ: writ,
id: this.id
}
values.documents = this.documents;
if (!this.$getAccess('personnel.train')) {
values.writ = this.writ
}
await axios.post('/personnel/writ/update', values);
this.$emit('update')
this.$ntSet()
} catch (e) {
this.$ntSetError()
console.log(e)
} finally {
this.loading = false
this.showAddEducationalInformation = false
}
}
else {
this.$ntGetError('اطلاعات را به صورت کامل وارد کنید');
}
},
},
}
</script>
<style scoped>
</style>
+4 -2
View File
@@ -1,6 +1,7 @@
import XTbl, {Xtc} from '../../components/new-x-table/index';
import { API_BASE_URL } from '@/config'
const tbl = new XTbl('http://hr.asco-intl.com:2020/kernel/api/personnel/table', 'لیست پرسنل');
const tbl = new XTbl(`${API_BASE_URL}/personnel/table`, 'لیست پرسنل');
tbl.add(new Xtc('id', 'کد پرسنلی').filterText())
tbl.add(new Xtc('name', 'نام و نام خانوادگی').filterText());
tbl.add(new Xtc('insurance_no', 'شماره بیمه').filterText())
@@ -13,8 +14,9 @@ tbl.add(new Xtc('unit', 'واحد کار').filterText())
tbl.add(new Xtc('birth_date', 'تاریخ تولد').filterDate().filterKey('birth_date').hidden().renderSlot('birth_date'))
tbl.add(new Xtc('proposal.gender', 'جنسیت').filterSelect({1: 'مرد', 2: 'زن'}).filterKey('proposal.gender').hidden().renderSlot('gender'))
tbl.add(new Xtc('last_education_str', 'مقطع تحصیلی'))
tbl.add(new Xtc('caj', 'ثبت نام').filterDate().filterKey('created_at'))
tbl.add(new Xtc('uaj', 'به روز رسانی').filterDate().filterKey('updated_at'))
tbl.add(new Xtc('uaj', 'به روز رسانی').filterDate().filterKey('updated_at').hidden())
tbl.add(new Xtc('operator', 'عملیات').renderSlot('operator').noSort())
export default tbl;
File diff suppressed because it is too large Load Diff
+23 -13
View File
@@ -337,15 +337,17 @@
<a-card :title="personalInformation.name" :bordered="true">
<div class="grid grid-cols-3 gap-4">
<div>نام و نام خانوادگی : {{ personalInformation.name }}</div>
<div>نام لاتین : {{ personalInformation.name_en }}</div>
<div>کد ملی : {{ personalInformation.ncode }}</div>
<div>موبایل : {{ personalInformation.mobile }}</div>
<div>تاریخ ثبت نام : {{ personalInformation.caj }}</div>
<div>تاریخ به روز رسانی : {{ personalInformation.uaj }}</div>
<div>شغل متقاضی : {{ personalInformation.job_title }}</div>
<div>نام پدر : {{ personalInformation.father_name }}</div>
<div>تاریخ تولد : {{ personalInformation.birth_date }}</div>
<div>تاریخ تولد : {{ personalInformation.birth_date | jdate }}</div>
<div>جنسیت : {{ personalInformation.gender_str }}</div>
<div>وضعیت تاهل : {{ personalInformation.marriage_sts_str }}</div>
<div>تعداد فرزند : {{ personalInformation.count_child }}</div>
<div>شماره شناسنامه : {{ personalInformation.iden_id }}</div>
<div>سریال شناسنامه : {{ personalInformation.iden_serial }}</div>
<div>محل صدور : {{ personalInformation.iden_place }}</div>
@@ -423,7 +425,7 @@
<a-upload-dragger
:disabled="true"
:multiple="false"
action="http://hr.asco-intl.com:2020/kernel/api/register/upload"
:action="$apiBase + '/register/upload'"
:file-list="prsonalFileList"
:default-file-list="prsonalFileList"
@change="fileUpload"
@@ -967,7 +969,7 @@ export default {
data() {
return {
prsonalFileList: [],
file_id: undefined,
file_ids: [],
showMosahebeModal: false,
showInformationModal: false,
showAddMosahebeModal: false,
@@ -1041,12 +1043,13 @@ export default {
},
fileUpload({fileList, event, file}) {
if (file.response && file.response.id) {
this.file_id = file.response.id;
this.file_ids = fileList.map(x => x.id || x.response.id)
}
this.prsonalFileList = fileList;
},
fileRemove() {
this.file_id = null
/*if (file.response && file.response.id) {
this.file_id = file.response.id;
}
this.prsonalFileList = fileList;*/
},
showAddMosahebe(id) {
this.showAddMosahebeModal = true;
@@ -1130,12 +1133,19 @@ export default {
this.current--;
},
async showDetails(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}
)
console.clear()
console.log(record)
if (record.file_ids) {
this.file_ids = record.file_ids
this.prsonalFileList = record.file_list.map(x => {
return {
uid: x.id,
id: x.id,
name: x.filename,
status: 'done',
url: x.storage
}
})
}
try {
this.loading = true
+2 -1
View File
@@ -1,6 +1,7 @@
import XTbl, {Xtc} from '../../components/new-x-table/index';
import { API_BASE_URL } from '@/config'
const tbl = new XTbl('http://hr.asco-intl.com:2020/kernel/api/proposal/table', 'لیست درخواست ها');
const tbl = new XTbl(`${API_BASE_URL}/proposal/table`, 'لیست درخواست ها');
tbl.add(new Xtc('name', 'نام و نام خانوادگی').filterText());
tbl.add(new Xtc('ncode', 'کد ملی').filterText())
tbl.add(new Xtc('mobile', 'موبایل').filterText())
+10 -12
View File
@@ -270,7 +270,7 @@
<a-row>
<a-form-item label="تلفن ثابت">
<input class="ant-input" autocomplete="off"
v-decorator="['phone',{initialValue: null,rules: [{ required: true, message: 'تلفن ثابت را وارد نمایید' },{pattern:/^((\+98|0098|98|0)\d{2})?\d{8}$/g,message:'تلفن وارد شده معتبر نیست.'}]}]">
v-decorator="['phone',{initialValue: null,rules: [{ required: false, message: 'تلفن ثابت را وارد نمایید' },{pattern:/^((\+98|0098|98|0)\d{2})?\d{8}$/g,message:'تلفن وارد شده معتبر نیست.'}]}]">
<!--<feather-icon style="direction: ltr !important;" icon="PhoneIcon" slot="addonAfter" class="pt-1" svgClasses="w-5 h-5" />-->
<!-- </a-input>-->
</a-form-item>
@@ -285,7 +285,7 @@
<a-row>
<a-form-item label="تلفن ضروری">
<input class="ant-input" style="direction: rtl !important;"
v-decorator="['phone_emergency',{initialValue: null,rules: [{ required: true, message: 'تلفن ضروری را وارد نمایید' },{pattern:/^[0-9]+$/,message:'مقدار وارد شده باید عددی باشد.'},{max: 11,message:'تلفن ضروری حد اکثر 11 رقم است'}]}]">
v-decorator="['phone_emergency',{initialValue: null,rules: [{ required: false, message: 'تلفن ضروری را وارد نمایید' },{pattern:/^[0-9]+$/,message:'مقدار وارد شده باید عددی باشد.'},{max: 11,message:'تلفن ضروری حد اکثر 11 رقم است'}]}]">
<!-- <feather-icon style="direction: ltr !important;" icon="MailIcon" slot="addonAfter" class="pt-1" svgClasses="w-5 h-5" />-->
<!-- </a-input>-->
</a-form-item>
@@ -524,12 +524,11 @@
<div class="dropbox">
<a-upload-dragger
:multiple="false"
action="http://hr.asco-intl.com:2020/kernel/api/register/upload"
:multiple="true"
:action="$apiBase + '/register/upload'"
:file-list="fileList"
:default-file-list="fileList"
@change="changeDocumentUpload"
:remove="handleRemoveDocument"
>
<p class="ant-upload-drag-icon">
<a-icon type="inbox"/>
@@ -814,7 +813,7 @@ export default {
marriage_sts: 1,
},
fileList: [],
file_id: undefined,
file_ids: [],
current: 0,
from: this.$form.createForm(this, {name: 'coordinated'}),
formEdu: this.$form.createForm(this, {name: 'coordinated'}),
@@ -860,6 +859,8 @@ export default {
this.formWork.resetFields()
this.formFirst.resetFields()
this.current = 0
this.birth_day = ''
this.fileList = []
},
setMarriage_sts(event) {
this.flags.marriage_sts = event.target.value
@@ -867,15 +868,12 @@ export default {
setGender(event) {
this.flags.gender = event.target.value
},
changeDocumentUpload({fileList, event, file}) {
changeDocumentUpload({fileList, file}) {
if (file.response && file.response.id) {
this.file_id = file.response.id;
this.file_ids = fileList.map(x => x.response.id)
}
this.fileList = fileList;
},
handleRemoveDocument() {
this.file_id = null
},
deleteCity(index) {
this.jobsList.splice(index, 1);
@@ -917,7 +915,7 @@ export default {
values.model = this.formFirst.getFieldsValue();
values.birth_date = this.birth_day;
values.work = this.work;
values.file_id = this.file_id;
values.file_ids = this.file_ids;
values.training = this.educational;
values.academic = this.edu;
values.family = this.family;
+1 -1
View File
@@ -532,7 +532,7 @@
<div class="dropbox">
<a-upload-dragger
:multiple="false"
action="http://hr.asco-intl.com:2020/kernel/api/register/upload"
:action="$apiBase + '/register/upload'"
:file-list="fileList"
:default-file-list="fileList"
@change="changeDocumentUpload"
+2 -1
View File
@@ -1,6 +1,7 @@
import XTbl, {Xtc} from '../../components/new-x-table/index';
import { API_BASE_URL } from '@/config'
const tbl = new XTbl('http://hr.asco-intl.com:2020/kernel/api/user/table', 'لیست کاربران');
const tbl = new XTbl(`${API_BASE_URL}/user/table`, 'لیست کاربران');
tbl.add(new Xtc('id', 'id').filterNumber());
tbl.add(new Xtc('name', 'نام و نام خانوادگی').filterText());
tbl.add(new Xtc('user_type.value', 'نوع کاربر').filterText());