mirror of
https://gitee.com/lab1024/smart-admin.git
synced 2025-11-11 13:13:49 +08:00
@@ -61,7 +61,6 @@
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
(nVal) => {
|
||||
console.log(nVal);
|
||||
editorHtml.value = nVal;
|
||||
},
|
||||
{
|
||||
|
||||
@@ -27,9 +27,13 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed, onMounted, ref, watch } from 'vue';
|
||||
import { computed, onMounted, ref, watch, defineExpose } from 'vue';
|
||||
import { dictApi } from '/src/api/support/dict-api';
|
||||
|
||||
defineExpose({
|
||||
queryDict,
|
||||
});
|
||||
|
||||
const props = defineProps({
|
||||
value: [Array, String],
|
||||
placeholder: {
|
||||
|
||||
@@ -64,24 +64,6 @@
|
||||
dictValueList.value = res.data;
|
||||
}
|
||||
|
||||
const values = computed(() => {
|
||||
if (!props.value) {
|
||||
return [];
|
||||
}
|
||||
if (!Array.isArray(props.value)) {
|
||||
console.error('valueList is not array!!!');
|
||||
return [];
|
||||
}
|
||||
let res = [];
|
||||
if (props.value && props.value.length > 0) {
|
||||
props.value.forEach((element) => {
|
||||
res.push(element.valueCode);
|
||||
});
|
||||
return res;
|
||||
}
|
||||
return res;
|
||||
});
|
||||
|
||||
onMounted(queryDict);
|
||||
|
||||
// -------------------------- 选中 相关、事件 --------------------------
|
||||
@@ -96,21 +78,16 @@
|
||||
|
||||
const emit = defineEmits(['update:value', 'change']);
|
||||
function onChange(value) {
|
||||
let selected = [];
|
||||
if (!value) {
|
||||
emit('update:value', selected);
|
||||
emit('change', selected);
|
||||
return selected;
|
||||
emit('update:value', []);
|
||||
emit('change', []);
|
||||
}
|
||||
if (Array.isArray(props.value)) {
|
||||
let valueList = dictValueList.value.filter((e) => value.includes(e.valueCode));
|
||||
valueList = valueList.map((e) => e.valueCode);
|
||||
emit('update:value', valueList);
|
||||
emit('change', valueList);
|
||||
if (Array.isArray(value)) {
|
||||
emit('update:value', value);
|
||||
emit('change', value);
|
||||
} else {
|
||||
let findValue = dictValueList.value.find((e) => e.valueCode === value);
|
||||
emit('update:value', findValue.valueCode);
|
||||
emit('change', findValue.valueCode);
|
||||
emit('update:value', [value]);
|
||||
emit('change', [value]);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
</a-row>
|
||||
</a-form>
|
||||
<a-table
|
||||
:row-selection="{ selectedRowKeys: selectedRowKeyList, onChange: onSelectChange }"
|
||||
:row-selection="{ selectedRowKeys: selectedRowKeyList, onChange: onSelectChange, getCheckboxProps: getCheckboxProps }"
|
||||
:loading="tableLoading"
|
||||
size="small"
|
||||
:columns="columns"
|
||||
@@ -95,6 +95,7 @@
|
||||
|
||||
const visible = ref(false);
|
||||
async function showModal(selectEmployeeId) {
|
||||
originalRowKeyList.value = selectEmployeeId || [];
|
||||
selectedRowKeyList.value = selectEmployeeId || [];
|
||||
visible.value = true;
|
||||
onSearch();
|
||||
@@ -144,8 +145,9 @@
|
||||
}
|
||||
|
||||
// ----------------------- 员工表格选择 ---------------------
|
||||
const originalRowKeyList = ref([]);
|
||||
let selectedRowKeyList = ref([]);
|
||||
const hasSelected = computed(() => selectedRowKeyList.value.length > 0);
|
||||
const hasSelected = computed(() => selectedRowKeyList.value.length !== originalRowKeyList.value.length);
|
||||
|
||||
function onSelectChange(selectedRowKeys) {
|
||||
selectedRowKeyList.value = selectedRowKeys;
|
||||
@@ -156,10 +158,19 @@
|
||||
message.warning('请选择角色人员');
|
||||
return;
|
||||
}
|
||||
emits('selectData', selectedRowKeyList.value);
|
||||
// 过滤出新选择的人员id
|
||||
const newEmployeeIdList = selectedRowKeyList.value.filter((id) => !originalRowKeyList.value.includes(id));
|
||||
emits('selectData', newEmployeeIdList);
|
||||
closeModal();
|
||||
}
|
||||
|
||||
function getCheckboxProps(record) {
|
||||
return {
|
||||
// 角色员工列表的添加员工弹窗中 禁止添加选择已存在该角色的员工
|
||||
disabled: originalRowKeyList.value.includes(record.employeeId),
|
||||
};
|
||||
}
|
||||
|
||||
// ----------------------- 员工表格渲染 ---------------------
|
||||
const tableData = ref([]);
|
||||
//字段
|
||||
|
||||
@@ -30,4 +30,6 @@ export default {
|
||||
HOME_QUICK_ENTRY: `${KEY_PREFIX}home_quick_entry`,
|
||||
// 通知信息已读
|
||||
NOTICE_READ: `${KEY_PREFIX}notice_read`,
|
||||
// 待办
|
||||
TO_BE_DONE: `${KEY_PREFIX}to_be_done`,
|
||||
};
|
||||
|
||||
@@ -37,7 +37,6 @@
|
||||
import { computed, ref, onMounted } from 'vue';
|
||||
import { loginApi } from '/src/api/system/login-api';
|
||||
import { useUserStore } from '/@/store/modules/system/user';
|
||||
import { localClear } from '/@/utils/local-util';
|
||||
import { smartSentry } from '/@/lib/smart-sentry';
|
||||
import HeaderResetPassword from './header-reset-password-modal/index.vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
@@ -53,7 +52,6 @@
|
||||
} catch (e) {
|
||||
smartSentry.captureError(e);
|
||||
} finally {
|
||||
localClear();
|
||||
useUserStore().logout();
|
||||
location.reload();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
<template>
|
||||
<a-modal v-model:open="showFlag" :width="800" title="消息内容" :destroyOnClose="true" @ok="showFlag = false">
|
||||
<a-descriptions bordered :column="2" size="small">
|
||||
<a-descriptions-item :labelStyle="{ width: '80px' }" :span="1" label="类型"
|
||||
>{{ $smartEnumPlugin.getDescByValue('MESSAGE_TYPE_ENUM', messageDetail.messageType) }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item :labelStyle="{ width: '120px' }" :span="1" label="发送时间">{{ messageDetail.createTime }}</a-descriptions-item>
|
||||
<a-descriptions-item :labelStyle="{ width: '80px' }" :span="2" label="标题">{{ messageDetail.title }}</a-descriptions-item>
|
||||
<a-descriptions-item :labelStyle="{ width: '80px' }" :span="2" label="内容">
|
||||
<pre>{{ messageDetail.content }}</pre>
|
||||
</a-descriptions-item>
|
||||
</a-descriptions>
|
||||
</a-modal>
|
||||
</template>
|
||||
<script setup>
|
||||
import { reactive, ref } from 'vue';
|
||||
import { messageApi } from '/@/api/support/message-api.js';
|
||||
|
||||
const emit = defineEmits(['refresh']);
|
||||
|
||||
const messageDetail = reactive({
|
||||
messageType: '',
|
||||
title: '',
|
||||
content: '',
|
||||
createTime: '',
|
||||
});
|
||||
|
||||
const showFlag = ref(false);
|
||||
|
||||
function show(data) {
|
||||
Object.assign(messageDetail, data);
|
||||
showFlag.value = true;
|
||||
read(data);
|
||||
}
|
||||
|
||||
async function read(message) {
|
||||
if (!message.readFlag) {
|
||||
await messageApi.updateReadFlag(message.messageId);
|
||||
emit('refresh');
|
||||
}
|
||||
}
|
||||
|
||||
defineExpose({ show });
|
||||
</script>
|
||||
@@ -9,26 +9,33 @@
|
||||
-->
|
||||
|
||||
<template>
|
||||
<a-dropdown trigger="click" v-model:open="show">
|
||||
<a-button type="text" @click="queryMessage" style="padding: 4px 5px">
|
||||
<a-badge :count="unreadMessageCount">
|
||||
<div style="width: 26px; height: 26px">
|
||||
<BellOutlined :style="{ fontSize: '16px' }" />
|
||||
</div>
|
||||
</a-badge>
|
||||
</a-button>
|
||||
<div>
|
||||
<a-popover v-model:open="show" trigger="contextmenu" placement="bottomLeft" @openChange="() => (show = true)">
|
||||
<a-button type="text" @click="showMessage" style="padding: 4px 5px">
|
||||
<a-badge :count="unreadMessageCount + toBeDoneCount">
|
||||
<div style="width: 26px; height: 26px">
|
||||
<BellOutlined :style="{ fontSize: '16px' }" />
|
||||
</div>
|
||||
</a-badge>
|
||||
</a-button>
|
||||
|
||||
<template #overlay>
|
||||
<a-card class="message-container" :bodyStyle="{ padding: 0 }">
|
||||
<template #content>
|
||||
<!-- 为了能在点击查看消息详情弹窗的同时防止消息气泡卡片关闭 所以加了一个手动关闭按钮 -->
|
||||
<a-button type="text" @click="closeMessage" style="padding: 4px 5px"> 关闭 </a-button>
|
||||
<a-spin :spinning="loading">
|
||||
<a-tabs class="dropdown-tabs" centered :tabBarStyle="{ textAlign: 'center' }" style="width: 300px">
|
||||
<a-tab-pane tab="未读消息" key="message">
|
||||
<a-tab-pane key="message">
|
||||
<template #tab>
|
||||
未读消息
|
||||
<a-badge :count="unreadMessageCount" showZero :offset="[0, -20]" />
|
||||
</template>
|
||||
<a-list class="tab-pane" size="small">
|
||||
<a-list-item v-for="item in messageList" :key="item.messageId">
|
||||
<a-list-item-meta>
|
||||
<template #title>
|
||||
<div class="title">
|
||||
<a @click="gotoMessage">{{ item.title }}</a>
|
||||
<a-badge status="error" />
|
||||
<a @click="showMessageDetail(item)">{{ item.title }}</a>
|
||||
</div>
|
||||
</template>
|
||||
<template #description>
|
||||
@@ -36,16 +43,34 @@
|
||||
</template>
|
||||
</a-list-item-meta>
|
||||
</a-list-item>
|
||||
<a-list-item v-if="unreadMessageCount > 3">
|
||||
<a-button type="text" @click="gotoMessage" style="padding: 4px 5px"> ... 查看更多 </a-button>
|
||||
</a-list-item>
|
||||
</a-list>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane tab="待办工作" key="todo">
|
||||
<a-list class="tab-pane" />
|
||||
<a-tab-pane key="to_be_done">
|
||||
<template #tab>
|
||||
待办工作
|
||||
<a-badge :count="toBeDoneCount" showZero :offset="[0, -20]" />
|
||||
</template>
|
||||
<a-list class="tab-pane" size="small" :locale="{ emptyText: '暂无待办' }">
|
||||
<a-list-item v-for="(item, index) in toBeDoneList" :key="index">
|
||||
<a-list-item-meta>
|
||||
<template #title>
|
||||
<a-badge status="error" />
|
||||
<a-tag v-if="item.starFlag" color="red">重要</a-tag>
|
||||
<span>{{ item.title }}</span>
|
||||
</template>
|
||||
</a-list-item-meta>
|
||||
</a-list-item>
|
||||
</a-list>
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
</a-spin>
|
||||
</a-card>
|
||||
</template>
|
||||
</a-dropdown>
|
||||
</template>
|
||||
</a-popover>
|
||||
<MessageDetailModal ref="messageDetailModalRef" @refresh="queryMessage" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
@@ -57,19 +82,27 @@
|
||||
import dayjs from 'dayjs';
|
||||
import { theme } from 'ant-design-vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
import MessageDetailModal from './header-message-detail-modal.vue';
|
||||
import localKey from '/@/constants/local-storage-key-const';
|
||||
import { localRead } from '/@/utils/local-util';
|
||||
|
||||
const { useToken } = theme;
|
||||
const { token } = useToken();
|
||||
|
||||
defineExpose({ showMessage });
|
||||
|
||||
function showMessage() {
|
||||
show.value = true;
|
||||
}
|
||||
|
||||
const loading = ref(false);
|
||||
const show = ref(false);
|
||||
|
||||
// 点击按钮打开消息气泡卡片的同时刷新消息
|
||||
function showMessage() {
|
||||
show.value = true;
|
||||
queryMessage();
|
||||
loadToBeDoneList();
|
||||
}
|
||||
|
||||
function closeMessage() {
|
||||
show.value = false;
|
||||
}
|
||||
|
||||
// ------------------------- 查询消息 -------------------------
|
||||
|
||||
// 未读消息
|
||||
@@ -90,6 +123,8 @@
|
||||
readFlag: false,
|
||||
});
|
||||
messageList.value = responseModel.data.list;
|
||||
// 若中途有新消息了 打开列表也能及时更新未读数量
|
||||
useUserStore().queryUnreadMessageCount();
|
||||
} catch (e) {
|
||||
smartSentry.captureError(e);
|
||||
} finally {
|
||||
@@ -97,12 +132,41 @@
|
||||
}
|
||||
}
|
||||
|
||||
const messageDetailModalRef = ref();
|
||||
function showMessageDetail(data) {
|
||||
messageDetailModalRef.value.show(data);
|
||||
}
|
||||
|
||||
const router = useRouter();
|
||||
function gotoMessage() {
|
||||
show.value = false;
|
||||
router.push({ path: '/account', query: { menuId: 'message' } });
|
||||
}
|
||||
|
||||
// ------------------------- 待办工作 -------------------------
|
||||
|
||||
// 待办工作数
|
||||
const toBeDoneCount = computed(() => {
|
||||
return useUserStore().toBeDoneCount;
|
||||
});
|
||||
|
||||
// 待办工作列表
|
||||
const toBeDoneList = ref([]);
|
||||
|
||||
const loadToBeDoneList = async () => {
|
||||
try {
|
||||
loading.value = true;
|
||||
let localToBeDoneList = localRead(localKey.TO_BE_DONE);
|
||||
if (localToBeDoneList) {
|
||||
toBeDoneList.value = JSON.parse(localToBeDoneList).filter((e) => !e.doneFlag);
|
||||
}
|
||||
} catch (err) {
|
||||
smartSentry.captureError(err);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// ------------------------- 时间计算 -------------------------
|
||||
function timeago(dateStr) {
|
||||
let dateTimeStamp = dayjs(dateStr).toDate().getTime();
|
||||
@@ -181,12 +245,13 @@
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.message-container {
|
||||
border: #eeeeee solid 1px;
|
||||
}
|
||||
|
||||
.dropdown-tabs {
|
||||
background-color: @base-bg-color;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.tab-pane {
|
||||
height: 250px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
</a-form-item>
|
||||
<a-form-item :label="$t('setting.color')">
|
||||
<div class="color-container">
|
||||
<template v-for="(item, index) in themeColors">
|
||||
<template v-for="(item, index) in themeColors" :key="index">
|
||||
<div v-if="index === formState.colorIndex" class="color">
|
||||
<CheckSquareFilled :style="{ color: item.primaryColor, fontSize: '22px' }" />
|
||||
</div>
|
||||
@@ -34,7 +34,7 @@
|
||||
>
|
||||
<path
|
||||
d="M128 160.01219c0-17.67619 14.336-32.01219 32.01219-32.01219h704c17.65181 0 31.98781 14.336 31.98781 32.01219v704c0 17.65181-14.336 31.98781-32.01219 31.98781H160.036571a31.98781 31.98781 0 0 1-32.01219-32.01219V160.036571z"
|
||||
></path>
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -57,12 +57,6 @@
|
||||
headerSetting.value.show();
|
||||
}
|
||||
|
||||
//消息通知
|
||||
const headerMessage = ref();
|
||||
function showMessage() {
|
||||
headerMessage.value.showMessage();
|
||||
}
|
||||
|
||||
//帮助文档
|
||||
function showHelpDoc() {
|
||||
useAppConfigStore().showHelpDoc();
|
||||
|
||||
@@ -9,7 +9,8 @@
|
||||
*/
|
||||
import { message, Modal } from 'ant-design-vue';
|
||||
import axios from 'axios';
|
||||
import { localClear, localRead } from '/@/utils/local-util';
|
||||
import { localRead } from '/@/utils/local-util';
|
||||
import { useUserStore } from '/@/store/modules/system/user';
|
||||
import { decryptData, encryptData } from './encrypt';
|
||||
import { DATA_TYPE_ENUM } from '../constants/common-const';
|
||||
import _ from 'lodash';
|
||||
@@ -25,7 +26,7 @@ const smartAxios = axios.create({
|
||||
|
||||
// 退出系统
|
||||
function logout() {
|
||||
localClear();
|
||||
useUserStore().logout();
|
||||
location.href = '/';
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ import { PAGE_PATH_404, PAGE_PATH_LOGIN } from '/@/constants/common-const';
|
||||
import { HOME_PAGE_NAME } from '/@/constants/system/home-const';
|
||||
import SmartLayout from '../layout/index.vue';
|
||||
import { useUserStore } from '/@/store/modules/system/user';
|
||||
import { localClear, localRead } from '/@/utils/local-util';
|
||||
import { localRead } from '/@/utils/local-util';
|
||||
import _ from 'lodash';
|
||||
import LocalStorageKeyConst from '/@/constants/local-storage-key-const.js';
|
||||
|
||||
@@ -41,7 +41,7 @@ router.beforeEach(async (to, from, next) => {
|
||||
// 验证登录
|
||||
const token = localRead(LocalStorageKeyConst.USER_TOKEN);
|
||||
if (!token) {
|
||||
localClear();
|
||||
useUserStore().logout();
|
||||
next({ path: PAGE_PATH_LOGIN });
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -12,10 +12,10 @@ import { defineStore } from 'pinia';
|
||||
import localKey from '/@/constants/local-storage-key-const';
|
||||
import { HOME_PAGE_NAME } from '/@/constants/system/home-const';
|
||||
import { MENU_TYPE_ENUM } from '/@/constants/system/menu-const';
|
||||
import { localClear, localRead, localSave } from '/@/utils/local-util';
|
||||
import LocalStorageKeyConst from '/@/constants/local-storage-key-const';
|
||||
import { messageApi } from '/@/api/support/message-api.js';
|
||||
import { smartSentry } from '/@/lib/smart-sentry.js';
|
||||
import { localRead, localSave, localRemove } from '/@/utils/local-util';
|
||||
|
||||
|
||||
export const useUserStore = defineStore({
|
||||
id: 'userStore',
|
||||
@@ -61,13 +61,15 @@ export const useUserStore = defineStore({
|
||||
keepAliveIncludes: [],
|
||||
// 未读消息数量
|
||||
unreadMessageCount: 0,
|
||||
// 待办工作数
|
||||
toBeDoneCount: 0,
|
||||
}),
|
||||
getters: {
|
||||
getToken(state) {
|
||||
if (state.token) {
|
||||
return state.token;
|
||||
}
|
||||
return localRead(LocalStorageKeyConst.USER_TOKEN);
|
||||
return localRead(localKey.USER_TOKEN);
|
||||
},
|
||||
//是否初始化了 路由
|
||||
getMenuRouterInitFlag(state) {
|
||||
@@ -115,7 +117,9 @@ export const useUserStore = defineStore({
|
||||
this.tagNav = [];
|
||||
this.userInfo = {};
|
||||
this.unreadMessageCount = 0;
|
||||
localClear();
|
||||
localRemove(localKey.USER_TOKEN);
|
||||
localRemove(localKey.USER_POINTS);
|
||||
localRemove(localKey.USER_TAG_NAV);
|
||||
},
|
||||
// 查询未读消息数量
|
||||
async queryUnreadMessageCount() {
|
||||
@@ -126,6 +130,16 @@ export const useUserStore = defineStore({
|
||||
smartSentry.captureError(e);
|
||||
}
|
||||
},
|
||||
async queryToBeDoneList() {
|
||||
try {
|
||||
let localToBeDoneList = localRead(localKey.TO_BE_DONE);
|
||||
if (localToBeDoneList) {
|
||||
this.toBeDoneCount = JSON.parse(localToBeDoneList).filter((e) => !e.doneFlag).length;
|
||||
}
|
||||
} catch (err) {
|
||||
smartSentry.captureError(err);
|
||||
}
|
||||
},
|
||||
//设置登录信息
|
||||
setUserLoginInfo(data) {
|
||||
// 用户基本信息
|
||||
@@ -157,6 +171,8 @@ export const useUserStore = defineStore({
|
||||
|
||||
// 获取用户未读消息
|
||||
this.queryUnreadMessageCount();
|
||||
// 获取待办工作数
|
||||
this.queryToBeDoneList();
|
||||
},
|
||||
setToken(token) {
|
||||
this.token = token;
|
||||
|
||||
@@ -19,3 +19,7 @@ export const localRead = (key) => {
|
||||
export const localClear = () => {
|
||||
localStorage.clear();
|
||||
};
|
||||
|
||||
export const localRemove = (key) => {
|
||||
localStorage.removeItem(key);
|
||||
};
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
<SmartEnumSelect enum-name="GOODS_STATUS_ENUM" v-model:value="form.goodsStatus" />
|
||||
</a-form-item>
|
||||
<a-form-item label="产地" name="place">
|
||||
<DictSelect key-code="GODOS_PLACE" v-model:value="form.place" />
|
||||
<DictSelect width="100%" key-code="GODOS_PLACE" v-model:value="form.place" mode="tags" />
|
||||
</a-form-item>
|
||||
<a-form-item label="上架状态" name="shelvesFlag">
|
||||
<a-radio-group v-model:value="form.shelvesFlag">
|
||||
@@ -80,7 +80,7 @@
|
||||
//商品状态
|
||||
goodsStatus: GOODS_STATUS_ENUM.APPOINTMENT.value,
|
||||
//产地
|
||||
place: undefined,
|
||||
place: [],
|
||||
//商品价格
|
||||
price: undefined,
|
||||
//上架状态
|
||||
@@ -107,9 +107,8 @@
|
||||
Object.assign(form, rowData);
|
||||
}
|
||||
if (form.place && form.place.length > 0) {
|
||||
form.place = form.place[0].valueCode;
|
||||
form.place = form.place.map((e) => e.valueCode);
|
||||
}
|
||||
console.log(form);
|
||||
visible.value = true;
|
||||
nextTick(() => {
|
||||
formRef.value.clearValidate();
|
||||
@@ -127,14 +126,10 @@
|
||||
.then(async () => {
|
||||
SmartLoading.show();
|
||||
try {
|
||||
let params = _.cloneDeep(form);
|
||||
if (params.place && Array.isArray(params.place) && params.place.length > 0) {
|
||||
params.place = params.place[0].valueCode;
|
||||
}
|
||||
if (form.goodsId) {
|
||||
await goodsApi.updateGoods(params);
|
||||
await goodsApi.updateGoods(form);
|
||||
} else {
|
||||
await goodsApi.addGoods(params);
|
||||
await goodsApi.addGoods(form);
|
||||
}
|
||||
message.success(`${form.goodsId ? '修改' : '添加'}成功`);
|
||||
onClose();
|
||||
|
||||
@@ -109,7 +109,7 @@
|
||||
>
|
||||
<template #bodyCell="{ text, record, column }">
|
||||
<template v-if="column.dataIndex === 'place'">
|
||||
<span>{{ text && text.length > 0 ? text[0].valueName : '' }}</span>
|
||||
<span>{{ text && text.length > 0 ? text.map((e) => e.valueName).join(',') : '' }}</span>
|
||||
</template>
|
||||
<template v-if="column.dataIndex === 'goodsStatus'">
|
||||
<span>{{ $smartEnumPlugin.getDescByValue('GOODS_STATUS_ENUM', text) }}</span>
|
||||
|
||||
@@ -2,6 +2,7 @@ import { convertUpperCamel } from '/@/utils/str-util';
|
||||
|
||||
// -------------------------------- java 类型 --------------------------------
|
||||
export const JavaTypeMap = new Map();
|
||||
JavaTypeMap.set('bit', 'Boolean');
|
||||
JavaTypeMap.set('int', 'Integer');
|
||||
JavaTypeMap.set('tinyint', 'Integer');
|
||||
JavaTypeMap.set('smallint', 'Integer');
|
||||
@@ -37,6 +38,7 @@ export function getJavaType(dataType) {
|
||||
|
||||
// -------------------------------- js 类型 --------------------------------
|
||||
export const JsTypeMap = new Map();
|
||||
JsTypeMap.set('bit', 'Boolean');
|
||||
JsTypeMap.set('int', 'Number');
|
||||
JsTypeMap.set('tinyint', 'Number');
|
||||
JsTypeMap.set('smallint', 'Number');
|
||||
@@ -56,11 +58,10 @@ JsTypeMap.set('date', 'Date');
|
||||
JsTypeMap.set('datetime', 'Date');
|
||||
|
||||
export const JsTypeList = [
|
||||
'Boolean', //
|
||||
'Number', //
|
||||
'String', //
|
||||
'Date', //
|
||||
'Boolean', //
|
||||
'String', //
|
||||
];
|
||||
|
||||
export function getJsType(dataType) {
|
||||
@@ -70,8 +71,9 @@ export function getJsType(dataType) {
|
||||
// -------------------------------- 前端组件 --------------------------------
|
||||
|
||||
export const FrontComponentMap = new Map();
|
||||
FrontComponentMap.set('bit', 'BooleanSelect');
|
||||
FrontComponentMap.set('int', 'InputNumber');
|
||||
FrontComponentMap.set('tinyint', 'BooleanSelect');
|
||||
FrontComponentMap.set('tinyint', 'InputNumber');
|
||||
FrontComponentMap.set('smallint', 'InputNumber');
|
||||
FrontComponentMap.set('integer', 'InputNumber');
|
||||
FrontComponentMap.set('year', 'Date');
|
||||
@@ -84,7 +86,7 @@ FrontComponentMap.set('varchar', 'Input');
|
||||
FrontComponentMap.set('tinytext', 'Input');
|
||||
FrontComponentMap.set('text', 'Textarea');
|
||||
FrontComponentMap.set('longtext', 'Textarea');
|
||||
FrontComponentMap.set('blob', 'Upload');
|
||||
FrontComponentMap.set('blob', 'FileUpload');
|
||||
FrontComponentMap.set('date', 'Date');
|
||||
FrontComponentMap.set('datetime', 'DateTime');
|
||||
|
||||
@@ -131,6 +133,7 @@ export const JAVA_FILE_LIST = [
|
||||
'Dao.java', //
|
||||
'Mapper.xml', //
|
||||
...JAVA_DOMAIN_FILE_LIST,
|
||||
'Menu.sql', //
|
||||
];
|
||||
|
||||
// -------------------------------- 枚举enum --------------------------------
|
||||
|
||||
@@ -68,11 +68,12 @@
|
||||
if (deletedFlagColumn) {
|
||||
deleteFlagColumnName.value = deletedFlagColumn.columnName;
|
||||
}
|
||||
console.log(deletedFlagColumn);
|
||||
|
||||
//表单
|
||||
let deleteInfo = config.delete;
|
||||
let deleteInfo = config.deleteInfo;
|
||||
|
||||
formData.isSupportDelete = deleteInfo && deleteInfo.isSupportDelete ? deleteInfo.isSupportDelete : true;
|
||||
formData.isSupportDelete = deleteInfo ? deleteInfo.isSupportDelete : true;
|
||||
formData.isPhysicallyDeleted = deleteInfo && deleteInfo.isPhysicallyDeleted ? deleteInfo.isPhysicallyDeleted : !deletedFlagColumn;
|
||||
formData.deleteEnum = deleteInfo && deleteInfo.deleteEnum ? deleteInfo.deleteEnum : CODE_DELETE_ENUM.SINGLE_AND_BATCH.value;
|
||||
}
|
||||
|
||||
@@ -11,6 +11,10 @@
|
||||
<a-alert :closable="true" message="请务必将每一个字段的 “ 字段名词 ” 填写完整!!!" type="success" show-icon>
|
||||
<template #icon><smile-outlined /></template>
|
||||
</a-alert>
|
||||
<!-- 为了方便再配置时中途新增字典后 可以重新刷新字典下拉 (需要先随便选择一个字典后才能看到最新的字典) -->
|
||||
<div style="float: right; padding: 10px 0px">
|
||||
<a-button type="primary" @click="refreshDict">刷新字典</a-button>
|
||||
</div>
|
||||
<a-table
|
||||
:scroll="{ x: 1300 }"
|
||||
size="small"
|
||||
@@ -64,7 +68,7 @@
|
||||
</template>
|
||||
|
||||
<template v-if="column.dataIndex === 'dict'">
|
||||
<DictKeySelect v-model:value="record.dict" />
|
||||
<DictKeySelect ref="dictRef" v-model:value="record.dict" />
|
||||
</template>
|
||||
|
||||
<template v-if="column.dataIndex === 'enumName'">
|
||||
@@ -81,6 +85,11 @@
|
||||
import { convertUpperCamel, convertLowerCamel } from '/@/utils/str-util';
|
||||
import _ from 'lodash';
|
||||
|
||||
const dictRef = ref();
|
||||
function refreshDict() {
|
||||
dictRef.value.queryDict();
|
||||
}
|
||||
|
||||
//------------------------ 全局数据 ---------------------
|
||||
const tableInfo = inject('tableInfo');
|
||||
|
||||
|
||||
@@ -75,11 +75,9 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import _ from 'lodash';
|
||||
import Sortable from 'sortablejs';
|
||||
import { inject, nextTick, ref } from 'vue';
|
||||
import SmartEnumSelect from '/@/components/framework/smart-enum-select/index.vue';
|
||||
import { SmartLoading } from '/@/components/framework/smart-loading';
|
||||
import { CODE_QUERY_FIELD_QUERY_TYPE_ENUM } from '/@/constants/support/code-generator-const';
|
||||
import { convertLowerCamel } from '/@/utils/str-util';
|
||||
|
||||
@@ -130,12 +128,13 @@
|
||||
|
||||
const tableColumns = ref([]);
|
||||
|
||||
let rowKeyCounter = 1;
|
||||
//初始化设置数据
|
||||
function setData(tableColumnInfos, config) {
|
||||
rowKeyCounter = 1;
|
||||
let data = config && config.queryFields ? config.queryFields : [];
|
||||
for (let index = 0; index < data.length; index++) {
|
||||
data[index].rowKey = 'rowKey' + (index + 1);
|
||||
data[index].rowKey = 'rowKey' + rowKeyCounter;
|
||||
rowKeyCounter++;
|
||||
}
|
||||
tableData.value = data;
|
||||
@@ -147,7 +146,6 @@
|
||||
}
|
||||
|
||||
// ------------------- 增加、删除 -------------------
|
||||
let rowKeyCounter = 1;
|
||||
function addQuery() {
|
||||
tableData.value.push({
|
||||
rowKey: 'rowKey' + rowKeyCounter,
|
||||
@@ -155,13 +153,19 @@
|
||||
fieldName: '',
|
||||
queryTypeEnum: '',
|
||||
columnNameList: null,
|
||||
width: '',
|
||||
width: '200px',
|
||||
});
|
||||
rowKeyCounter++;
|
||||
}
|
||||
|
||||
function onDelete(index) {
|
||||
_.pullAt(tableData.value, index);
|
||||
// 以这种方式删除 列表才会重新渲染
|
||||
const tempList = [...tableData.value];
|
||||
tempList.splice(index, 1);
|
||||
tableData.value = [];
|
||||
nextTick(() => {
|
||||
tableData.value = tempList;
|
||||
});
|
||||
}
|
||||
|
||||
//初始化拖拽
|
||||
@@ -173,6 +177,10 @@
|
||||
ghostClass: 'smart-ghost-class', //设置拖拽停靠样式类名
|
||||
chosenClass: 'smart-ghost-class', //设置选中样式类名
|
||||
handle: '.handle',
|
||||
onEnd: ({ oldIndex, newIndex }) => {
|
||||
const oldRow = tableData.value.splice(oldIndex, 1)[0];
|
||||
tableData.value.splice(newIndex, 0, oldRow);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -211,36 +219,16 @@
|
||||
|
||||
// 获取表单数据
|
||||
function getFieldsForm() {
|
||||
let result = [];
|
||||
let trList = document.querySelectorAll('#smartCodeQueryFieldsTable tbody .column-row');
|
||||
if (trList && trList.length === 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
for (let tr of trList) {
|
||||
let rowKey = tr.getAttribute('data-row-key');
|
||||
if (!rowKey) {
|
||||
continue;
|
||||
}
|
||||
if (rowKey && rowKey.indexOf('rowKey') === -1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let index = parseInt(rowKey.substring(6));
|
||||
let tableItem = tableData.value[index - 1];
|
||||
let obj = {
|
||||
queryTypeEnum: tableItem.queryTypeEnum,
|
||||
label: tableItem.label,
|
||||
fieldName: tableItem.fieldName,
|
||||
columnNameList: tableItem.columnNameList,
|
||||
width: tableItem.width,
|
||||
let result = tableData.value.map((item) => {
|
||||
return {
|
||||
label: item.label,
|
||||
width: item.width,
|
||||
fieldName: item.fieldName,
|
||||
queryTypeEnum: item.queryTypeEnum,
|
||||
// 字符串转为数组
|
||||
columnNameList: item.columnNameList && typeof item.columnNameList === 'string' ? [item.columnNameList] : item.columnNameList,
|
||||
};
|
||||
// 字符串转为数组
|
||||
if (obj.columnNameList && typeof obj.columnNameList === 'string') {
|
||||
obj.columnNameList = [obj.columnNameList];
|
||||
}
|
||||
result.push(obj);
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
title="代码配置"
|
||||
style=""
|
||||
:open="visibleFlag"
|
||||
:width="1000"
|
||||
:width="1500"
|
||||
:footerStyle="{ textAlign: 'right' }"
|
||||
@close="onClose"
|
||||
:maskClosable="false"
|
||||
@@ -175,7 +175,7 @@
|
||||
let insertAndUpdateValidated = await insertAndUpdateRef.value.validateForm();
|
||||
let deleteValidated = await deleteRef.value.validateForm();
|
||||
|
||||
if (!basicValidated || !insertAndUpdateValidated || !deleteValidated ) {
|
||||
if (!basicValidated || !insertAndUpdateValidated || !deleteValidated) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -201,7 +201,7 @@
|
||||
onClose();
|
||||
} catch (e) {
|
||||
smartSentry.captureError(e);
|
||||
}finally{
|
||||
} finally {
|
||||
SmartLoading.hide();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
<a-drawer
|
||||
title="代码预览"
|
||||
:open="visibleFlag"
|
||||
:width="1200"
|
||||
:width="1500"
|
||||
:footerStyle="{ textAlign: 'right' }"
|
||||
:bodyStyle="{ padding: '8px 24px' }"
|
||||
@close="onClose"
|
||||
@@ -37,9 +37,9 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed, nextTick, ref, watch } from 'vue';
|
||||
import { computed, nextTick, ref } from 'vue';
|
||||
import { codeGeneratorApi } from '/@/api/support/code-generator-api';
|
||||
import { JAVA_FILE_LIST, LANGUAGE_LIST, JS_FILE_LIST,TS_FILE_LIST, JAVA_DOMAIN_FILE_LIST } from '../../code-generator-util';
|
||||
import { JAVA_FILE_LIST, LANGUAGE_LIST, JS_FILE_LIST, TS_FILE_LIST } from '../../code-generator-util';
|
||||
import { smartSentry } from '/@/lib/smart-sentry';
|
||||
import { lineNumbersBlock } from '/@/lib/highlight-line-number';
|
||||
import hljs from 'highlight.js';
|
||||
@@ -74,11 +74,11 @@
|
||||
// ------------------ 标签页 ------------------
|
||||
const languageType = ref(LANGUAGE_LIST[0]);
|
||||
const tabList = computed(() => {
|
||||
if(languageType.value === LANGUAGE_LIST[0]){
|
||||
if (languageType.value === LANGUAGE_LIST[0]) {
|
||||
return JS_FILE_LIST;
|
||||
}else if(languageType.value === LANGUAGE_LIST[1]){
|
||||
} else if (languageType.value === LANGUAGE_LIST[1]) {
|
||||
return TS_FILE_LIST;
|
||||
}else{
|
||||
} else {
|
||||
return JAVA_FILE_LIST;
|
||||
}
|
||||
});
|
||||
@@ -86,21 +86,21 @@
|
||||
const fileKey = ref(tabList.value[0]);
|
||||
|
||||
function getLanguage() {
|
||||
if(languageType.value === LANGUAGE_LIST[0]){
|
||||
if (languageType.value === LANGUAGE_LIST[0]) {
|
||||
return 'javascript';
|
||||
}else if(languageType.value === LANGUAGE_LIST[1]){
|
||||
} else if (languageType.value === LANGUAGE_LIST[1]) {
|
||||
return 'typescript';
|
||||
}else{
|
||||
} else {
|
||||
return 'java';
|
||||
}
|
||||
}
|
||||
|
||||
function onChangeLanguageType(e){
|
||||
if(e.target.value === LANGUAGE_LIST[0]){
|
||||
function onChangeLanguageType(e) {
|
||||
if (e.target.value === LANGUAGE_LIST[0]) {
|
||||
fileKey.value = JS_FILE_LIST[0];
|
||||
}else if(e.target.value === LANGUAGE_LIST[1]){
|
||||
} else if (e.target.value === LANGUAGE_LIST[1]) {
|
||||
fileKey.value = TS_FILE_LIST[0];
|
||||
}else{
|
||||
} else {
|
||||
fileKey.value = JAVA_FILE_LIST[0];
|
||||
}
|
||||
onChangeTab(fileKey.value);
|
||||
|
||||
@@ -270,7 +270,7 @@
|
||||
// 下载文件
|
||||
async function download(file) {
|
||||
try {
|
||||
await fileApi.downLoadFile(file.fileName, file.fileKey);
|
||||
await fileApi.downLoadFile(file.fileKey);
|
||||
} catch (e) {
|
||||
smartSentry.captureError(e);
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item label="类型" class="smart-query-form-item">
|
||||
<smart-enum-select v-model:value="queryForm.messageType" placeholder="消息类型" enum-name="MESSAGE_TYPE_ENUM" />
|
||||
<smart-enum-select style="width: 150px" v-model:value="queryForm.messageType" placeholder="消息类型" enum-name="MESSAGE_TYPE_ENUM" />
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item label="消息时间" class="smart-query-form-item">
|
||||
@@ -43,7 +43,7 @@
|
||||
</a-form>
|
||||
|
||||
<a-table size="small" :dataSource="tableData" :columns="columns" rowKey="messageId" :pagination="false" bordered>
|
||||
<template #bodyCell="{ text, record, index, column }">
|
||||
<template #bodyCell="{ text, record, column }">
|
||||
<template v-if="column.dataIndex === 'messageType'">
|
||||
<span>{{ $smartEnumPlugin.getDescByValue('MESSAGE_TYPE_ENUM', text) }}</span>
|
||||
</template>
|
||||
|
||||
@@ -49,7 +49,6 @@
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.card-container {
|
||||
background-color: #fff;
|
||||
height: 100%;
|
||||
|
||||
.title {
|
||||
|
||||
@@ -1,158 +0,0 @@
|
||||
<!--
|
||||
* 已办/代办
|
||||
*
|
||||
* @Author: 1024创新实验室-主任:卓大
|
||||
* @Date: 2022-09-12 22:34:00
|
||||
* @Wechat: zhuda1024
|
||||
* @Email: lab1024@163.com
|
||||
* @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012
|
||||
*
|
||||
-->
|
||||
<template>
|
||||
<default-home-card icon="Star" title="已办待办">
|
||||
<div style="height: 280px">
|
||||
<div class="center column">
|
||||
<a-space direction="vertical" style="width: 100%">
|
||||
<div v-for="(item, index) in toDoList" :key="index" :class="['to-do', { done: item.doneFlag }]">
|
||||
<a-checkbox v-model:checked="item.doneFlag">
|
||||
<span class="task">{{ item.title }}</span>
|
||||
</a-checkbox>
|
||||
<div class="star-icon" @click="itemStar(item)">
|
||||
<StarFilled v-if="item.starFlag" style="color: #ff8c00" />
|
||||
<StarOutlined v-else style="color: #c0c0c0" />
|
||||
</div>
|
||||
</div>
|
||||
<div v-for="(item, index) in doneList" :key="index" :class="['to-do', { done: item.doneFlag }]">
|
||||
<a-checkbox v-model:checked="item.doneFlag">
|
||||
<span class="task">{{ item.title }}</span>
|
||||
</a-checkbox>
|
||||
<div class="star-icon" @click="itemStar(item)">
|
||||
<StarFilled v-if="item.starFlag" style="color: #ff8c00" />
|
||||
<StarOutlined v-else style="color: #c0c0c0" />
|
||||
</div>
|
||||
</div>
|
||||
</a-space>
|
||||
</div>
|
||||
</div>
|
||||
</default-home-card>
|
||||
</template>
|
||||
<script setup>
|
||||
import DefaultHomeCard from '/@/views/system/home/components/default-home-card.vue';
|
||||
import { computed, ref } from 'vue';
|
||||
import dayjs from 'dayjs';
|
||||
import { message } from 'ant-design-vue';
|
||||
|
||||
let taskList = ref([
|
||||
{
|
||||
title: '周五下班前需要提交周报',
|
||||
doneFlag: true,
|
||||
starFlag: true,
|
||||
starTime: 0,
|
||||
},
|
||||
{
|
||||
title: '为SmartAdmin前端小组分配任务',
|
||||
doneFlag: false,
|
||||
starFlag: false,
|
||||
starTime: 0,
|
||||
},
|
||||
{
|
||||
title: '跟进团建内容事宜',
|
||||
doneFlag: false,
|
||||
starFlag: true,
|
||||
starTime: 0,
|
||||
},
|
||||
{
|
||||
title: '跟进客户定制一个软件平台',
|
||||
doneFlag: false,
|
||||
starFlag: false,
|
||||
starTime: 0,
|
||||
},
|
||||
{
|
||||
title: '下个版本的需求确认',
|
||||
doneFlag: false,
|
||||
starFlag: false,
|
||||
starTime: 0,
|
||||
},
|
||||
{
|
||||
title: '线上版本发布',
|
||||
doneFlag: true,
|
||||
starFlag: true,
|
||||
starTime: dayjs().unix(),
|
||||
},
|
||||
{
|
||||
title: '周一财务报销',
|
||||
doneFlag: true,
|
||||
starFlag: false,
|
||||
starTime: 0,
|
||||
},
|
||||
]);
|
||||
|
||||
let toDoList = computed(() => {
|
||||
return taskList.value.filter((e) => !e.doneFlag).sort((a, b) => b.starTime - a.starTime);
|
||||
});
|
||||
|
||||
let doneList = computed(() => {
|
||||
return taskList.value.filter((e) => e.doneFlag);
|
||||
});
|
||||
|
||||
function itemStar(item) {
|
||||
item.starFlag = !item.starFlag;
|
||||
if (item.starFlag) {
|
||||
item.starTime = dayjs().unix();
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------任务新建-----------------------
|
||||
let taskTitle = ref('');
|
||||
function addTask() {
|
||||
if (!taskTitle.value) {
|
||||
message.warn('请输入任务标题');
|
||||
return;
|
||||
}
|
||||
let data = {
|
||||
title: taskTitle.value,
|
||||
doneFlag: false,
|
||||
starFlag: false,
|
||||
starTime: 0,
|
||||
};
|
||||
taskList.value.unshift(data);
|
||||
taskTitle.value = '';
|
||||
}
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.center {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
|
||||
&.column {
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
padding: 0 10px;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
}
|
||||
|
||||
.to-do {
|
||||
width: 100%;
|
||||
border: 1px solid #d3d3d3;
|
||||
border-radius: 4px;
|
||||
padding: 4px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.star-icon {
|
||||
margin-left: auto;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&.done {
|
||||
text-decoration: line-through;
|
||||
color: #8c8c8c;
|
||||
|
||||
.task {
|
||||
color: #8c8c8c;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,177 @@
|
||||
<!--
|
||||
* 待办工作
|
||||
*
|
||||
* @Author: 1024创新实验室-主任:卓大
|
||||
* @Date: 2022-09-12 22:34:00
|
||||
* @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012
|
||||
*
|
||||
-->
|
||||
<template>
|
||||
<default-home-card extra="添加" icon="StarTwoTone" title="待办工作" @extraClick="showAddToBeDone">
|
||||
<div style="height: 280px">
|
||||
<div class="center column">
|
||||
<a-space direction="vertical" style="width: 100%">
|
||||
<a-empty v-if="$lodash.isEmpty(toBeDoneList)" description="暂无待办工作" />
|
||||
<div v-for="(item, index) in toDoList" :key="index" :class="['to-do', { done: item.doneFlag }]">
|
||||
<a-checkbox v-model:checked="item.doneFlag" @change="handleCheckbox">
|
||||
<span class="task">{{ item.title }}</span>
|
||||
</a-checkbox>
|
||||
<div v-if="!item.doneFlag" class="star-icon" @click="itemStar(item)">
|
||||
<StarFilled v-if="item.starFlag" style="color: #ff8c00" />
|
||||
<StarOutlined v-else style="color: #c0c0c0" />
|
||||
</div>
|
||||
<close-circle-outlined class="delete-icon" @click="toDelete(item)" />
|
||||
</div>
|
||||
<div v-for="(item, index) in doneList" :key="index" :class="['to-do', { done: item.doneFlag }]">
|
||||
<a-checkbox v-model:checked="item.doneFlag" @change="handleCheckbox">
|
||||
<span class="task">{{ item.title }}</span>
|
||||
</a-checkbox>
|
||||
<div v-if="!item.doneFlag" class="star-icon" @click="itemStar(item)">
|
||||
<StarFilled v-if="item.starFlag" style="color: #ff8c00" />
|
||||
<StarOutlined v-else style="color: #c0c0c0" />
|
||||
</div>
|
||||
<close-circle-outlined class="delete-icon" @click="toDelete(item)" />
|
||||
</div>
|
||||
</a-space>
|
||||
</div>
|
||||
</div>
|
||||
</default-home-card>
|
||||
<ToBeDoneModal ref="toBeDoneModalRef" @addToBeDone="addToBeDone" />
|
||||
</template>
|
||||
<script setup>
|
||||
import DefaultHomeCard from '/@/views/system/home/components/default-home-card.vue';
|
||||
import ToBeDoneModal from './to-be-done-modal.vue';
|
||||
import localKey from '/@/constants/local-storage-key-const';
|
||||
import { localRead, localSave } from '/@/utils/local-util';
|
||||
import { useUserStore } from '/@/store/modules/system/user.js';
|
||||
import { computed, ref, onMounted } from 'vue';
|
||||
import { Modal } from 'ant-design-vue';
|
||||
|
||||
let toBeDoneList = ref([]);
|
||||
|
||||
onMounted(() => {
|
||||
initTaskList();
|
||||
});
|
||||
|
||||
function initTaskList() {
|
||||
let localTaskList = localRead(localKey.TO_BE_DONE);
|
||||
if (localTaskList) {
|
||||
toBeDoneList.value = JSON.parse(localTaskList);
|
||||
}
|
||||
}
|
||||
|
||||
let toDoList = computed(() => {
|
||||
return toBeDoneList.value.filter((e) => !e.doneFlag);
|
||||
});
|
||||
|
||||
let doneList = computed(() => {
|
||||
return toBeDoneList.value.filter((e) => e.doneFlag);
|
||||
});
|
||||
|
||||
function handleCheckbox(e) {
|
||||
localSave(localKey.TO_BE_DONE, JSON.stringify(toBeDoneList.value));
|
||||
useUserStore().toBeDoneCount = toDoList.value.length;
|
||||
}
|
||||
|
||||
function itemStar(data) {
|
||||
data.starFlag = !data.starFlag;
|
||||
// 将取消 star 的删除掉
|
||||
const index = toBeDoneList.value.findIndex((item) => item.title === data.title);
|
||||
toBeDoneList.value.splice(index, 1);
|
||||
if (data.starFlag) {
|
||||
// 最新添加标记star的移动到第一位
|
||||
toBeDoneList.value.unshift(data);
|
||||
} else {
|
||||
// 取消标记star的移动到最后一个标记 star 的后面添加
|
||||
const lastStarIndex = toBeDoneList.value.findLastIndex((item) => item.starFlag);
|
||||
toBeDoneList.value.splice(lastStarIndex + 1, 0, data);
|
||||
}
|
||||
localSave(localKey.TO_BE_DONE, JSON.stringify(toBeDoneList.value));
|
||||
}
|
||||
|
||||
//-------------------------任务新建-----------------------
|
||||
|
||||
let toBeDoneModalRef = ref();
|
||||
|
||||
function showAddToBeDone() {
|
||||
toBeDoneModalRef.value.showModal();
|
||||
}
|
||||
|
||||
// 添加待办工作
|
||||
function addToBeDone(data) {
|
||||
toBeDoneList.value.push(data);
|
||||
localSave(localKey.TO_BE_DONE, JSON.stringify(toBeDoneList.value));
|
||||
useUserStore().toBeDoneCount = toDoList.value.length;
|
||||
}
|
||||
|
||||
function toDelete(data) {
|
||||
if (!data.doneFlag) {
|
||||
Modal.confirm({
|
||||
title: '提示',
|
||||
content: '确定要删除吗?',
|
||||
okText: '删除',
|
||||
okType: 'danger',
|
||||
onOk() {
|
||||
deleteToBeDone(data);
|
||||
},
|
||||
cancelText: '取消',
|
||||
onCancel() {},
|
||||
});
|
||||
} else {
|
||||
deleteToBeDone(data);
|
||||
}
|
||||
}
|
||||
|
||||
// 删除待办工作
|
||||
function deleteToBeDone(data) {
|
||||
const index = toBeDoneList.value.findIndex((item) => item.title === data.title);
|
||||
toBeDoneList.value.splice(index, 1);
|
||||
localSave(localKey.TO_BE_DONE, JSON.stringify(toBeDoneList.value));
|
||||
useUserStore().toBeDoneCount = toDoList.value.length;
|
||||
}
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.center {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
|
||||
&.column {
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
padding: 0 10px;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
}
|
||||
|
||||
.to-do {
|
||||
width: 100%;
|
||||
border: 1px solid #d3d3d3;
|
||||
border-radius: 4px;
|
||||
padding: 4px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.star-icon {
|
||||
margin-left: auto;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&.done {
|
||||
text-decoration: line-through;
|
||||
color: #8c8c8c;
|
||||
|
||||
.task {
|
||||
color: #8c8c8c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.delete-icon {
|
||||
color: #f08080;
|
||||
padding-left: 10px;
|
||||
top: -5px;
|
||||
right: -5px;
|
||||
float: right;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,65 @@
|
||||
<template>
|
||||
<div>
|
||||
<a-modal v-model:open="visible" title="新建待办" @close="onClose">
|
||||
<a-form ref="formRef" :model="form" :rules="rules">
|
||||
<a-form-item label="标题" name="title">
|
||||
<a-input v-model:value="form.title" placeholder="请输入标题" />
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
<template #footer>
|
||||
<a-button @click="onClose">取消</a-button>
|
||||
<a-button type="primary" @click="onSubmit">确定</a-button>
|
||||
</template>
|
||||
</a-modal>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { reactive, ref } from 'vue';
|
||||
import { message } from 'ant-design-vue';
|
||||
import _ from 'lodash';
|
||||
|
||||
defineExpose({
|
||||
showModal,
|
||||
});
|
||||
|
||||
const emit = defineEmits(['addToBeDone']);
|
||||
|
||||
// 组件ref
|
||||
const formRef = ref();
|
||||
|
||||
const formDefault = {
|
||||
title: undefined,
|
||||
doneFlag: false,
|
||||
starFlag: false,
|
||||
starTime: 0,
|
||||
};
|
||||
let form = reactive({ ...formDefault });
|
||||
const rules = {
|
||||
title: [{ required: true, message: '标题不能为空' }],
|
||||
};
|
||||
|
||||
const visible = ref(false);
|
||||
|
||||
function showModal() {
|
||||
visible.value = true;
|
||||
}
|
||||
|
||||
function onClose() {
|
||||
Object.assign(form, formDefault);
|
||||
visible.value = false;
|
||||
}
|
||||
|
||||
function onSubmit() {
|
||||
formRef.value
|
||||
.validate()
|
||||
.then(() => {
|
||||
emit('addToBeDone', _.cloneDeep(form));
|
||||
onClose();
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log('error', error);
|
||||
message.error('参数验证错误,请仔细填写表单数据!');
|
||||
});
|
||||
}
|
||||
</script>
|
||||
<style lang="less" scoped></style>
|
||||
@@ -70,7 +70,7 @@
|
||||
import HomeNotice from './home-notice.vue';
|
||||
import HomeQuickEntry from './components/quick-entry/home-quick-entry.vue';
|
||||
import OfficialAccountCard from './components/official-account-card.vue';
|
||||
import ToBeDoneCard from './components/to-be-done-card.vue';
|
||||
import ToBeDoneCard from './components/to-be-done-card/home-to-be-done.vue';
|
||||
import ChangelogCard from './components/changelog-card.vue';
|
||||
import Gauge from './components/echarts/gauge.vue';
|
||||
import Category from './components/echarts/category.vue';
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
<a-switch v-model:checked="form.visibleFlag" checked-children="显示" un-checked-children="不显示" />
|
||||
</a-form-item>
|
||||
<a-form-item label="禁用状态" name="frameFlag">
|
||||
<a-switch v-model:checked="form.disabledFlag" checked-children="启用" un-checked-children="禁用" />
|
||||
<a-switch v-model:checked="form.disabledFlag" :checkedValue="false" :unCheckedValue="true" checked-children="启用" un-checked-children="禁用" />
|
||||
</a-form-item>
|
||||
</template>
|
||||
<!-- 目录 菜单 end -->
|
||||
@@ -74,7 +74,7 @@
|
||||
<MenuTreeSelect ref="contextMenuTreeSelect" v-model:value="form.contextMenuId" />
|
||||
</a-form-item>
|
||||
<a-form-item label="功能点状态" name="frameFlag">
|
||||
<a-switch v-model:checked="form.disabledFlag" checked-children="启用" un-checked-children="禁用" />
|
||||
<a-switch v-model:checked="form.disabledFlag" :checkedValue="false" :unCheckedValue="true" checked-children="启用" un-checked-children="禁用" />
|
||||
</a-form-item>
|
||||
<a-form-item label="权限类型" name="permsType">
|
||||
<a-radio-group v-model:value="form.permsType">
|
||||
|
||||
@@ -168,7 +168,7 @@
|
||||
|
||||
async function addRoleEmployee() {
|
||||
let res = await roleApi.getRoleAllEmployee(selectRoleId.value);
|
||||
let selectedIdList = res.data.map((e) => e.roleId) || [];
|
||||
let selectedIdList = res.data.map((e) => e.employeeId) || [];
|
||||
selectEmployeeModal.value.showModal(selectedIdList);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user