Jobsuche: Berufsbezeichnungen steuern die Suche, nicht mehr Faehigkeiten
Der Feinschliff schlug per KI Technologien vor ("Proxmox", "Rechenzentrum")
und verbot Rollenbezeichnungen ausdruecklich - die sollte die Suche selbst
aus dem Lebenslauf ableiten. Das war schief: Welche Anzeigen ueberhaupt
gefunden werden, entscheidet die Suchanfrage, also der Stellentitel.
Technologien gewichten nur, was schon da ist. Damit schlug die KI genau das
vor, was der Such-Agent ohnehin selbst ableitet, waehrend die eine Sache,
die der Nutzer weder sieht noch steuern kann - unter welchen Titeln gesucht
wird -, bei jedem Lauf neu improvisiert wurde. Faellt "Fachinformatiker
Systemintegration" weg, merkt das niemand; es kommt nur wenig zurueck.
- Neues Profilfeld berufsbezeichnungen: die KI schlaegt es vor, der Nutzer
editiert es, der Such-Agent fragt jeden Titel einzeln ab.
- zusatz_begriffe bleibt, aber als Kontext (Branche, Umfeld, Arbeitszeit),
nicht als Stellentitel; ausschluesse unveraendert.
- Leeres Feld = altes Verhalten (Titel aus dem Lebenslauf), niemandes
Profil aendert sich durch das Update.
- Spalte wird fuer bestehende Installationen nachgezogen.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+13
-5
@@ -2103,10 +2103,11 @@ async function generateEmailReply({
|
|||||||
const FEINSCHLIFF_SCHEMA = {
|
const FEINSCHLIFF_SCHEMA = {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
properties: {
|
properties: {
|
||||||
|
berufsbezeichnungen: { type: 'array', items: { type: 'string' } },
|
||||||
zusatz_begriffe: { type: 'array', items: { type: 'string' } },
|
zusatz_begriffe: { type: 'array', items: { type: 'string' } },
|
||||||
ausschluesse: { type: 'array', items: { type: 'string' } },
|
ausschluesse: { type: 'array', items: { type: 'string' } },
|
||||||
},
|
},
|
||||||
required: ['zusatz_begriffe', 'ausschluesse'],
|
required: ['berufsbezeichnungen', 'zusatz_begriffe', 'ausschluesse'],
|
||||||
};
|
};
|
||||||
|
|
||||||
// How many terms per field we keep. The two lists end up verbatim in the search
|
// How many terms per field we keep. The two lists end up verbatim in the search
|
||||||
@@ -2139,10 +2140,16 @@ async function generateFeinschliff({ unterlagen, profil = {}, prompts = null })
|
|||||||
`Suchmodus: ${modusText}\n` +
|
`Suchmodus: ${modusText}\n` +
|
||||||
(staedte ? `Städte: ${staedte}\n` : '') +
|
(staedte ? `Städte: ${staedte}\n` : '') +
|
||||||
`\n# Aufgabe\n` +
|
`\n# Aufgabe\n` +
|
||||||
`Schlage die beiden Leitplanken der Stellensuche vor:\n` +
|
`Schlage die drei Listen der Stellensuche vor:\n` +
|
||||||
`- "zusatz_begriffe": Begriffe, die die Suche zusätzlich berücksichtigen soll - Technologien, ` +
|
`- "berufsbezeichnungen": die Stellentitel, unter denen der Bewerber suchen sollte - das sind die ` +
|
||||||
`Branchen, Arbeitsumfelder oder Arbeitszeitmodelle, die aus den Unterlagen belegbar sind ` +
|
`Suchanfragen und damit das Wichtigste. Nimm die Titel, unter denen SEINE Tätigkeit real ` +
|
||||||
`(z. B. "Rechenzentrum", "Systemhaus"). KEINE Rollen-/Stellenbezeichnungen.\n` +
|
`ausgeschrieben wird, und decke die üblichen Varianten derselben Rolle ab (z. B. ` +
|
||||||
|
`"Systemadministrator", "IT-Administrator", "Fachinformatiker Systemintegration"). Bleib bei dem, ` +
|
||||||
|
`was sein Erfahrungsniveau hergibt - keine Titel, für die er erkennbar zu wenig oder zu viel ` +
|
||||||
|
`Erfahrung hat, und keine reinen Technologie-Wörter.\n` +
|
||||||
|
`- "zusatz_begriffe": KEINE Stellentitel, sondern Kontext, der einen Treffer zusätzlich attraktiv ` +
|
||||||
|
`macht und aus den Unterlagen belegbar ist - Branchen, Arbeitsumfelder, Arbeitszeitmodelle ` +
|
||||||
|
`(z. B. "Rechenzentrum", "Systemhaus", "Teilzeit").\n` +
|
||||||
`- "ausschluesse": Kriterien, bei denen ein Treffer verworfen werden soll (z. B. Anstellungsformen ` +
|
`- "ausschluesse": Kriterien, bei denen ein Treffer verworfen werden soll (z. B. Anstellungsformen ` +
|
||||||
`oder Rollen, die erkennbar nicht zum Profil passen).\n` +
|
`oder Rollen, die erkennbar nicht zum Profil passen).\n` +
|
||||||
`Höchstens ${FEINSCHLIFF_MAX} Einträge je Liste, nach Wichtigkeit sortiert. Jeder Eintrag ist ein ` +
|
`Höchstens ${FEINSCHLIFF_MAX} Einträge je Liste, nach Wichtigkeit sortiert. Jeder Eintrag ist ein ` +
|
||||||
@@ -2170,6 +2177,7 @@ async function generateFeinschliff({ unterlagen, profil = {}, prompts = null })
|
|||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
berufsbezeichnungen: liste(['berufsbezeichnungen', 'berufsbezeichnung', 'stellentitel', 'rollen', 'jobtitel', 'titel']),
|
||||||
zusatz_begriffe: liste(['zusatz_begriffe', 'zusatzbegriffe', 'zusatz', 'begriffe', 'einschluesse']),
|
zusatz_begriffe: liste(['zusatz_begriffe', 'zusatzbegriffe', 'zusatz', 'begriffe', 'einschluesse']),
|
||||||
ausschluesse: liste(['ausschluesse', 'ausschlüsse', 'ausschlusskriterien', 'exclude', 'ausschluss']),
|
ausschluesse: liste(['ausschluesse', 'ausschlüsse', 'ausschlusskriterien', 'exclude', 'ausschluss']),
|
||||||
};
|
};
|
||||||
|
|||||||
+12
-10
@@ -92,20 +92,22 @@ const DEFAULTS = [
|
|||||||
key: 'jobsuche_feinschliff',
|
key: 'jobsuche_feinschliff',
|
||||||
titel: 'Jobsuche: Feinschliff vorschlagen',
|
titel: 'Jobsuche: Feinschliff vorschlagen',
|
||||||
beschreibung:
|
beschreibung:
|
||||||
'Rolle für den KI-Vorschlag der Leitplanken deiner Jobsuche (zusätzlich berücksichtigen / ' +
|
'Rolle für den KI-Vorschlag deiner Jobsuche (Berufsbezeichnungen / zusätzlich berücksichtigen / ' +
|
||||||
'ausschließen). Grundlage sind deine Basis-Unterlagen oben.',
|
'ausschließen). Grundlage sind deine Basis-Unterlagen oben.',
|
||||||
platzhalter: [],
|
platzhalter: [],
|
||||||
inhalt:
|
inhalt:
|
||||||
'Du bist ein erfahrener Recruiter und stellst die Leitplanken für die automatische ' +
|
'Du bist ein erfahrener Recruiter und stellst die Suchkriterien für die automatische ' +
|
||||||
'Stellensuche eines Bewerbers auf. Du liest seine Basis-Unterlagen (Lebenslauf, Kurzprofil, ' +
|
'Stellensuche eines Bewerbers auf. Du liest seine Basis-Unterlagen (Lebenslauf, Kurzprofil, ' +
|
||||||
'Anschreiben) und leitest daraus ab, welche Zusatzbegriffe eine Stellensuche treffsicherer ' +
|
'Anschreiben). Das Wichtigste sind die Berufsbezeichnungen: unter welchen Stellentiteln seine ' +
|
||||||
'machen und welche Treffer von vornherein verworfen werden sollten. Du erfindest nichts: ' +
|
'Tätigkeit real ausgeschrieben wird - denn danach wird gesucht, und was hier fehlt, findet die ' +
|
||||||
'Jeder Zusatzbegriff muss sich aus den Unterlagen belegen lassen (nachgewiesene Technologien, ' +
|
'Suche nie. Dieselbe Arbeit läuft je nach Firma unter verschiedenen Titeln; decke diese ' +
|
||||||
'Branchen, Umfelder, Arbeitszeitmodelle). Ausschlüsse leitest du aus dem ab, was erkennbar ' +
|
'Varianten ab, aber bleib bei dem, was sein Erfahrungsniveau hergibt. Zusatzbegriffe sind ' +
|
||||||
'nicht zum Bewerber passt - etwa Stellen weit unter oder weit über seinem Erfahrungsniveau, ' +
|
'KEINE Stellentitel, sondern belegbarer Kontext (Technologien, Branchen, Umfelder, ' +
|
||||||
'fachfremde Rollen oder Anstellungsformen, die er offensichtlich nicht sucht. Keine ' +
|
'Arbeitszeitmodelle). Ausschlüsse leitest du aus dem ab, was erkennbar nicht zum Bewerber ' +
|
||||||
'Rollenbezeichnungen als Zusatzbegriffe: die leitet die Suche ohnehin selbst aus dem ' +
|
'passt - etwa Stellen weit unter oder weit über seinem Erfahrungsniveau, fachfremde Rollen ' +
|
||||||
'Lebenslauf ab. Antworte auf Deutsch im lateinischen Alphabet.',
|
'oder Anstellungsformen, die er offensichtlich nicht sucht. Du erfindest nichts: Jeder ' +
|
||||||
|
'Vorschlag muss sich aus den Unterlagen belegen lassen. Antworte auf Deutsch im lateinischen ' +
|
||||||
|
'Alphabet.',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
+30
-3
@@ -34,6 +34,7 @@ const DEFAULTS = {
|
|||||||
aktiv: 0,
|
aktiv: 0,
|
||||||
modus: 'regional',
|
modus: 'regional',
|
||||||
staedte: [],
|
staedte: [],
|
||||||
|
berufsbezeichnungen: '',
|
||||||
zusatz_begriffe: '',
|
zusatz_begriffe: '',
|
||||||
ausschluesse: 'Zeitarbeit / Arbeitnehmerüberlassung, Personalvermittler / Headhunter',
|
ausschluesse: 'Zeitarbeit / Arbeitnehmerüberlassung, Personalvermittler / Headhunter',
|
||||||
zeitplan_tage: '1,2,3,4,5',
|
zeitplan_tage: '1,2,3,4,5',
|
||||||
@@ -91,6 +92,7 @@ function fromRow(row) {
|
|||||||
aktiv: r.aktiv ? 1 : 0,
|
aktiv: r.aktiv ? 1 : 0,
|
||||||
modus,
|
modus,
|
||||||
staedte: parseStaedte(r.staedte),
|
staedte: parseStaedte(r.staedte),
|
||||||
|
berufsbezeichnungen: r.berufsbezeichnungen || '',
|
||||||
zusatz_begriffe: r.zusatz_begriffe || '',
|
zusatz_begriffe: r.zusatz_begriffe || '',
|
||||||
ausschluesse: r.ausschluesse != null ? r.ausschluesse : DEFAULTS.ausschluesse,
|
ausschluesse: r.ausschluesse != null ? r.ausschluesse : DEFAULTS.ausschluesse,
|
||||||
zeitplan_tage: parseTage(r.zeitplan_tage != null ? r.zeitplan_tage : DEFAULTS.zeitplan_tage),
|
zeitplan_tage: parseTage(r.zeitplan_tage != null ? r.zeitplan_tage : DEFAULTS.zeitplan_tage),
|
||||||
@@ -108,6 +110,7 @@ function fromForm(body, sanitize = (v) => v) {
|
|||||||
aktiv: (b.aktiv === '1' || b.aktiv === 'on' || b.aktiv === true) ? 1 : 0,
|
aktiv: (b.aktiv === '1' || b.aktiv === 'on' || b.aktiv === true) ? 1 : 0,
|
||||||
modus,
|
modus,
|
||||||
staedte: parseStaedte(b.staedte).map((s) => sanitize(s)),
|
staedte: parseStaedte(b.staedte).map((s) => sanitize(s)),
|
||||||
|
berufsbezeichnungen: sanitize(String(b.berufsbezeichnungen || '').trim()),
|
||||||
zusatz_begriffe: sanitize(String(b.zusatz_begriffe || '').trim()),
|
zusatz_begriffe: sanitize(String(b.zusatz_begriffe || '').trim()),
|
||||||
ausschluesse: sanitize(String(b.ausschluesse || '').trim()),
|
ausschluesse: sanitize(String(b.ausschluesse || '').trim()),
|
||||||
zeitplan_tage: parseTage(tage.join(',')),
|
zeitplan_tage: parseTage(tage.join(',')),
|
||||||
@@ -121,6 +124,7 @@ function toRow(profil) {
|
|||||||
aktiv: profil.aktiv ? 1 : 0,
|
aktiv: profil.aktiv ? 1 : 0,
|
||||||
modus: profil.modus,
|
modus: profil.modus,
|
||||||
staedte: JSON.stringify(profil.staedte || []),
|
staedte: JSON.stringify(profil.staedte || []),
|
||||||
|
berufsbezeichnungen: profil.berufsbezeichnungen || '',
|
||||||
zusatz_begriffe: profil.zusatz_begriffe || '',
|
zusatz_begriffe: profil.zusatz_begriffe || '',
|
||||||
ausschluesse: profil.ausschluesse || '',
|
ausschluesse: profil.ausschluesse || '',
|
||||||
zeitplan_tage: (profil.zeitplan_tage || []).join(','),
|
zeitplan_tage: (profil.zeitplan_tage || []).join(','),
|
||||||
@@ -203,14 +207,37 @@ function buildPrompt(profil, profilText) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Die Berufsbezeichnungen sind die eigentlichen Suchanfragen — sie entscheiden,
|
||||||
|
// welche Anzeigen überhaupt gefunden werden. Sind sie gesetzt, sucht der Agent
|
||||||
|
// danach, statt sich die Titel bei jedem Lauf neu aus dem Lebenslauf zu
|
||||||
|
// improvisieren (was der Nutzer weder sieht noch steuern kann). Das Profil
|
||||||
|
// liefert dann nur noch die Technologien zur Gewichtung.
|
||||||
|
if (profil.berufsbezeichnungen) {
|
||||||
|
teile.push(
|
||||||
|
`Suche gezielt nach Stellen mit diesen Berufsbezeichnungen (das sind deine Suchanfragen, jede einzeln ` +
|
||||||
|
`abfragen): ${profil.berufsbezeichnungen}. Nahe Schreibweisen und gängige Varianten desselben Titels ` +
|
||||||
|
`(m/w/d, "IT-" davor, Singular/Plural, englische Entsprechung) darfst du ergänzen; auf fachfremde Rollen ` +
|
||||||
|
`ausweichen darfst du NICHT.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (profilText && profilText.trim()) {
|
if (profilText && profilText.trim()) {
|
||||||
teile.push(
|
teile.push(
|
||||||
'Leite Rollenbezeichnungen (Query-Varianten) und Technologie-Buzzwords AUS DEM FOLGENDEN PROFIL DES ' +
|
(profil.berufsbezeichnungen
|
||||||
'BEWERBERS ab — fasse die Rolle breit (dieselbe Tätigkeit läuft je nach Firma unter vielen Titeln) und ' +
|
? 'Technologie-Buzzwords und die Gewichtung der Treffer leitest du AUS DEM FOLGENDEN PROFIL DES ' +
|
||||||
'gewichte Treffer höher, je mehr aus dem Profil passt:\n\n--- PROFIL ---\n' +
|
'BEWERBERS ab (die Suchtitel stehen oben und gelten) — gewichte Treffer höher, je mehr aus dem ' +
|
||||||
|
'Profil passt:'
|
||||||
|
: 'Leite Rollenbezeichnungen (Query-Varianten) und Technologie-Buzzwords AUS DEM FOLGENDEN PROFIL DES ' +
|
||||||
|
'BEWERBERS ab — fasse die Rolle breit (dieselbe Tätigkeit läuft je nach Firma unter vielen Titeln) und ' +
|
||||||
|
'gewichte Treffer höher, je mehr aus dem Profil passt:') +
|
||||||
|
'\n\n--- PROFIL ---\n' +
|
||||||
profilText.trim().slice(0, 6000) +
|
profilText.trim().slice(0, 6000) +
|
||||||
'\n--- ENDE PROFIL ---'
|
'\n--- ENDE PROFIL ---'
|
||||||
);
|
);
|
||||||
|
} else if (profil.berufsbezeichnungen) {
|
||||||
|
teile.push(
|
||||||
|
'Es ist kein Lebenslauf/Profil hinterlegt — halte dich strikt an die oben genannten Berufsbezeichnungen.'
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
teile.push(
|
teile.push(
|
||||||
'ACHTUNG: Es ist kein Lebenslauf/Profil hinterlegt. Leite Rollen und Suchbegriffe aus den bereits ' +
|
'ACHTUNG: Es ist kein Lebenslauf/Profil hinterlegt. Leite Rollen und Suchbegriffe aus den bereits ' +
|
||||||
|
|||||||
@@ -916,14 +916,15 @@ async function loadSuchprofil(userId) {
|
|||||||
async function saveSuchprofil(userId, profil) {
|
async function saveSuchprofil(userId, profil) {
|
||||||
const r = suchprofil.toRow(profil);
|
const r = suchprofil.toRow(profil);
|
||||||
await dbRun(
|
await dbRun(
|
||||||
`INSERT INTO suchprofil (user_id, aktiv, modus, staedte, zusatz_begriffe, ausschluesse, zeitplan_tage, zeitplan_zeit, updated_at)
|
`INSERT INTO suchprofil (user_id, aktiv, modus, staedte, berufsbezeichnungen, zusatz_begriffe, ausschluesse, zeitplan_tage, zeitplan_zeit, updated_at)
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP)
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP)
|
||||||
ON CONFLICT(user_id) DO UPDATE SET
|
ON CONFLICT(user_id) DO UPDATE SET
|
||||||
aktiv = excluded.aktiv, modus = excluded.modus, staedte = excluded.staedte,
|
aktiv = excluded.aktiv, modus = excluded.modus, staedte = excluded.staedte,
|
||||||
|
berufsbezeichnungen = excluded.berufsbezeichnungen,
|
||||||
zusatz_begriffe = excluded.zusatz_begriffe, ausschluesse = excluded.ausschluesse,
|
zusatz_begriffe = excluded.zusatz_begriffe, ausschluesse = excluded.ausschluesse,
|
||||||
zeitplan_tage = excluded.zeitplan_tage, zeitplan_zeit = excluded.zeitplan_zeit,
|
zeitplan_tage = excluded.zeitplan_tage, zeitplan_zeit = excluded.zeitplan_zeit,
|
||||||
updated_at = CURRENT_TIMESTAMP`,
|
updated_at = CURRENT_TIMESTAMP`,
|
||||||
[userId, r.aktiv, r.modus, r.staedte, r.zusatz_begriffe, r.ausschluesse, r.zeitplan_tage, r.zeitplan_zeit]
|
[userId, r.aktiv, r.modus, r.staedte, r.berufsbezeichnungen, r.zusatz_begriffe, r.ausschluesse, r.zeitplan_tage, r.zeitplan_zeit]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1525,14 +1526,16 @@ async function initializeDatabase() {
|
|||||||
`);
|
`);
|
||||||
|
|
||||||
// Job-search profile (one row per user; a missing row = no search configured).
|
// Job-search profile (one row per user; a missing row = no search configured).
|
||||||
// The user sets *where* (Städte/Modus) and the guard rails; the roles and
|
// The user sets *where* (Städte/Modus), *unter welchen Titeln* gesucht wird
|
||||||
// buzzwords are derived from their Lebenslauf at run time — see lib/suchprofil.
|
// (berufsbezeichnungen) und die Leitplanken; Technologien/Buzzwords leitet die
|
||||||
|
// Suche weiter aus dem Lebenslauf ab — siehe lib/suchprofil.
|
||||||
await exec(`
|
await exec(`
|
||||||
CREATE TABLE IF NOT EXISTS suchprofil (
|
CREATE TABLE IF NOT EXISTS suchprofil (
|
||||||
user_id INTEGER PRIMARY KEY,
|
user_id INTEGER PRIMARY KEY,
|
||||||
aktiv INTEGER NOT NULL DEFAULT 0,
|
aktiv INTEGER NOT NULL DEFAULT 0,
|
||||||
modus TEXT NOT NULL DEFAULT 'regional',
|
modus TEXT NOT NULL DEFAULT 'regional',
|
||||||
staedte TEXT NOT NULL DEFAULT '[]',
|
staedte TEXT NOT NULL DEFAULT '[]',
|
||||||
|
berufsbezeichnungen TEXT DEFAULT '',
|
||||||
zusatz_begriffe TEXT DEFAULT '',
|
zusatz_begriffe TEXT DEFAULT '',
|
||||||
ausschluesse TEXT DEFAULT '',
|
ausschluesse TEXT DEFAULT '',
|
||||||
zeitplan_tage TEXT DEFAULT '1,2,3,4,5',
|
zeitplan_tage TEXT DEFAULT '1,2,3,4,5',
|
||||||
@@ -1541,6 +1544,13 @@ async function initializeDatabase() {
|
|||||||
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
|
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
|
||||||
)
|
)
|
||||||
`);
|
`);
|
||||||
|
// Bestehende Installationen: die Spalte kam nach dem CREATE TABLE oben dazu.
|
||||||
|
// Leer heißt „wie bisher" — die Suche leitet die Rollen dann weiter selbst aus
|
||||||
|
// dem Lebenslauf ab, niemandes Profil ändert sich durch das Update.
|
||||||
|
const suchprofilSpalten = await dbAll('PRAGMA table_info(suchprofil)');
|
||||||
|
if (!suchprofilSpalten.some((s) => s.name === 'berufsbezeichnungen')) {
|
||||||
|
await exec("ALTER TABLE suchprofil ADD COLUMN berufsbezeichnungen TEXT DEFAULT ''");
|
||||||
|
}
|
||||||
|
|
||||||
// Queue + history of search runs. The app only ever *enqueues* (status
|
// Queue + history of search runs. The app only ever *enqueues* (status
|
||||||
// 'angefordert'); the host-side runner (bin/jobsuche-runner.sh) picks runs up,
|
// 'angefordert'); the host-side runner (bin/jobsuche-runner.sh) picks runs up,
|
||||||
|
|||||||
+16
-2
@@ -109,7 +109,7 @@
|
|||||||
<div>
|
<div>
|
||||||
<h3 class="text-base font-semibold text-gray-800 dark:text-white">Feinschliff</h3>
|
<h3 class="text-base font-semibold text-gray-800 dark:text-white">Feinschliff</h3>
|
||||||
<p class="text-sm text-gray-500 dark:text-gray-400 mt-1">
|
<p class="text-sm text-gray-500 dark:text-gray-400 mt-1">
|
||||||
Optional. Rollen und Technologien kommen aus deinem Lebenslauf – hier ergänzt du nur Leitplanken.
|
Unter welchen Titeln gesucht wird – und was die Suche zusätzlich beachten oder verwerfen soll.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<button type="button" id="feinschliffKi"
|
<button type="button" id="feinschliffKi"
|
||||||
@@ -125,9 +125,21 @@
|
|||||||
<p id="feinschliffHinweis" class="hidden text-sm mt-3"></p>
|
<p id="feinschliffHinweis" class="hidden text-sm mt-3"></p>
|
||||||
<p class="text-xs text-gray-400 dark:text-gray-500 mt-3 mb-5">
|
<p class="text-xs text-gray-400 dark:text-gray-500 mt-3 mb-5">
|
||||||
Der KI-Vorschlag wertet deine <a href="/vorlagen" class="underline">Basis-Unterlagen</a> aus und
|
Der KI-Vorschlag wertet deine <a href="/vorlagen" class="underline">Basis-Unterlagen</a> aus und
|
||||||
überschreibt beide Felder. Gespeichert wird er erst, wenn du unten auf „Speichern“ klickst.
|
überschreibt alle drei Felder. Gespeichert wird er erst, wenn du unten auf „Speichern“ klickst.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<div class="mb-4">
|
||||||
|
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1" for="berufsbezeichnungen">Berufsbezeichnungen</label>
|
||||||
|
<textarea id="berufsbezeichnungen" name="berufsbezeichnungen" rows="2"
|
||||||
|
class="w-full rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 px-3 py-2 text-sm"
|
||||||
|
placeholder="z. B. Systemadministrator, IT-Administrator, Fachinformatiker Systemintegration"><%= profil.berufsbezeichnungen %></textarea>
|
||||||
|
<p class="text-xs text-gray-400 dark:text-gray-500 mt-1">
|
||||||
|
<strong>Danach wird gesucht</strong> – was hier fehlt, findet die Suche nicht. Kommagetrennt;
|
||||||
|
gängige Varianten desselben Titels ergänzt die Suche selbst. Leer = die Suche leitet die Titel
|
||||||
|
wie bisher aus deinem Lebenslauf ab.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="grid gap-4 sm:grid-cols-2">
|
<div class="grid gap-4 sm:grid-cols-2">
|
||||||
<div>
|
<div>
|
||||||
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1" for="zusatz_begriffe">Zusätzlich berücksichtigen</label>
|
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1" for="zusatz_begriffe">Zusätzlich berücksichtigen</label>
|
||||||
@@ -249,6 +261,7 @@
|
|||||||
if (!btn) return;
|
if (!btn) return;
|
||||||
const label = document.getElementById('feinschliffKiText');
|
const label = document.getElementById('feinschliffKiText');
|
||||||
const hinweis = document.getElementById('feinschliffHinweis');
|
const hinweis = document.getElementById('feinschliffHinweis');
|
||||||
|
const berufe = document.getElementById('berufsbezeichnungen');
|
||||||
const zusatz = document.getElementById('zusatz_begriffe');
|
const zusatz = document.getElementById('zusatz_begriffe');
|
||||||
const ausschluesse = document.getElementById('ausschluesse');
|
const ausschluesse = document.getElementById('ausschluesse');
|
||||||
const zielUser = <%- fremd ? zielUser.id : 'null' %>;
|
const zielUser = <%- fremd ? zielUser.id : 'null' %>;
|
||||||
@@ -282,6 +295,7 @@
|
|||||||
const data = await res.json().catch(function () { return {}; });
|
const data = await res.json().catch(function () { return {}; });
|
||||||
if (!res.ok) throw new Error(data.error || ('Fehler ' + res.status));
|
if (!res.ok) throw new Error(data.error || ('Fehler ' + res.status));
|
||||||
|
|
||||||
|
berufe.value = data.berufsbezeichnungen || '';
|
||||||
zusatz.value = data.zusatz_begriffe || '';
|
zusatz.value = data.zusatz_begriffe || '';
|
||||||
ausschluesse.value = data.ausschluesse || '';
|
ausschluesse.value = data.ausschluesse || '';
|
||||||
melde('Vorschlag übernommen. Prüfe ihn und klicke auf „Speichern“.', 'ok');
|
melde('Vorschlag übernommen. Prüfe ihn und klicke auf „Speichern“.', 'ok');
|
||||||
|
|||||||
Reference in New Issue
Block a user