feat:完善转移、共享、分组功能
This commit is contained in:
parent
7cb83882b8
commit
da7397ce7e
@ -76,8 +76,8 @@
|
|||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="block-content">
|
<view class="block-content">
|
||||||
<view v-if="archive.groups && archive.groups.length" class="tags-wrap">
|
<view v-if="archiveGroupNames.length" class="tags-wrap">
|
||||||
<view v-for="tag in archive.groups" :key="tag" class="tag-item">
|
<view v-for="tag in archiveGroupNames" :key="tag" class="tag-item">
|
||||||
{{ tag }}
|
{{ tag }}
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@ -184,13 +184,13 @@
|
|||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view class="group-list">
|
<view class="group-list">
|
||||||
<view v-for="g in groupOptions" :key="g" class="group-item" @click="toggleGroup(g)">
|
<view v-for="g in teamGroups" :key="g._id" class="group-item" @click="toggleGroup(String(g._id))">
|
||||||
<uni-icons
|
<uni-icons
|
||||||
:type="selectedGroupMap[g] ? 'checkbox-filled' : 'checkbox'"
|
:type="selectedGroupMap[String(g._id)] ? 'checkbox-filled' : 'checkbox'"
|
||||||
size="20"
|
size="20"
|
||||||
:color="selectedGroupMap[g] ? '#4f6ef7' : '#c7c7c7'"
|
:color="selectedGroupMap[String(g._id)] ? '#4f6ef7' : '#c7c7c7'"
|
||||||
/>
|
/>
|
||||||
<text class="group-name">{{ g }}</text>
|
<text class="group-name">{{ g.groupName }}</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
@ -259,8 +259,7 @@ const archive = ref({
|
|||||||
createdByDoctor: true,
|
createdByDoctor: true,
|
||||||
hasBindWechat: false,
|
hasBindWechat: false,
|
||||||
notes: '',
|
notes: '',
|
||||||
groups: [],
|
groupIds: []
|
||||||
groupOptions: ['高血压', '糖尿病', '高血脂']
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const accountStore = useAccountStore();
|
const accountStore = useAccountStore();
|
||||||
@ -295,6 +294,7 @@ function normalizeArchiveFromApi(raw) {
|
|||||||
createTime: r.createTime || '',
|
createTime: r.createTime || '',
|
||||||
creator: r.creator || '',
|
creator: r.creator || '',
|
||||||
notes: r.notes || r.remark || '',
|
notes: r.notes || r.remark || '',
|
||||||
|
groupIds: Array.isArray(r.groupIds) ? r.groupIds : [],
|
||||||
};
|
};
|
||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
@ -321,6 +321,7 @@ async function fetchArchive() {
|
|||||||
}
|
}
|
||||||
archive.value = { ...archive.value, ...normalizeArchiveFromApi(res.data) };
|
archive.value = { ...archive.value, ...normalizeArchiveFromApi(res.data) };
|
||||||
saveToStorage();
|
saveToStorage();
|
||||||
|
await fetchTeamGroups(true);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
toast('获取档案失败');
|
toast('获取档案失败');
|
||||||
} finally {
|
} finally {
|
||||||
@ -328,6 +329,56 @@ async function fetchArchive() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const teamGroups = ref([]);
|
||||||
|
const groupNameMap = computed(() => {
|
||||||
|
const map = new Map();
|
||||||
|
(Array.isArray(teamGroups.value) ? teamGroups.value : []).forEach((g) => {
|
||||||
|
if (g && g._id && g.groupName) map.set(String(g._id), String(g.groupName));
|
||||||
|
});
|
||||||
|
return map;
|
||||||
|
});
|
||||||
|
|
||||||
|
const archiveGroupNames = computed(() => {
|
||||||
|
const ids = Array.isArray(archive.value.groupIds) ? archive.value.groupIds : [];
|
||||||
|
const map = groupNameMap.value;
|
||||||
|
return ids.map((id) => map.get(String(id))).filter(Boolean);
|
||||||
|
});
|
||||||
|
|
||||||
|
function sortGroupList(list) {
|
||||||
|
const { orderList, corpList, restList } = (Array.isArray(list) ? list : []).reduce(
|
||||||
|
(p, c) => {
|
||||||
|
if (typeof c?.sortOrder === 'number') p.orderList.push(c);
|
||||||
|
else if (c?.parentGroupId) p.corpList.push(c);
|
||||||
|
else p.restList.push(c);
|
||||||
|
return p;
|
||||||
|
},
|
||||||
|
{ orderList: [], corpList: [], restList: [] }
|
||||||
|
);
|
||||||
|
orderList.sort((a, b) => a.sortOrder - b.sortOrder);
|
||||||
|
return [...orderList, ...corpList, ...restList];
|
||||||
|
}
|
||||||
|
|
||||||
|
async function fetchTeamGroups(silent = false) {
|
||||||
|
const corpId = getCorpId();
|
||||||
|
const team = uni.getStorageSync(CURRENT_TEAM_STORAGE_KEY) || {};
|
||||||
|
const teamId = team?.teamId ? String(team.teamId) : '';
|
||||||
|
if (!corpId || !teamId) return;
|
||||||
|
try {
|
||||||
|
const projection = { _id: 1, groupName: 1, parentGroupId: 1, sortOrder: 1 };
|
||||||
|
const res = await api('getGroups', { corpId, teamId, page: 1, pageSize: 1000, projection, countGroupMember: false });
|
||||||
|
if (!res?.success) {
|
||||||
|
if (!silent) toast(res?.message || '获取分组失败');
|
||||||
|
teamGroups.value = [];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const list = Array.isArray(res.data) ? res.data : Array.isArray(res.data?.data) ? res.data.data : [];
|
||||||
|
teamGroups.value = sortGroupList(list);
|
||||||
|
} catch (e) {
|
||||||
|
if (!silent) toast('获取分组失败');
|
||||||
|
teamGroups.value = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function updateArchive(patch) {
|
async function updateArchive(patch) {
|
||||||
const id = String(archiveId.value || '');
|
const id = String(archiveId.value || '');
|
||||||
if (!id) return false;
|
if (!id) return false;
|
||||||
@ -375,8 +426,7 @@ onLoad((options) => {
|
|||||||
archive.value = {
|
archive.value = {
|
||||||
...archive.value,
|
...archive.value,
|
||||||
...cached,
|
...cached,
|
||||||
groups: Array.isArray(cached.groups) ? cached.groups : archive.value.groups,
|
groupIds: Array.isArray(cached.groupIds) ? cached.groupIds : archive.value.groupIds
|
||||||
groupOptions: Array.isArray(cached.groupOptions) ? cached.groupOptions : archive.value.groupOptions
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -416,8 +466,7 @@ onShow(() => {
|
|||||||
archive.value = {
|
archive.value = {
|
||||||
...archive.value,
|
...archive.value,
|
||||||
...cached,
|
...cached,
|
||||||
groups: Array.isArray(cached.groups) ? cached.groups : archive.value.groups,
|
groupIds: Array.isArray(cached.groupIds) ? cached.groupIds : archive.value.groupIds,
|
||||||
groupOptions: Array.isArray(cached.groupOptions) ? cached.groupOptions : archive.value.groupOptions,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
setTimeout(measureTabsTop, 30);
|
setTimeout(measureTabsTop, 30);
|
||||||
@ -528,19 +577,18 @@ const saveNotes = () => {
|
|||||||
const groupPopup = ref(null);
|
const groupPopup = ref(null);
|
||||||
const addGroupPopup = ref(null);
|
const addGroupPopup = ref(null);
|
||||||
|
|
||||||
const groupOptions = computed(() => (Array.isArray(archive.value.groupOptions) ? archive.value.groupOptions : []));
|
|
||||||
|
|
||||||
const selectedGroupMap = ref({});
|
const selectedGroupMap = ref({});
|
||||||
|
|
||||||
const syncSelectedMapFromArchive = () => {
|
const syncSelectedMapFromArchive = () => {
|
||||||
const current = Array.isArray(archive.value.groups) ? archive.value.groups : [];
|
const current = Array.isArray(archive.value.groupIds) ? archive.value.groupIds.map(String) : [];
|
||||||
selectedGroupMap.value = current.reduce((acc, name) => {
|
selectedGroupMap.value = current.reduce((acc, id) => {
|
||||||
acc[name] = true;
|
acc[String(id)] = true;
|
||||||
return acc;
|
return acc;
|
||||||
}, {});
|
}, {});
|
||||||
};
|
};
|
||||||
|
|
||||||
const openGroups = () => {
|
const openGroups = async () => {
|
||||||
|
await fetchTeamGroups(false);
|
||||||
syncSelectedMapFromArchive();
|
syncSelectedMapFromArchive();
|
||||||
groupPopup.value?.open();
|
groupPopup.value?.open();
|
||||||
};
|
};
|
||||||
@ -549,14 +597,54 @@ const closeGroups = () => {
|
|||||||
groupPopup.value?.close();
|
groupPopup.value?.close();
|
||||||
};
|
};
|
||||||
|
|
||||||
const toggleGroup = (name) => {
|
const toggleGroup = (groupId) => {
|
||||||
selectedGroupMap.value[name] = !selectedGroupMap.value[name];
|
const key = String(groupId || '');
|
||||||
|
if (!key) return;
|
||||||
|
selectedGroupMap.value[key] = !selectedGroupMap.value[key];
|
||||||
};
|
};
|
||||||
|
|
||||||
const saveGroups = () => {
|
async function applyGroupChange(nextIds) {
|
||||||
archive.value.groups = Object.keys(selectedGroupMap.value).filter(k => selectedGroupMap.value[k]);
|
const memberId = String(archiveId.value || '');
|
||||||
saveToStorage();
|
if (!memberId) return false;
|
||||||
closeGroups();
|
const prevIds = Array.isArray(archive.value.groupIds) ? archive.value.groupIds.map(String) : [];
|
||||||
|
const next = Array.isArray(nextIds) ? nextIds.map(String).filter(Boolean) : [];
|
||||||
|
|
||||||
|
const toAdd = next.filter((id) => !prevIds.includes(id));
|
||||||
|
const toRemove = prevIds.filter((id) => !next.includes(id));
|
||||||
|
|
||||||
|
if (toAdd.length === 0 && toRemove.length === 0) return true;
|
||||||
|
|
||||||
|
loading('保存中...');
|
||||||
|
try {
|
||||||
|
for (const id of toAdd) {
|
||||||
|
const res = await api('addGroupIdForMember', { memberId, toGroupId: id });
|
||||||
|
if (!res?.success) {
|
||||||
|
toast(res?.message || '分组保存失败');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const id of toRemove) {
|
||||||
|
const res = await api('addGroupIdForMember', { memberId, fromGroupId: id });
|
||||||
|
if (!res?.success) {
|
||||||
|
toast(res?.message || '分组保存失败');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
uni.setStorageSync(NEED_RELOAD_STORAGE_KEY, 1);
|
||||||
|
await fetchArchive();
|
||||||
|
return true;
|
||||||
|
} catch (e) {
|
||||||
|
toast('分组保存失败');
|
||||||
|
return false;
|
||||||
|
} finally {
|
||||||
|
hideLoading();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const saveGroups = async () => {
|
||||||
|
const nextIds = Object.keys(selectedGroupMap.value).filter((k) => selectedGroupMap.value[k]);
|
||||||
|
const ok = await applyGroupChange(nextIds);
|
||||||
|
if (ok) closeGroups();
|
||||||
};
|
};
|
||||||
|
|
||||||
// 添加新分组
|
// 添加新分组
|
||||||
@ -571,22 +659,46 @@ const closeAddGroup = () => {
|
|||||||
addGroupPopup.value?.close();
|
addGroupPopup.value?.close();
|
||||||
};
|
};
|
||||||
|
|
||||||
const saveAddGroup = () => {
|
const saveAddGroup = async () => {
|
||||||
const name = String(newGroupName.value || '').trim();
|
const name = String(newGroupName.value || '').trim();
|
||||||
if (!name) {
|
if (!name) {
|
||||||
uni.showToast({ title: '请输入分组名称', icon: 'none' });
|
uni.showToast({ title: '请输入分组名称', icon: 'none' });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const exists = groupOptions.value.some(g => String(g).trim() === name);
|
const exists = (Array.isArray(teamGroups.value) ? teamGroups.value : []).some((g) => String(g?.groupName || '').trim() === name);
|
||||||
if (exists) {
|
if (exists) {
|
||||||
uni.showToast({ title: '该分组已存在', icon: 'none' });
|
uni.showToast({ title: '该分组已存在', icon: 'none' });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
archive.value.groupOptions = [...groupOptions.value, name];
|
const corpId = getCorpId();
|
||||||
selectedGroupMap.value[name] = true;
|
const team = uni.getStorageSync(CURRENT_TEAM_STORAGE_KEY) || {};
|
||||||
saveToStorage();
|
const teamId = team?.teamId ? String(team.teamId) : '';
|
||||||
closeAddGroup();
|
const creator = getUserId();
|
||||||
|
if (!corpId || !teamId || !creator) {
|
||||||
|
toast('缺少用户/团队信息');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
loading('保存中...');
|
||||||
|
try {
|
||||||
|
const params = { groupName: name, teamId, groupType: 'team', creator };
|
||||||
|
const res = await api('createGroup', { corpId, teamId, params });
|
||||||
|
if (!res?.success) {
|
||||||
|
toast(res?.message || '新增分组失败');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await fetchTeamGroups(true);
|
||||||
|
// 自动选中新建分组(后续在“保存”时调用 addGroupIdForMember)
|
||||||
|
const newId = res.data ? String(res.data) : '';
|
||||||
|
if (newId) selectedGroupMap.value[newId] = true;
|
||||||
|
uni.setStorageSync('ykt_case_groups_need_reload', 1);
|
||||||
|
closeAddGroup();
|
||||||
|
} catch (e) {
|
||||||
|
toast('新增分组失败');
|
||||||
|
} finally {
|
||||||
|
hideLoading();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@ -3,8 +3,8 @@
|
|||||||
<view class="content">
|
<view class="content">
|
||||||
<view class="section-title">选择共享团队</view>
|
<view class="section-title">选择共享团队</view>
|
||||||
<view class="selector-item" @click="selectTeam">
|
<view class="selector-item" @click="selectTeam">
|
||||||
<text :class="team ? '' : 'placeholder'">{{ team ? team.name : "请选择团队" }}</text>
|
<text :class="team ? '' : 'placeholder'">{{ team ? team.name : '请选择团队' }}</text>
|
||||||
<uni-icons type="arrowdown" size="16" color="#999"></uni-icons>
|
<uni-icons type="arrowdown" size="16" color="#999" />
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view class="tips">共享客户:表示客户档案共享多个团队可见,多个团队可同时为该客户服务。</view>
|
<view class="tips">共享客户:表示客户档案共享多个团队可见,多个团队可同时为该客户服务。</view>
|
||||||
@ -12,8 +12,8 @@
|
|||||||
<template v-if="team">
|
<template v-if="team">
|
||||||
<view class="section-title">选择责任人</view>
|
<view class="section-title">选择责任人</view>
|
||||||
<view class="selector-item" @click="selectUser">
|
<view class="selector-item" @click="selectUser">
|
||||||
<text :class="user ? '' : 'placeholder'">{{ user ? user.name : "请选择责任人" }}</text>
|
<text :class="userId ? '' : 'placeholder'">{{ userLabel || '请选择责任人' }}</text>
|
||||||
<uni-icons type="arrowdown" size="16" color="#999"></uni-icons>
|
<uni-icons type="arrowdown" size="16" color="#999" />
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
</view>
|
</view>
|
||||||
@ -26,39 +26,129 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref } from 'vue';
|
import { computed, ref } from 'vue';
|
||||||
|
import { onLoad } from '@dcloudio/uni-app';
|
||||||
|
import { storeToRefs } from 'pinia';
|
||||||
|
import api from '@/utils/api';
|
||||||
|
import useAccountStore from '@/store/account';
|
||||||
|
import { hideLoading, loading, toast } from '@/utils/widget';
|
||||||
|
|
||||||
|
const CURRENT_TEAM_STORAGE_KEY = 'ykt_case_current_team';
|
||||||
|
const NEED_RELOAD_STORAGE_KEY = 'ykt_case_need_reload';
|
||||||
|
const BATCH_CUSTOMER_IDS_KEY = 'ykt_case_batch_customer_ids';
|
||||||
|
|
||||||
|
const accountStore = useAccountStore();
|
||||||
|
const { account, doctorInfo } = storeToRefs(accountStore);
|
||||||
|
const { getDoctorInfo } = accountStore;
|
||||||
|
|
||||||
|
const customerIds = ref([]);
|
||||||
|
const currentTeam = ref(null);
|
||||||
|
const teams = ref([]);
|
||||||
const team = ref(null);
|
const team = ref(null);
|
||||||
const user = ref(null);
|
const teamMembers = ref([]);
|
||||||
|
const userId = ref('');
|
||||||
|
|
||||||
// Mock Data
|
const userLabel = computed(() => {
|
||||||
const teams = [
|
const list = Array.isArray(teamMembers.value) ? teamMembers.value : [];
|
||||||
{ id: 1, name: '李医生团队' },
|
const found = list.find((m) => String(m?.userid || '') === String(userId.value));
|
||||||
{ id: 2, name: '王医生团队' }
|
return found ? String(found.anotherName || found.name || found.userid || '') : '';
|
||||||
];
|
});
|
||||||
|
|
||||||
const users = [
|
function getUserId() {
|
||||||
{ id: 101, name: '张医生' },
|
const d = doctorInfo.value || {};
|
||||||
{ id: 102, name: '李医生' },
|
const a = account.value || {};
|
||||||
{ id: 103, name: '王医生' }
|
return String(d.userid || d.userId || d.corpUserId || a.userid || a.userId || '') || '';
|
||||||
];
|
}
|
||||||
|
|
||||||
const selectTeam = () => {
|
function getCorpId() {
|
||||||
|
const t = currentTeam.value || {};
|
||||||
|
const a = account.value || {};
|
||||||
|
const d = doctorInfo.value || {};
|
||||||
|
return String(t.corpId || d.corpId || a.corpId || '') || '';
|
||||||
|
}
|
||||||
|
|
||||||
|
function getCurrentTeamId() {
|
||||||
|
return String(currentTeam.value?.teamId || '') || '';
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizeTeam(raw) {
|
||||||
|
if (!raw || typeof raw !== 'object') return null;
|
||||||
|
const teamId = raw.teamId || raw.id || raw._id || '';
|
||||||
|
const name = raw.name || raw.teamName || raw.team || '';
|
||||||
|
const corpId = raw.corpId || raw.corpID || '';
|
||||||
|
if (!teamId || !name) return null;
|
||||||
|
return { teamId: String(teamId), name: String(name), corpId: corpId ? String(corpId) : '' };
|
||||||
|
}
|
||||||
|
|
||||||
|
async function ensureDoctor() {
|
||||||
|
if (doctorInfo.value) return;
|
||||||
|
if (!account.value?.openid) return;
|
||||||
|
try {
|
||||||
|
await getDoctorInfo();
|
||||||
|
} catch (e) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function loadTeams() {
|
||||||
|
await ensureDoctor();
|
||||||
|
const corpId = getCorpId();
|
||||||
|
const userId = getUserId();
|
||||||
|
if (!corpId || !userId) return;
|
||||||
|
const res = await api('getTeamBymember', { corpId, corpUserId: userId });
|
||||||
|
if (!res?.success) {
|
||||||
|
toast(res?.message || '获取团队失败');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const list = Array.isArray(res?.data) ? res.data : Array.isArray(res?.data?.data) ? res.data.data : [];
|
||||||
|
teams.value = list.map(normalizeTeam).filter(Boolean);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function loadTeamMembers(teamId) {
|
||||||
|
const corpId = getCorpId();
|
||||||
|
if (!teamId) return;
|
||||||
|
const res = await api('getTeamData', { corpId, teamId });
|
||||||
|
if (!res?.success) {
|
||||||
|
toast(res?.message || '获取团队成员失败');
|
||||||
|
teamMembers.value = [];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const t = res?.data && typeof res.data === 'object' ? res.data : {};
|
||||||
|
teamMembers.value = Array.isArray(t.memberList) ? t.memberList : [];
|
||||||
|
}
|
||||||
|
|
||||||
|
const selectTeam = async () => {
|
||||||
|
if (!teams.value.length) await loadTeams();
|
||||||
|
const currentId = getCurrentTeamId();
|
||||||
|
const candidates = teams.value.filter((t) => t.teamId !== currentId);
|
||||||
|
if (!candidates.length) {
|
||||||
|
toast('暂无可选团队');
|
||||||
|
return;
|
||||||
|
}
|
||||||
uni.showActionSheet({
|
uni.showActionSheet({
|
||||||
itemList: teams.map(t => t.name),
|
itemList: candidates.map((t) => t.name),
|
||||||
success: (res) => {
|
success: async (res) => {
|
||||||
team.value = teams[res.tapIndex];
|
team.value = candidates[res.tapIndex] || null;
|
||||||
user.value = null;
|
userId.value = '';
|
||||||
}
|
teamMembers.value = [];
|
||||||
|
if (team.value) await loadTeamMembers(team.value.teamId);
|
||||||
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const selectUser = () => {
|
const selectUser = () => {
|
||||||
|
const list = Array.isArray(teamMembers.value) ? teamMembers.value : [];
|
||||||
|
if (!list.length) {
|
||||||
|
toast('当前团队暂无可选成员');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const labels = list.map((m) => String(m?.anotherName || m?.name || m?.userid || ''));
|
||||||
uni.showActionSheet({
|
uni.showActionSheet({
|
||||||
itemList: users.map(u => u.name),
|
itemList: labels,
|
||||||
success: (res) => {
|
success: (res) => {
|
||||||
user.value = users[res.tapIndex];
|
const picked = list[res.tapIndex];
|
||||||
}
|
userId.value = picked?.userid ? String(picked.userid) : '';
|
||||||
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -66,25 +156,52 @@ const cancel = () => {
|
|||||||
uni.navigateBack();
|
uni.navigateBack();
|
||||||
};
|
};
|
||||||
|
|
||||||
const save = () => {
|
const save = async () => {
|
||||||
if (!team.value) {
|
if (!team.value) return toast('请选择团队');
|
||||||
uni.showToast({ title: '请选择团队', icon: 'none' });
|
if (!userId.value) return toast('请选择负责人');
|
||||||
return;
|
const corpId = getCorpId();
|
||||||
}
|
const currentTeamId = getCurrentTeamId();
|
||||||
if (!user.value) {
|
const creatorUserId = getUserId();
|
||||||
uni.showToast({ title: '请选择负责人', icon: 'none' });
|
if (!corpId || !currentTeamId || !creatorUserId) return toast('缺少用户/团队信息');
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
uni.showLoading({ title: '保存中' });
|
loading('保存中...');
|
||||||
setTimeout(() => {
|
try {
|
||||||
uni.hideLoading();
|
const res = await api('transferCustomers', {
|
||||||
uni.showToast({ title: '操作成功' });
|
corpId,
|
||||||
setTimeout(() => {
|
customerIds: customerIds.value,
|
||||||
uni.navigateBack();
|
currentTeamId,
|
||||||
}, 1500);
|
targetTeamId: team.value.teamId,
|
||||||
}, 1000);
|
targetUserId: userId.value,
|
||||||
|
operationType: 'share',
|
||||||
|
creatorUserId,
|
||||||
|
});
|
||||||
|
if (!res?.success) {
|
||||||
|
toast(res?.message || '操作失败');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
toast('操作成功');
|
||||||
|
uni.removeStorageSync(BATCH_CUSTOMER_IDS_KEY);
|
||||||
|
uni.setStorageSync(NEED_RELOAD_STORAGE_KEY, 1);
|
||||||
|
uni.navigateBack();
|
||||||
|
} catch (e) {
|
||||||
|
toast('操作失败');
|
||||||
|
} finally {
|
||||||
|
hideLoading();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
onLoad(async () => {
|
||||||
|
customerIds.value = Array.isArray(uni.getStorageSync(BATCH_CUSTOMER_IDS_KEY))
|
||||||
|
? uni.getStorageSync(BATCH_CUSTOMER_IDS_KEY).map(String).filter(Boolean)
|
||||||
|
: [];
|
||||||
|
currentTeam.value = uni.getStorageSync(CURRENT_TEAM_STORAGE_KEY) || null;
|
||||||
|
if (!customerIds.value.length) {
|
||||||
|
toast('未选择客户');
|
||||||
|
setTimeout(() => uni.navigateBack(), 200);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await loadTeams();
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
@ -143,7 +260,7 @@ const save = () => {
|
|||||||
padding: 15px 20px 30px;
|
padding: 15px 20px 30px;
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 15px;
|
gap: 15px;
|
||||||
box-shadow: 0 -2px 10px rgba(0,0,0,0.05);
|
box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.05);
|
||||||
|
|
||||||
.btn {
|
.btn {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
@ -171,3 +288,4 @@ const save = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|||||||
@ -3,15 +3,15 @@
|
|||||||
<view class="content">
|
<view class="content">
|
||||||
<view class="section-title">选择新负责团队</view>
|
<view class="section-title">选择新负责团队</view>
|
||||||
<view class="selector-item" @click="selectTeam">
|
<view class="selector-item" @click="selectTeam">
|
||||||
<text :class="team ? '' : 'placeholder'">{{ team ? team.name : "请选择选择团队" }}</text>
|
<text :class="team ? '' : 'placeholder'">{{ team ? team.name : '请选择团队' }}</text>
|
||||||
<uni-icons type="arrowdown" size="16" color="#999"></uni-icons>
|
<uni-icons type="arrowdown" size="16" color="#999" />
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<template v-if="team">
|
<template v-if="team">
|
||||||
<view class="section-title">选择责任人</view>
|
<view class="section-title">选择责任人</view>
|
||||||
<view class="selector-item" @click="selectUser">
|
<view class="selector-item" @click="selectUser">
|
||||||
<text :class="user ? '' : 'placeholder'">{{ user ? user.name : "请选择责任人" }}</text>
|
<text :class="userId ? '' : 'placeholder'">{{ userLabel || '请选择责任人' }}</text>
|
||||||
<uni-icons type="arrowdown" size="16" color="#999"></uni-icons>
|
<uni-icons type="arrowdown" size="16" color="#999" />
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -26,40 +26,129 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref } from 'vue';
|
import { computed, ref } from 'vue';
|
||||||
|
import { onLoad } from '@dcloudio/uni-app';
|
||||||
|
import { storeToRefs } from 'pinia';
|
||||||
|
import api from '@/utils/api';
|
||||||
|
import useAccountStore from '@/store/account';
|
||||||
|
import { hideLoading, loading, toast } from '@/utils/widget';
|
||||||
|
|
||||||
|
const CURRENT_TEAM_STORAGE_KEY = 'ykt_case_current_team';
|
||||||
|
const NEED_RELOAD_STORAGE_KEY = 'ykt_case_need_reload';
|
||||||
|
const BATCH_CUSTOMER_IDS_KEY = 'ykt_case_batch_customer_ids';
|
||||||
|
|
||||||
|
const accountStore = useAccountStore();
|
||||||
|
const { account, doctorInfo } = storeToRefs(accountStore);
|
||||||
|
const { getDoctorInfo } = accountStore;
|
||||||
|
|
||||||
|
const customerIds = ref([]);
|
||||||
|
const currentTeam = ref(null);
|
||||||
|
const teams = ref([]);
|
||||||
const team = ref(null);
|
const team = ref(null);
|
||||||
const user = ref(null);
|
const teamMembers = ref([]);
|
||||||
|
const userId = ref('');
|
||||||
|
|
||||||
// Mock Data
|
const userLabel = computed(() => {
|
||||||
const teams = [
|
const list = Array.isArray(teamMembers.value) ? teamMembers.value : [];
|
||||||
{ id: 1, name: '张敏西服务团队' },
|
const found = list.find((m) => String(m?.userid || '') === String(userId.value));
|
||||||
{ id: 2, name: '李医生团队' },
|
return found ? String(found.anotherName || found.name || found.userid || '') : '';
|
||||||
{ id: 3, name: '王医生团队' }
|
});
|
||||||
];
|
|
||||||
|
|
||||||
const users = [
|
function getUserId() {
|
||||||
{ id: 101, name: '张医生' },
|
const d = doctorInfo.value || {};
|
||||||
{ id: 102, name: '李医生' },
|
const a = account.value || {};
|
||||||
{ id: 103, name: '王医生' }
|
return String(d.userid || d.userId || d.corpUserId || a.userid || a.userId || '') || '';
|
||||||
];
|
}
|
||||||
|
|
||||||
const selectTeam = () => {
|
function getCorpId() {
|
||||||
|
const t = currentTeam.value || {};
|
||||||
|
const a = account.value || {};
|
||||||
|
const d = doctorInfo.value || {};
|
||||||
|
return String(t.corpId || d.corpId || a.corpId || '') || '';
|
||||||
|
}
|
||||||
|
|
||||||
|
function getCurrentTeamId() {
|
||||||
|
return String(currentTeam.value?.teamId || '') || '';
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizeTeam(raw) {
|
||||||
|
if (!raw || typeof raw !== 'object') return null;
|
||||||
|
const teamId = raw.teamId || raw.id || raw._id || '';
|
||||||
|
const name = raw.name || raw.teamName || raw.team || '';
|
||||||
|
const corpId = raw.corpId || raw.corpID || '';
|
||||||
|
if (!teamId || !name) return null;
|
||||||
|
return { teamId: String(teamId), name: String(name), corpId: corpId ? String(corpId) : '' };
|
||||||
|
}
|
||||||
|
|
||||||
|
async function ensureDoctor() {
|
||||||
|
if (doctorInfo.value) return;
|
||||||
|
if (!account.value?.openid) return;
|
||||||
|
try {
|
||||||
|
await getDoctorInfo();
|
||||||
|
} catch (e) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function loadTeams() {
|
||||||
|
await ensureDoctor();
|
||||||
|
const corpId = getCorpId();
|
||||||
|
const userId = getUserId();
|
||||||
|
if (!corpId || !userId) return;
|
||||||
|
const res = await api('getTeamBymember', { corpId, corpUserId: userId });
|
||||||
|
if (!res?.success) {
|
||||||
|
toast(res?.message || '获取团队失败');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const list = Array.isArray(res?.data) ? res.data : Array.isArray(res?.data?.data) ? res.data.data : [];
|
||||||
|
teams.value = list.map(normalizeTeam).filter(Boolean);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function loadTeamMembers(teamId) {
|
||||||
|
const corpId = getCorpId();
|
||||||
|
if (!teamId) return;
|
||||||
|
const res = await api('getTeamData', { corpId, teamId });
|
||||||
|
if (!res?.success) {
|
||||||
|
toast(res?.message || '获取团队成员失败');
|
||||||
|
teamMembers.value = [];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const t = res?.data && typeof res.data === 'object' ? res.data : {};
|
||||||
|
teamMembers.value = Array.isArray(t.memberList) ? t.memberList : [];
|
||||||
|
}
|
||||||
|
|
||||||
|
const selectTeam = async () => {
|
||||||
|
if (!teams.value.length) await loadTeams();
|
||||||
|
const currentId = getCurrentTeamId();
|
||||||
|
const candidates = teams.value.filter((t) => t.teamId !== currentId);
|
||||||
|
if (!candidates.length) {
|
||||||
|
toast('暂无可选团队');
|
||||||
|
return;
|
||||||
|
}
|
||||||
uni.showActionSheet({
|
uni.showActionSheet({
|
||||||
itemList: teams.map(t => t.name),
|
itemList: candidates.map((t) => t.name),
|
||||||
success: (res) => {
|
success: async (res) => {
|
||||||
team.value = teams[res.tapIndex];
|
team.value = candidates[res.tapIndex] || null;
|
||||||
user.value = null; // Reset user when team changes
|
userId.value = '';
|
||||||
}
|
teamMembers.value = [];
|
||||||
|
if (team.value) await loadTeamMembers(team.value.teamId);
|
||||||
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const selectUser = () => {
|
const selectUser = () => {
|
||||||
|
const list = Array.isArray(teamMembers.value) ? teamMembers.value : [];
|
||||||
|
if (!list.length) {
|
||||||
|
toast('当前团队暂无可选成员');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const labels = list.map((m) => String(m?.anotherName || m?.name || m?.userid || ''));
|
||||||
uni.showActionSheet({
|
uni.showActionSheet({
|
||||||
itemList: users.map(u => u.name),
|
itemList: labels,
|
||||||
success: (res) => {
|
success: (res) => {
|
||||||
user.value = users[res.tapIndex];
|
const picked = list[res.tapIndex];
|
||||||
}
|
userId.value = picked?.userid ? String(picked.userid) : '';
|
||||||
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -67,25 +156,53 @@ const cancel = () => {
|
|||||||
uni.navigateBack();
|
uni.navigateBack();
|
||||||
};
|
};
|
||||||
|
|
||||||
const save = () => {
|
const save = async () => {
|
||||||
if (!team.value) {
|
if (!team.value) return toast('请选择团队');
|
||||||
uni.showToast({ title: '请选择团队', icon: 'none' });
|
if (!userId.value) return toast('请选择负责人');
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!user.value) {
|
|
||||||
uni.showToast({ title: '请选择责任人', icon: 'none' });
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
uni.showLoading({ title: '保存中' });
|
const corpId = getCorpId();
|
||||||
setTimeout(() => {
|
const currentTeamId = getCurrentTeamId();
|
||||||
uni.hideLoading();
|
const creatorUserId = getUserId();
|
||||||
uni.showToast({ title: '操作成功' });
|
if (!corpId || !currentTeamId || !creatorUserId) return toast('缺少用户/团队信息');
|
||||||
setTimeout(() => {
|
|
||||||
uni.navigateBack();
|
loading('保存中...');
|
||||||
}, 1500);
|
try {
|
||||||
}, 1000);
|
const res = await api('transferCustomers', {
|
||||||
|
corpId,
|
||||||
|
customerIds: customerIds.value,
|
||||||
|
currentTeamId,
|
||||||
|
targetTeamId: team.value.teamId,
|
||||||
|
targetUserId: userId.value,
|
||||||
|
operationType: 'transferToOtherTeam',
|
||||||
|
creatorUserId,
|
||||||
|
});
|
||||||
|
if (!res?.success) {
|
||||||
|
toast(res?.message || '操作失败');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
toast('操作成功');
|
||||||
|
uni.removeStorageSync(BATCH_CUSTOMER_IDS_KEY);
|
||||||
|
uni.setStorageSync(NEED_RELOAD_STORAGE_KEY, 1);
|
||||||
|
uni.navigateBack();
|
||||||
|
} catch (e) {
|
||||||
|
toast('操作失败');
|
||||||
|
} finally {
|
||||||
|
hideLoading();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
onLoad(async () => {
|
||||||
|
customerIds.value = Array.isArray(uni.getStorageSync(BATCH_CUSTOMER_IDS_KEY))
|
||||||
|
? uni.getStorageSync(BATCH_CUSTOMER_IDS_KEY).map(String).filter(Boolean)
|
||||||
|
: [];
|
||||||
|
currentTeam.value = uni.getStorageSync(CURRENT_TEAM_STORAGE_KEY) || null;
|
||||||
|
if (!customerIds.value.length) {
|
||||||
|
toast('未选择客户');
|
||||||
|
setTimeout(() => uni.navigateBack(), 200);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await loadTeams();
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
@ -144,7 +261,7 @@ const save = () => {
|
|||||||
padding: 15px 20px 30px;
|
padding: 15px 20px 30px;
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 15px;
|
gap: 15px;
|
||||||
box-shadow: 0 -2px 10px rgba(0,0,0,0.05);
|
box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.05);
|
||||||
|
|
||||||
.btn {
|
.btn {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
@ -172,3 +289,4 @@ const save = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|||||||
@ -31,13 +31,13 @@
|
|||||||
<scroll-view scroll-x class="tabs-scroll" :show-scrollbar="false">
|
<scroll-view scroll-x class="tabs-scroll" :show-scrollbar="false">
|
||||||
<view class="tabs-container">
|
<view class="tabs-container">
|
||||||
<view
|
<view
|
||||||
v-for="(tab, index) in tabs"
|
v-for="tab in tabs"
|
||||||
:key="index"
|
:key="tab.key"
|
||||||
class="tab-item"
|
class="tab-item"
|
||||||
:class="{ active: currentTab === index }"
|
:class="{ active: currentTabKey === tab.key }"
|
||||||
@click="currentTab = index"
|
@click="onTabClick(tab)"
|
||||||
>
|
>
|
||||||
{{ tab }}
|
{{ tab.label }}
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</scroll-view>
|
</scroll-view>
|
||||||
@ -83,7 +83,7 @@
|
|||||||
|
|
||||||
<!-- Row 2 / 3 -->
|
<!-- Row 2 / 3 -->
|
||||||
<view class="card-row-bottom">
|
<view class="card-row-bottom">
|
||||||
<template v-if="currentTab === 1"> <!-- New Patient Tab -->
|
<template v-if="currentTabKey === 'new'"> <!-- New Patient Tab -->
|
||||||
<text class="record-text">
|
<text class="record-text">
|
||||||
{{ patient.createTime || '-' }} / {{ patient.creator || '-' }}
|
{{ patient.createTime || '-' }} / {{ patient.creator || '-' }}
|
||||||
</text>
|
</text>
|
||||||
@ -147,9 +147,19 @@ import { toast } from '@/utils/widget';
|
|||||||
// State
|
// State
|
||||||
const teams = ref([]);
|
const teams = ref([]);
|
||||||
const currentTeam = ref(null);
|
const currentTeam = ref(null);
|
||||||
const currentTab = ref(0);
|
const currentTabKey = ref('all');
|
||||||
const scrollIntoId = ref('');
|
const scrollIntoId = ref('');
|
||||||
const tabs = ['全部', '新患者', '糖尿病', '高血压', '冠心病', '慢阻肺'];
|
const teamGroups = ref([]);
|
||||||
|
const tabs = computed(() => {
|
||||||
|
const base = [
|
||||||
|
{ key: 'all', label: '全部', kind: 'all' },
|
||||||
|
{ key: 'new', label: '新患者', kind: 'new' },
|
||||||
|
];
|
||||||
|
const groupTabs = (Array.isArray(teamGroups.value) ? teamGroups.value : [])
|
||||||
|
.filter((g) => g && g._id && g.groupName)
|
||||||
|
.map((g) => ({ key: `group:${g._id}`, label: String(g.groupName), kind: 'group', groupId: String(g._id) }));
|
||||||
|
return [...base, ...groupTabs];
|
||||||
|
});
|
||||||
const isBatchMode = ref(false);
|
const isBatchMode = ref(false);
|
||||||
const selectedItems = ref([]); // Stores patient phone or unique ID
|
const selectedItems = ref([]); // Stores patient phone or unique ID
|
||||||
|
|
||||||
@ -162,6 +172,8 @@ const verifyFailedReason = ref('资料不完整,请补充营业执照/资质
|
|||||||
const DETAIL_STORAGE_KEY = 'ykt_case_archive_detail';
|
const DETAIL_STORAGE_KEY = 'ykt_case_archive_detail';
|
||||||
const CURRENT_TEAM_STORAGE_KEY = 'ykt_case_current_team';
|
const CURRENT_TEAM_STORAGE_KEY = 'ykt_case_current_team';
|
||||||
const NEED_RELOAD_STORAGE_KEY = 'ykt_case_need_reload';
|
const NEED_RELOAD_STORAGE_KEY = 'ykt_case_need_reload';
|
||||||
|
const GROUPS_RELOAD_KEY = 'ykt_case_groups_need_reload';
|
||||||
|
const BATCH_CUSTOMER_IDS_KEY = 'ykt_case_batch_customer_ids';
|
||||||
|
|
||||||
const page = ref(1);
|
const page = ref(1);
|
||||||
const pages = ref(0);
|
const pages = ref(0);
|
||||||
@ -170,6 +182,7 @@ const totalFromApi = ref(0);
|
|||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
const rawPatients = ref([]);
|
const rawPatients = ref([]);
|
||||||
const more = computed(() => page.value < pages.value);
|
const more = computed(() => page.value < pages.value);
|
||||||
|
const currentTab = computed(() => tabs.value.find((t) => t.key === currentTabKey.value) || tabs.value[0]);
|
||||||
|
|
||||||
const accountStore = useAccountStore();
|
const accountStore = useAccountStore();
|
||||||
const { account, doctorInfo } = storeToRefs(accountStore);
|
const { account, doctorInfo } = storeToRefs(accountStore);
|
||||||
@ -207,6 +220,41 @@ function getTeamId() {
|
|||||||
return String(currentTeam.value?.teamId || '') || '';
|
return String(currentTeam.value?.teamId || '') || '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function sortGroupList(list) {
|
||||||
|
const { orderList, corpList, restList } = (Array.isArray(list) ? list : []).reduce(
|
||||||
|
(p, c) => {
|
||||||
|
if (typeof c?.sortOrder === 'number') p.orderList.push(c);
|
||||||
|
else if (c?.parentGroupId) p.corpList.push(c);
|
||||||
|
else p.restList.push(c);
|
||||||
|
return p;
|
||||||
|
},
|
||||||
|
{ orderList: [], corpList: [], restList: [] }
|
||||||
|
);
|
||||||
|
orderList.sort((a, b) => a.sortOrder - b.sortOrder);
|
||||||
|
return [...orderList, ...corpList, ...restList];
|
||||||
|
}
|
||||||
|
|
||||||
|
async function loadGroups() {
|
||||||
|
if (!currentTeam.value) return;
|
||||||
|
const corpId = getCorpId();
|
||||||
|
const teamId = getTeamId();
|
||||||
|
if (!corpId || !teamId) return;
|
||||||
|
const projection = { _id: 1, groupName: 1, parentGroupId: 1, sortOrder: 1 };
|
||||||
|
const res = await api('getGroups', { corpId, teamId, page: 1, pageSize: 1000, projection, countGroupMember: false });
|
||||||
|
if (!res?.success) {
|
||||||
|
teamGroups.value = [];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const list = Array.isArray(res.data) ? res.data : Array.isArray(res.data?.data) ? res.data.data : [];
|
||||||
|
teamGroups.value = sortGroupList(list);
|
||||||
|
|
||||||
|
// 当前 tab 如果是分组,但分组已不存在,则回退到“全部”
|
||||||
|
if (currentTabKey.value.startsWith('group:')) {
|
||||||
|
const gid = currentTabKey.value.slice('group:'.length);
|
||||||
|
if (!teamGroups.value.some((g) => String(g._id) === String(gid))) currentTabKey.value = 'all';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function getLetter(patient) {
|
function getLetter(patient) {
|
||||||
const raw = patient?.firstLetter || patient?.nameFirstLetter || patient?.pinyinFirstLetter || patient?.letter || '';
|
const raw = patient?.firstLetter || patient?.nameFirstLetter || patient?.pinyinFirstLetter || patient?.letter || '';
|
||||||
const candidate = String(raw || '').trim();
|
const candidate = String(raw || '').trim();
|
||||||
@ -342,14 +390,25 @@ async function reload(reset = true) {
|
|||||||
totalFromApi.value = 0;
|
totalFromApi.value = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
loading.value = true;
|
const query = {
|
||||||
const res = await api('searchCorpCustomerWithFollowTime', {
|
|
||||||
corpId,
|
corpId,
|
||||||
userId,
|
userId,
|
||||||
teamId,
|
teamId,
|
||||||
page: page.value,
|
page: page.value,
|
||||||
pageSize: pageSize.value,
|
pageSize: pageSize.value,
|
||||||
});
|
};
|
||||||
|
|
||||||
|
if (currentTab.value.kind === 'group' && currentTab.value.groupId) {
|
||||||
|
query.groupIds = [currentTab.value.groupId];
|
||||||
|
} else if (currentTab.value.kind === 'new') {
|
||||||
|
const start = dayjs().subtract(7, 'day').startOf('day').valueOf();
|
||||||
|
const end = dayjs().endOf('day').valueOf();
|
||||||
|
query.startCreateTime = start;
|
||||||
|
query.endCreateTime = end;
|
||||||
|
}
|
||||||
|
|
||||||
|
loading.value = true;
|
||||||
|
const res = await api('searchCorpCustomerWithFollowTime', query);
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
|
|
||||||
if (!res?.success) {
|
if (!res?.success) {
|
||||||
@ -409,7 +468,7 @@ const patientList = computed(() => {
|
|||||||
const all = rawPatients.value || [];
|
const all = rawPatients.value || [];
|
||||||
|
|
||||||
// New Patient Filter (Last 7 days)
|
// New Patient Filter (Last 7 days)
|
||||||
if (currentTab.value === 1) {
|
if (currentTab.value.kind === 'new') {
|
||||||
const now = dayjs();
|
const now = dayjs();
|
||||||
const sevenDaysAgo = now.subtract(7, 'day').valueOf();
|
const sevenDaysAgo = now.subtract(7, 'day').valueOf();
|
||||||
const flatList = all
|
const flatList = all
|
||||||
@ -423,25 +482,18 @@ const patientList = computed(() => {
|
|||||||
return [{ letter: '最近新增', data: flatList }];
|
return [{ letter: '最近新增', data: flatList }];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tab Filtering (Mock logic for other tabs)
|
return groupByLetter(all);
|
||||||
let filtered = all;
|
|
||||||
if (currentTab.value > 1) {
|
|
||||||
const tabName = tabs[currentTab.value];
|
|
||||||
filtered = filtered.filter((p) => Array.isArray(p.tags) && p.tags.includes(tabName));
|
|
||||||
}
|
|
||||||
return groupByLetter(filtered);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const indexList = computed(() => {
|
const indexList = computed(() => {
|
||||||
if (currentTab.value === 1) return []; // No index bar for new patient
|
if (currentTab.value.kind === 'new') return []; // No index bar for new patient
|
||||||
return 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('').filter(l => patientList.value.some(g => g.letter === l));
|
return 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('').filter(l => patientList.value.some(g => g.letter === l));
|
||||||
});
|
});
|
||||||
|
|
||||||
const totalPatients = computed(() => {
|
const totalPatients = computed(() => {
|
||||||
let count = 0;
|
let count = 0;
|
||||||
patientList.value.forEach(g => count += g.data.length);
|
patientList.value.forEach(g => count += g.data.length);
|
||||||
if (currentTab.value === 0 && totalFromApi.value) return totalFromApi.value;
|
return totalFromApi.value || count;
|
||||||
return count;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Methods
|
// Methods
|
||||||
@ -454,7 +506,7 @@ const checkBatchMode = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const scrollToLetter = (letter) => {
|
const scrollToLetter = (letter) => {
|
||||||
if (currentTab.value === 1) return;
|
if (currentTab.value.kind === 'new') return;
|
||||||
scrollIntoId.value = letterToDomId(letter);
|
scrollIntoId.value = letterToDomId(letter);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -469,6 +521,8 @@ const toggleTeamPopup = () => {
|
|||||||
success: function (res) {
|
success: function (res) {
|
||||||
currentTeam.value = teams.value[res.tapIndex] || teams.value[0] || null;
|
currentTeam.value = teams.value[res.tapIndex] || teams.value[0] || null;
|
||||||
if (currentTeam.value) uni.setStorageSync(CURRENT_TEAM_STORAGE_KEY, currentTeam.value);
|
if (currentTeam.value) uni.setStorageSync(CURRENT_TEAM_STORAGE_KEY, currentTeam.value);
|
||||||
|
currentTabKey.value = 'all';
|
||||||
|
loadGroups();
|
||||||
reload(true);
|
reload(true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -619,6 +673,7 @@ const handleTransfer = () => {
|
|||||||
uni.showToast({ title: '请选择患者', icon: 'none' });
|
uni.showToast({ title: '请选择患者', icon: 'none' });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
uni.setStorageSync(BATCH_CUSTOMER_IDS_KEY, selectedItems.value.slice());
|
||||||
// Navigate to Transfer Page
|
// Navigate to Transfer Page
|
||||||
uni.navigateTo({ url: '/pages/case/batch-transfer' });
|
uni.navigateTo({ url: '/pages/case/batch-transfer' });
|
||||||
};
|
};
|
||||||
@ -628,12 +683,12 @@ const handleShare = () => {
|
|||||||
uni.showToast({ title: '请选择患者', icon: 'none' });
|
uni.showToast({ title: '请选择患者', icon: 'none' });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
uni.setStorageSync(BATCH_CUSTOMER_IDS_KEY, selectedItems.value.slice());
|
||||||
// Navigate to Share Page
|
// Navigate to Share Page
|
||||||
uni.navigateTo({ url: '/pages/case/batch-share' });
|
uni.navigateTo({ url: '/pages/case/batch-share' });
|
||||||
};
|
};
|
||||||
|
|
||||||
function loadMore() {
|
function loadMore() {
|
||||||
if (currentTab.value === 1) return;
|
|
||||||
if (!more.value || loading.value) return;
|
if (!more.value || loading.value) return;
|
||||||
page.value += 1;
|
page.value += 1;
|
||||||
reload(false);
|
reload(false);
|
||||||
@ -644,9 +699,24 @@ watch(currentTeam, (t) => {
|
|||||||
uni.setStorageSync(CURRENT_TEAM_STORAGE_KEY, t);
|
uni.setStorageSync(CURRENT_TEAM_STORAGE_KEY, t);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
watch(currentTabKey, () => {
|
||||||
|
if (!currentTeam.value) return;
|
||||||
|
reload(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
function onTabClick(tab) {
|
||||||
|
if (checkBatchMode()) return;
|
||||||
|
if (!tab || !tab.key) return;
|
||||||
|
if (currentTabKey.value === tab.key) return;
|
||||||
|
currentTabKey.value = tab.key;
|
||||||
|
}
|
||||||
|
|
||||||
onLoad(async () => {
|
onLoad(async () => {
|
||||||
await loadTeams();
|
await loadTeams();
|
||||||
if (currentTeam.value) await reload(true);
|
if (currentTeam.value) {
|
||||||
|
await loadGroups();
|
||||||
|
await reload(true);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
onShow(async () => {
|
onShow(async () => {
|
||||||
@ -654,6 +724,18 @@ onShow(async () => {
|
|||||||
if (need) {
|
if (need) {
|
||||||
uni.removeStorageSync(NEED_RELOAD_STORAGE_KEY);
|
uni.removeStorageSync(NEED_RELOAD_STORAGE_KEY);
|
||||||
await reload(true);
|
await reload(true);
|
||||||
|
// 批量操作完成后回到列表,默认退出批量态
|
||||||
|
isBatchMode.value = false;
|
||||||
|
selectedItems.value = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
const needGroups = uni.getStorageSync(GROUPS_RELOAD_KEY);
|
||||||
|
if (needGroups) {
|
||||||
|
uni.removeStorageSync(GROUPS_RELOAD_KEY);
|
||||||
|
await loadGroups();
|
||||||
|
await reload(true);
|
||||||
|
} else {
|
||||||
|
await loadGroups();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -1,21 +1,35 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="manage-container">
|
<view class="manage-container">
|
||||||
<view class="group-list">
|
<view class="group-list">
|
||||||
<view v-for="(item, index) in groups" :key="index" class="group-item">
|
<view v-for="(item, index) in groups" :key="item._id" class="group-item">
|
||||||
<view class="left-action" @click="handleDelete(index)">
|
<view class="left-action" :class="{ disabled: Boolean(item.parentGroupId) || isSort }" @click="handleDelete(item, index)">
|
||||||
<uni-icons type="minus-filled" size="24" color="#ff4d4f"></uni-icons>
|
<uni-icons type="minus-filled" size="24" :color="Boolean(item.parentGroupId) || isSort ? '#ddd' : '#ff4d4f'"></uni-icons>
|
||||||
|
</view>
|
||||||
|
<view class="group-name">
|
||||||
|
<view class="name-row">
|
||||||
|
<text class="name-text">{{ item.groupName }}</text>
|
||||||
|
<text v-if="item.parentGroupId" class="corp-tag">机构</text>
|
||||||
|
</view>
|
||||||
|
<text v-if="item.description" class="desc">{{ item.description }}</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="group-name">{{ item.name }}</view>
|
|
||||||
<view class="right-actions">
|
<view class="right-actions">
|
||||||
<uni-icons type="compose" size="24" color="#5d8aff" class="icon-edit" @click="handleEdit(item, index)"></uni-icons>
|
<uni-icons type="compose" size="24" :color="isSort ? '#ddd' : '#5d8aff'" class="icon-edit" @click="handleEdit(item, index)"></uni-icons>
|
||||||
<uni-icons type="bars" size="24" color="#5d8aff" class="icon-drag"></uni-icons>
|
<template v-if="isSort">
|
||||||
|
<uni-icons type="arrowup" size="20" color="#5d8aff" class="icon-sort" @click="moveUp(index)"></uni-icons>
|
||||||
|
<uni-icons type="arrowdown" size="20" color="#5d8aff" class="icon-sort" @click="moveDown(index)"></uni-icons>
|
||||||
|
</template>
|
||||||
|
<uni-icons v-else type="bars" size="24" color="#5d8aff" class="icon-drag" @click="enterSort"></uni-icons>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- Bottom Button -->
|
<!-- Bottom Button -->
|
||||||
<view class="footer">
|
<view class="footer">
|
||||||
<button class="add-btn" @click="handleAdd">添加新分组</button>
|
<template v-if="isSort">
|
||||||
|
<button class="add-btn plain" @click="cancelSort">取消</button>
|
||||||
|
<button class="add-btn" @click="saveSort">保存</button>
|
||||||
|
</template>
|
||||||
|
<button v-else class="add-btn" @click="handleAdd">添加新分组</button>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- Dialog -->
|
<!-- Dialog -->
|
||||||
@ -36,13 +50,90 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
|
import { onLoad } from '@dcloudio/uni-app';
|
||||||
|
import { storeToRefs } from 'pinia';
|
||||||
|
import api from '@/utils/api';
|
||||||
|
import useAccountStore from '@/store/account';
|
||||||
|
import { hideLoading, loading, toast } from '@/utils/widget';
|
||||||
|
|
||||||
// State
|
// State
|
||||||
const groups = ref([
|
const groups = ref([]);
|
||||||
{ id: 1, name: '糖尿病' },
|
const originalGroups = ref([]);
|
||||||
{ id: 2, name: '高血压' },
|
const isSort = ref(false);
|
||||||
{ id: 3, name: '高血脂' }
|
|
||||||
]);
|
const GROUPS_RELOAD_KEY = 'ykt_case_groups_need_reload';
|
||||||
|
const CURRENT_TEAM_STORAGE_KEY = 'ykt_case_current_team';
|
||||||
|
|
||||||
|
const accountStore = useAccountStore();
|
||||||
|
const { account, doctorInfo } = storeToRefs(accountStore);
|
||||||
|
const { getDoctorInfo } = accountStore;
|
||||||
|
|
||||||
|
function getUserId() {
|
||||||
|
const d = doctorInfo.value || {};
|
||||||
|
const a = account.value || {};
|
||||||
|
return String(d.userid || d.userId || d.corpUserId || a.userid || a.userId || '') || '';
|
||||||
|
}
|
||||||
|
|
||||||
|
function getCorpId() {
|
||||||
|
const d = doctorInfo.value || {};
|
||||||
|
const a = account.value || {};
|
||||||
|
const team = uni.getStorageSync(CURRENT_TEAM_STORAGE_KEY) || {};
|
||||||
|
return String(d.corpId || a.corpId || team.corpId || '') || '';
|
||||||
|
}
|
||||||
|
|
||||||
|
function getTeamId() {
|
||||||
|
const team = uni.getStorageSync(CURRENT_TEAM_STORAGE_KEY) || {};
|
||||||
|
return String(team.teamId || '') || '';
|
||||||
|
}
|
||||||
|
|
||||||
|
function sortGroupList(list) {
|
||||||
|
const { orderList, corpList, restList } = (Array.isArray(list) ? list : []).reduce(
|
||||||
|
(p, c) => {
|
||||||
|
if (typeof c?.sortOrder === 'number') p.orderList.push(c);
|
||||||
|
else if (c?.parentGroupId) p.corpList.push(c);
|
||||||
|
else p.restList.push(c);
|
||||||
|
return p;
|
||||||
|
},
|
||||||
|
{ orderList: [], corpList: [], restList: [] }
|
||||||
|
);
|
||||||
|
orderList.sort((a, b) => a.sortOrder - b.sortOrder);
|
||||||
|
return [...orderList, ...corpList, ...restList];
|
||||||
|
}
|
||||||
|
|
||||||
|
async function ensureDoctor() {
|
||||||
|
if (doctorInfo.value) return;
|
||||||
|
if (!account.value?.openid) return;
|
||||||
|
try {
|
||||||
|
await getDoctorInfo();
|
||||||
|
} catch (e) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function loadGroups() {
|
||||||
|
await ensureDoctor();
|
||||||
|
const corpId = getCorpId();
|
||||||
|
const teamId = getTeamId();
|
||||||
|
if (!corpId || !teamId) return;
|
||||||
|
|
||||||
|
loading('加载中...');
|
||||||
|
try {
|
||||||
|
const projection = { _id: 1, groupName: 1, parentGroupId: 1, description: 1, sortOrder: 1 };
|
||||||
|
const res = await api('getGroups', { corpId, teamId, page: 1, pageSize: 1000, projection, countGroupMember: false });
|
||||||
|
if (!res?.success) {
|
||||||
|
toast(res?.message || '获取分组失败');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const list = Array.isArray(res.data) ? res.data : Array.isArray(res.data?.data) ? res.data.data : [];
|
||||||
|
const sorted = sortGroupList(list);
|
||||||
|
groups.value = sorted.map((i) => ({ ...i }));
|
||||||
|
originalGroups.value = sorted.map((i) => ({ ...i }));
|
||||||
|
} catch (e) {
|
||||||
|
toast('获取分组失败');
|
||||||
|
} finally {
|
||||||
|
hideLoading();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const showDialog = ref(false);
|
const showDialog = ref(false);
|
||||||
const dialogMode = ref('add'); // 'add' or 'edit'
|
const dialogMode = ref('add'); // 'add' or 'edit'
|
||||||
@ -53,6 +144,7 @@ const dialogTitle = ref('添加新分组');
|
|||||||
|
|
||||||
// Methods
|
// Methods
|
||||||
const handleAdd = () => {
|
const handleAdd = () => {
|
||||||
|
if (isSort.value) return;
|
||||||
dialogMode.value = 'add';
|
dialogMode.value = 'add';
|
||||||
dialogTitle.value = '添加新分组';
|
dialogTitle.value = '添加新分组';
|
||||||
inputValue.value = '';
|
inputValue.value = '';
|
||||||
@ -60,22 +152,42 @@ const handleAdd = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleEdit = (item, index) => {
|
const handleEdit = (item, index) => {
|
||||||
|
if (isSort.value) return;
|
||||||
dialogMode.value = 'edit';
|
dialogMode.value = 'edit';
|
||||||
dialogTitle.value = '编辑分组名称';
|
dialogTitle.value = '编辑分组名称';
|
||||||
inputValue.value = item.name;
|
inputValue.value = item.groupName || '';
|
||||||
editingIndex.value = index;
|
editingIndex.value = index;
|
||||||
showDialog.value = true;
|
showDialog.value = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleDelete = (index) => {
|
const handleDelete = (item, index) => {
|
||||||
|
if (isSort.value) return;
|
||||||
|
if (item?.parentGroupId) return;
|
||||||
uni.showModal({
|
uni.showModal({
|
||||||
title: '提示',
|
title: '提示',
|
||||||
content: '确定要删除该分组吗?',
|
content: '确定要删除该分组吗?',
|
||||||
success: (res) => {
|
success: async (res) => {
|
||||||
if (res.confirm) {
|
if (!res.confirm) return;
|
||||||
groups.value.splice(index, 1);
|
const corpId = getCorpId();
|
||||||
|
const teamId = getTeamId();
|
||||||
|
if (!corpId || !teamId) {
|
||||||
|
toast('缺少团队信息');
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
loading('');
|
||||||
|
try {
|
||||||
|
const delRes = await api('removeGroup', { corpId, id: item._id, teamId, groupType: 'team' });
|
||||||
|
if (!delRes?.success) {
|
||||||
|
toast(delRes?.message || '删除失败');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
toast('删除成功');
|
||||||
|
uni.setStorageSync(GROUPS_RELOAD_KEY, 1);
|
||||||
|
await loadGroups();
|
||||||
|
} finally {
|
||||||
|
hideLoading();
|
||||||
|
}
|
||||||
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -83,23 +195,107 @@ const closeDialog = () => {
|
|||||||
showDialog.value = false;
|
showDialog.value = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSave = () => {
|
const handleSave = async () => {
|
||||||
if (!inputValue.value.trim()) {
|
if (!inputValue.value.trim()) {
|
||||||
uni.showToast({ title: '请输入分组名称', icon: 'none' });
|
uni.showToast({ title: '请输入分组名称', icon: 'none' });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dialogMode.value === 'add') {
|
await ensureDoctor();
|
||||||
groups.value.push({
|
const corpId = getCorpId();
|
||||||
id: Date.now(),
|
const teamId = getTeamId();
|
||||||
name: inputValue.value
|
const userId = getUserId();
|
||||||
});
|
if (!corpId || !teamId || !userId) {
|
||||||
} else {
|
toast('缺少用户/团队信息');
|
||||||
groups.value[editingIndex.value].name = inputValue.value;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
closeDialog();
|
loading('保存中...');
|
||||||
|
try {
|
||||||
|
if (dialogMode.value === 'add') {
|
||||||
|
const params = {
|
||||||
|
groupName: inputValue.value.trim(),
|
||||||
|
teamId,
|
||||||
|
groupType: 'team',
|
||||||
|
creator: userId,
|
||||||
|
};
|
||||||
|
const res = await api('createGroup', { corpId, teamId, params });
|
||||||
|
if (!res?.success) {
|
||||||
|
toast(res?.message || '新增失败');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
toast('新增成功');
|
||||||
|
} else {
|
||||||
|
const item = groups.value[editingIndex.value];
|
||||||
|
if (!item?._id) return;
|
||||||
|
const res = await api('updateGroup', { corpId, id: item._id, params: { groupName: inputValue.value.trim() } });
|
||||||
|
if (!res?.success) {
|
||||||
|
toast(res?.message || '修改失败');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
toast('修改成功');
|
||||||
|
}
|
||||||
|
uni.setStorageSync(GROUPS_RELOAD_KEY, 1);
|
||||||
|
closeDialog();
|
||||||
|
await loadGroups();
|
||||||
|
} finally {
|
||||||
|
hideLoading();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function enterSort() {
|
||||||
|
if (!groups.value.length) return;
|
||||||
|
isSort.value = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function cancelSort() {
|
||||||
|
isSort.value = false;
|
||||||
|
groups.value = originalGroups.value.map((i) => ({ ...i }));
|
||||||
|
}
|
||||||
|
|
||||||
|
function moveUp(index) {
|
||||||
|
if (!isSort.value) return;
|
||||||
|
if (index <= 0) return;
|
||||||
|
const next = groups.value.slice();
|
||||||
|
const tmp = next[index - 1];
|
||||||
|
next[index - 1] = next[index];
|
||||||
|
next[index] = tmp;
|
||||||
|
groups.value = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
function moveDown(index) {
|
||||||
|
if (!isSort.value) return;
|
||||||
|
if (index >= groups.value.length - 1) return;
|
||||||
|
const next = groups.value.slice();
|
||||||
|
const tmp = next[index + 1];
|
||||||
|
next[index + 1] = next[index];
|
||||||
|
next[index] = tmp;
|
||||||
|
groups.value = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function saveSort() {
|
||||||
|
const teamId = getTeamId();
|
||||||
|
if (!teamId) return;
|
||||||
|
loading('');
|
||||||
|
try {
|
||||||
|
const data = groups.value.map((i, idx) => ({ _id: i._id, sortOrder: idx }));
|
||||||
|
const res = await api('sortGroups', { teamId, data });
|
||||||
|
if (!res?.success) {
|
||||||
|
toast(res?.message || '保存失败');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
toast('保存成功');
|
||||||
|
uni.setStorageSync(GROUPS_RELOAD_KEY, 1);
|
||||||
|
isSort.value = false;
|
||||||
|
await loadGroups();
|
||||||
|
} finally {
|
||||||
|
hideLoading();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onLoad(() => {
|
||||||
|
loadGroups();
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
@ -121,12 +317,33 @@ const handleSave = () => {
|
|||||||
|
|
||||||
.left-action {
|
.left-action {
|
||||||
margin-right: 15px;
|
margin-right: 15px;
|
||||||
|
&.disabled {
|
||||||
|
opacity: 0.6;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.group-name {
|
.group-name {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
color: #333;
|
color: #333;
|
||||||
|
.name-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
.corp-tag {
|
||||||
|
font-size: 12px;
|
||||||
|
padding: 2px 6px;
|
||||||
|
border-radius: 10px;
|
||||||
|
background: #f0f0f0;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
.desc {
|
||||||
|
display: block;
|
||||||
|
margin-top: 4px;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.right-actions {
|
.right-actions {
|
||||||
@ -137,6 +354,9 @@ const handleSave = () => {
|
|||||||
.icon-edit, .icon-drag {
|
.icon-edit, .icon-drag {
|
||||||
padding: 5px; // Increase tap area
|
padding: 5px; // Increase tap area
|
||||||
}
|
}
|
||||||
|
.icon-sort {
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -161,6 +381,12 @@ const handleSave = () => {
|
|||||||
&::after {
|
&::after {
|
||||||
border: none;
|
border: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.plain {
|
||||||
|
background-color: #fff;
|
||||||
|
color: #666;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -21,6 +21,13 @@ const urlsConfig = {
|
|||||||
member: {
|
member: {
|
||||||
addCustomer: 'add',
|
addCustomer: 'add',
|
||||||
updateCustomer: 'update',
|
updateCustomer: 'update',
|
||||||
|
transferCustomers: 'transferCustomers',
|
||||||
|
getGroups: 'getGroups',
|
||||||
|
createGroup: 'createGroup',
|
||||||
|
updateGroup: 'updateGroup',
|
||||||
|
removeGroup: 'removeGroup',
|
||||||
|
sortGroups: 'sortGroups',
|
||||||
|
addGroupIdForMember: 'addGroupIdForMember',
|
||||||
bindMiniAppArchive: "bindMiniAppArchive",
|
bindMiniAppArchive: "bindMiniAppArchive",
|
||||||
getCustomerByCustomerId: 'getCustomerByCustomerId',
|
getCustomerByCustomerId: 'getCustomerByCustomerId',
|
||||||
getMiniAppCustomers: 'getMiniAppCustomers',
|
getMiniAppCustomers: 'getMiniAppCustomers',
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user