Commit f801d1bc138d1b3eb41ece9decdd00563f319247

Authored by xp.Huang
2 parents 55a68bee 89ba4c36

Merge branch 'perf/three-editor/10-23/2024' into 'main_dev'

feat(src/packages): 3d编辑器 新增批量操作(删除,发布,取消发布)

See merge request yunteng/thingskit-view!297
... ... @@ -112,7 +112,7 @@ export const uploadFile = async (file: FormData, mode: ErrorMessageMode = 'modal
112 112 export function threeJsDeleteApi(ids: string[], mode: ErrorMessageMode = 'modal') {
113 113 return defHttp.delete(
114 114 {
115   - url: Api.THREE_JS_MODEL +'?ids=' + ids,
  115 + url: Api.THREE_JS_MODEL + '?ids=' + ids
116 116 },
117 117 {
118 118 errorMessageMode: mode
... ... @@ -145,7 +145,7 @@ export const putThreeJsModelRelease = (params: { id: string | number; state: num
145 145 */
146 146 export const updateThreeJsModel = (params: { id: string; name: string }) => {
147 147 return defHttp.put({
148   - url: Api.THREE_JS_MODEL +'/' + params['id'] + '/' + params['name'],
  148 + url: Api.THREE_JS_MODEL + '/' + params['id'] + '/' + params['name'],
149 149 params
150 150 })
151 151 }
... ... @@ -155,7 +155,7 @@ export const updateThreeJsModel = (params: { id: string; name: string }) => {
155 155 */
156 156 export function saveOrUpdateThreeJsModel(params: Recordable) {
157 157 return defHttp.post({
158   - url: Api.THREE_JS_MODEL +'/' + params['id'],
  158 + url: Api.THREE_JS_MODEL + '/' + params['id'],
159 159 data: params['data']
160 160 })
161 161 }
... ... @@ -165,7 +165,16 @@ export function saveOrUpdateThreeJsModel(params: Recordable) {
165 165 */
166 166 export function getThreeJsModel(id: string) {
167 167 return defHttp.get({
168   - url: Api.THREE_JS_MODEL +'/' + id,
  168 + url: Api.THREE_JS_MODEL + '/' + id
169 169 })
170 170 }
171 171
  172 +/**
  173 + * @description: 3D模型 批量发布/取消发布 api
  174 + */
  175 +export function putReleaseThreeJsModel(state: number, ids: string[]) {
  176 + return defHttp.put({
  177 + url: Api.THREE_JS_MODEL + '/publish/' + state,
  178 + data: ids
  179 + })
  180 +}
... ...
1 1 <template>
2 2 <div v-if="cardData" class="go-items-list-card">
3   - <n-card :hoverable="false" size="small">
  3 + <n-card hoverable size="small">
  4 + <template v-if="operationKey">
  5 + <n-checkbox v-model:checked="cardData.checkedValue"> </n-checkbox>
  6 + </template>
4 7 <div class="list-content">
5 8 <div class="list-content-img">
6 9 <n-image
... ... @@ -98,7 +101,8 @@ const { EllipsisHorizontalCircleSharpIcon, TrashIcon, HammerIcon, SendIcon } = i
98 101 const emit = defineEmits(['delete', 'resize', 'edit', 'release', 'inputUpdateCard'])
99 102
100 103 const props = defineProps({
101   - cardData: Object as PropType<ChartType>
  104 + cardData: Object as PropType<ChartType>,
  105 + operationKey: String,
102 106 })
103 107
104 108 // 处理url获取
... ... @@ -197,9 +201,9 @@ $contentHeight: 180px;
197 201 border-radius: $--border-radius-base;
198 202 border: 1px solid rgba(0, 0, 0, 0);
199 203 @extend .go-transition;
200   - &:hover {
201   - @include hover-border-color('hover-border-color');
202   - }
  204 + // &:hover {
  205 + // @include hover-border-color('hover-border-color');
  206 + // }
203 207 .list-content {
204 208 cursor: pointer;
205 209 border-radius: $--border-radius-base;
... ...
... ... @@ -44,7 +44,8 @@ export const useDataListInit = (formValue: { name: string; state: string | null
44 44 pagination.count = total
45 45 list.value = items.map(item => ({
46 46 ...item,
47   - threeModelFilePath: `${threeFilePath}${VITE_GLOB_API_URL}${VITE_GLOB_API_URL_PREFIX}/3d_component/json/${item.id}/scene.json`
  47 + threeModelFilePath: `${threeFilePath}${VITE_GLOB_API_URL}${VITE_GLOB_API_URL_PREFIX}/3d_component/json/${item.id}/scene.json`,
  48 + checkedValue: false
48 49 }))
49 50 setTimeout(() => {
50 51 loading.value = false
... ...
... ... @@ -40,7 +40,18 @@
40 40 <div style="display: flex; flex-direction: row-reverse">
41 41 <n-space>
42 42 <n-button type="primary" @click="handleOpenThreeEditor"> 新增 </n-button>
43   - <!-- <n-button disabled> 批量操作 </n-button> -->
  43 + <n-button v-if="list.length" @click="handleSelectAll" type="info">
  44 + {{ selectAllTextFlag ? '全选' : '反选' }}
  45 + </n-button>
  46 + <n-dropdown
  47 + v-if="list.length"
  48 + :disabled="isBulkOperationFlag"
  49 + trigger="hover"
  50 + :options="operationOptions"
  51 + @select="handleOperationSelect"
  52 + >
  53 + <n-button :disabled="isBulkOperationFlag"> 批量操作 </n-button>
  54 + </n-dropdown>
44 55 </n-space>
45 56 </div>
46 57 <n-grid style="margin-top: 16px" :x-gap="20" :y-gap="20" cols="2 s:2 m:3 l:4 xl:4 xxl:4" responsive="screen">
... ... @@ -48,6 +59,7 @@
48 59 <div style="display: none">{{ index }}</div>
49 60 <project-items-card
50 61 :cardData="item"
  62 + :operationKey="operationKey"
51 63 @resize="resizeHandle"
52 64 @delete="deleteHandle(item)"
53 65 @release="releaseHandle(item)"
... ... @@ -89,6 +101,10 @@ import { ref } from 'vue'
89 101 import type { FormInst } from 'naive-ui'
90 102 import { icon } from '@/plugins'
91 103 import { getUUID } from '@/utils/utils'
  104 +import { threeJsDeleteApi, putReleaseThreeJsModel } from '@/api/external/contentSave/content'
  105 +import { ChartType } from '../..'
  106 +import { DialogEnum } from '@/enums/pluginEnum'
  107 +import { goDialog } from '@/utils'
92 108
93 109 const { SearchIcon, ReloadSearch } = icon.ionicons5
94 110
... ... @@ -114,6 +130,88 @@ const statusOptions = ref([
114 130 }
115 131 ])
116 132
  133 +const operationKey = ref('')
  134 +
  135 +const operationOptions = [
  136 + {
  137 + label: '批量删除',
  138 + key: 'Bulk delete'
  139 + },
  140 + {
  141 + label: '批量发布',
  142 + key: 'Bulk release'
  143 + },
  144 + {
  145 + label: '批量取消发布',
  146 + key: 'Bulk un release'
  147 + }
  148 +]
  149 +
  150 +const resetSelect = (list: ChartType[], flag: boolean) => {
  151 + list.forEach(item => {
  152 + item.checkedValue = flag
  153 + })
  154 +}
  155 +
  156 +const releaseGoDialog = (message: string, state: number, messageText: string) => {
  157 + goDialog({
  158 + type: DialogEnum.DELETE,
  159 + promise: true,
  160 + message,
  161 + // eslint-disable-next-line @typescript-eslint/no-empty-function
  162 + onPositiveCallback: () => {},
  163 + promiseResCallback: async () => {
  164 + console.log(list.value)
  165 + // eslint-disable-next-line no-case-declarations
  166 + const bulkDeleteIds = list.value
  167 + ?.filter((item: ChartType) => item.checkedValue)
  168 + ?.map((item: ChartType) => item.id)
  169 + await putReleaseThreeJsModel(state, bulkDeleteIds as unknown as string[])
  170 + window['$message'].success(window['$t'](messageText))
  171 + handleSearchClick()
  172 + isBulkOperationFlag.value = true
  173 + selectAllTextFlag.value = false
  174 + operationKey.value = ''
  175 + resetSelect(list.value, false)
  176 + }
  177 + })
  178 +}
  179 +
  180 +const handleOperationSelect = async (key: string) => {
  181 + operationKey.value = key
  182 + switch (key) {
  183 + case 'Bulk delete':
  184 + goDialog({
  185 + type: DialogEnum.DELETE,
  186 + promise: true,
  187 + message: '是否批量删除所选数据?',
  188 + // eslint-disable-next-line @typescript-eslint/no-empty-function
  189 + onPositiveCallback: () => {},
  190 + promiseResCallback: async () => {
  191 + console.log(list.value)
  192 + // eslint-disable-next-line no-case-declarations
  193 + const bulkDeleteIds = list.value
  194 + ?.filter((item: ChartType) => item.checkedValue)
  195 + ?.map((item: ChartType) => item.id)
  196 + await threeJsDeleteApi([bulkDeleteIds] as unknown as string[])
  197 + window['$message'].success(window['$t']('common.deleteSuccessText'))
  198 + handleSearchClick()
  199 + isBulkOperationFlag.value = true
  200 + selectAllTextFlag.value = false
  201 + operationKey.value = ''
  202 + resetSelect(list.value, false)
  203 + }
  204 + })
  205 + break
  206 + case 'Bulk release':
  207 + releaseGoDialog('是否批量发布所选数据?', 1, 'common.releaseSuccessText')
  208 + break
  209 + case 'Bulk un release':
  210 + releaseGoDialog('是否批量取消发布所选数据?', 0, 'common.cancelReleaseSuccessText')
  211 + break
  212 + }
  213 +}
  214 +
117 215 const {
118 216 loading,
119 217 pagination,
... ... @@ -126,6 +224,23 @@ const {
126 224 handleSearchClick
127 225 } = useDataListInit(formValue.value)
128 226
  227 +const isBulkOperationFlag = ref(true)
  228 +
  229 +const selectAllTextFlag = ref(true)
  230 +
  231 +const handleSelectAll = () => {
  232 + selectAllTextFlag.value = !selectAllTextFlag.value
  233 + if (!selectAllTextFlag.value) {
  234 + resetSelect(list.value, true)
  235 + isBulkOperationFlag.value = false
  236 + operationKey.value = 'Bulk delete'
  237 + } else {
  238 + resetSelect(list.value, false)
  239 + isBulkOperationFlag.value = true
  240 + operationKey.value = ''
  241 + }
  242 +}
  243 +
129 244 const handleResetClick = () => {
130 245 formValue.value.name = ''
131 246 formValue.value.state = null
... ... @@ -151,7 +266,7 @@ $contentHeight: 250px;
151 266 }
152 267 .list-pagination {
153 268 position: fixed;
154   - bottom: 30px;
  269 + bottom: 10px;
155 270 right: 30px;
156 271 }
157 272 }
... ...
... ... @@ -9,6 +9,7 @@ export type ChartType = {
9 9 name?: string
10 10 threeModelFilePath?: string
11 11 imageUrl?: string | undefined
  12 + checkedValue?: boolean
12 13 }
13 14
14 15 export type ChartList = ChartType[]
... ...