parent
adf5a0dec5
commit
f2159083d7
21 changed files with 704 additions and 145 deletions
@ -1,7 +1,7 @@ |
||||
VITE_APP_TITLE=金融产品设计及数字化营销沙盘 |
||||
VITE_PORT=9520 |
||||
VITE_PROXY=http://192.168.31.126:8080 |
||||
VITE_PROXY=http://192.168.31.125:8080 |
||||
VITE_PUBLIC_PATH=./ |
||||
VITE_BASE_API=/api |
||||
VITE_BASE_API=http://192.168.31.217:9000 |
||||
VITE_I18N_LOCALE=zh-cn |
||||
VITE_I18N_FALLBACK_LOCALE=zh-cn |
||||
|
@ -0,0 +1,8 @@ |
||||
import axios from '@/utils/request'; |
||||
|
||||
export const queryStorageList = async (params?: Record<string, any>): Promise<any> => (await axios.get('/backend/core/storage', { params })).data; |
||||
export const queryStorage = async (id: number): Promise<any> => (await axios.get(`/backend/core/storage/${id}`)).data; |
||||
export const updateStorage = async (data: Record<string, any>): Promise<any> => (await axios.post('/backend/core/storage?_method=put', data)).data; |
||||
|
||||
export const primaryTypeOfGuarantee = async (): Promise<any> => (await axios.post('/product/bankGuaranteeType/primaryTypeOfGuarantee')).data; |
||||
export const bankingProductsList = async (data: Record<string, any>): Promise<any> => (await axios.post('/product/product/bank/products/bankingProductsList', data)).data; |
@ -1,28 +0,0 @@ |
||||
import axios from '@/utils/request'; |
||||
|
||||
export const queryStorageList = async (params?: Record<string, any>): Promise<any> => (await axios.get('/backend/core/storage', { params })).data; |
||||
export const queryStorage = async (id: number): Promise<any> => (await axios.get(`/backend/core/storage/${id}`)).data; |
||||
export const createStorage = async (data: Record<string, any>): Promise<any> => (await axios.post('/backend/core/storage', data)).data; |
||||
export const updateStorage = async (data: Record<string, any>): Promise<any> => (await axios.post('/backend/core/storage?_method=put', data)).data; |
||||
export const updateStorageOrder = async (data: number[]): Promise<any> => (await axios.post('/backend/core/storage/order?_method=put', data)).data; |
||||
export const deleteStorage = async (data: number[]): Promise<any> => (await axios.post('/backend/core/storage?_method=delete', data)).data; |
||||
|
||||
export const querySiteList = async (params?: Record<string, any>): Promise<any> => (await axios.get('/backend/core/site', { params })).data; |
||||
export const querySite = async (id: number): Promise<any> => (await axios.get(`/backend/core/site/${id}`)).data; |
||||
export const createSite = async (data: Record<string, any>): Promise<any> => (await axios.post('/backend/core/site', data)).data; |
||||
export const updateSite = async (data: Record<string, any>): Promise<any> => (await axios.post('/backend/core/site?_method=put', data)).data; |
||||
export const updateSiteOrder = async (data: number[]): Promise<any> => (await axios.post('/backend/core/site/order?_method=put', data)).data; |
||||
export const deleteSite = async (data: number[]): Promise<any> => (await axios.post('/backend/core/site?_method=delete', data)).data; |
||||
export const querySiteThemeList = async (id: number): Promise<any> => (await axios.get(`/backend/core/site/${id}/theme`)).data; |
||||
|
||||
export const queryAttachmentPage = async (params?: Record<string, any>): Promise<any> => (await axios.get('/backend/core/attachment', { params })).data; |
||||
export const queryAttachment = async (id: number): Promise<any> => (await axios.get(`/backend/core/attachment/${id}`)).data; |
||||
export const createAttachment = async (data: Record<string, any>): Promise<any> => (await axios.post('/backend/core/attachment', data)).data; |
||||
export const updateAttachment = async (data: Record<string, any>): Promise<any> => (await axios.post('/backend/core/attachment?_method=put', data)).data; |
||||
export const deleteAttachment = async (data: number[]): Promise<any> => (await axios.post('/backend/core/attachment?_method=delete', data)).data; |
||||
|
||||
export const queryTaskPage = async (params?: Record<string, any>): Promise<any> => (await axios.get('/backend/core/task', { params })).data; |
||||
export const queryTask = async (id: number): Promise<any> => (await axios.get(`/backend/core/task/${id}`)).data; |
||||
export const createTask = async (data: Record<string, any>): Promise<any> => (await axios.post('/backend/core/task', data)).data; |
||||
export const updateTask = async (data: Record<string, any>): Promise<any> => (await axios.post('/backend/core/task?_method=put', data)).data; |
||||
export const deleteTask = async (data: number[]): Promise<any> => (await axios.post('/backend/core/task?_method=delete', data)).data; |
After Width: | Height: | Size: 456 B |
After Width: | Height: | Size: 449 B |
After Width: | Height: | Size: 277 B |
After Width: | Height: | Size: 145 B |
After Width: | Height: | Size: 592 B |
After Width: | Height: | Size: 575 B |
@ -1,58 +1,56 @@ |
||||
import Cookies from 'js-cookie'; |
||||
|
||||
const JWT_ACCESS_TOKEN = 'jwt-access-token'; |
||||
const JWT_ACCESS_AT = 'jwt-access-at'; |
||||
const JWT_REFRESH_TOKEN = 'jwt-refresh-token'; |
||||
const JWT_REFRESH_AT = 'jwt-refresh-at'; |
||||
const JWT_SESSION_TIMEOUT = 'jwt-session-timeout'; |
||||
const SAND_ACCESS_TOKEN = 'sand-token'; |
||||
const SAND_ACCESS_AT = 'jwt-access-at'; |
||||
const SAND_REFRESH_TOKEN = 'jwt-refresh-token'; |
||||
const SAND_REFRESH_AT = 'jwt-refresh-at'; |
||||
const SAND_SESSION_TIMEOUT = 'jwt-session-timeout'; |
||||
|
||||
export const getAccessToken = (): string | undefined => Cookies.get(JWT_ACCESS_TOKEN); |
||||
export const getAccessToken = (): string | undefined => Cookies.get(SAND_ACCESS_TOKEN); |
||||
export const setAccessToken = (token: string): void => { |
||||
Cookies.set(JWT_ACCESS_TOKEN, token); |
||||
Cookies.set(SAND_ACCESS_TOKEN, token); |
||||
}; |
||||
export const removeAccessToken = (): void => Cookies.remove(JWT_ACCESS_TOKEN); |
||||
export const removeAccessToken = (): void => Cookies.remove(SAND_ACCESS_TOKEN); |
||||
|
||||
export const getRefreshToken = (): string | undefined => Cookies.get(JWT_REFRESH_TOKEN); |
||||
export const getRefreshToken = (): string | undefined => Cookies.get(SAND_REFRESH_TOKEN); |
||||
export const setRefreshToken = (token: string): void => { |
||||
Cookies.set(JWT_REFRESH_TOKEN, token); |
||||
Cookies.set(SAND_REFRESH_TOKEN, token); |
||||
}; |
||||
export const removeRefreshToken = (): void => { |
||||
Cookies.remove(JWT_REFRESH_TOKEN); |
||||
Cookies.remove(SAND_REFRESH_TOKEN); |
||||
}; |
||||
|
||||
export const getRefreshAt = (): number => { |
||||
const refreshAt = Cookies.get(JWT_REFRESH_AT); |
||||
const refreshAt = Cookies.get(SAND_REFRESH_AT); |
||||
return refreshAt ? Number(refreshAt) : 0; |
||||
}; |
||||
export const setRefreshAt = (refreshAt: number): void => { |
||||
Cookies.set(JWT_REFRESH_AT, String(refreshAt)); |
||||
Cookies.set(SAND_REFRESH_AT, String(refreshAt)); |
||||
}; |
||||
export const removeRefreshAt = (): void => { |
||||
Cookies.remove(JWT_REFRESH_AT); |
||||
Cookies.remove(SAND_REFRESH_AT); |
||||
}; |
||||
|
||||
export const getAccessAt = (): number => { |
||||
const accessAt = Cookies.get(JWT_ACCESS_AT); |
||||
const accessAt = Cookies.get(SAND_ACCESS_AT); |
||||
return accessAt ? Number(accessAt) : 0; |
||||
}; |
||||
export const setAccessAt = (accessAt: number): void => { |
||||
Cookies.set(JWT_ACCESS_AT, String(accessAt)); |
||||
Cookies.set(SAND_ACCESS_AT, String(accessAt)); |
||||
}; |
||||
export const removeAccessAt = () => Cookies.remove(JWT_ACCESS_AT); |
||||
|
||||
export const getSessionTimeout = (): number => { |
||||
const sessionTimeout = Cookies.get(JWT_SESSION_TIMEOUT); |
||||
const sessionTimeout = Cookies.get(SAND_SESSION_TIMEOUT); |
||||
// 默认 30 分钟
|
||||
return sessionTimeout ? Number(sessionTimeout) : 30; |
||||
}; |
||||
export const setSessionTimeout = (sessionTimeout: number): void => { |
||||
Cookies.set(JWT_SESSION_TIMEOUT, String(sessionTimeout)); |
||||
Cookies.set(SAND_SESSION_TIMEOUT, String(sessionTimeout)); |
||||
}; |
||||
export const removeSessionTimeout = (): void => { |
||||
Cookies.remove(JWT_SESSION_TIMEOUT); |
||||
Cookies.remove(SAND_SESSION_TIMEOUT); |
||||
}; |
||||
|
||||
export const getAuthHeaders = (): any => { |
||||
const accessToken = getAccessToken(); |
||||
return { Authorization: accessToken ? `Bearer ${accessToken}` : '' }; |
||||
return { token: getAccessToken() }; |
||||
}; |
||||
|
@ -0,0 +1,196 @@ |
||||
<template> |
||||
<div> |
||||
<div class="filter block"> |
||||
<dl> |
||||
<dt>担保方式:</dt> |
||||
<div class="vals"> |
||||
<dd v-for="(item, i) in methods" |
||||
:key="i" |
||||
:class="{ active: method === item.id }" |
||||
@click="filterClick(item, 'method')">{{ item.name }}</dd> |
||||
</div> |
||||
</dl> |
||||
<dl> |
||||
<dt>产品进度:</dt> |
||||
<div class="vals"> |
||||
<dd v-for="(item, i) in methods" |
||||
:key="i" |
||||
:class="{ active: method === item.id }" |
||||
@click="filterClick(item, 'method')">{{ item.name }}</dd> |
||||
</div> |
||||
</dl> |
||||
</div> |
||||
<div class="block mt-3"> |
||||
<div class="search"> |
||||
<input type="text" |
||||
placeholder="搜索" |
||||
maxlength="20" /> |
||||
<img src="@/assets/images/search.png" |
||||
alt="" |
||||
class="icon" /> |
||||
</div> |
||||
<el-table ref="table" |
||||
v-loading="loading" |
||||
:data="data" |
||||
@selection-change="(rows) => (selection = rows)" |
||||
@sort-change="handleSort"> |
||||
<el-table-column type="selection" |
||||
:selectable="deletable" |
||||
width="50"></el-table-column> |
||||
<el-table-column property="id" |
||||
label="ID" |
||||
width="64" |
||||
sortable="custom"></el-table-column> |
||||
</el-table> |
||||
<el-pagination v-model:currentPage="currentPage" |
||||
v-model:pageSize="pageSize" |
||||
:total="total" |
||||
:page-sizes="pageSizes" |
||||
:layout="pageLayout" |
||||
@size-change="fetchData()" |
||||
@current-change="fetchData()" |
||||
small |
||||
background |
||||
class="px-3 py-2 justify-end"></el-pagination> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
|
||||
<script setup lang="ts"> |
||||
import { computed, onMounted, ref } from 'vue'; |
||||
import { ElMessage } from 'element-plus'; |
||||
import { Search } from '@element-plus/icons-vue'; |
||||
import { useI18n } from 'vue-i18n'; |
||||
import dayjs from 'dayjs'; |
||||
import { perm } from '@/store/useCurrentUser'; |
||||
import { pageSizes, pageLayout, toParams, resetParams } from '@/utils/common'; |
||||
import { deleteUser, queryUserPage } from '@/api/user'; |
||||
|
||||
const { t } = useI18n(); |
||||
const params = ref<any>({}); |
||||
const sort = ref<any>(); |
||||
const currentPage = ref<number>(1); |
||||
const pageSize = ref<number>(10); |
||||
const total = ref<number>(0); |
||||
const table = ref<any>(); |
||||
const method = ref<any>(''); |
||||
const methods = ref<Array<any>>([ |
||||
{ |
||||
id: '', |
||||
name: '不限', |
||||
}, |
||||
{ |
||||
id: 1, |
||||
name: '信用贷', |
||||
}, |
||||
{ |
||||
id: 2, |
||||
name: '信用贷', |
||||
}, |
||||
]); |
||||
const data = ref<Array<any>>([]); |
||||
const selection = ref<Array<any>>([]); |
||||
const loading = ref<boolean>(false); |
||||
const beanId = ref<number>(); |
||||
const fetchData = async () => { |
||||
loading.value = true; |
||||
try { |
||||
const { content, totalElements } = await queryUserPage({ ...toParams(params.value), Q_OrderBy: sort.value, page: currentPage.value, pageSize: pageSize.value }); |
||||
data.value = content; |
||||
total.value = totalElements; |
||||
} finally { |
||||
loading.value = false; |
||||
} |
||||
}; |
||||
// onMounted(fetchData); |
||||
|
||||
const handleSort = ({ column, prop, order }: { column: any; prop: string; order: string }) => { |
||||
if (prop) { |
||||
sort.value = (column.sortBy ?? prop) + (order === 'descending' ? '_desc' : ''); |
||||
} else { |
||||
sort.value = undefined; |
||||
} |
||||
fetchData(); |
||||
}; |
||||
const handleSearch = () => fetchData(); |
||||
const handleReset = () => { |
||||
table.value.clearSort(); |
||||
resetParams(params.value); |
||||
sort.value = undefined; |
||||
fetchData(); |
||||
}; |
||||
|
||||
const handleAdd = () => { |
||||
beanId.value = undefined; |
||||
}; |
||||
const handleEdit = (id: number) => { |
||||
beanId.value = id; |
||||
}; |
||||
const handleDelete = async (ids: number[]) => { |
||||
await deleteUser(ids); |
||||
fetchData(); |
||||
ElMessage.success(t('success')); |
||||
}; |
||||
const deletable = (bean: any) => bean.id > 1; |
||||
</script> |
||||
|
||||
<style lang="scss" scoped> |
||||
.filter { |
||||
dl { |
||||
display: flex; |
||||
flex-wrap: wrap; |
||||
align-items: center; |
||||
margin-bottom: 17px; |
||||
&:last-child { |
||||
margin-bottom: 0; |
||||
} |
||||
dt, |
||||
dd { |
||||
font-size: 14px; |
||||
font-family: MiSans; |
||||
color: #333; |
||||
} |
||||
.vals { |
||||
display: inline-flex; |
||||
flex-wrap: wrap; |
||||
align-items: center; |
||||
margin-left: 10px; |
||||
} |
||||
dd { |
||||
padding: 6px 10px; |
||||
margin-right: 10px; |
||||
cursor: pointer; |
||||
} |
||||
.active { |
||||
color: #fff; |
||||
background: #006bff; |
||||
border-radius: 4px; |
||||
} |
||||
} |
||||
} |
||||
.search { |
||||
position: relative; |
||||
width: 320px; |
||||
padding: 0 12px; |
||||
background-color: #f6f8fc; |
||||
border-radius: 8px; |
||||
input { |
||||
width: 90%; |
||||
height: 36px; |
||||
font-size: 14px; |
||||
line-height: 36px; |
||||
color: #333; |
||||
border: 0; |
||||
background-color: transparent; |
||||
&:focus { |
||||
outline: none; |
||||
} |
||||
} |
||||
.icon { |
||||
position: absolute; |
||||
top: 9px; |
||||
right: 12px; |
||||
cursor: pointer; |
||||
} |
||||
} |
||||
</style> |
@ -0,0 +1,238 @@ |
||||
<template> |
||||
<div> |
||||
<div class="block"> |
||||
<div class="flex justify-between items-center mb-5"> |
||||
<div class="search"> |
||||
<input type="text" |
||||
placeholder="搜索" |
||||
maxlength="20" /> |
||||
<img src="@/assets/images/search.png" |
||||
alt="" |
||||
class="icon" /> |
||||
</div> |
||||
<div class="filter"> |
||||
<div class="select"> |
||||
<el-select v-model="guarantyStyleId" |
||||
placeholder="担保方式" |
||||
size="large"> |
||||
<el-option label="担保方式" |
||||
value="" /> |
||||
<el-option v-for="item in guarantees" |
||||
:key="item.id" |
||||
:label="item.guarantyStyle" |
||||
:value="item.id" /> |
||||
</el-select> |
||||
<img src="@/assets/images/7.png" |
||||
alt="" |
||||
class="icon" /> |
||||
</div> |
||||
<div class="select"> |
||||
<el-select v-model="pace" |
||||
placeholder="产品进度" |
||||
size="large"> |
||||
<el-option v-for="item in paces" |
||||
:key="item.id" |
||||
:label="item.name" |
||||
:value="item.id" /> |
||||
</el-select> |
||||
<img src="@/assets/images/8.png" |
||||
alt="" |
||||
class="icon" /> |
||||
</div> |
||||
<div class="add-btn"> |
||||
<img src="@/assets/images/plus.png" |
||||
alt="" |
||||
class="icon" /> |
||||
新增产品 |
||||
</div> |
||||
<img src="@/assets/images/9.png" |
||||
alt="" |
||||
class="ml-4 cursor-pointer" /> |
||||
</div> |
||||
</div> |
||||
<el-table ref="table" |
||||
v-loading="loading" |
||||
:data="list" |
||||
@sort-change="handleSort"> |
||||
<el-table-column prop="id" |
||||
label="产品名称"></el-table-column> |
||||
<el-table-column prop="id" |
||||
label="产品编号"></el-table-column> |
||||
<el-table-column prop="id" |
||||
label="担保方式"></el-table-column> |
||||
<el-table-column prop="id" |
||||
label="最高额度/年利率/期限"></el-table-column> |
||||
<el-table-column prop="id" |
||||
label="创建日期"></el-table-column> |
||||
<el-table-column prop="id" |
||||
label="产品进度"></el-table-column> |
||||
<el-table-column prop="id" |
||||
label="操作"> |
||||
<template #default="{ row }"> |
||||
<el-button type="text" |
||||
@click="handleEdit(row.id)" |
||||
size="small">配置要素</el-button> |
||||
<el-button type="text" |
||||
@click="handleEdit(row.id)" |
||||
size="small">产品详情</el-button> |
||||
<el-button type="text" |
||||
@click="handleEdit(row.id)" |
||||
size="small">删除</el-button> |
||||
</template></el-table-column> |
||||
</el-table> |
||||
<el-pagination v-model:currentPage="currentPage" |
||||
v-model:pageSize="pageSize" |
||||
:total="total" |
||||
:page-sizes="pageSizes" |
||||
:layout="pageLayout" |
||||
@size-change="fetchData()" |
||||
@current-change="fetchData()" |
||||
small |
||||
background |
||||
class="px-3 py-2 justify-end"></el-pagination> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
|
||||
<script setup lang="ts"> |
||||
import { computed, onMounted, ref } from 'vue'; |
||||
import { ElMessage } from 'element-plus'; |
||||
import { Search } from '@element-plus/icons-vue'; |
||||
import { useI18n } from 'vue-i18n'; |
||||
import dayjs from 'dayjs'; |
||||
import { perm } from '@/store/useCurrentUser'; |
||||
import { pageSizes, pageLayout, toParams, resetParams } from '@/utils/common'; |
||||
import { primaryTypeOfGuarantee, bankingProductsList } from '@/api/bank'; |
||||
|
||||
const { t } = useI18n(); |
||||
const params = ref<any>({ |
||||
createDateSort: '', |
||||
guarantyStyleId: '', |
||||
keyWord: '', |
||||
productType: '', |
||||
status: '', |
||||
}); |
||||
const sort = ref<any>(); |
||||
const currentPage = ref<number>(1); |
||||
const pageSize = ref<number>(10); |
||||
const total = ref<number>(0); |
||||
const table = ref<any>(); |
||||
const guarantyStyleId = ref<any>(''); |
||||
const guarantees = ref<Array<any>>([]); |
||||
const pace = ref<any>(''); |
||||
const paces = ref<Array<any>>([]); |
||||
const list = ref<Array<any>>([]); |
||||
const selection = ref<Array<any>>([]); |
||||
const loading = ref<boolean>(false); |
||||
const beanId = ref<number>(); |
||||
// 担保方式 |
||||
const getGuarantee = async () => { |
||||
try { |
||||
const { data } = await primaryTypeOfGuarantee(); |
||||
guarantees.value = data; |
||||
} finally { |
||||
} |
||||
}; |
||||
// 列表 |
||||
const fetchData = async () => { |
||||
loading.value = true; |
||||
try { |
||||
const { data } = await bankingProductsList({ pageNum: currentPage.value, pageSize: pageSize.value, ...toParams(params.value) }); |
||||
list.value = data.message.records; |
||||
total.value = data.message.total; |
||||
} finally { |
||||
loading.value = false; |
||||
} |
||||
}; |
||||
onMounted(() => { |
||||
getGuarantee(); |
||||
fetchData(); |
||||
}); |
||||
|
||||
const handleSort = ({ column, prop, order }: { column: any; prop: string; order: string }) => { |
||||
if (prop) { |
||||
sort.value = (column.sortBy ?? prop) + (order === 'descending' ? '_desc' : ''); |
||||
} else { |
||||
sort.value = undefined; |
||||
} |
||||
fetchData(); |
||||
}; |
||||
const handleSearch = () => fetchData(); |
||||
|
||||
const handleAdd = () => { |
||||
beanId.value = undefined; |
||||
}; |
||||
const handleEdit = (id: number) => { |
||||
beanId.value = id; |
||||
}; |
||||
const handleDelete = async (ids: number[]) => { |
||||
await deleteUser(ids); |
||||
fetchData(); |
||||
ElMessage.success(t('success')); |
||||
}; |
||||
const deletable = (bean: any) => bean.id > 1; |
||||
</script> |
||||
|
||||
<style lang="scss" scoped> |
||||
.search { |
||||
display: flex; |
||||
align-items: center; |
||||
width: 300px; |
||||
padding: 0 24px; |
||||
background-color: #fff; |
||||
border: 1px solid #dfe9f8; |
||||
border-radius: 18px; |
||||
input { |
||||
width: 230px; |
||||
height: 36px; |
||||
margin-right: 10px; |
||||
font-size: 14px; |
||||
line-height: 36px; |
||||
color: #333; |
||||
border: 0; |
||||
background-color: transparent; |
||||
&:focus { |
||||
outline: none; |
||||
} |
||||
} |
||||
.icon { |
||||
cursor: pointer; |
||||
} |
||||
} |
||||
.filter { |
||||
display: inline-flex; |
||||
align-items: center; |
||||
.select { |
||||
position: relative; |
||||
margin-right: 12px; |
||||
.icon { |
||||
position: absolute; |
||||
top: 12px; |
||||
left: 20px; |
||||
} |
||||
:deep(.el-select) { |
||||
width: 170px; |
||||
.el-input__inner { |
||||
padding-left: 41px; |
||||
border-radius: 18px; |
||||
border-color: #dfe9f8; |
||||
} |
||||
} |
||||
} |
||||
.add-btn { |
||||
display: inline-flex; |
||||
align-items: center; |
||||
height: 36px; |
||||
padding: 0 24px; |
||||
font-size: 14px; |
||||
color: #fff; |
||||
background: linear-gradient(-36deg, #006bff, #2ab1ff); |
||||
border: 1px solid #ffffff; |
||||
border-radius: 18px; |
||||
cursor: pointer; |
||||
.icon { |
||||
margin-right: 8px; |
||||
} |
||||
} |
||||
} |
||||
</style> |
Loading…
Reference in new issue