Lufaneng 9 months ago
parent 6dca1de96f
commit 9b2b5ee7e6

@ -56,12 +56,24 @@ export const asyncRoutes = [
component: () => import('@/views/ModelManage/index.vue'),
meta: { title: '模版管理', permissions: ['template'] },
},
{
path: 'ModelApproval',
name: 'ModelApproval',
component: () => import('@/views/ModelApproval/index.vue'),
meta: { title: '模版审批', permissions: ['template_approval'] },
},
{
path: 'ComboManage',
name: 'ComboManage',
component: () => import('@/views/ComboManage/index.vue'),
meta: { title: '套餐管理', permissions: ['membership_plan'] },
},
{
path: 'VendorManage',
name: 'VendorManage',
component: () => import('@/views/VendorManage/index.vue'),
meta: { title: '厂商管理', permissions: ['vendor_manage'] },
},
{
path: 'GenerateRecord',
name: 'GenerateRecord',

@ -0,0 +1,100 @@
<script setup>
import RPC from '@/utils/rpc'
const props = defineProps({
type: {
type: String,
required: true,
},
row: [Object],
})
const emit = defineEmits(['closed', 'onSuccess'])
const dialogVisible = ref(false)
const isAdd = computed(() => props.type === 'add')
onMounted(() => {
dialogVisible.value = true
})
const formRef = ref(null)
const formField = ref({ enabled: true, params: [] })
const formRules = reactive({
name: [{ required: true, message: '不可为空', trigger: 'change' }],
code: [{ required: true, message: '不可为空', trigger: 'change' }],
})
const loading = ref(false)
function closed() {
emit('closed')
}
const submitForm = async () => {
await formRef.value.validate()
const api = isAdd.value ? '/vendor/create' : '/vendor/update'
const params = {
...formField.value,
id: isAdd.value ? null : props.row.id,
}
loading.value = true
RPC.post(api, params)
.then((res) => {
ElMessage.success('操作成功')
emit('onSuccess')
emit('closed')
})
.finally(() => {
loading.value = false
})
}
if (!isAdd.value) {
formField.value = {
...props.row,
}
}
</script>
<template>
<el-dialog
align-center
:title="isAdd ? '新增' : '修改'"
width="80%"
v-model="dialogVisible"
@closed="closed"
:close-on-click-modal="false"
>
<el-form
ref="formRef"
label-position="right"
label-suffix=":"
:model="formField"
:rules="formRules"
v-loading="loading"
label-width="150"
>
<el-form-item prop="name" label="名称">
<el-input placeholder="请输入" v-model="formField.name" />
</el-form-item>
<el-form-item prop="code" label="字段">
<el-input placeholder="请输入" v-model="formField.code" />
</el-form-item>
<el-form-item prop="contact_name" label="联系人">
<el-input placeholder="请输入" v-model="formField.contact_name" />
</el-form-item>
<el-form-item prop="address" label="地址">
<el-input placeholder="请输入" v-model="formField.address" />
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button @click="closed"> </el-button>
<el-button type="primary" :loading="loading" @click="submitForm"> </el-button>
</div>
</template>
</el-dialog>
</template>
<style lang="scss" scoped></style>

@ -0,0 +1,134 @@
<template>
<div>
<div class="title">模板审批</div>
<el-form
ref="searchFormRef"
class="form"
:inline="true"
label-width="98px"
:model="queryParams"
>
<el-form-item label="名称" prop="name">
<el-input
clearable
placeholder="请输入"
style="width: 220px"
v-model="queryParams.name"
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label-width="100px">
<el-button icon="Search" type="primary" @click="handleQuery"> </el-button>
<el-button icon="RefreshRight" @click="resetQuery"> </el-button>
</el-form-item>
</el-form>
<div style="margin-bottom: 20px">
<el-button icon="Plus" type="primary" @click="add"> </el-button>
</div>
<div ref="tableContainerEl" class="table_border table">
<el-table
ref="tableRef"
:data="tableData"
v-loading="loading"
header-row-class-name="table-header"
>
<el-table-column align="center" label="名称" prop="name" show-overflow-tooltip />
<el-table-column align="center" label="价格(¥)" prop="price_cents">
<template #default="{ row }">
{{ row.price_cents ? row.price_cents / 100 : '' }}
</template>
</el-table-column>
<el-table-column align="center" label="字段" prop="code" show-overflow-tooltip />
<el-table-column align="center" label="表格名称" prop="sheet_name" show-overflow-tooltip />
<el-table-column align="center" label="路径" prop="auto_path" show-overflow-tooltip />
<el-table-column align="center" label="描述" prop="description" show-overflow-tooltip />
<el-table-column align="center" label="是否启用" prop="enabled">
<template #default="{ row }">
{{ row.enabled ? '启用' : '禁用' }}
</template>
</el-table-column>
<el-table-column align="center" label="操作" width="120">
<template #default="{ row }">
<el-button link type="primary" @click="edit(row)"> </el-button>
<el-button link type="danger" @click="handleDelete(row)"> </el-button>
</template>
</el-table-column>
</el-table>
</div>
<pagination
v-show="total > 0"
:total="total"
v-model:limit="queryParams.limit"
v-model:page="queryParams.page"
@pagination="getList"
/>
<HandleDialog
v-if="isShowDialog"
:type="rowType"
:row="currentRow"
@closed="isShowDialog = false"
@on-success="getList"
/>
</div>
</template>
<script setup>
import { useTableRPC } from '@/utils/hook'
import HandleDialog from './HandleDialog.vue'
const rowType = ref('')
const currentRow = ref(null)
const add = () => {
isShowDialog.value = true
currentRow.value = null
rowType.value = 'add'
}
const edit = (row) => {
isShowDialog.value = true
rowType.value = 'edit'
currentRow.value = row
}
const {
loading,
tableData,
tableRef,
searchFormRef,
total,
queryParams,
getList,
handleQuery,
resetQuery,
handleDelete,
isShowDialog,
maxHeight,
tableContainerEl,
} = useTableRPC({
queryParams: {
orderby: [{ sort: 'asc' }],
},
remoteDataFn: '/template/access/list',
// deleteConfig: {
// remote: '/vendor/delete',
// key: 'id',
// message(row) {
// return ` ${row.name}`
// },
// },
})
getList()
</script>
<style lang="scss" scoped>
.title {
font-size: 20px;
font-weight: 700;
margin-bottom: 20px;
}
</style>

@ -64,6 +64,7 @@ const addRow = () => {
type: 'string',
excel_loc: '',
enabled: true,
required: true,
})
} else {
formField.value.params = [
@ -74,6 +75,7 @@ const addRow = () => {
type: 'string',
excel_loc: '',
enabled: true,
required: true,
},
]
}
@ -141,14 +143,20 @@ const delRow = (index) => {
<el-input placeholder="请输入" v-model="row.value" />
</template>
</el-table-column>
<!-- <el-table-column align="center" label="字段类型">
<el-table-column align="center" label="字段类型">
<template #default="{ row }">
<el-select placeholder="请输入" v-model="row.type">
<el-option value="string" label="字符串"></el-option>
<el-option value="number" label="数字"></el-option>
<el-option value="select" label="下拉框"></el-option>
</el-select>
</template>
</el-table-column> -->
</el-table-column>
<el-table-column align="center" label="选项">
<template #default="{ row }">
<el-input placeholder="以,分隔每个选项" v-model="row.options" />
</template>
</el-table-column>
<el-table-column align="center" label="字段位置">
<template #default="{ row }">
<el-input placeholder="请输入" v-model="row.excel_loc" />
@ -159,6 +167,11 @@ const delRow = (index) => {
<el-switch v-model="row.enabled" active-text="" inactive-text="" />
</template>
</el-table-column>
<el-table-column align="center" label="是否必填">
<template #default="{ row }">
<el-switch v-model="row.required" active-text="" inactive-text="" />
</template>
</el-table-column>
<el-table-column align="center" label="操作" width="60">
<template #default="{ $index }">
<el-button link type="danger" @click="delRow($index)"> </el-button>

@ -42,12 +42,38 @@
{{ row.roles?.map((item) => item.name)?.join(',') }}
</template>
</el-table-column>
<el-table-column align="center" label="厂商" prop="vendors">
<template #default="{ row }">
{{ row.vendors?.map((item) => item.name)?.join(',') }}
</template>
</el-table-column>
<el-table-column align="center" label="操作" width="180">
<template #default="{ row }">
<div class="flex items-center">
<el-button link type="primary" @click="editRole(row)"> </el-button>
<el-button link type="primary" @click="edit(row)"> </el-button>
<el-button link type="danger" @click="handleDelete(row)"> </el-button>
</div>
<template v-if="useUserStore().userInfo?.isAdmin">
<div class="flex items-center">
<el-button link type="primary" @click="order(row)"> </el-button>
<el-button link type="primary" @click="pay(row)"> </el-button>
</div>
<div class="flex items-center">
<el-button link type="primary" @click="vendor(row, 'authorize')">
分配厂商
</el-button>
<el-button
link
type="primary"
v-if="row.vendors?.length > 0"
@click="vendor(row, 'revoke')"
>
撤销厂商
</el-button>
</div>
</template>
</template>
</el-table-column>
</el-table>
@ -75,6 +101,65 @@
@closed="isShowRoleDialog = false"
@on-success="getList"
/>
<el-dialog
align-center
title="充值"
width="500"
v-model="isShowPayDialog"
@closed="payClosed"
:close-on-click-modal="false"
>
是否给{{ currentRow.username }}进行充值
<el-input-number v-model="pay_amount"></el-input-number>
<template #footer>
<div class="dialog-footer">
<el-button @click="payClosed"> </el-button>
<el-button type="primary" :loading="payLoading" @click="payConfirm"> </el-button>
</div>
</template>
</el-dialog>
<el-dialog
align-center
title="赠送套餐"
width="500"
v-model="isShowOrderDialog"
@closed="orderClosed"
:close-on-click-modal="false"
>
是否给{{ currentRow.username }}进行赠送
<el-select v-model="order_id">
<el-option v-for="item in planList" :value="item.id" :label="item.name"></el-option>
</el-select>
<template #footer>
<div class="dialog-footer">
<el-button @click="orderClosed"> </el-button>
<el-button type="primary" :loading="orderLoading" @click="orderConfirm">
</el-button>
</div>
</template>
</el-dialog>
<el-dialog
align-center
:title="currentType === 'authorize' ? '分配厂商' : '撤销厂商'"
width="500"
v-model="isShowVendorDialog"
@closed="vendorClosed"
:close-on-click-modal="false"
>
<el-checkbox-group v-model="vendorSelected">
<el-checkbox v-for="item in vendorListFilter" :label="item.name" :value="item.id" />
</el-checkbox-group>
<template #footer>
<div class="dialog-footer">
<el-button @click="vendorClosed"> </el-button>
<el-button type="primary" :loading="vendorLoading" @click="vendorConfirm">
</el-button>
</div>
</template>
</el-dialog>
</div>
</template>
@ -84,6 +169,7 @@ import dayjs from 'dayjs'
import RPC from '@/utils/rpc'
import HandleDialog from './HandleDialog.vue'
import RoleDialog from './RoleDialog.vue'
import { useUserStore } from '@/stores/user'
const rowType = ref('')
const currentRow = ref(null)
@ -108,6 +194,137 @@ RPC.post('/role/list', { page: 1, limit: -1 }).then((res) => {
roleList.value = res.rows || []
})
const pay_amount = ref(0)
const isShowPayDialog = ref(false)
const payLoading = ref(false)
const payClosed = () => {
isShowPayDialog.value = false
currentRow.value = {}
}
const pay = (row) => {
currentRow.value = row
isShowPayDialog.value = true
pay_amount.value = 0
}
const payConfirm = () => {
if (!pay_amount.value) {
ElMessage.warning('请填写充值金额')
return
}
payLoading.value = true
RPC.post('/wallet/admin/recharge_and_pay', {
user_id: currentRow.value.id,
amount_cents: pay_amount.value * 100,
pay_channel: 'admin',
remark: '手动充值',
})
.then(() => {
isShowPayDialog.value = false
ElMessage.success('充值成功')
getList()
})
.finally(() => {
payLoading.value = false
})
}
const planList = ref([])
RPC.post('/membership_plan/list', { page: 0, limit: -1, orderby: [{ sort: 'asc' }] }).then(
(res) => {
planList.value = res.rows || []
},
)
const order_id = ref(0)
const isShowOrderDialog = ref(false)
const orderLoading = ref(false)
const orderClosed = () => {
isShowOrderDialog.value = false
currentRow.value = {}
order_id.value = null
}
const order = (row) => {
currentRow.value = row
isShowOrderDialog.value = true
order_id.value = null
}
const orderConfirm = () => {
if (!order_id) {
ElMessage.warning('请选择赠送套餐')
return
}
orderLoading.value = true
RPC.post('/membership/admin/order/create_and_pay', {
user_id: currentRow.value.id,
plan_id: order_id.value,
pay_channel: 'admin',
remark: '管理员手动完成',
})
.then(() => {
isShowOrderDialog.value = false
ElMessage.success('赠送成功')
getList()
})
.finally(() => {
orderLoading.value = false
})
}
const isShowVendorDialog = ref(false)
const vendorLoading = ref(false)
const vendorClosed = () => {
isShowVendorDialog.value = false
currentRow.value = {}
vendorSelected.value = []
}
const currentType = ref('')
const vendor = (row, type) => {
if (type === 'authorize') {
vendorListFilter.value = vendorList.value
vendorSelected.value = row.vendors.map((item) => item.vendor_id)
}
if (type === 'revoke') {
vendorListFilter.value = row.vendors.map((item) => {
return {
id: item.vendor_id,
...item,
}
})
}
currentType.value = type
currentRow.value = row
isShowVendorDialog.value = true
}
const vendorConfirm = () => {
if (vendorSelected?.value.length <= 0) {
ElMessage.warning('请选择厂商')
return
}
vendorLoading.value = true
RPC.post(`/vendor_user_${currentType.value}`, {
user_id: currentRow.value.id,
vendor_ids: vendorSelected.value,
})
.then(() => {
isShowVendorDialog.value = false
ElMessage.success('操作成功')
getList()
})
.finally(() => {
vendorLoading.value = false
})
}
const vendorList = ref([])
const vendorListFilter = ref([])
const vendorSelected = ref([])
RPC.post('/vendor/list', { page: 1, limit: -1 }).then((res) => {
vendorList.value = res.rows || []
})
const {
loading,
tableData,

@ -0,0 +1,103 @@
<script setup>
import RPC from '@/utils/rpc'
const props = defineProps({
type: {
type: String,
required: true,
},
row: [Object],
})
const emit = defineEmits(['closed', 'onSuccess'])
const dialogVisible = ref(false)
const isAdd = computed(() => props.type === 'add')
onMounted(() => {
dialogVisible.value = true
})
const formRef = ref(null)
const formField = ref({ enabled: true })
const formRules = reactive({
name: [{ required: true, message: '不可为空', trigger: 'change' }],
code: [{ required: true, message: '不可为空', trigger: 'change' }],
})
const loading = ref(false)
function closed() {
emit('closed')
}
const submitForm = async () => {
await formRef.value.validate()
const api = isAdd.value ? '/vendor/create' : '/vendor/update'
const params = {
...formField.value,
id: isAdd.value ? null : props.row.id,
}
loading.value = true
RPC.post(api, params)
.then((res) => {
ElMessage.success('操作成功')
emit('onSuccess')
emit('closed')
})
.finally(() => {
loading.value = false
})
}
if (!isAdd.value) {
formField.value = {
...props.row,
}
}
</script>
<template>
<el-dialog
align-center
:title="isAdd ? '新增' : '修改'"
width="80%"
v-model="dialogVisible"
@closed="closed"
:close-on-click-modal="false"
>
<el-form
ref="formRef"
label-position="right"
label-suffix=":"
:model="formField"
:rules="formRules"
v-loading="loading"
label-width="150"
>
<el-form-item prop="name" label="名称">
<el-input placeholder="请输入" v-model="formField.name" />
</el-form-item>
<el-form-item prop="code" label="字段">
<el-input placeholder="请输入" v-model="formField.code" />
</el-form-item>
<el-form-item prop="contact_name" label="联系人">
<el-input placeholder="请输入" v-model="formField.contact_name" />
</el-form-item>
<el-form-item prop="address" label="地址">
<el-input placeholder="请输入" v-model="formField.address" />
</el-form-item>
<el-form-item prop="enabled" label="是否启用">
<el-switch v-model="formField.enabled" active-text="" inactive-text="" />
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button @click="closed"> </el-button>
<el-button type="primary" :loading="loading" @click="submitForm"> </el-button>
</div>
</template>
</el-dialog>
</template>
<style lang="scss" scoped></style>

@ -0,0 +1,128 @@
<template>
<div>
<div class="title">厂商管理</div>
<el-form
ref="searchFormRef"
class="form"
:inline="true"
label-width="98px"
:model="queryParams"
>
<el-form-item label="名称" prop="name">
<el-input
clearable
placeholder="请输入"
style="width: 220px"
v-model="queryParams.name"
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label-width="100px">
<el-button icon="Search" type="primary" @click="handleQuery"> </el-button>
<el-button icon="RefreshRight" @click="resetQuery"> </el-button>
</el-form-item>
</el-form>
<div style="margin-bottom: 20px">
<el-button icon="Plus" type="primary" @click="add"> </el-button>
</div>
<div ref="tableContainerEl" class="table_border table">
<el-table
ref="tableRef"
:data="tableData"
v-loading="loading"
header-row-class-name="table-header"
>
<el-table-column align="center" label="名称" prop="name" show-overflow-tooltip />
<el-table-column align="center" label="字段" prop="code" show-overflow-tooltip />
<el-table-column align="center" label="联系人" prop="contact_name" show-overflow-tooltip />
<el-table-column align="center" label="地址" prop="address" show-overflow-tooltip />
<el-table-column align="center" label="是否启用" prop="enabled">
<template #default="{ row }">
{{ row.enabled ? '启用' : '禁用' }}
</template>
</el-table-column>
<el-table-column align="center" label="操作" width="120">
<template #default="{ row }">
<el-button link type="primary" @click="edit(row)"> </el-button>
<el-button link type="danger" @click="handleDelete(row)"> </el-button>
</template>
</el-table-column>
</el-table>
</div>
<pagination
v-show="total > 0"
:total="total"
v-model:limit="queryParams.limit"
v-model:page="queryParams.page"
@pagination="getList"
/>
<HandleDialog
v-if="isShowDialog"
:type="rowType"
:row="currentRow"
@closed="isShowDialog = false"
@on-success="getList"
/>
</div>
</template>
<script setup>
import { useTableRPC } from '@/utils/hook'
import HandleDialog from './HandleDialog.vue'
const rowType = ref('')
const currentRow = ref(null)
const add = () => {
isShowDialog.value = true
currentRow.value = null
rowType.value = 'add'
}
const edit = (row) => {
isShowDialog.value = true
rowType.value = 'edit'
currentRow.value = row
}
const {
loading,
tableData,
tableRef,
searchFormRef,
total,
queryParams,
getList,
handleQuery,
resetQuery,
handleDelete,
isShowDialog,
maxHeight,
tableContainerEl,
} = useTableRPC({
queryParams: {
orderby: [{ id: 'desc' }],
},
remoteDataFn: '/vendor/list',
deleteConfig: {
remote: '/vendor/delete',
key: 'id',
message(row) {
return `确认删除 “${row.name}`
},
},
})
getList()
</script>
<style lang="scss" scoped>
.title {
font-size: 20px;
font-weight: 700;
margin-bottom: 20px;
}
</style>
Loading…
Cancel
Save