提交 616bd57c 编写于 作者: W wuyb@phxg.cn

table

上级 bb5d5920
import {mock} from "mockjs";
let data = {
'list|1-10': [{
'rows|1-10': [{
// 属性 id 是一个自增数,起始值为 1,每次增 1
'id|+1': 1
'id|+1': 1,
'name': '@cname()',
"age|1-30": 18,
"address": '@county(true)',
"tags": '@shuffle([\'LOSER\', \'TEACHER\', \'DEVELOPER\', \'NICE\', \'COOL\'], 1, 3)'
}]
}
module.exports = [
// 登录
// 获取列表
{
url: '/api/table/all',
type: 'post',
type: 'get',
response: config => {
const {token} = config.body
if (!token) {
const {token} = config.headers
if (token) {
return {
code: 60204,
message: 'token失效'
code: 200,
data: data
}
}
return {
code: 200,
data: {
count: data.length,
rows: data
code: 60204,
data: token,
message: 'token失效'
}
}
},
{
url: '/api/table/add',
type: 'get',
response: config => {
const {token} = config.headers
if (token) {
return {
code: 200,
msg: 'ok'
}
}
}
},
]
......@@ -54,14 +54,15 @@ module.exports = [
url: '/api/user/info',
type: 'get',
response: config => {
const {token} = config.query
console.log('/api/user/info - config',config);
const {token} = config.headers
const info = users[token]
// mock error
if (!info) {
return {
code: 50008,
message: 'Login failed, unable to get user details.'
message: '获取信息失败'
}
}
......@@ -88,7 +89,7 @@ module.exports = [
url: '/api/menu/getRouter',
type: 'get',
response: config => {
const {token} = config.query
const {token} = config.headers
if (token) {
return {
code: 200,
......
/**
* 封装一些公用的接口
*/
import request from '@/utils/request';
// post
export const postAction = (url, data, params, option) => {
return request({
url,
method: 'post',
data,
params,
...option
});
};
// put
export const putAction = (url, data, params, option) => {
return request({
url,
method: 'put',
data,
params,
...option
});
};
// delete
export const deleteAction = (url, data, params, option) => {
return request({
url,
method: 'delete',
data,
params,
...option
});
};
// 所有查询方法 默认get
export const httpAction = (url, params, data, method = 'get', option) => {
console.log('httpAction',url, params, data, method = 'get', option);
return request({
url,
method,
data,
params,
...option
});
};
import request from '@/utils/request'
export function tabelAll(data) {
console.log(data);
return request({
url: '/api/table/all',
method: 'get',
data
})
}
\ No newline at end of file
......@@ -13,8 +13,8 @@
<a-input-number v-if="item.inputType === 'number'" :disabled="item.disabled || hasDisabled"
v-model:value="formState[`${item.fieldName}`]"
:placeholder="item.placeholder?item.placeholder:'请输入'"
:min="item.min?item.min:Infinity"
:max="item.max?item.max:Infinity"/>
:min="item.min"
:max="item.max"/>
<!--多行文本-->
<a-textarea v-if="item.inputType === 'textarea'" :disabled="item.disabled || hasDisabled"
v-model:value="formState[`${item.fieldName}`]"
......@@ -24,7 +24,8 @@
<!--单选-->
<a-radio-group v-if="item.inputType === 'radio'" :disabled="item.disabled || hasDisabled"
v-model:value="formState[`${item.fieldName}`]">
<a-radio v-for="radio in item.options" :key="radio.value" :value="radio.value">{{radio.name}}
<a-radio v-for="radio in item.options" :key="radio.value" :value="radio.value">
{{radio.name}}
</a-radio>
</a-radio-group>
<!-- 多选-->
......@@ -39,7 +40,7 @@
<a-select
v-if="item.inputType == 'select'"
allowClear
v-model="formState[`${item.fieldName}`]"
v-model:value="formState[`${item.fieldName}`]"
:placeholder="item.placeholder?item.placeholder:'请选择'"
:show-search="item.showSearch"
:options="item.options"
......@@ -91,7 +92,7 @@
props: {
config: Object,
},
setup(props) {
setup(props, {emit}) {
// 表单数据
const formRef = ref(null);
const dateFormat = 'YYYY-MM-DD';
......@@ -101,7 +102,7 @@
const initForm = () => {
props.config.data.forEach(item => {
if (item.inputType !== "range") {
let defaultVal = item.defaultVal ? item.defaultVal : ''
let defaultVal = item.defaultVal ? item.defaultVal : undefined
formState[`${item.fieldName}`] = defaultVal;
} else {
if (item.fieldName) {
......@@ -122,25 +123,27 @@
let validator = typeof item.validator === 'function' ? item.validator : null
if (!validator) {
rulesForm[item.fieldName] = [{
whitespace: true,
whitespace: item.required ? item.required : false, // 必选时,空格是否会被视为错误
required: item.required,
message: `${item.label}内容不能为空`,
trigger: 'blur',
message: `${item.label}不能为空`,
// trigger: 'change',
type: item.inputType === 'number' ? 'number' : 'string'
}]
} else {
// 自定义效验内容
rulesForm[item.fieldName] = [{
whitespace: true,
whitespace: item.required ? item.required : false,
required: item.required,
validator: validator,
trigger: 'blur',
// trigger: 'change',
}]
}
}
}
});
console.log('rules', rulesForm);
console.log('formState', formState);
console.log('form - rules', rulesForm);
console.log('form - formState', formState);
}
onMounted(() => {
......@@ -149,7 +152,7 @@
// 时间选择
function onInputChange(fieldName, date, dateStrings, type) {
// console.log(fieldName, date, dateStrings, type);
console.log(fieldName, date, dateStrings, type);
if (type) {
if (fieldName && type === 'range') {
let arr = fieldName.split(',');
......@@ -162,26 +165,34 @@
formState.endTime = dateStrings[1];
}
} else {
formState[fieldName] = date ? moment(date, dateFormat) : null
// moment(val).format("YYYY-MM-DD HH:mm:ss")
formState[fieldName] = date ? moment(date).format(dateFormat) : null
// console.log('formState - moment', moment(date).format(dateFormat));
console.log('formState - str', moment(date, dateFormat));
// console.log('formState', formState);
}
}
// 重置表单
const resetForm = () => {
formRef.value.resetFields();
console.log('resetForm', formState);
for (let key in formState) {
formState[key] = '';
formState[key] = undefined;
}
emit('close')
}
// 数据提交
const onSubmit = () => {
console.log('formRef', formRef);
formRef.value.validate()
.then(() => {
console.log('values', toRaw(formState));
let data = getQuery();
console.log(data);
emit('ok', data)
})
.catch((error) => {
console.log('error', error);
......
<template>
<a-drawer
:title="drawerTitle"
:title="title"
:width="drawerWidth"
:placement="drawerPlacement"
:closable="drawerClosable"
v-model:visible="isShow"
......@@ -18,8 +19,12 @@
type: Boolean,
default: false
},
drawerWidth:{
type: [Number,String],
default: 700
},
// 标题
drawerTitle: {
title: {
type: String,
default: ''
},
......
......@@ -2,19 +2,20 @@
<a-modal
:width="800"
:title="title"
:visible="isShow"
v-model:visible="isShow"
:maskClosable="false"
:confirmLoading="confirmLoading"
@ok="handleOk"
@cancel="handleCancel"
@ok="modalOk"
@cancel="modalCancel"
>
<slot></slot>
<slot>默认插槽</slot>
</a-modal>
</template>
<script>
import {ref, watch} from 'vue'
import {useModal} from "@/hook/useModal";
export default {
name: "modalIndex",
......@@ -28,27 +29,17 @@
default: false
},
},
setup(props, content) {
console.log('props - modal', props);
let confirmLoading = ref(false)
const handleOk = (e) => {
confirmLoading.value = true
content.emit('modalOk');
handleCancel()
setTimeout(() => {
confirmLoading.value = false
}, 300)
}
setup(props, {emit}) {
const {
modalOk,
modalCancel,
} = useModal(emit)
const handleCancel = () => {
content.emit('modalCancel');
content.emit('update:isShow', false);
}
return {
handleOk,
handleCancel,
confirmLoading
modalOk,
modalCancel,
confirmLoading:false
}
}
}
......
......@@ -3,7 +3,9 @@ import modal from './modal.vue'
import {h} from 'vue'
export const renderPopups = function (props, {slots}) {
console.log('renderPopups',props);
return props.type === 'modal' ? h(modal, slots.default()) : h(drawer, slots.default())
}
const paramsProps = {
isShow: props.isShow,
title: props.title,
}
return props.type === 'modal' ? h(modal, paramsProps, slots.default()) : h(drawer, paramsProps, slots.default())
}
\ No newline at end of file
import {ref, reactive, computed} from 'vue'
import {ref, reactive, toRefs, computed} from 'vue'
import {postAction, putAction, deleteAction, httpAction} from '@/api/commonApi/index';
// 设置模态框
export function useModal() {
const isShow = ref(false)
const isModalLoading = ref(false)
export function useModal(emit) {
const useModalData = reactive({
isShow: false,
confirmLoading: false
})
const onModalShow = () => {
isShow.value = true
console.log('打开弹框')
useModalData.isShow = true
console.log('modal - use', useModalData.isShow);
}
const modalOk = () => {
console.log('确认')
useModalData.isShow = false
}
const modalCancel = () => {
console.log('取消')
console.log('modal - use - 取消')
useModalData.isShow = false
console.log(useModalData.isShow);
emit('update:isShow', false)
}
const handleOk = ({url,formItem, otherValues = {}, type = 'add', path}) => {
useModalData.confirmLoading = true;
let axios;
let formData = Object.assign(formItem, otherValues);
if (type === 'edit') { // 修改
if (!this.url.edit) {
message.error('请设置url.edit属性!');
console.error('请设置url.edit属性!');
return;
}
axios = putAction(`${url.edit}/${path}`, formData);
} else { // 新增
if (!url.add) {
message.error('请设置url.add属性!');
console.error('请设置url.add属性!');
return;
}
axios = postAction(url.add, formData);
}
axios.then((res) => {
if (res.code === 201 || res.code === 202) {
this.$emit('ok');
this.close();
}
}).catch(err => {
console.error(err);
}).finally(() => {
useModalData.confirmLoading = false;
});
}
// 根据屏幕变化,设置抽屉尺寸
// const resetScreenSize = () => {
// const screenWidth = document.body.clientWidth;
// if (screenWidth < 500) {
// this.drawerWidth = screenWidth;
// } else {
// this.drawerWidth = 700;
// }
// }
return {
modalOk,
modalCancel,
onModalShow,
isShow
...toRefs(useModalData),
handleOk
}
}
......
......@@ -3,10 +3,10 @@
* useTable 表格查询,分页, 删除
* @modalMixin 弹窗新增,修改,详情
*/
import {ref, reactive, computed} from 'vue'
import {message, confirm} from 'ant-design-vue'
// import { postAction, putAction, deleteAction, httpAction } from 'api/commonApi/index';
let postAction, putAction, deleteAction, httpAction;
import {ref, reactive, toRefs, computed, onMounted} from 'vue'
import {message, Modal} from 'ant-design-vue'
import {postAction, putAction, deleteAction, httpAction} from '@/api/commonApi/index';
// let postAction, putAction, deleteAction, httpAction;
let filterObjByKey, parseDate, getMoment, formatObjDate, getTreeKeys;
// import { filterObjByKey, parseDate, getMoment, formatObjDate, getTreeKeys } from 'utils/util';
......@@ -61,15 +61,19 @@ export function usePaging() {
}
}
// 表格
export function useTable(url) {
const {ipagination} = usePaging()
let tableData = reactive({
// 数据源
dataSource: [],
})
let isInitTable = true, // 是否初始化表格
// 查询条件
queryParam = {},
// 折叠区域查询条件
subQueryParam = {},
// 数据源
dataSource = [],
// 表格加载状态
tableLoading = ref(false),
......@@ -114,9 +118,9 @@ export function useTable(url) {
if (url.dataAll) { // 数据和表格总数一起请求
httpAction(url.dataAll, data).then((res) => { // 列表数据
if (res.code === 200) {
dataSource = res.data.rows;
tableData.dataSource = res.data.rows;
ipagination.total = Number(res.data.count);
console.log(dataSource)
console.log('tableData.', tableData.dataSource)
}
tableLoading.value = false;
}).catch(error => {
......@@ -126,7 +130,7 @@ export function useTable(url) {
} else { // 数据和表格总数分开请求请求
httpAction(url.list, data).then((res) => { // 列表数据
if (res.code === 200) {
dataSource = res.data;
tableData.dataSource = res.data;
console.log(dataSource)
}
tableLoading.value = false;
......@@ -157,7 +161,6 @@ export function useTable(url) {
return params;
}
// 表格行选择
const onSelectChange = (selectedRowKeys, selectionRows) => {
console.log(selectedRowKeys, selectionRows)
......@@ -214,7 +217,7 @@ export function useTable(url) {
// }
const openModal = () => {
this.showModal = true;
showModal.value = true;
}
// 批量删除
......@@ -268,7 +271,7 @@ export function useTable(url) {
console.error('请设置url.delete属性!');
return;
}
confirm({
Modal.confirm({
title: '确认删除',
content: tip,
centered: true,
......@@ -295,16 +298,19 @@ export function useTable(url) {
// 排序 分页
const handleTableChange = (pagination, filters, sorter) => {
ipagination = pagination;
// ipagination = pagination;
loadData();
}
if (isInitTable) {
onMounted(() => {
loadData();
}
})
return {
ipagination,
loadData,
...toRefs(tableData),
// ipagination,
onSelectChange
};
};
......@@ -331,7 +337,7 @@ const props = {
}
export function useModal() {
return {
const useModalData = reactive({
// 弹窗设置
drawerWidth: 700,
// 布局
......@@ -344,8 +350,7 @@ export function useModal() {
sm: {span: 16}
},
confirmLoading: false,
form: this.$form.createForm(this)
}
})
const disableSubmit = computed({
get: () => {
if (type === 'detail') {
......@@ -353,95 +358,56 @@ export function useModal() {
}
return false;
},
set: () => {
}// 查看详情,禁用所有表单
})
const close = () => {
this.confirmLoading = false;
this.disableSubmit = false;
this.$emit('close');
this.$emit('update:show', false);
}
methods: {
// 回填数据
backfillData()
{
this.resetScreenSize();
// 回填数据
this.$nextTick().finally(() => {
this.form.resetFields();
// 日期处理
if (this.type !== 'add') {
this.data = parseDate(this.data);
setTimeout(() => {
this.form.setFieldsValue(this.data);
}
)
}
})
;
}
,
handleOk(otherValues = {}, path, dateFormat = 'YYYY-MM-DD')
{
this.confirmLoading = true;
// 触发表单验证
this.form.validateFields((err, values) => {
if (!err) {
let formData = Object.assign(values, otherValues);
formData = formatObjDate(formData, dateFormat);
Object.keys(formData).forEach(item => { // 清空字符串前后空格
if (typeof formData[item] === 'string') {
formData[item] = formData[item].trim();
}
})
let axios;
if (this.type === 'edit') { // 修改
if (!this.url.edit) {
this.$message.error('请设置url.edit属性!');
console.error('请设置url.edit属性!');
return;
}
axios = putAction(`${this.url.edit}/${path}`, formData);
} else { // 新增
if (!this.url.add) {
this.$message.error('请设置url.add属性!');
console.error('请设置url.add属性!');
return;
}
axios = postAction(this.url.add, formData);
}
axios.then((res) => {
if (res.code === 201 || res.code === 202) {
this.$emit('ok');
this.close();
}
}).catch(err => {
console.error(err);
}).finally(() => {
this.confirmLoading = false;
});
} else {
this.confirmLoading = false;
}
})
}
,
close()
{
this.confirmLoading = false;
this.disableSubmit = false;
this.$emit('close');
this.$emit('update:show', false);
}
,
// 根据屏幕变化,设置抽屉尺寸
resetScreenSize()
{
const screenWidth = document.body.clientWidth;
if (screenWidth < 500) {
this.drawerWidth = screenWidth;
} else {
this.drawerWidth = 700;
const handleOk = (otherValues = {}, path, dateFormat = 'YYYY-MM-DD') => {
useModalData.confirmLoading = true;
let axios;
if (this.type === 'edit') { // 修改
if (!this.url.edit) {
this.$message.error('请设置url.edit属性!');
console.error('请设置url.edit属性!');
return;
}
axios = putAction(`${this.url.edit}/${path}`, formData);
} else { // 新增
if (!this.url.add) {
this.$message.error('请设置url.add属性!');
console.error('请设置url.add属性!');
return;
}
axios = postAction(this.url.add, formData);
}
,
axios.then((res) => {
if (res.code === 201 || res.code === 202) {
this.$emit('ok');
this.close();
}
}).catch(err => {
console.error(err);
}).finally(() => {
this.confirmLoading = false;
});
}
// 根据屏幕变化,设置抽屉尺寸
const resetScreenSize = () => {
const screenWidth = document.body.clientWidth;
if (screenWidth < 500) {
this.drawerWidth = screenWidth;
} else {
this.drawerWidth = 700;
}
}
};
const getters = {
roles: state => state.user.roles, // 用户权限
router: state => state.permission.router // 用户路由
router: state => state.permission.router, // 用户路由
token: state => state.user.token // 用户路由
}
export default getters
\ No newline at end of file
......@@ -34,7 +34,7 @@ const user = {
// 获取用户信息
getUserInfo({commit}, token) {
return new Promise((resolve, reject) => {
getInfo(token).then(res => {
getInfo().then(res => {
const {data} = res;
console.log('res', data.roles)
commit('SER_USER_ROLES',data.roles)
......
import axios from 'axios'
import {Modal, message} from 'ant-design-vue'
import store from '@/store'
import store from '@/store/index'
import {getToken} from '@/utils/auth'
// create an axios instance
const service = axios.create({
baseURL: import.meta.env.BASE_API, // url = base url + request url
......@@ -14,13 +15,15 @@ const service = axios.create({
service.interceptors.request.use(
config => {
// do something before request is sent
console.log('store',store);
console.log('store.getters.token',store.getters.token);
if (store.getters.token) {
// let each request carry token
// ['X-Token'] is a custom headers key
// please modify it according to the actual situation
config.headers['X-Token'] = getToken()
config.headers['token'] = getToken()
}
console.log('config',config);
return config
},
error => {
......@@ -34,6 +37,8 @@ service.interceptors.request.use(
service.interceptors.response.use(
response => {
const res = response.data
console.log('response',response);
if (res.code !== 200) {
message.error({
content: res.message || 'Error',
......@@ -57,6 +62,7 @@ service.interceptors.response.use(
}
return Promise.reject(new Error(res.message || 'Error'))
} else {
console.log('response',res);
return res
}
},
......
<template>
<!-- <modal >-->
<!-- <div>1232</div>-->
<!-- </modal>-->
<renderPopups :isShow="isShow" :type="2">
<template>
drawer
</template>
<renderPopups v-model:isShow="isShow" :title="title" type="drawer">
<a-spin :spinning="confirmLoading">
<configForm :config="configListForm" ref="getQueryRef" @ok="query" @close="modalCancel"></configForm>
</a-spin>
</renderPopups>
</template>
<script>
import {ref, reactive} from 'vue'
import modal from '@c/modal/index.vue'
import {renderPopups} from '@c/popups/popups'
import {useModal} from "@/hook/useModal";
import configForm from '@c/configForm/form.vue'
export default {
name: "fromModal",
props: {
isShow: Boolean
title: String
},
components: {
modal,
renderPopups
renderPopups,
configForm
},
setup() {
setup(props, {emit}) {
const {onModalShow, isShow, modalCancel, handleOk, confirmLoading} = useModal(emit)
let spinning = ref(false)
let getQueryRef = ref(null)
const query = (data) => {
console.log('spinning', data);
handleOk({
url: {
add: '/api/table/add'
},
formItem: data
})
}
let configListForm = reactive({
data: [
{
inputType: "text",
fieldName: "name",
required: true,
label: "姓名",
placeholder: "请输入姓名"
},
{
inputType: "number",
fieldName: "age",
label: "年龄",
required: true,
placeholder: "请输入年龄"
},
{
inputType: "text",
fieldName: "address",
label: "地址",
required: true,
placeholder: "请输入地址"
},
{
inputType: "date",
fieldName: "time",
label: "时间",
required: true,
placeholder: "请选择时间"
},
{
inputType: "select",
fieldName: "tags",
label: "标签",
required: true,
placeholder: "请选择",
options: [
{value: "0", label: "LOSER"},
{value: "1", label: "TEACHER"},
{value: "2", label: "DEVELOPER"},
{value: "3", label: "NICE"},
{value: "4", label: "COOL"},
]
}
],
})
return {
onModalShow,
isShow,
modalCancel,
//
confirmLoading,
configListForm,
getQueryRef,
query
}
}
}
</script>
......
<template>
<a-space direction="vertical" style="width: 100%">
<a-button @click="onModalShow">新增</a-button>
<a-table :columns="columns" :data-source="data">
<a-button @click="bindModalShow">新增</a-button>
<a-table :columns="columns" :data-source="dataSource"
:rowKey="(row,index) => index">
<template #name="{ text }">{{ text }}</template>
<!--设置表头信息-->
<template #customTitle>
......@@ -32,7 +33,8 @@
</template>
</a-table>
</a-space>
<fromModal v-model:isShow="isShow" :title="13"></fromModal>
<fromModal ref="fromModalRef" title="jsx组价"></fromModal>
</template>
<script>
......@@ -91,26 +93,34 @@
},
];
import {SmileOutlined, DownOutlined} from '@ant-design/icons-vue';
import {useModal} from "@/hook/useModal";
import fromModal from './components/fromModal.vue'
import {ref} from 'vue'
// import {tabelAll} from '@/api/list'
import {useTable} from '@/hook/useTableMdal'
export default {
name: "tableIndex",
setup() {
const {
modalOk,
modalCancel,
onModalShow,
isShow
} = useModal()
setup(props, {emit}) {
const fromModalRef = ref()
const bindModalShow = () => {
console.log(fromModalRef.value);
fromModalRef.value.onModalShow()
}
const {dataSource} = useTable({
dataAll: '/api/table/all'
})
console.log('dataSource', dataSource);
return {
data,
columns,
modalOk,
modalCancel,
onModalShow,
isShow
dataSource,
fromModalRef,
bindModalShow,
};
},
components: {
......
......@@ -10,7 +10,7 @@
</div>
</template>
<script>
import {ref, defineComponent} from 'vue'
import {ref, defineComponent, watch} from 'vue'
export default defineComponent({
name: 'btn1',
......@@ -22,9 +22,9 @@
setup(props, {emit}) {
console.log('props - btn', props);
const num = ref(1)
const close = () => {
console.log('close')
emit('close');
console.log('props - close', 'close')
emit('update:show', false)
}
return {num, close}
......
<template>
<button @click="componentsToggle">切换</button>
<button @click="onShow">显示</button>
<renderFn :type="componentsType" title="自定义title" :show.sync="isShow">
<renderFn :type="componentsType" title="自定义title" v-model:show="isShow">
<div default="{text}">
<p> 默认插槽: 111111</p>
</div>
......@@ -11,18 +11,21 @@
<!-- </template>-->
</renderFn>
<!-- <btn1 title="自定义title" v-model:show="isShow"></btn1>-->
</template>
<script>
import renderFn from './renderFn.js'
import vnode from "./vnode"
import {ref} from 'vue'
import btn1 from './btn1.vue'
export default {
name: "index",
components: {
renderFn,
vnode
vnode,
btn1
},
setup() {
let isShow = ref(false)
......
import btn1 from './btn1.vue'
import btn2 from './btn2.vue'
import {h, watch} from 'vue'
import {h} from 'vue'
// export const renderFn = function (props, {slots}) {
//
......@@ -14,13 +14,14 @@ import {h, watch} from 'vue'
export default {
props: ['type', 'show', 'title'],
setup(props, {slots}) {
setup(props, {slots,emit}) {
console.log('props - renderFn', props);
return () => [
props.type === 1 ? h(btn1, {
title: props.title,
type: props.type,
show: props.show
show: props.show,
'onUpdate:show': (value) => emit('update:show', false)
}, slots.default) : h(btn2)
]
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册