更新页面

This commit is contained in:
shengchanzhe 2023-11-12 16:51:11 +08:00
parent 94bf0a5e95
commit cd2ca93418
32 changed files with 5333 additions and 4495 deletions

13
src/api/common.ts Normal file
View File

@ -0,0 +1,13 @@
import request from "@/utils/request";
// 省列表
export function apiProvinceList(params: any) {
return request.get({ url: "/common/province", params });
}
// 市列表
export function apiCityList(params: any) {
return request.get({ url: "/common/city", params });
}
// 区列表
export function apiAreaList(params: any) {
return request.get({ url: "/common/area", params });
}

26
src/api/custom.ts Normal file
View File

@ -0,0 +1,26 @@
import request from '@/utils/request'
// 客户表列表
export function apiCustomLists(params: any) {
return request.get({ url: '/custom.custom/lists', params })
}
// 添加客户表
export function apiCustomAdd(params: any) {
return request.post({ url: '/custom.custom/add', params })
}
// 编辑客户表
export function apiCustomEdit(params: any) {
return request.post({ url: '/custom.custom/edit', params })
}
// 删除客户表
export function apiCustomDelete(params: any) {
return request.post({ url: '/custom.custom/delete', params })
}
// 客户表详情
export function apiCustomDetail(params: any) {
return request.get({ url: '/custom.custom/detail', params })
}

View File

@ -0,0 +1,26 @@
import request from '@/utils/request'
// 客户联系人列表
export function apiCustomContactsLists(params: any) {
return request.get({ url: '/custom.custom_contacts/lists', params })
}
// 添加客户联系人
export function apiCustomContactsAdd(params: any) {
return request.post({ url: '/custom.custom_contacts/add', params })
}
// 编辑客户联系人
export function apiCustomContactsEdit(params: any) {
return request.post({ url: '/custom.custom_contacts/edit', params })
}
// 删除客户联系人
export function apiCustomContactsDelete(params: any) {
return request.post({ url: '/custom.custom_contacts/delete', params })
}
// 客户联系人详情
export function apiCustomContactsDetail(params: any) {
return request.get({ url: '/custom.custom_contacts/detail', params })
}

26
src/api/custom_follow.ts Normal file
View File

@ -0,0 +1,26 @@
import request from '@/utils/request'
// 客户跟进记录列表
export function apiCustomFollowLists(params: any) {
return request.get({ url: '/custom_follow.custom_follow/lists', params })
}
// 添加客户跟进记录
export function apiCustomFollowAdd(params: any) {
return request.post({ url: '/custom_follow.custom_follow/add', params })
}
// 编辑客户跟进记录
export function apiCustomFollowEdit(params: any) {
return request.post({ url: '/custom_follow.custom_follow/edit', params })
}
// 删除客户跟进记录
export function apiCustomFollowDelete(params: any) {
return request.post({ url: '/custom_follow.custom_follow/delete', params })
}
// 客户跟进记录详情
export function apiCustomFollowDetail(params: any) {
return request.get({ url: '/custom_follow.custom_follow/detail', params })
}

26
src/api/custom_service.ts Normal file
View File

@ -0,0 +1,26 @@
import request from '@/utils/request'
// 客户售后列表
export function apiCustomServiceLists(params: any) {
return request.get({ url: '/custom_service.custom_service/lists', params })
}
// 添加客户售后
export function apiCustomServiceAdd(params: any) {
return request.post({ url: '/custom_service.custom_service/add', params })
}
// 编辑客户售后
export function apiCustomServiceEdit(params: any) {
return request.post({ url: '/custom_service.custom_service/edit', params })
}
// 删除客户售后
export function apiCustomServiceDelete(params: any) {
return request.post({ url: '/custom_service.custom_service/delete', params })
}
// 客户售后详情
export function apiCustomServiceDetail(params: any) {
return request.get({ url: '/custom_service.custom_service/detail', params })
}

26
src/api/project.ts Normal file
View File

@ -0,0 +1,26 @@
import request from '@/utils/request'
// 项目表列表
export function apiProjectLists(params: any) {
return request.get({ url: '/project.project/lists', params })
}
// 添加项目表
export function apiProjectAdd(params: any) {
return request.post({ url: '/project.project/add', params })
}
// 编辑项目表
export function apiProjectEdit(params: any) {
return request.post({ url: '/project.project/edit', params })
}
// 删除项目表
export function apiProjectDelete(params: any) {
return request.post({ url: '/project.project/delete', params })
}
// 项目表详情
export function apiProjectDetail(params: any) {
return request.get({ url: '/project.project/detail', params })
}

View File

@ -0,0 +1,62 @@
<template>
<div>
<el-card class="!border-none" shadow="never">
<el-form class="mb-[-16px]" :model="queryParams" inline>
<el-form-item label="客户名称" prop="name">
<el-input class="w-[280px]" v-model="queryParams.name" clearable placeholder="请输入客户名称" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="resetPage">查询</el-button>
<el-button @click="resetParams">重置</el-button>
</el-form-item>
</el-form>
</el-card>
<el-card class="!border-none" v-loading="pager.loading" shadow="never">
<div class="mt-4">
<el-table :data="pager.lists" @cell-click="handleCurrentChange">
<el-table-column label="客户名称" property="name" />
<el-table-column label="客户属性" property="custom_type" />
<el-table-column label="信用度" property="credit_rating" />
<el-table-column label="省" property="province_name" />
<el-table-column label="市" property="city_name" />
<el-table-column label="区" property="street_name" />
<el-table-column label="主联系人" property="master_name" />
<el-table-column label="联系方式" property="master_phone" />
</el-table>
</div>
<div class="flex mt-4 justify-end">
<pagination v-model="pager" @change="getLists" />
</div>
</el-card>
</div>
</template>
<script lang="ts" setup>
import { usePaging } from "@/hooks/usePaging"
import { useDictData } from "@/hooks/useDictOptions"
import { apiCustomLists } from '@/api/custom'
import { defineEmits } from "vue"
//
const queryParams = reactive({
name: ''
});
//
const emits = defineEmits(["customEvent"]);
//
const handleCurrentChange = (value: any) => {
emits("customEvent", value);
};
//
const { pager, getLists, resetParams, resetPage } = usePaging({
fetchFun: apiCustomLists,
params: queryParams,
});
getLists();
</script>

View File

@ -4,22 +4,11 @@
<div class="flex-1 min-h-0">
<el-scrollbar>
<div class="material-left__content pt-4 p-b-4">
<el-tree
ref="treeRef"
node-key="id"
:data="cateLists"
empty-text="''"
:highlight-current="true"
:expand-on-click-node="false"
:current-node-key="cateId"
@node-click="handleCatSelect"
>
<el-tree ref="treeRef" node-key="id" :data="cateLists" empty-text="''" :highlight-current="true"
:expand-on-click-node="false" :current-node-key="cateId" @node-click="handleCatSelect">
<template v-slot="{ data }">
<div class="flex flex-1 items-center min-w-0 pr-4">
<img
class="w-[20px] h-[16px] mr-3"
src="@/assets/images/icon_folder.png"
/>
<img class="w-[20px] h-[16px] mr-3" src="@/assets/images/icon_folder.png" />
<span class="flex-1 truncate mr-2">
<overflow-tooltip :content="data.name" />
</span>
@ -27,15 +16,8 @@
<span class="muted m-r-10">···</span>
<template #dropdown>
<el-dropdown-menu>
<popover-input
@confirm="handleEditCate($event, data.id)"
size="default"
:value="data.name"
width="400px"
:limit="20"
show-limit
teleported
>
<popover-input @confirm="handleEditCate($event, data.id)" size="default"
:value="data.name" width="400px" :limit="20" show-limit teleported>
<div>
<el-dropdown-item>
命名分组
@ -56,14 +38,7 @@
</div>
<div class="flex justify-center p-2 border-t border-br">
<popover-input
@confirm="handleAddCate"
size="default"
width="400px"
:limit="20"
show-limit
teleported
>
<popover-input @confirm="handleAddCate" size="default" width="400px" :limit="20" show-limit teleported>
<el-button> 添加分组 </el-button>
</popover-input>
</div>
@ -71,41 +46,24 @@
<div class="material__center flex flex-col">
<div class="operate-btn flex">
<div class="flex-1 flex">
<upload
v-if="type == 'image'"
class="mr-3"
:data="{ cid: cateId }"
:type="type"
:show-progress="true"
@change="refresh"
>
<upload v-if="type == 'image'" class="mr-3" :data="{ cid: cateId }" :type="type" :show-progress="true"
@change="refresh">
<el-button type="primary">本地上传</el-button>
</upload>
<upload
v-if="type == 'video'"
class="mr-3"
:data="{ cid: cateId }"
:type="type"
:show-progress="true"
@change="refresh"
>
<upload v-if="type == 'video'" class="mr-3" :data="{ cid: cateId }" :type="type" :show-progress="true"
@change="refresh">
<el-button type="primary">本地上传</el-button>
</upload>
<el-button
v-if="mode == 'page'"
:disabled="!select.length"
@click.stop="batchFileDelete()"
>
<upload v-if="type == 'file'" class="mr-3" :data="{ cid: cateId }" :type="type" :show-progress="true"
@change="refresh">
<el-button type="primary">本地上传</el-button>
</upload>
<el-button v-if="mode == 'page'" :disabled="!select.length" @click.stop="batchFileDelete()">
删除
</el-button>
<popup
v-if="mode == 'page'"
class="ml-3"
@confirm="batchFileMove"
:disabled="!select.length"
title="移动文件"
>
<popup v-if="mode == 'page'" class="ml-3" @confirm="batchFileMove" :disabled="!select.length"
title="移动文件">
<template #trigger>
<el-button :disabled="!select.length">移动</el-button>
</template>
@ -114,22 +72,13 @@
<span class="mr-5">移动文件至</span>
<el-select v-model="moveId" placeholder="请选择">
<template v-for="item in cateLists" :key="item.id">
<el-option
v-if="item.id !== ''"
:label="item.name"
:value="item.id"
></el-option>
<el-option v-if="item.id !== ''" :label="item.name" :value="item.id"></el-option>
</template>
</el-select>
</div>
</popup>
</div>
<el-input
class="w-60"
placeholder="请输入名称"
v-model="fileParams.name"
@keyup.enter="refresh"
>
<el-input class="w-60" placeholder="请输入名称" v-model="fileParams.name" @keyup.enter="refresh">
<template #append>
<el-button @click="refresh">
<template #icon>
@ -140,55 +89,33 @@
</el-input>
<div class="flex items-center ml-2">
<el-tooltip content="列表视图" placement="top">
<div
class="list-icon"
:class="{
select: listShowType == 'table'
}"
@click="listShowType = 'table'"
>
<div class="list-icon" :class="{
select: listShowType == 'table'
}" @click="listShowType = 'table'">
<icon name="local-icon-list-2" :size="18" />
</div>
</el-tooltip>
<el-tooltip content="平铺视图" placement="top">
<div
class="list-icon"
:class="{
select: listShowType == 'normal'
}"
@click="listShowType = 'normal'"
>
<div class="list-icon" :class="{
select: listShowType == 'normal'
}" @click="listShowType = 'normal'">
<icon name="el-icon-Menu" :size="18" />
</div>
</el-tooltip>
</div>
</div>
<div class="mt-3" v-if="mode == 'page'">
<el-checkbox
:disabled="!pager.lists.length"
v-model="isCheckAll"
@change="selectAll"
:indeterminate="isIndeterminate"
>
<el-checkbox :disabled="!pager.lists.length" v-model="isCheckAll" @change="selectAll"
:indeterminate="isIndeterminate">
当页全选
</el-checkbox>
</div>
<div class="material-center__content flex flex-col flex-1 mb-1 min-h-0">
<el-scrollbar v-if="pager.lists.length" v-show="listShowType == 'normal'">
<ul class="file-list flex flex-wrap mt-4">
<li
class="file-item-wrap"
v-for="item in pager.lists"
:key="item.id"
:style="{ width: fileSize }"
>
<li class="file-item-wrap" v-for="item in pager.lists" :key="item.id" :style="{ width: fileSize }">
<del-wrap @close="batchFileDelete([item.id])">
<file-item
:uri="item.uri"
:file-size="fileSize"
:type="type"
@click="selectFile(item)"
>
<file-item :uri="item.uri" :file-size="fileSize" :type="type" @click="selectFile(item)">
<div class="item-selected" v-if="isSelect(item.id)">
<icon :size="24" name="el-icon-Check" color="#fff" />
</div>
@ -197,15 +124,8 @@
<overflow-tooltip class="mt-1" :content="item.name" />
<div class="operation-btns flex items-center">
<popover-input
@confirm="handleFileRename($event, item.id)"
size="default"
:value="item.name"
width="400px"
:limit="50"
show-limit
teleported
>
<popover-input @confirm="handleFileRename($event, item.id)" size="default"
:value="item.name" width="400px" :limit="50" show-limit teleported>
<el-button type="primary" link> 重命名 </el-button>
</popover-input>
<el-button type="primary" link @click="handlePreview(item.uri)">
@ -216,16 +136,8 @@
</ul>
</el-scrollbar>
<el-table
ref="tableRef"
class="mt-4"
v-show="listShowType == 'table'"
:data="pager.lists"
width="100%"
height="100%"
size="large"
@row-click="selectFile"
>
<el-table ref="tableRef" class="mt-4" v-show="listShowType == 'table'" :data="pager.lists" width="100%"
height="100%" size="large" @row-click="selectFile">
<el-table-column width="55">
<template #default="{ row }">
<el-checkbox :modelValue="isSelect(row.id)" @change="selectFile(row)" />
@ -247,15 +159,8 @@
<el-table-column label="操作" width="150" fixed="right">
<template #default="{ row }">
<div class="inline-block">
<popover-input
@confirm="handleFileRename($event, row.id)"
size="default"
:value="row.name"
width="400px"
:limit="50"
show-limit
teleported
>
<popover-input @confirm="handleFileRename($event, row.id)" size="default" :value="row.name"
width="400px" :limit="50" show-limit teleported>
<el-button type="primary" link> 重命名 </el-button>
</popover-input>
</div>
@ -265,11 +170,7 @@
</el-button>
</div>
<div class="inline-block">
<el-button
type="primary"
link
@click.stop="batchFileDelete([row.id])"
>
<el-button type="primary" link @click.stop="batchFileDelete([row.id])">
删除
</el-button>
</div>
@ -277,10 +178,7 @@
</el-table-column>
</el-table>
<div
class="flex flex-1 justify-center items-center"
v-if="!pager.loading && !pager.lists.length"
>
<div class="flex flex-1 justify-center items-center" v-if="!pager.loading && !pager.lists.length">
暂无数据~
</div>
</div>
@ -288,24 +186,15 @@
<div class="flex">
<template v-if="mode == 'page'">
<span class="mr-3">
<el-checkbox
:disabled="!pager.lists.length"
v-model="isCheckAll"
@change="selectAll"
:indeterminate="isIndeterminate"
>
<el-checkbox :disabled="!pager.lists.length" v-model="isCheckAll" @change="selectAll"
:indeterminate="isIndeterminate">
当页全选
</el-checkbox>
</span>
<el-button :disabled="!select.length" @click="batchFileDelete()">
删除
</el-button>
<popup
class="ml-3 inline"
@confirm="batchFileMove"
:disabled="!select.length"
title="移动文件"
>
<popup class="ml-3 inline" @confirm="batchFileMove" :disabled="!select.length" title="移动文件">
<template #trigger>
<el-button :disabled="!select.length">移动</el-button>
</template>
@ -314,22 +203,14 @@
<span class="mr-5">移动文件至</span>
<el-select v-model="moveId" placeholder="请选择">
<template v-for="item in cateLists" :key="item.id">
<el-option
v-if="item.id !== ''"
:label="item.name"
:value="item.id"
></el-option>
<el-option v-if="item.id !== ''" :label="item.name" :value="item.id"></el-option>
</template>
</el-select>
</div>
</popup>
</template>
</div>
<pagination
v-model="pager"
@change="getFileList"
layout="total, prev, pager, next, jumper"
/>
<pagination v-model="pager" @change="getFileList" layout="total, prev, pager, next, jumper" />
</div>
</div>
<div class="material__right" v-if="mode == 'picker'">
@ -346,11 +227,7 @@
<li class="mb-4" v-for="item in select" :key="item.id">
<div class="select-item">
<del-wrap @close="cancelSelete(item.id)">
<file-item
:uri="item.uri"
file-size="100px"
:type="type"
></file-item>
<file-item :uri="item.uri" file-size="100px" :type="type"></file-item>
</del-wrap>
</div>
</li>
@ -497,10 +374,13 @@ defineExpose({
<style scoped lang="scss">
.material {
@apply h-full min-h-0 flex flex-1;
&__left {
@apply border-r border-br flex flex-col w-[200px];
:deep(.el-tree-node__content) {
height: 36px;
.el-tree-node__label {
display: flex;
flex: 1;
@ -508,25 +388,30 @@ defineExpose({
}
}
}
&__center {
flex: 1;
min-width: 0;
min-height: 0;
padding: 16px 16px 0;
.list-icon {
border-radius: 3px;
display: flex;
padding: 5px;
cursor: pointer;
&.select {
@apply text-primary bg-primary-light-8;
}
}
.file-list {
.file-item-wrap {
margin-right: 16px;
line-height: 1.3;
cursor: pointer;
.item-selected {
display: flex;
align-items: center;
@ -540,19 +425,23 @@ defineExpose({
background-color: rgba(0, 0, 0, 0.5);
box-sizing: border-box;
}
.operation-btns {
height: 28px;
visibility: hidden;
}
&:hover .operation-btns {
visibility: visible;
}
}
}
}
&__right {
@apply border-l border-br flex flex-col;
width: 130px;
.select-lists {
padding: 10px;

View File

@ -1,368 +0,0 @@
<template>
<div>
<el-row :gutter="10">
<el-form ref="elForm" :model="formData" :rules="rules" size="medium" label-width="100px">
<el-card>
<div class="tit">客户基本资料</div>
<el-row>
<el-col :span="8">
<el-form-item label="客户姓名" prop="field101">
<el-input v-model="formData.field101" placeholder="请输入本文行单客户姓名" clearable
:style="{ width: '100%' }"></el-input>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="客户属性" prop="field103">
<el-select v-model="formData.field103" placeholder="请选择客户属性" clearable
:style="{ width: '100%' }">
<el-option v-for="(item, index) in field103Options" :key="index" :label="item.label"
:value="item.value" :disabled="item.disabled"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="上级公司" prop="field104">
<el-input v-model="formData.field104" placeholder="请输入上级公司" clearable
:style="{ width: '100%' }">
</el-input>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="电话" prop="field105">
<el-input v-model="formData.field105" placeholder="请输入电话" clearable
:style="{ width: '100%' }">
</el-input>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="信用度" prop="field106">
<el-radio-group v-model="formData.field106" size="medium">
<el-radio v-for="(item, index) in field106Options" :key="index" :label="item.value"
:disabled="item.disabled">{{ item.label }}</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="16">
<el-form-item label="客户地址" prop="field107">
<el-select v-model="formData.field107" placeholder="请选择客户地址" clearable
:style="{ width: '100%' }">
<el-option v-for="(item, index) in field107Options" :key="index" :label="item.label"
:value="item.value" :disabled="item.disabled"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="备注" prop="field108">
<el-input v-model="formData.field108" type="textarea" placeholder="请输入备注"
:autosize="{ minRows: 4, maxRows: 4 }" :style="{ width: '100%' }"></el-input>
</el-form-item>
</el-col>
</el-row>
</el-card>
<el-card>
<div class="tit">主要负责人</div>
<el-row>
<el-col :span="8">
<el-form-item label="姓名" prop="field109">
<el-input v-model="formData.field109" placeholder="请输入姓名" clearable
:style="{ width: '100%' }">
</el-input>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="职位" prop="field110">
<el-input v-model="formData.field110" placeholder="请输入职位" clearable
:style="{ width: '100%' }">
</el-input>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="手机" prop="field111">
<el-input v-model="formData.field111" placeholder="请输入手机" clearable
:style="{ width: '100%' }">
</el-input>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="邮箱" prop="field112">
<el-input v-model="formData.field112" placeholder="请输入邮箱" clearable
:style="{ width: '100%' }">
</el-input>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="电话" prop="field113">
<el-input v-model="formData.field113" placeholder="请输入电话" clearable
:style="{ width: '100%' }">
</el-input>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="备注" prop="field114">
<el-input v-model="formData.field114" placeholder="请输入备注" clearable
:style="{ width: '100%' }">
</el-input>
</el-form-item>
</el-col>
</el-row>
</el-card>
<el-card>
<div class="tit">其他联系人</div>
<el-row>
<el-col :span="6">
<el-form-item label="姓名" prop="field116">
<el-input v-model="formData.field116" placeholder="请输入姓名" clearable
:style="{ width: '100%' }">
</el-input>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="职位" prop="field117">
<el-input v-model="formData.field117" placeholder="请输入职位" clearable
:style="{ width: '100%' }">
</el-input>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="手机" prop="field118">
<el-input v-model="formData.field118" placeholder="请输入手机" clearable
:style="{ width: '100%' }">
</el-input>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="电话" prop="field119">
<el-input v-model="formData.field119" placeholder="请输入电话" clearable
:style="{ width: '100%' }">
</el-input>
</el-form-item>
</el-col>
<el-col :span="9">
<el-form-item label="邮箱" prop="field120">
<el-input v-model="formData.field120" placeholder="请输入邮箱" clearable
:style="{ width: '100%' }">
</el-input>
</el-form-item>
</el-col>
<el-col :span="9">
<el-form-item label="备注" prop="field121">
<el-input v-model="formData.field121" placeholder="请输入备注" clearable
:style="{ width: '100%' }">
</el-input>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="附件" prop="field122">
<el-upload ref="field122" :file-list="field122fileList" :action="field122Action"
:before-upload="field122BeforeUpload">
<el-button size="small" type="primary" icon="el-icon-upload">点击上传</el-button>
</el-upload>
</el-form-item>
</el-col>
</el-row>
</el-card>
<el-card>
<div class="tit">开票信息</div>
<el-row>
<el-col :span="8">
<el-form-item label="开票公司" prop="field123">
<el-input v-model="formData.field123" placeholder="请输入开票公司" clearable
:style="{ width: '100%' }">
</el-input>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="纳税人识别" prop="field124">
<el-input v-model="formData.field124" placeholder="请输入纳税人识别" clearable
:style="{ width: '100%' }">
</el-input>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="开户地址" prop="field125">
<el-input v-model="formData.field125" placeholder="请输入开户地址" clearable
:style="{ width: '100%' }">
</el-input>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="电话" prop="field126">
<el-input v-model="formData.field126" placeholder="请输入电话" clearable
:style="{ width: '100%' }">
</el-input>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="开户地址" prop="field127">
<el-input v-model="formData.field127" placeholder="请输入开户地址" clearable
:style="{ width: '100%' }">
</el-input>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="银行账号" prop="field128">
<el-input v-model="formData.field128" placeholder="请输入银行账号" clearable
:style="{ width: '100%' }">
</el-input>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item size="large">
<el-button type="primary" @click="submitForm">提交</el-button>
<el-button @click="resetForm">重置</el-button>
</el-form-item>
</el-col>
</el-row>
</el-card>
</el-form>
</el-row>
</div>
</template>
<script>
export default {
components: {},
props: [],
data() {
return {
formData: {
field101: undefined,
field103: undefined,
field104: undefined,
field105: undefined,
field106: undefined,
field107: undefined,
field108: undefined,
field109: undefined,
field110: undefined,
field111: undefined,
field112: undefined,
field113: undefined,
field114: undefined,
field116: undefined,
field117: undefined,
field118: undefined,
field119: undefined,
field120: undefined,
field121: undefined,
field122: null,
field123: undefined,
field124: undefined,
field125: undefined,
field126: undefined,
field127: undefined,
field128: undefined,
},
rules: {
field101: [{
required: true,
message: '请输入本文行单客户姓名',
trigger: 'blur'
}],
field103: [],
field104: [],
field105: [{
required: true,
message: '请输入电话',
trigger: 'blur'
}],
field106: [],
field107: [],
field108: [],
field109: [{
required: true,
message: '请输入姓名',
trigger: 'blur'
}],
field110: [],
field111: [],
field112: [],
field113: [],
field114: [],
field116: [],
field117: [],
field118: [],
field119: [],
field120: [],
field121: [],
field123: [],
field124: [],
field125: [],
field126: [],
field127: [{
required: true,
message: '请输入开户地址',
trigger: 'blur'
}],
field128: [],
},
field122Action: 'https://jsonplaceholder.typicode.com/posts/',
field122fileList: [],
field103Options: [{
"label": "选项一",
"value": 1
}, {
"label": "选项二",
"value": 2
}],
field106Options: [{
"label": "良好",
"value": 1
}, {
"label": "一般",
"value": 2
}, {
"label": "较差",
"value": ""
}],
field107Options: [{
"label": "选项一",
"value": 1
}, {
"label": "选项二",
"value": 2
}],
}
},
computed: {},
watch: {},
created() { },
mounted() { },
methods: {
submitForm() {
this.$refs['elForm'].validate(valid => {
if (!valid) return
// TODO
})
},
resetForm() {
this.$refs['elForm'].resetFields()
},
field122BeforeUpload(file) {
let isRightSize = file.size / 1024 / 1024 < 2
if (!isRightSize) {
this.$message.error('文件大小超过 2MB')
}
return isRightSize
},
}
}
</script>
<style>
.el-upload__tip {
line-height: 1.2;
}
.tit {
font-size: 17px;
margin-bottom: 10px;
}
</style>

330
src/views/custom/edit.vue Normal file
View File

@ -0,0 +1,330 @@
<template>
<div class="edit-popup">
<popup ref="popupRef" :title="popupTitle" :async="true" width="80%" @confirm="handleSubmit" @close="handleClose">
<el-form ref="formRef" :model="formData" label-width="90px" :rules="formRules">
<el-card class="mb-2">
<div class="tit">客户基本资料</div>
<el-row>
<el-col :span="8">
<el-form-item label="客户姓名" prop="name">
<el-input v-model="formData.name" placeholder="请输入本文行单客户姓名" clearable
:style="{ width: '100%' }"></el-input>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="客户属性" prop="custom_type">
<el-select class="flex-1" v-model="formData.custom_type" clearable placeholder="请选择客户属性">
<el-option v-for="(item, index) in dictData.custom_type" :key="index" :label="item.name"
:value="parseInt(item.value)" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="上级公司" prop="parent_company">
<el-input v-model="formData.parent_company" placeholder="请输入上级公司" clearable
:style="{ width: '100%' }">
</el-input>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="电话" prop="phone">
<el-input v-model="formData.phone" placeholder="请输入电话" clearable :style="{ width: '100%' }">
</el-input>
</el-form-item>
</el-col>
<el-col :span="16">
<el-form-item label="信用度" prop="credit_rating">
<el-radio-group v-model="formData.credit_rating" placeholder="请选择信用度">
<el-radio v-for="(item, index) in dictData.credit_rating" :key="index"
:label="parseInt(item.value)">
{{ item.name }}
</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="4">
<el-form-item label="省" prop="province"
:rules="[{ required: true, message: '不可为空', trigger: 'blur' }]">
<el-select v-model="formData.province" clearable placeholder="请选择省"
@change="province_change">
<el-option v-for="(item, index) in datas.provinceOptions" :key="index"
:label="item.province_name" :value="parseInt(item.province_code)" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="4">
<el-form-item label="市" prop="city"
:rules="[{ required: true, message: '不可为空', trigger: 'blur' }]">
<el-select v-model="formData.city" clearable placeholder="请选择市" @change="city_change">
<el-option v-for="(item, index) in datas.cityOptions" :key="index"
:label="item.city_name" :value="parseInt(item.city_code)" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="4">
<el-form-item label="区" prop="area"
:rules="[{ required: true, message: '不可为空', trigger: 'blur' }]">
<el-select v-model="formData.area" clearable placeholder="请选择区" @change="area_change">
<el-option v-for="(item, index) in datas.areaOptions" :key="index"
:label="item.area_name" :value="parseInt(item.area_code)" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="地址" prop="address">
<el-input v-model="formData.address" clearable placeholder="请输入地址" />
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="备注" prop="notes">
<el-input v-model="formData.notes" type="textarea" placeholder="请输入备注"
:autosize="{ minRows: 4, maxRows: 4 }" :style="{ width: '100%' }"></el-input>
</el-form-item>
</el-col>
</el-row>
</el-card>
<el-card class="mb-2">
<div class="tit">主要负责人</div>
<el-row>
<el-col :span="8">
<el-form-item label="姓名" prop="master_name">
<el-input v-model="formData.master_name" placeholder="请输入姓名" clearable
:style="{ width: '100%' }">
</el-input>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="职位" prop="master_position">
<el-input v-model="formData.master_position" placeholder="请输入职位" clearable
:style="{ width: '100%' }">
</el-input>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="手机" prop="master_phone">
<el-input v-model="formData.master_phone" placeholder="请输入手机" clearable
:style="{ width: '100%' }">
</el-input>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="邮箱" prop="master_email">
<el-input v-model="formData.master_email" placeholder="请输入邮箱" clearable
:style="{ width: '100%' }">
</el-input>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="电话" prop="master_telephone">
<el-input v-model="formData.master_telephone" placeholder="请输入电话" clearable
:style="{ width: '100%' }">
</el-input>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="备注" prop="master_notes">
<el-input v-model="formData.master_notes" placeholder="请输入备注" clearable
:style="{ width: '100%' }">
</el-input>
</el-form-item>
</el-col>
</el-row>
</el-card>
<el-card class="mb-2">
<div class="tit">开票信息</div>
<el-row>
<el-col :span="8">
<el-form-item label="开票公司" prop="company_name">
<el-input v-model="formData.company_name" placeholder="请输入开票公司" clearable
:style="{ width: '100%' }">
</el-input>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="纳税人识别" prop="company_tin">
<el-input v-model="formData.company_tin" placeholder="请输入纳税人识别" clearable
:style="{ width: '100%' }">
</el-input>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="开户地址" prop="bank_open_address">
<el-input v-model="formData.bank_open_address" placeholder="请输入开户地址" clearable
:style="{ width: '100%' }">
</el-input>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="公司电话" prop="company_telephone">
<el-input v-model="formData.company_telephone" placeholder="请输入公司电话" clearable
:style="{ width: '100%' }">
</el-input>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="开户银行" prop="bank_name">
<el-input v-model="formData.bank_name" placeholder="请输入开户银行" clearable
:style="{ width: '100%' }">
</el-input>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="银行账号" prop="bank_account">
<el-input v-model="formData.bank_account" placeholder="请输入银行账号" clearable
:style="{ width: '100%' }">
</el-input>
</el-form-item>
</el-col>
</el-row>
</el-card>
</el-form>
</popup>
</div>
</template>
<script lang="ts" setup name="customEdit">
import {
apiCityList,
apiAreaList,
apiProvinceList,
} from "@/api/common";
import type { FormInstance } from 'element-plus'
import Popup from '@/components/popup/index.vue'
import { apiCustomAdd, apiCustomEdit, apiCustomDetail } from '@/api/custom'
import { timeFormat } from '@/utils/util'
import type { PropType } from 'vue'
defineProps({
dictData: {
type: Object as PropType<Record<string, any[]>>,
default: () => ({})
}
})
const emit = defineEmits(['success', 'close'])
const formRef = shallowRef<FormInstance>()
const popupRef = shallowRef<InstanceType<typeof Popup>>()
const mode = ref('add')
const datas = reactive({
provinceOptions: [],
cityOptions: [],
areaOptions: [],
});
//
const popupTitle = computed(() => {
return mode.value == 'edit' ? '编辑客户表' : '新增客户表'
})
//
const formData = reactive({
id: '',
name: '',
custom_type: '',
parent_company: '',
phone: '',
credit_rating: '',
province: '',
city: '',
street: '',
address: '',
notes: '',
master_name: '',
master_position: '',
master_phone: '',
master_email: '',
master_telephone: '',
master_notes: '',
company_name: '',
company_tin: '',
bank_open_address: '',
company_telephone: '',
bank_name: '',
bank_account: '',
status: '',
})
//
const formRules = reactive<any>({
})
//
const setFormData = async (data: Record<any, any>) => {
for (const key in formData) {
if (data[key] != null && data[key] != undefined) {
//@ts-ignore
formData[key] = data[key]
}
}
}
const getDetail = async (row: Record<string, any>) => {
const data = await apiCustomDetail({
id: row.id
})
setFormData(data)
}
//
const handleSubmit = async () => {
await formRef.value?.validate()
const data = { ...formData, }
mode.value == 'edit'
? await apiCustomEdit(data)
: await apiCustomAdd(data)
popupRef.value?.close()
emit('success')
}
//
const open = (type = 'add') => {
mode.value = type
popupRef.value?.open()
}
//
const handleClose = () => {
emit('close')
}
//
function province_change (value: string) {
getCityList();
}
function city_change (value: string) {
getAreaList();
}
// function brigade_change(value: string) {
// formData.brigade = value
// }
const getProvinceList = async () => {
const data = await apiProvinceList({});
datas["provinceOptions"] = data;
};
const getCityList = async () => {
const data = await apiCityList({ city: formData.province });
datas["cityOptions"] = data;
};
const getAreaList = async () => {
const data = await apiAreaList({ area: formData.city });
datas["areaOptions"] = data;
};
getProvinceList();
defineExpose({
open,
setFormData,
getDetail
})
</script>

139
src/views/custom/index.vue Normal file
View File

@ -0,0 +1,139 @@
<template>
<div>
<el-card class="!border-none mb-4" shadow="never">
<el-form class="mb-[-16px]" :model="queryParams" inline>
<el-form-item label="客户名称" prop="name">
<el-input class="w-[280px]" v-model="queryParams.name" clearable placeholder="请输入客户名称" />
</el-form-item>
<el-form-item label="客户属性" prop="custom_type">
<el-select class="w-[280px]" v-model="queryParams.custom_type" clearable placeholder="请选择客户属性">
<el-option label="全部" value=""></el-option>
<el-option v-for="(item, index) in dictData.custom_type" :key="index" :label="item.name"
:value="item.value" />
</el-select>
</el-form-item>
<el-form-item label="电话" prop="phone">
<el-input class="w-[280px]" v-model="queryParams.phone" clearable placeholder="请输入电话" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="resetPage">查询</el-button>
<el-button @click="resetParams">重置</el-button>
</el-form-item>
</el-form>
</el-card>
<el-card class="!border-none" v-loading="pager.loading" shadow="never">
<el-button v-perms="['custom.custom/add']" type="primary" @click="handleAdd">
<template #icon>
<icon name="el-icon-Plus" />
</template>
新增
</el-button>
<el-button v-perms="['custom.custom/delete']" :disabled="!selectData.length" @click="handleDelete(selectData)">
删除
</el-button>
<div class="mt-4">
<el-table :data="pager.lists" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" />
<el-table-column label="客户名称" prop="name" show-overflow-tooltip />
<el-table-column label="客户属性" prop="custom_type">
<template #default="{ row }">
<dict-value :options="dictData.custom_type" :value="row.custom_type" />
</template>
</el-table-column>
<el-table-column label="省" prop="province_name" show-overflow-tooltip />
<el-table-column label="职务" prop="master_position" show-overflow-tooltip />
<el-table-column label="电话" prop="master_telephone" show-overflow-tooltip />
<el-table-column label="手机" prop="master_phone" show-overflow-tooltip />
<el-table-column label="备注" prop="master_notes" show-overflow-tooltip />
<el-table-column label="负责人" show-overflow-tooltip />
<el-table-column label="创建时间" prop="create_time" show-overflow-tooltip />
<el-table-column label="最后跟进" show-overflow-tooltip />
<el-table-column label="下次回访日期" show-overflow-tooltip />
<el-table-column label="操作" width="120" fixed="right">
<template #default="{ row }">
<el-button v-perms="['custom.custom/edit']" type="primary" link @click="handleEdit(row)">
编辑
</el-button>
<el-button v-perms="['custom.custom/delete']" type="danger" link @click="handleDelete(row.id)">
删除
</el-button>
</template>
</el-table-column>
</el-table>
</div>
<div class="flex mt-4 justify-end">
<pagination v-model="pager" @change="getLists" />
</div>
</el-card>
<edit-popup v-if="showEdit" ref="editRef" :dict-data="dictData" @success="getLists" @close="showEdit = false" />
</div>
</template>
<script lang="ts" setup name="customLists">
import { usePaging } from '@/hooks/usePaging'
import { useDictData } from '@/hooks/useDictOptions'
import { apiCustomLists, apiCustomDelete } from '@/api/custom'
import { timeFormat } from '@/utils/util'
import feedback from '@/utils/feedback'
import EditPopup from './edit.vue'
const editRef = shallowRef<InstanceType<typeof EditPopup>>()
//
const showEdit = ref(false)
//
const queryParams = reactive({
name: '',
custom_type: '',
phone: '',
credit_rating: '',
province: '',
city: '',
status: ''
})
//
const selectData = ref<any[]>([])
//
const handleSelectionChange = (val: any[]) => {
selectData.value = val.map(({ id }) => id)
}
//
const { dictData } = useDictData('custom_type,credit_rating')
//
const { pager, getLists, resetParams, resetPage } = usePaging({
fetchFun: apiCustomLists,
params: queryParams
})
//
const handleAdd = async () => {
showEdit.value = true
await nextTick()
editRef.value?.open('add')
}
//
const handleEdit = async (data: any) => {
showEdit.value = true
await nextTick()
editRef.value?.open('edit')
editRef.value?.setFormData(data)
}
//
const handleDelete = async (id: number | any[]) => {
await feedback.confirm('确定要删除?')
await apiCustomDelete({ id })
getLists()
}
getLists()
</script>

View File

@ -0,0 +1,161 @@
<template>
<div class="edit-popup">
<popup ref="popupRef" :title="popupTitle" :async="true" width="80%" @confirm="handleSubmit" @close="handleClose">
<el-form ref="formRef" :model="formData" label-width="90px" :rules="formRules">
<el-row>
<el-col :span="12">
<el-form-item label="客户名称" prop="custom_id">
<el-input v-model="formData.custom_name" clearable placeholder="请选择客户"
@click="showDialog = true" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="姓名" prop="name">
<el-input v-model="formData.name" clearable placeholder="请输入姓名" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="职位" prop="position">
<el-input v-model="formData.position" clearable placeholder="请输入职位" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="手机" prop="phone">
<el-input v-model="formData.phone" clearable placeholder="请输入手机" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="电话" prop="telephone">
<el-input v-model="formData.telephone" clearable placeholder="请输入电话" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="邮箱" prop="email">
<el-input v-model="formData.email" clearable placeholder="请输入邮箱" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="备注" prop="notes">
<el-input v-model="formData.notes" clearable placeholder="请输入备注" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="附件" prop="annex">
<material-picker v-model="formData.annex" />
</el-form-item>
</el-col>
</el-row>
<el-dialog v-model="showDialog">
<DialogIndex @customEvent="customEvent"></DialogIndex>
</el-dialog>
</el-form>
</popup>
</div>
</template>
<script lang="ts" setup name="customContactsEdit">
import type { FormInstance } from 'element-plus'
import Popup from '@/components/popup/index.vue'
import customDialog from '@/components/custom-dialog/index.vue'
import { apiCustomContactsAdd, apiCustomContactsEdit, apiCustomContactsDetail } from '@/api/custom_contacts'
import { timeFormat } from '@/utils/util'
import type { PropType } from 'vue'
defineProps({
dictData: {
type: Object as PropType<Record<string, any[]>>,
default: () => ({})
}
})
const showDialog = ref(false);
const emit = defineEmits(['success', 'close'])
const formRef = shallowRef<FormInstance>()
const popupRef = shallowRef<InstanceType<typeof Popup>>()
const mode = ref('add')
const customEvent = (e: any) => {
formData.custom_id = e.id;
formData.custom_name = e.name;
showDialog.value = false;
};
//
const popupTitle = computed(() => {
return mode.value == 'edit' ? '编辑客户联系人' : '新增客户联系人'
})
//
const formData = reactive({
id: '',
custom_id: '',
custom_name: '',
name: '',
position: '',
phone: '',
telephone: '',
email: '',
notes: '',
annex: '',
status: '',
})
//
const formRules = reactive<any>({
custom_id: [{
required: true,
message: '请输入',
trigger: ['blur']
}]
})
//
const setFormData = async (data: Record<any, any>) => {
for (const key in formData) {
if (data[key] != null && data[key] != undefined) {
//@ts-ignore
formData[key] = data[key]
}
}
}
const getDetail = async (row: Record<string, any>) => {
const data = await apiCustomContactsDetail({
id: row.id
})
setFormData(data)
}
//
const handleSubmit = async () => {
await formRef.value?.validate()
const data = { ...formData, }
mode.value == 'edit'
? await apiCustomContactsEdit(data)
: await apiCustomContactsAdd(data)
popupRef.value?.close()
emit('success')
}
//
const open = (type = 'add') => {
mode.value = type
popupRef.value?.open()
}
//
const handleClose = () => {
emit('close')
}
defineExpose({
open,
setFormData,
getDetail
})
</script>

View File

@ -0,0 +1,128 @@
<template>
<div>
<el-card class="!border-none mb-4" shadow="never">
<el-form class="mb-[-16px]" :model="queryParams" inline>
<el-form-item label="姓名" prop="name">
<el-input class="w-[280px]" v-model="queryParams.name" clearable placeholder="请输入姓名" />
</el-form-item>
<el-form-item label="手机" prop="phone">
<el-input class="w-[280px]" v-model="queryParams.phone" clearable placeholder="请输入手机" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="resetPage">查询</el-button>
<el-button @click="resetParams">重置</el-button>
</el-form-item>
</el-form>
</el-card>
<el-card class="!border-none" v-loading="pager.loading" shadow="never">
<el-button v-perms="['custom.custom_contacts/add']" type="primary" @click="handleAdd">
<template #icon>
<icon name="el-icon-Plus" />
</template>
新增
</el-button>
<el-button v-perms="['custom.custom_contacts/delete']" :disabled="!selectData.length"
@click="handleDelete(selectData)">
删除
</el-button>
<div class="mt-4">
<el-table :data="pager.lists" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" />
<el-table-column label="组织" prop="custom_id" show-overflow-tooltip />
<el-table-column label="姓名" prop="name" show-overflow-tooltip />
<el-table-column label="职位" prop="position" show-overflow-tooltip />
<el-table-column label="手机" prop="phone" show-overflow-tooltip />
<el-table-column label="电话" prop="telephone" show-overflow-tooltip />
<el-table-column label="邮箱" prop="email" show-overflow-tooltip />
<el-table-column label="备注" prop="notes" show-overflow-tooltip />
<el-table-column label="状态" prop="status" show-overflow-tooltip />
<el-table-column label="操作" width="120" fixed="right">
<template #default="{ row }">
<el-button v-perms="['custom.custom_contacts/edit']" type="primary" link
@click="handleEdit(row)">
编辑
</el-button>
<el-button v-perms="['custom.custom_contacts/delete']" type="danger" link
@click="handleDelete(row.id)">
删除
</el-button>
</template>
</el-table-column>
</el-table>
</div>
<div class="flex mt-4 justify-end">
<pagination v-model="pager" @change="getLists" />
</div>
</el-card>
<edit-popup v-if="showEdit" ref="editRef" :dict-data="dictData" @success="getLists" @close="showEdit = false" />
</div>
</template>
<script lang="ts" setup name="customContactsLists">
import { usePaging } from '@/hooks/usePaging'
import { useDictData } from '@/hooks/useDictOptions'
import { apiCustomContactsLists, apiCustomContactsDelete } from '@/api/custom_contacts'
import { timeFormat } from '@/utils/util'
import feedback from '@/utils/feedback'
import EditPopup from './edit.vue'
const editRef = shallowRef<InstanceType<typeof EditPopup>>()
//
const showEdit = ref(false)
//
const queryParams = reactive({
custom_id: '',
name: '',
position: '',
phone: '',
telephone: '',
email: '',
notes: '',
annex: '',
status: ''
})
//
const selectData = ref<any[]>([])
//
const handleSelectionChange = (val: any[]) => {
selectData.value = val.map(({ id }) => id)
}
//
const { dictData } = useDictData('')
//
const { pager, getLists, resetParams, resetPage } = usePaging({
fetchFun: apiCustomContactsLists,
params: queryParams
})
//
const handleAdd = async () => {
showEdit.value = true
await nextTick()
editRef.value?.open('add')
}
//
const handleEdit = async (data: any) => {
showEdit.value = true
await nextTick()
editRef.value?.open('edit')
editRef.value?.setFormData(data)
}
//
const handleDelete = async (id: number | any[]) => {
await feedback.confirm('确定要删除?')
await apiCustomContactsDelete({ id })
getLists()
}
getLists()
</script>

View File

@ -0,0 +1,146 @@
<template>
<div class="edit-popup">
<popup ref="popupRef" :title="popupTitle" :async="true" width="60%" @confirm="handleSubmit" @close="handleClose">
<el-form ref="formRef" :model="formData" label-width="90px" :rules="formRules">
<el-form-item label="主题" prop="name">
<el-input v-model="formData.name" clearable placeholder="请输入主题" />
</el-form-item>
<el-form-item label="客户名称" prop="custom_id">
<el-input v-model="formData.custom_id" clearable placeholder="请选择客户" />
</el-form-item>
<el-form-item label="联系人" prop="contacts">
<el-input v-model="formData.contacts" clearable placeholder="请输入联系人" />
</el-form-item>
<el-form-item label="日期" prop="date">
<el-date-picker class="flex-1 !flex" v-model="formData.date" clearable type="datetime"
value-format="YYYY-MM-DD HH:mm:ss" placeholder="选择日期">
</el-date-picker>
</el-form-item>
<el-form-item label="类型" prop="types">
<el-select class="flex-1" v-model="formData.types" clearable placeholder="请选择类型">
<el-option v-for="(item, index) in dictData.types" :key="index" :label="item.name"
:value="parseInt(item.value)" />
</el-select>
</el-form-item>
<el-form-item label="执行人" prop="admin_id">
<el-input v-model="formData.admin_id" clearable placeholder="请输入执行人" />
</el-form-item>
<el-form-item label="行动描述" prop="description">
<el-input v-model="formData.description" clearable placeholder="请输入行动描述" />
</el-form-item>
<el-form-item label="附件/现场照片" prop="annex">
<material-picker v-model="formData.annex" />
</el-form-item>
<el-form-item label="位置" prop="coordinate">
<el-input v-model="formData.coordinate" clearable placeholder="请输入位置" />
</el-form-item>
<el-form-item label="下次回访日期" prop="next_follow_date">
<el-date-picker class="flex-1 !flex" v-model="formData.next_follow_date" clearable type="datetime"
value-format="YYYY-MM-DD HH:mm:ss" placeholder="选择下次回访日期">
</el-date-picker>
</el-form-item>
</el-form>
</popup>
</div>
</template>
<script lang="ts" setup name="customFollowEdit">
import type { FormInstance } from 'element-plus'
import Popup from '@/components/popup/index.vue'
import { apiCustomFollowAdd, apiCustomFollowEdit, apiCustomFollowDetail } from '@/api/custom_follow'
import { timeFormat } from '@/utils/util'
import type { PropType } from 'vue'
defineProps({
dictData: {
type: Object as PropType<Record<string, any[]>>,
default: () => ({})
}
})
const emit = defineEmits(['success', 'close'])
const formRef = shallowRef<FormInstance>()
const popupRef = shallowRef<InstanceType<typeof Popup>>()
const mode = ref('add')
//
const popupTitle = computed(() => {
return mode.value == 'edit' ? '编辑客户跟进记录' : '新增客户跟进记录'
})
//
const formData = reactive({
id: '',
name: '',
custom_id: '',
contacts: '',
date: '',
types: '',
admin_id: '',
description: '',
annex: '',
coordinate: '',
next_follow_date: '',
status: '',
})
//
const formRules = reactive<any>({
})
//
const setFormData = async (data: Record<any, any>) => {
for (const key in formData) {
if (data[key] != null && data[key] != undefined) {
//@ts-ignore
formData[key] = data[key]
}
}
//@ts-ignore
formData.date = timeFormat(formData.date, 'yyyy-mm-dd hh:MM:ss')
//@ts-ignore
formData.next_follow_date = timeFormat(formData.next_follow_date, 'yyyy-mm-dd hh:MM:ss')
}
const getDetail = async (row: Record<string, any>) => {
const data = await apiCustomFollowDetail({
id: row.id
})
setFormData(data)
}
//
const handleSubmit = async () => {
await formRef.value?.validate()
const data = { ...formData, }
mode.value == 'edit'
? await apiCustomFollowEdit(data)
: await apiCustomFollowAdd(data)
popupRef.value?.close()
emit('success')
}
//
const open = (type = 'add') => {
mode.value = type
popupRef.value?.open()
}
//
const handleClose = () => {
emit('close')
}
defineExpose({
open,
setFormData,
getDetail
})
</script>

View File

@ -0,0 +1,154 @@
<template>
<div>
<el-card class="!border-none mb-4" shadow="never">
<el-form class="mb-[-16px]" :model="queryParams" inline>
<el-form-item label="联系人" prop="contacts">
<el-input class="w-[280px]" v-model="queryParams.contacts" clearable placeholder="请输入联系人" />
</el-form-item>
<el-form-item label="类型" prop="types">
<el-select class="w-[280px]" v-model="queryParams.types" clearable placeholder="请选择类型">
<el-option label="全部" value=""></el-option>
<el-option v-for="(item, index) in dictData.types" :key="index" :label="item.name"
:value="item.value" />
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="resetPage">查询</el-button>
<el-button @click="resetParams">重置</el-button>
</el-form-item>
</el-form>
</el-card>
<el-card class="!border-none" v-loading="pager.loading" shadow="never">
<el-button v-perms="['custom_follow.custom_follow/add']" type="primary" @click="handleAdd">
<template #icon>
<icon name="el-icon-Plus" />
</template>
新增
</el-button>
<el-button v-perms="['custom_follow.custom_follow/delete']" :disabled="!selectData.length"
@click="handleDelete(selectData)">
删除
</el-button>
<div class="mt-4">
<el-table :data="pager.lists" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" />
<el-table-column label="" prop="custom_id" show-overflow-tooltip />
<el-table-column label="联系人" prop="contacts" show-overflow-tooltip />
<el-table-column label="日期" prop="date">
<template #default="{ row }">
<span>{{ row.date ? timeFormat(row.date, 'yyyy-mm-dd hh:MM:ss') : '' }}</span>
</template>
</el-table-column>
<el-table-column label="类型" prop="types">
<template #default="{ row }">
<dict-value :options="dictData.types" :value="row.types" />
</template>
</el-table-column>
<el-table-column label="执行人" prop="admin_id" show-overflow-tooltip />
<el-table-column label="行动描述" prop="description" show-overflow-tooltip />
<el-table-column label="附件/现场照片" prop="annex">
<template #default="{ row }">
<el-image style="width:50px;height:50px;" :src="row.annex" />
</template>
</el-table-column>
<el-table-column label="位置" prop="coordinate" show-overflow-tooltip />
<el-table-column label="下次回访日期" prop="next_follow_date">
<template #default="{ row }">
<span>{{ row.next_follow_date ? timeFormat(row.next_follow_date, 'yyyy-mm-dd hh:MM:ss') : ''
}}</span>
</template>
</el-table-column>
<el-table-column label="状态" prop="status" show-overflow-tooltip />
<el-table-column label="操作" width="120" fixed="right">
<template #default="{ row }">
<el-button v-perms="['custom_follow.custom_follow/edit']" type="primary" link
@click="handleEdit(row)">
编辑
</el-button>
<el-button v-perms="['custom_follow.custom_follow/delete']" type="danger" link
@click="handleDelete(row.id)">
删除
</el-button>
</template>
</el-table-column>
</el-table>
</div>
<div class="flex mt-4 justify-end">
<pagination v-model="pager" @change="getLists" />
</div>
</el-card>
<edit-popup v-if="showEdit" ref="editRef" :dict-data="dictData" @success="getLists" @close="showEdit = false" />
</div>
</template>
<script lang="ts" setup name="customFollowLists">
import { usePaging } from '@/hooks/usePaging'
import { useDictData } from '@/hooks/useDictOptions'
import { apiCustomFollowLists, apiCustomFollowDelete } from '@/api/custom_follow'
import { timeFormat } from '@/utils/util'
import feedback from '@/utils/feedback'
import EditPopup from './edit.vue'
const editRef = shallowRef<InstanceType<typeof EditPopup>>()
//
const showEdit = ref(false)
//
const queryParams = reactive({
custom_id: '',
contacts: '',
date: '',
types: '',
admin_id: '',
description: '',
annex: '',
coordinate: '',
next_follow_date: '',
status: ''
})
//
const selectData = ref<any[]>([])
//
const handleSelectionChange = (val: any[]) => {
selectData.value = val.map(({ id }) => id)
}
//
const { dictData } = useDictData('types')
//
const { pager, getLists, resetParams, resetPage } = usePaging({
fetchFun: apiCustomFollowLists,
params: queryParams
})
//
const handleAdd = async () => {
showEdit.value = true
await nextTick()
editRef.value?.open('add')
}
//
const handleEdit = async (data: any) => {
showEdit.value = true
await nextTick()
editRef.value?.open('edit')
editRef.value?.setFormData(data)
}
//
const handleDelete = async (id: number | any[]) => {
await feedback.confirm('确定要删除?')
await apiCustomFollowDelete({ id })
getLists()
}
getLists()
</script>

View File

@ -0,0 +1,195 @@
<template>
<div class="edit-popup">
<popup ref="popupRef" :title="popupTitle" :async="true" width="80%" @confirm="handleSubmit" @close="handleClose">
<el-form ref="formRef" :model="formData" label-width="90px" :rules="formRules">
<el-row :gutter="10">
<el-col :span="12">
<el-form-item label="项目id" prop="project_id">
<el-input v-model="formData.project_id" clearable placeholder="请输入项目id" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="客户id" prop="custom_id">
<el-input v-model="formData.custom_id" clearable placeholder="请输入客户id" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="审批id" prop="approve_id">
<el-input v-model="formData.approve_id" clearable placeholder="请输入审批id" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="联系人" prop="contacts">
<el-input v-model="formData.contacts" clearable placeholder="请输入联系人" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="电话" prop="phone">
<el-input v-model="formData.phone" clearable placeholder="请输入电话" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="日期" prop="date">
<el-date-picker class="flex-1 !flex" v-model="formData.date" clearable type="datetime"
value-format="YYYY-MM-DD HH:mm:ss" placeholder="选择日期">
</el-date-picker>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="分类" prop="classification">
<el-select class="flex-1" v-model="formData.classification" clearable placeholder="请选择分类">
<el-option v-for="(item, index) in dictData.classification" :key="index" :label="item.name"
:value="parseInt(item.value)" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="紧急程度" prop="urgency">
<el-radio-group v-model="formData.urgency" placeholder="请选择紧急程度">
<el-radio v-for="(item, index) in dictData.urgency" :key="index"
:label="parseInt(item.value)">
{{ item.name }}
</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="接待人" prop="receiver">
<el-input v-model="formData.receiver" clearable placeholder="请输入接待人" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="指定处理人" prop="processed_admin_id">
<el-input v-model="formData.processed_admin_id" clearable placeholder="请输入指定处理人" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="投诉主题" prop="name">
<el-input v-model="formData.name" clearable placeholder="请输入投诉主题" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="问题描述" prop="description">
<el-input v-model="formData.description" clearable placeholder="请输入问题描述" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="备注" prop="notes">
<el-input v-model="formData.notes" clearable placeholder="请输入备注" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="附件" prop="annex">
<material-picker v-model="formData.annex" />
</el-form-item>
</el-col>
</el-row>
</el-form>
</popup>
</div>
</template>
<script lang="ts" setup name="customServiceEdit">
import type { FormInstance } from 'element-plus'
import Popup from '@/components/popup/index.vue'
import { apiCustomServiceAdd, apiCustomServiceEdit, apiCustomServiceDetail } from '@/api/custom_service'
import { timeFormat } from '@/utils/util'
import type { PropType } from 'vue'
defineProps({
dictData: {
type: Object as PropType<Record<string, any[]>>,
default: () => ({})
}
})
const emit = defineEmits(['success', 'close'])
const formRef = shallowRef<FormInstance>()
const popupRef = shallowRef<InstanceType<typeof Popup>>()
const mode = ref('add')
//
const popupTitle = computed(() => {
return mode.value == 'edit' ? '编辑客户售后' : '新增客户售后'
})
//
const formData = reactive({
id: '',
project_id: '',
custom_id: '',
approve_id: '',
contacts: '',
phone: '',
date: '',
classification: '',
urgency: '',
receiver: '',
processed_admin_id: '',
name: '',
description: '',
notes: '',
annex: '',
status: '',
})
//
const formRules = reactive<any>({
})
//
const setFormData = async (data: Record<any, any>) => {
for (const key in formData) {
if (data[key] != null && data[key] != undefined) {
//@ts-ignore
formData[key] = data[key]
}
}
//@ts-ignore
formData.date = timeFormat(formData.date, 'yyyy-mm-dd hh:MM:ss')
}
const getDetail = async (row: Record<string, any>) => {
const data = await apiCustomServiceDetail({
id: row.id
})
setFormData(data)
}
//
const handleSubmit = async () => {
await formRef.value?.validate()
const data = { ...formData, }
mode.value == 'edit'
? await apiCustomServiceEdit(data)
: await apiCustomServiceAdd(data)
popupRef.value?.close()
emit('success')
}
//
const open = (type = 'add') => {
mode.value = type
popupRef.value?.open()
}
//
const handleClose = () => {
emit('close')
}
defineExpose({
open,
setFormData,
getDetail
})
</script>

View File

@ -0,0 +1,160 @@
<template>
<div>
<el-card class="!border-none mb-4" shadow="never">
<el-form class="mb-[-16px]" :model="queryParams" inline>
<el-form-item label="项目" prop="project_id">
<el-input class="w-[280px]" v-model="queryParams.project_id" clearable placeholder="请输入项目id" />
</el-form-item>
<el-form-item label="客户" prop="custom_id">
<el-input class="w-[280px]" v-model="queryParams.custom_id" clearable placeholder="请输入客户id" />
</el-form-item>
<el-form-item label="紧急程度" prop="urgency">
<el-select class="w-[280px]" v-model="queryParams.urgency" clearable placeholder="请选择紧急程度">
<el-option label="全部" value=""></el-option>
<el-option v-for="(item, index) in dictData.urgency" :key="index" :label="item.name"
:value="item.value" />
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="resetPage">查询</el-button>
<el-button @click="resetParams">重置</el-button>
</el-form-item>
</el-form>
</el-card>
<el-card class="!border-none" v-loading="pager.loading" shadow="never">
<el-button v-perms="['custom_service.custom_service/add']" type="primary" @click="handleAdd">
<template #icon>
<icon name="el-icon-Plus" />
</template>
新增
</el-button>
<el-button v-perms="['custom_service.custom_service/delete']" :disabled="!selectData.length"
@click="handleDelete(selectData)">
删除
</el-button>
<div class="mt-4">
<el-table :data="pager.lists" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" />
<el-table-column label="项目" prop="project_id" show-overflow-tooltip />
<el-table-column label="客户" prop="custom_id" show-overflow-tooltip />
<el-table-column label="审批" prop="approve_id" show-overflow-tooltip />
<el-table-column label="联系人" prop="contacts" show-overflow-tooltip />
<el-table-column label="电话" prop="phone" show-overflow-tooltip />
<el-table-column label="日期" prop="date">
<template #default="{ row }">
<span>{{ row.date ? timeFormat(row.date, 'yyyy-mm-dd hh:MM:ss') : '' }}</span>
</template>
</el-table-column>
<el-table-column label="分类" prop="classification">
<template #default="{ row }">
<dict-value :options="dictData.classification" :value="row.classification" />
</template>
</el-table-column>
<el-table-column label="紧急程度" prop="urgency">
<template #default="{ row }">
<dict-value :options="dictData.urgency" :value="row.urgency" />
</template>
</el-table-column>
<el-table-column label="接待人" prop="receiver" show-overflow-tooltip />
<el-table-column label="指定处理人" prop="processed_admin_id" show-overflow-tooltip />
<el-table-column label="投诉主题" prop="name" show-overflow-tooltip />
<el-table-column label="问题描述" prop="description" show-overflow-tooltip />
<el-table-column label="备注" prop="notes" show-overflow-tooltip />
<el-table-column label="状态" prop="status" show-overflow-tooltip />
<el-table-column label="操作" width="120" fixed="right">
<template #default="{ row }">
<el-button v-perms="['custom_service.custom_service/edit']" type="primary" link
@click="handleEdit(row)">
编辑
</el-button>
<el-button v-perms="['custom_service.custom_service/delete']" type="danger" link
@click="handleDelete(row.id)">
删除
</el-button>
</template>
</el-table-column>
</el-table>
</div>
<div class="flex mt-4 justify-end">
<pagination v-model="pager" @change="getLists" />
</div>
</el-card>
<edit-popup v-if="showEdit" ref="editRef" :dict-data="dictData" @success="getLists" @close="showEdit = false" />
</div>
</template>
<script lang="ts" setup name="customServiceLists">
import { usePaging } from '@/hooks/usePaging'
import { useDictData } from '@/hooks/useDictOptions'
import { apiCustomServiceLists, apiCustomServiceDelete } from '@/api/custom_service'
import { timeFormat } from '@/utils/util'
import feedback from '@/utils/feedback'
import EditPopup from './edit.vue'
const editRef = shallowRef<InstanceType<typeof EditPopup>>()
//
const showEdit = ref(false)
//
const queryParams = reactive({
project_id: '',
custom_id: '',
approve_id: '',
contacts: '',
phone: '',
date: '',
classification: '',
urgency: '',
receiver: '',
processed_admin_id: '',
name: '',
description: '',
notes: '',
annex: '',
status: ''
})
//
const selectData = ref<any[]>([])
//
const handleSelectionChange = (val: any[]) => {
selectData.value = val.map(({ id }) => id)
}
//
const { dictData } = useDictData('classification,urgency')
//
const { pager, getLists, resetParams, resetPage } = usePaging({
fetchFun: apiCustomServiceLists,
params: queryParams
})
//
const handleAdd = async () => {
showEdit.value = true
await nextTick()
editRef.value?.open('add')
}
//
const handleEdit = async (data: any) => {
showEdit.value = true
await nextTick()
editRef.value?.open('edit')
editRef.value?.setFormData(data)
}
//
const handleDelete = async (id: number | any[]) => {
await feedback.confirm('确定要删除?')
await apiCustomServiceDelete({ id })
getLists()
}
getLists()
</script>

View File

@ -1,106 +0,0 @@
<template>
<div>
<el-card class="!border-none" shadow="never">
<el-alert
type="warning"
title="温馨提示:用户账户变动记录"
:closable="false"
show-icon
></el-alert>
<el-form ref="formRef" class="mb-[-16px] mt-[16px]" :model="queryParams" :inline="true">
<el-form-item label="用户信息">
<el-input
class="w-[280px]"
v-model="queryParams.user_info"
placeholder="请输入用户编号/昵称/手机号"
clearable
@keyup.enter="resetPage"
/>
</el-form-item>
<el-form-item label="变动类型">
<el-select class="w-[280px]" v-model="queryParams.change_type">
<el-option label="全部" value />
<el-option
v-for="(value, key) in optionsData.change_type"
:key="key"
:label="value"
:value="key"
/>
</el-select>
</el-form-item>
<el-form-item label="记录时间">
<daterange-picker
v-model:startTime="queryParams.start_time"
v-model:endTime="queryParams.end_time"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="resetPage">查询</el-button>
<el-button @click="resetParams">重置</el-button>
</el-form-item>
</el-form>
</el-card>
<el-card class="!border-none mt-4" shadow="never">
<el-table size="large" v-loading="pager.loading" :data="pager.lists">
<el-table-column label="用户编号" prop="sn" min-width="100" />
<el-table-column label="用户昵称" min-width="160">
<template #default="{ row }">
<div class="flex items-center">
<image-contain
class="flex-none mr-2"
:src="row.avatar"
:width="40"
:height="40"
preview-teleported
fit="contain"
/>
{{ row.nickname }}
</div>
</template>
</el-table-column>
<el-table-column label="手机号码" prop="mobile" min-width="100" />
<el-table-column label="变动金额" prop="change_amount" min-width="100">
<template #default="{ row }">
<span :class="{ 'text-error': row.action == 2 }">
{{ row.change_amount }}
</span>
</template>
</el-table-column>
<el-table-column label="剩余金额" prop="left_amount" min-width="100" />
<el-table-column label="变动类型" prop="change_type_desc" min-width="120" />
<el-table-column label="来源单号" prop="source_sn" min-width="100" />
<el-table-column label="记录时间" prop="create_time" min-width="120" />
</el-table>
<div class="flex justify-end mt-4">
<pagination v-model="pager" @change="getLists" />
</div>
</el-card>
</div>
</template>
<script lang="ts" setup name="articleLists">
import { getUmChangeType, accountLog } from '@/api/finance'
import { useDictOptions } from '@/hooks/useDictOptions'
import { usePaging } from '@/hooks/usePaging'
const queryParams = reactive({
user_info: '',
change_type: '',
start_time: '',
end_time: ''
})
const { pager, getLists, resetPage, resetParams } = usePaging({
fetchFun: accountLog,
params: queryParams
})
const { optionsData } = useDictOptions<{
change_type: Record<number, string>
}>({
change_type: {
api: getUmChangeType
}
})
getLists()
</script>

View File

@ -1,68 +0,0 @@
<template>
<div class="code-preview">
<el-dialog v-model="show" width="760px" title="退款日志">
<el-table size="large" v-loading="loading" :data="logLists" height="500">
<el-table-column label="流水单号" prop="sn" min-width="190" />
<el-table-column label="退款金额" min-width="110">
<template #default="{ row }"> ¥{{ row.refund_amount }} </template>
</el-table-column>
<el-table-column label="退款状态" prop="" min-width="100">
<template #default="{ row }">
<el-tag type="warning" v-if="row.refund_status == 0">
{{ row.refund_status_text }}
</el-tag>
<el-tag v-if="row.refund_status == 1">
{{ row.refund_status_text }}
</el-tag>
<el-tag type="danger" v-if="row.refund_status == 2">
{{ row.refund_status_text }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="记录时间" prop="create_time" min-width="180" />
<el-table-column label="操作人" prop="handler" min-width="120" />
</el-table>
</el-dialog>
</div>
</template>
<script lang="ts" setup>
import { refundLog } from '@/api/finance'
const loading = ref(false)
const logLists = ref([])
const props = defineProps<{
modelValue: boolean
refundId: number
}>()
const emit = defineEmits<{
(event: 'update:modelValue', value: boolean): void
}>()
const show = computed<boolean>({
get() {
return props.modelValue
},
set(value) {
emit('update:modelValue', value)
}
})
const getRefundLog = async () => {
loading.value = true
logLists.value = []
try {
const res = await refundLog({
record_id: props.refundId
})
logLists.value = res
} catch (error) {}
loading.value = false
}
watch(show, (value) => {
if (value) {
getRefundLog()
}
})
</script>

View File

@ -1,141 +0,0 @@
<template>
<div>
<el-card class="!border-none" shadow="never">
<el-alert
type="warning"
title="温馨提示:用户充值记录"
:closable="false"
show-icon
></el-alert>
<el-form ref="formRef" class="mb-[-16px] mt-[16px]" :model="queryParams" :inline="true">
<el-form-item label="充值单号">
<el-input
class="w-[280px]"
v-model="queryParams.sn"
placeholder="请输入充值单号"
clearable
@keyup.enter="resetPage"
/>
</el-form-item>
<el-form-item label="用户信息">
<el-input
class="w-[280px]"
v-model="queryParams.user_info"
placeholder="请输入用户编号/昵称/手机号"
clearable
@keyup.enter="resetPage"
/>
</el-form-item>
<el-form-item label="支付方式">
<el-select class="w-[280px]" v-model="queryParams.pay_status">
<el-option label="全部" value />
<el-option label="微信支付" :value="2" />
</el-select>
</el-form-item>
<el-form-item label="支付状态">
<el-select class="w-[280px]" v-model="queryParams.pay_way">
<el-option label="全部" value />
<el-option label="未支付" :value="0" />
<el-option label="已支付" :value="1" />
</el-select>
</el-form-item>
<el-form-item label="下单时间">
<daterange-picker
v-model:startTime="queryParams.start_time"
v-model:endTime="queryParams.end_time"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="resetPage">查询</el-button>
<el-button @click="resetParams">重置</el-button>
<export-data
class="ml-2.5"
:fetch-fun="rechargeLists"
:params="queryParams"
:page-size="pager.size"
/>
</el-form-item>
</el-form>
</el-card>
<el-card class="!border-none mt-4" shadow="never">
<el-table size="large" v-loading="pager.loading" :data="pager.lists">
<el-table-column label="用户信息" min-width="160">
<template #default="{ row }">
<div class="flex items-center">
<image-contain
class="flex-none mr-2"
:src="row.avatar"
:width="40"
:height="40"
preview-teleported
fit="contain"
/>
{{ row.nickname }}
</div>
</template>
</el-table-column>
<el-table-column label="充值单号" prop="sn" min-width="190" />
<el-table-column label="充值金额" prop="order_amount" min-width="100">
</el-table-column>
<el-table-column label="支付方式" prop="pay_way_text" min-width="100" />
<el-table-column label="支付状态" prop="" min-width="100">
<template #default="{ row }">
<span
:class="{
'text-error': row.pay_status == 0
}"
>
{{ row.pay_status_text }}
</span>
</template>
</el-table-column>
<el-table-column label="提交时间" prop="create_time" min-width="180" />
<el-table-column label="支付时间" prop="pay_time" min-width="180" />
<el-table-column label="操作" width="120" fixed="right">
<template #default="{ row }">
<el-button
v-if="row.pay_status == 1"
v-perms="['recharge.recharge/refund']"
type="primary"
link
:disabled="row.refund_status == 1"
@click="handleRefund(row.id)"
>
退款
</el-button>
</template>
</el-table-column>
</el-table>
<div class="flex justify-end mt-4">
<pagination v-model="pager" @change="getLists" />
</div>
</el-card>
</div>
</template>
<script lang="ts" setup name="articleLists">
import { rechargeLists, refund } from '@/api/finance'
import { usePaging } from '@/hooks/usePaging'
import feedback from '@/utils/feedback'
const queryParams = reactive({
sn: '',
user_info: '',
pay_way: '',
pay_status: '',
start_time: '',
end_time: ''
})
const { pager, getLists, resetPage, resetParams } = usePaging({
fetchFun: rechargeLists,
params: queryParams
})
const handleRefund = async (id: number) => {
await feedback.confirm('确认重新退款?')
await refund({
recharge_id: id
})
getLists()
}
getLists()
</script>

View File

@ -1,228 +0,0 @@
<template>
<div>
<el-card class="!border-none mb-4" shadow="never">
<div class="flex flex-wrap">
<div class="w-1/2 md:w-1/4">
<div class="leading-10">累计退款金额 ()</div>
<div class="text-6xl">{{ refundData.total }}</div>
</div>
<div class="w-1/2 md:w-1/4">
<div class="leading-10">退款中金额 ()</div>
<div class="text-6xl">{{ refundData.ing }}</div>
</div>
<div class="w-1/2 md:w-1/4">
<div class="leading-10">退款成功金额 ()</div>
<div class="text-6xl">{{ refundData.success }}</div>
</div>
<div class="w-1/2 md:w-1/4">
<div class="leading-10">退款失败金额 ()</div>
<div class="text-6xl">{{ refundData.error }}</div>
</div>
</div>
</el-card>
<el-card class="!border-none" shadow="never">
<el-form ref="formRef" class="mb-[-16px] mt-[16px]" :model="queryParams" :inline="true">
<el-form-item label="退款单号">
<el-input
class="w-[280px]"
v-model="queryParams.sn"
placeholder="请输入退款单号"
clearable
@keyup.enter="resetPage"
/>
</el-form-item>
<el-form-item label="来源单号">
<el-input
class="w-[280px]"
v-model="queryParams.order_sn"
placeholder="请输入来源单号"
clearable
@keyup.enter="resetPage"
/>
</el-form-item>
<el-form-item label="用户信息">
<el-input
class="w-[280px]"
v-model="queryParams.user_info"
placeholder="请输入用户信息"
clearable
@keyup.enter="resetPage"
/>
</el-form-item>
<el-form-item label="退款类型">
<el-select class="w-[280px]" v-model="queryParams.refund_type">
<el-option label="全部" value />
<el-option label="后台退款" :value="1" />
</el-select>
</el-form-item>
<el-form-item label="记录时间">
<daterange-picker
v-model:startTime="queryParams.start_time"
v-model:endTime="queryParams.end_time"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="resetPage">查询</el-button>
<el-button @click="resetParams">重置</el-button>
<!-- <export-data
class="ml-2.5"
:fetch-fun="refundRecord"
:params="queryParams"
:page-size="pager.size"
/> -->
</el-form-item>
</el-form>
</el-card>
<el-card class="!border-none mt-4" shadow="never">
<el-tabs v-model="activeTab" @tab-change="handleTabChange">
<el-tab-pane
v-for="(item, index) in tabLists"
:label="`${item.name}(${pager.extend[item.numKey] ?? 0})`"
:name="index"
:key="index"
>
<el-table size="large" v-loading="pager.loading" :data="pager.lists">
<el-table-column label="退款单号" prop="sn" min-width="190" />
<el-table-column label="用户信息" min-width="160">
<template #default="{ row }">
<div class="flex items-center">
<image-contain
class="flex-none mr-2"
:src="row.avatar"
:width="40"
:height="40"
preview-teleported
fit="contain"
/>
{{ row.nickname }}
</div>
</template>
</el-table-column>
<el-table-column label="来源单号" prop="order_sn" min-width="190" />
<el-table-column label="退款金额" min-width="100">
<template #default="{ row }"> ¥ {{ row.refund_amount }} </template>
</el-table-column>
<el-table-column label="退款类型" prop="refund_type_text" min-width="100" />
<el-table-column label="退款状态" prop="" min-width="100">
<template #default="{ row }">
<el-tag type="warning" v-if="row.refund_status == 0">
{{ row.refund_status_text }}
</el-tag>
<el-tag v-if="row.refund_status == 1">
{{ row.refund_status_text }}
</el-tag>
<el-tag type="danger" v-if="row.refund_status == 2">
{{ row.refund_status_text }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="记录时间" prop="create_time" min-width="180" />
<el-table-column label="操作" width="180" fixed="right">
<template #default="{ row }">
<el-button
v-perms="['finance.refund/log']"
type="primary"
link
@click="handleShowRefundLog(row.id)"
>
退款日志
</el-button>
<el-button
v-if="row.refund_status == 2"
v-perms="['recharge.recharge/refundAgain']"
type="primary"
link
@click="handleRefund(row.id)"
>
重新退款
</el-button>
</template>
</el-table-column>
</el-table>
</el-tab-pane>
</el-tabs>
<div class="flex justify-end mt-4">
<pagination v-model="pager" @change="getLists" />
</div>
</el-card>
<refund-log v-model="showRefundLog" :refund-id="selectRefundId" />
</div>
</template>
<script lang="ts" setup name="articleLists">
import { refundRecord, refundAgain, refundStat } from '@/api/finance'
import { usePaging } from '@/hooks/usePaging'
import feedback from '@/utils/feedback'
import RefundLog from './component/refund-log.vue'
const queryParams = reactive({
sn: '',
order_sn: '',
user_info: '',
refund_type: '',
start_time: '',
end_time: '',
refund_status: ''
})
const refundData = reactive({
total: 0,
ing: 0,
success: 0,
error: 0
})
const showRefundLog = ref(false)
const selectRefundId = ref(0)
const activeTab = ref(0)
const tabLists = ref([
{
name: '全部',
type: '',
numKey: 'total'
},
{
name: '退款中',
type: 0,
numKey: 'ing'
},
{
name: '退款成功',
type: 1,
numKey: 'success'
},
{
name: '退款失败',
type: 2,
numKey: 'error'
}
])
const { pager, getLists, resetPage, resetParams } = usePaging({
fetchFun: refundRecord,
params: queryParams
})
const handleRefund = async (id: number) => {
await feedback.confirm('确认重新退款?')
await refundAgain({
record_id: id
})
getLists()
getRefundStat()
}
const handleShowRefundLog = async (id: number) => {
showRefundLog.value = true
selectRefundId.value = id
}
const handleTabChange = (index: any) => {
queryParams.refund_status = tabLists.value[index].type as string
resetPage()
}
const getRefundStat = async () => {
const res = await refundStat()
Object.assign(refundData, res)
}
getRefundStat()
getLists()
</script>

View File

@ -2,21 +2,9 @@
<div class="material-index">
<el-card class="!border-none" shadow="never">
<el-tabs v-model="activeTab">
<el-tab-pane
v-for="item in tabsMap"
:label="item.name"
:name="item.type"
:index="item.type"
:key="item.type"
lazy
>
<material
:type="item.type"
mode="page"
file-size="120px"
:limit="-1"
:page-size="20"
/>
<el-tab-pane v-for="item in tabsMap" :label="item.name" :name="item.type" :index="item.type"
:key="item.type" lazy>
<material :type="item.type" mode="page" file-size="120px" :limit="-1" :page-size="20" />
</el-tab-pane>
</el-tabs>
</el-card>
@ -32,6 +20,9 @@ const tabsMap = [
{
type: 'video',
name: '视频'
}, {
type: 'file',
name: '文件'
}
]
const activeTab = ref('image')
@ -40,13 +31,16 @@ const activeTab = ref('image')
<style lang="scss" scoped>
.material-index {
min-width: 700px;
:deep(.el-tabs) {
height: calc(100vh - 180px);
display: flex;
flex-direction: column;
.el-tabs__header {
margin-bottom: 0 !important;
}
.el-tabs__content,
.el-tab-pane {
min-height: 0;

329
src/views/project/edit.vue Normal file
View File

@ -0,0 +1,329 @@
<template>
<div class="edit-popup">
<popup ref="popupRef" :title="popupTitle" :async="true" width="80%" @confirm="handleSubmit" @close="handleClose">
<el-form ref="formRef" :model="formData" label-width="auto" :rules="formRules">
<el-row :gutter="10">
<el-col :span="12">
<el-form-item label="客户名称" prop="custom_id">
<el-input v-model="formData.custom_id" clearable placeholder="请选择客户" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="项目类型" prop="project_type">
<el-select class="flex-1" v-model="formData.project_type" clearable placeholder="请选择项目类型">
<el-option v-for="(item, index) in dictData.project_type" :key="index" :label="item.name"
:value="parseInt(item.value)" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="项目名称" prop="name">
<el-input v-model="formData.name" clearable placeholder="请输入项目名称" />
</el-form-item>
</el-col> <el-col :span="12">
<el-form-item label="项目编码" prop="project_code">
<el-input v-model="formData.project_code" clearable placeholder="请输入项目编码" />
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="项目内容" prop="project_content">
<el-checkbox-group v-model="formData.project_content" placeholder="请选择项目内容">
<el-checkbox v-for="(item, index) in dictData.project_content" :key="index"
:label="item.value">
{{ item.name }}
</el-checkbox>
</el-checkbox-group>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="项目估算" prop="project_estimation">
<el-input v-model="formData.project_estimation" clearable placeholder="请输入项目估算" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="项目所在地" prop="project_address">
<el-input v-model="formData.project_address" clearable placeholder="请输入项目所在地" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="预计工期" prop="estimated_construction">
<el-input v-model="formData.estimated_construction" clearable placeholder="请输入预计工期" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="投标时间" prop="bidding_time">
<el-date-picker class="flex-1 !flex" v-model="formData.bidding_time" clearable type="datetime"
value-format="YYYY-MM-DD HH:mm:ss" placeholder="选择投标时间">
</el-date-picker>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="招标方式" prop="bidding_method">
<el-radio-group v-model="formData.bidding_method" placeholder="请选择招标方式">
<el-radio v-for="(item, index) in dictData.bidding_method" :key="index"
:label="parseInt(item.value)">
{{ item.name }}
</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="联系人" prop="contacts">
<el-input v-model="formData.contacts" clearable placeholder="请输入联系人" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="联系人职位" prop="position">
<el-input v-model="formData.position" clearable placeholder="请输入联系人职位" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="联系电话" prop="telephone">
<el-input v-model="formData.telephone" clearable placeholder="请输入联系电话" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="联系人部门" prop="department">
<el-input v-model="formData.department" clearable placeholder="请输入联系人部门" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="负责人" prop="person">
<el-input v-model="formData.person" clearable placeholder="请输入负责人" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="关系度" prop="relationship">
<el-radio-group v-model="formData.relationship" placeholder="请选择关系度">
<el-radio v-for="(item, index) in dictData.relationship" :key="index"
:label="parseInt(item.value)">
{{ item.name }}
</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="发现时间" prop="discovery_time">
<el-date-picker class="flex-1 !flex" v-model="formData.discovery_time" clearable type="datetime"
value-format="YYYY-MM-DD HH:mm:ss" placeholder="选择发现时间">
</el-date-picker>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="信息来源" prop="information_sources">
<el-select class="flex-1" v-model="formData.information_sources" clearable
placeholder="请选择信息来源">
<el-option v-for="(item, index) in dictData.information_sources" :key="index"
:label="item.name" :value="parseInt(item.value)" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="竞争对手" prop="competitor">
<el-input v-model="formData.competitor" clearable placeholder="请输入竞争对手" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="项目建设资金来源" prop="construction_funds_sources">
<el-radio-group v-model="formData.construction_funds_sources" placeholder="请选择项目建设资金来源">
<el-radio v-for="(item, index) in dictData.construction_funds_sources" :key="index"
:label="parseInt(item.value)">
{{ item.name }}
</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="建设方付款方式" prop="construction_payment_method">
<el-input v-model="formData.construction_payment_method" clearable placeholder="请输入建设方付款方式" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="建设方财务状况" prop="construction_financial_status">
<el-radio-group v-model="formData.construction_financial_status" placeholder="请选择建设方财务状况">
<el-radio v-for="(item, index) in dictData.construction_financial_status" :key="index"
:label="parseInt(item.value)">
{{ item.name }}
</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="建设方对我方认可度" prop="construction_recognition">
<el-radio-group v-model="formData.construction_recognition" placeholder="请选择建设方对我方认可度">
<el-radio v-for="(item, index) in dictData.construction_recognition" :key="index"
:label="parseInt(item.value)">
{{ item.name }}
</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="我方对建设方认可度" prop="my_construction_recognition">
<el-radio-group v-model="formData.my_construction_recognition" placeholder="请选择我方对建设方认可度">
<el-radio v-for="(item, index) in dictData.my_construction_recognition" :key="index"
:label="parseInt(item.value)">
{{ item.name }}
</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="战略意义" prop="strategic_significance">
<el-radio-group v-model="formData.strategic_significance" placeholder="请选择战略意义">
<el-radio v-for="(item, index) in dictData.strategic_significance" :key="index"
:label="parseInt(item.value)">
{{ item.name }}
</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="所属行业" prop="industry">
<el-radio-group v-model="formData.industry" placeholder="请选择所属行业">
<el-radio v-for="(item, index) in dictData.industry" :key="index"
:label="parseInt(item.value)">
{{ item.name }}
</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="单位性质" prop="unit_nature">
<el-radio-group v-model="formData.unit_nature" placeholder="请选择单位性质">
<el-radio v-for="(item, index) in dictData.unit_nature" :key="index"
:label="parseInt(item.value)">
{{ item.name }}
</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="附件" prop="annex">
<el-input v-model="formData.annex" clearable placeholder="请输入附件" />
</el-form-item>
</el-col>
</el-row>
</el-form>
</popup>
</div>
</template>
<script lang="ts" setup name="projectEdit">
import type { FormInstance } from 'element-plus'
import Popup from '@/components/popup/index.vue'
import { apiProjectAdd, apiProjectEdit, apiProjectDetail } from '@/api/project'
import { timeFormat } from '@/utils/util'
import type { PropType } from 'vue'
defineProps({
dictData: {
type: Object as PropType<Record<string, any[]>>,
default: () => ({})
}
})
const emit = defineEmits(['success', 'close'])
const formRef = shallowRef<FormInstance>()
const popupRef = shallowRef<InstanceType<typeof Popup>>()
const mode = ref('add')
//
const popupTitle = computed(() => {
return mode.value == 'edit' ? '编辑项目表' : '新增项目表'
})
//
const formData = reactive({
id: '',
name: '',
custom_id: '',
project_type: '',
project_code: '',
project_content: [],
project_estimation: '',
project_address: '',
estimated_construction: '',
bidding_time: '',
bidding_method: '',
contacts: '',
position: '',
telephone: '',
department: '',
person: '',
relationship: '',
discovery_time: '',
information_sources: '',
competitor: '',
construction_funds_sources: '',
construction_payment_method: '',
construction_financial_status: '',
construction_recognition: '',
my_construction_recognition: '',
strategic_significance: '',
industry: '',
unit_nature: '',
annex: '',
status: '',
})
//
const formRules = reactive<any>({
})
//
const setFormData = async (data: Record<any, any>) => {
for (const key in formData) {
if (data[key] != null && data[key] != undefined) {
//@ts-ignore
formData[key] = data[key]
}
}
//@ts-ignore
data.project_content && (formData.project_content = String(data.project_content).split(","))
//@ts-ignore
formData.bidding_time = timeFormat(formData.bidding_time, 'yyyy-mm-dd hh:MM:ss')
//@ts-ignore
formData.discovery_time = timeFormat(formData.discovery_time, 'yyyy-mm-dd hh:MM:ss')
}
const getDetail = async (row: Record<string, any>) => {
const data = await apiProjectDetail({
id: row.id
})
setFormData(data)
}
//
const handleSubmit = async () => {
await formRef.value?.validate()
const data = { ...formData, project_content: formData.project_content.join(",") }
mode.value == 'edit'
? await apiProjectEdit(data)
: await apiProjectAdd(data)
popupRef.value?.close()
emit('success')
}
//
const open = (type = 'add') => {
mode.value = type
popupRef.value?.open()
}
//
const handleClose = () => {
emit('close')
}
defineExpose({
open,
setFormData,
getDetail
})
</script>

201
src/views/project/index.vue Normal file
View File

@ -0,0 +1,201 @@
<template>
<div>
<el-card class="!border-none mb-4" shadow="never">
<el-form class="mb-[-16px]" :model="queryParams" inline>
<el-form-item label="客户" prop="custom_name">
<el-input class="w-[280px]" v-model="queryParams.custom_id" clearable placeholder="请输入客户昵称" />
</el-form-item>
<el-form-item label="项目类型" prop="project_type">
<el-select class="w-[280px]" v-model="queryParams.project_type" clearable placeholder="请选择项目类型">
<el-option label="全部" value=""></el-option>
<el-option v-for="(item, index) in dictData.project_type" :key="index" :label="item.name"
:value="item.value" />
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="resetPage">查询</el-button>
<el-button @click="resetParams">重置</el-button>
</el-form-item>
</el-form>
</el-card>
<el-card class="!border-none" v-loading="pager.loading" shadow="never">
<el-button v-perms="['project.project/add']" type="primary" @click="handleAdd">
<template #icon>
<icon name="el-icon-Plus" />
</template>
新增
</el-button>
<el-button v-perms="['project.project/delete']" :disabled="!selectData.length"
@click="handleDelete(selectData)">
删除
</el-button>
<div class="mt-4">
<el-table :data="pager.lists" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" />
<el-table-column label="客户" prop="custom_name" show-overflow-tooltip />
<el-table-column label="项目类型" prop="project_type">
<template #default="{ row }">
<dict-value :options="dictData.project_type" :value="row.project_type" />
</template>
</el-table-column>
<el-table-column label="项目编码" prop="project_code" show-overflow-tooltip />
<el-table-column label="项目内容" prop="project_content">
<template #default="{ row }">
<dict-value :options="dictData.project_content" :value="row.project_content" />
</template>
</el-table-column>
<el-table-column label="项目估算" prop="project_estimation" show-overflow-tooltip />
<el-table-column label="项目所在地" prop="project_address" show-overflow-tooltip />
<el-table-column label="预计工期" prop="estimated_construction" show-overflow-tooltip />
<el-table-column label="投标时间" prop="bidding_time">
<template #default="{ row }">
<span>{{ row.bidding_time ? timeFormat(row.bidding_time, 'yyyy-mm-dd hh:MM:ss') : '' }}</span>
</template>
</el-table-column>
<el-table-column label="招标方式" prop="bidding_method">
<template #default="{ row }">
<dict-value :options="dictData.bidding_method" :value="row.bidding_method" />
</template>
</el-table-column>
<el-table-column label="联系人" prop="contacts" show-overflow-tooltip />
<el-table-column label="联系人职位" prop="position" show-overflow-tooltip />
<el-table-column label="联系电话" prop="telephone" show-overflow-tooltip />
<el-table-column label="联系人部门" prop="department" show-overflow-tooltip />
<el-table-column label="负责人" prop="person" show-overflow-tooltip />
<el-table-column label="关系度" prop="relationship">
<template #default="{ row }">
<dict-value :options="dictData.relationship" :value="row.relationship" />
</template>
</el-table-column>
<el-table-column label="发现时间" prop="discovery_time">
<template #default="{ row }">
<span>{{ row.discovery_time ? timeFormat(row.discovery_time, 'yyyy-mm-dd hh:MM:ss') : ''
}}</span>
</template>
</el-table-column>
<el-table-column label="战略意义" prop="strategic_significance">
<template #default="{ row }">
<dict-value :options="dictData.strategic_significance" :value="row.strategic_significance" />
</template>
</el-table-column>
<el-table-column label="所属行业" prop="industry">
<template #default="{ row }">
<dict-value :options="dictData.industry" :value="row.industry" />
</template>
</el-table-column>
<el-table-column label="单位性质" prop="unit_nature">
<template #default="{ row }">
<dict-value :options="dictData.unit_nature" :value="row.unit_nature" />
</template>
</el-table-column>
<el-table-column label="状态" prop="status" show-overflow-tooltip />
<el-table-column label="操作" width="120" fixed="right">
<template #default="{ row }">
<el-button v-perms="['project.project/edit']" type="primary" link @click="handleEdit(row)">
编辑
</el-button>
<el-button v-perms="['project.project/delete']" type="danger" link
@click="handleDelete(row.id)">
删除
</el-button>
</template>
</el-table-column>
</el-table>
</div>
<div class="flex mt-4 justify-end">
<pagination v-model="pager" @change="getLists" />
</div>
</el-card>
<edit-popup v-if="showEdit" ref="editRef" :dict-data="dictData" @success="getLists" @close="showEdit = false" />
</div>
</template>
<script lang="ts" setup name="projectLists">
import { usePaging } from '@/hooks/usePaging'
import { useDictData } from '@/hooks/useDictOptions'
import { apiProjectLists, apiProjectDelete } from '@/api/project'
import { timeFormat } from '@/utils/util'
import feedback from '@/utils/feedback'
import EditPopup from './edit.vue'
const editRef = shallowRef<InstanceType<typeof EditPopup>>()
//
const showEdit = ref(false)
//
const queryParams = reactive({
custom_id: '',
project_type: '',
project_code: '',
project_content: '',
project_estimation: '',
project_address: '',
estimated_construction: '',
bidding_time: '',
bidding_method: '',
contacts: '',
position: '',
telephone: '',
department: '',
person: '',
relationship: '',
discovery_time: '',
information_sources: '',
competitor: '',
construction_funds_sources: '',
construction_payment_method: '',
construction_financial_status: '',
construction_recognition: '',
my_construction_recognition: '',
strategic_significance: '',
industry: '',
unit_nature: '',
annex: '',
status: ''
})
//
const selectData = ref<any[]>([])
//
const handleSelectionChange = (val: any[]) => {
selectData.value = val.map(({ id }) => id)
}
//
const { dictData } = useDictData('project_type,project_content,bidding_method,relationship,information_sources,construction_funds_sources,construction_financial_status,construction_recognition,my_construction_recognition,strategic_significance,industry,unit_nature')
//
const { pager, getLists, resetParams, resetPage } = usePaging({
fetchFun: apiProjectLists,
params: queryParams
})
//
const handleAdd = async () => {
showEdit.value = true
await nextTick()
editRef.value?.open('add')
}
//
const handleEdit = async (data: any) => {
showEdit.value = true
await nextTick()
editRef.value?.open('edit')
editRef.value?.setFormData(data)
}
//
const handleDelete = async (id: number | any[]) => {
await feedback.confirm('确定要删除?')
await apiProjectDelete({ id })
getLists()
}
getLists()
</script>

View File

@ -1,63 +0,0 @@
<template>
<div>
<el-card header="基础使用" shadow="none" class="!border-none">
<div class="flex flex-wrap">
<div class="flex m-4">
<div class="mr-4">选择图片</div>
<material-picker v-model="state.value1" />
</div>
<div class="flex m-4">
<div class="mr-4">选择视频</div>
<material-picker type="video" v-model="state.value3" />
</div>
<div class="flex flex-1 m-4">
<div class="mr-4">多张图片</div>
<div class="flex-1">
<!-- 外层需要有足够的宽度这样预览图和选择按钮才不会直接换行 -->
<material-picker :limit="4" v-model="state.value2" />
</div>
</div>
</div>
</el-card>
<el-card header="进阶用法" shadow="none" class="!border-none mt-4">
<div class="flex flex-wrap">
<div class="flex m-4">
<div class="mr-4">自定义选择器大小</div>
<material-picker size="60px" v-model="state.value4" />
</div>
<div class="flex m-4">
<div class="mr-4">使用插槽</div>
<material-picker v-model="state.value5">
<template #upload>
<el-button>选择文件</el-button>
</template>
</material-picker>
</div>
<div class="flex m-4">
<div class="mr-4">选出地址不带域名</div>
<material-picker :exclude-domain="true" v-model="state.value6" />
</div>
</div>
<div>
<div class="flex m-4 items-center">
<div class="w-20 flex-none">带域名</div>
<el-input class="w-[500px]" :model-value="state.value5" />
</div>
<div class="flex m-4 items-center">
<div class="w-20 flex-none">不带域名</div>
<el-input class="w-[500px]" :model-value="state.value6" />
</div>
</div>
</el-card>
</div>
</template>
<script lang="ts" setup>
const state = reactive({
value1: '',
value2: [],
value3: '',
value4: '',
value5: '',
value6: ''
})
</script>

View File

@ -1,64 +0,0 @@
<template>
<div>
<el-card header="element-plus图标" shadow="none" class="!border-none">
<div class="flex items-center">
<icon class="m-4" :size="24" name="el-icon-Search" />
<icon class="m-4" :size="24" name="el-icon-Plus" />
<icon class="m-4" :size="24" name="el-icon-FullScreen" />
<icon class="m-4" :size="24" name="el-icon-Setting" />
<icon class="m-4" :size="24" name="el-icon-Warning" />
</div>
</el-card>
<el-card header="本地图标" shadow="none" class="!border-none mt-4">
<div class="flex items-center">
<icon class="m-4" :size="24" name="local-icon-baoxian" />
<icon class="m-4" :size="24" name="local-icon-youhui" />
<icon class="m-4" :size="24" name="local-icon-daiyunying" />
<icon class="m-4" :size="24" name="local-icon-diancanshezhi" />
<icon class="m-4" :size="24" name="local-icon-dianzifapiao" />
</div>
</el-card>
<el-card header="图标选择器" shadow="none" class="!border-none mt-4">
<div class="flex items-center">
<icon-picker v-model="state.value" />
</div>
</el-card>
<el-card
header="element-plus图标库大全点击复制图标名称"
shadow="none"
class="!border-none mt-4"
>
<div class="flex items-center">
<div class="flex flex-wrap">
<div v-for="item in getElementPlusIconNames()" :key="item" class="m-1">
<el-button v-copy="item">
<icon :name="item" :size="20" />
</el-button>
</div>
</div>
</div>
</el-card>
<el-card
header="本地图标库大全(点击复制图标名称)"
shadow="none"
class="!border-none mt-4"
>
<div class="flex items-center">
<div class="flex flex-wrap">
<div v-for="item in getLocalIconNames()" :key="item" class="m-1">
<el-button v-copy="item">
<icon :name="item" :size="20" />
</el-button>
</div>
</div>
</div>
</el-card>
</div>
</template>
<script lang="ts" setup>
import Icon from '@/components/icon/index.vue'
import { getElementPlusIconNames, getLocalIconNames } from '@/components/icon'
const state = reactive({
value: ''
})
</script>

View File

@ -1,12 +0,0 @@
<template>
<div>
<el-card header="基础使用" shadow="none" class="!border-none">
<link-picker v-model="state.value1" />
</el-card>
</div>
</template>
<script lang="ts" setup>
const state = reactive({
value1: {}
})
</script>

View File

@ -1,9 +0,0 @@
<template>
<div>
<el-card header="基础使用" shadow="none" class="!border-none">
<overflow-tooltip class="w-20 m-4" content="超出自动打点,悬浮弹窗显示全部内容" />
<overflow-tooltip class="w-60 m-4" content="超出自动打点,悬浮弹窗显示全部内容" />
</el-card>
</div>
</template>
<script lang="ts" setup></script>

View File

@ -1,48 +0,0 @@
<template>
<div>
<el-card header="基础使用" shadow="none" class="!border-none">
<div class="flex flex-wrap">
<div class="m-4">
<popover-input @confirm="onConfirm">
<template #default>
<el-button> 点击输入 </el-button>
</template>
</popover-input>
</div>
<div class="m-4">
<popover-input type="number" @confirm="onConfirm">
<template #default>
<el-button> 输入数字 </el-button>
</template>
</popover-input>
</div>
<div class="m-4">
<popover-input size="small" @confirm="onConfirm">
<template #default>
<el-button> 调整大小 </el-button>
</template>
</popover-input>
</div>
<div class="m-4">
<popover-input :limit="20" :show-limit="true" @confirm="onConfirm">
<template #default>
<el-button> 限制输入长度 </el-button>
</template>
</popover-input>
</div>
<div class="m-4">
<popover-input value="默认值" @confirm="onConfirm">
<template #default>
<el-button> 默认值 </el-button>
</template>
</popover-input>
</div>
</div>
</el-card>
</div>
</template>
<script lang="ts" setup>
const onConfirm = (value: string) => {
console.log(value)
}
</script>

View File

@ -1,16 +0,0 @@
<template>
<div>
<el-card header="基础使用" shadow="none" class="!border-none">
<editor v-model="state.value1" height="500px" />
</el-card>
<el-card header="简洁模式" shadow="none" class="!border-none mt-4">
<editor v-model="state.value2" height="500px" mode="simple" />
</el-card>
</div>
</template>
<script lang="ts" setup>
const state = reactive({
value1: '',
value2: ''
})
</script>

View File

@ -1,65 +0,0 @@
<template>
<div>
<el-card header="基础使用" shadow="none" class="!border-none">
<div class="flex flex-wrap">
<div class="m-4">
<upload
@change="onChange"
@success="onSuccess"
@error="onError"
:show-progress="true"
>
<el-button type="primary">上传图片</el-button>
</upload>
</div>
<div class="m-4">
<upload
type="video"
@change="onChange"
@success="onSuccess"
@error="onError"
:show-progress="true"
>
<el-button type="primary">上传视频</el-button>
</upload>
</div>
<div class="m-4">
<upload
:multiple="false"
@change="onChange"
@success="onSuccess"
@error="onError"
:show-progress="true"
>
<el-button type="primary">取消多选</el-button>
</upload>
</div>
<div class="m-4">
<upload
:limit="2"
@change="onChange"
@success="onSuccess"
@error="onError"
:show-progress="true"
>
<el-button type="primary">一次最多上传2张</el-button>
</upload>
</div>
</div>
</el-card>
</div>
</template>
<script lang="ts" setup>
import Upload from '@/components/upload/index.vue'
const onChange = (file: any) => {
console.log('上传文件的状态发生改变', file)
}
const onSuccess = (file: any) => {
console.log('上传文件成功', file)
}
const onError = (file: any) => {
console.log('上传文件失败', file)
}
</script>

6247
yarn.lock

File diff suppressed because it is too large Load Diff