2025-06-22 23:55:55 +08:00
|
|
|
<template>
|
2025-07-14 01:15:52 +08:00
|
|
|
<div class="setting_role_list">
|
|
|
|
|
<Breadcrumb
|
|
|
|
|
:items="['menu.setting', 'menu.setting.user', 'menu.setting.role']"
|
|
|
|
|
/>
|
|
|
|
|
<a-row :gutter="12" :wrap="false">
|
|
|
|
|
<a-col flex="310px">
|
|
|
|
|
<a-card class="full_height" :bordered="false">
|
|
|
|
|
<template #title>
|
|
|
|
|
<div class="card-title_between">
|
|
|
|
|
<p class="title">{{ $t('role.list') }}</p>
|
|
|
|
|
<a-button type="primary" @click="handleAddRole">
|
|
|
|
|
<template #icon>
|
|
|
|
|
<icon-plus />
|
|
|
|
|
</template>
|
|
|
|
|
{{ $t('role.add') }}
|
|
|
|
|
</a-button>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
<a-spin style="display: block" :loading="loading">
|
|
|
|
|
<ul class="role_list">
|
|
|
|
|
<li
|
|
|
|
|
v-for="role in roleList"
|
|
|
|
|
:key="role.id"
|
|
|
|
|
:class="[
|
|
|
|
|
'role_item',
|
|
|
|
|
{ active: currentRoleActiveId === role.id },
|
|
|
|
|
]"
|
|
|
|
|
@click="handleClickRoleItem(role.id)"
|
|
|
|
|
>
|
|
|
|
|
<p class="name">{{ role.name }}</p>
|
|
|
|
|
<div v-if="currentRoleActiveId === role.id" class="actions">
|
|
|
|
|
<span @click="handleEditRole(role)"><icon-edit /></span>
|
|
|
|
|
<span>
|
|
|
|
|
<a-popconfirm
|
|
|
|
|
:ok-text="$t('cancel')"
|
|
|
|
|
:cancel-text="$t('delete')"
|
|
|
|
|
:ok-button-props="{ type: 'outline' }"
|
|
|
|
|
:cancel-button-props="{
|
|
|
|
|
type: 'primary',
|
|
|
|
|
status: 'danger',
|
|
|
|
|
}"
|
|
|
|
|
:content="
|
|
|
|
|
$t('please.confirm.delete.some', { name: $t('role') })
|
|
|
|
|
"
|
|
|
|
|
type="error"
|
|
|
|
|
@cancel="handleDelRole(role.id)"
|
|
|
|
|
>
|
|
|
|
|
<icon-delete />
|
|
|
|
|
</a-popconfirm>
|
|
|
|
|
</span>
|
|
|
|
|
</div>
|
|
|
|
|
</li>
|
|
|
|
|
</ul>
|
|
|
|
|
</a-spin>
|
|
|
|
|
<roleFormDrawer
|
|
|
|
|
v-model:visible="showDrawer"
|
|
|
|
|
:record="roleItemInfo"
|
|
|
|
|
:is-edit="isEdit"
|
|
|
|
|
@submitted="onRoleSubmit"
|
|
|
|
|
@update:checked-keys="(val) => (checkedKeys = val)"
|
|
|
|
|
/>
|
|
|
|
|
</a-card>
|
|
|
|
|
</a-col>
|
|
|
|
|
<a-col flex="auto" class="full_height">
|
2025-07-15 00:54:36 +08:00
|
|
|
<a-tabs v-model:active-key="currentTabsKey" class="tabs_card">
|
2025-07-14 01:15:52 +08:00
|
|
|
<template #extra>
|
|
|
|
|
<p style="margin-right: 10px">
|
|
|
|
|
<span>{{ $t('last.updated') }}</span>
|
|
|
|
|
<span>{{ roleItemInfo ? roleItemInfo.updatedAt : '' }}</span>
|
|
|
|
|
</p>
|
2025-07-15 00:54:36 +08:00
|
|
|
<a-button
|
|
|
|
|
v-if="currentTabsKey !== '3'"
|
|
|
|
|
type="primary"
|
|
|
|
|
@click="handleSubmit"
|
|
|
|
|
>
|
|
|
|
|
{{ $t('submit') }}</a-button
|
|
|
|
|
>
|
2025-07-14 01:15:52 +08:00
|
|
|
</template>
|
|
|
|
|
<a-tab-pane key="1" :title="$t('function.permission')">
|
|
|
|
|
<permissionCollapse
|
|
|
|
|
:role-id="currentRoleActiveId"
|
|
|
|
|
:permission-list="permissionList"
|
|
|
|
|
@update:checked-keys="(val) => (checkedKeys = val)"
|
|
|
|
|
/>
|
|
|
|
|
</a-tab-pane>
|
|
|
|
|
<a-tab-pane key="2" :title="$t('data.permission')">
|
2025-07-15 00:54:36 +08:00
|
|
|
<h4>{{ $t('data.permission.setting') }}</h4>
|
|
|
|
|
<div style="padding: 20px 0">
|
|
|
|
|
<a-radio-group v-model="dataType">
|
|
|
|
|
<a-radio :value="1">{{ $t('all.data.permission') }}</a-radio>
|
|
|
|
|
<a-radio :value="2">{{
|
|
|
|
|
$t('customize.data.permission')
|
|
|
|
|
}}</a-radio>
|
|
|
|
|
<a-radio :value="3">{{ $t('self.data.permission') }}</a-radio>
|
|
|
|
|
</a-radio-group>
|
|
|
|
|
<a-row
|
|
|
|
|
v-if="dataType === 2"
|
|
|
|
|
:gutter="12"
|
|
|
|
|
style="margin-top: 20px"
|
|
|
|
|
>
|
|
|
|
|
<a-col :span="12">
|
|
|
|
|
<a-card>
|
|
|
|
|
<h4 style="margin-bottom: 10px">选择组织架构</h4>
|
|
|
|
|
<DepartmentTree
|
|
|
|
|
v-model:expanded-keys="expandedKeys"
|
|
|
|
|
v-model:selected-keys="selectedKeys"
|
|
|
|
|
:data="departmentListData"
|
|
|
|
|
checkable
|
|
|
|
|
/>
|
|
|
|
|
</a-card>
|
|
|
|
|
</a-col>
|
|
|
|
|
<a-col :span="12">
|
|
|
|
|
<a-card>
|
|
|
|
|
<h4 style="margin-bottom: 10px">选择项目</h4>
|
|
|
|
|
<div style="margin-top: 20px"> TODO 后面再对接 </div>
|
|
|
|
|
</a-card>
|
|
|
|
|
</a-col>
|
|
|
|
|
</a-row>
|
|
|
|
|
</div>
|
2025-07-14 01:15:52 +08:00
|
|
|
</a-tab-pane>
|
|
|
|
|
<a-tab-pane key="3" :title="$t('user.assignment')">
|
|
|
|
|
<h4>{{ $t('user.assignment.setting') }}</h4>
|
2025-07-15 00:54:36 +08:00
|
|
|
<div style="padding-bottom: 20px">
|
|
|
|
|
<DataTable
|
|
|
|
|
style="margin-top: 20px"
|
|
|
|
|
:data="renderData"
|
|
|
|
|
:columns="projectColumn"
|
|
|
|
|
:loading="loading"
|
|
|
|
|
:total="total"
|
|
|
|
|
:current="current"
|
|
|
|
|
:page-size="pageSize"
|
|
|
|
|
pagination
|
|
|
|
|
@page-change="onPageChange"
|
|
|
|
|
@page-size-change="onPageSizeChange"
|
|
|
|
|
>
|
|
|
|
|
<template #realname="{ record }">
|
|
|
|
|
<span>{{ record.realname }}</span>
|
|
|
|
|
<icon-idcard v-if="record.isManager === 1" />
|
|
|
|
|
</template>
|
|
|
|
|
<template #status="{ record }">
|
|
|
|
|
<a-tag :color="record.status == 1 ? 'green' : 'red'">
|
|
|
|
|
{{
|
|
|
|
|
record.status == 1 ? $t('enable') : $t('disable')
|
|
|
|
|
}}</a-tag
|
|
|
|
|
>
|
|
|
|
|
</template>
|
|
|
|
|
<template #operate="{ record }">
|
|
|
|
|
<a-button @click="changeRole(record?.id)">{{
|
|
|
|
|
$t('change.role')
|
|
|
|
|
}}</a-button>
|
|
|
|
|
</template>
|
|
|
|
|
</DataTable>
|
|
|
|
|
</div>
|
2025-07-14 01:15:52 +08:00
|
|
|
<changeRoleDrawer
|
|
|
|
|
v-model:visible="changeRoleDrawerVisible"
|
|
|
|
|
:role-id="currentRoleActiveId"
|
|
|
|
|
:user-id="selectedUserId"
|
|
|
|
|
:role-list="roleList"
|
|
|
|
|
@update-user="onChangeRole"
|
|
|
|
|
/>
|
|
|
|
|
</a-tab-pane>
|
|
|
|
|
</a-tabs>
|
|
|
|
|
</a-col>
|
|
|
|
|
</a-row>
|
|
|
|
|
</div>
|
2025-06-22 23:55:55 +08:00
|
|
|
</template>
|
2025-07-14 01:15:52 +08:00
|
|
|
|
|
|
|
|
<script lang="ts" setup>
|
2025-07-15 00:54:36 +08:00
|
|
|
import { ref, onMounted, watch } from 'vue';
|
2025-07-14 01:15:52 +08:00
|
|
|
import {
|
|
|
|
|
getRoleList,
|
|
|
|
|
delRole,
|
|
|
|
|
saveRolePermission,
|
|
|
|
|
getPermissionList,
|
|
|
|
|
getUserListFromRole,
|
|
|
|
|
} from '@/api/setting';
|
2025-07-27 14:59:30 +08:00
|
|
|
import { UserList, RoleItem } from '@/types/setting';
|
2025-07-14 01:15:52 +08:00
|
|
|
import useLoading from '@/hooks/loading';
|
|
|
|
|
import { Message } from '@arco-design/web-vue';
|
|
|
|
|
import useDataTable from '@/composables/useDataTable';
|
|
|
|
|
import type { TableColumnData } from '@arco-design/web-vue';
|
|
|
|
|
import { useI18n } from 'vue-i18n';
|
2025-07-15 00:54:36 +08:00
|
|
|
import DepartmentTree from '@/components/common/DepartmentTree.vue';
|
|
|
|
|
import useDepartmentList from '@/composables/useDepartmentList';
|
2025-07-14 01:15:52 +08:00
|
|
|
import permissionCollapse from './components/permission-collapse.vue';
|
|
|
|
|
import roleFormDrawer from './components/role-form-drawer.vue';
|
|
|
|
|
import changeRoleDrawer from './components/change-role-drawer.vue';
|
|
|
|
|
|
2025-07-15 00:54:36 +08:00
|
|
|
const { departmentListData, allDepartmentKeys } = useDepartmentList();
|
|
|
|
|
|
2025-07-14 01:15:52 +08:00
|
|
|
const { loading, setLoading } = useLoading(true);
|
|
|
|
|
const { t } = useI18n();
|
|
|
|
|
const roleList = ref<RoleItem[]>([]);
|
|
|
|
|
const currentRoleActiveId = ref<number | null>(null);
|
|
|
|
|
const showDrawer = ref<boolean>(false);
|
|
|
|
|
const isEdit = ref<boolean>(false);
|
|
|
|
|
const roleItemInfo = ref<RoleItem | null>(null);
|
|
|
|
|
const checkedKeys = ref<number[]>([]);
|
|
|
|
|
const permissionList = ref<any[]>([]);
|
|
|
|
|
const changeRoleDrawerVisible = ref<boolean>(false);
|
|
|
|
|
const selectedUserId = ref<number | null>(null);
|
2025-07-15 00:54:36 +08:00
|
|
|
const currentTabsKey = ref<string>('1');
|
|
|
|
|
const dataType = ref<number>(1);
|
|
|
|
|
const expandedKeys = ref<(string | number)[]>([]);
|
|
|
|
|
const selectedKeys = ref<(string | number)[]>([]);
|
2025-07-14 01:15:52 +08:00
|
|
|
// 使用 DataTable composable
|
|
|
|
|
const {
|
|
|
|
|
data: renderData,
|
|
|
|
|
columns: projectColumn,
|
|
|
|
|
// loading,
|
|
|
|
|
total,
|
|
|
|
|
current,
|
|
|
|
|
pageSize,
|
|
|
|
|
setData,
|
|
|
|
|
setColumns,
|
|
|
|
|
// setLoading,
|
|
|
|
|
setTotal,
|
|
|
|
|
setCurrent,
|
|
|
|
|
setPageSize,
|
|
|
|
|
} = useDataTable({
|
|
|
|
|
initialPage: 1,
|
|
|
|
|
initialPageSize: 10,
|
|
|
|
|
pageSizeOptions: [10, 20, 50, 100],
|
|
|
|
|
});
|
|
|
|
|
const userListData = ref<UserList>([]);
|
|
|
|
|
const columns: TableColumnData[] = [
|
|
|
|
|
{
|
|
|
|
|
title: t('username'),
|
|
|
|
|
dataIndex: 'username',
|
|
|
|
|
key: 'username',
|
|
|
|
|
width: 120,
|
|
|
|
|
ellipsis: true,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
title: t('name'),
|
|
|
|
|
dataIndex: 'realname',
|
|
|
|
|
key: 'realname',
|
|
|
|
|
width: 150,
|
|
|
|
|
ellipsis: true,
|
|
|
|
|
slotName: 'realname',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
title: t('department'),
|
|
|
|
|
dataIndex: 'deptName',
|
|
|
|
|
key: 'departmentId',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
title: t('role'),
|
|
|
|
|
dataIndex: 'roleName',
|
|
|
|
|
key: 'roleName',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
title: t('status'),
|
|
|
|
|
dataIndex: 'status',
|
|
|
|
|
key: 'status',
|
|
|
|
|
slotName: 'status',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
title: t('lastLogin'),
|
|
|
|
|
dataIndex: 'lastLoginTime',
|
|
|
|
|
key: 'lastLoginTime',
|
2025-07-15 00:54:36 +08:00
|
|
|
align: 'center',
|
2025-07-14 01:15:52 +08:00
|
|
|
render: ({ record }) => record.lastLoginTime || '-',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
title: '操作',
|
|
|
|
|
key: 'operate',
|
|
|
|
|
slotName: 'operate',
|
|
|
|
|
width: 200,
|
|
|
|
|
},
|
|
|
|
|
];
|
|
|
|
|
// 获取权限列表数据
|
|
|
|
|
const getPermissionListData = async () => {
|
|
|
|
|
try {
|
|
|
|
|
const { code, data } = await getPermissionList();
|
|
|
|
|
if (code === 200 && data) {
|
|
|
|
|
// 根据 permission-collapse 组件的使用,API 返回的是权限数组
|
|
|
|
|
permissionList.value = Array.isArray(data?.permission)
|
|
|
|
|
? data.permission
|
|
|
|
|
: [];
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('获取权限列表失败:', error);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 根据权限ID获取权限信息(包括路径)
|
|
|
|
|
const getPermissionById = (id: number): any => {
|
|
|
|
|
const findPermission = (list: any[]): any => {
|
|
|
|
|
// 用数组方法替换 for...of 循环
|
|
|
|
|
return list.reduce((found, item) => {
|
|
|
|
|
if (found) return found;
|
|
|
|
|
if (item.id === id) {
|
|
|
|
|
return item;
|
|
|
|
|
}
|
|
|
|
|
if (item.children && item.children.length > 0) {
|
|
|
|
|
return findPermission(item.children) || found;
|
|
|
|
|
}
|
|
|
|
|
return found;
|
|
|
|
|
}, null);
|
|
|
|
|
};
|
|
|
|
|
return findPermission(permissionList.value);
|
|
|
|
|
};
|
|
|
|
|
const getUserListFromRoleData = async () => {
|
|
|
|
|
try {
|
|
|
|
|
setLoading(true);
|
|
|
|
|
const params = {
|
|
|
|
|
role_id: currentRoleActiveId.value,
|
|
|
|
|
page: current.value,
|
|
|
|
|
page_size: pageSize.value,
|
|
|
|
|
};
|
|
|
|
|
const { code, data } = await getUserListFromRole(params);
|
|
|
|
|
if (code === 200) {
|
|
|
|
|
const { page, userList } = data;
|
|
|
|
|
userListData.value = Array.isArray(userList) ? userList : [];
|
|
|
|
|
setData(userListData.value);
|
|
|
|
|
setTotal(typeof page.total === 'number' ? page.total : 0);
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error(error);
|
|
|
|
|
} finally {
|
|
|
|
|
setLoading(false);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
const getRoleListData = async (isInit: boolean) => {
|
|
|
|
|
try {
|
|
|
|
|
setLoading(true);
|
|
|
|
|
const { code, data } = await getRoleList();
|
|
|
|
|
if (code === 200) {
|
|
|
|
|
roleList.value = Array.isArray(data?.rolesList) ? data.rolesList : [];
|
|
|
|
|
if (isInit) {
|
|
|
|
|
roleItemInfo.value = roleList.value[0];
|
|
|
|
|
currentRoleActiveId.value = roleItemInfo.value
|
|
|
|
|
? roleItemInfo.value.id
|
|
|
|
|
: null;
|
|
|
|
|
getUserListFromRoleData();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
// 错误处理(保留注释,避免空代码块)
|
|
|
|
|
} finally {
|
|
|
|
|
setLoading(false);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
const handleAddRole = () => {
|
|
|
|
|
isEdit.value = false;
|
|
|
|
|
showDrawer.value = true;
|
|
|
|
|
roleItemInfo.value = null;
|
|
|
|
|
};
|
|
|
|
|
const handleClickRoleItem = (id: number) => {
|
|
|
|
|
if (id === currentRoleActiveId.value) return;
|
|
|
|
|
currentRoleActiveId.value = id;
|
|
|
|
|
getUserListFromRoleData();
|
|
|
|
|
};
|
|
|
|
|
const handleEditRole = (role: RoleItem) => {
|
|
|
|
|
roleItemInfo.value = role;
|
|
|
|
|
isEdit.value = true;
|
|
|
|
|
showDrawer.value = true;
|
|
|
|
|
};
|
|
|
|
|
const handleDelRole = async (id: number) => {
|
|
|
|
|
try {
|
|
|
|
|
const { code, message } = await delRole(Number(id));
|
|
|
|
|
if (code === 200) {
|
|
|
|
|
Message.success(message);
|
|
|
|
|
getRoleListData(false);
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
// 处理错误
|
|
|
|
|
console.error(error);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
const onRoleSubmit = () => {
|
|
|
|
|
getRoleListData(false);
|
|
|
|
|
};
|
2025-07-15 00:54:36 +08:00
|
|
|
watch(
|
|
|
|
|
allDepartmentKeys,
|
|
|
|
|
(val) => {
|
|
|
|
|
expandedKeys.value = val;
|
|
|
|
|
},
|
|
|
|
|
{ immediate: true }
|
|
|
|
|
);
|
2025-07-14 01:15:52 +08:00
|
|
|
function handleSubmit() {
|
|
|
|
|
if (!currentRoleActiveId.value) {
|
|
|
|
|
Message.warning('请先选择一个角色');
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (checkedKeys.value.length === 0) {
|
|
|
|
|
Message.warning('请至少选择一个权限');
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 根据选中的权限ID获取完整的权限信息
|
|
|
|
|
const permissionData = checkedKeys.value
|
|
|
|
|
.map((key) => {
|
|
|
|
|
const permission = getPermissionById(key);
|
|
|
|
|
return {
|
|
|
|
|
id: key,
|
|
|
|
|
path: permission?.path || '',
|
|
|
|
|
};
|
|
|
|
|
})
|
|
|
|
|
.filter((item) => item.id);
|
|
|
|
|
|
|
|
|
|
// 调用保存角色权限的API
|
|
|
|
|
saveRolePermission({
|
|
|
|
|
id: currentRoleActiveId.value,
|
|
|
|
|
children: permissionData,
|
|
|
|
|
})
|
|
|
|
|
.then(({ code, message }) => {
|
|
|
|
|
if (code === 200) {
|
|
|
|
|
Message.success(message || '权限保存成功');
|
|
|
|
|
} else {
|
|
|
|
|
Message.error(message || '权限保存失败');
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
.catch((error) => {
|
|
|
|
|
Message.error('权限保存失败');
|
|
|
|
|
console.error('保存角色权限失败:', error);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
// 分页事件处理
|
|
|
|
|
const onPageChange = (page: number) => {
|
|
|
|
|
setCurrent(page);
|
|
|
|
|
current.value = page;
|
|
|
|
|
getUserListFromRoleData();
|
|
|
|
|
};
|
|
|
|
|
const onPageSizeChange = (size: number) => {
|
|
|
|
|
setPageSize(size);
|
|
|
|
|
pageSize.value = size;
|
|
|
|
|
getUserListFromRoleData();
|
|
|
|
|
};
|
|
|
|
|
const changeRole = (id: number) => {
|
|
|
|
|
selectedUserId.value = id;
|
|
|
|
|
changeRoleDrawerVisible.value = true;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const onChangeRole = () => {
|
|
|
|
|
getUserListFromRoleData();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
onMounted(() => {
|
|
|
|
|
getRoleListData(true);
|
|
|
|
|
getPermissionListData();
|
|
|
|
|
setColumns(columns);
|
|
|
|
|
});
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<style lang="less" scoped>
|
|
|
|
|
.tabs_card {
|
|
|
|
|
background-color: #fff;
|
|
|
|
|
padding: 0 20px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.role_list {
|
|
|
|
|
.role_item {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
height: 42px;
|
|
|
|
|
line-height: 42px;
|
|
|
|
|
padding: 0 16px;
|
|
|
|
|
border-bottom: 1px solid #efefef;
|
|
|
|
|
|
|
|
|
|
&.active {
|
|
|
|
|
background-color: #efefef;
|
|
|
|
|
|
|
|
|
|
.name {
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
color: #2d5cf6;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.name {
|
|
|
|
|
color: #000;
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
text-align: left;
|
|
|
|
|
flex: 1;
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.actions {
|
|
|
|
|
& > span {
|
|
|
|
|
width: 16px;
|
|
|
|
|
margin-left: 10px;
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
|
|
|
|
&:last-child {
|
|
|
|
|
margin-right: 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
</style>
|