feat: add expire time data for import/export handle
This commit is contained in:
parent
3fe8767c44
commit
f597002378
|
@ -2056,7 +2056,7 @@ func (b *browserService) DeleteKeys(server string, db int, ks []any, serialNo st
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExportKey export keys
|
// ExportKey export keys
|
||||||
func (b *browserService) ExportKey(server string, db int, ks []any, path string) (resp types.JSResp) {
|
func (b *browserService) ExportKey(server string, db int, ks []any, path string, includeExpire bool) (resp types.JSResp) {
|
||||||
// connect a new connection to export keys
|
// connect a new connection to export keys
|
||||||
conf := Connection().getConnection(server)
|
conf := Connection().getConnection(server)
|
||||||
if conf == nil {
|
if conf == nil {
|
||||||
|
@ -2111,7 +2111,15 @@ func (b *browserService) ExportKey(server string, db int, ks []any, path string)
|
||||||
canceled = true
|
canceled = true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if err = writer.Write([]string{hex.EncodeToString([]byte(key)), hex.EncodeToString(content)}); err != nil {
|
record := []string{hex.EncodeToString([]byte(key)), hex.EncodeToString(content)}
|
||||||
|
if includeExpire {
|
||||||
|
if dur, ttlErr := client.PTTL(ctx, key).Result(); ttlErr == nil && dur > 0 {
|
||||||
|
record = append(record, strconv.FormatInt(time.Now().Add(dur).UnixMilli(), 10))
|
||||||
|
} else {
|
||||||
|
record = append(record, "-1")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err = writer.Write(record); err != nil {
|
||||||
failed += 1
|
failed += 1
|
||||||
} else {
|
} else {
|
||||||
exported += 1
|
exported += 1
|
||||||
|
@ -2133,7 +2141,7 @@ func (b *browserService) ExportKey(server string, db int, ks []any, path string)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ImportCSV import data from csv file
|
// ImportCSV import data from csv file
|
||||||
func (b *browserService) ImportCSV(server string, db int, path string, conflict int) (resp types.JSResp) {
|
func (b *browserService) ImportCSV(server string, db int, path string, conflict int, includeExpire bool) (resp types.JSResp) {
|
||||||
// connect a new connection to export keys
|
// connect a new connection to export keys
|
||||||
conf := Connection().getConnection(server)
|
conf := Connection().getConnection(server)
|
||||||
if conf == nil {
|
if conf == nil {
|
||||||
|
@ -2169,7 +2177,7 @@ func (b *browserService) ImportCSV(server string, db int, path string, conflict
|
||||||
var line []string
|
var line []string
|
||||||
var readErr error
|
var readErr error
|
||||||
var key, value []byte
|
var key, value []byte
|
||||||
var ttl int64
|
var ttl time.Duration
|
||||||
var imported, ignored int64
|
var imported, ignored int64
|
||||||
var canceled bool
|
var canceled bool
|
||||||
startTime := time.Now().Add(-10 * time.Second)
|
startTime := time.Now().Add(-10 * time.Second)
|
||||||
|
@ -2192,19 +2200,19 @@ func (b *browserService) ImportCSV(server string, db int, path string, conflict
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// get ttl
|
// get ttl
|
||||||
if len(line) > 2 {
|
if includeExpire && len(line) > 2 {
|
||||||
if ttl, readErr = strconv.ParseInt(line[2], 10, 64); readErr != nil {
|
if expire, ttlErr := strconv.ParseInt(line[2], 10, 64); ttlErr == nil && expire > 0 {
|
||||||
ttl = redis.KeepTTL
|
ttl = time.UnixMilli(expire).Sub(time.Now())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if conflict == 0 {
|
if conflict == 0 {
|
||||||
readErr = client.RestoreReplace(ctx, string(key), time.Duration(ttl), string(value)).Err()
|
readErr = client.RestoreReplace(ctx, string(key), ttl, string(value)).Err()
|
||||||
} else {
|
} else {
|
||||||
keyStr := string(key)
|
keyStr := string(key)
|
||||||
// go-redis may crash when batch calling restore
|
// go-redis may crash when batch calling restore
|
||||||
// use "exists" to filter first
|
// use "exists" to filter first
|
||||||
if n, _ := client.Exists(ctx, keyStr).Result(); n <= 0 {
|
if n, _ := client.Exists(ctx, keyStr).Result(); n <= 0 {
|
||||||
readErr = client.Restore(ctx, keyStr, time.Duration(ttl), string(value)).Err()
|
readErr = client.Restore(ctx, keyStr, ttl, string(value)).Err()
|
||||||
} else {
|
} else {
|
||||||
readErr = errors.New("key existed")
|
readErr = errors.New("key existed")
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,14 @@ const props = defineProps({
|
||||||
|
|
||||||
const emit = defineEmits(['update:value'])
|
const emit = defineEmits(['update:value'])
|
||||||
|
|
||||||
|
const onInput = (val) => {
|
||||||
|
emit('update:value', val)
|
||||||
|
}
|
||||||
|
|
||||||
|
const onClear = () => {
|
||||||
|
emit('update:value', '')
|
||||||
|
}
|
||||||
|
|
||||||
const handleSelectFile = async () => {
|
const handleSelectFile = async () => {
|
||||||
const { success, data } = await SelectFile('', isEmpty(props.ext) ? null : [props.ext])
|
const { success, data } = await SelectFile('', isEmpty(props.ext) ? null : [props.ext])
|
||||||
if (success) {
|
if (success) {
|
||||||
|
@ -24,7 +32,13 @@ const handleSelectFile = async () => {
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<n-input-group>
|
<n-input-group>
|
||||||
<n-input v-model:value="props.value" :disabled="props.disabled" :placeholder="placeholder" clearable />
|
<n-input
|
||||||
|
:disabled="props.disabled"
|
||||||
|
:placeholder="placeholder"
|
||||||
|
:value="props.value"
|
||||||
|
clearable
|
||||||
|
@clear="onClear"
|
||||||
|
@input="onInput" />
|
||||||
<n-button :disabled="props.disabled" :focusable="false" @click="handleSelectFile">...</n-button>
|
<n-button :disabled="props.disabled" :focusable="false" @click="handleSelectFile">...</n-button>
|
||||||
</n-input-group>
|
</n-input-group>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -11,6 +11,10 @@ const props = defineProps({
|
||||||
|
|
||||||
const emit = defineEmits(['update:value'])
|
const emit = defineEmits(['update:value'])
|
||||||
|
|
||||||
|
const onInput = (val) => {
|
||||||
|
emit('update:value', val)
|
||||||
|
}
|
||||||
|
|
||||||
const onClear = () => {
|
const onClear = () => {
|
||||||
emit('update:value', '')
|
emit('update:value', '')
|
||||||
}
|
}
|
||||||
|
@ -29,10 +33,11 @@ const handleSaveFile = async () => {
|
||||||
<template>
|
<template>
|
||||||
<n-input-group>
|
<n-input-group>
|
||||||
<n-input
|
<n-input
|
||||||
v-model:value="props.value"
|
:value="props.value"
|
||||||
:disabled="props.disabled"
|
:disabled="props.disabled"
|
||||||
:placeholder="placeholder"
|
:placeholder="placeholder"
|
||||||
clearable
|
clearable
|
||||||
|
@input="onInput"
|
||||||
@clear="onClear" />
|
@clear="onClear" />
|
||||||
<n-button :disabled="props.disabled" :focusable="false" @click="handleSaveFile">...</n-button>
|
<n-button :disabled="props.disabled" :focusable="false" @click="handleSaveFile">...</n-button>
|
||||||
</n-input-group>
|
</n-input-group>
|
||||||
|
|
|
@ -11,6 +11,7 @@ import dayjs from 'dayjs'
|
||||||
const exportKeyForm = reactive({
|
const exportKeyForm = reactive({
|
||||||
server: '',
|
server: '',
|
||||||
db: 0,
|
db: 0,
|
||||||
|
expire: false,
|
||||||
keys: [],
|
keys: [],
|
||||||
file: '',
|
file: '',
|
||||||
})
|
})
|
||||||
|
@ -24,7 +25,9 @@ watchEffect(() => {
|
||||||
const { server, db, keys } = dialogStore.exportKeyParam
|
const { server, db, keys } = dialogStore.exportKeyParam
|
||||||
exportKeyForm.server = server
|
exportKeyForm.server = server
|
||||||
exportKeyForm.db = db
|
exportKeyForm.db = db
|
||||||
|
exportKeyForm.ttl = false
|
||||||
exportKeyForm.keys = keys
|
exportKeyForm.keys = keys
|
||||||
|
exportKeyForm.file = ''
|
||||||
exporting.value = false
|
exporting.value = false
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -41,8 +44,8 @@ const i18n = useI18n()
|
||||||
const onConfirmExport = async () => {
|
const onConfirmExport = async () => {
|
||||||
try {
|
try {
|
||||||
exporting.value = true
|
exporting.value = true
|
||||||
const { server, db, keys, file } = exportKeyForm
|
const { server, db, keys, file, expire } = exportKeyForm
|
||||||
browserStore.exportKeys(server, db, keys, file).catch((e) => {})
|
browserStore.exportKeys(server, db, keys, file, expire).catch((e) => {})
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
$message.error(e.message)
|
$message.error(e.message)
|
||||||
return
|
return
|
||||||
|
@ -77,6 +80,11 @@ const onClose = () => {
|
||||||
<n-input :autofocus="false" :value="exportKeyForm.db.toString()" readonly />
|
<n-input :autofocus="false" :value="exportKeyForm.db.toString()" readonly />
|
||||||
</n-form-item-gi>
|
</n-form-item-gi>
|
||||||
</n-grid>
|
</n-grid>
|
||||||
|
<n-form-item :label="$t('dialogue.export.export_expire_title')">
|
||||||
|
<n-checkbox v-model:checked="exportKeyForm.expire" :autofocus="false">
|
||||||
|
{{ $t('dialogue.export.export_expire') }}
|
||||||
|
</n-checkbox>
|
||||||
|
</n-form-item>
|
||||||
<n-form-item :label="$t('dialogue.export.save_file')" required>
|
<n-form-item :label="$t('dialogue.export.save_file')" required>
|
||||||
<file-save-input
|
<file-save-input
|
||||||
v-model:value="exportKeyForm.file"
|
v-model:value="exportKeyForm.file"
|
||||||
|
@ -94,12 +102,14 @@ const onClose = () => {
|
||||||
|
|
||||||
<template #action>
|
<template #action>
|
||||||
<div class="flex-item n-dialog__action">
|
<div class="flex-item n-dialog__action">
|
||||||
<n-button :disabled="loading" :focusable="false" @click="onClose">{{ $t('common.cancel') }}</n-button>
|
<n-button :disabled="loading" :focusable="false" @click="onClose">
|
||||||
|
{{ $t('common.cancel') }}
|
||||||
|
</n-button>
|
||||||
<n-button
|
<n-button
|
||||||
:disabled="!exportEnable"
|
:disabled="!exportEnable"
|
||||||
:focusable="false"
|
:focusable="false"
|
||||||
:loading="loading"
|
:loading="loading"
|
||||||
type="error"
|
type="primary"
|
||||||
@click="onConfirmExport">
|
@click="onConfirmExport">
|
||||||
{{ $t('dialogue.export.export') }}
|
{{ $t('dialogue.export.export') }}
|
||||||
</n-button>
|
</n-button>
|
||||||
|
|
|
@ -9,6 +9,7 @@ import FileOpenInput from '@/components/common/FileOpenInput.vue'
|
||||||
const importKeyForm = reactive({
|
const importKeyForm = reactive({
|
||||||
server: '',
|
server: '',
|
||||||
db: 0,
|
db: 0,
|
||||||
|
expire: true,
|
||||||
file: '',
|
file: '',
|
||||||
type: 0,
|
type: 0,
|
||||||
conflict: 0,
|
conflict: 0,
|
||||||
|
@ -23,6 +24,7 @@ watchEffect(() => {
|
||||||
const { server, db } = dialogStore.importKeyParam
|
const { server, db } = dialogStore.importKeyParam
|
||||||
importKeyForm.server = server
|
importKeyForm.server = server
|
||||||
importKeyForm.db = db
|
importKeyForm.db = db
|
||||||
|
importKeyForm.expire = true
|
||||||
importKeyForm.file = ''
|
importKeyForm.file = ''
|
||||||
importKeyForm.type = 0
|
importKeyForm.type = 0
|
||||||
importKeyForm.conflict = 0
|
importKeyForm.conflict = 0
|
||||||
|
@ -49,8 +51,8 @@ const importEnable = computed(() => {
|
||||||
const onConfirmImport = async () => {
|
const onConfirmImport = async () => {
|
||||||
try {
|
try {
|
||||||
importing.value = true
|
importing.value = true
|
||||||
const { server, db, file, conflict } = importKeyForm
|
const { server, db, file, conflict, expire } = importKeyForm
|
||||||
browserStore.importKeysFromCSVFile(server, db, file, conflict).catch((e) => {})
|
browserStore.importKeysFromCSVFile(server, db, file, conflict, expire).catch((e) => {})
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
$message.error(e.message)
|
$message.error(e.message)
|
||||||
return
|
return
|
||||||
|
@ -91,6 +93,11 @@ const onClose = () => {
|
||||||
:placeholder="$t('dialogue.import.open_csv_file_tip')"
|
:placeholder="$t('dialogue.import.open_csv_file_tip')"
|
||||||
ext="csv" />
|
ext="csv" />
|
||||||
</n-form-item>
|
</n-form-item>
|
||||||
|
<n-form-item :label="$t('dialogue.import.import_expire_title')">
|
||||||
|
<n-checkbox v-model:checked="importKeyForm.expire" :autofocus="false">
|
||||||
|
{{ $t('dialogue.import.import_expire') }}
|
||||||
|
</n-checkbox>
|
||||||
|
</n-form-item>
|
||||||
<n-form-item :label="$t('dialogue.import.conflict_handle')">
|
<n-form-item :label="$t('dialogue.import.conflict_handle')">
|
||||||
<n-radio-group v-model:value="importKeyForm.conflict">
|
<n-radio-group v-model:value="importKeyForm.conflict">
|
||||||
<n-radio-button
|
<n-radio-button
|
||||||
|
@ -110,7 +117,7 @@ const onClose = () => {
|
||||||
:disabled="!importEnable"
|
:disabled="!importEnable"
|
||||||
:focusable="false"
|
:focusable="false"
|
||||||
:loading="loading"
|
:loading="loading"
|
||||||
type="error"
|
type="primary"
|
||||||
@click="onConfirmImport">
|
@click="onConfirmImport">
|
||||||
{{ $t('dialogue.export.export') }}
|
{{ $t('dialogue.export.export') }}
|
||||||
</n-button>
|
</n-button>
|
||||||
|
|
|
@ -11,19 +11,19 @@ const props = defineProps({
|
||||||
<svg fill="none" viewBox="0 0 48 48" xmlns="http://www.w3.org/2000/svg">
|
<svg fill="none" viewBox="0 0 48 48" xmlns="http://www.w3.org/2000/svg">
|
||||||
<path
|
<path
|
||||||
:stroke-width="props.strokeWidth"
|
:stroke-width="props.strokeWidth"
|
||||||
d="M6 24.0083V42H42V24"
|
d="M6 24V42H42V24"
|
||||||
stroke="currentColor"
|
stroke="currentColor"
|
||||||
stroke-linecap="round"
|
stroke-linecap="round"
|
||||||
stroke-linejoin="round" />
|
stroke-linejoin="round" />
|
||||||
<path
|
<path
|
||||||
:stroke-width="props.strokeWidth"
|
:stroke-width="props.strokeWidth"
|
||||||
d="M33 23L24 32L15 23"
|
d="M33 15L24 6L15 15"
|
||||||
stroke="currentColor"
|
stroke="currentColor"
|
||||||
stroke-linecap="round"
|
stroke-linecap="round"
|
||||||
stroke-linejoin="round" />
|
stroke-linejoin="round" />
|
||||||
<path
|
<path
|
||||||
:stroke-width="props.strokeWidth"
|
:stroke-width="props.strokeWidth"
|
||||||
d="M23.9917 6V32"
|
d="M24 6V32"
|
||||||
stroke="currentColor"
|
stroke="currentColor"
|
||||||
stroke-linecap="round"
|
stroke-linecap="round"
|
||||||
stroke-linejoin="round" />
|
stroke-linejoin="round" />
|
||||||
|
|
|
@ -11,19 +11,19 @@ const props = defineProps({
|
||||||
<svg fill="none" viewBox="0 0 48 48" xmlns="http://www.w3.org/2000/svg">
|
<svg fill="none" viewBox="0 0 48 48" xmlns="http://www.w3.org/2000/svg">
|
||||||
<path
|
<path
|
||||||
:stroke-width="props.strokeWidth"
|
:stroke-width="props.strokeWidth"
|
||||||
d="M6 24V42H42V24"
|
d="M6 24.0083V42H42V24"
|
||||||
stroke="currentColor"
|
stroke="currentColor"
|
||||||
stroke-linecap="round"
|
stroke-linecap="round"
|
||||||
stroke-linejoin="round" />
|
stroke-linejoin="round" />
|
||||||
<path
|
<path
|
||||||
:stroke-width="props.strokeWidth"
|
:stroke-width="props.strokeWidth"
|
||||||
d="M33 15L24 6L15 15"
|
d="M33 23L24 32L15 23"
|
||||||
stroke="currentColor"
|
stroke="currentColor"
|
||||||
stroke-linecap="round"
|
stroke-linecap="round"
|
||||||
stroke-linejoin="round" />
|
stroke-linejoin="round" />
|
||||||
<path
|
<path
|
||||||
:stroke-width="props.strokeWidth"
|
:stroke-width="props.strokeWidth"
|
||||||
d="M24 6V32"
|
d="M23.9917 6V32"
|
||||||
stroke="currentColor"
|
stroke="currentColor"
|
||||||
stroke-linecap="round"
|
stroke-linecap="round"
|
||||||
stroke-linejoin="round" />
|
stroke-linejoin="round" />
|
||||||
|
|
|
@ -66,6 +66,7 @@ const dbSelectOptions = computed(() => {
|
||||||
const moreOptions = computed(() => {
|
const moreOptions = computed(() => {
|
||||||
return [
|
return [
|
||||||
{ key: 'import', label: i18n.t('interface.import_key'), icon: render.renderIcon(Import, { strokeWidth: 3.5 }) },
|
{ key: 'import', label: i18n.t('interface.import_key'), icon: render.renderIcon(Import, { strokeWidth: 3.5 }) },
|
||||||
|
{ key: 'divider', type: 'divider' },
|
||||||
{ key: 'flush', label: i18n.t('interface.flush_db'), icon: render.renderIcon(Delete, { strokeWidth: 3.5 }) },
|
{ key: 'flush', label: i18n.t('interface.flush_db'), icon: render.renderIcon(Delete, { strokeWidth: 3.5 }) },
|
||||||
{
|
{
|
||||||
key: 'disconnect',
|
key: 'disconnect',
|
||||||
|
|
|
@ -282,6 +282,8 @@
|
||||||
},
|
},
|
||||||
"import": {
|
"import": {
|
||||||
"name": "Import Data",
|
"name": "Import Data",
|
||||||
|
"export_expire_title": "Expiration",
|
||||||
|
"export_expire": "Export Expiration Time",
|
||||||
"import": "Import",
|
"import": "Import",
|
||||||
"open_csv_file": "Import File",
|
"open_csv_file": "Import File",
|
||||||
"open_csv_file_tip": "Select the file for import",
|
"open_csv_file_tip": "Select the file for import",
|
||||||
|
@ -296,6 +298,8 @@
|
||||||
},
|
},
|
||||||
"upgrade": {
|
"upgrade": {
|
||||||
"title": "New Version Available",
|
"title": "New Version Available",
|
||||||
|
"import_expire_title": "Expiration",
|
||||||
|
"import_expire": "Try Import Expiration Time",
|
||||||
"new_version_tip": "A new version({ver}) is available. Download now?",
|
"new_version_tip": "A new version({ver}) is available. Download now?",
|
||||||
"no_update": "You're update to date",
|
"no_update": "You're update to date",
|
||||||
"download_now": "Download",
|
"download_now": "Download",
|
||||||
|
|
|
@ -274,6 +274,8 @@
|
||||||
},
|
},
|
||||||
"export": {
|
"export": {
|
||||||
"name": "导出数据",
|
"name": "导出数据",
|
||||||
|
"export_expire_title": "过期时间",
|
||||||
|
"export_expire": "同时导出过期时间",
|
||||||
"export": "确认导出",
|
"export": "确认导出",
|
||||||
"save_file": "导出路径",
|
"save_file": "导出路径",
|
||||||
"save_file_tip": "选择导出文件保存路径",
|
"save_file_tip": "选择导出文件保存路径",
|
||||||
|
@ -282,6 +284,8 @@
|
||||||
},
|
},
|
||||||
"import": {
|
"import": {
|
||||||
"name": "导入数据",
|
"name": "导入数据",
|
||||||
|
"import_expire_title": "过期时间",
|
||||||
|
"import_expire": "尝试同时导入过期时间",
|
||||||
"import": "确认导入",
|
"import": "确认导入",
|
||||||
"open_csv_file": "导入文件路径",
|
"open_csv_file": "导入文件路径",
|
||||||
"open_csv_file_tip": "选择需要导入的文件",
|
"open_csv_file_tip": "选择需要导入的文件",
|
||||||
|
|
|
@ -1606,9 +1606,10 @@ const useBrowserStore = defineStore('browser', {
|
||||||
* @param {number} db
|
* @param {number} db
|
||||||
* @param {string[]|number[][]} keys
|
* @param {string[]|number[][]} keys
|
||||||
* @param {string} path
|
* @param {string} path
|
||||||
|
* @param {boolean} [expire]
|
||||||
* @returns {Promise<void>}
|
* @returns {Promise<void>}
|
||||||
*/
|
*/
|
||||||
async exportKeys(server, db, keys, path) {
|
async exportKeys(server, db, keys, path, expire) {
|
||||||
const msgRef = $message.loading('', { duration: 0, closable: true })
|
const msgRef = $message.loading('', { duration: 0, closable: true })
|
||||||
let exported = 0
|
let exported = 0
|
||||||
let failCount = 0
|
let failCount = 0
|
||||||
|
@ -1626,7 +1627,7 @@ const useBrowserStore = defineStore('browser', {
|
||||||
msgRef.onClose = () => {
|
msgRef.onClose = () => {
|
||||||
EventsEmit('export:stop:' + path)
|
EventsEmit('export:stop:' + path)
|
||||||
}
|
}
|
||||||
const { data, success, msg } = await ExportKey(server, db, keys, path)
|
const { data, success, msg } = await ExportKey(server, db, keys, path, expire)
|
||||||
if (success) {
|
if (success) {
|
||||||
canceled = get(data, 'canceled', false)
|
canceled = get(data, 'canceled', false)
|
||||||
exported = get(data, 'exported', 0)
|
exported = get(data, 'exported', 0)
|
||||||
|
@ -1659,10 +1660,11 @@ const useBrowserStore = defineStore('browser', {
|
||||||
* @param {string} server
|
* @param {string} server
|
||||||
* @param {number} db
|
* @param {number} db
|
||||||
* @param {string} path
|
* @param {string} path
|
||||||
* @param {int} conflict
|
* @param {number} conflict
|
||||||
|
* @param {boolean} [expire]
|
||||||
* @return {Promise<void>}
|
* @return {Promise<void>}
|
||||||
*/
|
*/
|
||||||
async importKeysFromCSVFile(server, db, path, conflict) {
|
async importKeysFromCSVFile(server, db, path, conflict, expire) {
|
||||||
const msgRef = $message.loading('', { duration: 0, closable: true })
|
const msgRef = $message.loading('', { duration: 0, closable: true })
|
||||||
let imported = 0
|
let imported = 0
|
||||||
let ignored = 0
|
let ignored = 0
|
||||||
|
@ -1680,7 +1682,7 @@ const useBrowserStore = defineStore('browser', {
|
||||||
msgRef.onClose = () => {
|
msgRef.onClose = () => {
|
||||||
EventsEmit('import:stop:' + path)
|
EventsEmit('import:stop:' + path)
|
||||||
}
|
}
|
||||||
const { data, success, msg } = await ImportCSV(server, db, path, conflict)
|
const { data, success, msg } = await ImportCSV(server, db, path, conflict, expire)
|
||||||
if (success) {
|
if (success) {
|
||||||
canceled = get(data, 'canceled', false)
|
canceled = get(data, 'canceled', false)
|
||||||
imported = get(data, 'imported', 0)
|
imported = get(data, 'imported', 0)
|
||||||
|
|
Loading…
Reference in New Issue