update

parent 1ebaa459
......@@ -139,5 +139,8 @@ export enum API_PATHS {
artistFeaturedProducts = 'artist/featuredProducts',
// duyệt chủ quản
artistOwnerBrowseManagement = 'artistOwner/browseManagement'
artistOwnerBrowseManagement = 'artistOwner/browseManagement',
// thêm người dùng vào nhóm
addUser = 'user/group/addUser',
importExcel = 'artist/importExcel'
}
......@@ -80,11 +80,51 @@ export type ArtistInfoType = {
mnWhatsapp: string | null;
favoriteScore: number;
listProductNotActivess: listProductNotActives[];
artistOwner: {
name: string;
};
};
export type groupDetail = {
group: {
groupName: null | string;
id: number;
status: number;
description: null | string;
};
pageRoles: pageRoles[];
users: users[];
};
export type GroupInfoType = {
groupName: null | string;
id: number;
status: number;
description: null | string;
};
export type users = {
address: null | string;
birthday: string;
confirmPassword: string;
email: null | string;
fullName: null | string;
id: number;
userName: null | string;
};
export type pageRoles = {
description: null;
id: number;
level: number;
menuIndex: number;
pageIcon: string;
pageName: string;
pageUrl: null | string;
parentId: number;
roles: string;
};
export type artistFeatured = {
ids: string;
};
......@@ -279,7 +319,7 @@ export type ArtistOwnerAdd = {
export type DetailUnit = {
id: number;
name: string;
unitName: string;
code: string;
representative: string;
address: string;
......
<template>
<q-dialog
persistent
:model-value="isOpened"
@update:model-value="$emit('update:isOpened', $event)"
>
<q-card class="full-width" style="max-width: 60rem" bordered>
<q-form greedy @submit.prevent="$emit('update:isOpened', false)">
<q-card-section class="q-pa-none">
<q-item>
<q-item-section>
<q-item-label class="text-h6 text-weight-regular"
>Danh sách người dùng</q-item-label
>
</q-item-section>
</q-item>
</q-card-section>
<q-separator />
<q-card-section
class="overflow-auto"
style="max-height: calc(100vh - 10rem)"
>
<div class="col-12 q-mt-sm">
<q-table
:rows="userTableRows"
:columns="userTableColumnsAccountGroup"
:no-data-label="$t('emptyData')"
:rows-per-page-label="$t('recordPerPage')"
:pagination="{
rowsPerPage: 0,
}"
wrap-cells
hide-pagination
class="sticky-header-table"
row-key="id"
:selected-rows-label="getSelectedString"
selection="multiple"
v-model:selected="selected"
>
<template v-slot:body-cell-stt="item">
<q-td class="text-center">
{{ 1 + item.rowIndex + 20 * (1 - 1) }}
</q-td>
</template>
</q-table>
</div>
<div class="col-12 q-mt-sm">
<Pagination
v-model:currentPage="pageIndex"
v-model:pageSize="pageSize"
:totalPage="totalPage"
@update:pageSize="changePageSize"
@update:currentPage="getListAccont"
/>
</div>
</q-card-section>
<q-card-actions align="right">
<div>
<q-btn
color="grey"
no-caps
style="width: 90px"
class="q-mr-sm"
:label="$t('post.crudActions.cancel')"
@click="$emit('update:isOpened', false)"
/>
<q-btn
@click="confirm"
color="primary"
no-caps
style="width: 90px"
:label="$t('post.crudActions.save')"
/>
</div>
</q-card-actions>
</q-form>
</q-card>
</q-dialog>
</template>
<script lang="ts">
import { AxiosResponse } from 'axios';
import { Dialog, Notify } from 'quasar';
import { API_PATHS, config } from 'src/assets/configurations.example';
import { PaginationResponse, UserObject, users } from 'src/assets/type';
import { api, BaseResponseBody } from 'src/boot/axios';
import { defineComponent, PropType, ref, Ref, watch, onMounted } from 'vue';
import Pagination from 'components/pagination/index.vue';
import User from 'src/pages/nguoi-dung/User';
export default defineComponent({
components: {
Pagination,
},
props: {
isOpened: {
type: Boolean,
required: true,
},
dataItemId: {
type: Number,
required: true,
},
listUsers: {
type: Array as PropType<users[]>,
required: true,
},
},
setup(props, context) {
const totalPage = ref(0);
const pageIndex = ref(1);
const pageSize = ref(20);
const userTableRows: Ref<UserObject[]> = ref([]);
const selected: Ref<users[]> = ref([]);
const changePageSize = () => {
pageIndex.value = 1;
void getListAccont();
};
// watch(
// () => props.isOpened,
// (value) => {
// if(value) {
// }
// }
// );
const getSelectedString = () => {
return selected.value.length === 0
? ''
: `${selected.value.length} người dùng đã chọn `;
};
const confirm = async () => {
try {
const browserResult = (await api({
url: API_PATHS.addUser,
method: 'POST',
data: {
group: {
id: props.dataItemId,
},
users: selected.value,
pageRoles: [],
},
})) as AxiosResponse<BaseResponseBody<unknown>>;
if (browserResult.data.error.code === config.API_RES_CODE.OK.code) {
Notify.create({
type: 'positive',
message: 'Thêm người dùng vào nhóm thành công',
actions: [{ icon: 'close', color: 'white' }],
});
context.emit('update:isOpened', false);
context.emit('successful');
}
} catch (error) {}
};
const getListAccont = async () => {
try {
const response = (await api({
url: API_PATHS.getListUsers,
method: 'GET',
params: {
pageIndex: pageIndex.value,
pageSize: pageSize.value,
name: null,
},
})) as AxiosResponse<BaseResponseBody<PaginationResponse<UserObject>>>;
if (response.data.error.code === config.API_RES_CODE.OK.code) {
userTableRows.value = response.data.data.data;
totalPage.value = response.data.data.totalPages;
}
} catch (error) {}
};
const userTableColumnsAccountGroup = [
{
name: 'stt',
field: 'stt',
required: true,
label: 'STT',
align: 'center',
sortable: false,
},
{
name: 'fullName',
field: 'fullName',
required: true,
label: 'Họ tên',
align: 'center',
sortable: false,
},
{
name: 'userName',
field: 'userName',
required: true,
label: 'Tên đăng nhập',
align: 'center',
sortable: false,
},
{
name: 'unit',
field: 'unit',
required: true,
label: 'Đơn vị',
align: 'center',
sortable: false,
},
];
onMounted(() => {
void getListAccont();
selected.value = props.listUsers;
});
return {
getListAccont,
changePageSize,
userTableColumnsAccountGroup,
userTableRows,
totalPage,
pageIndex,
pageSize,
selected,
getSelectedString,
confirm,
};
},
emits: ['update:isOpened', 'successful'],
});
</script>
......@@ -6,7 +6,7 @@
<q-space></q-space>
<div class="col-auto">
<q-btn
@click="$emit('click:addAccountGroup')"
@click="addAccountGroup"
color="primary"
no-caps
style="width: 100px"
......@@ -24,13 +24,13 @@
hide-pagination
>
<template v-slot:body-cell-stt="item">
<q-td :item="item">
{{ 1 + item.rowIndex + pageSize * (pageIndex - 1) }}
<q-td class="text-center">
{{ 1 + item.rowIndex + 10 * (1 - 1) }}
</q-td>
</template>
</q-table>
</div>
<div class="col-12 q-mt-sm">
<!-- <div class="col-12 q-mt-sm">
<Pagination
v-model:currentPage="pageIndex"
v-model:pageSize="pageSize"
......@@ -38,22 +38,53 @@
@update:pageSize="changePageSize"
@update:currentPage="getListAccountGroup"
/>
</div>
</div> -->
<addUser
v-if="addIsOpened"
v-model:isOpened="addIsOpened"
:dataItemId="dataItemId"
:listUsers="listUsers"
@successful="$emit('successful')"
></addUser>
</div>
</template>
<script lang="ts">
import { i18n } from 'src/boot/i18n';
import { defineComponent, onMounted, Ref, ref } from 'vue';
import Pagination from 'components/pagination/index.vue';
import { defineComponent, onMounted, Ref, ref, watch } from 'vue';
// import Pagination from 'components/pagination/index.vue';
import { users } from 'src/assets/type';
import addUser from '../../components/accountGroup/add.vue';
import { GroupInfoType } from '../../assets/type';
export default defineComponent({
components: {
Pagination,
addUser,
},
setup() {
props: {
listUsers: {
type: Array,
required: true,
},
selectedGroupId: {
type: Number,
required: true,
},
},
setup(props) {
// watch(
// () => props.listUsers,
// (value) => {
// if (value) {
// console.log(value);
// }
// }
// );
const userTableColumnsAccountGroup = [
{
name: 'STT',
name: 'stt',
field: 'stt',
required: true,
label: 'STT',
align: 'center',
......@@ -68,18 +99,18 @@ export default defineComponent({
sortable: false,
},
{
name: 'user',
field: 'user',
name: 'userName',
field: 'userName',
required: true,
label: i18n.global.t('userGroupPage.groupInfo.fieldLabels.user'),
align: 'center',
sortable: false,
},
{
name: 'user',
field: 'user',
name: 'unit',
field: 'unit',
required: true,
label: i18n.global.t('userGroupPage.groupInfo.fieldLabels.position'),
label: 'Đơn vị',
align: 'center',
sortable: false,
},
......@@ -88,26 +119,35 @@ export default defineComponent({
const pageIndex = ref(1);
const pageSize = ref(20);
const totalPage = ref(0);
const dataAccountGroup: Ref<unknown[]> = ref([]);
const dataAccountGroup: Ref<users[] | any> = ref([]);
const dataItemId: Ref<number | null> = ref(null);
const changePageSize = () => {
pageIndex.value = 1;
void getListAccountGroup();
};
const getListAccountGroup = () => {
console.log();
const dataUser = () => {
// console.log(props.listUsers, 'props.listUsers');
return (dataAccountGroup.value = props.listUsers);
};
void dataUser();
const addIsOpened = ref(false);
const addAccountGroup = () => {
addIsOpened.value = true;
dataItemId.value = props.selectedGroupId;
};
onMounted(() => {
void getListAccountGroup();
});
return {
userTableColumnsAccountGroup,
dataAccountGroup,
pageIndex,
pageSize,
totalPage,
addIsOpened,
dataItemId,
dataUser,
changePageSize,
getListAccountGroup,
addAccountGroup,
};
},
emits: ['successful'],
});
</script>
......@@ -37,6 +37,7 @@
</q-input>
<q-input
v-if="isUpdate"
:model-value="password"
@update:model-value="$emit('update:password', $event)"
:label="`${$t('loginPage.passwordInputLabel')} *`"
......@@ -55,7 +56,7 @@
</template>
</q-input>
<q-input
<!-- <q-input
:model-value="code"
@update:model-value="$emit('update:code', $event)"
:label="$t('managingUnit.dialogLabel.fieldLabels.code')"
......@@ -64,7 +65,7 @@
class="q-my-sm"
outlined
clearable
></q-input>
></q-input> -->
<q-input
:model-value="name"
@update:model-value="$emit('update:name', $event)"
......@@ -437,7 +438,7 @@ const artistTableColumns = [
},
{
name: 'fieldsAdd',
field: 'field',
field: 'fieldNames',
required: true,
label: i18n.global.t('managingUnitAdd.tableColumns.fieldsAdd'),
headerStyle: 'text-align: center !important;',
......@@ -557,7 +558,7 @@ export default defineComponent({
fieldsAddOptions: { type: Array, required: true },
fields: { type: Number, required: true },
code: { type: String, required: true },
name: { type: String, required: true },
representative: { type: String, required: true },
userName: { type: String, required: true },
......@@ -605,14 +606,6 @@ export default defineComponent({
(val?: string) => (val && val.trim().length) || 'Vui lòng nhập mật khẩu',
];
const codeRules = [
(val?: string) =>
(val && val.trim().length) ||
i18n.global.t('managingUnit.validateMessages.requireCode'),
(val?: string) =>
(val && val.trim().length < 20) ||
i18n.global.t('managingUnit.validateMessages.requireLengthCode'),
];
const nameRules = [
(val?: string) =>
(val && val.trim().length) ||
......@@ -717,6 +710,10 @@ export default defineComponent({
})) as AxiosResponse<BaseResponseBody<FieldType[]>>;
if (response.data.error.code === config.API_RES_CODE.OK.code) {
fieldsAddOptions.value = response.data.data;
}
};
......@@ -900,7 +897,7 @@ export default defineComponent({
getArtistDicitionaryOptions,
addArtistDialogIsOpened,
addListArtistDialogIsOpened,
codeRules,
nameRules,
representativeRules,
addressRules,
......@@ -945,7 +942,7 @@ export default defineComponent({
emits: [
'update:isOpened',
'click:CloseBtn',
'update:code',
'update:name',
'update:representative',
'update:fields',
......
......@@ -201,7 +201,7 @@ export default defineComponent({
},
isUpdate: { type: Boolean, default: false },
artistOptions: { type: Array as PropType<FieldType[]>, required: true },
fieldsAddOptions: { type: Array, required: true },
// fieldsAddOptions: { type: Array, required: true },
artistField: { type: Object as PropType<ArtistInfoType>, required: true },
artistName: { type: Object as PropType<ArtistInfoType>, required: true },
artistStatus: { type: Number, required: true },
......@@ -216,20 +216,17 @@ export default defineComponent({
const isId: Ref<number | null> = ref(null);
const artistListOptions: Ref<ArtistInfoType[]> = ref([]);
const filteredOptions: Ref<ArtistInfoType[]> = ref([]);
const fieldsAddOptions: Ref<FieldType[]> = ref([]);
watch(
() => props.artistField,
(value) => {
if (value) {
isId.value = value.id;
void getArrayArtist();
}
}
);
const getArrayArtist = async () => {
artistListOptions.value = [];
const response = (await api({
......@@ -241,7 +238,17 @@ export default defineComponent({
})) as AxiosResponse<BaseResponseBody<ArtistInfoType[]>>;
if (response.data.error.code === config.API_RES_CODE.OK.code) {
artistListOptions.value = response.data.data;
}
};
const getFieldOptions = async () => {
const response = (await api({
url: API_PATHS.getFieldOptions,
method: 'GET',
params: {},
})) as AxiosResponse<BaseResponseBody<FieldType[]>>;
if (response.data.error.code === config.API_RES_CODE.OK.code) {
fieldsAddOptions.value = response.data.data;
}
};
......@@ -249,7 +256,6 @@ export default defineComponent({
if (val === '') {
update(() => {
filteredOptions.value = artistListOptions.value;
});
}
update(() => {
......@@ -291,6 +297,8 @@ export default defineComponent({
filterFn,
artistListOptions,
filteredOptions,
fieldsAddOptions,
getFieldOptions,
};
},
emits: [
......
......@@ -177,7 +177,6 @@
<AddUpdateUnitDialog
v-model:isOpened="addUnitDialogIsOpened"
v-model:address="unitAddress"
v-model:code="unitCode"
v-model:email="unitEmail"
v-model:fields="unitField"
v-model:fieldsOptions="fieldsOptions"
......@@ -197,7 +196,6 @@
<AddUpdateUnitDialog
v-model:isOpened="updateUnitDialogIsOpened"
v-model:address="unitAddress"
v-model:code="unitCode"
v-model:email="unitEmail"
v-model:fields="unitField"
v-model:fieldsOptions="fieldsOptions"
......@@ -358,8 +356,7 @@ export default defineComponent({
const unitField: Ref<ClassificationOptions[]> = ref([]);
const unitCode = ref('');
const unitName = ref('');
const unitName: Ref<string | null> = ref(null);
const unitRepresentative = ref('');
const unitEmail = ref('');
const unitAddress = ref('');
......@@ -382,7 +379,9 @@ export default defineComponent({
title: i18n.global.t(
'customer.confirmActionsTitle.confirmDeleteUserTitle'
),
message: i18n.global.t('Bạn có chắc muốn duyệt đơn vị quản lý này không?'),
message: i18n.global.t(
'Bạn có chắc muốn duyệt đơn vị quản lý này không?'
),
cancel: i18n.global.t(
'customer.confirmActionsTitle.confirmDeleteUserCancelBtnLabel'
),
......@@ -436,8 +435,8 @@ export default defineComponent({
const openAddUnitDialog = () => {
unitField.value = [];
unitCode.value = '';
unitName.value = '';
unitName.value = null;
unitRepresentative.value = '';
unitEmail.value = '';
unitAddress.value = '';
......@@ -465,8 +464,8 @@ export default defineComponent({
})) as AxiosResponse<BaseResponseBody<DetailUnit>>;
if (response.data.error.code === config.API_RES_CODE.OK.code) {
unitId.value = response.data.data.id;
unitName.value = response.data.data.name;
unitCode.value = response.data.data.code;
unitName.value = response.data.data.unitName;
unitEmail.value = response.data.data.email;
unitPhoneNumber.value = response.data.data.phoneNumber;
unitRepresentative.value = response.data.data.representative;
......@@ -553,8 +552,7 @@ export default defineComponent({
const updateNewUnit = async () => {
const data = {
id: unitId.value,
name: unitName.value,
code: unitCode.value,
unitName: unitName.value,
representative: unitRepresentative.value,
address: unitAddress.value,
email: unitEmail.value,
......@@ -590,8 +588,8 @@ export default defineComponent({
if (hasError === false) {
const data = {
name: unitName.value,
code: unitCode.value,
unitName: unitName.value,
representative: unitRepresentative.value,
address: unitAddress.value,
email: unitEmail.value,
......@@ -650,7 +648,6 @@ export default defineComponent({
totalPage,
changePageSize,
unitField,
unitCode,
unitName,
unitRepresentative,
unitEmail,
......
......@@ -34,7 +34,6 @@
</div>
<div class="col-auto">
<q-btn
class="q-mr-md"
color="primary"
no-caps
style="width: 7.14rem"
......@@ -42,6 +41,16 @@
to="/nghe-sy/them-nghe-sy"
></q-btn>
</div>
<v-col class="q-col">
<q-btn
color="primary"
no-caps
style="width: 7.14rem"
label="Import File"
@click="importExcel"
>
</q-btn>
</v-col>
<div class="col-12 q-mt-sm">
<q-table
......@@ -254,7 +263,6 @@
</div>
<AddNewArtistDialog
v-model:is-open-new-artist-dialog="isOpenNewArtistDialog"
v-model:full-name="fullName"
v-model:artist-name="artistName"
v-model:birthday="birthday"
......@@ -305,6 +313,7 @@ import {
WorkType,
ProvinceType,
MusicType,
FileUploadType,
} from 'src/assets/type';
import Pagination from 'components/pagination/index.vue';
import { api, BaseResponseBody } from 'src/boot/axios';
......@@ -482,6 +491,75 @@ export default defineComponent({
const costFrom = ref(0);
const costTo = ref(100000000);
// const level: Ref<string | null> = ref(null);
const upload = ref(null);
const callApiUploadAvatar = async (file: File) => {
try {
const bodyFormData = new FormData();
bodyFormData.append('file', file);
const response = (await api({
headers: { 'Content-Type': 'multipart/form-data' },
url: config.API_IMAGE_ENDPOINT, // pro
method: 'POST',
data: bodyFormData,
})) as AxiosResponse<BaseResponseBody<FileUploadType>>;
if (response.data.error.code === config.API_RES_CODE.OK.code) {
return response.data.data.filePath;
} else {
return '';
}
} catch (error) {
return '';
}
};
const avatarUploaded: Ref<string> = ref('');
const dataUrl = ref('');
const importExcel = () => {
const input = document.createElement('input');
input.type = 'file';
input.accept = '.xls, .xlsx'; // file extensions allowed
input.onchange = (e) => {
const files = (<HTMLInputElement & EventTarget>e.target).files;
// eslint-disable-next-line
// @ts-ignore
// eslint-disable-next-line
const file = files[0];
// eslint-disable-next-line
// @ts-ignore
// eslint-disable-next-line
avatarUploaded.value = callApiUploadAvatar(file).then((res) => {
// eslint-disable-next-line
// @ts-ignore
// eslint-disable-next-line
void importExcelUrl(res);
});
};
input.click();
};
const importExcelUrl = async (value: string) => {
try {
const dataItem = (await api({
url: API_PATHS.importExcel,
method: 'GET',
params: {
filePath: value,
},
})) as AxiosResponse<BaseResponseBody<unknown>>;
if (dataItem.data.error.code === config.API_RES_CODE.OK.code) {
Notify.create({
type: 'positive',
message: 'Import File thành công',
actions: [{ icon: 'close', color: 'white' }],
});
void getListArtists();
}
} catch (error) {}
};
const filter = () => {
void getListArtists();
......@@ -705,6 +783,9 @@ export default defineComponent({
confirmDeleteArtist,
deleteArtist,
filter,
importExcel,
upload,
importExcelUrl,
};
},
});
......
......@@ -9,7 +9,9 @@ import { EditMode } from 'src/assets/enums';
import { API_PATHS, config } from 'src/assets/configurations.example';
import { Dialog, Notify } from 'quasar';
import { i18n } from 'src/boot/i18n';
import { Store } from 'vuex'
import { Store } from 'vuex';
import { type } from 'os';
import { groupDetail } from 'src/assets/type';
export type GroupInfoType = {
createBy: null | string;
......@@ -21,11 +23,23 @@ export type GroupInfoType = {
updateBy: null | string;
updateTime: null | string;
};
export type infoType = {
address: null | string;
birthday: string;
confirmPassword: string;
email: null | string;
fullName: null | string;
id: number;
userName: null | string;
};
const tab = ref('inforGroup');
const userList: Ref<GroupInfoType[]> = ref([]);
const listUsers: Ref<infoType[]> = ref([]);
const isDisable = ref(EditMode.default);
const groupName = ref('');
const groupDescription = ref('');
const selectedGroupId = ref(-1);
const selectedPageRoles: Ref<string[]> = ref([]);
......@@ -95,7 +109,7 @@ const updateGroupInfo = async ($store: Store<StateInterface>) => {
id: parsedPage.id || -1,
roles: parsedPage.roles,
});
console.log(acc,'12312')
return acc;
},
[]
......@@ -127,7 +141,11 @@ const updateGroupInfo = async ($store: Store<StateInterface>) => {
}
} catch (error) {}
};
const successful = () => {
tab.value = 'inforGroup';
void getGroupDetail()
};
const changeValueIsDisable = (value: number) => {
isDisable.value = value;
groupName.value = '';
......@@ -204,10 +222,11 @@ const getGroupDetail = async () => {
params: {
groupId: selectedGroupId.value,
},
})) as AxiosResponse<BaseResponseBody<unknown>>;
})) as AxiosResponse<BaseResponseBody<groupDetail>>;
if (groupDetailRes.data.error.code === config.API_RES_CODE.OK.code) {
// selectedPageRoles.value
listUsers.value = groupDetailRes.data.data.users;
const groupDetail = groupDetailRes.data.data as {
pageRoles: {
id: number;
......@@ -244,6 +263,7 @@ export default defineComponent({
selectedGroupId.value = groupInfo.id;
groupName.value = groupInfo.groupName;
groupDescription.value = groupInfo.description;
void getGroupDetail();
};
......@@ -252,16 +272,19 @@ export default defineComponent({
});
return {
userList,
listUsers,
getGroupInfo,
isDisable,
changeValueIsDisable,
groupName,
groupDescription,
selectedGroupId,
saveGroupInfo,
confirmDeleteGroup,
selectedPageRoles,
tab,
successful,
};
},
});
......@@ -32,6 +32,7 @@
/>
</q-tabs>
<q-separator />
<q-tab-panels v-model="tab" animated>
<q-tab-panel name="inforGroup">
<GroupInfoComponent
......@@ -45,7 +46,11 @@
></GroupInfoComponent>
</q-tab-panel>
<q-tab-panel name="accountGroup">
<accountGroup></accountGroup>
<accountGroup
v-model:listUsers="listUsers"
v-model:selectedGroupId="selectedGroupId"
@successful="successful()"
></accountGroup>
</q-tab-panel>
</q-tab-panels>
</div>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment